docker-publish.yml:
- Rewrote as matrix build + manifest merge.
- amd64 on ubuntu-latest, arm64 on ubuntu-24.04-arm (free for public
repos). No QEMU — argon2 and every other native dep compile on
their target CPU, no more SIGILL / exit 132.
- Per-arch GHA cache scopes so builds don't thrash each other.
- Final step merges both digests under one tag (vX.Y.Z + latest),
publishing a real multi-arch manifest. `docker pull` from either
arch gets the right variant automatically.
auto-version.yml, version-bump.yml:
- Checkout now uses `secrets.RELEASE_PAT || secrets.GITHUB_TOKEN`.
With RELEASE_PAT set, the tag push this workflow does DOES
trigger downstream (android-release, docker-publish). Without
it, falls back to GITHUB_TOKEN (no downstream trigger, what we
have today).
All workflows (auto-version, version-bump, android-release,
docker-publish):
- Added FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: 'true' so actions
still on Node 20 runtime (checkout/cache/setup-*) opt in to
Node 24 early. GitHub makes Node 24 default 2026-06-02 and
removes Node 20 2026-09-16.
To finish the chain (one-time user step): create a fine-grained
PAT with "Contents: Read and write" on this repo and add as
RELEASE_PAT secret. After that `feat:` / `fix:` commits auto-tag
AND auto-build with zero manual intervention.
148 lines
5.5 KiB
YAML
148 lines
5.5 KiB
YAML
name: Auto version & release
|
|
|
|
# Fires on every push to main. Parses commit messages since the
|
|
# last semver tag, decides patch/minor/major bump, creates the
|
|
# tag, pushes. The tag push then triggers android-release.yml and
|
|
# docker-publish.yml. Fully hands-off — you never pick a version
|
|
# number; your commit messages do.
|
|
#
|
|
# Commit message grammar (Conventional Commits):
|
|
# feat: → minor bump (new feature, backward-compatible)
|
|
# fix: → patch bump (bug fix)
|
|
# feat!: / BREAKING CHANGE in body → major bump
|
|
# everything else (docs, refactor, chore, style, ci, test) → no bump
|
|
#
|
|
# Skip conditions (no new release created):
|
|
# - No commits match the above patterns
|
|
# - The most recent commit is itself a release commit ("Release v…")
|
|
# - [skip ci] appears in any commit message since the last tag
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
|
|
# Opt in to Node 24 runtime early (deprecation of Node 20 begins 2026-06-02)
|
|
env:
|
|
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: 'true'
|
|
|
|
permissions:
|
|
contents: write
|
|
|
|
jobs:
|
|
version:
|
|
runs-on: ubuntu-latest
|
|
if: "!contains(github.event.head_commit.message, 'Release v') && !contains(github.event.head_commit.message, '[skip ci]')"
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
# Use RELEASE_PAT (a Personal Access Token you add as a repo
|
|
# secret) so the tag push this workflow performs actually
|
|
# triggers the downstream tag-based workflows (android-release,
|
|
# docker-publish). GITHUB_TOKEN pushes are deliberately
|
|
# blocked from triggering other workflows by GitHub.
|
|
# Fine-grained PAT with "Contents: Read and write" on this
|
|
# repo is enough.
|
|
token: ${{ secrets.RELEASE_PAT || secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Find last semver tag
|
|
id: last
|
|
run: |
|
|
LAST=$(git tag --list 'v[0-9]*.[0-9]*.[0-9]*' --sort=-v:refname | head -1)
|
|
if [[ -z "$LAST" ]]; then
|
|
LAST="v0.0.0"
|
|
echo "no previous tag, starting from v0.0.0"
|
|
fi
|
|
echo "tag=$LAST"
|
|
echo "tag=$LAST" >> "$GITHUB_OUTPUT"
|
|
echo "version=${LAST#v}" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Decide bump type from commit messages
|
|
id: decide
|
|
env:
|
|
LAST: ${{ steps.last.outputs.tag }}
|
|
run: |
|
|
# All commits from the last tag → HEAD (exclusive of tag commit)
|
|
if [[ "$LAST" == "v0.0.0" ]]; then
|
|
MSGS=$(git log --format='%s%n%b%n---')
|
|
else
|
|
MSGS=$(git log "${LAST}..HEAD" --format='%s%n%b%n---')
|
|
fi
|
|
|
|
BUMP=none
|
|
if echo "$MSGS" | grep -qE '(^|\n)(BREAKING CHANGE:|[a-z]+(\([^)]+\))?!:)'; then
|
|
BUMP=major
|
|
elif echo "$MSGS" | grep -qE '(^|\n)feat(\([^)]+\))?: '; then
|
|
BUMP=minor
|
|
elif echo "$MSGS" | grep -qE '(^|\n)fix(\([^)]+\))?: '; then
|
|
BUMP=patch
|
|
fi
|
|
|
|
echo "Bump type decided: $BUMP"
|
|
echo "bump=$BUMP" >> "$GITHUB_OUTPUT"
|
|
{
|
|
echo "### Commits since $LAST"
|
|
echo '```'
|
|
if [[ "$LAST" == "v0.0.0" ]]; then
|
|
git log --oneline | head -20
|
|
else
|
|
git log "${LAST}..HEAD" --oneline
|
|
fi
|
|
echo '```'
|
|
echo ""
|
|
echo "**Bump decision**: \`$BUMP\`"
|
|
} >> "$GITHUB_STEP_SUMMARY"
|
|
|
|
- name: Stop if no release-worthy commits
|
|
if: steps.decide.outputs.bump == 'none'
|
|
run: |
|
|
echo "No feat / fix / BREAKING commits since last tag — not cutting a release."
|
|
echo "::notice::No release cut. Commit with 'feat:', 'fix:', or BREAKING CHANGE to trigger one."
|
|
|
|
- name: Compute next version
|
|
id: next
|
|
if: steps.decide.outputs.bump != 'none'
|
|
env:
|
|
CUR: ${{ steps.last.outputs.version }}
|
|
BUMP: ${{ steps.decide.outputs.bump }}
|
|
run: |
|
|
IFS='.' read -r MAJ MIN PAT <<< "$CUR"
|
|
case "$BUMP" in
|
|
major) NEXT="$((MAJ+1)).0.0" ;;
|
|
minor) NEXT="${MAJ}.$((MIN+1)).0" ;;
|
|
patch) NEXT="${MAJ}.${MIN}.$((PAT+1))" ;;
|
|
esac
|
|
echo "next=$NEXT" >> "$GITHUB_OUTPUT"
|
|
echo "### Next version: v$NEXT" >> "$GITHUB_STEP_SUMMARY"
|
|
|
|
- name: Configure git
|
|
if: steps.decide.outputs.bump != 'none'
|
|
run: |
|
|
git config user.name "github-actions[bot]"
|
|
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
|
|
- name: Bump version strings + tag + push
|
|
if: steps.decide.outputs.bump != 'none'
|
|
env:
|
|
V: ${{ steps.next.outputs.next }}
|
|
run: |
|
|
IFS='.' read -r MAJ MIN PAT <<< "$V"
|
|
ANDROID_CODE=$(( MAJ * 100000 + MIN * 1000 + PAT ))
|
|
|
|
sed -i -E "0,/(\"version\"[[:space:]]*:[[:space:]]*\")[^\"]+(\")/ s//\1${V}\2/" package.json
|
|
sed -i -E "0,/(\"version\"[[:space:]]*:[[:space:]]*\")[^\"]+(\")/ s//\1${V}\2/" mobile/package.json
|
|
sed -i -E \
|
|
-e "s/versionCode +[0-9]+/versionCode ${ANDROID_CODE}/" \
|
|
-e "s/versionName +\"[^\"]+\"/versionName \"${V}\"/" \
|
|
mobile/android/app/build.gradle
|
|
|
|
git add package.json mobile/package.json mobile/android/app/build.gradle
|
|
git commit -m "Release v${V}"
|
|
git tag -a "v${V}" -m "Release v${V}"
|
|
|
|
git push origin HEAD
|
|
git push origin "v${V}"
|
|
|
|
echo "### Released v$V" >> "$GITHUB_STEP_SUMMARY"
|
|
echo "android-release + docker-publish workflows will now run." >> "$GITHUB_STEP_SUMMARY"
|