From 6ddff302832b87d26eae96addaf5875628e2c847 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 30 Sep 2026 17:26:24 +0000 Subject: [PATCH] ci: one release run at a time, no release for ci/docs/test/style/chore commits - concurrency group release- (cancel-in-progress: false): parallel runs raced on the atomic version-bump push; the Android one once left a tag without a release. - New "Release needed?" job reads the first line of the head commit (the PR title for squash merges). ci/docs/test/style/chore commits, including our own "chore: bump version", land without a release and ship with the next fix/feat. chore(deps) and unprefixed commits (e.g. Dependabot npm/gradle bumps) still release. - Dependabot github-actions updates use the "ci" prefix, so the weekly action pin bumps no longer create releases. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_016xX1efcZF1f6G9rhmaJNLD --- .github/dependabot.yml | 3 +++ .github/workflows/release.yml | 38 ++++++++++++++++++++++++++++++++--- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 10ef8311..9acc51d6 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -6,5 +6,8 @@ updates: interval: "weekly" - package-ecosystem: "github-actions" directory: "/" + # "ci:" commits land without a release (see release.yml "decide"). + commit-message: + prefix: "ci" schedule: interval: "weekly" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 62755281..58ab7c35 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -5,6 +5,11 @@ on: branches: - main +concurrency: + # One release run at a time: parallel runs race on the version bump push. + group: release-${{ github.ref }} + cancel-in-progress: false + permissions: contents: write checks: write @@ -13,10 +18,37 @@ env: FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true jobs: + decide: + name: Release needed? + runs-on: ubuntu-latest + outputs: + release: ${{ steps.check.outputs.release }} + steps: + - name: Check commit type + id: check + env: + COMMIT_MSG: ${{ github.event.head_commit.message }} + run: | + # Squash merges put the PR title on the first line. ci/docs/test/style + # and chore commits (incl. our own "chore: bump version") land on the + # default branch without a release and ship with the next fix/feat. + # chore(deps) stays releasable: dependency updates can carry fixes. + FIRST_LINE=$(printf '%s\n' "$COMMIT_MSG" | head -n1) + if printf '%s' "$FIRST_LINE" | grep -qE '^chore\(deps(-dev)?\)!?:'; then + RELEASE=true + elif printf '%s' "$FIRST_LINE" | grep -qE '^(ci|docs|test|style|chore)(\([^)]*\))?!?:'; then + RELEASE=false + else + RELEASE=true + fi + echo "release=$RELEASE" >> "$GITHUB_OUTPUT" + echo "First line: $FIRST_LINE -> release=$RELEASE" + test-gate: name: Test Gate runs-on: ubuntu-latest - if: "!startsWith(github.event.head_commit.message, 'chore: bump version')" + needs: decide + if: needs.decide.outputs.release == 'true' steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 @@ -58,8 +90,8 @@ jobs: build: name: Build and Publish runs-on: ubuntu-latest - needs: test-gate - if: "!startsWith(github.event.head_commit.message, 'chore: bump version')" + needs: [decide, test-gate] + if: needs.decide.outputs.release == 'true' steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: