openai/codex-action

Public

mirrored from https://github.com/openai/codex-actionAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
pr1

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

action.yml

196lines · modecode

1name: "Codex Exec Action"
2description: "Run `codex exec` with a prompt."
3author: "OpenAI"
4inputs:
5 prompt:
6 description: "Prompt to pass to `codex exec`. `prompt` or `prompt_file` must be provided."
7 required: false
8 default: ""
9 prompt_file:
10 description: "Path to file that contains the prompt to pass to `codex exec`. `prompt` or `prompt_file` must be provided."
11 required: false
12 default: ""
13 openai_api_key:
14 description: "OpenAI API key used by the Codex CLI."
15 required: true
16 codex_working_directory:
17 description: "Optional working directory to `cd` into before running `codex exec`."
18 required: false
19 default: ""
20 codex_version:
21 description: "Version of `@openai/codex` to install."
22 required: false
23 default: "0.43.0-alpha.3"
24 codex_args:
25 description: "Additional args to pass through to `codex exec`. If this value starts with `[`, it will be parsed as a JSON array; otherwise, it will be parsed as a shell-like string."
26 required: false
27 default: ""
28 codex_output_file:
29 description: "File path where the Codex output should be written. Ignored if the empty string."
30 required: false
31 default: ""
32 codex_home:
33 description: "Directory to use as the Codex home directory. If empty, the default Codex home directory will be used."
34 required: false
35 default: ""
36 safety_strategy:
37 description: |
38 Specify one of the following options (on Windows, the only supported option is `unsafe`):
39
40 * `drop_sudo` (default, IRREVERSIBLE) Drop sudo privileges (if any) from
41 the default user before running Codex, and run Codex as that user. This
42 is only supported on Linux and macOS runners. This option is
43 irreversible: if the default user has sudo privileges, they will be
44 removed permanently for the duration of the job.
45 * `unprivileged_user` Run Codex as the specified user specified by the
46 `codex_user` option (the user must already exist). Note the caller is
47 responsible for ensuring the specified user has the privileges it needs
48 to perform the requested actions. For example, the copy of the repo
49 created by `actions/checkout` is not world-readable by default.
50 * `read_only` Run Codex in a sandbox that can read any file on disk,
51 but cannot write to disk or access the network. Note Codex will still
52 run as the default user for this Action, which likely has sudo
53 privileges, so it could read `openai_api_key` from memory and reveal it
54 by printing it to the output of the GitHub Action.
55 * `unsafe` (NOT RECOMMENDED) Do not try to restrict Codex's privileges at all.
56 This is extremely dangerous, as the default user for this Action likely
57 has sudo privileges, which means it can read secrets stored in memory
58 (such as the value of `openai_api_key`) and print them to the output
59 of the GitHub Action or exfiltrate them in other ways.
60 required: false
61 default: "drop_sudo"
62 codex_user:
63 description: "If `safety_strategy` is set to `unprivileged_user`, this specifies the UNIX username to run Codex as."
64 required: false
65 default: ""
66 require_repo_write:
67 description: "Whether to require the triggering actor to have write access to the repository before running."
68 required: false
69 default: "true"
70 allow_bots:
71 description: "Allow runs triggered by GitHub Apps/bot accounts to bypass the write-access check."
72 required: false
73 default: "false"
74outputs:
75 final_message:
76 description: "Raw output emitted by `codex exec`."
77 value: ${{ steps.run_codex.outputs.final_message }}
78runs:
79 using: "composite"
80 steps:
81 - name: Validate Windows safety strategy
82 if: ${{ runner.os == 'Windows' }}
83 shell: bash
84 run: |
85 if [ "${{ inputs.safety_strategy }}" != "unsafe" ]; then
86 echo "On Windows, inputs.safety_strategy must be 'unsafe'" >&2
87 echo "because no viable sandboxing options are available at this time." >&2
88 exit 1
89 fi
90
91 - name: Ensure Node.js available
92 uses: actions/setup-node@v4
93 with:
94 node-version: "20"
95
96 - name: Check repository write access
97 if: ${{ inputs.require_repo_write == 'true' }}
98 env:
99 ALLOW_BOTS: ${{ inputs.allow_bots }}
100 GITHUB_TOKEN: ${{ github.token }}
101 shell: bash
102 run: |
103 node "${{ github.action_path }}/dist/main.js" check-write-access --allow-bots "$ALLOW_BOTS"
104
105 - name: Install Codex CLI
106 shell: bash
107 run: npm install -g "@openai/codex@${{ inputs.codex_version }}"
108
109 - name: Install Codex Responses API proxy
110 shell: bash
111 run: npm install -g "@openai/codex-responses-api-proxy@${{ inputs.codex_version }}"
112
113 - name: Start Responses API proxy
114 id: start_proxy
115 env:
116 OPENAI_API_KEY: ${{ inputs.openai_api_key }}
117 shell: bash
118 run: |
119 tmpfile=$(mktemp)
120 (
121 printenv OPENAI_API_KEY | codex-responses-api-proxy --http-shutdown --server-info "$tmpfile"
122 ) &
123 for _ in {1..10}; do
124 if [ -s "$tmpfile" ]; then
125 break
126 fi
127 sleep 1
128 done
129 if [ ! -s "$tmpfile" ]; then
130 echo "responses-api-proxy did not write server info" >&2
131 exit 1
132 fi
133 echo "server_info_file=$tmpfile" >> "$GITHUB_OUTPUT"
134
135 # This step has an output named `port`.
136 - name: Read server info
137 id: read_server_info
138 shell: bash
139 run: node "${{ github.action_path }}/dist/main.js" read-server-info "${{ steps.start_proxy.outputs.server_info_file }}"
140
141 - name: Drop sudo privilege, if appropriate
142 if: ${{ inputs.safety_strategy == 'drop_sudo' }}
143 shell: bash
144 run: |
145 case "${RUNNER_OS}" in
146 Linux)
147 node "${{ github.action_path }}/dist/main.js" drop-sudo --user runner --group sudo
148 ;;
149 macOS)
150 node "${{ github.action_path }}/dist/main.js" drop-sudo --user runner --group admin
151 ;;
152 *)
153 echo "Unsupported OS for drop_sudo: ${RUNNER_OS}" >&2
154 exit 1
155 ;;
156 esac
157
158 - name: Verify sudo privilege removed
159 if: ${{ inputs.safety_strategy == 'drop_sudo' }}
160 shell: bash
161 run: |
162 if sudo -n true 2>/dev/null; then
163 echo "Expected sudo to be disabled, but sudo succeeded." >&2
164 exit 1
165 fi
166 echo "Confirmed sudo privilege is disabled."
167
168 - name: Run codex exec
169 id: run_codex
170 env:
171 CODEX_PROMPT: ${{ inputs.prompt }}
172 CODEX_PROMPT_FILE: ${{ inputs.prompt_file }}
173 CODEX_HOME: ${{ inputs.codex_home }}
174 CODEX_WORKING_DIRECTORY: ${{ inputs.codex_working_directory || github.workspace }}
175 CODEX_ARGS: ${{ inputs.codex_args }}
176 CODEX_OUTPUT_FILE: ${{ inputs.codex_output_file }}
177 CODEX_SAFETY_STRATEGY: ${{ inputs.safety_strategy }}
178 CODEX_USER: ${{ inputs.codex_user }}
179 shell: bash
180 run: |
181 node "${{ github.action_path }}/dist/main.js" run-codex-exec \
182 --prompt "${CODEX_PROMPT}" \
183 --prompt-file "${CODEX_PROMPT_FILE}" \
184 --codex-home "$CODEX_HOME" \
185 --cd "$CODEX_WORKING_DIRECTORY" \
186 --proxy-port "${{ steps.read_server_info.outputs.port }}" \
187 --extra-args "$CODEX_ARGS" \
188 --output-file "$CODEX_OUTPUT_FILE" \
189 --safety-strategy "$CODEX_SAFETY_STRATEGY" \
190 --codex-user "$CODEX_USER"
191
192 - name: Shutdown codex webserver
193 env:
194 CODEX_SERVER_PORT: ${{ steps.read_server_info.outputs.port }}
195 shell: bash
196 run: curl --fail --silent --show-error "http://127.0.0.1:${CODEX_SERVER_PORT}/shutdown"
197