Skip to content

Commit 67fd716

Browse files
authored
Merge pull request #98 from zivy/releaseAndBinaryPackages
Binary distributions via GitHub Releases.
2 parents 3a1894b + 338b72c commit 67fd716

14 files changed

Lines changed: 746 additions & 10 deletions

File tree

.github/workflows/main.yml

Lines changed: 156 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ on:
22
push:
33
branches:
44
- main
5+
tags:
6+
- 'v*' # Trigger on version tags
57
pull_request:
68
branches:
79
- main
@@ -11,25 +13,29 @@ on:
1113
# run testing on the first of each month 5am ET / 9am UTC
1214
- cron: '0 9 1 * *'
1315

16+
# Set minimal permissions for all jobs (read-only)
17+
permissions:
18+
contents: read
19+
actions: read
20+
1421
jobs:
1522
R-build:
1623
strategy:
1724
fail-fast: false
1825
matrix:
1926
R: [ '4.4.3', '4.5.3', '4.6.0' ]
20-
os: [ 'macos-15-intel', 'ubuntu-latest', 'windows-latest']
27+
os: [ 'macos-15-intel', 'ubuntu-24.04', 'windows-latest']
2128
runs-on: ${{ matrix.os }}
2229
name: ${{ matrix.R }} ${{ matrix.os }} build
23-
env:
24-
R_LIBS: ${{ github.workspace }}/Rlibs
2530

