kopia lustrzana https://github.com/jupyterhub/repo2docker
Merge branch 'main' into 1455-fail-earlier
commit
53e8ce11a7
|
@ -5,23 +5,23 @@
|
||||||
(And thank you particularly for coming to read the guidelines! :heart_eyes:)
|
(And thank you particularly for coming to read the guidelines! :heart_eyes:)
|
||||||
|
|
||||||
The repo2docker developer documentation is all rendered on our documentation website: [https://repo2docker.readthedocs.io](https://repo2docker.readthedocs.io).
|
The repo2docker developer documentation is all rendered on our documentation website: [https://repo2docker.readthedocs.io](https://repo2docker.readthedocs.io).
|
||||||
If you're here, you're probably looking for the [Contributing to repo2docker development](https://repo2docker.readthedocs.io/en/latest/contributing/contributing.html) page.
|
If you're here, you're probably looking for the [Contributing to repo2docker development](https://repo2docker.readthedocs.io/en/latest/contribute/contributing.html) page.
|
||||||
|
|
||||||
Please make sure you've read the following sections before opening an issue/pull request:
|
Please make sure you've read the following sections before opening an issue/pull request:
|
||||||
|
|
||||||
- [Process for making a contribution](https://repo2docker.readthedocs.io/en/latest/contributing/contributing.html#process-for-making-a-contribution).
|
- [Process for making a contribution](https://repo2docker.readthedocs.io/en/latest/contribute/contributing.html#process-for-making-a-contribution).
|
||||||
- These steps talk you through choosing the right issue template (bug report or feature request) and making a change.
|
- These steps talk you through choosing the right issue template (bug report or feature request) and making a change.
|
||||||
- [Guidelines to getting a Pull Request merged](https://repo2docker.readthedocs.io/en/latest/contributing/contributing.html#guidelines-to-getting-a-pull-request-merged).
|
- [Guidelines to getting a Pull Request merged](https://repo2docker.readthedocs.io/en/latest/contribute/contributing.html#guidelines-to-getting-a-pull-request-merged).
|
||||||
- These are tips and tricks to help make your contribution as smooth as possible for you and for the repo2docker maintenance team.
|
- These are tips and tricks to help make your contribution as smooth as possible for you and for the repo2docker maintenance team.
|
||||||
|
|
||||||
There are a few other pages to highlight:
|
There are a few other pages to highlight:
|
||||||
|
|
||||||
- [Our roadmap](https://repo2docker.readthedocs.io/en/latest/contributing/roadmap.html)
|
- [Our roadmap](https://repo2docker.readthedocs.io/en/latest/contribute/roadmap.html)
|
||||||
- We use the roadmap to develop a shared understanding of the project's vision and direction amongst the community of users, contributors, and maintainers.
|
- We use the roadmap to develop a shared understanding of the project's vision and direction amongst the community of users, contributors, and maintainers.
|
||||||
This is a great place to get a feel for what the maintainers are thinking about for the short, medium, and long term future of the project.
|
This is a great place to get a feel for what the maintainers are thinking about for the short, medium, and long term future of the project.
|
||||||
- [Design of repo2docker](https://repo2docker.readthedocs.io/en/latest/design.html)
|
- [Design of repo2docker](https://repo2docker.readthedocs.io/en/latest/design.html)
|
||||||
- This page explains some of the design principles behind repo2docker.
|
- This page explains some of the design principles behind repo2docker.
|
||||||
Its a good place to understand _why_ the team have made the decisions that they have along the way!
|
Its a good place to understand _why_ the team have made the decisions that they have along the way!
|
||||||
- We absolutely encourage discussion around refactoring, updating or extending repo2docker, but please make sure that you've understood this page before opening an issue to discuss the change you'd like to propose.
|
- We absolutely encourage discussion around refactoring, updating or extending repo2docker, but please make sure that you've understood this page before opening an issue to discuss the change you'd like to propose.
|
||||||
- [Common developer tasks and how-tos](https://repo2docker.readthedocs.io/en/latest/contributing/tasks.html)
|
- [Common developer tasks and how-tos](https://repo2docker.readthedocs.io/en/latest/contribute/tasks.html)
|
||||||
- Some notes on running tests, buildpack dependencies, creating a release, and keeping the pip files up to date.
|
- Some notes on running tests, buildpack dependencies, creating a release, and keeping the pip files up to date.
|
||||||
|
|
|
@ -1,5 +1,80 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## Unreleased breaking changes
|
||||||
|
|
||||||
|
`RBuildPack.runtime` previously returned the contents of `runtime.txt` as a string.
|
||||||
|
It has been replaced by `BuildPack.runtime` which returns a tuple `(name, version, date)`.
|
||||||
|
|
||||||
|
## 2025.08.0
|
||||||
|
|
||||||
|
([full changelog](https://github.com/jupyterhub/repo2docker/compare/4da768765372c602c06606cb79d21a398fcc2987...6cf91e45d5b03f79e365cd82eda09d1178d03327))
|
||||||
|
|
||||||
|
### API and Breaking Changes
|
||||||
|
|
||||||
|
- Switch to using CLI for everything except running the container [#1421](https://github.com/jupyterhub/repo2docker/pull/1421) ([@yuvipanda](https://github.com/yuvipanda), [@manics](https://github.com/manics), [@minrk](https://github.com/minrk))
|
||||||
|
- Require Python 3.9 to run repo2docker [#1411](https://github.com/jupyterhub/repo2docker/pull/1411) ([@manics](https://github.com/manics), [@minrk](https://github.com/minrk), [@yuvipanda](https://github.com/yuvipanda))
|
||||||
|
- Shell out to `docker buildx build` to build images [#1402](https://github.com/jupyterhub/repo2docker/pull/1402) ([@yuvipanda](https://github.com/yuvipanda), [@manics](https://github.com/manics), [@minrk](https://github.com/minrk))
|
||||||
|
- notebook 7 [#1363](https://github.com/jupyterhub/repo2docker/pull/1363) ([@minrk](https://github.com/minrk), [@manics](https://github.com/manics))
|
||||||
|
- Major version bump node (18->20) and jupyterhub-singleuser (3->5) [#1359](https://github.com/jupyterhub/repo2docker/pull/1359) ([@consideRatio](https://github.com/consideRatio), [@yuvipanda](https://github.com/yuvipanda))
|
||||||
|
|
||||||
|
### Enhancements made
|
||||||
|
|
||||||
|
- add triplets for r versions 4.3, 4.4 [#1403](https://github.com/jupyterhub/repo2docker/pull/1403) ([@minrk](https://github.com/minrk), [@yuvipanda](https://github.com/yuvipanda), [@manics](https://github.com/manics))
|
||||||
|
- Upgrade Shiny server to 2024.12 [#1400](https://github.com/jupyterhub/repo2docker/pull/1400) ([@rgaiacs](https://github.com/rgaiacs), [@manics](https://github.com/manics))
|
||||||
|
- Upgrade RStudio to 2024.12 [#1399](https://github.com/jupyterhub/repo2docker/pull/1399) ([@rgaiacs](https://github.com/rgaiacs), [@manics](https://github.com/manics))
|
||||||
|
- Use REST APIs to resolve DOIs + cleanup dataverse provider [#1390](https://github.com/jupyterhub/repo2docker/pull/1390) ([@yuvipanda](https://github.com/yuvipanda), [@minrk](https://github.com/minrk), [@pdurbin](https://github.com/pdurbin))
|
||||||
|
- exclude defaults channel by default [#1365](https://github.com/jupyterhub/repo2docker/pull/1365) ([@minrk](https://github.com/minrk), [@rgaiacs](https://github.com/rgaiacs))
|
||||||
|
|
||||||
|
### Bugs fixed
|
||||||
|
|
||||||
|
- [MRG] Disable bash trace output in conda activation script [#1425](https://github.com/jupyterhub/repo2docker/pull/1425) ([@mfisher87](https://github.com/mfisher87), [@manics](https://github.com/manics))
|
||||||
|
- Simulate json output from docker buildx build [#1413](https://github.com/jupyterhub/repo2docker/pull/1413) ([@yuvipanda](https://github.com/yuvipanda), [@manics](https://github.com/manics), [@minrk](https://github.com/minrk))
|
||||||
|
- `set -e` should not be set after conda environment is sourced [#1409](https://github.com/jupyterhub/repo2docker/pull/1409) ([@manics](https://github.com/manics), [@yuvipanda](https://github.com/yuvipanda))
|
||||||
|
- Use self.log rather than logging module directly [#1378](https://github.com/jupyterhub/repo2docker/pull/1378) ([@yuvipanda](https://github.com/yuvipanda), [@manics](https://github.com/manics))
|
||||||
|
- julia_project.py: fix Pkg REPL api warning [#1376](https://github.com/jupyterhub/repo2docker/pull/1376) ([@fonsp](https://github.com/fonsp), [@GeorgianaElena](https://github.com/GeorgianaElena), [@agoose77](https://github.com/agoose77))
|
||||||
|
- TarFile.add: don't add recursively [#1371](https://github.com/jupyterhub/repo2docker/pull/1371) ([@manics](https://github.com/manics), [@minrk](https://github.com/minrk))
|
||||||
|
|
||||||
|
### Maintenance and upkeep improvements
|
||||||
|
|
||||||
|
- Bump mamba from 2.0.5 to 2.1.0 [#1423](https://github.com/jupyterhub/repo2docker/pull/1423) ([@weiji14](https://github.com/weiji14), [@yuvipanda](https://github.com/yuvipanda))
|
||||||
|
- maint: Adapt mamba activation [#1419](https://github.com/jupyterhub/repo2docker/pull/1419) ([@jjerphan](https://github.com/jjerphan), [@yuvipanda](https://github.com/yuvipanda), [@minrk](https://github.com/minrk))
|
||||||
|
- Add a test for runtime.txt with full R version specified [#1416](https://github.com/jupyterhub/repo2docker/pull/1416) ([@yuvipanda](https://github.com/yuvipanda), [@minrk](https://github.com/minrk))
|
||||||
|
- Bump alpine docker to 3.21 [#1412](https://github.com/jupyterhub/repo2docker/pull/1412) ([@manics](https://github.com/manics), [@minrk](https://github.com/minrk))
|
||||||
|
- Refreeze base environment for package upgrades [#1407](https://github.com/jupyterhub/repo2docker/pull/1407) ([@yuvipanda](https://github.com/yuvipanda), [@manics](https://github.com/manics))
|
||||||
|
- Remove unused \_urlopen method [#1392](https://github.com/jupyterhub/repo2docker/pull/1392) ([@yuvipanda](https://github.com/yuvipanda), [@minrk](https://github.com/minrk))
|
||||||
|
- Upgraded to micromamba 2.0.5 [#1387](https://github.com/jupyterhub/repo2docker/pull/1387) ([@JohanMabille](https://github.com/JohanMabille), [@yuvipanda](https://github.com/yuvipanda), [@SylvainCorlay](https://github.com/SylvainCorlay))
|
||||||
|
- Use self.log.warning instead of warnings.warn [#1384](https://github.com/jupyterhub/repo2docker/pull/1384) ([@yuvipanda](https://github.com/yuvipanda), [@manics](https://github.com/manics))
|
||||||
|
- call close_handlers before garbage collection [#1380](https://github.com/jupyterhub/repo2docker/pull/1380) ([@minrk](https://github.com/minrk), [@manics](https://github.com/manics))
|
||||||
|
- [pre-commit.ci] pre-commit autoupdate [#1377](https://github.com/jupyterhub/repo2docker/pull/1377) ([@minrk](https://github.com/minrk))
|
||||||
|
- Update to mamba 1.5.9 [#1370](https://github.com/jupyterhub/repo2docker/pull/1370) ([@SylvainCorlay](https://github.com/SylvainCorlay), [@manics](https://github.com/manics))
|
||||||
|
- Refreeze conda packages (JupyterLab 4.2.3 -> 4.2.5) [#1369](https://github.com/jupyterhub/repo2docker/pull/1369) ([@manics](https://github.com/manics), [@minrk](https://github.com/minrk))
|
||||||
|
- Update for mamba 1.5.8 [#1367](https://github.com/jupyterhub/repo2docker/pull/1367) ([@jjerphan](https://github.com/jjerphan), [@manics](https://github.com/manics), [@SylvainCorlay](https://github.com/SylvainCorlay))
|
||||||
|
- update import of shlex.quote [#1364](https://github.com/jupyterhub/repo2docker/pull/1364) ([@minrk](https://github.com/minrk), [@manics](https://github.com/manics))
|
||||||
|
- [pre-commit.ci] pre-commit autoupdate [#1362](https://github.com/jupyterhub/repo2docker/pull/1362) ([@minrk](https://github.com/minrk))
|
||||||
|
|
||||||
|
### Documentation improvements
|
||||||
|
|
||||||
|
- Revamp our documentation and refactor a bit [#1433](https://github.com/jupyterhub/repo2docker/pull/1433) ([@choldgraf](https://github.com/choldgraf), [@chuckwondo](https://github.com/chuckwondo), [@rgaiacs](https://github.com/rgaiacs), [@yuvipanda](https://github.com/yuvipanda))
|
||||||
|
- bug report.rst [#1429](https://github.com/jupyterhub/repo2docker/pull/1429) ([@nadiaguiffant](https://github.com/nadiaguiffant), [@manics](https://github.com/manics))
|
||||||
|
- Add changelog for 2024.07.0 [#1356](https://github.com/jupyterhub/repo2docker/pull/1356) ([@yuvipanda](https://github.com/yuvipanda), [@consideRatio](https://github.com/consideRatio), [@manics](https://github.com/manics))
|
||||||
|
|
||||||
|
### Continuous integration improvements
|
||||||
|
|
||||||
|
- Add basic UI Playwright tests [#1410](https://github.com/jupyterhub/repo2docker/pull/1410) ([@manics](https://github.com/manics), [@minrk](https://github.com/minrk))
|
||||||
|
- Don't run scheduled workflows on forks [#1408](https://github.com/jupyterhub/repo2docker/pull/1408) ([@manics](https://github.com/manics), [@yuvipanda](https://github.com/yuvipanda))
|
||||||
|
- build(deps): bump codecov/codecov-action from 4 to 5 [#1381](https://github.com/jupyterhub/repo2docker/pull/1381) ([@minrk](https://github.com/minrk))
|
||||||
|
- [pre-commit.ci] pre-commit autoupdate [#1358](https://github.com/jupyterhub/repo2docker/pull/1358) ([@minrk](https://github.com/minrk))
|
||||||
|
- build(deps): bump docker/build-push-action from 5 to 6 [#1357](https://github.com/jupyterhub/repo2docker/pull/1357) ([@manics](https://github.com/manics))
|
||||||
|
|
||||||
|
### Contributors to this release
|
||||||
|
|
||||||
|
The following people contributed discussions, new ideas, code and documentation contributions, and review.
|
||||||
|
See [our definition of contributors](https://github-activity.readthedocs.io/en/latest/#how-does-this-tool-define-contributions-in-the-reports).
|
||||||
|
|
||||||
|
([GitHub contributors page for this release](https://github.com/jupyterhub/repo2docker/graphs/contributors?from=2024-07-01&to=2025-08-03&type=c))
|
||||||
|
|
||||||
|
@agoose77 ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Frepo2docker+involves%3Aagoose77+updated%3A2024-07-01..2025-08-03&type=Issues)) | @AliMirlou ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Frepo2docker+involves%3AAliMirlou+updated%3A2024-07-01..2025-08-03&type=Issues)) | @betatim ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Frepo2docker+involves%3Abetatim+updated%3A2024-07-01..2025-08-03&type=Issues)) | @choldgraf ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Frepo2docker+involves%3Acholdgraf+updated%3A2024-07-01..2025-08-03&type=Issues)) | @chuckwondo ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Frepo2docker+involves%3Achuckwondo+updated%3A2024-07-01..2025-08-03&type=Issues)) | @consideRatio ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Frepo2docker+involves%3AconsideRatio+updated%3A2024-07-01..2025-08-03&type=Issues)) | @d70-t ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Frepo2docker+involves%3Ad70-t+updated%3A2024-07-01..2025-08-03&type=Issues)) | @felder ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Frepo2docker+involves%3Afelder+updated%3A2024-07-01..2025-08-03&type=Issues)) | @fonsp ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Frepo2docker+involves%3Afonsp+updated%3A2024-07-01..2025-08-03&type=Issues)) | @GeorgianaElena ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Frepo2docker+involves%3AGeorgianaElena+updated%3A2024-07-01..2025-08-03&type=Issues)) | @Hind-M ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Frepo2docker+involves%3AHind-M+updated%3A2024-07-01..2025-08-03&type=Issues)) | @hiroyuki-sato ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Frepo2docker+involves%3Ahiroyuki-sato+updated%3A2024-07-01..2025-08-03&type=Issues)) | @jjerphan ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Frepo2docker+involves%3Ajjerphan+updated%3A2024-07-01..2025-08-03&type=Issues)) | @JohanMabille ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Frepo2docker+involves%3AJohanMabille+updated%3A2024-07-01..2025-08-03&type=Issues)) | @manics ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Frepo2docker+involves%3Amanics+updated%3A2024-07-01..2025-08-03&type=Issues)) | @mfisher87 ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Frepo2docker+involves%3Amfisher87+updated%3A2024-07-01..2025-08-03&type=Issues)) | @minrk ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Frepo2docker+involves%3Aminrk+updated%3A2024-07-01..2025-08-03&type=Issues)) | @nadiaguiffant ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Frepo2docker+involves%3Anadiaguiffant+updated%3A2024-07-01..2025-08-03&type=Issues)) | @pdurbin ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Frepo2docker+involves%3Apdurbin+updated%3A2024-07-01..2025-08-03&type=Issues)) | @rgaiacs ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Frepo2docker+involves%3Argaiacs+updated%3A2024-07-01..2025-08-03&type=Issues)) | @ryanlovett ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Frepo2docker+involves%3Aryanlovett+updated%3A2024-07-01..2025-08-03&type=Issues)) | @SylvainCorlay ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Frepo2docker+involves%3ASylvainCorlay+updated%3A2024-07-01..2025-08-03&type=Issues)) | @weiji14 ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Frepo2docker+involves%3Aweiji14+updated%3A2024-07-01..2025-08-03&type=Issues)) | @yuvipanda ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Frepo2docker+involves%3Ayuvipanda+updated%3A2024-07-01..2025-08-03&type=Issues))
|
||||||
|
|
||||||
## 2024.07.0
|
## 2024.07.0
|
||||||
|
|
||||||
([full changelog](https://github.com/jupyterhub/repo2docker/compare/2024.03.0...2024.07.0))
|
([full changelog](https://github.com/jupyterhub/repo2docker/compare/2024.03.0...2024.07.0))
|
||||||
|
|
|
@ -733,7 +733,10 @@ class Repo2Docker(Application):
|
||||||
try:
|
try:
|
||||||
self.fetch(self.repo, self.ref, checkout_path)
|
self.fetch(self.repo, self.ref, checkout_path)
|
||||||
|
|
||||||
if self.find_image():
|
if self.find_image() and not self.push:
|
||||||
|
# If push is requested we don't have a general way to query the registry.
|
||||||
|
# ContainerEngine.build() also handles pushing, so always "build" and
|
||||||
|
# rely on the implementation to decide whether to rebuild.
|
||||||
self.log.info(
|
self.log.info(
|
||||||
f"Reusing existing image ({self.output_image_spec}), not building."
|
f"Reusing existing image ({self.output_image_spec}), not building."
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import datetime
|
||||||
import hashlib
|
import hashlib
|
||||||
import io
|
import io
|
||||||
import logging
|
import logging
|
||||||
|
@ -750,3 +751,50 @@ class BaseImage(BuildPack):
|
||||||
# the only path evaluated at container start time rather than build time
|
# the only path evaluated at container start time rather than build time
|
||||||
return os.path.join("${REPO_DIR}", start)
|
return os.path.join("${REPO_DIR}", start)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def runtime(self):
|
||||||
|
"""
|
||||||
|
Return parsed contents of runtime.txt
|
||||||
|
|
||||||
|
Returns (runtime, version, date), tuple components may be None.
|
||||||
|
Returns (None, None, None) if runtime.txt not found.
|
||||||
|
|
||||||
|
Supported formats:
|
||||||
|
name-version
|
||||||
|
name-version-yyyy-mm-dd
|
||||||
|
name-yyyy-mm-dd
|
||||||
|
"""
|
||||||
|
if hasattr(self, "_runtime"):
|
||||||
|
return self._runtime
|
||||||
|
|
||||||
|
self._runtime = (None, None, None)
|
||||||
|
|
||||||
|
runtime_path = self.binder_path("runtime.txt")
|
||||||
|
try:
|
||||||
|
with open(runtime_path) as f:
|
||||||
|
runtime_txt = f.read().strip()
|
||||||
|
except FileNotFoundError:
|
||||||
|
return self._runtime
|
||||||
|
|
||||||
|
name = None
|
||||||
|
version = None
|
||||||
|
date = None
|
||||||
|
|
||||||
|
parts = runtime_txt.split("-")
|
||||||
|
if len(parts) not in (2, 4, 5) or any(not (p) for p in parts):
|
||||||
|
raise ValueError(f"Invalid runtime.txt: {runtime_txt}")
|
||||||
|
|
||||||
|
name = parts[0]
|
||||||
|
|
||||||
|
if len(parts) in (2, 5):
|
||||||
|
version = parts[1]
|
||||||
|
|
||||||
|
if len(parts) in (4, 5):
|
||||||
|
date = "-".join(parts[-3:])
|
||||||
|
if not re.match(r"\d\d\d\d-\d\d-\d\d", date):
|
||||||
|
raise ValueError(f"Invalid runtime.txt date: {date}")
|
||||||
|
date = datetime.datetime.fromisoformat(date).date()
|
||||||
|
|
||||||
|
self._runtime = (name, version, date)
|
||||||
|
return self._runtime
|
||||||
|
|
|
@ -187,12 +187,9 @@ class PipfileBuildPack(CondaBuildPack):
|
||||||
def detect(self):
|
def detect(self):
|
||||||
"""Check if current repo should be built with the Pipfile buildpack."""
|
"""Check if current repo should be built with the Pipfile buildpack."""
|
||||||
# first make sure python is not explicitly unwanted
|
# first make sure python is not explicitly unwanted
|
||||||
runtime_txt = self.binder_path("runtime.txt")
|
name = self.runtime[0]
|
||||||
if os.path.exists(runtime_txt):
|
if name and name != "python":
|
||||||
with open(runtime_txt) as f:
|
return False
|
||||||
runtime = f.read().strip()
|
|
||||||
if not runtime.startswith("python-"):
|
|
||||||
return False
|
|
||||||
|
|
||||||
pipfile = self.binder_path("Pipfile")
|
pipfile = self.binder_path("Pipfile")
|
||||||
pipfile_lock = self.binder_path("Pipfile.lock")
|
pipfile_lock = self.binder_path("Pipfile.lock")
|
||||||
|
|
|
@ -15,14 +15,10 @@ class PythonBuildPack(CondaBuildPack):
|
||||||
if hasattr(self, "_python_version"):
|
if hasattr(self, "_python_version"):
|
||||||
return self._python_version
|
return self._python_version
|
||||||
|
|
||||||
try:
|
name, version, _ = self.runtime
|
||||||
with open(self.binder_path("runtime.txt")) as f:
|
|
||||||
runtime = f.read().strip()
|
|
||||||
except FileNotFoundError:
|
|
||||||
runtime = ""
|
|
||||||
|
|
||||||
if not runtime.startswith("python-"):
|
if name != "python" or not version:
|
||||||
# not a Python runtime (e.g. R, which subclasses this)
|
# Either not specified, or not a Python runtime (e.g. R, which subclasses this)
|
||||||
# use the default Python
|
# use the default Python
|
||||||
self._python_version = self.major_pythons["3"]
|
self._python_version = self.major_pythons["3"]
|
||||||
self.log.warning(
|
self.log.warning(
|
||||||
|
@ -30,7 +26,7 @@ class PythonBuildPack(CondaBuildPack):
|
||||||
)
|
)
|
||||||
return self._python_version
|
return self._python_version
|
||||||
|
|
||||||
py_version_info = runtime.split("-", 1)[1].split(".")
|
py_version_info = version.split(".")
|
||||||
py_version = ""
|
py_version = ""
|
||||||
if len(py_version_info) == 1:
|
if len(py_version_info) == 1:
|
||||||
py_version = self.major_pythons[py_version_info[0]]
|
py_version = self.major_pythons[py_version_info[0]]
|
||||||
|
@ -138,16 +134,11 @@ class PythonBuildPack(CondaBuildPack):
|
||||||
def detect(self):
|
def detect(self):
|
||||||
"""Check if current repo should be built with the Python buildpack."""
|
"""Check if current repo should be built with the Python buildpack."""
|
||||||
requirements_txt = self.binder_path("requirements.txt")
|
requirements_txt = self.binder_path("requirements.txt")
|
||||||
runtime_txt = self.binder_path("runtime.txt")
|
|
||||||
setup_py = "setup.py"
|
setup_py = "setup.py"
|
||||||
|
|
||||||
if os.path.exists(runtime_txt):
|
name = self.runtime[0]
|
||||||
with open(runtime_txt) as f:
|
if name:
|
||||||
runtime = f.read().strip()
|
return name == "python"
|
||||||
if runtime.startswith("python-"):
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
if not self.binder_dir and os.path.exists(setup_py):
|
if not self.binder_dir and os.path.exists(setup_py):
|
||||||
return True
|
return True
|
||||||
return os.path.exists(requirements_txt)
|
return os.path.exists(requirements_txt)
|
||||||
|
|
|
@ -46,21 +46,6 @@ class RBuildPack(PythonBuildPack):
|
||||||
R is installed from https://docs.rstudio.com/resources/install-r/
|
R is installed from https://docs.rstudio.com/resources/install-r/
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@property
|
|
||||||
def runtime(self):
|
|
||||||
"""
|
|
||||||
Return contents of runtime.txt if it exists, '' otherwise
|
|
||||||
"""
|
|
||||||
if not hasattr(self, "_runtime"):
|
|
||||||
runtime_path = self.binder_path("runtime.txt")
|
|
||||||
try:
|
|
||||||
with open(runtime_path) as f:
|
|
||||||
self._runtime = f.read().strip()
|
|
||||||
except FileNotFoundError:
|
|
||||||
self._runtime = ""
|
|
||||||
|
|
||||||
return self._runtime
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def r_version(self):
|
def r_version(self):
|
||||||
"""Detect the R version for a given `runtime.txt`
|
"""Detect the R version for a given `runtime.txt`
|
||||||
|
@ -70,6 +55,7 @@ class RBuildPack(PythonBuildPack):
|
||||||
"""
|
"""
|
||||||
# Available versions at https://cran.r-project.org/src/base/
|
# Available versions at https://cran.r-project.org/src/base/
|
||||||
version_map = {
|
version_map = {
|
||||||
|
"4.5": "4.5.1",
|
||||||
"4.4": "4.4.2",
|
"4.4": "4.4.2",
|
||||||
"4.3": "4.3.3",
|
"4.3": "4.3.3",
|
||||||
"4.2": "4.2.3",
|
"4.2": "4.2.3",
|
||||||
|
@ -91,11 +77,11 @@ class RBuildPack(PythonBuildPack):
|
||||||
r_version = version_map["4.4"]
|
r_version = version_map["4.4"]
|
||||||
|
|
||||||
if not hasattr(self, "_r_version"):
|
if not hasattr(self, "_r_version"):
|
||||||
parts = self.runtime.split("-")
|
_, version, date = self.runtime
|
||||||
# If runtime.txt is not set, or if it isn't of the form r-<version>-<yyyy>-<mm>-<dd>,
|
# If runtime.txt is not set, or if it isn't of the form r-<version>-<yyyy>-<mm>-<dd>,
|
||||||
# we don't use any of it in determining r version and just use the default
|
# we don't use any of it in determining r version and just use the default
|
||||||
if len(parts) == 5:
|
if version and date:
|
||||||
r_version = parts[1]
|
r_version = version
|
||||||
# For versions of form x.y, we want to explicitly provide x.y.z - latest patchlevel
|
# For versions of form x.y, we want to explicitly provide x.y.z - latest patchlevel
|
||||||
# available. Users can however explicitly specify the full version to get something specific
|
# available. Users can however explicitly specify the full version to get something specific
|
||||||
if r_version in version_map:
|
if r_version in version_map:
|
||||||
|
@ -131,15 +117,11 @@ class RBuildPack(PythonBuildPack):
|
||||||
Returns '' if no date is specified
|
Returns '' if no date is specified
|
||||||
"""
|
"""
|
||||||
if not hasattr(self, "_checkpoint_date"):
|
if not hasattr(self, "_checkpoint_date"):
|
||||||
match = re.match(r"r-(\d.\d(.\d)?-)?(\d\d\d\d)-(\d\d)-(\d\d)", self.runtime)
|
name, version, date = self.runtime
|
||||||
if not match:
|
if name == "r" and date:
|
||||||
self._checkpoint_date = False
|
self._checkpoint_date = date
|
||||||
else:
|
else:
|
||||||
# turn the last three groups of the match into a date
|
self._checkpoint_date = False
|
||||||
self._checkpoint_date = datetime.date(
|
|
||||||
*[int(s) for s in match.groups()[-3:]]
|
|
||||||
)
|
|
||||||
|
|
||||||
return self._checkpoint_date
|
return self._checkpoint_date
|
||||||
|
|
||||||
def detect(self):
|
def detect(self):
|
||||||
|
@ -157,13 +139,9 @@ class RBuildPack(PythonBuildPack):
|
||||||
|
|
||||||
description_R = "DESCRIPTION"
|
description_R = "DESCRIPTION"
|
||||||
if not self.binder_dir and os.path.exists(description_R):
|
if not self.binder_dir and os.path.exists(description_R):
|
||||||
if not self.checkpoint_date:
|
# no R snapshot date set through runtime.txt
|
||||||
# no R snapshot date set through runtime.txt
|
# Set it to two days ago from today
|
||||||
# Set it to two days ago from today
|
self._checkpoint_date = datetime.date.today() - datetime.timedelta(days=2)
|
||||||
self._checkpoint_date = datetime.date.today() - datetime.timedelta(
|
|
||||||
days=2
|
|
||||||
)
|
|
||||||
self._runtime = f"r-{str(self._checkpoint_date)}"
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@lru_cache
|
@lru_cache
|
||||||
|
|
|
@ -107,6 +107,13 @@ class DockerEngine(ContainerEngine):
|
||||||
):
|
):
|
||||||
if not shutil.which("docker"):
|
if not shutil.which("docker"):
|
||||||
raise RuntimeError("The docker commandline client must be installed")
|
raise RuntimeError("The docker commandline client must be installed")
|
||||||
|
|
||||||
|
# docker buildx is based in a plugin that might not be installed
|
||||||
|
# https://github.com/docker/buildx
|
||||||
|
docker_buildx_version = subprocess.run(["docker", "buildx", "version"])
|
||||||
|
if docker_buildx_version.returncode:
|
||||||
|
raise RuntimeError("The docker buildx plugin must be installed")
|
||||||
|
|
||||||
args = ["docker", "buildx", "build", "--progress", "plain"]
|
args = ["docker", "buildx", "build", "--progress", "plain"]
|
||||||
if load:
|
if load:
|
||||||
if push:
|
if push:
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
r-4.4-2025-01-01
|
|
|
@ -0,0 +1 @@
|
||||||
|
r-4.5.1-2025-06-13
|
|
@ -1,9 +1,9 @@
|
||||||
#!/usr/bin/env Rscript
|
#!/usr/bin/env Rscript
|
||||||
library('digest')
|
library('digest')
|
||||||
|
|
||||||
# Fail if version is not 4.0
|
# Fail if version is not 4.5
|
||||||
print(version)
|
print(version)
|
||||||
if (!(version$major == "4" && as.double(version$minor) >= 4 && as.double(version$minor) < 5)) {
|
if (!(version$major == "4" && as.double(version$minor) >= 5 && as.double(version$minor) < 6)) {
|
||||||
quit("yes", 1)
|
quit("yes", 1)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
|
from datetime import date
|
||||||
from os.path import join as pjoin
|
from os.path import join as pjoin
|
||||||
from tempfile import TemporaryDirectory
|
from tempfile import TemporaryDirectory
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from repo2docker.buildpacks import LegacyBinderDockerBuildPack, PythonBuildPack
|
from repo2docker.buildpacks import (
|
||||||
|
BaseImage,
|
||||||
|
LegacyBinderDockerBuildPack,
|
||||||
|
PythonBuildPack,
|
||||||
|
)
|
||||||
from repo2docker.utils import chdir
|
from repo2docker.utils import chdir
|
||||||
|
|
||||||
|
|
||||||
|
@ -46,3 +51,45 @@ def test_unsupported_python(tmpdir, python_version, base_image):
|
||||||
assert bp.python_version == python_version
|
assert bp.python_version == python_version
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
bp.render()
|
bp.render()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"runtime_txt, expected",
|
||||||
|
[
|
||||||
|
(None, (None, None, None)),
|
||||||
|
("abc-001", ("abc", "001", None)),
|
||||||
|
("abc-001-2025-06-22", ("abc", "001", date(2025, 6, 22))),
|
||||||
|
("abc-2025-06-22", ("abc", None, date(2025, 6, 22))),
|
||||||
|
("a_b/c-0.0.1-2025-06-22", ("a_b/c", "0.0.1", date(2025, 6, 22))),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_runtime(tmpdir, runtime_txt, expected, base_image):
|
||||||
|
tmpdir.chdir()
|
||||||
|
|
||||||
|
if runtime_txt is not None:
|
||||||
|
with open("runtime.txt", "w") as f:
|
||||||
|
f.write(runtime_txt)
|
||||||
|
|
||||||
|
base = BaseImage(base_image)
|
||||||
|
assert base.runtime == expected
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"runtime_txt",
|
||||||
|
[
|
||||||
|
"",
|
||||||
|
"abc",
|
||||||
|
"abc-001-25-06-22",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_invalid_runtime(tmpdir, runtime_txt, base_image):
|
||||||
|
tmpdir.chdir()
|
||||||
|
|
||||||
|
if runtime_txt is not None:
|
||||||
|
with open("runtime.txt", "w") as f:
|
||||||
|
f.write(runtime_txt)
|
||||||
|
|
||||||
|
base = BaseImage(base_image)
|
||||||
|
|
||||||
|
with pytest.raises(ValueError, match=r"^Invalid runtime.txt.*"):
|
||||||
|
base.runtime
|
||||||
|
|
Ładowanie…
Reference in New Issue