👷 Mark issues as released when new tag published

- Fixed issue where tag body was missing PR info
- Adds tag logic to mark release version for applicable issues
- Trigger rebuild of docs website when version released
- Upgraded the github-script action from v7 to v8
- Show summary of changes when workflow completes
- Updated code comments to explain wtf is happening
This commit is contained in:
Alicia Sykes
2026-04-01 12:26:32 +01:00
parent c608879006
commit da63ebc830

View File

@@ -1,7 +1,14 @@
# When a PR is merged into master, this workflow handles versioning:
# - If code files changed but version wasn't bumped: auto-increments patch version
# Creates a new git tag when a PR is merged
#
# Here's the flow:
# - Triggered whenever a PR is merged, if that PR made code changes
# - If version wasn't bumped in PR, increment patch version and update package.json
# - Otherwise (if the PR did bump version) we use the new version from package.json
# - Creates and pushes a git tag for the new version
# - The tag then triggers Docker publishing and release drafting
# - That git tag then triggers Docker publishing and release drafting in other CI
# - Add tags to issues from newly relesaed features/fixes (if applicable)
# - Trigger fresh deploy of docs site, so changelog remains up-to-date
# - Finally, shows summary of actions taken and new tag published
name: 🔖 Auto Version & Tag
on:
@@ -16,6 +23,7 @@ concurrency:
permissions:
contents: write
pull-requests: read
issues: write
jobs:
version-and-tag:
@@ -25,7 +33,7 @@ jobs:
steps:
- name: Check PR for code changes and version bump 📂
id: check_pr
uses: actions/github-script@v7
uses: actions/github-script@v8
with:
script: |
const { owner, repo } = context.repo;
@@ -77,7 +85,7 @@ jobs:
- name: Checkout repository 🛎️
if: steps.check_pr.outputs.needs_tag == 'true'
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
@@ -87,6 +95,23 @@ jobs:
git config user.name "Liss-Bot"
git config user.email "liss-bot@d0h.co"
- name: Extract referenced issues 🔍
id: issues
if: steps.check_pr.outputs.needs_tag == 'true'
uses: actions/github-script@v8
with:
script: |
const body = context.payload.pull_request.body || '';
const matches = body.match(/#(\d+)/g);
if (!matches) {
core.info('No issue references found in PR body');
core.setOutput('numbers', '');
return;
}
const unique = [...new Set(matches.map(m => m.replace('#', '')))];
core.info(`Found issue references: ${unique.join(', ')}`);
core.setOutput('numbers', unique.join(','));
- name: Bump patch version ⬆️
if: steps.check_pr.outputs.needs_bump == 'true'
run: |
@@ -96,7 +121,13 @@ jobs:
git push
- name: Create and push tag 🏷️
id: tag
if: steps.check_pr.outputs.needs_tag == 'true'
env:
PR_NUMBER: ${{ github.event.pull_request.number }}
PR_TITLE: ${{ github.event.pull_request.title }}
MERGE_SHA: ${{ github.event.pull_request.merge_commit_sha }}
ISSUES: ${{ steps.issues.outputs.numbers }}
run: |
VERSION=$(node -p "require('./package.json').version")
git fetch --tags --force
@@ -111,5 +142,121 @@ jobs:
"$PR_TITLE" \
"$MERGE_SHA" > tag-message.txt
if [ -n "$ISSUES" ]; then
printf 'Resolves: %s\n' "$(echo "$ISSUES" | sed 's/,/, #/g; s/^/#/')" >> tag-message.txt
fi
git tag -a "$VERSION" -F tag-message.txt
git push origin "$VERSION"
- name: Label referenced issues 🛩️
id: label
if: steps.check_pr.outputs.needs_tag == 'true' && steps.issues.outputs.numbers != ''
continue-on-error: true
uses: actions/github-script@v8
env:
ISSUES: ${{ steps.issues.outputs.numbers }}
with:
github-token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
script: |
const { owner, repo } = context.repo;
const { version } = JSON.parse(require('fs').readFileSync('package.json', 'utf8'));
const labelName = `🛩️ Released ${version}`;
const issues = process.env.ISSUES.split(',').filter(Boolean);
try {
await github.rest.issues.createLabel({
owner, repo,
name: labelName,
color: 'EDEDED',
description: `Included in release v${version}`,
});
core.info(`Created label: ${labelName}`);
} catch (e) {
if (e.status === 422) {
core.info(`Label already exists: ${labelName}`);
} else {
core.warning(`Failed to create label: ${e.message}`);
}
}
for (const num of issues) {
try {
await github.rest.issues.addLabels({
owner, repo,
issue_number: parseInt(num, 10),
labels: [labelName],
});
core.info(`Labeled issue #${num}`);
} catch (e) {
core.warning(`Failed to label issue #${num}: ${e.message}`);
}
}
- name: Trigger docs site rebuild 📝
id: docs
if: steps.tag.outcome == 'success'
continue-on-error: true
env:
HOOK_URL: ${{ secrets.DOCS_SITE_REBUILD_HOOK }}
run: |
if [ -z "$HOOK_URL" ]; then
echo "::warning::DOCS_SITE_REBUILD_HOOK secret is not set, skipping"
exit 1
fi
VERSION=$(node -p "require('./package.json').version" 2>/dev/null || echo "unknown")
curl -sf -X POST -d '{}' "${HOOK_URL}?trigger_title=v${VERSION}+released" \
--max-time 15 --retry 2 --retry-max-time 30
echo "Triggered docs rebuild for v${VERSION}"
- name: Job summary 📋
if: always()
env:
PR_NUMBER: ${{ github.event.pull_request.number }}
PR_TITLE: ${{ github.event.pull_request.title }}
REPO_URL: ${{ github.server_url }}/${{ github.repository }}
NEEDS_BUMP: ${{ steps.check_pr.outputs.needs_bump }}
NEEDS_TAG: ${{ steps.check_pr.outputs.needs_tag }}
ISSUES: ${{ steps.issues.outputs.numbers }}
TAG_OUTCOME: ${{ steps.tag.outcome }}
LABEL_OUTCOME: ${{ steps.label.outcome }}
DOCS_OUTCOME: ${{ steps.docs.outcome }}
run: |
VERSION=$(node -p "require('./package.json').version" 2>/dev/null || echo "unknown")
{
echo "## 🔖 Auto Version & Tag"
echo ""
echo "| Step | Result |"
echo "|------|--------|"
echo "| PR | [#${PR_NUMBER}](${REPO_URL}/pull/${PR_NUMBER}) — ${PR_TITLE} |"
if [ "$NEEDS_BUMP" = "true" ]; then
echo "| Version bump | ✅ \`${VERSION}\` |"
else
echo "| Version bump | ⏭️ Skipped |"
fi
if [ "$NEEDS_TAG" = "true" ] && [ "$TAG_OUTCOME" = "success" ]; then
echo "| Tag | ✅ [\`${VERSION}\`](${REPO_URL}/releases/tag/${VERSION}) |"
elif [ "$NEEDS_TAG" = "true" ]; then
echo "| Tag | ❌ Failed |"
else
echo "| Tag | ⏭️ Skipped |"
fi
if [ "$DOCS_OUTCOME" = "success" ]; then
echo "| Docs rebuild | ✅ Triggered |"
elif [ "$DOCS_OUTCOME" = "failure" ]; then
echo "| Docs rebuild | ⚠️ Failed |"
fi
if [ -n "$ISSUES" ]; then
ISSUE_LINKS=$(echo "$ISSUES" | tr ',' '\n' | sed "s|.*|[#&](${REPO_URL}/issues/&)|" | paste -sd ' ' -)
if [ "$LABEL_OUTCOME" = "success" ]; then
echo "| Issues labeled | ✅ ${ISSUE_LINKS} |"
else
echo "| Issues labeled | ⚠️ ${ISSUE_LINKS} |"
fi
fi
} >> "$GITHUB_STEP_SUMMARY"