2631
steps:
27-
- uses: actions/checkout@v6
32+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
2833
with:
2934
fetch-depth: 0
3035
ref: ${{ github.event.pull_request.head.sha }}
31-
- name: Setup R
32-
uses: r-lib/actions/setup-r@v2
36+
37+
- name: Setup R (also sets the R_LIBS_USER environment variable)
38+
uses: r-lib/actions/setup-r@a51a8012b0aab7c32ef9d19bf54da93f3254335e # v2.12.0
3339
with:
3440
r-version: ${{ matrix.R }}
3541
- name: System Dependencies
@@ -41,7 +47,6 @@ jobs:
4147
- name: Configuration Information
4248
shell: bash
4349
run: |
44-
mkdir -p "$R_LIBS"
4550
cmake --version
4651
if [[ "$RUNNER_OS" == "Windows" ]]; then
4752
ls -d /c/rtools* 2>/dev/null || echo "No rtools found in /c/"
@@ -55,11 +60,153 @@ jobs:
5560
- name: Install R packages
5661
shell: bash
5762
run: |
58-
R -e "install.packages(c('remotes'), lib=Sys.getenv('R_LIBS'), repos='https://cloud.r-project.org/')"
63+
R -e "install.packages(c('remotes'), lib=Sys.getenv('R_LIBS_USER'), repos='https://cloud.r-project.org/')"
5964
- name: Build and test
6065
shell: bash
6166
env:
6267
ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS: 2
6368
run: |
64-
R -e "Sys.setenv(MAKEJ=2); remotes::install_git(c('.'), lib=Sys.getenv('R_LIBS'))"
69+
R -e "Sys.setenv(MAKEJ=2); remotes::install_git(c('.'), lib=Sys.getenv('R_LIBS_USER'), upgrade='never', INSTALL_opts='--build')"
6570
R -e "library(SimpleITK); Version()"
71+
- name: Rename package artifact
72+
# The original artifact name is SimpleITK_<sitk_version>.zip (windows),
73+
# SimpleITK_<sitk_version>.tgz (macOS), or SimpleITK_<sitk_version>.tar.gz (Linux).
74+
# This is irrespective of the R version. We need to rename them so that they are
75+
# unique. Otherwise we could not upload artifacts for different
76+
# R versions because the names collide.
77+
id: rename_package
78+
shell: bash
79+
run: |
80+
# canonical approach to collecting build artifacts in a directory for upload
81+
mkdir -p artifacts
82+
83+
# remotes::install_git(..., INSTALL_opts='--build') writes a valid package
84+
# file into the current working directory (GITHUB_WORKSPACE).
85+
PKG_PATH=$(find "${GITHUB_WORKSPACE}" -maxdepth 1 -type f \
86+
\( -name 'SimpleITK_*.tgz' -o -name 'SimpleITK_*.zip' -o -name 'SimpleITK_*.tar.gz' \) \
87+
| head -n 1)
88+
89+
if [[ -z "${PKG_PATH}" ]]; then
90+
echo "No built package artifact found in ${GITHUB_WORKSPACE}."
91+
exit 1
92+
fi
93+
94+
# package naming is SimpleITK_${PKG_VERSION}_R${R_VERSION_SHORT}_${OS_ARCHIVE_EXT}
95+
R_VERSION_SHORT=$(echo "${{ matrix.R }}" | cut -d'.' -f1,2)
96+
PKG_VERSION=$(Rscript -e "cat(read.dcf('DESCRIPTION', 'Version')[1])")
97+
98+
if [[ "$RUNNER_OS" == "macOS" ]]; then
99+
PKG_NAME="SimpleITK_${PKG_VERSION}_R${R_VERSION_SHORT}_macos-x86_64.tgz"
100+
elif [[ "$RUNNER_OS" == "Linux" ]]; then
101+
PKG_NAME="SimpleITK_${PKG_VERSION}_R${R_VERSION_SHORT}_linux-x86_64.tar.gz"
102+
elif [[ "$RUNNER_OS" == "Windows" ]]; then
103+
PKG_NAME="SimpleITK_${PKG_VERSION}_R${R_VERSION_SHORT}_windows-x86_64.zip"
104+
else
105+
echo "Unsupported OS: $RUNNER_OS"
106+
exit 1
107+
fi
108+
109+
mv "${PKG_PATH}" "${GITHUB_WORKSPACE}/artifacts/${PKG_NAME}"
110+
ls -lh artifacts/
111+
112+
# Export PKG_NAME as output for use in upload step
113+
echo "pkg_name=${PKG_NAME}" >> $GITHUB_OUTPUT
114+
- name: Upload binary package
115+
if: steps.rename_package.outcome == 'success'
116+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
117+
with:
118+
name: ${{ steps.rename_package.outputs.pkg_name }}
119+
path: artifacts/*
120+
retention-days: 30
121+
122+
create-release:
123+
name: Create GitHub Draft Release
124+
# Only run this job for tag pushes after the R-build job completes
125+
# successfully.
126+
if: startsWith(github.ref, 'refs/tags/v')
127+
needs: R-build
128+
runs-on: ubuntu-latest
129+
permissions:
130+
contents: write
131+
132+
steps:
133+
- name: Checkout repository
134+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
135+
with:
136+
fetch-depth: 1
137+
138+
- name: Verify tag matches SITK_TARGET
139+
id: verify_tag
140+
run: |
141+
SITK_TARGET=$(grep '^SITK_TARGET:' DESCRIPTION | awk '{print $2}')
142+
TAG_NAME="${{ github.ref_name }}"
143+
if [ "${TAG_NAME}" != "${SITK_TARGET}" ]; then
144+
echo "Tag ${TAG_NAME} does not match SITK_TARGET ${SITK_TARGET}"
145+
echo "Skipping draft release creation."
146+
echo "draft_release=false" >> $GITHUB_OUTPUT
147+
else
148+
echo "draft_release=true" >> $GITHUB_OUTPUT
149+
fi
150+
151+
- name: Download all artifacts
152+
if: steps.verify_tag.outputs.draft_release == 'true'
153+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
154+
with:
155+
path: release-artifacts
156+
pattern: SimpleITK_*
157+
merge-multiple: true
158+
159+
- name: Display downloaded artifacts
160+
if: steps.verify_tag.outputs.draft_release == 'true'
161+
run: |
162+
echo "Downloaded artifacts:"
163+
ls -lhR release-artifacts/
164+
165+
# This action automatically creates the release if it doesn't exist,
166+
# or updates it if it does.
167+
- name: Create or Update Draft Release
168+
if: steps.verify_tag.outputs.draft_release == 'true'
169+
uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0
170+
env:
171+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
172+
with:
173+
draft: true
174+
name: SimpleITK ${{ github.ref_name }} R Package Release
175+
body: |
176+
**Please review and test the packages before publishing this release. Then remove this line and make it public.**
177+
178+
Detailed release notes are available on the [main SimpleITK repository](https://github.com/SimpleITK/SimpleITK/releases/${{ github.ref_name }}).
179+
180+
To install SimpleITK we use a Foyer helper package that downloads the appropriate binary from the GitHub release assets. This is a two step process.
181+
182+
To install the latest SimpleITK version to your primary library directory, first element of `.libPaths()`, run the following:
183+
184+
```r
185+
# install the SimpleITK foyer package
186+
install.packages(
187+
"SimpleITK.foyer",
188+
repos = c("https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/"),
189+
type = "source"
190+
)
191+
192+
# Use foyer to install SimpleITK
193+
library(SimpleITK.foyer)
194+
install_simpleitk()
195+
```
196+
Now you can load the SimpleITK library as usual:
197+
198+
```r
199+
library(SimpleITK)
200+
```
201+
202+
The `install_simpleitk` function provides finer installation control such as SimpleITK version, library installation location and more. To see all options:
203+
204+
```r
205+
help(install_simpleitk)
206+
```
207+
208+
If you directly download the package artifact from this release page, before you install the package you will need to first unzip the file. Then rename it to `SimpleITK_<version>.zip` (windows), `SimpleITK_<version>.tgz` (macOS), or `SimpleITK_<version>.tar.gz` (Linux) to match the expected file name format.
209+
210+
files: |
211+
release-artifacts/*
212+
fail_on_unmatched_files: true
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
name: Update CRAN Repository
2+
3+
on:
4+
release:
5+
types: [published]
6+
7+
permissions:
8+
contents: write
9+
10+
concurrency:
11+
group: update-cran-repository
12+
cancel-in-progress: false
13+
14+
jobs:
15+
update-repo:
16+
runs-on: ubuntu-latest
17+
steps:
18+
- name: Checkout repository
19+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
20+
with:
21+
fetch-depth: 0
22+
ref: main
23+
24+
- name: Set up R
25+
uses: r-lib/actions/setup-r@a51a8012b0aab7c32ef9d19bf54da93f3254335e # v2.12.0
26+
27+
- name: Build Foyer Package
28+
run: |
29+
Rscript update_cran_repo.R \
30+
--foyer_dir SimpleITK_Foyer \
31+
--output_dir /tmp/cran_output \
32+
--repo_url https://github.com/${{ github.repository }}
33+
34+
- name: Deploy to gh-pages
35+
run: |
36+
git config --global user.name "github-actions[bot]"
37+
git config --global user.email "github-actions[bot]@users.noreply.github.com"
38+
git checkout gh-pages
39+
rm -rf src
40+
cp -r /tmp/cran_output/src .
41+
git add src
42+
if ! git diff --cached --quiet; then
43+
git commit -m "Update CRAN-like repository for release ${{ github.event.release.tag_name }}"
44+
git push
45+
fi

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ Authors@R: c(person("Richard", "Beare", role = c("aut", "cre"),
1313
email = "blowekamp@mail.nih.gov"),
1414
person("Ziv", "Yaniv", role="aut",
1515
email = "zivyaniv@nih.gov"))
16-
Author: Richard Beare, Bradley Lowekamp, Ziv Yaniv plus loads of others
16+
Author: Richard Beare, Bradley Lowekamp, Ziv Yaniv, The Insight Software Consortium and the ITK user and developer communities.
1717
Depends: R (>= 4.0)
1818
Imports: methods,
1919
desc

SimpleITK_Foyer/DESCRIPTION

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
Package: SimpleITK.foyer
2+
Version: 1.0.0
3+
Title: Lightweight Installer for SimpleITK
4+
Authors@R: c(person("Richard", "Beare", role = "aut",
5+
email = "Richard.Beare@ieee.org"),
6+
person("Bradley", "Lowekamp", role = "aut",
7+
email = "blowekamp@mail.nih.gov"),
8+
person("Ziv", "Yaniv", role = c("aut", "cre"),
9+
email = "zivyaniv@nih.gov"))
10+
Description: Provides a lightweight installer for the SimpleITK package, which
11+
is an interface to the Insight Toolkit (ITK) for medical image segmentation
12+
and registration. After installing this package, call install_simpleitk().
13+
to download and install the pre-built binary packages for your platform
14+
from the SimpleITKRInstaller GitHub releases. Due to the large size of the compiled
15+
package, the actual functionality is distributed as platform-specific binaries
16+
on GitHub.
17+
License: Apache License (>= 2)
18+
URL: https://github.com/SimpleITK/SimpleITKRInstaller
19+
BugReports: https://github.com/SimpleITK/SimpleITKRInstaller/issues
20+
Encoding: UTF-8
21+
Depends: R (>= 4.0)
22+
Imports: utils
23+
SystemRequirements: Internet connection for downloading binary packages
24+
Maintainer: Ziv Yaniv <zivyaniv@nih.gov>
25+
Config/roxygen2/version: 8.0.0

SimpleITK_Foyer/NAMESPACE

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export(install_simpleitk)
2+
importFrom(utils, install.packages)
3+
importFrom(utils, download.file)

0 commit comments

Comments
 (0)