Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
4 changes: 2 additions & 2 deletions .github/workflows/codex-update.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ jobs:
npm install "$CODEX_PACKAGE@$VERSION"
npm run generate-types
git add package.json package-lock.json src/app-server
git commit -m "Update codex to $VERSION"
git commit -m "fix: update codex to $VERSION"

- name: Finalize update with Codex
id: codex-finalize
Expand Down Expand Up @@ -112,7 +112,7 @@ jobs:

gh pr create \
--base main \
--title "Update codex to $VERSION" \
--title "fix: update codex to $VERSION" \
--body-file pr-body.md \
--label "$CODEX_UPDATE_LABEL"

Expand Down
48 changes: 48 additions & 0 deletions .github/workflows/conventional-prs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: Conventional PRs

# Squash merges use the PR title as the commit subject, so the title is what
# ends up in the history release notes are generated from.
on:
pull_request:
branches: [main]
# labeled/unlabeled so validation re-runs when `dependencies` is applied.
types: [opened, reopened, edited, synchronize, labeled, unlabeled]

permissions: {}

concurrency:
group: "conventional-prs-${{ github.event.pull_request.number }}"
cancel-in-progress: true

jobs:
validate:
name: Validate PR title
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
pull-requests: read

steps:
# Config reference: https://github.com/amannn/action-semantic-pull-request#configuration
- uses: amannn/action-semantic-pull-request@48f256284bd46cdaab1048c3721360e808335d50 # v6.1.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
# Exactly the types release-please understands. feat/fix/perf/revert/docs
# appear in the changelog; the rest are valid but hidden. Any other type
# would be dropped silently, so it is rejected here instead.
types: |
feat
fix
perf
revert
docs
style
chore
refactor
test
build
ci
# Dependabot titles itself conventionally already; don't block bot PRs.
ignoreLabels: |
dependencies
107 changes: 77 additions & 30 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -1,23 +1,82 @@
name: Release
name: Publish and Release

on:
push:
tags:
- 'v*'
branches:
- main
# Recovery path for a release whose tag exists but whose npm publish or
# registry update did not land. See docs/RELEASES.md.
workflow_dispatch:
inputs:
ref:
description: Tag or commit to publish
required: true
type: string
publish_npm:
description: Publish the package before updating the registry
required: true
default: true
type: boolean

permissions: {}

jobs:
verify:
# Every push to main re-computes the next version from the conventional commit
# messages and keeps a single release PR open. Merging that PR is what tags,
# releases and publishes; there is no manual release button.
release-please:
if: ${{ github.event_name == 'push' }}
runs-on: ubuntu-latest
environment: release # Optional: for enhanced security
permissions:
contents: write
issues: write
pull-requests: write
steps:
# Generating a GitHub token, so that PRs and tags created by
# the release-please-action can trigger actions workflows.
- name: Generate GitHub token
uses: actions/create-github-app-token@v3
id: generate-token
with:
app-id: ${{ secrets.RELEASE_PLZ_APP_ID }}
private-key: ${{ secrets.RELEASE_PLZ_APP_PRIVATE_KEY }}

- uses: googleapis/release-please-action@45996ed1f6d02564a971a2fa1b5860e934307cf7 # v5.0.0
id: release
with:
token: ${{ steps.generate-token.outputs.token }}
# Do not add release-type here. The action ignores config-file whenever
# release-type is set, which would silently drop
# include-component-in-tag and start tagging codex-acp-vX.Y.Z instead of
# vX.Y.Z. The node release type is declared in that config instead, so
# nothing is lost by leaving this out.
config-file: release-please-config.json
manifest-file: .release-please-manifest.json
outputs:
release_created: ${{ steps.release.outputs.release_created }}
tag_name: ${{ steps.release.outputs.tag_name }}

