Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ci] consolidate R package installs into a CI script #6808

Merged
merged 21 commits into from
Feb 24, 2025

Conversation

jameslamb
Copy link
Collaborator

@jameslamb jameslamb commented Jan 31, 2025

Follow-up to #6804 (comment)

Consolidates the various install.packages() calls across the project's CI into a single .ci/ script.

Notes for Reviewers

I'm intentionally not proposing updating user-facing docs like this:

# install dependencies
RDscript${R_CUSTOMIZATION} \
-e "install.packages(c('R6', 'data.table', 'jsonlite', 'knitr', 'markdown', 'Matrix', 'RhpcBLASctl', 'testthat'), repos = 'https://cran.r-project.org', Ncpus = parallel::detectCores())"

I'd like to keep this script limited to LightGBM's CI, and changeable at any time. I don't want to make it a part of the public interface of the project or encourage anyone else to use it.

@@ -65,7 +65,7 @@ jobs:
shell: bash
# yamllint disable rule:line-length
run: |
Rscript -e "install.packages(c('R6', 'data.table', 'jsonlite', 'knitr', 'markdown', 'Matrix', 'RhpcBLASctl', 'roxygen2', 'testthat'), repos = 'https://cran.rstudio.com', Ncpus = parallel::detectCores())"
Rscript ./.ci/install-r-deps.R --build --roxygen
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Notice... {testthat} and all its dependencies were being installed unnecessarily here! So this change should also make the static analysis job a little faster 🎉

Comment on lines 180 to 181
# $command_args_patch = "commandArgs <- function(...){c('--build', '--test')};"
# Invoke-R-Code-Redirect-Stderr "$command_args_patch source('install-r-deps.R')" ; Assert-Output $?
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# $command_args_patch = "commandArgs <- function(...){c('--build', '--test')};"
# Invoke-R-Code-Redirect-Stderr "$command_args_patch source('install-r-deps.R')" ; Assert-Output $?

This seems to work ok without the more complicated Invoke-R-Code-Redirect-Stderr pattern 😁

@jameslamb jameslamb changed the title WIP: [ci] consolidate R package installs into a CI script [ci] consolidate R package installs into a CI script Feb 3, 2025
@jameslamb jameslamb marked this pull request as ready for review February 3, 2025 02:32
Copy link
Collaborator

@StrikerRUS StrikerRUS left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you so much for simplifying the codebase by writing this script!

I looked carefully through the diff and left some comments below:

"lib = '$env:R_LIB_PATH', Ncpus = parallel::detectCores())"
)
Invoke-R-Code-Redirect-Stderr $params ; Assert-Output $?
Rscript.exe --vanilla ".ci/install-r-deps.R" --build --test ; Assert-Output $?
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seem that processx was lost.

"Using system2() to run shell commands. Installing "
, "'processx' with install.packages('processx') might "
, "make this faster."

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in dae117f.

Rscript.exe --vanilla ".ci/install-r-deps.R" --build --include=processx --test ; Assert-Output $?

.vsts-ci.yml Outdated
@@ -420,7 +420,7 @@ jobs:
R_LIB_PATH=~/Rlib
export R_LIBS=${R_LIB_PATH}
mkdir -p ${R_LIB_PATH}
RDscript -e "install.packages(c('R6', 'data.table', 'jsonlite', 'knitr', 'markdown', 'Matrix', 'RhpcBLASctl'), lib = '${R_LIB_PATH}', dependencies = c('Depends', 'Imports', 'LinkingTo'), repos = 'https://cran.rstudio.com', Ncpus = parallel::detectCores())" || exit 1
RDscript .ci/install-r-deps.R --build --test || exit 1
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm, I don't see testthat in master here...

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Modified this in dae117f, to

RDscript .ci/install-r-deps.R --build --include=RhpcBLASctl || exit 1

R_LIBS="c('R6', 'data.table', 'jsonlite', 'knitr', 'markdown', 'Matrix', 'RhpcBLASctl')"
Rscript \
-e "install.packages(${R_LIBS}, repos = 'https://cran.rstudio.com', Ncpus = parallel::detectCores())"
Rscript ./.ci/install-r-deps.R --build --test
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see testthat in master here...

# 'testthat' is not needed by 'rchk', so avoid installing it until here
Rscript -e "install.packages('testthat', repos = 'https://cran.rstudio.com', Ncpus = parallel::detectCores())"

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah you are right. Adding --test here was to pull in {RhpcBLASctl}. I will rework this.

