Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions .github/workflows/_release-github.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,62 @@ jobs:

echo "No 'DO NOT RELEASE' markers found in codebase. Proceeding with release."

# If there are any open issues or PRs labeled "X.Y.Z-blocker", abort the release (and let us know)
check-release-blockers:
name: 'Check for Open "<version>-blocker" Issues/PRs'
if: >-
inputs.tag != ''
runs-on: ubuntu-latest
permissions:
contents: read
issues: read
pull-requests: read
steps:
- name: 'Check for open "<version>-blocker" issues and pull requests'
shell: bash
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ inputs.tag }}
run: |
# The blocker label is the 3-part version (X.Y.Z) of the release tag, i.e. "4.0.0-blocker".
# Anything after the 3-part version (i.e. "-rc1", or extra version parts) is ignored.

if [[ ! "${TAG}" =~ ^([0-9]+\.[0-9]+\.[0-9]+) ]]; then
echo "::error::Could not determine an X.Y.Z version from the tag '${TAG}'. Aborting release."
exit 1
fi
LABEL="${BASH_REMATCH[1]}-blocker"
echo "Checking for open issues and pull requests labeled '${LABEL}'"

# The REST "list repository issues" endpoint returns both issues and pull requests,
# and returns an empty list (rather than an error) when the label does not exist.
BLOCKERS=$(gh api --paginate -X GET "repos/${GITHUB_REPOSITORY}/issues" \
-f state=open \
-f labels="${LABEL}" \
-f per_page=100 \
--jq '.[] | "- [\(if .pull_request then "PR" else "Issue" end) #\(.number)](\(.html_url)): \(.title)"')

if [ -n "$BLOCKERS" ]; then
{
echo "### ❌ Release Blocked"
echo "Found open issue(s)/pull request(s) labeled \`${LABEL}\`:"
echo "$BLOCKERS"
echo ""
echo 'These must be resolved (or the label removed) before a release can be completed.'
} >> "$GITHUB_STEP_SUMMARY"

echo "::error::Found open issues/PRs labeled '${LABEL}'. Aborting release."
exit 1
fi

echo "No open issues or pull requests labeled '${LABEL}'. Proceeding with release."

# Wait for someone to pull the andon cord (as configured in the "Builds Release" GitHub Actions environment)
andon-cord:
name: Andon Cord
needs:
- check-do-not-release
- check-release-blockers
if: >-
inputs.tag != ''
runs-on: ubuntu-latest
Expand Down
10 changes: 6 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -328,10 +328,12 @@ jobs:
needs.check-release.outputs.is_release == 'true' &&
github.event_name != 'merge_group'
permissions:
contents: write # required for github release
id-token: write # required for attestation
attestations: write # required for attestation
packages: write # required for image push to ghcr
contents: write # required for github release
id-token: write # required for attestation
attestations: write # required for attestation
packages: write # required for image push to ghcr
issues: read # required for release blocker check
pull-requests: read # required for release blocker check
uses: ./.github/workflows/_release-github.yml
with:
tag: ${{ needs.check-release.outputs.tag }} # 3-part version shared by the node and signer, like 4.0.0
Expand Down
8 changes: 8 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,14 @@ To safeguard against accidentally deploying incomplete work, experimental featur
- **CI Safety Check:** During automated release workflows, the `check-do-not-release` job recursively scans the codebase (excluding `.git` and `.github`). If it detects the string anywhere, it immediately halts the pipeline, logs an inline error annotation, and writes a detailed breakdown to the GitHub Job Summary showing every location where the phrase was found.
- **Resolving the block:** A release cannot proceed until all instances of `"DO NOT RELEASE"` are removed from the codebase and merged to the target branch.

### Blocking a Release With a Label (`X.Y.Z-blocker`)

Work that must land _before_ a given release can also be tracked with a label instead of a marker in the code.

- **How to use it:** Apply the label `X.Y.Z-blocker` (where `X.Y.Z` is the release version, i.e. `4.0.0-blocker`) to any issue or pull request that must be resolved before that release ships.
- **CI Safety Check:** During automated release workflows, the `check-release-blockers` job derives the label from the release tag and queries the repository for open issues and pull requests carrying it. If any are found, it halts the pipeline, logs an inline error annotation, and writes a list of the blocking issues/PRs to the GitHub Job Summary.
- **Resolving the block:** A release cannot proceed until every issue/PR with that label is closed (or merged), or the label is removed from anything that turns out not to be a blocker.

# Coding Guidelines

## Documentation
Expand Down