Release Automation skill for Codex

Versions, changelogs and publishes nobody types. Codex picks a release tool from how the repo already works, then wires it so the next version comes from merged changes, the changelog is reviewable in a release PR, and publishing runs from CI through OIDC trusted publishing instead of stored tokens. It catches the GITHUB_TOKEN trap that leaves release PRs without checks and dry-runs everything before the first public release.

Install

curl -fsSL codexskills.dev/install.sh \  | sh -s -- release-automation

Installs to ~/.agents/skills/release-automation/ for every project on this machine.

104-line POSIX script. No sudo, no telemetry. Read install.sh

Use it in Codex

Start a prompt with $release-automation, or pick it from /skills. You can also just describe the task: Codex reads the description below and loads the playbook when your request matches.

What Codex reads before loading it

Automates versioning, changelogs, tags, GitHub releases and package publishing with release-please, Changesets, semantic-release or GoReleaser - choosing the tool from repo shape and team habits, wiring CI with the right token and permissions, npm and PyPI trusted publishing over OIDC with provenance, monorepo package versioning, prereleases, and dry runs before the first real release. Use when setting up automated releases, replacing a manual version-bump script, publishing to npm, PyPI or GitHub Releases from CI, or fixing a release workflow that skipped or duplicated a version.

Use it when

  • Versions and changelogs are bumped by hand before each release
  • Packages are published from a developer laptop
  • A monorepo needs per-package versions and release notes
  • A release workflow skipped, duplicated or mis-numbered a version

Use something else when

How to check the result

A dry run shows the expected version, the release PR runs normal CI checks, and the first release's tag, GitHub release, registry version and changelog all agree.

The mistake it prevents

Opening release PRs with the default GITHUB_TOKEN, which does not trigger other workflows, so the release PR merges without CI having run.

~/.agents/skills/release-automation/SKILL.md

--- name: release-automation description: Automates versioning, changelogs, tags, GitHub releases and package publishing with release-please, Changesets, semantic-release or GoReleaser -… license: MIT ---

A good release pipeline derives the next version from merged changes, writes the changelog entry from the same source, tags exactly once, publishes from CI with short-lived credentials and provenance, and gives a human one obvious place to approve the release. Nobody edits a version number by hand, and a dry run proves the setup before the first real publish.

Inspect first

  1. Read AGENTS.md, CONTRIBUTING.md and recent history: git log --oneline -30 and git tag --sort=-creatordate | head. Are commits Conventional Commits? Squash merges?
  2. Find current version sources: package.json, pyproject.toml, Cargo.toml, version.go, Helm Chart.yaml, docs that mention the version.
  3. Find the registry and how publishing works today (local npm publish, a token in CI).
  4. Monorepo? List packages and whether they version together or independently.
  5. Existing CHANGELOG.md format; the new tool should continue it, not restart it.

Choose the tool

SituationTool
Conventional commits already enforced, want a reviewable release PRrelease-please
JS/TS monorepo, contributors describe changes per PRChangesets
Fully automatic publish on every merge to main, conventional commitssemantic-release
Go binaries, cross-compiled archives, Homebrew taps, container imagesGoReleaser (triggered by a tag; pair with release-please for the tag)
Python packagerelease-please (release-type: python) + PyPI trusted publishing

Default recommendation: release-please. The release PR is the approval gate, the changelog is reviewable before it ships, and it works for most languages.

release-please

// release-please-config.json
{
  "packages": {
    ".": { "release-type": "node", "changelog-path": "CHANGELOG.md" }
  }
}
// .release-please-manifest.json
{ ".": "1.4.2" }
# .github/workflows/release.yml
on:
  push:
    branches: [main]
