WIP: Binary distributions via GitHub Releases. #183
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| on: | |
| push: | |
| branches: | |
| - main | |
| tags: | |
| - 'v*' # Trigger on version tags | |
| pull_request: | |
| branches: | |
| - main | |
| workflow_dispatch: | |
| # enable manual triggering | |
| schedule: | |
| # run testing on the first of each month 5am ET / 9am UTC | |
| - cron: '0 9 1 * *' | |
| # Set minimal permissions for all jobs (read-only) | |
| permissions: | |
| contents: read | |
| actions: read | |
| jobs: | |
| R-build: | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| R: [ '4.4.3', '4.5.3', '4.6.0' ] | |
| os: [ 'macos-15-intel', 'ubuntu-24.04', 'windows-latest'] | |
| runs-on: ${{ matrix.os }} | |
| name: ${{ matrix.R }} ${{ matrix.os }} build | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| fetch-depth: 0 | |
| ref: ${{ github.event.pull_request.head.sha }} | |
| - name: Setup R (also sets the R_LIBS_USER environment variable) | |
| uses: r-lib/actions/setup-r@a51a8012b0aab7c32ef9d19bf54da93f3254335e # v2.12.0 | |
| with: | |
| r-version: ${{ matrix.R }} | |
| - name: System Dependencies | |
| if: startsWith( matrix.os, 'ubuntu' ) | |
| run: | | |
| sudo apt-get -y update && | |
| sudo apt-get install -y libcurl4-openssl-dev libssh2-1-dev libharfbuzz-dev libfribidi-dev gh && | |
| sudo rm -rf /var/lib/apt/lists/* | |
| - name: Configuration Information | |
| shell: bash | |
| run: | | |
| cmake --version | |
| if [[ "$RUNNER_OS" == "Windows" ]]; then | |
| ls -d /c/rtools* 2>/dev/null || echo "No rtools found in /c/" | |
| which g++ || { echo "No g++ found on PATH"; exit 1; } | |
| g++ --version | |
| else | |
| c++ --version | |
| fi | |
| which R | |
| R --version | |
| - name: Install R packages | |
| shell: bash | |
| run: | | |
| R -e "install.packages(c('remotes'), lib=Sys.getenv('R_LIBS_USER'), repos='https://cloud.r-project.org/')" | |
| - name: Build and test | |
| shell: bash | |
| env: | |
| ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS: 2 | |
| run: | | |
| R -e "Sys.setenv(MAKEJ=2); remotes::install_git(c('.'), lib=Sys.getenv('R_LIBS_USER'), upgrade='never', INSTALL_opts='--build')" | |
| R -e "library(SimpleITK); Version()" | |
| - name: Collect built package artifact | |
| id: create_package | |
| shell: bash | |
| run: | | |
| # canonical approach to collecting build artifacts in a directory for upload | |
| mkdir -p artifacts | |
| # remotes::install_git(..., INSTALL_opts='--build') writes a valid package | |
| # file into the current working directory (GITHUB_WORKSPACE). | |
| PKG_PATH=$(find "${GITHUB_WORKSPACE}" -maxdepth 1 -type f \ | |
| \( -name 'SimpleITK_*.tgz' -o -name 'SimpleITK_*.zip' -o -name 'SimpleITK_*.tar.gz' \) \ | |
| | head -n 1) | |
| if [[ -z "${PKG_PATH}" ]]; then | |
| echo "No built package artifact found in ${GITHUB_WORKSPACE}." | |
| exit 1 | |
| fi | |
| # package naming is SimpleITK_${PKG_VERSION}_R${R_VERSION_SHORT}_${OS_ARCHIVE_EXT} | |
| R_VERSION_SHORT=$(echo "${{ matrix.R }}" | cut -d'.' -f1,2) | |
| PKG_VERSION=$(Rscript -e "cat(read.dcf('DESCRIPTION', 'Version')[1])") | |
| if [[ "$RUNNER_OS" == "macOS" ]]; then | |
| PKG_NAME="SimpleITK_${PKG_VERSION}_R${R_VERSION_SHORT}_macos-x86_64.tgz" | |
| elif [[ "$RUNNER_OS" == "Linux" ]]; then | |
| PKG_NAME="SimpleITK_${PKG_VERSION}_R${R_VERSION_SHORT}_linux-x86_64.tar.gz" | |
| elif [[ "$RUNNER_OS" == "Windows" ]]; then | |
| PKG_NAME="SimpleITK_${PKG_VERSION}_R${R_VERSION_SHORT}_windows-x86_64.zip" | |
| else | |
| echo "Unsupported OS: $RUNNER_OS" | |
| exit 1 | |
| fi | |
| mv "${PKG_PATH}" "${GITHUB_WORKSPACE}/artifacts/${PKG_NAME}" | |
| ls -lh artifacts/ | |
| # Export PKG_NAME as output for use in upload step | |
| echo "pkg_name=${PKG_NAME}" >> $GITHUB_OUTPUT | |
| - name: Upload binary package | |
| if: steps.create_package.outcome == 'success' | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: ${{ steps.create_package.outputs.pkg_name }} | |
| path: artifacts/* | |
| retention-days: 30 | |
| create-release: | |
| name: Create GitHub Draft Release | |
| # Only run this job for tag pushes after the R-build job completes | |
| # successfully. | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| needs: R-build | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| fetch-depth: 1 | |
| - name: Verify tag matches SITK_TARGET | |
| id: verify_tag | |
| run: | | |
| SITK_TARGET=$(grep '^SITK_TARGET:' DESCRIPTION | awk '{print $2}') | |
| TAG_NAME="${{ github.ref_name }}" | |
| if [ "${TAG_NAME}" != "${SITK_TARGET}" ]; then | |
| echo "Tag ${TAG_NAME} does not match SITK_TARGET ${SITK_TARGET}" | |
| echo "Skipping draft release creation." | |
| echo "draft_release=false" >> $GITHUB_OUTPUT | |
| else | |
| echo "draft_release=true" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Download all artifacts | |
| if: steps.verify_tag.outputs.draft_release == 'true' | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| path: release-artifacts | |
| pattern: SimpleITK_* | |
| merge-multiple: true | |
| - name: Display downloaded artifacts | |
| if: steps.verify_tag.outputs.draft_release == 'true' | |
| run: | | |
| echo "Downloaded artifacts:" | |
| ls -lhR release-artifacts/ | |
| # This action automatically creates the release if it doesn't exist, | |
| # or updates it if it does. | |
| - name: Create or Update Draft Release | |
| if: steps.verify_tag.outputs.draft_release == 'true' | |
| uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| with: | |
| draft: true | |
| name: SimpleITK ${{ github.ref_name }} R Package Release | |
| body: | | |
| **Please review and test the packages before publishing this release. Then remove this line and make it public.** | |
| Detailed release notes are available on the [main SimpleITK repository](https://github.com/SimpleITK/SimpleITK/releases/${{ github.ref_name }}). | |
| The GitHub Pages repository provides platform-specific binaries. If a binary is not available, you will need to build SimpleITK locally using the remotes installer. See the [README](https://github.com/${{ github.repository }}/blob/main/README.md) for detailed instructions. | |
| Windows and macOS: | |
| ```r | |
| install.packages( | |
| "SimpleITK", | |
| repos = c("https://simpleitk.github.io/SimpleITKRInstaller/${{ github.ref_name }}"), | |
| type = "binary" | |
| ) | |
| ``` | |
| Linux: | |
| ```r | |
| install.packages( | |
| "SimpleITK", | |
| repos = NULL, | |
| contriburl = paste0( | |
| "https://simpleitk.github.io/SimpleITKRInstaller/${{ github.ref_name }}/__linux__/ubuntu-noble/", | |
| paste(R.version$major, sub("\\..*$", "", R.version$minor), sep = "."), | |
| "/src/contrib" | |
| ), | |
| type = "source" | |
| ) | |
| ``` | |
| The Linux install above uses a "source" type installation even though it is binary, due to the way R handles binary packages on this platform. | |
| files: | | |
| release-artifacts/* | |
| fail_on_unmatched_files: true |