Skip to content

Smoke Codex

Smoke Codex #2622

# ___ _ _
# / _ \ | | (_)
# | |_| | __ _ ___ _ __ | |_ _ ___
# | _ |/ _` |/ _ \ '_ \| __| |/ __|
# | | | | (_| | __/ | | | |_| | (__
# \_| |_/\__, |\___|_| |_|\__|_|\___|
# __/ |
# _ _ |___/
# | | | | / _| |
# | | | | ___ _ __ _ __| |_| | _____ ____
# | |/\| |/ _ \ '__| |/ /| _| |/ _ \ \ /\ / / ___|
# \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \
# \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/
#
# This file was automatically generated by gh-aw. DO NOT EDIT.
#
# To update this file, edit the corresponding .md file and run:
# gh aw compile
# Not all edits will cause changes to this file.
#
# For more information: https://github.github.com/gh-aw/introduction/overview/
#
# Smoke test workflow that validates Codex engine functionality by reviewing recent PRs twice daily
#
# Resolved workflow manifest:
# Imports:
# - shared/gh.md
# - shared/mcp/serena-go.md
# - shared/mcp/serena.md
# - shared/qmd.md
# - shared/reporting.md
#
# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"06451e0a825e8159b30a37bce567f63fb0e4e4c6f49a7e61578822b85109b12b","agent_id":"codex"}
name: "Smoke Codex"
"on":
pull_request:
# names: # Label filtering applied via job conditions
# - smoke # Label filtering applied via job conditions
types:
- labeled
schedule:
- cron: "45 */12 * * *"
workflow_dispatch:
inputs:
aw_context:
default: ""
description: Agent caller context (used internally by Agentic Workflows).
required: false
type: string
permissions: {}
concurrency:
group: "gh-aw-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref || github.run_id }}"
cancel-in-progress: true
run-name: "Smoke Codex"
jobs:
activation:
needs: pre_activation
if: >
needs.pre_activation.outputs.activated == 'true' && ((github.event_name != 'pull_request' || github.event.pull_request.head.repo.id == github.repository_id) &&
(github.event_name != 'pull_request' || github.event.action != 'labeled' || github.event.label.name == 'smoke'))
runs-on: ubuntu-slim
permissions:
contents: read
discussions: write
issues: write
pull-requests: write
outputs:
body: ${{ steps.sanitized.outputs.body }}
comment_id: ${{ steps.add-comment.outputs.comment-id }}
comment_repo: ${{ steps.add-comment.outputs.comment-repo }}
comment_url: ${{ steps.add-comment.outputs.comment-url }}
lockdown_check_failed: ${{ steps.generate_aw_info.outputs.lockdown_check_failed == 'true' }}
model: ${{ steps.generate_aw_info.outputs.model }}
secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }}
text: ${{ steps.sanitized.outputs.text }}
title: ${{ steps.sanitized.outputs.title }}
steps:
- name: Checkout actions folder
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
repository: github/gh-aw
sparse-checkout: |
actions
persist-credentials: false
- name: Setup Scripts
uses: ./actions/setup
with:
destination: ${{ runner.temp }}/gh-aw/actions
- name: Generate agentic run info
id: generate_aw_info
env:
GH_AW_INFO_ENGINE_ID: "codex"
GH_AW_INFO_ENGINE_NAME: "Codex"
GH_AW_INFO_MODEL: ${{ vars.GH_AW_MODEL_AGENT_CODEX || 'auto' }}
GH_AW_INFO_VERSION: "latest"
GH_AW_INFO_AGENT_VERSION: "latest"
GH_AW_INFO_WORKFLOW_NAME: "Smoke Codex"
GH_AW_INFO_EXPERIMENTAL: "false"
GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true"
GH_AW_INFO_STAGED: "false"
GH_AW_INFO_ALLOWED_DOMAINS: '["defaults","github","playwright"]'
GH_AW_INFO_FIREWALL_ENABLED: "true"
GH_AW_INFO_AWF_VERSION: "v0.25.13"
GH_AW_INFO_AWMG_VERSION: ""
GH_AW_INFO_FIREWALL_TYPE: "squid"
GH_AW_COMPILED_STRICT: "false"
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
with:
script: |
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
setupGlobals(core, github, context, exec, io);
const { main } = require('${{ runner.temp }}/gh-aw/actions/generate_aw_info.cjs');
await main(core, context);
- name: Add hooray reaction for immediate feedback
id: react
if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || github.event_name == 'pull_request' && github.event.pull_request.head.repo.id == github.repository_id
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
env:
GH_AW_REACTION: "hooray"
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
setupGlobals(core, github, context, exec, io);
const { main } = require('${{ runner.temp }}/gh-aw/actions/add_reaction.cjs');
await main();
- name: Validate CODEX_API_KEY or OPENAI_API_KEY secret
id: validate-secret
run: ${RUNNER_TEMP}/gh-aw/actions/validate_multi_secret.sh CODEX_API_KEY OPENAI_API_KEY Codex https://github.github.com/gh-aw/reference/engines/#openai-codex
env:
CODEX_API_KEY: ${{ secrets.CODEX_API_KEY }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
- name: Checkout .github and .agents folders
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
sparse-checkout: |
.github
.agents
actions/setup
sparse-checkout-cone-mode: true
fetch-depth: 1
- name: Check workflow lock file
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
env:
GH_AW_WORKFLOW_FILE: "smoke-codex.lock.yml"
GH_AW_CONTEXT_WORKFLOW_REF: "${{ github.workflow_ref }}"
with:
script: |
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
setupGlobals(core, github, context, exec, io);
const { main } = require('${{ runner.temp }}/gh-aw/actions/check_workflow_timestamp_api.cjs');
await main();
- name: Compute current body text
id: sanitized
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
with:
script: |
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
setupGlobals(core, github, context, exec, io);
const { main } = require('${{ runner.temp }}/gh-aw/actions/compute_text.cjs');
await main();
- name: Add comment with workflow run link
id: add-comment
if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || github.event_name == 'pull_request' && github.event.pull_request.head.repo.id == github.repository_id
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
env:
GH_AW_WORKFLOW_NAME: "Smoke Codex"
GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"\\u003e 🔮 *The oracle has spoken through [{workflow_name}]({run_url})*{effective_tokens_suffix}{history_link}\",\"runStarted\":\"🔮 The ancient spirits stir... [{workflow_name}]({run_url}) awakens to divine this {event_type}...\",\"runSuccess\":\"✨ The prophecy is fulfilled... [{workflow_name}]({run_url}) has completed its mystical journey. The stars align. 🌟\",\"runFailure\":\"🌑 The shadows whisper... [{workflow_name}]({run_url}) {status}. The oracle requires further meditation...\"}"
with:
script: |
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
setupGlobals(core, github, context, exec, io);
const { main } = require('${{ runner.temp }}/gh-aw/actions/add_workflow_run_comment.cjs');
await main();
- name: Create prompt with built-in context
env:
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ runner.temp }}/gh-aw/safeoutputs/outputs.jsonl
GH_AW_GITHUB_ACTOR: ${{ github.actor }}
GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }}
GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }}
GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }}
GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }}
GH_AW_GITHUB_REPOSITORY: ${{ github.repository }}
GH_AW_GITHUB_RUN_ID: ${{ github.run_id }}
GH_AW_GITHUB_SERVER_URL: ${{ github.server_url }}
GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }}
# poutine:ignore untrusted_checkout_exec
run: |
bash ${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh
{
cat << 'GH_AW_PROMPT_119ad86e92d10934_EOF'
<system>
GH_AW_PROMPT_119ad86e92d10934_EOF
cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md"
cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md"
cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md"
cat "${RUNNER_TEMP}/gh-aw/prompts/playwright_prompt.md"
cat "${RUNNER_TEMP}/gh-aw/prompts/qmd_prompt.md"
cat "${RUNNER_TEMP}/gh-aw/prompts/cache_memory_prompt.md"
cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md"
cat << 'GH_AW_PROMPT_119ad86e92d10934_EOF'
<safe-output-tools>
Tools: add_comment(max:2), create_issue, add_labels, remove_labels, unassign_from_user, hide_comment(max:5), missing_tool, missing_data, noop, add_smoked_label
</safe-output-tools>
<github-context>
The following GitHub context information is available for this workflow:
{{#if __GH_AW_GITHUB_ACTOR__ }}
- **actor**: __GH_AW_GITHUB_ACTOR__
{{/if}}
{{#if __GH_AW_GITHUB_REPOSITORY__ }}
- **repository**: __GH_AW_GITHUB_REPOSITORY__
{{/if}}
{{#if __GH_AW_GITHUB_WORKSPACE__ }}
- **workspace**: __GH_AW_GITHUB_WORKSPACE__
{{/if}}
{{#if __GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ }}
- **issue-number**: #__GH_AW_GITHUB_EVENT_ISSUE_NUMBER__
{{/if}}
{{#if __GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ }}
- **discussion-number**: #__GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__
{{/if}}
{{#if __GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ }}
- **pull-request-number**: #__GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__
{{/if}}
{{#if __GH_AW_GITHUB_EVENT_COMMENT_ID__ }}
- **comment-id**: __GH_AW_GITHUB_EVENT_COMMENT_ID__
{{/if}}
{{#if __GH_AW_GITHUB_RUN_ID__ }}
- **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__
{{/if}}
- **checkouts**: The following repositories have been checked out and are available in the workspace:
- `$GITHUB_WORKSPACE` → `__GH_AW_GITHUB_REPOSITORY__` (cwd) (**current** - this is the repository you are working on; use this as the target for all GitHub operations unless otherwise specified) [shallow clone, fetch-depth=2]
- **Note**: If a branch you need is not in the list above and is not listed as an additional fetched ref, it has NOT been checked out. For private repositories you cannot fetch it without proper authentication. If the branch is required and not available, exit with an error and ask the user to add it to the `fetch:` option of the `checkout:` configuration (e.g., `fetch: ["refs/pulls/open/*"]` for all open PR refs, or `fetch: ["main", "feature/my-branch"]` for specific branches).
</github-context>
GH_AW_PROMPT_119ad86e92d10934_EOF
cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md"
cat << 'GH_AW_PROMPT_119ad86e92d10934_EOF'
</system>
<qmd>
Use the `search` tool to find relevant documentation and content with a natural language request — it queries a local vector database built from the configured collections.
**Always use `search` first** when you need to find, verify, or look up information:
- **Before using `find` or `bash` to list files** — use `search` to discover the most relevant content
- **Before writing new content** — search first to check whether similar content already exists
- **When identifying relevant files** — use it to narrow down which files cover a feature or concept
- **When understanding a term or concept** — query to find authoritative documentation
**Usage tips:**
- Use descriptive, natural language queries: e.g., `"how to configure MCP servers"` or `"safe-outputs create-pull-request options"` or `"permissions frontmatter field"`
- Always read the returned file paths to get the full content — `search` returns paths only, not content
- Combine multiple targeted queries rather than one broad query for better coverage
</qmd>
## Serena Code Analysis
The Serena MCP server is configured for **["go"]** analysis in this workspace:
- **Workspace**: `__GH_AW_GITHUB_WORKSPACE__`
- **Memory**: `/tmp/gh-aw/cache-memory/serena/`
### Project Activation
Before analyzing code, activate the Serena project:
```
Tool: activate_project
Args: { "path": "__GH_AW_GITHUB_WORKSPACE__" }
```
### Available Capabilities
Serena provides IDE-grade Language Server Protocol (LSP) tools including:
- **Symbol search**: `find_symbol` — locate functions, types, interfaces by name
- **Navigation**: `find_referencing_symbols` — find all callers/usages of a symbol
- **Type info**: `get_symbol_documentation` — hover-level type and doc information
- **Code editing**: `replace_symbol_body`, `insert_after_symbol` — symbol-level edits
- **Diagnostics**: `get_diagnostics` — compiler errors and linter warnings
### Analysis Guidelines
1. **Use semantic tools over text search** — prefer Serena's LSP tools over `grep`
2. **Activate project first** — always call `activate_project` before other tools
3. **Cross-reference findings** — validate with multiple tools for accuracy
4. **Focus on the relevant language files** — ignore unrelated file types
{{#runtime-import .github/workflows/shared/gh.md}}
{{#runtime-import .github/workflows/shared/reporting.md}}
{{#runtime-import .github/workflows/shared/mcp/serena-go.md}}
{{#runtime-import .github/workflows/smoke-codex.md}}
GH_AW_PROMPT_119ad86e92d10934_EOF
} > "$GH_AW_PROMPT"
- name: Interpolate variables and render templates
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
env:
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }}
GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }}
GH_AW_GITHUB_REPOSITORY: ${{ github.repository }}
GH_AW_GITHUB_RUN_ID: ${{ github.run_id }}
GH_AW_GITHUB_SERVER_URL: ${{ github.server_url }}
with:
script: |
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
setupGlobals(core, github, context, exec, io);
const { main } = require('${{ runner.temp }}/gh-aw/actions/interpolate_prompt.cjs');
await main();
- name: Substitute placeholders
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
env:
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_ALLOWED_EXTENSIONS: ''
GH_AW_CACHE_DESCRIPTION: ''
GH_AW_CACHE_DIR: '/tmp/gh-aw/cache-memory/'
GH_AW_GITHUB_ACTOR: ${{ github.actor }}
GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }}
GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }}
GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }}
GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }}
GH_AW_GITHUB_REPOSITORY: ${{ github.repository }}
GH_AW_GITHUB_RUN_ID: ${{ github.run_id }}
GH_AW_GITHUB_SERVER_URL: ${{ github.server_url }}
GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }}
GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: ${{ needs.pre_activation.outputs.activated }}
with:
script: |
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
setupGlobals(core, github, context, exec, io);
const substitutePlaceholders = require('${{ runner.temp }}/gh-aw/actions/substitute_placeholders.cjs');
// Call the substitution function
return await substitutePlaceholders({
file: process.env.GH_AW_PROMPT,
substitutions: {
GH_AW_ALLOWED_EXTENSIONS: process.env.GH_AW_ALLOWED_EXTENSIONS,
GH_AW_CACHE_DESCRIPTION: process.env.GH_AW_CACHE_DESCRIPTION,
GH_AW_CACHE_DIR: process.env.GH_AW_CACHE_DIR,
GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR,
GH_AW_GITHUB_EVENT_COMMENT_ID: process.env.GH_AW_GITHUB_EVENT_COMMENT_ID,
GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: process.env.GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER,
GH_AW_GITHUB_EVENT_ISSUE_NUMBER: process.env.GH_AW_GITHUB_EVENT_ISSUE_NUMBER,
GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: process.env.GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER,
GH_AW_GITHUB_REPOSITORY: process.env.GH_AW_GITHUB_REPOSITORY,
GH_AW_GITHUB_RUN_ID: process.env.GH_AW_GITHUB_RUN_ID,
GH_AW_GITHUB_SERVER_URL: process.env.GH_AW_GITHUB_SERVER_URL,
GH_AW_GITHUB_WORKSPACE: process.env.GH_AW_GITHUB_WORKSPACE,
GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: process.env.GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED
}
});
- name: Validate prompt placeholders
env:
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
# poutine:ignore untrusted_checkout_exec
run: bash ${RUNNER_TEMP}/gh-aw/actions/validate_prompt_placeholders.sh
- name: Print prompt
env:
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
# poutine:ignore untrusted_checkout_exec
run: bash ${RUNNER_TEMP}/gh-aw/actions/print_prompt_summary.sh
- name: Upload activation artifact
if: success()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
with:
name: activation
path: |
/tmp/gh-aw/aw_info.json
/tmp/gh-aw/aw-prompts/prompt.txt
retention-days: 1
agent:
needs:
- activation
- indexing
runs-on: ubuntu-latest
permissions:
contents: read
issues: read
pull-requests: read
env:
DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
GH_AW_ASSETS_ALLOWED_EXTS: ""
GH_AW_ASSETS_BRANCH: ""
GH_AW_ASSETS_MAX_SIZE_KB: 0
GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs
GH_AW_WORKFLOW_ID_SANITIZED: smokecodex
outputs:
checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }}
effective_tokens: ${{ steps.parse-mcp-gateway.outputs.effective_tokens }}
has_patch: ${{ steps.collect_output.outputs.has_patch }}
model: ${{ needs.activation.outputs.model }}
output: ${{ steps.collect_output.outputs.output }}
output_types: ${{ steps.collect_output.outputs.output_types }}
steps:
- name: Checkout actions folder
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
repository: github/gh-aw
sparse-checkout: |
actions
persist-credentials: false
- name: Setup Scripts
uses: ./actions/setup
with:
destination: ${{ runner.temp }}/gh-aw/actions
- name: Set runtime paths
id: set-runtime-paths
run: |
echo "GH_AW_SAFE_OUTPUTS=${RUNNER_TEMP}/gh-aw/safeoutputs/outputs.jsonl" >> "$GITHUB_OUTPUT"
echo "GH_AW_SAFE_OUTPUTS_CONFIG_PATH=${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" >> "$GITHUB_OUTPUT"
echo "GH_AW_SAFE_OUTPUTS_TOOLS_PATH=${RUNNER_TEMP}/gh-aw/safeoutputs/tools.json" >> "$GITHUB_OUTPUT"
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
fetch-depth: 2
- name: Setup Go
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
with:
go-version: '1.25'
cache: false
- name: Capture GOROOT for AWF chroot mode
run: echo "GOROOT=$(go env GOROOT)" >> "$GITHUB_ENV"
- name: Create gh-aw temp directory
run: bash ${RUNNER_TEMP}/gh-aw/actions/create_gh_aw_tmp_dir.sh
- name: Configure gh CLI for GitHub Enterprise
run: bash ${RUNNER_TEMP}/gh-aw/actions/configure_gh_for_ghe.sh
env:
GH_TOKEN: ${{ github.token }}
# Cache memory file share configuration from frontmatter processed below
- name: Create cache-memory directory
run: bash ${RUNNER_TEMP}/gh-aw/actions/create_cache_memory_dir.sh
- name: Restore cache-memory file share data
uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
with:
key: memory-none-nopolicy-${{ env.GH_AW_WORKFLOW_ID_SANITIZED }}-${{ github.run_id }}
path: /tmp/gh-aw/cache-memory
restore-keys: |
memory-none-nopolicy-${{ env.GH_AW_WORKFLOW_ID_SANITIZED }}-
- name: Setup cache-memory git repository
env:
GH_AW_CACHE_DIR: /tmp/gh-aw/cache-memory
GH_AW_MIN_INTEGRITY: none
run: bash ${RUNNER_TEMP}/gh-aw/actions/setup_cache_memory_git.sh
- name: Configure Git credentials
env:
REPO_NAME: ${{ github.repository }}
SERVER_URL: ${{ github.server_url }}
run: |
git config --global user.email "github-actions[bot]@users.noreply.github.com"
git config --global user.name "github-actions[bot]"
git config --global am.keepcr true
# Re-authenticate git with GitHub token
SERVER_URL_STRIPPED="${SERVER_URL#https://}"
git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git"
echo "Git configured with standard GitHub Actions identity"
- name: Checkout PR branch
id: checkout-pr
if: |
github.event.pull_request || github.event.issue.pull_request
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
env:
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
with:
github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
script: |
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
setupGlobals(core, github, context, exec, io);
const { main } = require('${{ runner.temp }}/gh-aw/actions/checkout_pr_branch.cjs');
await main();
- name: Setup Node.js
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: '24'
package-manager-cache: false
- name: Install Codex CLI
run: npm install -g @openai/codex@latest
- name: Install AWF binary
run: bash ${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh v0.25.13
- name: Restore qmd index from cache
uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
with:
key: gh-aw-qmd-2.0.1-${{ github.run_id }}
path: /tmp/gh-aw/qmd-index/
- name: Restore qmd models from cache
uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
with:
path: ~/.cache/qmd/models/
key: qmd-models-2.0.1-${{ runner.os }}
- name: Determine automatic lockdown mode for GitHub MCP Server
id: determine-automatic-lockdown
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
env:
GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }}
GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }}
with:
script: |
const determineAutomaticLockdown = require('${{ runner.temp }}/gh-aw/actions/determine_automatic_lockdown.cjs');
await determineAutomaticLockdown(github, context, core);
- name: Download container images
run: bash ${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh ghcr.io/github/gh-aw-firewall/agent:0.25.13 ghcr.io/github/gh-aw-firewall/api-proxy:0.25.13 ghcr.io/github/gh-aw-firewall/squid:0.25.13 ghcr.io/github/gh-aw-mcpg:v0.2.12 ghcr.io/github/github-mcp-server:v0.32.0 ghcr.io/github/serena-mcp-server:latest mcr.microsoft.com/playwright/mcp node:lts-alpine
- name: Write Safe Outputs Config
run: |
mkdir -p ${RUNNER_TEMP}/gh-aw/safeoutputs
mkdir -p /tmp/gh-aw/safeoutputs
mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs
cat > ${RUNNER_TEMP}/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_50edf469cc655054_EOF'
{"add_comment":{"hide_older_comments":true,"max":2},"add_labels":{"allowed":["smoke-codex"]},"create_issue":{"close_older_issues":true,"close_older_key":"smoke-codex","expires":2,"labels":["automation","testing"],"max":1},"hide_comment":{"max":5},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"remove_labels":{"allowed":["smoke"]},"unassign_from_user":{"allowed":["githubactionagent"],"max":1}}
GH_AW_SAFE_OUTPUTS_CONFIG_50edf469cc655054_EOF
- name: Write Safe Outputs Tools
run: |
cat > ${RUNNER_TEMP}/gh-aw/safeoutputs/tools_meta.json << 'GH_AW_SAFE_OUTPUTS_TOOLS_META_49d024a692caf8ad_EOF'
{
"description_suffixes": {
"add_comment": " CONSTRAINTS: Maximum 2 comment(s) can be added.",
"add_labels": " CONSTRAINTS: Only these labels are allowed: [\"smoke-codex\"].",
"create_issue": " CONSTRAINTS: Maximum 1 issue(s) can be created. Labels [\"automation\" \"testing\"] will be automatically added.",
"remove_labels": " CONSTRAINTS: Only these labels can be removed: [smoke]."
},
"repo_params": {},
"dynamic_tools": [
{
"description": "Add the 'smoked' label to the current pull request (can only be called once)",
"inputSchema": {
"additionalProperties": false,
"properties": {
"labels": {
"description": "The labels' name to be added. Must be separated with line breaks if there're multiple labels.",
"type": "string"
},
"number": {
"description": "The number of the issue or pull request.",
"type": "string"
}
},
"required": [
"labels"
],
"type": "object"
},
"name": "add_smoked_label"
}
]
}
GH_AW_SAFE_OUTPUTS_TOOLS_META_49d024a692caf8ad_EOF
cat > ${RUNNER_TEMP}/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_f1befde6ad6a3154_EOF'
{
"add_comment": {
"defaultMax": 1,
"fields": {
"body": {
"required": true,
"type": "string",
"sanitize": true,
"maxLength": 65000
},
"item_number": {
"issueOrPRNumber": true
},
"repo": {
"type": "string",
"maxLength": 256
}
}
},
"add_labels": {
"defaultMax": 5,
"fields": {
"item_number": {
"issueNumberOrTemporaryId": true
},
"labels": {
"required": true,
"type": "array",
"itemType": "string",
"itemSanitize": true,
"itemMaxLength": 128
},
"repo": {
"type": "string",
"maxLength": 256
}
}
},
"create_issue": {
"defaultMax": 1,
"fields": {
"body": {
"required": true,
"type": "string",
"sanitize": true,
"maxLength": 65000
},
"labels": {
"type": "array",
"itemType": "string",
"itemSanitize": true,
"itemMaxLength": 128
},
"parent": {
"issueOrPRNumber": true
},
"repo": {
"type": "string",
"maxLength": 256
},
"temporary_id": {
"type": "string"
},
"title": {
"required": true,
"type": "string",
"sanitize": true,
"maxLength": 128
}
}
},
"hide_comment": {
"defaultMax": 5,
"fields": {
"comment_id": {
"required": true,
"type": "string",
"maxLength": 256
},
"reason": {
"type": "string",
"enum": [
"SPAM",
"ABUSE",
"OFF_TOPIC",
"OUTDATED",
"RESOLVED"
]
},
"repo": {
"type": "string",
"maxLength": 256
}
}
},
"missing_data": {
"defaultMax": 20,
"fields": {
"alternatives": {
"type": "string",
"sanitize": true,
"maxLength": 256
},
"context": {
"type": "string",
"sanitize": true,
"maxLength": 256
},
"data_type": {
"type": "string",
"sanitize": true,
"maxLength": 128
},
"reason": {
"type": "string",
"sanitize": true,
"maxLength": 256
}
}
},
"missing_tool": {
"defaultMax": 20,
"fields": {
"alternatives": {
"type": "string",
"sanitize": true,
"maxLength": 512
},
"reason": {
"required": true,
"type": "string",
"sanitize": true,
"maxLength": 256
},
"tool": {
"type": "string",
"sanitize": true,
"maxLength": 128
}
}
},
"noop": {
"defaultMax": 1,
"fields": {
"message": {
"required": true,
"type": "string",
"sanitize": true,
"maxLength": 65000
}
}
},
"remove_labels": {
"defaultMax": 5,
"fields": {
"item_number": {
"issueNumberOrTemporaryId": true
},
"labels": {
"required": true,
"type": "array",
"itemType": "string",
"itemSanitize": true,
"itemMaxLength": 128
},
"repo": {
"type": "string",
"maxLength": 256
}
}
},
"unassign_from_user": {
"defaultMax": 1,
"fields": {
"assignee": {
"type": "string",
"sanitize": true,
"maxLength": 39
},
"assignees": {
"type": "array",
"itemType": "string",
"itemSanitize": true,
"itemMaxLength": 39
},
"issue_number": {
"issueOrPRNumber": true
},
"repo": {
"type": "string",
"maxLength": 256
}
}
}
}
GH_AW_SAFE_OUTPUTS_VALIDATION_f1befde6ad6a3154_EOF
node ${RUNNER_TEMP}/gh-aw/actions/generate_safe_outputs_tools.cjs
- name: Generate Safe Outputs MCP Server Config
id: safe-outputs-config
run: |
# Generate a secure random API key (360 bits of entropy, 40+ chars)
# Mask immediately to prevent timing vulnerabilities
API_KEY=$(openssl rand -base64 45 | tr -d '/+=')
echo "::add-mask::${API_KEY}"
PORT=3001
# Set outputs for next steps
{
echo "safe_outputs_api_key=${API_KEY}"
echo "safe_outputs_port=${PORT}"
} >> "$GITHUB_OUTPUT"
echo "Safe Outputs MCP server will run on port ${PORT}"
- name: Start Safe Outputs MCP HTTP Server
id: safe-outputs-start
env:
DEBUG: '*'
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-config.outputs.safe_outputs_port }}
GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-config.outputs.safe_outputs_api_key }}
GH_AW_SAFE_OUTPUTS_TOOLS_PATH: ${{ runner.temp }}/gh-aw/safeoutputs/tools.json
GH_AW_SAFE_OUTPUTS_CONFIG_PATH: ${{ runner.temp }}/gh-aw/safeoutputs/config.json
GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs
run: |
# Environment variables are set above to prevent template injection
export DEBUG
export GH_AW_SAFE_OUTPUTS
export GH_AW_SAFE_OUTPUTS_PORT
export GH_AW_SAFE_OUTPUTS_API_KEY
export GH_AW_SAFE_OUTPUTS_TOOLS_PATH
export GH_AW_SAFE_OUTPUTS_CONFIG_PATH
export GH_AW_MCP_LOG_DIR
bash ${RUNNER_TEMP}/gh-aw/actions/start_safe_outputs_server.sh
- name: Setup MCP Scripts Config
run: |
mkdir -p ${RUNNER_TEMP}/gh-aw/mcp-scripts/logs
cat > ${RUNNER_TEMP}/gh-aw/mcp-scripts/tools.json << 'GH_AW_MCP_SCRIPTS_TOOLS_8fc2797d26cb4918_EOF'
{
"serverName": "mcpscripts",
"version": "1.0.0",
"logDir": "${RUNNER_TEMP}/gh-aw/mcp-scripts/logs",
"tools": [
{
"name": "gh",
"description": "Execute any gh CLI command. This tool is accessible as 'mcpscripts-gh'. Provide the full command after 'gh' (e.g., args: 'pr list --limit 5'). The tool will run: gh \u003cargs\u003e. Use single quotes ' for complex args to avoid shell interpretation issues.",
"inputSchema": {
"properties": {
"args": {
"description": "Arguments to pass to gh CLI (without the 'gh' prefix). Examples: 'pr list --limit 5', 'issue view 123', 'api repos/{owner}/{repo}'",
"type": "string"
}
},
"required": [
"args"
],
"type": "object"
},
"handler": "gh.sh",
"env": {
"GH_AW_GH_TOKEN": "GH_AW_GH_TOKEN",
"GH_DEBUG": "GH_DEBUG"
},
"timeout": 60
}
]
}
GH_AW_MCP_SCRIPTS_TOOLS_8fc2797d26cb4918_EOF
cat > ${RUNNER_TEMP}/gh-aw/mcp-scripts/mcp-server.cjs << 'GH_AW_MCP_SCRIPTS_SERVER_9cd03b7817afbd8c_EOF'
const path = require("path");
const { startHttpServer } = require("./mcp_scripts_mcp_server_http.cjs");
const configPath = path.join(__dirname, "tools.json");
const port = parseInt(process.env.GH_AW_MCP_SCRIPTS_PORT || "3000", 10);
const apiKey = process.env.GH_AW_MCP_SCRIPTS_API_KEY || "";
startHttpServer(configPath, {
port: port,
stateless: true,
logDir: "${RUNNER_TEMP}/gh-aw/mcp-scripts/logs"
}).catch(error => {
console.error("Failed to start mcp-scripts HTTP server:", error);
process.exit(1);
});
GH_AW_MCP_SCRIPTS_SERVER_9cd03b7817afbd8c_EOF
chmod +x ${RUNNER_TEMP}/gh-aw/mcp-scripts/mcp-server.cjs
- name: Setup MCP Scripts Tool Files
run: |
cat > ${RUNNER_TEMP}/gh-aw/mcp-scripts/gh.sh << 'GH_AW_MCP_SCRIPTS_SH_GH_275beea46129d17f_EOF'
#!/bin/bash
# Auto-generated mcp-script tool: gh
# Execute any gh CLI command. This tool is accessible as 'mcpscripts-gh'. Provide the full command after 'gh' (e.g., args: 'pr list --limit 5'). The tool will run: gh <args>. Use single quotes ' for complex args to avoid shell interpretation issues.
set -euo pipefail
echo "gh $INPUT_ARGS"
echo " token: ${GH_AW_GH_TOKEN:0:6}..."
GH_TOKEN="$GH_AW_GH_TOKEN" gh $INPUT_ARGS
GH_AW_MCP_SCRIPTS_SH_GH_275beea46129d17f_EOF
chmod +x ${RUNNER_TEMP}/gh-aw/mcp-scripts/gh.sh
- name: Generate MCP Scripts Server Config
id: mcp-scripts-config
run: |
# Generate a secure random API key (360 bits of entropy, 40+ chars)
# Mask immediately to prevent timing vulnerabilities
API_KEY=$(openssl rand -base64 45 | tr -d '/+=')
echo "::add-mask::${API_KEY}"
PORT=3000
# Set outputs for next steps
{
echo "mcp_scripts_api_key=${API_KEY}"
echo "mcp_scripts_port=${PORT}"
} >> "$GITHUB_OUTPUT"
echo "MCP Scripts server will run on port ${PORT}"
- name: Start MCP Scripts HTTP Server
id: mcp-scripts-start
env:
DEBUG: '*'
GH_AW_MCP_SCRIPTS_PORT: ${{ steps.mcp-scripts-config.outputs.mcp_scripts_port }}
GH_AW_MCP_SCRIPTS_API_KEY: ${{ steps.mcp-scripts-config.outputs.mcp_scripts_api_key }}
GH_AW_GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_DEBUG: 1
run: |
# Environment variables are set above to prevent template injection
export DEBUG
export GH_AW_MCP_SCRIPTS_PORT
export GH_AW_MCP_SCRIPTS_API_KEY
bash ${RUNNER_TEMP}/gh-aw/actions/start_mcp_scripts_server.sh
- name: Setup Node.js for qmd MCP server
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: "24"
- name: Start qmd MCP Server
id: qmd-mcp-start
env:
INDEX_PATH: /tmp/gh-aw/qmd-index/index.sqlite
NO_COLOR: '1'
NODE_LLAMA_CPP_GPU: 'false'
run: |
# Start qmd MCP server natively in HTTP mode.
# qmd must run on the host VM (not in Docker) because node-llama-cpp
# requires platform-native binaries that cannot run in a generic container.
# HTTP transport keeps MCP traffic on TCP, fully separate from stdout.
npx --yes --package @tobilu/qmd@2.0.1 qmd mcp --http --port 8181 \
>> /tmp/qmd-mcp.log 2>&1 &
# Save PID for logs; the GitHub Actions runner terminates all processes at job end.
echo $! > /tmp/qmd-mcp.pid
# Wait up to 120 s for the server to accept requests
echo 'Waiting for QMD MCP server on port 8181...'
for i in $(seq 1 60); do
if curl -sf http://localhost:8181/health > /dev/null 2>&1; then
echo 'QMD MCP server is ready'
break
fi
if [ "$i" -eq 60 ]; then
echo 'ERROR: QMD MCP server failed to start within 120 s' >&2
cat /tmp/qmd-mcp.log 2>&1 || true
exit 1
fi
sleep 2
done
- name: Start MCP Gateway
id: start-mcp-gateway
env:
GH_AW_GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_AW_MCP_SCRIPTS_API_KEY: ${{ steps.mcp-scripts-start.outputs.api_key }}
GH_AW_MCP_SCRIPTS_PORT: ${{ steps.mcp-scripts-start.outputs.port }}
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-start.outputs.api_key }}
GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-start.outputs.port }}
GH_DEBUG: 1
GITHUB_MCP_GUARD_MIN_INTEGRITY: ${{ steps.determine-automatic-lockdown.outputs.min_integrity }}
GITHUB_MCP_GUARD_REPOS: ${{ steps.determine-automatic-lockdown.outputs.repos }}
GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
run: |
set -eo pipefail
mkdir -p /tmp/gh-aw/mcp-config
mkdir -p /tmp/gh-aw/mcp-logs/playwright
# Export gateway environment variables for MCP config and gateway script
export MCP_GATEWAY_PORT="80"
export MCP_GATEWAY_DOMAIN="host.docker.internal"
MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=')
echo "::add-mask::${MCP_GATEWAY_API_KEY}"
export MCP_GATEWAY_API_KEY
export MCP_GATEWAY_PAYLOAD_DIR="/tmp/gh-aw/mcp-payloads"
mkdir -p "${MCP_GATEWAY_PAYLOAD_DIR}"
export MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD="524288"
export DEBUG="*"
export GH_AW_ENGINE="codex"
export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_MCP_SCRIPTS_PORT -e GH_AW_MCP_SCRIPTS_API_KEY -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -e GH_AW_GH_TOKEN -e GH_DEBUG -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.2.12'
cat > /tmp/gh-aw/mcp-config/config.toml << GH_AW_MCP_CONFIG_c3d48ebeb7d5907a_EOF
[history]
persistence = "none"
[shell_environment_policy]
inherit = "core"
include_only = ["CODEX_API_KEY", "GH_AW_ASSETS_ALLOWED_EXTS", "GH_AW_ASSETS_BRANCH", "GH_AW_ASSETS_MAX_SIZE_KB", "GH_AW_SAFE_OUTPUTS", "GITHUB_PERSONAL_ACCESS_TOKEN", "GITHUB_REPOSITORY", "GITHUB_SERVER_URL", "HOME", "OPENAI_API_KEY", "PATH"]
[mcp_servers.github]
user_agent = "smoke-codex"
startup_timeout_sec = 120
tool_timeout_sec = 60
container = "ghcr.io/github/github-mcp-server:v0.32.0"
env = { "GITHUB_HOST" = "$GITHUB_SERVER_URL", "GITHUB_PERSONAL_ACCESS_TOKEN" = "$GH_AW_GITHUB_TOKEN", "GITHUB_READ_ONLY" = "1", "GITHUB_TOOLSETS" = "context,repos,issues,pull_requests" }
env_vars = ["GITHUB_HOST", "GITHUB_PERSONAL_ACCESS_TOKEN", "GITHUB_READ_ONLY", "GITHUB_TOOLSETS"]
[mcp_servers.mcpscripts]
type = "http"
url = "http://host.docker.internal:$GH_AW_MCP_SCRIPTS_PORT"
headers = { Authorization = "$GH_AW_MCP_SCRIPTS_API_KEY" }
[mcp_servers.mcpscripts."guard-policies"]
[mcp_servers.mcpscripts."guard-policies".write-sink]
accept = ["*"]
[mcp_servers.playwright]
container = "mcr.microsoft.com/playwright/mcp"
args = [
"--init",
"--network",
"host",
"--security-opt",
"seccomp=unconfined",
"--ipc=host",
]
entrypointArgs = [
"--output-dir",
"/tmp/gh-aw/mcp-logs/playwright"
]
mounts = ["/tmp/gh-aw/mcp-logs:/tmp/gh-aw/mcp-logs:rw"]
[mcp_servers.playwright."guard-policies"]
[mcp_servers.playwright."guard-policies".write-sink]
accept = ["*"]
[mcp_servers.qmd]
type = "http"
url = "http://host.docker.internal:8181/mcp"
[mcp_servers.qmd."guard-policies"]
[mcp_servers.qmd."guard-policies".write-sink]
accept = ["*"]
[mcp_servers.safeoutputs]
type = "http"
url = "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT"
[mcp_servers.safeoutputs.headers]
Authorization = "$GH_AW_SAFE_OUTPUTS_API_KEY"
[mcp_servers.safeoutputs."guard-policies"]
[mcp_servers.safeoutputs."guard-policies".write-sink]
accept = ["*"]
[mcp_servers.serena]
container = "ghcr.io/github/serena-mcp-server:latest"
entrypoint = "serena"
entrypointArgs = ["start-mcp-server", "--context", "codex", "--project", "\${GITHUB_WORKSPACE}"]
mounts = ["\${GITHUB_WORKSPACE}:\${GITHUB_WORKSPACE}:rw"]
args = [
"--network",
"host",
]
[mcp_servers.serena."guard-policies"]
[mcp_servers.serena."guard-policies".write-sink]
accept = ["*"]
GH_AW_MCP_CONFIG_c3d48ebeb7d5907a_EOF
# Generate JSON config for MCP gateway
cat << GH_AW_MCP_CONFIG_c3d48ebeb7d5907a_EOF | bash ${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh
{
"mcpServers": {
"github": {
"container": "ghcr.io/github/github-mcp-server:v0.32.0",
"env": {
"GITHUB_HOST": "$GITHUB_SERVER_URL",
"GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_MCP_SERVER_TOKEN",
"GITHUB_READ_ONLY": "1",
"GITHUB_TOOLSETS": "context,repos,issues,pull_requests"
},
"guard-policies": {
"allow-only": {
"min-integrity": "$GITHUB_MCP_GUARD_MIN_INTEGRITY",
"repos": "$GITHUB_MCP_GUARD_REPOS"
}
}
},
"mcpscripts": {
"type": "http",
"url": "http://host.docker.internal:$GH_AW_MCP_SCRIPTS_PORT",
"headers": {
"Authorization": "$GH_AW_MCP_SCRIPTS_API_KEY"
},
"guard-policies": {
"write-sink": {
"accept": [
"*"
]
}
}
},
"playwright": {
"container": "mcr.microsoft.com/playwright/mcp",
"args": [
"--init",
"--network",
"host",
"--security-opt",
"seccomp=unconfined",
"--ipc=host"
],
"entrypointArgs": [
"--output-dir",
"/tmp/gh-aw/mcp-logs/playwright",
"--no-sandbox"
],
"mounts": ["/tmp/gh-aw/mcp-logs:/tmp/gh-aw/mcp-logs:rw"],
"guard-policies": {
"write-sink": {
"accept": [
"*"
]
}
}
},
"qmd": {
"type": "http",
"url": "http://host.docker.internal:8181/mcp",
"guard-policies": {
"write-sink": {
"accept": [
"*"
]
}
}
},
"safeoutputs": {
"type": "http",
"url": "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT",
"headers": {
"Authorization": "$GH_AW_SAFE_OUTPUTS_API_KEY"
},
"guard-policies": {
"write-sink": {
"accept": [
"*"
]
}
}
},
"serena": {
"type": "stdio",
"container": "ghcr.io/github/serena-mcp-server:latest",
"entrypoint": "serena",
"entrypointArgs": [
"start-mcp-server",
"--context",
"codex",
"--project",
"\${GITHUB_WORKSPACE}"
],
"mounts": [
"\${GITHUB_WORKSPACE}:\${GITHUB_WORKSPACE}:rw"
],
"args": [
"--network",
"host"
],
"guard-policies": {
"write-sink": {
"accept": [
"*"
]
}
}
}
},
"gateway": {
"port": $MCP_GATEWAY_PORT,
"domain": "${MCP_GATEWAY_DOMAIN}",
"apiKey": "${MCP_GATEWAY_API_KEY}",
"payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}"
}
}
GH_AW_MCP_CONFIG_c3d48ebeb7d5907a_EOF
- name: Download activation artifact
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: activation
path: /tmp/gh-aw
- name: Clean git credentials
continue-on-error: true
run: bash ${RUNNER_TEMP}/gh-aw/actions/clean_git_credentials.sh
- name: Execute Codex CLI
id: agentic_execution
run: |
set -o pipefail
mkdir -p "$CODEX_HOME/logs" && touch /tmp/gh-aw/agent-step-summary.md
# shellcheck disable=SC1003
sudo -E awf --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" --env-all --exclude-env CODEX_API_KEY --exclude-env GH_AW_GH_TOKEN --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --exclude-env OPENAI_API_KEY --allow-domains '*.githubusercontent.com,172.30.0.1,api.openai.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,cdn.playwright.dev,codeload.github.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,docs.github.com,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,go.dev,golang.org,goproxy.io,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,lfs.github.com,objects.githubusercontent.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,openai.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,pkg.go.dev,playwright.download.prss.microsoft.com,ppa.launchpad.net,proxy.golang.org,raw.githubusercontent.com,s.symcb.com,s.symcd.com,security.ubuntu.com,storage.googleapis.com,sum.golang.org,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --image-tag 0.25.13 --skip-pull --enable-api-proxy \
-- /bin/bash -c 'export PATH="$(find /opt/hostedtoolcache -maxdepth 4 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true && INSTRUCTION="$(cat /tmp/gh-aw/aw-prompts/prompt.txt)" && codex ${GH_AW_MODEL_AGENT_CODEX:+-c model="$GH_AW_MODEL_AGENT_CODEX" }exec -c web_search="disabled" --dangerously-bypass-approvals-and-sandbox --skip-git-repo-check "$INSTRUCTION"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log
env:
CODEX_API_KEY: ${{ secrets.CODEX_API_KEY || secrets.OPENAI_API_KEY }}
CODEX_HOME: /tmp/gh-aw/mcp-config
GH_AW_GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_AW_MCP_CONFIG: /tmp/gh-aw/mcp-config/config.toml
GH_AW_MODEL_AGENT_CODEX: ${{ vars.GH_AW_MODEL_AGENT_CODEX || '' }}
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
GH_AW_VERSION: dev
GH_DEBUG: 1
GITHUB_AW: true
GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md
GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com
GIT_AUTHOR_NAME: github-actions[bot]
GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com
GIT_COMMITTER_NAME: github-actions[bot]
OPENAI_API_KEY: ${{ secrets.CODEX_API_KEY || secrets.OPENAI_API_KEY }}
RUST_LOG: trace,hyper_util=info,mio=info,reqwest=info,os_info=info,codex_otel=warn,codex_core=debug,ocodex_exec=debug
- name: Configure Git credentials
env:
REPO_NAME: ${{ github.repository }}
SERVER_URL: ${{ github.server_url }}
run: |
git config --global user.email "github-actions[bot]@users.noreply.github.com"
git config --global user.name "github-actions[bot]"
git config --global am.keepcr true
# Re-authenticate git with GitHub token
SERVER_URL_STRIPPED="${SERVER_URL#https://}"
git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git"
echo "Git configured with standard GitHub Actions identity"
- name: Stop MCP Gateway
if: always()
continue-on-error: true
env:
MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }}
MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }}
GATEWAY_PID: ${{ steps.start-mcp-gateway.outputs.gateway-pid }}
run: |
bash ${RUNNER_TEMP}/gh-aw/actions/stop_mcp_gateway.sh "$GATEWAY_PID"
- name: Redact secrets in logs
if: always()
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
with:
script: |
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
setupGlobals(core, github, context, exec, io);
const { main } = require('${{ runner.temp }}/gh-aw/actions/redact_secrets.cjs');
await main();
env:
GH_AW_SECRET_NAMES: 'CODEX_API_KEY,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN,OPENAI_API_KEY'
SECRET_CODEX_API_KEY: ${{ secrets.CODEX_API_KEY }}
SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }}
SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }}
SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SECRET_OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
- name: Append agent step summary
if: always()
run: bash ${RUNNER_TEMP}/gh-aw/actions/append_agent_step_summary.sh
- name: Copy Safe Outputs
if: always()
env:
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
run: |
mkdir -p /tmp/gh-aw
cp "$GH_AW_SAFE_OUTPUTS" /tmp/gh-aw/safeoutputs.jsonl 2>/dev/null || true
- name: Ingest agent output
id: collect_output
if: always()
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
env:
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,127.0.0.1,172.30.0.1,::1,api.openai.com,api.snapcraft.io,app.renovatebot.com,appveyor.com,archive.ubuntu.com,azure.archive.ubuntu.com,badgen.net,cdn.playwright.dev,circleci.com,codacy.com,codeclimate.com,codecov.io,codeload.github.com,coveralls.io,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,deepsource.io,docs.github.com,drone.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,go.dev,golang.org,goproxy.io,host.docker.internal,img.shields.io,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,lfs.github.com,localhost,objects.githubusercontent.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,openai.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,pkg.go.dev,playwright.download.prss.microsoft.com,ppa.launchpad.net,proxy.golang.org,raw.githubusercontent.com,readthedocs.io,readthedocs.org,renovatebot.com,s.symcb.com,s.symcd.com,security.ubuntu.com,semaphoreci.com,shields.io,snyk.io,sonarcloud.io,sonarqube.com,storage.googleapis.com,sum.golang.org,travis-ci.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com"
GITHUB_SERVER_URL: ${{ github.server_url }}
GITHUB_API_URL: ${{ github.api_url }}
with:
script: |
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
setupGlobals(core, github, context, exec, io);
const { main } = require('${{ runner.temp }}/gh-aw/actions/collect_ndjson_output.cjs');
await main();
- name: Parse agent logs for step summary
if: always()
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
env:
GH_AW_AGENT_OUTPUT: /tmp/gh-aw/agent-stdio.log
with:
script: |
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
setupGlobals(core, github, context, exec, io);
const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_codex_log.cjs');
await main();
- name: Parse MCP Scripts logs for step summary
if: always()
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
with:
script: |
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
setupGlobals(core, github, context, exec, io);
const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_mcp_scripts_logs.cjs');
await main();
- name: Parse MCP Gateway logs for step summary
if: always()
id: parse-mcp-gateway
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
with:
script: |
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
setupGlobals(core, github, context, exec, io);
const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_mcp_gateway_log.cjs');
await main();
- name: Print firewall logs
if: always()
continue-on-error: true
env:
AWF_LOGS_DIR: /tmp/gh-aw/sandbox/firewall/logs
run: |
# Fix permissions on firewall logs so they can be uploaded as artifacts
# AWF runs with sudo, creating files owned by root
sudo chmod -R a+r /tmp/gh-aw/sandbox/firewall/logs 2>/dev/null || true
# Only run awf logs summary if awf command exists (it may not be installed if workflow failed before install step)
if command -v awf &> /dev/null; then
awf logs summary | tee -a "$GITHUB_STEP_SUMMARY"
else
echo 'AWF binary not installed, skipping firewall log summary'
fi
- name: Parse token usage for step summary
if: always()
continue-on-error: true
run: bash ${RUNNER_TEMP}/gh-aw/actions/parse_token_usage.sh
- name: Write agent output placeholder if missing
if: always()
run: |
if [ ! -f /tmp/gh-aw/agent_output.json ]; then
echo '{"items":[]}' > /tmp/gh-aw/agent_output.json
fi
- name: Commit cache-memory changes
if: always()
env:
GH_AW_CACHE_DIR: /tmp/gh-aw/cache-memory
run: bash ${RUNNER_TEMP}/gh-aw/actions/commit_cache_memory_git.sh
- name: Upload cache-memory data as artifact
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
if: always()
with:
name: cache-memory
path: /tmp/gh-aw/cache-memory
- name: Upload agent artifacts
if: always()
continue-on-error: true
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
with:
name: agent
path: |
/tmp/gh-aw/aw-prompts/prompt.txt
/tmp/gh-aw/mcp-config/logs/
/tmp/gh-aw/redacted-urls.log
/tmp/gh-aw/mcp-logs/
/tmp/gh-aw/mcp-scripts/logs/
/tmp/gh-aw/agent-stdio.log
/tmp/gh-aw/agent/
/tmp/gh-aw/safeoutputs.jsonl
/tmp/gh-aw/agent_output.json
/tmp/gh-aw/aw-*.patch
/tmp/gh-aw/aw-*.bundle
if-no-files-found: ignore
- name: Upload firewall audit logs
if: always()
continue-on-error: true
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
with:
name: firewall-audit-logs
path: |
/tmp/gh-aw/sandbox/firewall/logs/
/tmp/gh-aw/sandbox/firewall/audit/
if-no-files-found: ignore
conclusion:
needs:
- activation
- agent
- detection
- indexing
- safe_outputs
- update_cache_memory
if: always() && (needs.agent.result != 'skipped' || needs.activation.outputs.lockdown_check_failed == 'true')
runs-on: ubuntu-slim
permissions:
contents: read
discussions: write
issues: write
pull-requests: write
concurrency:
group: "gh-aw-conclusion-smoke-codex"
cancel-in-progress: false
outputs:
noop_message: ${{ steps.noop.outputs.noop_message }}
tools_reported: ${{ steps.missing_tool.outputs.tools_reported }}
total_count: ${{ steps.missing_tool.outputs.total_count }}
steps:
- name: Checkout actions folder
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
repository: github/gh-aw
sparse-checkout: |
actions
persist-credentials: false
- name: Setup Scripts
uses: ./actions/setup
with:
destination: ${{ runner.temp }}/gh-aw/actions
- name: Download agent output artifact
id: download-agent-output
continue-on-error: true
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: agent
path: /tmp/gh-aw/
- name: Setup agent output environment variable
id: setup-agent-output-env
if: steps.download-agent-output.outcome == 'success'
run: |
mkdir -p /tmp/gh-aw/
find "/tmp/gh-aw/" -type f -print
echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT"
- name: Process No-Op Messages
id: noop
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
env:
GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }}
GH_AW_NOOP_MAX: "1"
GH_AW_WORKFLOW_NAME: "Smoke Codex"
GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }}
GH_AW_NOOP_REPORT_AS_ISSUE: "true"
with:
github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
script: |
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
setupGlobals(core, github, context, exec, io);
const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_noop_message.cjs');
await main();
- name: Record Missing Tool
id: missing_tool
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
env:
GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }}
GH_AW_MISSING_TOOL_CREATE_ISSUE: "true"
GH_AW_WORKFLOW_NAME: "Smoke Codex"
with:
github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
script: |
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
setupGlobals(core, github, context, exec, io);
const { main } = require('${{ runner.temp }}/gh-aw/actions/missing_tool.cjs');
await main();
- name: Handle Agent Failure
id: handle_agent_failure
if: always()
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
env:
GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }}
GH_AW_WORKFLOW_NAME: "Smoke Codex"
GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }}
GH_AW_WORKFLOW_ID: "smoke-codex"
GH_AW_ENGINE_ID: "codex"
GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.activation.outputs.secret_verification_result }}
GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }}
GH_AW_LOCKDOWN_CHECK_FAILED: ${{ needs.activation.outputs.lockdown_check_failed }}
GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"\\u003e 🔮 *The oracle has spoken through [{workflow_name}]({run_url})*{effective_tokens_suffix}{history_link}\",\"runStarted\":\"🔮 The ancient spirits stir... [{workflow_name}]({run_url}) awakens to divine this {event_type}...\",\"runSuccess\":\"✨ The prophecy is fulfilled... [{workflow_name}]({run_url}) has completed its mystical journey. The stars align. 🌟\",\"runFailure\":\"🌑 The shadows whisper... [{workflow_name}]({run_url}) {status}. The oracle requires further meditation...\"}"
GH_AW_GROUP_REPORTS: "false"
GH_AW_FAILURE_REPORT_AS_ISSUE: "true"
GH_AW_TIMEOUT_MINUTES: "15"
with:
github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
script: |
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
setupGlobals(core, github, context, exec, io);
const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_agent_failure.cjs');
await main();
- name: Update reaction comment with completion status
id: conclusion
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
env:
GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }}
GH_AW_COMMENT_ID: ${{ needs.activation.outputs.comment_id }}
GH_AW_COMMENT_REPO: ${{ needs.activation.outputs.comment_repo }}
GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
GH_AW_WORKFLOW_NAME: "Smoke Codex"
GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }}
GH_AW_DETECTION_CONCLUSION: ${{ needs.detection.outputs.detection_conclusion }}
GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"\\u003e 🔮 *The oracle has spoken through [{workflow_name}]({run_url})*{effective_tokens_suffix}{history_link}\",\"runStarted\":\"🔮 The ancient spirits stir... [{workflow_name}]({run_url}) awakens to divine this {event_type}...\",\"runSuccess\":\"✨ The prophecy is fulfilled... [{workflow_name}]({run_url}) has completed its mystical journey. The stars align. 🌟\",\"runFailure\":\"🌑 The shadows whisper... [{workflow_name}]({run_url}) {status}. The oracle requires further meditation...\"}"
with:
github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
script: |
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
setupGlobals(core, github, context, exec, io);
const { main } = require('${{ runner.temp }}/gh-aw/actions/notify_comment_error.cjs');
await main();
detection:
needs: agent
if: >
always() && needs.agent.result != 'skipped' && (needs.agent.outputs.output_types != '' || needs.agent.outputs.has_patch == 'true')
runs-on: ubuntu-latest
permissions:
contents: read
outputs:
detection_conclusion: ${{ steps.detection_conclusion.outputs.conclusion }}
detection_success: ${{ steps.detection_conclusion.outputs.success }}
steps:
- name: Checkout actions folder
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
repository: github/gh-aw
sparse-checkout: |
actions
persist-credentials: false
- name: Setup Scripts
uses: ./actions/setup
with:
destination: ${{ runner.temp }}/gh-aw/actions
- name: Download agent output artifact
id: download-agent-output
continue-on-error: true
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: agent
path: /tmp/gh-aw/
- name: Setup agent output environment variable
id: setup-agent-output-env
if: steps.download-agent-output.outcome == 'success'
run: |
mkdir -p /tmp/gh-aw/
find "/tmp/gh-aw/" -type f -print
echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT"
- name: Checkout repository for patch context
if: needs.agent.outputs.has_patch == 'true'
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
# --- Threat Detection ---
- name: Download container images
run: bash ${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh ghcr.io/github/gh-aw-firewall/agent:0.25.13 ghcr.io/github/gh-aw-firewall/api-proxy:0.25.13 ghcr.io/github/gh-aw-firewall/squid:0.25.13
- name: Check if detection needed
id: detection_guard
if: always()
env:
OUTPUT_TYPES: ${{ needs.agent.outputs.output_types }}
HAS_PATCH: ${{ needs.agent.outputs.has_patch }}
run: |
if [[ -n "$OUTPUT_TYPES" || "$HAS_PATCH" == "true" ]]; then
echo "run_detection=true" >> "$GITHUB_OUTPUT"
echo "Detection will run: output_types=$OUTPUT_TYPES, has_patch=$HAS_PATCH"
else
echo "run_detection=false" >> "$GITHUB_OUTPUT"
echo "Detection skipped: no agent outputs or patches to analyze"
fi
- name: Clear MCP configuration for detection
if: always() && steps.detection_guard.outputs.run_detection == 'true'
run: |
rm -f /tmp/gh-aw/mcp-config/mcp-servers.json
rm -f /home/runner/.copilot/mcp-config.json
rm -f "$GITHUB_WORKSPACE/.gemini/settings.json"
- name: Prepare threat detection files
if: always() && steps.detection_guard.outputs.run_detection == 'true'
run: |
mkdir -p /tmp/gh-aw/threat-detection/aw-prompts
cp /tmp/gh-aw/aw-prompts/prompt.txt /tmp/gh-aw/threat-detection/aw-prompts/prompt.txt 2>/dev/null || true
cp /tmp/gh-aw/agent_output.json /tmp/gh-aw/threat-detection/agent_output.json 2>/dev/null || true
for f in /tmp/gh-aw/aw-*.patch; do
[ -f "$f" ] && cp "$f" /tmp/gh-aw/threat-detection/ 2>/dev/null || true
done
for f in /tmp/gh-aw/aw-*.bundle; do
[ -f "$f" ] && cp "$f" /tmp/gh-aw/threat-detection/ 2>/dev/null || true
done
echo "Prepared threat detection files:"
ls -la /tmp/gh-aw/threat-detection/ 2>/dev/null || true
- name: Setup threat detection
if: always() && steps.detection_guard.outputs.run_detection == 'true'
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
env:
WORKFLOW_NAME: "Smoke Codex"
WORKFLOW_DESCRIPTION: "Smoke test workflow that validates Codex engine functionality by reviewing recent PRs twice daily"
HAS_PATCH: ${{ needs.agent.outputs.has_patch }}
with:
script: |
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
setupGlobals(core, github, context, exec, io);
const { main } = require('${{ runner.temp }}/gh-aw/actions/setup_threat_detection.cjs');
await main();
- name: Ensure threat-detection directory and log
if: always() && steps.detection_guard.outputs.run_detection == 'true'
run: |
mkdir -p /tmp/gh-aw/threat-detection
touch /tmp/gh-aw/threat-detection/detection.log
- name: Setup Node.js
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: '24'
package-manager-cache: false
- name: Install Codex CLI
run: npm install -g @openai/codex@latest
- name: Install AWF binary
run: bash ${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh v0.25.13
- name: Execute Codex CLI
if: always() && steps.detection_guard.outputs.run_detection == 'true'
id: detection_agentic_execution
run: |
set -o pipefail
mkdir -p "$CODEX_HOME/logs" && touch /tmp/gh-aw/agent-step-summary.md
# shellcheck disable=SC1003
sudo -E awf --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" --env-all --exclude-env CODEX_API_KEY --exclude-env OPENAI_API_KEY --allow-domains 172.30.0.1,api.openai.com,host.docker.internal,openai.com --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --image-tag 0.25.13 --skip-pull --enable-api-proxy \
-- /bin/bash -c 'export PATH="$(find /opt/hostedtoolcache -maxdepth 4 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true && INSTRUCTION="$(cat /tmp/gh-aw/aw-prompts/prompt.txt)" && codex ${GH_AW_MODEL_DETECTION_CODEX:+-c model="$GH_AW_MODEL_DETECTION_CODEX" }exec -c web_search="disabled" -c fetch="disabled" --dangerously-bypass-approvals-and-sandbox --skip-git-repo-check "$INSTRUCTION"' 2>&1 | tee -a /tmp/gh-aw/threat-detection/detection.log
env:
CODEX_API_KEY: ${{ secrets.CODEX_API_KEY || secrets.OPENAI_API_KEY }}
CODEX_HOME: /tmp/gh-aw/mcp-config
GH_AW_MCP_CONFIG: /tmp/gh-aw/mcp-config/config.toml
GH_AW_MODEL_DETECTION_CODEX: ${{ vars.GH_AW_MODEL_DETECTION_CODEX || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_VERSION: dev
GITHUB_AW: true
GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md
GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com
GIT_AUTHOR_NAME: github-actions[bot]
GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com
GIT_COMMITTER_NAME: github-actions[bot]
OPENAI_API_KEY: ${{ secrets.CODEX_API_KEY || secrets.OPENAI_API_KEY }}
RUST_LOG: trace,hyper_util=info,mio=info,reqwest=info,os_info=info,codex_otel=warn,codex_core=debug,ocodex_exec=debug
- name: Upload threat detection log
if: always() && steps.detection_guard.outputs.run_detection == 'true'
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
with:
name: detection
path: /tmp/gh-aw/threat-detection/detection.log
if-no-files-found: ignore
- name: Parse and conclude threat detection
id: detection_conclusion
if: always()
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
env:
RUN_DETECTION: ${{ steps.detection_guard.outputs.run_detection }}
with:
script: |
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
setupGlobals(core, github, context, exec, io);
const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_threat_detection_results.cjs');
await main();
indexing:
needs: activation
runs-on: ubuntu-latest
permissions:
contents: read
timeout-minutes: 60
steps:
- name: Checkout actions folder
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
repository: github/gh-aw
sparse-checkout: |
actions
persist-credentials: false
- name: Setup Scripts
uses: ./actions/setup
with:
destination: ${{ runner.temp }}/gh-aw/actions
- name: Checkout repository for qmd indexing
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Restore qmd index from cache
id: qmd-cache-restore
uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
with:
key: gh-aw-qmd-2.0.1-${{ github.run_id }}
path: /tmp/gh-aw/qmd-index/
restore-keys: |
gh-aw-qmd-2.0.1-
- name: Save qmd models to cache
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
with:
path: ~/.cache/qmd/models/
key: qmd-models-2.0.1-${{ runner.os }}
- name: Cache node-llama-cpp binaries
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
with:
path: ~/.cache/node-llama-cpp/
key: node-llama-cpp-2.0.1-${{ runner.os }}-${{ runner.arch }}-${{ runner.imageid }}
- name: Setup Node.js for qmd
if: steps.qmd-cache-restore.outputs.cache-hit != 'true'
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: "24"
- name: Install @tobilu/qmd SDK
if: steps.qmd-cache-restore.outputs.cache-hit != 'true'
run: |
npm install --prefix "${{ runner.temp }}/gh-aw/actions" --legacy-peer-deps @tobilu/qmd@2.0.1 @actions/github
- name: Build qmd index
if: steps.qmd-cache-restore.outputs.cache-hit != 'true'
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
env:
QMD_CONFIG_JSON: |
{"dbPath":"/tmp/gh-aw/qmd-index","checkouts":[{"name":"docs","path":"${GITHUB_WORKSPACE}","pattern":"docs/src/**/*.{md,mdx}","context":"gh-aw project documentation"}],"searches":[{"name":"issues","type":"issues","max":500,"tokenEnvVar":"QMD_SEARCH_TOKEN_0"}]}
NODE_LLAMA_CPP_GPU: "false"
QMD_SEARCH_TOKEN_0: ${{ secrets.GITHUB_TOKEN }}
with:
github-token: ${{ github.token }}
script: |
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
setupGlobals(core, github, context, exec, io);
const { main } = require('${{ runner.temp }}/gh-aw/actions/qmd_index.cjs');
await main();
- name: Save qmd index to cache
if: steps.qmd-cache-restore.outputs.cache-hit != 'true'
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
with:
key: gh-aw-qmd-2.0.1-${{ github.run_id }}
path: /tmp/gh-aw/qmd-index/
pre_activation:
if: >
(github.event_name != 'pull_request' || github.event.pull_request.head.repo.id == github.repository_id) &&
(github.event_name != 'pull_request' || github.event.action != 'labeled' || github.event.label.name == 'smoke')
runs-on: ubuntu-slim
permissions:
contents: read
outputs:
activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }}
matched_command: ''
steps:
- name: Checkout actions folder
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
repository: github/gh-aw
sparse-checkout: |
actions
persist-credentials: false
- name: Setup Scripts
uses: ./actions/setup
with:
destination: ${{ runner.temp }}/gh-aw/actions
- name: Check team membership for workflow
id: check_membership
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
env:
GH_AW_REQUIRED_ROLES: "admin,maintainer,write"
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
setupGlobals(core, github, context, exec, io);
const { main } = require('${{ runner.temp }}/gh-aw/actions/check_membership.cjs');
await main();
safe_outputs:
needs:
- agent
- detection
if: (!cancelled()) && needs.agent.result != 'skipped' && needs.detection.result == 'success'
runs-on: ubuntu-slim
permissions:
contents: read
discussions: write
issues: write
pull-requests: write
timeout-minutes: 15
env:
GH_AW_CALLER_WORKFLOW_ID: "${{ github.repository }}/smoke-codex"
GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens }}
GH_AW_ENGINE_ID: "codex"
GH_AW_ENGINE_MODEL: ${{ needs.agent.outputs.model }}
GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"\\u003e 🔮 *The oracle has spoken through [{workflow_name}]({run_url})*{effective_tokens_suffix}{history_link}\",\"runStarted\":\"🔮 The ancient spirits stir... [{workflow_name}]({run_url}) awakens to divine this {event_type}...\",\"runSuccess\":\"✨ The prophecy is fulfilled... [{workflow_name}]({run_url}) has completed its mystical journey. The stars align. 🌟\",\"runFailure\":\"🌑 The shadows whisper... [{workflow_name}]({run_url}) {status}. The oracle requires further meditation...\"}"
GH_AW_WORKFLOW_ID: "smoke-codex"
GH_AW_WORKFLOW_NAME: "Smoke Codex"
outputs:
code_push_failure_count: ${{ steps.process_safe_outputs.outputs.code_push_failure_count }}
code_push_failure_errors: ${{ steps.process_safe_outputs.outputs.code_push_failure_errors }}
comment_id: ${{ steps.process_safe_outputs.outputs.comment_id }}
comment_url: ${{ steps.process_safe_outputs.outputs.comment_url }}
create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }}
create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }}
created_issue_number: ${{ steps.process_safe_outputs.outputs.created_issue_number }}
created_issue_url: ${{ steps.process_safe_outputs.outputs.created_issue_url }}
process_safe_outputs_processed_count: ${{ steps.process_safe_outputs.outputs.processed_count }}
process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }}
steps:
- name: Checkout actions folder
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
repository: github/gh-aw
sparse-checkout: |
actions
persist-credentials: false
- name: Setup Scripts
uses: ./actions/setup
with:
destination: ${{ runner.temp }}/gh-aw/actions
- name: Download agent output artifact
id: download-agent-output
continue-on-error: true
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: agent
path: /tmp/gh-aw/
- name: Setup agent output environment variable
id: setup-agent-output-env
if: steps.download-agent-output.outcome == 'success'
run: |
mkdir -p /tmp/gh-aw/
find "/tmp/gh-aw/" -type f -print
echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT"
- name: Configure GH_HOST for enterprise compatibility
id: ghes-host-config
shell: bash
run: |
# Derive GH_HOST from GITHUB_SERVER_URL so the gh CLI targets the correct
# GitHub instance (GHES/GHEC). On github.com this is a harmless no-op.
GH_HOST="${GITHUB_SERVER_URL#https://}"
GH_HOST="${GH_HOST#http://}"
echo "GH_HOST=${GH_HOST}" >> "$GITHUB_ENV"
- name: Process Safe Outputs
id: process_safe_outputs
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
env:
GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }}
GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,127.0.0.1,172.30.0.1,::1,api.openai.com,api.snapcraft.io,app.renovatebot.com,appveyor.com,archive.ubuntu.com,azure.archive.ubuntu.com,badgen.net,cdn.playwright.dev,circleci.com,codacy.com,codeclimate.com,codecov.io,codeload.github.com,coveralls.io,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,deepsource.io,docs.github.com,drone.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,go.dev,golang.org,goproxy.io,host.docker.internal,img.shields.io,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,lfs.github.com,localhost,objects.githubusercontent.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,openai.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,pkg.go.dev,playwright.download.prss.microsoft.com,ppa.launchpad.net,proxy.golang.org,raw.githubusercontent.com,readthedocs.io,readthedocs.org,renovatebot.com,s.symcb.com,s.symcd.com,security.ubuntu.com,semaphoreci.com,shields.io,snyk.io,sonarcloud.io,sonarqube.com,storage.googleapis.com,sum.golang.org,travis-ci.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com"
GITHUB_SERVER_URL: ${{ github.server_url }}
GITHUB_API_URL: ${{ github.api_url }}
GH_AW_SAFE_OUTPUT_ACTIONS: "{\"add_smoked_label\":\"add_smoked_label\"}"
GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"hide_older_comments\":true,\"max\":2},\"add_labels\":{\"allowed\":[\"smoke-codex\"]},\"create_issue\":{\"close_older_issues\":true,\"close_older_key\":\"smoke-codex\",\"expires\":2,\"labels\":[\"automation\",\"testing\"],\"max\":1},\"hide_comment\":{\"max\":5},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"remove_labels\":{\"allowed\":[\"smoke\"]},\"unassign_from_user\":{\"allowed\":[\"githubactionagent\"],\"max\":1}}"
with:
github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
script: |
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
setupGlobals(core, github, context, exec, io);
const { main } = require('${{ runner.temp }}/gh-aw/actions/safe_output_handler_manager.cjs');
await main();
- name: Add the 'smoked' label to the current pull request
id: action_add_smoked_label
if: steps.process_safe_outputs.outputs.action_add_smoked_label_payload != ''
uses: actions-ecosystem/action-add-labels@c96b68fec76a0987cd93957189e9abd0b9a72ff1 # v1.1.3
env:
GITHUB_TOKEN: ${{ github.token }}
with:
labels: ${{ fromJSON(steps.process_safe_outputs.outputs.action_add_smoked_label_payload).labels }}
number: ${{ fromJSON(steps.process_safe_outputs.outputs.action_add_smoked_label_payload).number }}
- name: Upload Safe Output Items
if: always()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
with:
name: safe-output-items
path: /tmp/gh-aw/safe-output-items.jsonl
if-no-files-found: ignore
update_cache_memory:
needs:
- agent
- detection
if: >
always() && (needs.detection.result == 'success' || needs.detection.result == 'skipped') &&
needs.agent.result == 'success'
runs-on: ubuntu-slim
permissions:
contents: read
env:
GH_AW_WORKFLOW_ID_SANITIZED: smokecodex
steps:
- name: Checkout actions folder
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
repository: github/gh-aw
sparse-checkout: |
actions
persist-credentials: false
- name: Setup Scripts
uses: ./actions/setup
with:
destination: ${{ runner.temp }}/gh-aw/actions
- name: Download cache-memory artifact (default)
id: download_cache_default
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
continue-on-error: true
with:
name: cache-memory
path: /tmp/gh-aw/cache-memory
- name: Check if cache-memory folder has content (default)
id: check_cache_default
shell: bash
run: |
if [ -d "/tmp/gh-aw/cache-memory" ] && [ "$(ls -A /tmp/gh-aw/cache-memory 2>/dev/null)" ]; then
echo "has_content=true" >> "$GITHUB_OUTPUT"
else
echo "has_content=false" >> "$GITHUB_OUTPUT"
fi
- name: Save cache-memory to cache (default)
if: steps.check_cache_default.outputs.has_content == 'true'
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
with:
key: memory-none-nopolicy-${{ env.GH_AW_WORKFLOW_ID_SANITIZED }}-${{ github.run_id }}
path: /tmp/gh-aw/cache-memory