diff --git a/.github/workflows/releases.yml b/.github/workflows/releases.yml index a3dccf453b..d4095b1c78 100644 --- a/.github/workflows/releases.yml +++ b/.github/workflows/releases.yml @@ -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<> "$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<> "$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: | @@ -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 \ No newline at end of file