Copy link
Collaborator Author

@jameslamb jameslamb Feb 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I modified this in dae117f, to this:

Rscript ./.ci/install-r-deps.R --build --test --exclude=testthat

{testthat} is installed later:

# 'testthat' is not needed by 'rchk', so avoid installing it until here
Rscript -e "install.packages('testthat', repos = 'https://cran.rstudio.com', Ncpus = parallel::detectCores())"

# always use the same CRAN mirror
CRAN_MIRROR <- Sys.getenv("CRAN_MIRROR", unset = "https://cran.r-project.org")

# we always want these
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should allow installation of arbitrary R package by this script? For example, late testthat installation or processx.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I agree! I implemented this in dae117f

Proposing adding two arguments, --include and --exclude, which are applied to the list of dependencies calculated after processing coarser arguments like --all, --build, and --test.

@jameslamb jameslamb requested a review from StrikerRUS February 8, 2025 04:22
@StrikerRUS
Copy link
Collaborator

StrikerRUS commented Feb 14, 2025

/gha run r-valgrind

Workflow R valgrind tests has been triggered! 🚀
https://github.com/microsoft/LightGBM/actions/runs/13328574983

Status: success ✔️.

Copy link
Collaborator

@StrikerRUS StrikerRUS left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please consider checking my next round of comments. One of them about roxygen2 is important, I think.

run: |
Rscript -e "install.packages(c('R6', 'data.table', 'jsonlite', 'knitr', 'markdown', 'Matrix', 'RhpcBLASctl', 'roxygen2', 'testthat'), repos = 'https://cran.rstudio.com', Ncpus = parallel::detectCores())"
Rscript ./.ci/install-r-deps.R --build --include=roxygen
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Rscript ./.ci/install-r-deps.R --build --include=roxygen
Rscript ./.ci/install-r-deps.R --build --include=roxygen2

Hmmm... Strange that check-docs job was failed but green.

Warning message:
package ‘roxygen’ is not available for this version of R

A version of this package for your version of R might be available elsewhere,
see the ideas at
https://cran.r-project.org/doc/manuals/r-patched/R-admin.html#Installing-packages 
Run Rscript --vanilla -e "roxygen2::roxygenize('R-package/', load = 'installed')" || exit 1
✖ In topic 'lgb_predict_shared_params.Rd': Skipping; no name and/or title.

https://github.com/microsoft/LightGBM/actions/runs/13361788471/job/37312577620?pr=6808#step:6:22

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🙈 oy, thank you for catching this.

Looks like we are getting{roxygen2} that comes pre-installed in the container image used for that job.

container: rocker/verse

docker run \
  --rm \
  --platform linux/amd64 \
  -it rocker/verse \
  Rscript -e "library(roxygen2); print(sessionInfo())"
...
other attached packages:
[1] roxygen2_7.3.2
...

That note about lgb_predict_shared_params comes from roxygen2::roxygenize(), so {roxygen2} must be installed. It's just a warning, so it wouldn't cause this to fail.

And then I guess the other reason this isn't failing is that install.packages() returns a 0 exit code for a non-existent package 🙃

Rscript -e "install.packages('doesnotexist', repos = 'https://cran.r-project.org')"
# Warning message:
# package ‘doesnotexist’ is not available for this version of R

echo $?
# 0

So many things together led to this silently passing. I'm very very glad you were so thorough and caught this bug that CI didn't, thank you!!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's just a warning, so it wouldn't cause this to fail.

Ah, ok! Thanks for clarifying. A ✖ sign confused me and I thought that roxygenization was not run at all.

install.packages() returns a 0 exit code for a non-existent package

Thanks for checking this! Indeed, this seems to be an old annoying problem without any easy workaround.
https://stackoverflow.com/q/26244530
r-lib/remotes#755 (comment)

@jameslamb jameslamb requested a review from StrikerRUS February 18, 2025 01:35
Copy link
Collaborator

@StrikerRUS StrikerRUS left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, happy to merge this finally!

@StrikerRUS StrikerRUS merged commit 6b624fb into master Feb 24, 2025
50 checks passed
@StrikerRUS StrikerRUS deleted the ci/r-deps-scripts branch February 24, 2025 00:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants