Skip to content

ci(build): add repo-wide verify:dist self-check; fix un-inlined JSON … #112

ci(build): add repo-wide verify:dist self-check; fix un-inlined JSON …

ci(build): add repo-wide verify:dist self-check; fix un-inlined JSON … #112

Workflow file for this run

name: Release
on:
push:
branches: [main]
permissions:
contents: write
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'pnpm'
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Run tests
run: pnpm test 2>&1 | tee /tmp/test-output.log
- name: Capture test counts
id: tests
run: |
CLEAN=$(sed 's/\x1b\[[0-9;]*m//g' /tmp/test-output.log)
TEST_COUNT=$(echo "$CLEAN" | sed -n 's/.*Tests *\([0-9][0-9]*\) passed.*/\1/p' | tail -1)
TEST_FILES=$(echo "$CLEAN" | sed -n 's/.*Test Files *\([0-9][0-9]*\) passed.*/\1/p' | tail -1)
echo "count=${TEST_COUNT:-0}" >> "$GITHUB_OUTPUT"
echo "files=${TEST_FILES:-0}" >> "$GITHUB_OUTPUT"
- name: Count agents
id: agents
run: |
# Single source of truth: scripts/count-agents.ts walks the
# workspace exactly the same way the CLI's discoverAgents() does.
# The previous `find` undercounted by skipping agents-platform
# and agents-tmc.
AGENT_COUNT=$(pnpm tsx scripts/count-agents.ts --json | node -e "let s=''; process.stdin.on('data',c=>s+=c).on('end',()=>console.log(JSON.parse(s).total))")
echo "count=${AGENT_COUNT}" >> "$GITHUB_OUTPUT"
- name: Get version
id: version
run: |
VERSION=$(node -p "require('./package.json').version")
echo "tag=v${VERSION}" >> "$GITHUB_OUTPUT"
- name: Check if release exists
id: check
run: |
TAG="${{ steps.version.outputs.tag }}"
if curl -s -o /dev/null -w "%{http_code}" -H "Authorization: token $GH_TOKEN" "https://api.github.com/repos/${{ github.repository }}/releases/tags/$TAG" | grep -q "200"; then
echo "exists=true" >> "$GITHUB_OUTPUT"
else
echo "exists=false" >> "$GITHUB_OUTPUT"
fi
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Build release notes
if: steps.check.outputs.exists == 'false'
id: notes
run: |
VERSION=$(node -p "require('./package.json').version")
AGENT_COUNT="${{ steps.agents.outputs.count }}"
TEST_COUNT="${{ steps.tests.outputs.count }}"
TEST_FILES="${{ steps.tests.outputs.files }}"
# Extract the current version's section from CHANGELOG.md.
# Matches '## <version> — ...' through the next '## <digit>...' or EOF.
# Require ' — ' after the version so '0.3.2' doesn't match '0.3.2.1'.
CHANGELOG_BODY=$(node -e "
const fs = require('fs');
const version = process.argv[1];
try {
const content = fs.readFileSync('CHANGELOG.md', 'utf8');
const escaped = version.replace(/\./g, '\\\\.');
const re = new RegExp('## ' + escaped + ' — [^\\\\n]*\\\\n([\\\\s\\\\S]*?)(?=\\\\n## \\\\d|\$)');
const m = content.match(re);
if (m) process.stdout.write(m[1].trim());
} catch (e) { /* CHANGELOG missing — fall through */ }
" "$VERSION")
{
if [ -n "$CHANGELOG_BODY" ]; then
# CHANGELOG has an entry for this version — use it verbatim.
echo "$CHANGELOG_BODY"
echo ""
echo "---"
echo ""
fi
echo "${AGENT_COUNT} agents · ${TEST_COUNT} tests passing across ${TEST_FILES} files · Apache 2.0"
} > /tmp/release-notes.md
- name: Create release
if: steps.check.outputs.exists == 'false'
# Why RELEASE_PAT instead of GITHUB_TOKEN:
# GitHub Actions silently DOES NOT trigger downstream workflows
# for events created by GITHUB_TOKEN (the default Actions token).
# Without this, `gh release create` fires a `release: published`
# event that the Publish-to-npm workflow never sees, and packages
# never get published. Using a personal access token makes the
# event "user-fired", which propagates correctly.
# If RELEASE_PAT isn't configured the workflow falls back to
# GITHUB_TOKEN so the release still gets created — but the
# publish step won't auto-fire and someone will have to trigger
# it manually via workflow_dispatch.
env:
GH_TOKEN: ${{ secrets.RELEASE_PAT || secrets.GITHUB_TOKEN }}
run: |
gh release create "${{ steps.version.outputs.tag }}" \
--title "${{ steps.version.outputs.tag }}" \
--notes-file /tmp/release-notes.md \
--latest