From 9c40da1e27c0aeed43f0eb996d0c1a0fda34414a Mon Sep 17 00:00:00 2001 From: yacchin1205 <968739+yacchin1205@users.noreply.github.com> Date: Tue, 14 Jul 2026 14:24:47 +0900 Subject: [PATCH 1/2] Update CS-repo2docker to 2026.07.2 --- dev-requirements.txt | 2 +- helm-chart/images/binderhub/requirements.in | 2 +- helm-chart/images/binderhub/requirements.txt | 2 +- requirements.txt | 2 +- testing/local-binder-local-hub/requirements.txt | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dev-requirements.txt b/dev-requirements.txt index 1d909a09b..da4f1554d 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -4,7 +4,7 @@ chartpress>=2.1 click dockerspawner jsonschema -jupyter-repo2docker @ git+https://github.com/RCOSDP/CS-repo2docker.git@2026.06.0 +jupyter-repo2docker @ git+https://github.com/RCOSDP/CS-repo2docker.git@2026.07.2 jupyter_packaging>=0.10.4,<2 jupyterhub @ git+https://github.com/RCOSDP/CS-jupyterhub.git@5.2.1 nest-asyncio diff --git a/helm-chart/images/binderhub/requirements.in b/helm-chart/images/binderhub/requirements.in index bbb603978..db0832b1a 100644 --- a/helm-chart/images/binderhub/requirements.in +++ b/helm-chart/images/binderhub/requirements.in @@ -12,7 +12,7 @@ google-cloud-logging==3.* jupyterhub @ git+https://github.com/RCOSDP/CS-jupyterhub.git@5.2.1 # jupyter-repo2docker is pinned to CS-repo2docker -jupyter-repo2docker @ git+https://github.com/RCOSDP/CS-repo2docker.git@2026.06.0 +jupyter-repo2docker @ git+https://github.com/RCOSDP/CS-repo2docker.git@2026.07.2 # Workaround: Added a dependecy of ruamel-yaml because jupyter-telemetry, # which has a dependency of ruamel-yaml, was removed from jupyterhub. diff --git a/helm-chart/images/binderhub/requirements.txt b/helm-chart/images/binderhub/requirements.txt index fa6f1c335..761a59833 100644 --- a/helm-chart/images/binderhub/requirements.txt +++ b/helm-chart/images/binderhub/requirements.txt @@ -127,7 +127,7 @@ jsonschema-specifications==2025.9.1 # via jsonschema jupyter-events==0.12.0 # via jupyterhub -jupyter-repo2docker @ git+https://github.com/RCOSDP/CS-repo2docker.git@2026.06.0 +jupyter-repo2docker @ git+https://github.com/RCOSDP/CS-repo2docker.git@2026.07.2 # via # -r helm-chart/images/binderhub/../../../requirements.txt # -r helm-chart/images/binderhub/requirements.in diff --git a/requirements.txt b/requirements.txt index 064a84e5a..d72effd10 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,7 +3,7 @@ escapism jinja2 jsonschema jupyterhub @ git+https://github.com/RCOSDP/CS-jupyterhub.git@5.2.1 -jupyter-repo2docker @ git+https://github.com/RCOSDP/CS-repo2docker.git@2026.06.0 +jupyter-repo2docker @ git+https://github.com/RCOSDP/CS-repo2docker.git@2026.07.2 kubernetes prometheus_client pyjwt>=2 diff --git a/testing/local-binder-local-hub/requirements.txt b/testing/local-binder-local-hub/requirements.txt index 6cb118686..fcd621df3 100644 --- a/testing/local-binder-local-hub/requirements.txt +++ b/testing/local-binder-local-hub/requirements.txt @@ -1,3 +1,3 @@ dockerspawner>=12 -jupyter-repo2docker @ git+https://github.com/RCOSDP/CS-repo2docker.git@2026.06.0 +jupyter-repo2docker @ git+https://github.com/RCOSDP/CS-repo2docker.git@2026.07.2 jupyterhub @ git+https://github.com/RCOSDP/CS-jupyterhub.git@5.2.1 From d8327a617202f6b08d4a6553ac8382dfeeb42ea8 Mon Sep 17 00:00:00 2001 From: Min RK Date: Fri, 10 Apr 2026 15:06:07 -0700 Subject: [PATCH 2/2] fix unversioned figshare doi handling rather than parse mutable URL schemes (since it has changed recently), parse more stable doi scheme and use figshare API to resolve versions if needed important fix: for dois without version, figshare resolves to latest, not 1 --- binderhub/repoproviders.py | 34 +++++++++++++++---- .../tests/http-record.api.figshare.com.json | 17 ++++++++++ binderhub/tests/test_repoproviders.py | 10 +++--- 3 files changed, 49 insertions(+), 12 deletions(-) create mode 100644 binderhub/tests/http-record.api.figshare.com.json diff --git a/binderhub/repoproviders.py b/binderhub/repoproviders.py index ebd937bd2..4bd2041a5 100644 --- a/binderhub/repoproviders.py +++ b/binderhub/repoproviders.py @@ -357,18 +357,38 @@ class FigshareProvider(RepoProvider): "ref": {"enabled": False}, } - url_regex = re.compile(r"(.*)/articles/([^/]+)/(\d+)(/)?(\d+)?") - async def get_resolved_ref(self): client = AsyncHTTPClient() req = HTTPRequest(f"https://doi.org/{self.spec}", user_agent="BinderHub") + # fetch doi: will 404 if it doesn't exist r = await client.fetch(req) + # parse doi, not figshare url + _doi_n, _, identifier = self.spec.partition("/") + doi_fields = identifier.split(".") + # 2 cases: + # versioned: 10.6084/m9.figshare.9782777.v1 + # unversioned: 10.6084/m9.figshare.9782777 + if len(doi_fields) < 3: + raise ValueError(f"Unexpected figshare doi: {self.spec}") + if doi_fields[-1].startswith("v"): + article_version = doi_fields[-1][1:] + article_id = doi_fields[-2] + else: + # unversioned, get latest version from API + # unversioned defaults to latest, + # and figshare doesn't put version in url, + # so resolve latest version from api + article_id = doi_fields[-1] + r = await client.fetch( + f"https://api.figshare.com/v2/articles/{article_id}/versions", + user_agent="BinderHub", + ) + # list of versions containing {"version": 2} + article_versions = json.loads(r.body) + if not article_versions: + raise ValueError(f"Article {article_id} has no versions") + article_version = sorted(v["version"] for v in article_versions)[-1] - match = self.url_regex.match(r.effective_url) - article_id = match.groups()[2] - article_version = match.groups()[4] - if not article_version: - article_version = "1" self.record_id = f"{article_id}.v{article_version}" return self.record_id diff --git a/binderhub/tests/http-record.api.figshare.com.json b/binderhub/tests/http-record.api.figshare.com.json new file mode 100644 index 000000000..351bb8ed0 --- /dev/null +++ b/binderhub/tests/http-record.api.figshare.com.json @@ -0,0 +1,17 @@ +{ + "https://api.figshare.com/v2/articles/9782777/versions": { + "body": "[{\"version\": 1, \"url\": \"https://api.figshare.com/v2/articles/9782777/versions/1\"}, {\"version\": 2, \"url\": \"https://api.figshare.com/v2/articles/9782777/versions/2\"}, {\"version\": 3, \"url\": \"https://api.figshare.com/v2/articles/9782777/versions/3\"}]", + "code": 200, + "headers": { + "Access-Control-Allow-Credentials": "true", + "Access-Control-Allow-Headers": "Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization,X-API-Revision", + "Access-Control-Allow-Methods": "GET, POST, OPTIONS, DELETE, PUT", + "Access-Control-Expose-Headers": "Location", + "Content-Encoding": "gzip", + "Content-Type": "application/json", + "Date": "Fri, 10 Apr 2026 22:03:18 GMT", + "Server": "nginx", + "Vary": "Accept-Encoding" + } + } +} diff --git a/binderhub/tests/test_repoproviders.py b/binderhub/tests/test_repoproviders.py index 124ece413..0bfb02e38 100644 --- a/binderhub/tests/test_repoproviders.py +++ b/binderhub/tests/test_repoproviders.py @@ -105,13 +105,13 @@ async def test_zenodo(spec, resolved_spec, resolved_ref, resolved_ref_url, build "https://doi.org/10.6084/m9.figshare.9782777.v1", "figshare-9782777.v1", ], - # spec without version is accepted as version 1 - check FigshareProvider.get_resolved_ref() + # spec without version is accepted as latest version - check FigshareProvider.get_resolved_ref() [ "10.6084/m9.figshare.9782777", - "10.6084/m9.figshare.9782777.v1", - "9782777.v1", - "https://doi.org/10.6084/m9.figshare.9782777.v1", - "figshare-9782777.v1", + "10.6084/m9.figshare.9782777.v3", + "9782777.v3", + "https://doi.org/10.6084/m9.figshare.9782777.v3", + "figshare-9782777.v3", ], ], )