diff --git a/docs/source/config_files.rst b/docs/source/config_files.rst index 1c2cca45b..eabbdb56b 100644 --- a/docs/source/config_files.rst +++ b/docs/source/config_files.rst @@ -118,7 +118,7 @@ with ``REQUIRE`` and ``environment.yml``, visit ================================================ This is used to install R libraries pinned to a specific snapshot on -`MRAN `_. +`Posit Package Manager `_. To set the date of the snapshot add a runtime.txt_. For an example ``install.R`` file, visit our `example install.R file `_. @@ -207,7 +207,7 @@ For these cases, we have a special file, ``runtime.txt``. Have ``python-x.y`` in ``runtime.txt`` to run the repository with Python version x.y. See our `Python2 example repository `_. -Have ``r----
`` in ``runtime.txt`` to run the repository with R version RVERSION and libraries from a YYYY-MM-DD snapshot of `MRAN `_. +Have ``r----
`` in ``runtime.txt`` to run the repository with R version RVERSION and libraries from a YYYY-MM-DD snapshot of `Posit Package Manager `__. RVERSION can be set to 3.4, 3.5, 3.6, or to patch releases for the 3.5 and 3.6 series. If you do not specify a version, the latest release will be used (currently R 3.6). See our `R example repository `_. diff --git a/docs/source/howto/languages.rst b/docs/source/howto/languages.rst index 75ea7e537..af51a6fdf 100644 --- a/docs/source/howto/languages.rst +++ b/docs/source/howto/languages.rst @@ -65,17 +65,14 @@ to install libraries from on the given date. You can install more R packages fro by adding a :ref:`install.R` file to your repo. RStudio and IRKernel are installed by default for all R versions. -If you request R 4.1 or later, or specify a snapshot date newer than -``2022-01-01``, `packagemanager.posit.co `_ +`packagemanager.posit.co `_ will be used to provide much faster installations via `binary packages `_. For *some* packages, this might require you install underlying system libraries using :ref:`apt.txt` - look at the page for the CRAN package you are interested in at `packagemanager.posit.co `_ to find a list. -For older R versions with an older snapshot date, `MRAN `_ -is used as source of packages. This purely provides source packages, and you should -migrate away from this if possible. +repo2docker stopped using the Microsoft mirror MRAN for older R versions after its shutdown in July, 2023. Julia diff --git a/repo2docker/buildpacks/r.py b/repo2docker/buildpacks/r.py index 464587d6a..7dd724e04 100644 --- a/repo2docker/buildpacks/r.py +++ b/repo2docker/buildpacks/r.py @@ -9,6 +9,10 @@ from ._r_base import rstudio_base_scripts from .python import PythonBuildPack +# Aproximately the first snapshot on RSPM (Posit package manager) +# that seems to have a working IRKernel. +RSPM_CUTOFF_DATE = datetime.date(2018, 12, 7) + class RBuildPack(PythonBuildPack): """ @@ -22,8 +26,7 @@ class RBuildPack(PythonBuildPack): Where 'year', 'month' and 'date' refer to a specific date whose CRAN snapshot we will use to fetch packages. - Uses https://packagemanager.posit.co, or MRAN if no snapshot - is found on packagemanager.posit.co + Uses https://packagemanager.posit.co. 2. A `DESCRIPTION` file signaling an R package @@ -229,31 +232,6 @@ def get_rspm_snapshot_url(self, snapshot_date, max_days_prior=7): ) ) - @lru_cache() - def get_mran_snapshot_url(self, snapshot_date, max_days_prior=7): - for i in range(max_days_prior): - try_date = snapshot_date - datetime.timedelta(days=i) - # Fall back to MRAN if packagemanager.posit.co doesn't have it - url = f"https://mran.microsoft.com/snapshot/{try_date.isoformat()}" - r = requests.head(url) - if r.ok: - return url - raise ValueError( - "No snapshot found for {} or {} days prior in mran.microsoft.com".format( - snapshot_date.strftime("%Y-%m-%d"), max_days_prior - ) - ) - - @lru_cache() - def get_cran_mirror_url(self, snapshot_date): - # Date after which we will use rspm + binary packages instead of MRAN + source packages - rspm_cutoff_date = datetime.date(2022, 1, 1) - - if snapshot_date >= rspm_cutoff_date or self.r_version >= V("4.1"): - return self.get_rspm_snapshot_url(snapshot_date) - else: - return self.get_mran_snapshot_url(snapshot_date) - @lru_cache() def get_devtools_snapshot_url(self): """ @@ -291,8 +269,14 @@ def get_build_scripts(self): We set the snapshot date used to install R libraries from based on the contents of runtime.txt. """ + if self.checkpoint_date < RSPM_CUTOFF_DATE: + raise RuntimeError( + f'Microsoft killed MRAN, the source of R package snapshots before {RSPM_CUTOFF_DATE.strftime("%Y-%m-%d")}. ' + f'This repo has a snapshot date of {self.checkpoint_date.strftime("%Y-%m-%d")} specified in runtime.txt. ' + "Please use a newer snapshot date" + ) - cran_mirror_url = self.get_cran_mirror_url(self.checkpoint_date) + cran_mirror_url = self.get_rspm_snapshot_url(self.checkpoint_date) if self.platform != "linux/amd64": raise RuntimeError( diff --git a/tests/r/README.md b/tests/r/README.md index 61df6db48..51488e41f 100644 --- a/tests/r/README.md +++ b/tests/r/README.md @@ -24,18 +24,6 @@ `runtime.txt` is omitted and a recent enough snapshot date is assumed a RSPM snapshot of CRAN to be used. -### r3.6-mran - -- Test setup of a R 3.6 environment by specifying `r-3.6-...` in `runtime.txt`, - where the date provided in `runtime.txt` is old enough for a MRAN snapshot of - CRAN to be used. - -### r4.0-mran - -- Test setup of a R 4.0 environment by specifying `r-4.0-...` in `runtime.txt`, - where the date provided in `runtime.txt` is old enough for a MRAN snapshot of - CRAN to be used. - ### r4.0-rspm - Test setup of a R 4.0 environment by specifying `r-4.0-...` in `runtime.txt`, diff --git a/tests/r/r3.6-mran/runtime.txt b/tests/r/r3.6-mran/runtime.txt deleted file mode 100644 index 308424ab2..000000000 --- a/tests/r/r3.6-mran/runtime.txt +++ /dev/null @@ -1 +0,0 @@ -r-3.6-2016-01-03 diff --git a/tests/r/r3.6-mran/install.R b/tests/r/r3.6-rspm/install.R similarity index 100% rename from tests/r/r3.6-mran/install.R rename to tests/r/r3.6-rspm/install.R diff --git a/tests/r/r3.6-rspm/runtime.txt b/tests/r/r3.6-rspm/runtime.txt new file mode 100644 index 000000000..ef918a220 --- /dev/null +++ b/tests/r/r3.6-rspm/runtime.txt @@ -0,0 +1 @@ +r-3.6-2018-12-07 diff --git a/tests/r/r3.6-mran/verify b/tests/r/r3.6-rspm/verify similarity index 63% rename from tests/r/r3.6-mran/verify rename to tests/r/r3.6-rspm/verify index 26f561028..475dd91f8 100755 --- a/tests/r/r3.6-mran/verify +++ b/tests/r/r3.6-rspm/verify @@ -7,7 +7,7 @@ if (!(version$major == "3" && as.double(version$minor) >= 6 && as.double(version quit("yes", 1) } -# Fail if MRAN isn't the configured CRAN mirror -if (!(startsWith(options()$repos["CRAN"], "https://mran.microsoft.com"))) { +# Fail if RSPM isn't the configured CRAN mirror +if (!(startsWith(options()$repos["CRAN"], "https://packagemanager.posit.co"))) { quit("yes", 1) } diff --git a/tests/r/r4.0-mran/install.R b/tests/r/r4.0-mran/install.R deleted file mode 100644 index f609959ef..000000000 --- a/tests/r/r4.0-mran/install.R +++ /dev/null @@ -1 +0,0 @@ -install.packages("digest") diff --git a/tests/r/r4.0-mran/runtime.txt b/tests/r/r4.0-mran/runtime.txt deleted file mode 100644 index b051a4326..000000000 --- a/tests/r/r4.0-mran/runtime.txt +++ /dev/null @@ -1 +0,0 @@ -r-4.0-2021-07-07 diff --git a/tests/r/r4.0-mran/verify b/tests/r/r4.0-mran/verify deleted file mode 100755 index b821ec6cc..000000000 --- a/tests/r/r4.0-mran/verify +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env Rscript -library('digest') - -# Fail if version is not 4.0 -print(version) -if (!(version$major == "4" && as.double(version$minor) >= 0 && as.double(version$minor) < 1)) { - quit("yes", 1) -} - -# The date we have chosen should give us an MRAN mirror -if (!(startsWith(options()$repos["CRAN"], "https://mran.microsoft.com"))) { - quit("yes", 1) -} \ No newline at end of file diff --git a/tests/unit/test_r.py b/tests/unit/test_r.py index f30d542a8..a7028d829 100644 --- a/tests/unit/test_r.py +++ b/tests/unit/test_r.py @@ -40,7 +40,7 @@ def test_version_completion(tmpdir, base_image): ("r-3.5-2019-01-01", (2019, 1, 1)), ], ) -def test_mran_date(tmpdir, runtime, expected, base_image): +def test_cran_date(tmpdir, runtime, expected, base_image): tmpdir.chdir() with open("runtime.txt", "w") as f: @@ -74,21 +74,15 @@ def test_snapshot_rspm_date(base_image): r.get_rspm_snapshot_url(date(1691, 9, 5)) -@pytest.mark.parametrize("expected", [date(2019, 12, 29), date(2019, 12, 26)]) -@pytest.mark.parametrize("requested", [date(2019, 12, 31)]) -def test_snapshot_mran_date(requested, expected, base_image): - def mock_request_head(url): - r = Response() - if url == "https://mran.microsoft.com/snapshot/" + expected.isoformat(): - r.status_code = 200 - else: - r.status_code = 404 - r.reason = "Mock MRAN no snapshot" - return r - - with patch("requests.head", side_effect=mock_request_head): - r = buildpacks.RBuildPack(base_image) - assert ( - r.get_mran_snapshot_url(requested) - == f"https://mran.microsoft.com/snapshot/{expected.isoformat()}" - ) +def test_mran_dead(tmpdir, base_image): + tmpdir.chdir() + + with open("runtime.txt", "w") as f: + f.write("r-3.6-2017-06-04") + + r = buildpacks.RBuildPack(base_image) + with pytest.raises( + RuntimeError, + match=r"^Microsoft killed MRAN, the source of R package snapshots before 2018-12-07.*", + ): + r.get_build_scripts()