# The gate for both paths: nothing is published unless this passes. Its `if`
# rather than `needs` alone decides whether a release is happening, because on
# workflow_dispatch the release-please job is skipped.
#
# Deliberately not in the `release` environment: OPENAI_API_KEY is a repository
# secret, so this needs nothing from it, and staying out keeps the job off the
# environment's deployment branch policy.
verify:
needs: [release-please]
if: ${{ always() && ((github.event_name == 'workflow_dispatch' && inputs.publish_npm) || needs.release-please.outputs.release_created == 'true') }}
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v7
with:
ref: ${{ github.event_name == 'workflow_dispatch' && inputs.ref || github.ref }}
- uses: actions/setup-node@v7
with:
node-version: '24'
node-version: "24"
- name: Configure sandboxing
run: |
sudo apt-get update
Expand All @@ -34,43 +93,31 @@ jobs:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
run: npm run test:e2e

publish-to-npm:
needs: verify
publish-npm:
name: Publish to npm
needs: [release-please, verify]
if: ${{ always() && needs.verify.result == 'success' }}
runs-on: ubuntu-latest
environment: release # Optional: for enhanced security
permissions:
contents: read
id-token: write
id-token: write # npm trusted publishing, so there is no npm token
steps:
- uses: actions/checkout@v7
with:
ref: ${{ github.event_name == 'workflow_dispatch' && inputs.ref || github.ref }}
# Setup .npmrc file to publish to npm
- uses: actions/setup-node@v7
with:
node-version: '24'
registry-url: 'https://registry.npmjs.org'
node-version: "24"
registry-url: "https://registry.npmjs.org"
- run: npm ci
# prepublishOnly builds the bundle.
- run: npm publish --access public

create-release:
needs: publish-to-npm
runs-on: ubuntu-latest
environment: release
permissions: {}
steps:
- name: Generate GitHub token
uses: actions/create-github-app-token@v3
id: generate-token
with:
app-id: ${{ secrets.RELEASE_PLZ_APP_ID }}
private-key: ${{ secrets.RELEASE_PLZ_APP_PRIVATE_KEY }}

- name: Create Release
uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2
with:
token: ${{ steps.generate-token.outputs.token }}
generate_release_notes: true

trigger-registry-update:
needs: create-release
needs: publish-npm
if: ${{ always() && (needs.publish-npm.result == 'success' || (github.event_name == 'workflow_dispatch' && !inputs.publish_npm)) }}
runs-on: ubuntu-latest
environment: release
permissions: {}
Expand Down
43 changes: 0 additions & 43 deletions .github/workflows/version-bump.yml

This file was deleted.

3 changes: 3 additions & 0 deletions .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
".": "1.1.14"
}
12 changes: 12 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,18 @@
- Focus on behavior and outputs rather than implementation details.
- Use `/run-codex` skill (`.claude/skills/run-codex/`) to test with real Codex and observe actual events.

## Pull Requests

- Squash merges use the PR title as the commit subject, and release-please parses it to compute the next version. Titles must be conventional commits using one of: `feat`, `fix`, `perf`, `revert`, `docs`, `style`, `chore`, `refactor`, `test`, `build`, `ci`. `conventional-prs.yml` rejects anything else.
- The title also decides the release: `feat:` bumps the minor, `fix:`/`perf:`/`revert:` the patch, a `!` bumps the major, and `chore:`/`ci:`/`docs:` and friends do not release at all.

## Releasing

- Releases are fully automated by release-please. There is no manual release workflow, and the version is never chosen by hand — it follows from the commit history.
- `npm run release:preflight` verifies it is safe to release and prints the PR number and version; then `gh pr merge <pr-number> --squash`.
- The preflight is the guard-list as code; if it exits non-zero, follow what it prints rather than merging.
- Full runbook, including how to recover a stalled release: [`docs/RELEASES.md`](docs/RELEASES.md).

## Docs

- Codex app-server usage: see https://github.com/openai/codex/blob/main/codex-rs/app-server/README.md when touching protocol/transport details, adding or consuming JSON-RPC methods, handling approvals/turn events, or updating generated schema/clients.
Expand Down
Loading
Loading