Add nightly prereleases at midnight Eastern, skipping unchanged commits
This commit is contained in:
1 parent
4ac803ab52
commit
31dadcee63
3 files changed
+84
-1
No files matched your search
@@ -3,6 +3,7 @@
|
|||||||
# Push to `release` to build packages and create/update a DRAFT GitHub Release. The version
|
# Push to `release` to build packages and create/update a DRAFT GitHub Release. The version
|
||||||
# comes from [workspace.package] in Cargo.toml. An agent verifies the artifacts and publishes
|
# comes from [workspace.package] in Cargo.toml. An agent verifies the artifacts and publishes
|
||||||
# the draft separately; see docs/releasing.md. Tags and pushes to main do not trigger releases.
|
# the draft separately; see docs/releasing.md. Tags and pushes to main do not trigger releases.
|
||||||
|
# At midnight Eastern, changed main commits build and publish a nightly pre-release.
|
||||||
# A version with a suffix (0.2.0-rc.1) is a pre-release. Nothing is signed yet.
|
# A version with a suffix (0.2.0-rc.1) is a pre-release. Nothing is signed yet.
|
||||||
#
|
#
|
||||||
# Linux x86_64, aarch64 AppImage (+ .zsync), .deb, .rpm, .flatpak, .tar.gz packaging/linux
|
# Linux x86_64, aarch64 AppImage (+ .zsync), .deb, .rpm, .flatpak, .tar.gz packaging/linux
|
||||||
@@ -15,6 +16,9 @@
|
|||||||
name: Release
|
name: Release
|
||||||
|
|
||||||
on:
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 0 * * *'
|
||||||
|
timezone: America/New_York
|
||||||
push:
|
push:
|
||||||
branches: [release]
|
branches: [release]
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
@@ -39,17 +43,30 @@ jobs:
|
|||||||
version:
|
version:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
outputs:
|
outputs:
|
||||||
|
build: ${{ steps.changed.outputs.build }}
|
||||||
version: ${{ steps.v.outputs.version }}
|
version: ${{ steps.v.outputs.version }}
|
||||||
date: ${{ steps.v.outputs.date }}
|
date: ${{ steps.v.outputs.date }}
|
||||||
prerelease: ${{ steps.v.outputs.prerelease }}
|
prerelease: ${{ steps.v.outputs.prerelease }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
- id: changed
|
||||||
|
name: Skip unchanged nightly builds
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ github.token }}
|
||||||
|
run: bash packaging/nightly.sh
|
||||||
- id: v
|
- id: v
|
||||||
|
if: steps.changed.outputs.build == 'true'
|
||||||
name: Resolve version
|
name: Resolve version
|
||||||
env:
|
env:
|
||||||
REQUEST_DRAFT: ${{ inputs.draft || false }}
|
REQUEST_DRAFT: ${{ inputs.draft || false }}
|
||||||
run: |
|
run: |
|
||||||
. packaging/env.sh
|
. packaging/env.sh
|
||||||
|
if [ "$GITHUB_EVENT_NAME" = schedule ]; then
|
||||||
|
# Unique SemVer without committing daily version bumps to main.
|
||||||
|
VERSION="${VERSION%%-*}-nightly.$(TZ=America/New_York date +%Y%m%d).$GITHUB_RUN_NUMBER.$GITHUB_RUN_ATTEMPT"
|
||||||
|
fi
|
||||||
if ! printf '%s' "$VERSION" | grep -Eq '^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-((0|[1-9][0-9]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*)(\.(0|[1-9][0-9]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*))*))?$'; then
|
if ! printf '%s' "$VERSION" | grep -Eq '^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-((0|[1-9][0-9]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*)(\.(0|[1-9][0-9]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*))*))?$'; then
|
||||||
echo "::error::Cargo.toml must contain a version like 1.2.3 or 1.2.3-rc.1"
|
echo "::error::Cargo.toml must contain a version like 1.2.3 or 1.2.3-rc.1"
|
||||||
exit 1
|
exit 1
|
||||||
@@ -65,6 +82,8 @@ jobs:
|
|||||||
# The app icon in every size, drawn by solvecraft-cli (no image files are committed), for the
|
# The app icon in every size, drawn by solvecraft-cli (no image files are committed), for the
|
||||||
# Windows jobs: the ARM64 build is cross-compiled and can't run there to draw its own.
|
# Windows jobs: the ARM64 build is cross-compiled and can't run there to draw its own.
|
||||||
icons:
|
icons:
|
||||||
|
needs: version
|
||||||
|
if: needs.version.outputs.build == 'true'
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
@@ -85,6 +104,7 @@ jobs:
|
|||||||
linux:
|
linux:
|
||||||
name: Linux ${{ matrix.arch }}
|
name: Linux ${{ matrix.arch }}
|
||||||
needs: version
|
needs: version
|
||||||
|
if: needs.version.outputs.build == 'true'
|
||||||
# The oldest GitHub-hosted image, so the binaries only need glibc >= 2.35.
|
# The oldest GitHub-hosted image, so the binaries only need glibc >= 2.35.
|
||||||
runs-on: ${{ matrix.runner }}
|
runs-on: ${{ matrix.runner }}
|
||||||
strategy:
|
strategy:
|
||||||
@@ -135,6 +155,7 @@ jobs:
|
|||||||
flatpak:
|
flatpak:
|
||||||
name: Flatpak ${{ matrix.arch }}
|
name: Flatpak ${{ matrix.arch }}
|
||||||
needs: [version, linux]
|
needs: [version, linux]
|
||||||
|
if: needs.version.outputs.build == 'true'
|
||||||
# Repackages the Linux job's tarball (the same binaries as the AppImage/deb/rpm); no Rust
|
# Repackages the Linux job's tarball (the same binaries as the AppImage/deb/rpm); no Rust
|
||||||
# build here. 24.04 for a newer flatpak-builder than 22.04 ships.
|
# build here. 24.04 for a newer flatpak-builder than 22.04 ships.
|
||||||
runs-on: ${{ matrix.runner }}
|
runs-on: ${{ matrix.runner }}
|
||||||
@@ -172,6 +193,7 @@ jobs:
|
|||||||
freebsd:
|
freebsd:
|
||||||
name: FreeBSD x86_64
|
name: FreeBSD x86_64
|
||||||
needs: version
|
needs: version
|
||||||
|
if: needs.version.outputs.build == 'true'
|
||||||
# GitHub has no FreeBSD runners: build in a FreeBSD 14.3 VM.
|
# GitHub has no FreeBSD runners: build in a FreeBSD 14.3 VM.
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 180
|
timeout-minutes: 180
|
||||||
@@ -212,6 +234,7 @@ jobs:
|
|||||||
macos:
|
macos:
|
||||||
name: macOS universal
|
name: macOS universal
|
||||||
needs: version
|
needs: version
|
||||||
|
if: needs.version.outputs.build == 'true'
|
||||||
runs-on: macos-14
|
runs-on: macos-14
|
||||||
env:
|
env:
|
||||||
SOLVECRAFT_VERSION: ${{ needs.version.outputs.version }}
|
SOLVECRAFT_VERSION: ${{ needs.version.outputs.version }}
|
||||||
@@ -235,6 +258,7 @@ jobs:
|
|||||||
windows:
|
windows:
|
||||||
name: Windows ${{ matrix.arch }}
|
name: Windows ${{ matrix.arch }}
|
||||||
needs: [version, icons]
|
needs: [version, icons]
|
||||||
|
if: needs.version.outputs.build == 'true'
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
@@ -277,6 +301,7 @@ jobs:
|
|||||||
web:
|
web:
|
||||||
name: Web (wasm)
|
name: Web (wasm)
|
||||||
needs: version
|
needs: version
|
||||||
|
if: needs.version.outputs.build == 'true'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
env:
|
env:
|
||||||
SOLVECRAFT_VERSION: ${{ needs.version.outputs.version }}
|
SOLVECRAFT_VERSION: ${{ needs.version.outputs.version }}
|
||||||
@@ -302,8 +327,9 @@ jobs:
|
|||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
release:
|
release:
|
||||||
name: Draft GitHub Release or dry-run artifacts
|
name: GitHub Release or dry-run artifacts
|
||||||
needs: [version, linux, flatpak, freebsd, macos, windows, web]
|
needs: [version, linux, flatpak, freebsd, macos, windows, web]
|
||||||
|
if: needs.version.outputs.build == 'true'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
@@ -323,6 +349,18 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
(cd artifacts && sha256sum -- * | tee SHA256SUMS.txt)
|
(cd artifacts && sha256sum -- * | tee SHA256SUMS.txt)
|
||||||
sed "s/{version}/$VERSION/g" .github/release-notes.md >notes.md
|
sed "s/{version}/$VERSION/g" .github/release-notes.md >notes.md
|
||||||
|
- name: Publish nightly pre-release
|
||||||
|
if: github.event_name == 'schedule'
|
||||||
|
working-directory: artifacts
|
||||||
|
run: |
|
||||||
|
tag="v$VERSION"
|
||||||
|
sha256sum --check SHA256SUMS.txt
|
||||||
|
# Stage all packages before publishing. Published tags are never replaced.
|
||||||
|
gh release create "$tag" --draft --prerelease --latest=false \
|
||||||
|
--title "SolveCraft v$VERSION (nightly)" --target "$GITHUB_SHA" \
|
||||||
|
--notes-file ../notes.md --generate-notes -- *
|
||||||
|
gh release edit "$tag" --draft=false --prerelease --latest=false
|
||||||
|
echo "### Published nightly: $tag (\`${GITHUB_SHA::9}\`)" >>"$GITHUB_STEP_SUMMARY"
|
||||||
- name: Create or update the draft release
|
- name: Create or update the draft release
|
||||||
if: github.ref == 'refs/heads/release' && (github.event_name == 'push' || inputs.draft)
|
if: github.ref == 'refs/heads/release' && (github.event_name == 'push' || inputs.draft)
|
||||||
working-directory: artifacts
|
working-directory: artifacts
|
||||||
|
|||||||
@@ -6,6 +6,27 @@ GitHub Release. Publishing that verified draft is a separate operation. Pushing
|
|||||||
pushing a tag does not start the release workflow. There is no automatic commit-message-based
|
pushing a tag does not start the release workflow. There is no automatic commit-message-based
|
||||||
version bump and no patch release for every merge.
|
version bump and no patch release for every merge.
|
||||||
|
|
||||||
|
## Nightly prereleases
|
||||||
|
|
||||||
|
`release.yml` also runs at midnight in `America/New_York` (Eastern time, following daylight
|
||||||
|
saving time). GitHub may start scheduled runs later when its runners are busy.
|
||||||
|
Before building, it compares the exact scheduled `main` commit with the tag of the most
|
||||||
|
recently published release, including prereleases. If the commits match, all packaging and
|
||||||
|
publication jobs are skipped: no new version, tag, or release is created. Drafts do not count
|
||||||
|
as published releases, so a failed build or publication can be retried the following night.
|
||||||
|
|
||||||
|
Changed commits use the existing package build and validation jobs. Only after all jobs
|
||||||
|
succeed, the workflow stages the assets in a draft and publishes a prerelease named
|
||||||
|
`v<workspace-version>-nightly.<YYYYMMDD>.<run-number>.<run-attempt>` with checksums and generated
|
||||||
|
notes. Any existing workspace prerelease suffix is replaced by the nightly suffix. Dates
|
||||||
|
use Eastern time; package versions are overridden without changing Cargo.toml or Cargo.lock,
|
||||||
|
so the binaries' embedded Cargo version remains the workspace version. Nightlies do not
|
||||||
|
replace the latest stable release or advance the `release` branch. The normal deliberate
|
||||||
|
release process below continues to create drafts for separate verification and publication.
|
||||||
|
|
||||||
|
Nightly publication uses `GITHUB_TOKEN`, so it does not trigger the downstream Flatpak Pages
|
||||||
|
deployment. The stable Flatpak repository is not automatically updated with nightly builds.
|
||||||
|
|
||||||
## Choose and prepare the version
|
## Choose and prepare the version
|
||||||
|
|
||||||
1. Fetch `origin` and its tags. Inspect the previous published release and the changes since
|
1. Fetch `origin` and its tags. Inspect the previous published release and the changes since
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Decide before building or assigning a nightly version. Checkout must include all tags.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
if [ "$GITHUB_EVENT_NAME" != schedule ]; then
|
||||||
|
echo 'build=true' >>"$GITHUB_OUTPUT"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# /releases/latest excludes prereleases. Include every published release instead,
|
||||||
|
# including nightlies, and sort by publication time across all API pages.
|
||||||
|
latest_tag="$(gh api --paginate --slurp "repos/$GITHUB_REPOSITORY/releases?per_page=100" \
|
||||||
|
--jq '[.[][] | select(.draft == false and .published_at != null)] | sort_by(.published_at) | last | .tag_name // empty')"
|
||||||
|
if [ -n "$latest_tag" ]; then
|
||||||
|
# Resolve the tag itself, not target_commitish (which can be a moving branch).
|
||||||
|
released_sha="$(git rev-parse --verify "refs/tags/$latest_tag^{commit}")"
|
||||||
|
if [ "$released_sha" = "$GITHUB_SHA" ]; then
|
||||||
|
echo 'build=false' >>"$GITHUB_OUTPUT"
|
||||||
|
echo "### Nightly skipped: no new commits since $latest_tag" >>"$GITHUB_STEP_SUMMARY"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo 'build=true' >>"$GITHUB_OUTPUT"
|
||||||
Reference in new issue
Block a user