This is a first cut at a GitHub Action that lets you define prompt
templates in `.md` files under `.github/codex/labels` that will run
Codex with the associated prompt when the label is added to a GitHub
pull request.
For example, this PR includes these files:
```
.github/codex/labels/codex-attempt.md
.github/codex/labels/codex-code-review.md
.github/codex/labels/codex-investigate-issue.md
```
And the new `.github/workflows/codex.yml` workflow declares the
following triggers:
```yaml
on:
issues:
types: [opened, labeled]
pull_request:
branches: [main]
types: [labeled]
```
as well as the following expression to gate the action:
```
jobs:
codex:
if: |
(github.event_name == 'issues' && (
(github.event.action == 'labeled' && (github.event.label.name == 'codex-attempt' || github.event.label.name == 'codex-investigate-issue'))
)) ||
(github.event_name == 'pull_request' && github.event.action == 'labeled' && github.event.label.name == 'codex-code-review')
```
Note the "actor" who added the label must have write access to the repo
for the action to take effect.
After adding a label, the action will "ack" the request by replacing the
original label (e.g., `codex-review`) with an `-in-progress` suffix
(e.g., `codex-review-in-progress`). When it is finished, it will swap
the `-in-progress` label with a `-completed` one (e.g.,
`codex-review-completed`).
Users of the action are responsible for providing an `OPENAI_API_KEY`
and making it available as a secret to the action.
125 lines
4.4 KiB
YAML
125 lines
4.4 KiB
YAML
name: "Codex [reusable action]"
|
|
description: "A reusable action that runs a Codex model."
|
|
|
|
inputs:
|
|
openai_api_key:
|
|
description: "The value to use as the OPENAI_API_KEY environment variable when running Codex."
|
|
required: true
|
|
trigger_phrase:
|
|
description: "Text to trigger Codex from a PR/issue body or comment."
|
|
required: false
|
|
default: ""
|
|
github_token:
|
|
description: "Token so Codex can comment on the PR or issue."
|
|
required: true
|
|
codex_args:
|
|
description: "A whitespace-delimited list of arguments to pass to Codex. Due to limitations in YAML, arguments with spaces are not supported. For more complex configurations, use the `codex_home` input."
|
|
required: false
|
|
default: "--full-auto"
|
|
codex_home:
|
|
description: "Value to use as the CODEX_HOME environment variable when running Codex."
|
|
required: false
|
|
codex_release_tag:
|
|
description: "The release tag of the Codex model to run."
|
|
required: false
|
|
default: "codex-rs-d519bd8bbd1e1fd9efdc5d68cf7bebdec0dd0f28-1-rust-v0.0.2505270918"
|
|
|
|
runs:
|
|
using: "composite"
|
|
steps:
|
|
# Do this in Bash so we do not even bother to install Bun if the sender does
|
|
# not have write access to the repo.
|
|
- name: Verify user has write access to the repo.
|
|
env:
|
|
GH_TOKEN: ${{ github.token }}
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
|
|
PERMISSION=$(gh api \
|
|
"/repos/${GITHUB_REPOSITORY}/collaborators/${{ github.event.sender.login }}/permission" \
|
|
| jq -r '.permission')
|
|
|
|
if [[ "$PERMISSION" != "admin" && "$PERMISSION" != "write" ]]; then
|
|
exit 1
|
|
fi
|
|
|
|
- name: Download Codex
|
|
env:
|
|
GH_TOKEN: ${{ github.token }}
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
|
|
# Determine OS/arch and corresponding Codex artifact name.
|
|
uname_s=$(uname -s)
|
|
uname_m=$(uname -m)
|
|
|
|
case "$uname_s" in
|
|
Linux*) os="linux" ;;
|
|
Darwin*) os="apple-darwin" ;;
|
|
*) echo "Unsupported operating system: $uname_s"; exit 1 ;;
|
|
esac
|
|
|
|
case "$uname_m" in
|
|
x86_64*) arch="x86_64" ;;
|
|
arm64*|aarch64*) arch="aarch64" ;;
|
|
*) echo "Unsupported architecture: $uname_m"; exit 1 ;;
|
|
esac
|
|
|
|
# linux builds differentiate between musl and gnu.
|
|
if [[ "$os" == "linux" ]]; then
|
|
if [[ "$arch" == "x86_64" ]]; then
|
|
triple="${arch}-unknown-linux-musl"
|
|
else
|
|
# Only other supported linux build is aarch64 gnu.
|
|
triple="${arch}-unknown-linux-gnu"
|
|
fi
|
|
else
|
|
# macOS
|
|
triple="${arch}-apple-darwin"
|
|
fi
|
|
|
|
# Note that if we start baking version numbers into the artifact name,
|
|
# we will need to update this action.yml file to match.
|
|
artifact="codex-exec-${triple}.tar.gz"
|
|
|
|
gh release download ${{ inputs.codex_release_tag }} --repo openai/codex \
|
|
--pattern "$artifact" --output - \
|
|
| tar xzO > /usr/local/bin/codex-exec
|
|
chmod +x /usr/local/bin/codex-exec
|
|
|
|
# Display Codex version to confirm binary integrity; ensure we point it
|
|
# at the checked-out repository via --cd so that any subsequent commands
|
|
# use the correct working directory.
|
|
codex-exec --cd "$GITHUB_WORKSPACE" --version
|
|
|
|
- name: Install Bun
|
|
uses: oven-sh/setup-bun@v2
|
|
with:
|
|
bun-version: 1.2.11
|
|
|
|
- name: Install dependencies
|
|
shell: bash
|
|
run: |
|
|
cd ${{ github.action_path }}
|
|
bun install --production
|
|
|
|
- name: Run Codex
|
|
shell: bash
|
|
run: bun run ${{ github.action_path }}/src/main.ts
|
|
# Process args plus environment variables often have a max of 128 KiB,
|
|
# so we should fit within that limit?
|
|
env:
|
|
INPUT_CODEX_ARGS: ${{ inputs.codex_args || '' }}
|
|
INPUT_CODEX_HOME: ${{ inputs.codex_home || ''}}
|
|
INPUT_TRIGGER_PHRASE: ${{ inputs.trigger_phrase || '' }}
|
|
OPENAI_API_KEY: ${{ inputs.openai_api_key }}
|
|
GITHUB_TOKEN: ${{ inputs.github_token }}
|
|
GITHUB_EVENT_ACTION: ${{ github.event.action || '' }}
|
|
GITHUB_EVENT_LABEL_NAME: ${{ github.event.label.name || '' }}
|
|
GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number || '' }}
|
|
GITHUB_EVENT_ISSUE_BODY: ${{ github.event.issue.body || '' }}
|
|
GITHUB_EVENT_REVIEW_BODY: ${{ github.event.review.body || '' }}
|
|
GITHUB_EVENT_COMMENT_BODY: ${{ github.event.comment.body || '' }}
|