diff --git a/.github/workflows/dev-release.yml b/.github/workflows/dev-release.yml index d3fb654c..4bd171ed 100644 --- a/.github/workflows/dev-release.yml +++ b/.github/workflows/dev-release.yml @@ -11,7 +11,9 @@ concurrency: jobs: release: - if: ${{ github.ref == 'refs/heads/dev' && (github.event_name != 'push' || !contains(github.event.head_commit.message, '[skip ci]')) }} + # Release commits must still report PR CI when dev is promoted to main. + # Skip recursive dev releases by subject instead of GitHub's global [skip ci]. + if: ${{ github.ref == 'refs/heads/dev' && (github.event_name != 'push' || !startsWith(github.event.head_commit.message, 'chore(release): ')) }} runs-on: ubuntu-latest permissions: diff --git a/scripts/dev-release.sh b/scripts/dev-release.sh index 5b372216..de01bde0 100755 --- a/scripts/dev-release.sh +++ b/scripts/dev-release.sh @@ -42,12 +42,14 @@ STABLE=${STABLE_TAG#v} CURRENT_VERSION=$(jq -r '.version' package.json) HEAD_SUBJECT=$(git log -1 --pretty=%s 2>/dev/null || echo "") DEV_VERSION_REGEX="^${STABLE//./\\.}-dev\\.[0-9]+$" +CURRENT_RELEASE_SUBJECT="chore(release): ${CURRENT_VERSION}" +LEGACY_CURRENT_RELEASE_SUBJECT="${CURRENT_RELEASE_SUBJECT} [skip ci]" PREVIOUS_DEV_TAG="" RECOVERY_MODE=false log_info "Current stable version: ${STABLE}" -if [[ "$CURRENT_VERSION" =~ $DEV_VERSION_REGEX ]] && [[ "$HEAD_SUBJECT" == "chore(release): ${CURRENT_VERSION} [skip ci]" ]]; then +if [[ "$CURRENT_VERSION" =~ $DEV_VERSION_REGEX ]] && { [[ "$HEAD_SUBJECT" == "$CURRENT_RELEASE_SUBJECT" ]] || [[ "$HEAD_SUBJECT" == "$LEGACY_CURRENT_RELEASE_SUBJECT" ]]; }; then VERSION="$CURRENT_VERSION" CURRENT_TAG="v${VERSION}" PREVIOUS_DEV_TAG=$(git tag -l "v${STABLE}-dev.*" --sort=-v:refname | grep -vx "$CURRENT_TAG" | head -1 || echo "") @@ -101,7 +103,7 @@ else # Commit version change git add package.json - git commit -m "chore(release): ${VERSION} [skip ci]" + git commit -m "chore(release): ${VERSION}" log_info "Created release commit" # Create tag diff --git a/tests/unit/scripts/github/dev-release-workflow.test.ts b/tests/unit/scripts/github/dev-release-workflow.test.ts index 5f103afb..86dbb948 100644 --- a/tests/unit/scripts/github/dev-release-workflow.test.ts +++ b/tests/unit/scripts/github/dev-release-workflow.test.ts @@ -31,4 +31,20 @@ describe('dev release workflow', () => { expect(releaseSection).not.toContain('GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}'); expect(releaseSection).not.toContain('GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}'); }); + + test('keeps release commits visible to promotion PR CI', () => { + const workflowPath = resolvePath('../../../../.github/workflows/dev-release.yml'); + const scriptPath = resolvePath('../../../../scripts/dev-release.sh'); + + const workflow = fs.readFileSync(workflowPath, 'utf8'); + const script = fs.readFileSync(scriptPath, 'utf8'); + + expect(workflow).toContain("!startsWith(github.event.head_commit.message, 'chore(release): ')"); + expect(workflow).not.toContain("contains(github.event.head_commit.message, '[skip ci]')"); + expect(script).toContain('LEGACY_CURRENT_RELEASE_SUBJECT="${CURRENT_RELEASE_SUBJECT} [skip ci]"'); + expect(script).toContain('[[ "$HEAD_SUBJECT" == "$CURRENT_RELEASE_SUBJECT" ]]'); + expect(script).toContain('[[ "$HEAD_SUBJECT" == "$LEGACY_CURRENT_RELEASE_SUBJECT" ]]'); + expect(script).toContain('git commit -m "chore(release): ${VERSION}"'); + expect(script).not.toContain('git commit -m "chore(release): ${VERSION} [skip ci]"'); + }); });