Files
renovate/.github/workflows/check-commit-messages.yml
Jamie Tanna bf37a4abaa ci: check for Closes #<discussion> (#45462)
Due to a long-standing issue with `semantic-release` not checking if
`#...` reference is for a Discussion or Issue, if a contributor says
`Closes #<discussion>`, then our release process fails.

We can extend our existing checks to try and catch this in the PR
itself, as users may not read the big warning that says "don't add a
Discussion here".

Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
2026-09-01 14:35:24 +00:00

98 lines
3.6 KiB
YAML

name: Check Commit Messages
on:
pull_request:
types:
- opened
- synchronize
- reopened
permissions:
contents: read
discussions: read
issues: read
statuses: write
concurrency:
group: ${{ github.workflow }}-${{ github.event.number || github.ref }}
cancel-in-progress: true
jobs:
closes-issue-or-discussion:
runs-on: ubuntu-slim
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
show-progress: false
- name: Check for closing keywords that would close a Discussion
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const script = require('./tools/check-closes-discussion.cjs')
await script({ github, context, core })
# Runs a full `semantic-release` dry-run for the state that would exist right
# after this PR merges, and fails if it would publish a new *major* version.
# Major releases are prepared deliberately (see docs/development/major-release.md),
# so when a major bump is intended, override this check manually.
dry-run-major:
runs-on: ubuntu-latest
env:
NODE_VERSION: 24
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
show-progress: false
# semantic-release needs the full history and all tags to find the
# previous release and the commits since it.
fetch-depth: 0
- name: Setup Node.js
uses: ./.github/actions/setup-node
with:
node-version: ${{ env.NODE_VERSION }}
os: ${{ runner.os }}
- name: Full semantic-release dry-run
env:
BASE_REF: ${{ github.event.pull_request.base.ref }}
BASE_SHA: ${{ github.event.pull_request.base.sha }}
HEAD_SHA: ${{ github.sha }}
run: |
set -euo pipefail
# `tools/check-release-dry-run.ts` runs a full `semantic-release` dry-run
# via its programmatic API and inspects the returned `nextRelease.type`.
# A real release needs a writable remote and GitHub-authenticating plugins
# - neither is available for fork PRs - so the run is fully offline:
# * a local bare mirror stands in for the remote (no network, no token);
# * only the analysis plugins run (see the script); dropping the publish
# plugins does not change the computed version;
# * it is presented as a push to the base branch at the merge commit,
# i.e. exactly the state that would exist right after this PR merges.
# Only main / next / maint/* ever publish a release.
case "$BASE_REF" in
main | next | maint/*) ;;
*)
echo "Base branch '$BASE_REF' is not a release branch; skipping."
exit 0
;;
esac
# The checkout is a detached merge commit; semantic-release runs
# `git tag --merged <baseRef>`, so the base ref must exist locally.
git branch -f "$BASE_REF" "$HEAD_SHA"
mirror="$RUNNER_TEMP/release-mirror.git"
git clone --bare --quiet . "$mirror"
# Pin the mirror's base branch to the PR base so the checked-out merge
# commit is strictly ahead of it (semantic-release treats it as releasable).
git -C "$mirror" branch -f "$BASE_REF" "$BASE_SHA"
node tools/check-release-dry-run.ts "file://$mirror" "$BASE_REF" "$HEAD_SHA"