Skip to content
293 changes: 210 additions & 83 deletions .github/workflows/releases.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,91 +7,115 @@ 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
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

- 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
- name: Select branch
id: vars
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
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

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 --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)"

- name: Install deps
run: brew install numpy cmake qt pkg-config libpng ninja
if [ -n "$RECENT" ]; then
{
echo "recent_commits<<EOF"
echo "$RECENT"
echo "EOF"
} >> "$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-dev tag
git fetch --tags origin

windows-release:
runs-on: windows-latest
defaults:
run:
shell: msys2 {0}
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-dev 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<<EOF"
echo "$LOG"
echo "EOF"
} >> "$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 }}
env:
MRTRIX_IGNORE_VERSION_MISMATCH: ${{ github.event_name == 'schedule' && '1' || '' }}
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: |
Expand All @@ -113,25 +137,128 @@ 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).Trim()
$date = (Get-Date -Format 'yyyyMMdd')
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: 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 pkg-config libpng ninja
- name: Run Linux build
if: matrix.platform == 'linux'
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
./packaging/package-linux-tarball.sh . "${{ steps.out.outputs.output_name }}"
mv mrtrix.tar.gz ${{ steps.out.outputs.output_name }}.${{ matrix.artifact_ext }}

- name: Run build
- name: Run macOS build
if: matrix.platform == 'macos'
run: |
cd ./packaging/macos
./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'
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 +%Y-%m-%d)."
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 >/dev/null 2>&1; then
gh release edit nightly-dev --notes-file "$NOTES_FILE"
else
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-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-dev "$asset" --yes
done
fi

gh release upload nightly-dev 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-dev "$NIGHTLY_COMMIT"
git push origin refs/tags/nightly-dev --force
Loading