permissions: {}
jobs:
  release-please:
    runs-on: ubuntu-latest
    permissions:
      contents: write
      pull-requests: write
    outputs:
      released: ${{ steps.rp.outputs.release_created }}
      tag: ${{ steps.rp.outputs.tag_name }}
    steps:
      - id: rp
        uses: googleapis/release-please-action@v4   # pin to a SHA in production
        with:
          token: ${{ secrets.RELEASE_BOT_TOKEN }}

  publish:
    needs: release-please
    if: needs.release-please.outputs.released == 'true'
    runs-on: ubuntu-latest
    environment: npm
    permissions:
      contents: read
      id-token: write
    steps:
      - uses: actions/checkout@v4
        with: { persist-credentials: false }
      - uses: actions/setup-node@v4
        with: { node-version: 22, registry-url: https://registry.npmjs.org }
      - run: npm ci && npm run build
      - run: npm publish
  • A PR opened with the default GITHUB_TOKEN does not trigger other workflows, so the release PR gets no CI checks. Use a GitHub App installation token (or fine-grained PAT) for the release-please step.
  • Monorepo: add each package path to both files; release-please opens one PR covering all changed packages (or separate PRs with separate-pull-requests: true).
  • Bootstrapping on an existing project: set the manifest to the current released version and, if history is long, bootstrap-sha in the config so it does not parse every commit.

Changesets

npx @changesets/cli init
npx changeset                      # contributor picks packages + bump + summary
npx changeset status --since=origin/main   # CI check that a PR includes a changeset
      - uses: changesets/action@v1
        with:
          version: npx changeset version     # opens "Version Packages" PR
          publish: npx changeset publish     # runs after that PR merges
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  • Internal dependents get patch bumps automatically when a dependency bumps (updateInternalDependencies in .changeset/config.json).
  • Prereleases: npx changeset pre enter next, release, then pre exit. Forgetting to exit keeps publishing -next versions.

semantic-release

// .releaserc.json
{
  "branches": ["main", { "name": "beta", "prerelease": true }],
  "plugins": [
    "@semantic-release/commit-analyzer",
    "@semantic-release/release-notes-generator",
    "@semantic-release/npm",
    "@semantic-release/github"
  ]
}
  • Checkout needs full history and tags: fetch-depth: 0.
  • npx semantic-release --dry-run --no-ci locally (needs network and a token with read access) shows the version it would cut without publishing.
  • Writing CHANGELOG.md back to the repo needs @semantic-release/changelog and @semantic-release/git, which commit to main from CI; branch protection must allow the bot. Many teams skip this and keep notes only in GitHub Releases.

Trusted publishing

Prefer OIDC over long-lived registry tokens:

RegistrySetup
npmConfigure a trusted publisher (repo, workflow file, environment) in the package settings on npmjs.com; job needs id-token: write and npm CLI 11.5.1 or later; provenance is generated automatically
PyPIAdd a trusted publisher on pypi.org; use pypa/gh-action-pypi-publish@release/v1 with id-token: write
crates.ioTrusted publishing via rust-lang/crates-io-auth-action on recent setups; otherwise a scoped token
ContainersPush to GHCR with packages: write; sign with cosign keyless

After switching, delete the old NPM_TOKEN or PyPI token, with the user’s approval.

GoReleaser

goreleaser check
goreleaser release --snapshot --clean      # local build of all artifacts, nothing published

Trigger the real goreleaser release --clean on tag push (on: push: tags: ['v*']) with contents: write. Fetch full history so it can build the changelog.

Version rules

  • Conventional commits map: fix: patch, feat: minor, feat!: or a BREAKING CHANGE: footer major. Before 1.0.0, release-please bumps minor for breaking changes unless configured otherwise.
  • Squash merges make the PR title the commit message; lint PR titles in CI (see conventional-commits).
  • Never reuse or move a published tag. Fix forward with a new patch version.

Confirmation

Publishing a package, creating a GitHub release, pushing tags and merging the release PR are public and mostly irreversible (npm unpublish is limited to 72 hours and blocked when dependents exist). Run dry runs freely; ask the user before the first real release and before deleting old tokens.

Verification

  • Dry run or snapshot shows the expected next version and changelog
  • Release PR (or changeset PR) runs the normal CI checks
  • First real release: tag, GitHub release, registry version and changelog agree
  • Registry page shows provenance or trusted-publisher attestation
  • A docs-only or chore commit does not trigger a release

Output

Report the tool chosen and why, files added, secrets or apps the user must create (GitHub App, trusted publisher entries), the dry-run version, and the steps that remain manual.

What the zip contains

SKILL.md plus the interface file below. Nothing runs on install.

agents/openai.yamlgenerated from this page

Gives the Codex app a display name, a one-line description and a starter prompt for this skill.

interface:
  display_name: "Release Automation"
  short_description: "Versions, changelogs and publishes nobody types"
  default_prompt: "$release-automation Set up release-please so merging to main produces a release PR and publishes to npm"

About this skill

Written and maintained by the Codex Skills editors to the same editorial standard as every skill here: a selective description, a real workflow, known pitfalls and a way to verify the work. First published , last updated . MIT licensed. Something wrong or out of date? Tell us.

esc
Just launched

Codex Skills Pro is live

79 premium skills for Codex, each with scripts, references and an evidence report that proves the result.

Bought one by one$882.21
All 79 skills$49
94% off

That's $0.62 a skill, paid once.

Get all 79 for $49Or pick single skills from $4.99 →

Secure checkout by Creem