From 62107547f0a6203fe5d7763b41875ca71c10ccac Mon Sep 17 00:00:00 2001 From: Daljit Singh Date: Tue, 16 Dec 2025 13:38:36 +0000 Subject: [PATCH 1/9] Refactor GitHub Actions workflow for nightly builds - Use matrices for building on separate platforms - Add support for (dev branch) nightly builds on which update the release (with 'nightly' tag). If no changes have been made to dev, then no changes are made. --- .github/workflows/releases.yml | 287 +++++++++++++++++++++++---------- 1 file changed, 204 insertions(+), 83 deletions(-) diff --git a/.github/workflows/releases.yml b/.github/workflows/releases.yml index a3dccf453b..747709ccda 100644 --- a/.github/workflows/releases.yml +++ b/.github/workflows/releases.yml @@ -7,91 +7,113 @@ on: description: 'Branch to release from' required: true default: 'dev' + schedule: + # Every day at 00:00 + - cron: '0 0 * * *' + +permissions: + contents: write jobs: - linux-release: - runs-on: ubuntu-20.04 + prepare: + name: Prepare release + runs-on: ubuntu-latest + outputs: + branch: ${{ steps.vars.outputs.branch }} + commit_sha: ${{ steps.sha.outputs.commit_sha }} + has_changes: ${{ steps.changes.outputs.has_changes }} + changelog: ${{ steps.changes.outputs.changelog }} + recent_commits: ${{ steps.changes.outputs.recent_commits }} steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - ref: ${{ github.event.inputs.branch }} - - - name: Set env vars - id: envs + - name: Select branch + id: vars run: | - commit_sha=$(git rev-parse HEAD) - date=$(date +%Y_%m_%d) - echo "commit_sha=$commit_sha" >> $GITHUB_OUTPUT - echo "date=$date" >> $GITHUB_OUTPUT - echo "output_name=mrtrix3-linux-$commit_sha-$date" >> $GITHUB_OUTPUT + if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then + echo "branch=${{ github.event.inputs.branch }}" >> "$GITHUB_OUTPUT" + else + # Nightly builds always from dev + echo "branch=dev" >> "$GITHUB_OUTPUT" + fi - - name: Install Eigen3 - run: | - git clone https://gitlab.com/libeigen/eigen.git && cd eigen && git checkout 3.4.0 - cmake -B build && cmake --build build - sudo cmake --install build - - - name: Install Qt 6 - uses: jurplel/install-qt-action@v3 - with: - version: '6.7.0' - set-env: true - - - name: Run build - run: | - ./packaging/package-linux-tarball.sh . - mv mrtrix.tar.gz ${{ steps.envs.outputs.output_name }}.tar.gz - - - name: Upload release artifact - uses: actions/upload-artifact@v4 - with: - name: ${{ steps.envs.outputs.output_name }} - path: ${{ steps.envs.outputs.output_name }}.tar.gz - - macos-release: - runs-on: macos-latest - steps: - - uses: actions/checkout@v3 + - name: Checkout selected branch + uses: actions/checkout@v3 with: fetch-depth: 0 - ref: ${{ github.event.inputs.branch }} + ref: ${{ steps.vars.outputs.branch }} + + - name: Capture commit SHA + id: sha + run: echo "commit_sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT" - - name: Set env vars - id: envs + - name: Determine if there are new commits since last nightly + id: changes run: | - commit_sha=$(git rev-parse HEAD) - date=$(date +%Y_%m_%d) - echo "commit_sha=$commit_sha" >> $GITHUB_OUTPUT - echo "date=$date" >> $GITHUB_OUTPUT - echo "output_name=mrtrix3-macos-$commit_sha-$date" >> $GITHUB_OUTPUT + RECENT="$(git log -n 15 --oneline || true)" - - name: Install deps - run: brew install numpy cmake qt pkg-config libpng ninja + if [ -n "$RECENT" ]; then + { + echo "recent_commits<> "$GITHUB_OUTPUT" + else + echo "recent_commits=" >> "$GITHUB_OUTPUT" + fi - - name: Run build - run: | - cd ./packaging/macos - ./build ${{ github.event.inputs.branch }} - mv ./mrtrix3-macos-${{ github.event.inputs.branch }}.tar.xz ../../${{ steps.envs.outputs.output_name }}.tar.xz + # Manual runs always build + if [ "${{ github.event_name }}" != "schedule" ]; then + echo "has_changes=true" >> "$GITHUB_OUTPUT" + echo "changelog=" >> "$GITHUB_OUTPUT" + exit 0 + fi - - name: Upload release artifact - uses: actions/upload-artifact@v4 - with: - name: ${{ steps.envs.outputs.output_name }} - path: ${{ steps.envs.outputs.output_name }}.tar.xz + # Nightly run: compare HEAD of dev vs nightly tag + git fetch --tags origin - windows-release: - runs-on: windows-latest - defaults: - run: - shell: msys2 {0} + if git rev-parse refs/tags/nightly >/dev/null 2>&1; then + LOG="$(git log --oneline refs/tags/nightly..HEAD || true)" + else + # If nightly tag doesn't exist yet, treat all recent commits as "new" + LOG="$(git log --oneline HEAD~50..HEAD || true)" + fi - env: - MINGW_PACKAGE_PREFIX: mingw-w64-ucrt-x86_64 + if [ -z "$LOG" ]; then + echo "No new commits since last nightly." + echo "has_changes=false" >> "$GITHUB_OUTPUT" + echo "changelog=" >> "$GITHUB_OUTPUT" + else + echo "Found new commits since last nightly." + echo "has_changes=true" >> "$GITHUB_OUTPUT" + { + echo "changelog<> "$GITHUB_OUTPUT" + fi + build-release: + needs: prepare + if: needs.prepare.outputs.has_changes == 'true' + strategy: + fail-fast: false + matrix: + include: + - platform: linux + runs_on: ubuntu-22.04 + artifact_ext: tar.gz + - platform: macos + runs_on: macos-latest + artifact_ext: tar.xz + - platform: windows + runs_on: windows-latest + artifact_ext: tar.zst + runs-on: ${{ matrix.runs_on }} steps: - - uses: msys2/setup-msys2@v2 + - name: Set up MSYS2 for Windows + if: matrix.platform == 'windows' + uses: msys2/setup-msys2@v2 + env: + MINGW_PACKAGE_PREFIX: mingw-w64-ucrt-x86_64 with: msystem: UCRT64 install: | @@ -113,25 +135,124 @@ jobs: - uses: actions/checkout@v3 with: fetch-depth: 0 - ref: ${{ github.event.inputs.branch }} - - - name: Set env vars - id: envs + ref: ${{ needs.prepare.outputs.branch }} + + - name: Set output name + id: out + shell: pwsh run: | - commit_sha=$(git rev-parse HEAD) - date=$(date +%Y_%m_%d) - echo "commit_sha=$commit_sha" >> $GITHUB_OUTPUT - echo "date=$date" >> $GITHUB_OUTPUT - echo "output_name=mrtrix3-windows-$commit_sha-$date" >> $GITHUB_OUTPUT + $commit_sha = (git rev-parse HEAD).Trim() + $date = (Get-Date -Format 'dd-MM-yyyy') + if ($env:GITHUB_EVENT_NAME -eq 'schedule') { + $output_name = "mrtrix3-${{ matrix.platform }}-$date" + } else { + $output_name = "mrtrix3-${{ matrix.platform }}-$commit_sha-$date" + } + "output_name=$output_name" >> $env:GITHUB_OUTPUT + + - name: Install Qt 6 on Linux + if: matrix.platform == 'linux' + uses: jurplel/install-qt-action@v3 + with: + version: '6.7.0' + set-env: true + + - name: Install dependencies on macOS + if: matrix.platform == 'macos' + run: brew install numpy cmake qt pkg-config libpng ninja - - name: Run build + - name: Run Linux build + if: matrix.platform == 'linux' + run: | + ./packaging/package-linux-tarball.sh . + mv mrtrix.tar.gz ${{ steps.out.outputs.output_name }}.${{ matrix.artifact_ext }} + + - name: Run macOS build + if: matrix.platform == 'macos' + run: | + cd ./packaging/macos + ./build ${{ needs.prepare.outputs.branch }} + mv ./mrtrix3-macos-${{ needs.prepare.outputs.branch }}.${{ matrix.artifact_ext }} ../../${{ steps.out.outputs.output_name }}.${{ matrix.artifact_ext }} + + - name: Run Windows build + if: matrix.platform == 'windows' + shell: msys2 {0} run: | cd packaging/mingw - ./run.sh ${{ steps.envs.outputs.commit_sha }} mrtrix3 - mv mingw*.tar.zst ../../${{ steps.envs.outputs.output_name }}.tar.zst + ./run.sh ${{ needs.prepare.outputs.commit_sha }} ${{ github.repository_owner }} + mv mingw*.${{ matrix.artifact_ext }} ../../${{ steps.out.outputs.output_name }}.${{ matrix.artifact_ext }} - name: Upload release artifact uses: actions/upload-artifact@v4 with: - name: ${{ steps.envs.outputs.output_name }} - path: ${{ steps.envs.outputs.output_name }}.tar.zst + name: ${{ steps.out.outputs.output_name }} + path: ${{ steps.out.outputs.output_name }}.${{ matrix.artifact_ext }} + + nightly-release: + name: Create/update nightly release + needs: + - prepare + - build-release + if: github.event_name == 'schedule' && needs.prepare.outputs.has_changes == 'true' + runs-on: ubuntu-latest + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} # GitHub CLI auth + RECENT_COMMITS: ${{ needs.prepare.outputs.recent_commits }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Download all artifacts + uses: actions/download-artifact@v4 + with: + path: dist + + - name: Show downloaded artifacts + run: ls -R dist + + - name: Create or update nightly release + run: | + NOTES_FILE=notes.txt + { + echo "Nightly build for $(date -u +%d-%m-%Y)." + echo + echo "Latest changes:" + echo + if [ -n "$RECENT_COMMITS" ]; then + echo "$RECENT_COMMITS" + else + echo "No commits to display." + fi + } > "$NOTES_FILE" + + # Ensure the nightly release exists and update its notes + if gh release view nightly >/dev/null 2>&1; then + gh release edit nightly --notes-file "$NOTES_FILE" + else + gh release create nightly --title "Nightly build" --notes-file "$NOTES_FILE" + fi + + # Remove existing assets so we only keep artifacts from the latest run + EXISTING_ASSETS="$(gh release view nightly --json assets --jq '.assets[].name' || true)" + if [ -n "$EXISTING_ASSETS" ]; then + printf '%s\n' "$EXISTING_ASSETS" | while IFS= read -r asset; do + [ -z "$asset" ] && continue + gh release delete-asset nightly "$asset" --yes + done + fi + + gh release upload nightly dist/*/* --clobber + + - name: Move nightly tag forward + env: + NIGHTLY_COMMIT: ${{ needs.prepare.outputs.commit_sha }} + run: | + if [ -z "$NIGHTLY_COMMIT" ]; then + echo "Missing commit SHA for nightly tag update." >&2 + exit 1 + fi + git fetch origin + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git tag -f nightly "$NIGHTLY_COMMIT" + git push origin refs/tags/nightly --force From 32307b610023b54144f7381ae565d2c16d9883b7 Mon Sep 17 00:00:00 2001 From: Daljit Singh Date: Wed, 17 Dec 2025 10:21:05 +0000 Subject: [PATCH 2/9] Show latest merged PRs rather than commits in release notes Co-authored-by: Robert Smith --- .github/workflows/releases.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/releases.yml b/.github/workflows/releases.yml index 747709ccda..d4c81c4db9 100644 --- a/.github/workflows/releases.yml +++ b/.github/workflows/releases.yml @@ -48,7 +48,7 @@ jobs: - name: Determine if there are new commits since last nightly id: changes run: | - RECENT="$(git log -n 15 --oneline || true)" + RECENT="$(git log --oneline --merges | grep -E 'Merge pull request #[0-9]+ from [^ ]+/' | head -n 15 || true)" if [ -n "$RECENT" ]; then { From 217e6e84f4edabd4f005943081fc531a9a60ec05 Mon Sep 17 00:00:00 2001 From: Daljit Singh Date: Wed, 17 Dec 2025 10:25:00 +0000 Subject: [PATCH 3/9] Switch date format for artefacts: dd-MM-yyyy -> yyyyMMdd Co-authored-by: Robert Smith --- .github/workflows/releases.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/releases.yml b/.github/workflows/releases.yml index d4c81c4db9..6e512a8339 100644 --- a/.github/workflows/releases.yml +++ b/.github/workflows/releases.yml @@ -142,7 +142,7 @@ jobs: shell: pwsh run: | $commit_sha = (git rev-parse HEAD).Trim() - $date = (Get-Date -Format 'dd-MM-yyyy') + $date = (Get-Date -Format 'yyyyMMdd') if ($env:GITHUB_EVENT_NAME -eq 'schedule') { $output_name = "mrtrix3-${{ matrix.platform }}-$date" } else { @@ -214,7 +214,7 @@ jobs: run: | NOTES_FILE=notes.txt { - echo "Nightly build for $(date -u +%d-%m-%Y)." + echo "Nightly build for $(date -u +%Y-%m-%d)." echo echo "Latest changes:" echo From 7beb217e08cb3c90ad97b870bf91420960fd4069 Mon Sep 17 00:00:00 2001 From: Daljit Singh Date: Mon, 30 Mar 2026 16:30:33 +0100 Subject: [PATCH 4/9] Include PR numbers and titles in latest changes --- .github/workflows/releases.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/releases.yml b/.github/workflows/releases.yml index 6e512a8339..625c19e455 100644 --- a/.github/workflows/releases.yml +++ b/.github/workflows/releases.yml @@ -48,7 +48,7 @@ jobs: - name: Determine if there are new commits since last nightly id: changes run: | - RECENT="$(git log --oneline --merges | grep -E 'Merge pull request #[0-9]+ from [^ ]+/' | head -n 15 || true)" + RECENT="$(git log --merges --format='%h|%s|%b' | sed -n -E 's/^([0-9a-f]+)\|Merge pull request #([0-9]+) [^|]+\|(.*)$/\1 MRtrix3#\2: \3/p' | head -n 15 || true)" if [ -n "$RECENT" ]; then { From e50c200f3c718c8326f53b73a57840a3cf763611 Mon Sep 17 00:00:00 2001 From: Daljit Singh Date: Mon, 30 Mar 2026 16:30:59 +0100 Subject: [PATCH 5/9] Set MRTRIX_IGNORE_VERSION_MISMATCH=1 for nightly --- .github/workflows/releases.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/releases.yml b/.github/workflows/releases.yml index 625c19e455..fc732f3044 100644 --- a/.github/workflows/releases.yml +++ b/.github/workflows/releases.yml @@ -108,6 +108,8 @@ jobs: runs_on: windows-latest artifact_ext: tar.zst runs-on: ${{ matrix.runs_on }} + env: + MRTRIX_IGNORE_VERSION_MISMATCH: ${{ github.event_name == 'schedule' && '1' || '' }} steps: - name: Set up MSYS2 for Windows if: matrix.platform == 'windows' From 7d28ecf88d2a580036f250cec91f96c9c0a11977 Mon Sep 17 00:00:00 2001 From: Daljit Singh Date: Mon, 30 Mar 2026 16:36:06 +0100 Subject: [PATCH 6/9] Rename nightly --> nightly-dev --- .github/workflows/releases.yml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/releases.yml b/.github/workflows/releases.yml index fc732f3044..b1ecdfa5b9 100644 --- a/.github/workflows/releases.yml +++ b/.github/workflows/releases.yml @@ -67,13 +67,13 @@ jobs: exit 0 fi - # Nightly run: compare HEAD of dev vs nightly tag + # Nightly run: compare HEAD of dev vs nightly-dev tag git fetch --tags origin - if git rev-parse refs/tags/nightly >/dev/null 2>&1; then - LOG="$(git log --oneline refs/tags/nightly..HEAD || true)" + if git rev-parse refs/tags/nightly-dev >/dev/null 2>&1; then + LOG="$(git log --oneline refs/tags/nightly-dev..HEAD || true)" else - # If nightly tag doesn't exist yet, treat all recent commits as "new" + # If nightly-dev tag doesn't exist yet, treat all recent commits as "new" LOG="$(git log --oneline HEAD~50..HEAD || true)" fi @@ -228,22 +228,22 @@ jobs: } > "$NOTES_FILE" # Ensure the nightly release exists and update its notes - if gh release view nightly >/dev/null 2>&1; then - gh release edit nightly --notes-file "$NOTES_FILE" + if gh release view nightly-dev >/dev/null 2>&1; then + gh release edit nightly-dev --notes-file "$NOTES_FILE" else - gh release create nightly --title "Nightly build" --notes-file "$NOTES_FILE" + gh release create nightly-dev --title "Nightly dev build" --notes-file "$NOTES_FILE" fi # Remove existing assets so we only keep artifacts from the latest run - EXISTING_ASSETS="$(gh release view nightly --json assets --jq '.assets[].name' || true)" + EXISTING_ASSETS="$(gh release view nightly-dev --json assets --jq '.assets[].name' || true)" if [ -n "$EXISTING_ASSETS" ]; then printf '%s\n' "$EXISTING_ASSETS" | while IFS= read -r asset; do [ -z "$asset" ] && continue - gh release delete-asset nightly "$asset" --yes + gh release delete-asset nightly-dev "$asset" --yes done fi - gh release upload nightly dist/*/* --clobber + gh release upload nightly-dev dist/*/* --clobber - name: Move nightly tag forward env: @@ -256,5 +256,5 @@ jobs: git fetch origin git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com" - git tag -f nightly "$NIGHTLY_COMMIT" - git push origin refs/tags/nightly --force + git tag -f nightly-dev "$NIGHTLY_COMMIT" + git push origin refs/tags/nightly-dev --force \ No newline at end of file From e1ae58674c8df01a774e299cb33ed63bfbc04da5 Mon Sep 17 00:00:00 2001 From: Daljit Singh Date: Mon, 30 Mar 2026 16:36:32 +0100 Subject: [PATCH 7/9] Remove nightly-dev tag when building --- .github/workflows/releases.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/releases.yml b/.github/workflows/releases.yml index b1ecdfa5b9..3e65e470ac 100644 --- a/.github/workflows/releases.yml +++ b/.github/workflows/releases.yml @@ -159,6 +159,11 @@ jobs: version: '6.7.0' set-env: true + - name: Remove non-release tags for Linux build + if: matrix.platform == 'linux' + run: | + git tag -l 'nightly-dev' | xargs -r git tag -d + - name: Install dependencies on macOS if: matrix.platform == 'macos' run: brew install numpy cmake qt pkg-config libpng ninja From 304aa8cd67f56ed5eecfc609e497b57c0e939333 Mon Sep 17 00:00:00 2001 From: Daljit Singh Date: Mon, 30 Mar 2026 16:33:11 +0100 Subject: [PATCH 8/9] Update macOS packages list --- .github/workflows/releases.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/releases.yml b/.github/workflows/releases.yml index 3e65e470ac..239943c52c 100644 --- a/.github/workflows/releases.yml +++ b/.github/workflows/releases.yml @@ -166,8 +166,7 @@ jobs: - name: Install dependencies on macOS if: matrix.platform == 'macos' - run: brew install numpy cmake qt pkg-config libpng ninja - + run: brew install numpy cmake pkg-config libpng ninja - name: Run Linux build if: matrix.platform == 'linux' run: | From f06bb662726ec930ba04ab4d9c4b58e627f74146 Mon Sep 17 00:00:00 2001 From: Daljit Singh Date: Mon, 30 Mar 2026 16:33:45 +0100 Subject: [PATCH 9/9] Update build scripts to pass output name as an argument for Linux and macOS --- .github/workflows/releases.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/releases.yml b/.github/workflows/releases.yml index 239943c52c..d4095b1c78 100644 --- a/.github/workflows/releases.yml +++ b/.github/workflows/releases.yml @@ -170,15 +170,15 @@ jobs: - name: Run Linux build if: matrix.platform == 'linux' run: | - ./packaging/package-linux-tarball.sh . + ./packaging/package-linux-tarball.sh . "${{ steps.out.outputs.output_name }}" mv mrtrix.tar.gz ${{ steps.out.outputs.output_name }}.${{ matrix.artifact_ext }} - name: Run macOS build if: matrix.platform == 'macos' run: | cd ./packaging/macos - ./build ${{ needs.prepare.outputs.branch }} - mv ./mrtrix3-macos-${{ needs.prepare.outputs.branch }}.${{ matrix.artifact_ext }} ../../${{ steps.out.outputs.output_name }}.${{ matrix.artifact_ext }} + ./build "${{ needs.prepare.outputs.branch }}" "${{ steps.out.outputs.output_name }}" + mv "./${{ steps.out.outputs.output_name }}.${{ matrix.artifact_ext }}" "../../${{ steps.out.outputs.output_name }}.${{ matrix.artifact_ext }}" - name: Run Windows build if: matrix.platform == 'windows'