Skip to content

Release

Release #10

Workflow file for this run

name: Release
on:
push:
branches: [main]
paths:
- package.json
- CHANGELOG.md
- .github/assets/social-preview-manifest.json
- .github/assets/codex-toolkit-social-preview.png
- .github/render_social_preview.py
- scripts/verify_release_metadata.py
- .github/workflows/release.yml
workflow_dispatch:
permissions:
contents: write
jobs:
preview:
runs-on: ubuntu-latest
timeout-minutes: 10
outputs:
changed: ${{ steps.refresh.outputs.changed }}
target_sha: ${{ steps.refresh.outputs.target_sha }}
steps:
- name: Check out repository
uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.13"
- name: Set up Node.js
uses: actions/setup-node@v5
with:
node-version: "24"
- name: Set up social-preview renderer
run: python -m pip install --disable-pip-version-check --no-input Pillow
- name: Render and persist canonical social preview
id: refresh
shell: bash
run: |
set -euo pipefail
python .github/render_social_preview.py
if git diff --quiet -- \
.github/assets/codex-toolkit-social-preview.png \
.github/assets/social-preview-manifest.json
then
echo "changed=false" >> "$GITHUB_OUTPUT"
echo "target_sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
exit 0
fi
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add \
.github/assets/codex-toolkit-social-preview.png \
.github/assets/social-preview-manifest.json
version="$(node -p "require('./package.json').version")"
git commit -m "chore: refresh v${version} social preview"
git push origin HEAD:main
echo "changed=true" >> "$GITHUB_OUTPUT"
echo "target_sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
release:
needs: preview
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Check out release candidate
uses: actions/checkout@v5
with:
fetch-depth: 0
ref: ${{ needs.preview.outputs.target_sha }}
- name: Assert candidate identity
env:
TARGET_SHA: ${{ needs.preview.outputs.target_sha }}
run: test "$(git rev-parse HEAD)" = "$TARGET_SHA"
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.13"
- name: Set up Node.js
uses: actions/setup-node@v5
with:
node-version: "24"
- name: Validate skill pack
run: python scripts/validate_skill_pack.py . --as-of 2026-08-16
- name: Verify anti-slop vendor integrity
run: python scripts/verify_anti_slop_vendor.py .
- name: Run TypeScript quality regressions
run: python scripts/test_typescript_quality_regressions.py .
- name: Verify release metadata
run: python scripts/verify_release_metadata.py .
- name: Run helper smoke tests
run: python scripts/run_smoke_tests.py . --as-of 2026-08-16
- name: Inspect package contents
run: npm pack --dry-run
- name: Prepare release notes
id: release
shell: bash
run: |
version="$(node -p "require('./package.json').version")"
tag="v${version}"
echo "version=$version" >> "$GITHUB_OUTPUT"
echo "tag=$tag" >> "$GITHUB_OUTPUT"
python - "$version" "$RUNNER_TEMP/release-notes.md" <<'PY'
import re
import sys
from pathlib import Path
version, output = sys.argv[1], Path(sys.argv[2])
text = Path("CHANGELOG.md").read_text(encoding="utf-8")
pattern = rf"(?ms)^## {re.escape(version)} - [^\n]+\n\n(.*?)(?=^## |\Z)"
match = re.search(pattern, text)
if match is None:
raise SystemExit(f"missing CHANGELOG section for {version}")
notes = match.group(1).strip()
if not notes:
raise SystemExit(f"empty CHANGELOG section for {version}")
output.write_text(notes + "\n", encoding="utf-8")
PY
- name: Check existing tag and release
id: existing
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ steps.release.outputs.tag }}
shell: bash
run: |
if git ls-remote --exit-code --tags origin "refs/tags/$TAG" >/dev/null 2>&1; then
echo "tag=true" >> "$GITHUB_OUTPUT"
else
echo "tag=false" >> "$GITHUB_OUTPUT"
fi
if gh release view "$TAG" >/dev/null 2>&1; then
echo "release=true" >> "$GITHUB_OUTPUT"
else
echo "release=false" >> "$GITHUB_OUTPUT"
fi
- name: Create version tag
if: steps.existing.outputs.tag != 'true'
env:
TAG: ${{ steps.release.outputs.tag }}
TARGET_SHA: ${{ needs.preview.outputs.target_sha }}
run: |
git tag "$TAG" "$TARGET_SHA"
git push origin "refs/tags/$TAG"
- name: Create GitHub release
if: steps.existing.outputs.release != 'true'
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ steps.release.outputs.tag }}
VERSION: ${{ steps.release.outputs.version }}
run: >-
gh release create "$TAG"
--verify-tag
--title "Codex Toolkit $VERSION"
--notes-file "$RUNNER_TEMP/release-notes.md"
- name: Remove known merged release branches
shell: bash
run: |
for branch in \
feat/codebase-improvement-planner \
feat/typescript-quality-enforcer \
feat/content-provenance-hygiene \
noop-do-not-create
do
if git ls-remote --exit-code --heads origin "refs/heads/$branch" >/dev/null 2>&1; then
git push origin --delete "$branch"
fi
done