Skip to content

/cloclo

/cloclo #77406

Workflow file for this run

# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"ec3efe8f7f3cc8e20f49b04164321e6e2923f0d55b80df96fbbc96638b33ade5","body_hash":"1577e7c80f76a3124113c4b9762a1f0094660f2ff5f8295d074879354653dfe3","strict":true,"agent_id":"codex","agent_model":"copilot/gpt-5.6-terra","engine_versions":{"codex":"0.165.0"}}
# gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_GRAFANA_AUTHORIZATION","GH_AW_OTEL_GRAFANA_ENDPOINT","GH_AW_OTEL_SENTRY_AUTHORIZATION","GH_AW_OTEL_SENTRY_ENDPOINT","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"55cc8345863c7cc4c66a329aec7e433d2d1c52a9","version":"v6.1.0"},{"repo":"actions/cache/save","sha":"55cc8345863c7cc4c66a329aec7e433d2d1c52a9","version":"v6.1.0"},{"repo":"actions/checkout","sha":"3d3c42e5aac5ba805825da76410c181273ba90b1","version":"v7.0.1"},{"repo":"actions/download-artifact","sha":"9000827ccba6bdab643e8b6fd33ac0654aef8333","version":"v8.0.2"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-go","sha":"b7ad1dad31e06c5925ef5d2fc7ad053ef454303e","version":"v7.0.0"},{"repo":"actions/setup-node","sha":"949feb2413d6458794dcd2491c4babbbce0c15c1","version":"v7.1.0"},{"repo":"actions/upload-artifact","sha":"cf430e030ddbb5b0abf93d22962f4752f3646cd9","version":"v7.0.2"},{"repo":"docker/build-push-action","sha":"c3c9e263c25d99ce0380d002d59b67737d91b0dc","version":"v7.4.0"},{"repo":"docker/setup-buildx-action","sha":"f87e5991a6d7451dcb8d9637bfbc97413f497069","version":"v4.4.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.29.5","digest":"sha256:921e50aed7b2a67265f42ab03c7d54a32c641922cc64f0875a5ae2bcb8b37532","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.29.5@sha256:921e50aed7b2a67265f42ab03c7d54a32c641922cc64f0875a5ae2bcb8b37532"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.29.5","digest":"sha256:f36a9fc78aef0509ed5fa280819848cbdf099f60d7b338455ea54a5def18d6b1","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.29.5@sha256:f36a9fc78aef0509ed5fa280819848cbdf099f60d7b338455ea54a5def18d6b1"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.29.5","digest":"sha256:34260cb89ea5d6d55b93ce13a5fe1772dbe8e1592e1200370160b7f5a0bd2ecd","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.29.5@sha256:34260cb89ea5d6d55b93ce13a5fe1772dbe8e1592e1200370160b7f5a0bd2ecd"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.5.0","digest":"sha256:d3544a4222e7efeeeb38669d8a1af0c72691c55b8f6506b15aa5920f7f31b7bc","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.5.0@sha256:d3544a4222e7efeeeb38669d8a1af0c72691c55b8f6506b15aa5920f7f31b7bc"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:2c2ea524e648b91c8333ce246e3838fcf5b19ac70e45baac1a51b9207299749f","pinned_image":"ghcr.io/github/gh-aw-node@sha256:2c2ea524e648b91c8333ce246e3838fcf5b19ac70e45baac1a51b9207299749f"},{"image":"ghcr.io/github/github-mcp-server:v2.0.3","digest":"sha256:250bc6ce70788207608ef74cef4397230ff2e8481218da74d6093e4bd9101132","pinned_image":"ghcr.io/github/github-mcp-server:v2.0.3@sha256:250bc6ce70788207608ef74cef4397230ff2e8481218da74d6093e4bd9101132"},{"image":"ghcr.io/oraios/serena:1.7.0","digest":"sha256:6c9459e4246a39c9deaa4f23fb05a526ac6e237b24c8e84a927a098fa1ab6730","pinned_image":"ghcr.io/oraios/serena:1.7.0@sha256:6c9459e4246a39c9deaa4f23fb05a526ac6e237b24c8e84a927a098fa1ab6730"}],"mcp_servers":[{"name":"agenticworkflows","tools":["*"]},{"name":"github","tools":["get_commit","get_file_contents","get_latest_release","get_me","get_pull_request","get_pull_request_comments","get_pull_request_diff","get_pull_request_files","get_pull_request_review_comments","get_pull_request_reviews","get_pull_request_status","get_release_by_tag","get_tag","issue_read","list_branches","list_commits","list_issue_types","list_issues","list_pull_requests","list_releases","list_starred_repositories","list_tags","pull_request_read","search_code","search_issues","search_pull_requests","search_repositories"]},{"name":"safeoutputs","tools":["add_comment","create_pull_request","noop","report_incomplete","report_missing_data","report_missing_tool"]},{"name":"serena","tools":["*"]}],"threat_detection":{"mode":"enabled"},"admission":true}
# This file was automatically generated by gh-aw. DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md
#
# ___ _ _
# / _ \ | | (_)
# | |_| | __ _ ___ _ __ | |_ _ ___
# | _ |/ _` |/ _ \ '_ \| __| |/ __|
# | | | | (_| | __/ | | | |_| | (__
# \_| |_/\__, |\___|_| |_|\__|_|\___|
# __/ |
# _ _ |___/
# | | | | / _| |
# | | | | ___ _ __ _ __| |_| | _____ ____
# | |/\| |/ _ \ '__| |/ /| _| |/ _ \ \ /\ / / ___|
# \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \
# \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/
#
#
# 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/
#
#
# Resolved workflow manifest:
# Imports:
# - ../skills/jqschema/SKILL.md
# - shared/mcp/serena.md
# - shared/mcp/serena-go.md
# - shared/reporting.md
# - shared/otlp.md
# - shared/graders/state-revisit-probability-rep.md
# - shared/graders/recurrence-determinism.md
# - shared/graders/recurrence-laminarity.md
# - shared/graders.md
#
# Secrets used:
# - COPILOT_GITHUB_TOKEN
# - GH_AW_CI_TRIGGER_TOKEN
# - GH_AW_GITHUB_MCP_SERVER_TOKEN
# - GH_AW_GITHUB_TOKEN
# - GH_AW_OTEL_GRAFANA_AUTHORIZATION
# - GH_AW_OTEL_GRAFANA_ENDPOINT
# - GH_AW_OTEL_SENTRY_AUTHORIZATION
# - GH_AW_OTEL_SENTRY_ENDPOINT
# - GITHUB_TOKEN
#
# Custom actions used:
# - actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
# - actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
# - actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
# - actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
# - actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
# - actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
# - actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
# - docker/build-push-action@c3c9e263c25d99ce0380d002d59b67737d91b0dc # v7.4.0
# - docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1
#
# Container images used:
# - ghcr.io/github/gh-aw-firewall/agent:0.29.5@sha256:921e50aed7b2a67265f42ab03c7d54a32c641922cc64f0875a5ae2bcb8b37532
# - ghcr.io/github/gh-aw-firewall/api-proxy:0.29.5@sha256:f36a9fc78aef0509ed5fa280819848cbdf099f60d7b338455ea54a5def18d6b1
# - ghcr.io/github/gh-aw-firewall/squid:0.29.5@sha256:34260cb89ea5d6d55b93ce13a5fe1772dbe8e1592e1200370160b7f5a0bd2ecd
# - ghcr.io/github/gh-aw-mcpg:v0.5.0@sha256:d3544a4222e7efeeeb38669d8a1af0c72691c55b8f6506b15aa5920f7f31b7bc
# - ghcr.io/github/gh-aw-node@sha256:2c2ea524e648b91c8333ce246e3838fcf5b19ac70e45baac1a51b9207299749f
# - ghcr.io/github/github-mcp-server:v2.0.3@sha256:250bc6ce70788207608ef74cef4397230ff2e8481218da74d6093e4bd9101132
# - ghcr.io/oraios/serena:1.7.0@sha256:6c9459e4246a39c9deaa4f23fb05a526ac6e237b24c8e84a927a098fa1ab6730
name: "/cloclo"
on:
workflow_dispatch:
inputs:
aw_context:
default: ""
description: "Agent caller context (Reserved for Agentic Workflows)."
required: false
type: string
issue_number:
description: Issue number to fix when dispatched by Issue Monster
required: false
type: string
# Jobs receive only their explicitly declared permissions.
permissions: {}
concurrency:
cancel-in-progress: false
group: ${{ github.workflow }}-${{ github.ref }}-cloclo-${{ inputs.issue_number || 'command' }}
run-name: "/cloclo"
env:
OTEL_EXPORTER_OTLP_ENDPOINT: ${{ secrets.GH_AW_OTEL_SENTRY_ENDPOINT }}
OTEL_SERVICE_NAME: gh-aw.cloclo
OTEL_RESOURCE_ATTRIBUTES: 'gh-aw.workflow.name=%2Fcloclo,gh-aw.repository=${{ github.repository }},gh-aw.run.id=${{ github.run_id }},github.run_id=${{ github.run_id }},gh-aw.engine.id=codex'
OTEL_EXPORTER_OTLP_HEADERS: x-sentry-auth=${{ secrets.GH_AW_OTEL_SENTRY_AUTHORIZATION }}
GH_AW_OTLP_ALL_HEADERS: x-sentry-auth=${{ secrets.GH_AW_OTEL_SENTRY_AUTHORIZATION }},Authorization=${{ secrets.GH_AW_OTEL_GRAFANA_AUTHORIZATION }}
GH_AW_OTLP_ENDPOINTS: '[{"url":"${{ secrets.GH_AW_OTEL_SENTRY_ENDPOINT }}","headers":"x-sentry-auth=${{ secrets.GH_AW_OTEL_SENTRY_AUTHORIZATION }}"},{"url":"${{ secrets.GH_AW_OTEL_GRAFANA_ENDPOINT }}","headers":"Authorization=${{ secrets.GH_AW_OTEL_GRAFANA_AUTHORIZATION }}"}]'
jobs:
activation:
name: activation
needs:
- admission
- pre_activation
if: >
((!cancelled()) && (needs.admission.result == 'success' || needs.admission.result == 'skipped') && needs.pre_activation.result == 'success') &&
(needs.pre_activation.outputs.activated == 'true' && ((fromJSON(github.event.inputs.aw_context || '{}').event_type == 'issues' ||
fromJSON(github.event.inputs.aw_context || '{}').event_type == 'pull_request' || fromJSON(github.event.inputs.aw_context ||
'{}').event_type == 'discussion') && (fromJSON(github.event.inputs.aw_context || '{}').trigger_label == 'cloclo') ||
!(fromJSON(github.event.inputs.aw_context || '{}').event_type == 'issues' || fromJSON(github.event.inputs.aw_context ||
'{}').event_type == 'pull_request' || fromJSON(github.event.inputs.aw_context || '{}').event_type == 'discussion')))
runs-on: ubuntu-slim
# Permissions for the activation job (workflow permissions default to none).
permissions:
actions: read
contents: read
discussions: write
issues: write
pull-requests: write
env:
GH_AW_ADMISSION_RESULT: ${{ needs.admission.outputs.result }}
GH_AW_MAX_DAILY_AI_CREDITS: "10000"
GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }}
outputs:
admission-max-ai-credits: ${{ needs.admission.outputs.max-ai-credits }}
admission-max-ai-credits-evals: ${{ needs.admission.outputs.max-ai-credits-evals }}
admission-max-ai-credits-threat-detection: ${{ needs.admission.outputs.max-ai-credits-threat-detection }}
admission-result: ${{ needs.admission.outputs.result }}
aw_context: ${{ steps.generate_aw_info.outputs.aw_context }}
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 }}
daily_ai_credits_estimated: ${{ steps.daily-ai-credits-workflow-guardrail.outputs.daily_ai_credits_estimated || '' }}
daily_ai_credits_exceeded: ${{ steps.daily-ai-credits-workflow-guardrail.outputs.daily_ai_credits_exceeded == 'true' }}
daily_ai_credits_guardrail_error: ${{ steps.daily-ai-credits-workflow-guardrail.outputs.daily_ai_credits_guardrail_error || '' }}
daily_ai_credits_guardrail_status: ${{ steps.daily-ai-credits-workflow-guardrail.outputs.daily_ai_credits_guardrail_status || '' }}
daily_ai_credits_threshold: ${{ steps.daily-ai-credits-workflow-guardrail.outputs.daily_ai_credits_threshold || '' }}
daily_ai_credits_total: ${{ steps.daily-ai-credits-workflow-guardrail.outputs.daily_ai_credits_total || '' }}
engine_id: ${{ steps.generate_aw_info.outputs.engine_id }}
label_command: ${{ steps.remove_trigger_label.outputs.label_name }}
lockdown_check_failed: ${{ steps.generate_aw_info.outputs.lockdown_check_failed == 'true' }}
model: ${{ steps.generate_aw_info.outputs.model }}
oauth_token_check_failed: ${{ steps.check-oauth-tokens.outputs.oauth_token_check_failed == 'true' }}
secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }}
setup-parent-span-id: ${{ steps.setup.outputs.parent-span-id || steps.setup.outputs.span-id }}
setup-span-id: ${{ steps.setup.outputs.span-id }}
setup-trace-id: ${{ steps.setup.outputs.trace-id }}
slash_command: ${{ needs.pre_activation.outputs.matched_command }}
stale_lock_file_failed: ${{ steps.check-lock-file.outputs.stale_lock_file_failed == 'true' }}
steering_issue_number: ${{ steps.create-steering-issue.outputs.issue_number }}
steering_issue_url: ${{ steps.create-steering-issue.outputs.issue_url }}
text: ${{ steps.sanitized.outputs.text }}
title: ${{ steps.sanitized.outputs.title }}
steps:
- name: Checkout actions folder
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: github/gh-aw
sparse-checkout: |
actions
fetch-depth: 1
clean: false
persist-credentials: false
- name: Setup Scripts
id: setup
uses: ./actions/setup
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
trace-id: ${{ needs.admission.outputs.trace-id || needs.pre_activation.outputs.setup-trace-id }}
parent-span-id: ${{ needs.pre_activation.outputs.setup-parent-span-id || needs.pre_activation.outputs.setup-span-id }}
safe-output-artifact-client: ${{ env.GH_AW_MAX_DAILY_AI_CREDITS != '' }}
env:
GH_AW_SETUP_WORKFLOW_NAME: "/cloclo"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/cloclo.lock.yml@${{ github.ref }}
GH_AW_INFO_VERSION: "0.165.0"
GH_AW_INFO_AWF_VERSION: "v0.29.5"
GH_AW_INFO_ENGINE_ID: "codex"
GH_AW_SETUP_AW_CONTEXT: ${{ inputs.aw_context }}
- name: Mask OTLP telemetry headers
run: bash "${RUNNER_TEMP}/gh-aw/actions/mask_otlp_headers.sh"
- 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: "copilot/gpt-5.6-terra"
GH_AW_INFO_VERSION: "0.165.0"
GH_AW_INFO_AGENT_VERSION: "0.165.0"
GH_AW_INFO_WORKFLOW_NAME: "/cloclo"
GH_AW_INFO_WORKFLOW_ID: ${{ job.workflow_ref }}
GH_AW_INFO_EXPERIMENTAL: "false"
GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true"
GH_AW_INFO_STAGED: "false"
GH_AW_INFO_ALLOWED_DOMAINS: '["*.grafana.net","*.sentry.io","defaults"]'
GH_AW_INFO_FIREWALL_ENABLED: "true"
GH_AW_INFO_AWF_VERSION: "v0.29.5"
GH_AW_INFO_AWMG_VERSION: ""
GH_AW_INFO_FIREWALL_TYPE: "squid"
GH_AW_INFO_AGENT_RUNTIME: ""
GH_AW_INFO_MODEL_CONFIG: '{"routing":{"enabled":false},"models":{"allowed":[],"blocked":[]},"max_ai_credits_source":"default"}'
GH_AW_INFO_MAX_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_MAX_AI_CREDITS || '1000' }}
GH_AW_INFO_CACHE_MEMORY: "true"
GH_AW_INFO_FRONTMATTER_EMOJI: "📊"
GH_AW_COMPILED_STRICT: "true"
GH_AW_INFO_MODEL_COSTS: '{"providers":{"github-copilot":{"models":{"gpt-5.6-terra":{"cost":{"cache_read":"2e-07","cache_write":"2.5e-06","input":"2e-06","output":"1.2e-05"}}}}}}'
GH_AW_INFO_FEATURES: '{"gh-aw-detection":true}'
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
const { main } = require(path.join(actionsDir, 'generate_aw_info.cjs'));
await main(core, context);
- name: Restore daily AIC scan observations
id: restore-daily-aic-cache-fallback
if: ${{ env.GH_AW_ADMISSION_RESULT != 'admitted' && env.GH_AW_MAX_DAILY_AI_CREDITS != '' }}
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
GH_AW_HAS_SLASH_COMMAND: "true"
GH_AW_HAS_LABEL_COMMAND: "true"
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
const { main } = require(path.join(actionsDir, 'restore_aic_scan_cache.cjs'));
await main();
- name: Check daily workflow token guardrail
id: daily-ai-credits-workflow-guardrail
if: ${{ env.GH_AW_ADMISSION_RESULT != 'admitted' && env.GH_AW_MAX_DAILY_AI_CREDITS != '' }}
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
GH_AW_WORKFLOW_NAME: "/cloclo"
GH_AW_WORKFLOW_ID: "cloclo"
GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
GH_AW_WORKFLOW_DISPATCH_AW_CONTEXT: ${{ github.event.inputs.aw_context || '' }}
GH_AW_HAS_SLASH_COMMAND: "true"
GH_AW_HAS_LABEL_COMMAND: "true"
GH_AW_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_AW_MAX_DAILY_AI_CREDITS: "10000"
GH_AW_MAX_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_MAX_AI_CREDITS || '1000' }}
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
const { main } = require(path.join(actionsDir, 'check_daily_aic_workflow_guardrail.cjs'));
await main();
- name: Publish daily AIC scan observations
if: always() && env.GH_AW_ADMISSION_RESULT != 'admitted' && env.GH_AW_MAX_DAILY_AI_CREDITS != ''
continue-on-error: true
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: aic-usage-scan-v2
path: /tmp/gh-aw/agentic-workflow-usage-scan-v2.jsonl
overwrite: true
if-no-files-found: ignore
retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '3' }}
- name: Add eyes 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 || github.event_name == 'workflow_dispatch' && (fromJSON(github.event.inputs.aw_context || '{}').event_type == 'issues' || fromJSON(github.event.inputs.aw_context || '{}').event_type == 'issue_comment' || fromJSON(github.event.inputs.aw_context || '{}').event_type == 'pull_request_review_comment' || fromJSON(github.event.inputs.aw_context || '{}').event_type == 'pull_request' || fromJSON(github.event.inputs.aw_context || '{}').event_type == 'discussion' || fromJSON(github.event.inputs.aw_context || '{}').event_type == 'discussion_comment')
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
GH_AW_REACTION: "eyes"
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
const { main } = require(path.join(actionsDir, 'add_reaction.cjs'));
await main();
- name: Validate COPILOT_GITHUB_TOKEN secret
id: validate-secret
run: bash "${RUNNER_TEMP}/gh-aw/actions/validate_multi_secret.sh" COPILOT_GITHUB_TOKEN Codex https://github.github.com/gh-aw/reference/engines/#github-copilot-default
env:
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
- name: Check for OAuth tokens
id: check-oauth-tokens
run: bash "${RUNNER_TEMP}/gh-aw/actions/check_oauth_tokens.sh"
env:
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }}
GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }}
- name: Checkout .github and .agents folders
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
sparse-checkout: |
.github
.agents
actions/setup
.claude
.codex
.gemini
.pi
sparse-checkout-cone-mode: true
fetch-depth: 1
- name: Save agent config folders for base branch restoration
env:
GH_AW_AGENT_FOLDERS: ".agents .codex .github"
GH_AW_AGENT_FILES: "AGENTS.md"
run: |
bash "${RUNNER_TEMP}/gh-aw/actions/save_base_github_folders.sh"
- name: Create steering issue
id: create-steering-issue
if: steps.daily-ai-credits-workflow-guardrail.outputs.daily_ai_credits_exceeded != 'true'
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
GH_AW_WORKFLOW_NAME: "/cloclo"
GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/cloclo.md"
GH_AW_WORKFLOW_ID: "cloclo"
GH_AW_ENGINE_ID: ${{ steps.generate_aw_info.outputs.engine_id }}
GH_AW_ENGINE_MODEL: ${{ steps.generate_aw_info.outputs.model }}
GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"\\u003e 🎤 *Magnifique! Performance by [{workflow_name}]({run_url})*{ai_credits_suffix}{history_link}\",\"runStarted\":\"🎵 Comme d'habitude! [{workflow_name}]({run_url}) takes the stage on this {event_type}...\",\"runSuccess\":\"🎤 Bravo! [{workflow_name}]({run_url}) has delivered a stunning performance! Standing ovation! 🌟\",\"runFailure\":\"🎵 Intermission... [{workflow_name}]({run_url}) {status}. Check the [run logs]({run_url}) for details.\"}"
with:
github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
const { main } = require(path.join(actionsDir, 'create_steering_issue.cjs'));
await main();
- name: Check workflow lock file
id: check-lock-file
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
GH_AW_WORKFLOW_FILE: "cloclo.lock.yml"
GH_AW_CONTEXT_WORKFLOW_REF: "${{ github.workflow_ref }}"
with:
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
const { main } = require(path.join(actionsDir, 'check_workflow_timestamp_api.cjs'));
await main();
- name: Compute current body text
id: sanitized
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
GH_AW_ALLOWED_DOMAINS: "*.grafana.net,*.sentry.io,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,cdn.playwright.dev,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,json-schema.org,json.schemastore.org,keyserver.ubuntu.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,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,playwright.download.prss.microsoft.com,ppa.launchpad.net,s.symcb.com,s.symcd.com,security.ubuntu.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com"
with:
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
const { main } = require(path.join(actionsDir, '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 || github.event_name == 'workflow_dispatch' && (fromJSON(github.event.inputs.aw_context || '{}').event_type == 'issues' || fromJSON(github.event.inputs.aw_context || '{}').event_type == 'issue_comment' || fromJSON(github.event.inputs.aw_context || '{}').event_type == 'pull_request_review_comment' || fromJSON(github.event.inputs.aw_context || '{}').event_type == 'pull_request' || fromJSON(github.event.inputs.aw_context || '{}').event_type == 'discussion' || fromJSON(github.event.inputs.aw_context || '{}').event_type == 'discussion_comment')
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
GH_AW_WORKFLOW_NAME: "/cloclo"
GH_AW_WORKFLOW_EMOJI: "📊"
GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"\\u003e 🎤 *Magnifique! Performance by [{workflow_name}]({run_url})*{ai_credits_suffix}{history_link}\",\"runStarted\":\"🎵 Comme d'habitude! [{workflow_name}]({run_url}) takes the stage on this {event_type}...\",\"runSuccess\":\"🎤 Bravo! [{workflow_name}]({run_url}) has delivered a stunning performance! Standing ovation! 🌟\",\"runFailure\":\"🎵 Intermission... [{workflow_name}]({run_url}) {status}. Check the [run logs]({run_url}) for details.\"}"
with:
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
const { main } = require(path.join(actionsDir, 'add_workflow_run_comment.cjs'));
await main();
- name: Remove trigger label
id: remove_trigger_label
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
GH_AW_LABEL_NAMES: "[\"cloclo\"]"
with:
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
const { main } = require(path.join(actionsDir, 'remove_trigger_label.cjs'));
await main();
- name: Log runtime features
if: ${{ contains(toJSON(vars), '"GH_AW_RUNTIME_FEATURES":') }}
run: bash "${RUNNER_TEMP}/gh-aw/actions/log_runtime_features_summary.sh"
- name: Create prompt with built-in context
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
github-token: no-authentication
script: |
const promptEnvironment = new Set(["GH_AW_ACTIONS_DIR","GH_AW_EXPR_76DF9333","GH_AW_EXPR_77C1A4D2","GH_AW_EXPR_7C248226","GH_AW_EXPR_C19C384F","GH_AW_GITHUB_ACTOR","GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER","GH_AW_GITHUB_EVENT_INPUTS_ISSUE_NUMBER","GH_AW_GITHUB_EVENT_ISSUE_NUMBER","GH_AW_GITHUB_EVENT_ISSUE_STATE","GH_AW_GITHUB_EVENT_PULL_REQUEST_BASE_SHA","GH_AW_GITHUB_EVENT_PULL_REQUEST_HEAD_SHA","GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER","GH_AW_GITHUB_EVENT_PULL_REQUEST_STATE","GH_AW_GITHUB_REPOSITORY","GH_AW_GITHUB_RUN_ID","GH_AW_GITHUB_WORKSPACE","GH_AW_INCLUDE_PR_CONTEXT","GH_AW_NEEDS_ACTIVATION_OUTPUTS_STEERING_ISSUE_NUMBER","GH_AW_PROMPT","GH_AW_PROMPT_CONFIG","GH_AW_PROMPT_CONTENT_0000","GH_AW_PROMPT_CONTENT_0001","GH_AW_PROMPT_CONTENT_0002","GH_AW_PROMPT_CONTENT_0003","GH_AW_PROMPT_CONTENT_0004","GH_AW_PROMPT_CONTENT_0005","GH_AW_PROMPT_CONTENT_0006","GH_AW_PROMPT_CONTENT_0007","GH_AW_PROMPT_CONTENT_0008","GH_AW_PROMPT_CONTENT_0009","GH_AW_PROMPT_CONTENT_0010","GH_AW_PROMPT_CONTENT_0011","GH_AW_PROMPT_CONTENT_0012","GH_AW_PROMPT_CONTENT_0013","GH_AW_PROMPT_CONTENT_0014","GH_AW_SAFE_OUTPUTS","GH_AW_STEPS_SANITIZED_OUTPUTS_TEXT","GITHUB_ACTION","GITHUB_ACTOR","GITHUB_API_URL","GITHUB_EVENT_NAME","GITHUB_EVENT_PATH","GITHUB_GRAPHQL_URL","GITHUB_JOB","GITHUB_OUTPUT","GITHUB_REF","GITHUB_REPOSITORY","GITHUB_RUN_ATTEMPT","GITHUB_RUN_ID","GITHUB_RUN_NUMBER","GITHUB_SERVER_URL","GITHUB_SHA","GITHUB_STEP_SUMMARY","GITHUB_WORKFLOW","GITHUB_WORKSPACE","PATH","RUNNER_ARCH","RUNNER_OS","RUNNER_TEMP"]);
for (const name of Object.keys(process.env)) {
if (!promptEnvironment.has(name)) delete process.env[name];
}
global.core = core;
global.context = context;
const { main } = require(process.env.GH_AW_ACTIONS_DIR + '/create_prompt.cjs');
await main(core);
env:
GH_AW_ACTIONS_DIR: ${{ runner.temp }}/gh-aw/actions
GH_AW_EXPR_76DF9333: ${{ github.event.pull_request.number || (fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_type == 'pull_request' && fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_number) }}
GH_AW_EXPR_77C1A4D2: ${{ github.event.comment.id || fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').comment_id }}
GH_AW_EXPR_7C248226: ${{ github.event.issue.number || (fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_type == 'issue' && fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_number) }}
GH_AW_EXPR_C19C384F: ${{ github.event.discussion.number || (fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_type == 'discussion' && fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_number) }}
GH_AW_GITHUB_ACTOR: ${{ github.actor }}
GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }}
GH_AW_GITHUB_EVENT_INPUTS_ISSUE_NUMBER: ${{ github.event.inputs.issue_number }}
GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }}
GH_AW_GITHUB_EVENT_ISSUE_STATE: ${{ github.event.issue.state }}
GH_AW_GITHUB_EVENT_PULL_REQUEST_BASE_SHA: ${{ github.event.pull_request.base.sha }}
GH_AW_GITHUB_EVENT_PULL_REQUEST_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }}
GH_AW_GITHUB_EVENT_PULL_REQUEST_STATE: ${{ github.event.pull_request.state }}
GH_AW_GITHUB_REPOSITORY: ${{ github.repository }}
GH_AW_GITHUB_RUN_ID: ${{ github.run_id }}
GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }}
GH_AW_INCLUDE_PR_CONTEXT: ${{ (github.event_name == 'issue_comment' && github.event.issue.pull_request != null) || github.event_name == 'pull_request_review_comment' || github.event_name == 'pull_request_review' }}
GH_AW_NEEDS_ACTIVATION_OUTPUTS_STEERING_ISSUE_NUMBER: ${{ (steps.create-steering-issue.outputs.issue_number) }}
GH_AW_OTLP_ALL_HEADERS: ""
GH_AW_OTLP_ENDPOINTS: ""
GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt
GH_AW_PROMPT_CONFIG: "{\"items\":[{\"content_env\":\"GH_AW_PROMPT_CONTENT_0000\"},{\"file\":\"xpia.md\"},{\"file\":\"temp_folder_prompt.md\"},{\"file\":\"markdown.md\"},{\"file\":\"playwright_prompt.md\"},{\"file\":\"playwright_awf_prompt.md\"},{\"file\":\"cache_memory_prompt.md\"},{\"file\":\"safe_outputs_cli_only_transport_prompt.md\"},{\"file\":\"safe_outputs_prompt.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0001\"},{\"file\":\"safe_outputs_create_pull_request.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0002\"},{\"file\":\"safe_outputs_steering_issue.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0003\"},{\"file\":\"mcp_cli_tools_with_safeoutputs_prompt.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0004\"},{\"file\":\"github_mcp_tools_with_safeoutputs_prompt.md\"},{\"file\":\"pr_context_prompt.md\",\"condition_env\":\"GH_AW_INCLUDE_PR_CONTEXT\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0005\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0006\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0007\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0008\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0009\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0010\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0011\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0012\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0013\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0014\"},{\"author_file\":\".github/workflows/cloclo.md\"}],\"system_item_count\":19,\"author_expressions\":{\"github.actor\":\"GH_AW_GITHUB_ACTOR\",\"github.event.discussion.number\":\"GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER\",\"github.event.inputs.issue_number\":\"GH_AW_GITHUB_EVENT_INPUTS_ISSUE_NUMBER\",\"github.event.issue.number\":\"GH_AW_GITHUB_EVENT_ISSUE_NUMBER\",\"github.event.issue.state\":\"GH_AW_GITHUB_EVENT_ISSUE_STATE\",\"github.event.pull_request.base.sha\":\"GH_AW_GITHUB_EVENT_PULL_REQUEST_BASE_SHA\",\"github.event.pull_request.head.sha\":\"GH_AW_GITHUB_EVENT_PULL_REQUEST_HEAD_SHA\",\"github.event.pull_request.number\":\"GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER\",\"github.event.pull_request.state\":\"GH_AW_GITHUB_EVENT_PULL_REQUEST_STATE\",\"github.repository\":\"GH_AW_GITHUB_REPOSITORY\",\"github.workspace\":\"GH_AW_GITHUB_WORKSPACE\",\"steps.sanitized.outputs.text\":\"GH_AW_STEPS_SANITIZED_OUTPUTS_TEXT\"}}"
GH_AW_PROMPT_CONTENT_0000: |
<system>
GH_AW_PROMPT_CONTENT_0001: |
<safe-output-tools>
Tools: add_comment, create_pull_request, report_missing_tool, report_missing_data, noop(max:2)
GH_AW_PROMPT_CONTENT_0002: |+
<issue-steering>
The steering issue for this run is #__GH_AW_NEEDS_ACTIVATION_OUTPUTS_STEERING_ISSUE_NUMBER__.
GH_AW_PROMPT_CONTENT_0003: |
</safe-output-tools>
GH_AW_PROMPT_CONTENT_0004: |+
<github-context>
The following GitHub context information is available for this workflow:
{{#if github.actor}}
- **actor**: __GH_AW_GITHUB_ACTOR__
{{/if}}
{{#if github.repository}}
- **repository**: __GH_AW_GITHUB_REPOSITORY__
{{/if}}
{{#if github.workspace}}
- **workspace**: __GH_AW_GITHUB_WORKSPACE__
{{/if}}
{{#if github.event.issue.number || (github.aw.context.item_type == 'issue' && github.aw.context.item_number)}}
- **issue-number**: #__GH_AW_EXPR_7C248226__
{{/if}}
{{#if github.event.discussion.number || (github.aw.context.item_type == 'discussion' && github.aw.context.item_number)}}
- **discussion-number**: #__GH_AW_EXPR_C19C384F__
{{/if}}
{{#if github.event.pull_request.number || (github.aw.context.item_type == 'pull_request' && github.aw.context.item_number)}}
- **pull-request-number**: #__GH_AW_EXPR_76DF9333__
{{/if}}
{{#if github.event.comment.id || github.aw.context.comment_id}}
- **comment-id**: __GH_AW_EXPR_77C1A4D2__
{{/if}}
{{#if github.run_id}}
- **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__
{{/if}}
</github-context>
GH_AW_PROMPT_CONTENT_0005: |
</system>
GH_AW_PROMPT_CONTENT_0006: |
{{#runtime-import .github/skills/jqschema/SKILL.md}}
GH_AW_PROMPT_CONTENT_0007: |
{{#runtime-import .github/workflows/shared/mcp/serena-go.md}}
GH_AW_PROMPT_CONTENT_0008: |
{{#runtime-import .github/workflows/shared/reporting.md}}
GH_AW_PROMPT_CONTENT_0009: |
{{#runtime-import .github/workflows/shared/otlp.md}}
GH_AW_PROMPT_CONTENT_0010: |
{{#runtime-import .github/workflows/shared/graders.md}}
GH_AW_PROMPT_CONTENT_0011: |
## Serena Code Analysis
Serena is enabled for **["go"]** in `__GH_AW_GITHUB_WORKSPACE__`. Start by calling `activate_project` with that workspace path, then prefer Serena semantic tools for symbol lookup, references, docs, diagnostics, and structured edits.
GH_AW_PROMPT_CONTENT_0012: |
{{#runtime-import .github/workflows/shared/graders/state-revisit-probability-rep.md}}
GH_AW_PROMPT_CONTENT_0013: |
{{#runtime-import .github/workflows/shared/graders/recurrence-determinism.md}}
GH_AW_PROMPT_CONTENT_0014: |
{{#runtime-import .github/workflows/shared/graders/recurrence-laminarity.md}}
GH_AW_SAFE_OUTPUTS: ${{ runner.temp }}/gh-aw/safeoutputs/outputs.jsonl
GH_AW_STEPS_SANITIZED_OUTPUTS_TEXT: ${{ steps.sanitized.outputs.text }}
OTEL_EXPORTER_OTLP_ENDPOINT: ""
OTEL_EXPORTER_OTLP_HEADERS: ""
OTEL_RESOURCE_ATTRIBUTES: ""
OTEL_SERVICE_NAME: ""
- name: Interpolate variables and render templates
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
github-token: no-authentication
script: |
const promptEnvironment = new Set(["GH_AW_ACTIONS_DIR","GH_AW_ENGINE_ID","GH_AW_GITHUB_ACTOR","GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER","GH_AW_GITHUB_EVENT_INPUTS_ISSUE_NUMBER","GH_AW_GITHUB_EVENT_ISSUE_NUMBER","GH_AW_GITHUB_EVENT_ISSUE_STATE","GH_AW_GITHUB_EVENT_PULL_REQUEST_BASE_SHA","GH_AW_GITHUB_EVENT_PULL_REQUEST_HEAD_SHA","GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER","GH_AW_GITHUB_EVENT_PULL_REQUEST_STATE","GH_AW_GITHUB_REPOSITORY","GH_AW_GITHUB_WORKSPACE","GH_AW_PROMPT","GH_AW_SKILL_DIR","GH_AW_SKILL_EXT","GH_AW_STEPS_SANITIZED_OUTPUTS_TEXT","GH_AW_SUB_AGENT_DIR","GH_AW_SUB_AGENT_EXT","GITHUB_ACTION","GITHUB_ACTOR","GITHUB_API_URL","GITHUB_EVENT_NAME","GITHUB_EVENT_PATH","GITHUB_GRAPHQL_URL","GITHUB_JOB","GITHUB_OUTPUT","GITHUB_REF","GITHUB_REPOSITORY","GITHUB_RUN_ATTEMPT","GITHUB_RUN_ID","GITHUB_RUN_NUMBER","GITHUB_SERVER_URL","GITHUB_SHA","GITHUB_STEP_SUMMARY","GITHUB_WORKFLOW","GITHUB_WORKSPACE","PATH","RUNNER_ARCH","RUNNER_OS","RUNNER_TEMP"]);
for (const name of Object.keys(process.env)) {
if (!promptEnvironment.has(name)) delete process.env[name];
}
global.core = core;
global.context = context;
const { main } = require(process.env.GH_AW_ACTIONS_DIR + '/interpolate_prompt.cjs');
await main({ authorExpressions: {"github.actor":"GH_AW_GITHUB_ACTOR","github.event.discussion.number":"GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER","github.event.inputs.issue_number":"GH_AW_GITHUB_EVENT_INPUTS_ISSUE_NUMBER","github.event.issue.number":"GH_AW_GITHUB_EVENT_ISSUE_NUMBER","github.event.issue.state":"GH_AW_GITHUB_EVENT_ISSUE_STATE","github.event.pull_request.base.sha":"GH_AW_GITHUB_EVENT_PULL_REQUEST_BASE_SHA","github.event.pull_request.head.sha":"GH_AW_GITHUB_EVENT_PULL_REQUEST_HEAD_SHA","github.event.pull_request.number":"GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER","github.event.pull_request.state":"GH_AW_GITHUB_EVENT_PULL_REQUEST_STATE","github.repository":"GH_AW_GITHUB_REPOSITORY","github.workspace":"GH_AW_GITHUB_WORKSPACE","steps.sanitized.outputs.text":"GH_AW_STEPS_SANITIZED_OUTPUTS_TEXT"} });
env:
GH_AW_ACTIONS_DIR: ${{ runner.temp }}/gh-aw/actions
GH_AW_ENGINE_ID: codex
GH_AW_GITHUB_ACTOR: ${{ github.actor }}
GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }}
GH_AW_GITHUB_EVENT_INPUTS_ISSUE_NUMBER: ${{ github.event.inputs.issue_number }}
GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }}
GH_AW_GITHUB_EVENT_ISSUE_STATE: ${{ github.event.issue.state }}
GH_AW_GITHUB_EVENT_PULL_REQUEST_BASE_SHA: ${{ github.event.pull_request.base.sha }}
GH_AW_GITHUB_EVENT_PULL_REQUEST_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }}
GH_AW_GITHUB_EVENT_PULL_REQUEST_STATE: ${{ github.event.pull_request.state }}
GH_AW_GITHUB_REPOSITORY: ${{ github.repository }}
GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }}
GH_AW_OTLP_ALL_HEADERS: ""
GH_AW_OTLP_ENDPOINTS: ""
GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt
GH_AW_SKILL_DIR: .codex/skills
GH_AW_SKILL_EXT: /SKILL.md
GH_AW_STEPS_SANITIZED_OUTPUTS_TEXT: ${{ steps.sanitized.outputs.text }}
GH_AW_SUB_AGENT_DIR: .codex/agents
GH_AW_SUB_AGENT_EXT: .md
OTEL_EXPORTER_OTLP_ENDPOINT: ""
OTEL_EXPORTER_OTLP_HEADERS: ""
OTEL_RESOURCE_ATTRIBUTES: ""
OTEL_SERVICE_NAME: ""
- name: Substitute placeholders
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
github-token: no-authentication
script: |
const promptEnvironment = new Set(["GH_AW_ACTIONS_DIR","GH_AW_ALLOWED_EXTENSIONS","GH_AW_CACHE_DESCRIPTION","GH_AW_CACHE_DIR","GH_AW_EXPR_76DF9333","GH_AW_EXPR_77C1A4D2","GH_AW_EXPR_7C248226","GH_AW_EXPR_C19C384F","GH_AW_GITHUB_ACTOR","GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER","GH_AW_GITHUB_EVENT_INPUTS_ISSUE_NUMBER","GH_AW_GITHUB_EVENT_ISSUE_NUMBER","GH_AW_GITHUB_EVENT_ISSUE_STATE","GH_AW_GITHUB_EVENT_PULL_REQUEST_BASE_SHA","GH_AW_GITHUB_EVENT_PULL_REQUEST_HEAD_SHA","GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER","GH_AW_GITHUB_EVENT_PULL_REQUEST_STATE","GH_AW_GITHUB_REPOSITORY","GH_AW_GITHUB_RUN_ID","GH_AW_GITHUB_WORKSPACE","GH_AW_INCLUDE_PR_CONTEXT","GH_AW_MCP_CLI_SERVERS_LIST","GH_AW_NEEDS_ACTIVATION_OUTPUTS_STEERING_ISSUE_NUMBER","GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED","GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_MATCHED_COMMAND","GH_AW_PROMPT","GH_AW_STEPS_SANITIZED_OUTPUTS_TEXT","GITHUB_ACTION","GITHUB_ACTOR","GITHUB_API_URL","GITHUB_EVENT_NAME","GITHUB_EVENT_PATH","GITHUB_GRAPHQL_URL","GITHUB_JOB","GITHUB_OUTPUT","GITHUB_REF","GITHUB_REPOSITORY","GITHUB_RUN_ATTEMPT","GITHUB_RUN_ID","GITHUB_RUN_NUMBER","GITHUB_SERVER_URL","GITHUB_SHA","GITHUB_STEP_SUMMARY","GITHUB_WORKFLOW","GITHUB_WORKSPACE","PATH","RUNNER_ARCH","RUNNER_OS","RUNNER_TEMP"]);
for (const name of Object.keys(process.env)) {
if (!promptEnvironment.has(name)) delete process.env[name];
}
global.core = core;
global.context = context;
const substitutePlaceholders = require(process.env.GH_AW_ACTIONS_DIR + '/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_EXPR_76DF9333: process.env.GH_AW_EXPR_76DF9333,
GH_AW_EXPR_77C1A4D2: process.env.GH_AW_EXPR_77C1A4D2,
GH_AW_EXPR_7C248226: process.env.GH_AW_EXPR_7C248226,
GH_AW_EXPR_C19C384F: process.env.GH_AW_EXPR_C19C384F,
GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR,
GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: process.env.GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER,
GH_AW_GITHUB_EVENT_INPUTS_ISSUE_NUMBER: process.env.GH_AW_GITHUB_EVENT_INPUTS_ISSUE_NUMBER,
GH_AW_GITHUB_EVENT_ISSUE_NUMBER: process.env.GH_AW_GITHUB_EVENT_ISSUE_NUMBER,
GH_AW_GITHUB_EVENT_ISSUE_STATE: process.env.GH_AW_GITHUB_EVENT_ISSUE_STATE,
GH_AW_GITHUB_EVENT_PULL_REQUEST_BASE_SHA: process.env.GH_AW_GITHUB_EVENT_PULL_REQUEST_BASE_SHA,
GH_AW_GITHUB_EVENT_PULL_REQUEST_HEAD_SHA: process.env.GH_AW_GITHUB_EVENT_PULL_REQUEST_HEAD_SHA,
GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: process.env.GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER,
GH_AW_GITHUB_EVENT_PULL_REQUEST_STATE: process.env.GH_AW_GITHUB_EVENT_PULL_REQUEST_STATE,
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_WORKSPACE: process.env.GH_AW_GITHUB_WORKSPACE,
GH_AW_INCLUDE_PR_CONTEXT: process.env.GH_AW_INCLUDE_PR_CONTEXT,
GH_AW_MCP_CLI_SERVERS_LIST: process.env.GH_AW_MCP_CLI_SERVERS_LIST,
GH_AW_NEEDS_ACTIVATION_OUTPUTS_STEERING_ISSUE_NUMBER: process.env.GH_AW_NEEDS_ACTIVATION_OUTPUTS_STEERING_ISSUE_NUMBER,
GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: process.env.GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED,
GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_MATCHED_COMMAND: process.env.GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_MATCHED_COMMAND,
GH_AW_STEPS_SANITIZED_OUTPUTS_TEXT: process.env.GH_AW_STEPS_SANITIZED_OUTPUTS_TEXT
}
});
env:
GH_AW_ACTIONS_DIR: ${{ runner.temp }}/gh-aw/actions
GH_AW_ALLOWED_EXTENSIONS: ""
GH_AW_CACHE_DESCRIPTION: ""
GH_AW_CACHE_DIR: /tmp/gh-aw/cache-memory/
GH_AW_EXPR_76DF9333: ${{ github.event.pull_request.number || (fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_type == 'pull_request' && fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_number) }}
GH_AW_EXPR_77C1A4D2: ${{ github.event.comment.id || fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').comment_id }}
GH_AW_EXPR_7C248226: ${{ github.event.issue.number || (fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_type == 'issue' && fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_number) }}
GH_AW_EXPR_C19C384F: ${{ github.event.discussion.number || (fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_type == 'discussion' && fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_number) }}
GH_AW_GITHUB_ACTOR: ${{ github.actor }}
GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }}
GH_AW_GITHUB_EVENT_INPUTS_ISSUE_NUMBER: ${{ github.event.inputs.issue_number }}
GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }}
GH_AW_GITHUB_EVENT_ISSUE_STATE: ${{ github.event.issue.state }}
GH_AW_GITHUB_EVENT_PULL_REQUEST_BASE_SHA: ${{ github.event.pull_request.base.sha }}
GH_AW_GITHUB_EVENT_PULL_REQUEST_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }}
GH_AW_GITHUB_EVENT_PULL_REQUEST_STATE: ${{ github.event.pull_request.state }}
GH_AW_GITHUB_REPOSITORY: ${{ github.repository }}
GH_AW_GITHUB_RUN_ID: ${{ github.run_id }}
GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }}
GH_AW_INCLUDE_PR_CONTEXT: ${{ (github.event_name == 'issue_comment' && github.event.issue.pull_request != null) || github.event_name == 'pull_request_review_comment' || github.event_name == 'pull_request_review' }}
GH_AW_MCP_CLI_SERVERS_LIST: |-
- `agenticworkflows` — run `agenticworkflows --help` to see available tools
- `safeoutputs` — run `safeoutputs --help` to see available tools
- `serena` — run `serena --help` to see available tools
GH_AW_NEEDS_ACTIVATION_OUTPUTS_STEERING_ISSUE_NUMBER: ${{ (steps.create-steering-issue.outputs.issue_number) }}
GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: ${{ needs.pre_activation.outputs.activated }}
GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_MATCHED_COMMAND: ${{ needs.pre_activation.outputs.matched_command }}
GH_AW_OTLP_ALL_HEADERS: ""
GH_AW_OTLP_ENDPOINTS: ""
GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt
GH_AW_STEPS_SANITIZED_OUTPUTS_TEXT: ${{ steps.sanitized.outputs.text }}
OTEL_EXPORTER_OTLP_ENDPOINT: ""
OTEL_EXPORTER_OTLP_HEADERS: ""
OTEL_RESOURCE_ATTRIBUTES: ""
OTEL_SERVICE_NAME: ""
- name: Validate prompt placeholders
run: |
bash "${RUNNER_TEMP}/gh-aw/actions/validate_prompt_placeholders.sh"
env:
GH_AW_OTLP_ALL_HEADERS: ""
GH_AW_OTLP_ENDPOINTS: ""
GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt
OTEL_EXPORTER_OTLP_ENDPOINT: ""
OTEL_EXPORTER_OTLP_HEADERS: ""
OTEL_RESOURCE_ATTRIBUTES: ""
OTEL_SERVICE_NAME: ""
- name: Print prompt
run: |
bash "${RUNNER_TEMP}/gh-aw/actions/print_prompt_summary.sh"
env:
GH_AW_OTLP_ALL_HEADERS: ""
GH_AW_OTLP_ENDPOINTS: ""
GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt
OTEL_EXPORTER_OTLP_ENDPOINT: ""
OTEL_EXPORTER_OTLP_HEADERS: ""
OTEL_RESOURCE_ATTRIBUTES: ""
OTEL_SERVICE_NAME: ""
- name: Inventory installed skills
if: success() || failure()
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
GH_AW_SKILL_DIR: ".codex/skills"
with:
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
const { main } = require(path.join(actionsDir, 'skill_inventory.cjs'));
await main();
- name: Upload info artifact
if: success() || failure()
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: info
path: /tmp/gh-aw/aw_info.json
if-no-files-found: ignore
retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '0' }}
- name: Stage prompt files for artifact upload
run: |
mkdir -p /tmp/gh-aw/aw-prompts
cp -a "${RUNNER_TEMP}/gh-aw/aw-prompts/." /tmp/gh-aw/aw-prompts/
- name: Upload activation artifact
if: success() || failure()
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: activation
include-hidden-files: true
path: |
/tmp/gh-aw/aw_info.json
/tmp/gh-aw/models.json
/tmp/gh-aw/aw-prompts/prompt.txt
/tmp/gh-aw/aw-prompts/system.txt
/tmp/gh-aw/aw-prompts/user.txt
/tmp/gh-aw/aw-prompts/prompt-template.txt
/tmp/gh-aw/aw-prompts/prompt-import-tree.json
/tmp/gh-aw/aw-prompts/prompt-literal-values.json
/tmp/gh-aw/github_rate_limits.jsonl
/tmp/gh-aw/base
/tmp/gh-aw/.codex/agents
/tmp/gh-aw/.codex/skills
/tmp/gh-aw/skill_inventory.json
if-no-files-found: ignore
retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '1' }}
admission:
name: admission
needs: pre_activation
if: >
(needs.pre_activation.outputs.activated == 'true' && ((fromJSON(github.event.inputs.aw_context || '{}').event_type == 'issues' ||
fromJSON(github.event.inputs.aw_context || '{}').event_type == 'pull_request' || fromJSON(github.event.inputs.aw_context ||
'{}').event_type == 'discussion') && (fromJSON(github.event.inputs.aw_context || '{}').trigger_label == 'cloclo') ||
!(fromJSON(github.event.inputs.aw_context || '{}').event_type == 'issues' || fromJSON(github.event.inputs.aw_context ||
'{}').event_type == 'pull_request' || fromJSON(github.event.inputs.aw_context || '{}').event_type == 'discussion'))) &&
(vars.GH_AW_DEFAULT_ADMISSION_URL != '')
runs-on: ubuntu-slim
# Permissions for the admission job (workflow permissions default to none).
permissions:
contents: read
id-token: write
timeout-minutes: 5
outputs:
max-ai-credits: ${{ steps.admission.outputs.max-ai-credits }}
max-ai-credits-evals: ${{ steps.admission.outputs.max-ai-credits-evals }}
max-ai-credits-threat-detection: ${{ steps.admission.outputs.max-ai-credits-threat-detection }}
result: ${{ steps.admission.outputs.result }}
trace-id: ${{ steps.admission.outputs.trace-id }}
steps:
- name: Checkout actions folder
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: github/gh-aw
sparse-checkout: |
actions
fetch-depth: 1
clean: false
persist-credentials: false
- name: Setup Scripts
id: setup
uses: ./actions/setup
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
trace-id: ${{ needs.pre_activation.outputs.setup-trace-id }}
parent-span-id: ${{ needs.pre_activation.outputs.setup-parent-span-id || needs.pre_activation.outputs.setup-span-id }}
env:
GH_AW_SETUP_WORKFLOW_NAME: "/cloclo"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/unknown.lock.yml@${{ github.ref }}
- name: Check workflow admission
id: admission
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
GH_AW_DEFAULT_ADMISSION_URL: ${{ vars.GH_AW_DEFAULT_ADMISSION_URL }}
GH_AW_DEFAULT_ADMISSION_AUDIENCE: ${{ vars.GH_AW_DEFAULT_ADMISSION_AUDIENCE }}
GH_AW_DEFAULT_ADMISSION_ON_OUTAGE: ${{ vars.GH_AW_DEFAULT_ADMISSION_ON_OUTAGE }}
GH_AW_ADMISSION_WORKFLOW_HASH: "ec3efe8f7f3cc8e20f49b04164321e6e2923f0d55b80df96fbbc96638b33ade5:1577e7c80f76a3124113c4b9762a1f0094660f2ff5f8295d074879354653dfe3"
GH_AW_INFO_WORKFLOW_ID: ${{ job.workflow_ref }}
GITHUB_ACTOR: ${{ github.actor }}
GITHUB_TRIGGERING_ACTOR: ${{ github.triggering_actor }}
with:
script: |
await require(require('node:path').join(process.env.RUNNER_TEMP, 'gh-aw', 'actions', 'activation_admission.cjs')).main(core, github, context, exec, io, getOctokit);
agent:
name: agent
needs: activation
if: >
((!cancelled()) && needs.activation.result == 'success') && (needs.activation.outputs.daily_ai_credits_exceeded != 'true')
runs-on: ubuntu-latest
# Permissions for the agent job (workflow permissions default to none).
permissions:
actions: read
contents: read
discussions: read
issues: read
pull-requests: read
cache-mode: read
timeout-minutes: 60
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_OBJECT_PACK_FETCH_DEPTHS: ${{ vars.GH_AW_OBJECT_PACK_FETCH_DEPTHS }}
GH_AW_OBJECT_PACK_MAX_BYTES: ${{ vars.GH_AW_OBJECT_PACK_MAX_BYTES }}
GH_AW_OBJECT_PACK_MAX_OBJECTS: ${{ vars.GH_AW_OBJECT_PACK_MAX_OBJECTS }}
GH_AW_OBJECT_PACK_TIMEOUT_MS: ${{ vars.GH_AW_OBJECT_PACK_TIMEOUT_MS }}
GH_AW_PROJECT_UTC: "-08:00"
GH_AW_PR_HEAD_BASE_BRANCH: ""
GH_AW_PR_HEAD_BASE_PR_NUMBER: ""
GH_AW_PR_HEAD_BASE_REF: ""
GH_AW_PR_HEAD_BASE_REPO: ""
GH_AW_PR_HEAD_BASE_SHA: ""
GH_AW_PR_HEAD_REPO: ""
GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }}
GH_AW_TARGET_REPO_SLUG: ""
GH_AW_WORKFLOW_ID_SANITIZED: cloclo
PLAYWRIGHT_MCP_SANDBOX: false
outputs:
agentic_engine_timeout: ${{ steps.detect-agent-errors.outputs.agentic_engine_timeout || 'false' }}
ai_credits_rate_limit_error: ${{ steps.parse-mcp-gateway.outputs.ai_credits_rate_limit_error || 'false' }}
aic: ${{ steps.parse-token-usage.outputs.aic }}
ambient_context: ${{ steps.parse-token-usage.outputs.ambient_context }}
cache_memory_restore_0_cache_hit: ${{ steps.restore_cache_memory_0.outputs.cache-hit || 'false' }}
cache_memory_restore_0_matched_key: ${{ steps.restore_cache_memory_0.outputs.cache-matched-key || '' }}
checkout_pr_invalidated: ${{ steps.checkout-pr.outputs.checkout_pr_invalidated || 'false' }}
checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }}
has_patch: ${{ steps.collect_output.outputs.has_patch }}
http_400_response_error: ${{ steps.detect-agent-errors.outputs.http_400_response_error || 'false' }}
inference_access_error: ${{ steps.detect-agent-errors.outputs.inference_access_error || 'false' }}
invocation_cap_exceeded: ${{ steps.detect-agent-errors.outputs.invocation_cap_exceeded || 'false' }}
max_cache_misses_exceeded: ${{ steps.detect-agent-errors.outputs.max_cache_misses_exceeded || 'false' }}
mcp_policy_error: ${{ steps.detect-agent-errors.outputs.mcp_policy_error || 'false' }}
missing_model_pricing_error: ${{ steps.detect-agent-errors.outputs.missing_model_pricing_error || 'false' }}
missing_model_pricing_model_name: ${{ steps.detect-agent-errors.outputs.missing_model_pricing_model_name || '' }}
model: ${{ needs.activation.outputs.model }}
model_endpoint_mismatch_error: ${{ steps.detect-agent-errors.outputs.model_endpoint_mismatch_error || 'false' }}
model_not_supported_error: ${{ steps.detect-agent-errors.outputs.model_not_supported_error || 'false' }}
output: ${{ steps.collect_output.outputs.output }}
output_types: ${{ steps.collect_output.outputs.output_types }}
setup-parent-span-id: ${{ steps.setup.outputs.parent-span-id || steps.setup.outputs.span-id }}
setup-span-id: ${{ steps.setup.outputs.span-id }}
setup-trace-id: ${{ steps.setup.outputs.trace-id }}
shell_expansion_guard_rejected: ${{ steps.detect-agent-errors.outputs.shell_expansion_guard_rejected || 'false' }}
unknown_model_ai_credits: ${{ steps.parse-mcp-gateway.outputs.unknown_model_ai_credits || 'false' }}
steps:
- name: Checkout actions folder
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: github/gh-aw
sparse-checkout: |
actions
fetch-depth: 1
clean: false
persist-credentials: false
- name: Setup Scripts
id: setup
uses: ./actions/setup
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
trace-id: ${{ needs.activation.outputs.setup-trace-id }}
parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }}
env:
GH_AW_SETUP_WORKFLOW_NAME: "/cloclo"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/cloclo.lock.yml@${{ github.ref }}
GH_AW_INFO_VERSION: "0.165.0"
GH_AW_INFO_AWF_VERSION: "v0.29.5"
GH_AW_INFO_ENGINE_ID: "codex"
GH_AW_SETUP_AW_CONTEXT: ${{ inputs.aw_context }}
- name: Set runtime paths
id: set-runtime-paths
env:
GH_AW_RUNNER_TOOL_CACHE: ${{ runner.tool_cache }}
run: | # zizmor: ignore[github-env] - runner.tool_cache is set by GitHub Actions, not user input.
if [ -z "${RUNNER_TOOL_CACHE:-}" ]; then
echo "RUNNER_TOOL_CACHE=${GH_AW_RUNNER_TOOL_CACHE}" >> "$GITHUB_ENV"
fi
{
echo "GH_AW_SAFE_OUTPUTS=${RUNNER_TEMP}/gh-aw/safeoutputs/outputs.jsonl"
echo "GH_AW_SAFE_OUTPUTS_CONFIG_PATH=${RUNNER_TEMP}/gh-aw/safeoutputs/config.json"
echo "GH_AW_SAFE_OUTPUTS_TOOLS_PATH=${RUNNER_TEMP}/gh-aw/safeoutputs/tools.json"
} >> "$GITHUB_OUTPUT"
- name: Mask OTLP telemetry headers
run: bash "${RUNNER_TEMP}/gh-aw/actions/mask_otlp_headers.sh"
- name: Checkout repository (gh-aw default)
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Setup Go for CLI build
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version-file: go.mod
cache: true
- name: Build gh-aw CLI
run: |
echo "Building gh-aw CLI for linux/amd64..."
mkdir -p dist
VERSION=$(git describe --tags --always --dirty)
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \
-ldflags "-s -w -X main.version=${VERSION}" \
-o dist/gh-aw-linux-amd64 \
./cmd/gh-aw
# Copy binary to root for direct execution in user-defined steps
cp dist/gh-aw-linux-amd64 ./gh-aw
chmod +x ./gh-aw
echo "✓ Built gh-aw CLI successfully"
- name: Setup Docker Buildx
uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1
- name: Build gh-aw Docker image
uses: docker/build-push-action@c3c9e263c25d99ce0380d002d59b67737d91b0dc # v7.4.0
with:
context: .
platforms: linux/amd64
push: false
load: true
tags: localhost/gh-aw:dev
build-args: |
BINARY=dist/gh-aw-linux-amd64
- name: Initialize agent execution evidence
run: |
mkdir -p "/tmp/gh-aw"
evidence_tmp="/tmp/gh-aw/agent_execution.json.tmp"
printf '{"version":1,"component":"agent","run_id":%s,"run_attempt":%s,"state":"not_started"}\n' "$GITHUB_RUN_ID" "$GITHUB_RUN_ATTEMPT" > "$evidence_tmp"
mv "$evidence_tmp" "/tmp/gh-aw/agent_execution.json"
- 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 }}
- name: Download activation artifact
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: activation
path: /tmp/gh-aw
# 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
id: restore_cache_memory_0
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
key: memory-none-nopolicy-cloclo-memory-${{ github.workflow }}-${{ github.run_id }}
path: /tmp/gh-aw/cache-memory
restore-keys: |
memory-none-nopolicy-cloclo-memory-${{ github.workflow }}-
- 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:
GITHUB_REPOSITORY: ${{ github.repository }}
GITHUB_SERVER_URL: ${{ github.server_url }}
GITHUB_TOKEN: ${{ github.token }}
run: bash "${RUNNER_TEMP}/gh-aw/actions/configure_git_credentials.sh"
- name: Checkout PR branch
id: checkout-pr
if: |
github.event.pull_request || github.event.issue.pull_request || github.event_name == 'workflow_dispatch'
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
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 path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
const { main } = require(path.join(actionsDir, 'checkout_pr_branch.cjs'));
await main();
- name: Setup Node.js
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version: '24'
package-manager-cache: false
- name: Install Codex CLI
run: npm install --ignore-scripts -g @openai/codex@0.165.0
env:
NPM_CONFIG_MIN_RELEASE_AGE: '3'
- name: Install AWF binary
env:
GH_TOKEN: ${{ github.token }}
GH_HOST: github.com
run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.29.5 --rootless
- name: Install Playwright CLI
run: npm install -g @playwright/cli@0.1.22
env:
NPM_CONFIG_MIN_RELEASE_AGE: '3'
timeout-minutes: 10
- name: Install Playwright browsers
run: bash "${RUNNER_TEMP}/gh-aw/actions/install_playwright_browsers.sh" chromium
env:
PLAYWRIGHT_BROWSERS_PATH: ${{ runner.temp }}/gh-aw/playwright-browsers
timeout-minutes: 10
- name: Install Playwright CLI skills
run: playwright-cli install --skills
env:
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: '1'
PLAYWRIGHT_BROWSERS_PATH: ${{ runner.temp }}/gh-aw/playwright-browsers
timeout-minutes: 10
- name: Determine automatic lockdown mode for GitHub MCP Server
id: determine-automatic-lockdown
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
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 path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const determineAutomaticLockdown = require(path.join(actionsDir, 'determine_automatic_lockdown.cjs'));
await determineAutomaticLockdown(github, context, core);
- name: Restore agent config folders from base branch
if: steps.checkout-pr.outputs.checked_out == 'true'
env:
GH_AW_AGENT_FOLDERS: ".agents .codex .github"
GH_AW_AGENT_FILES: "AGENTS.md"
run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_base_github_folders.sh"
- name: Restore inline sub-agents from activation artifact
env:
GH_AW_SUB_AGENT_DIR: ".codex/agents"
GH_AW_SUB_AGENT_EXT: ".md"
run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_inline_sub_agents.sh"
- name: Restore inline skills from activation artifact
env:
GH_AW_SKILL_DIR: ".codex/skills"
run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_inline_skills.sh"
- name: Setup Node.js for Serena
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version: "24"
- name: Setup Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
cache: true
go-version-file: go.mod
- name: Expose Go to Serena container
run: "set -euo pipefail\nunset GOROOT\ngo_root=\"$(GOTOOLCHAIN=local go env GOROOT)\"\ncase \"$go_root\" in\n \"${RUNNER_TOOL_CACHE:?RUNNER_TOOL_CACHE must be set}\"/go/*) ;;\n *)\n echo \"Serena Go runtime is outside its read-only runner tool-cache mount; check actions/setup-go and RUNNER_TOOL_CACHE.\" >&2\n exit 1\n ;;\nesac\nif [ ! -x \"$go_root/bin/go\" ]; then\n echo \"Serena Go runtime has no executable bin/go in the mounted toolchain.\" >&2\n exit 1\nfi\nexport GOROOT=\"$go_root\"\ngopls_bin=\"$RUNNER_TOOL_CACHE/gopls/0.22.0/bin\"\nif ! CGO_ENABLED=0 GOTOOLCHAIN=local GOBIN=\"$gopls_bin\" \"$go_root/bin/go\" install golang.org/x/tools/gopls@v0.22.0; then\n echo \"Serena Go preflight failed: could not install gopls v0.22.0 with the selected Go toolchain.\" >&2\n exit 1\nfi\nif ! \"$gopls_bin/gopls\" version; then\n echo \"Serena Go preflight failed: installed gopls cannot start.\" >&2\n exit 1\nfi\nprintf 'GOROOT=%s\\n' \"$go_root\" >> \"$GITHUB_ENV\"\nprintf 'GH_AW_SERENA_GO_PATH=%s/bin:%s:%s\\n' \"$go_root\" \"$gopls_bin\" \"$PATH\" >> \"$GITHUB_ENV\"\n\"$go_root/bin/go\" version\n"
- name: Check Serena Go semantic analysis
run: "set -euo pipefail\nif ! docker run --rm --init \\\n --network host \\\n --mount \"type=bind,source=$GITHUB_WORKSPACE,target=$GITHUB_WORKSPACE\" \\\n --mount \"type=bind,source=$RUNNER_TOOL_CACHE,target=$RUNNER_TOOL_CACHE,readonly\" \\\n --env \"PATH=$GH_AW_SERENA_GO_PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\" \\\n --entrypoint /usr/bin/timeout \\\n ghcr.io/oraios/serena:1.7.0@sha256:6c9459e4246a39c9deaa4f23fb05a526ac6e237b24c8e84a927a098fa1ab6730 \\\n 240 /workspaces/serena/.venv/bin/serena project health-check \"$GITHUB_WORKSPACE\"; then\n echo \"Serena Go preflight failed: Go language-server semantic health check failed or timed out. Check the gopls and Serena diagnostics above; the agent will not start.\" >&2\n exit 1\nfi\necho \"Serena Go preflight passed: gopls started and semantic symbol analysis succeeded.\"\n"
timeout-minutes: 5
- name: Download container images
run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.29.5@sha256:921e50aed7b2a67265f42ab03c7d54a32c641922cc64f0875a5ae2bcb8b37532 ghcr.io/github/gh-aw-firewall/api-proxy:0.29.5@sha256:f36a9fc78aef0509ed5fa280819848cbdf099f60d7b338455ea54a5def18d6b1 ghcr.io/github/gh-aw-firewall/squid:0.29.5@sha256:34260cb89ea5d6d55b93ce13a5fe1772dbe8e1592e1200370160b7f5a0bd2ecd ghcr.io/github/gh-aw-mcpg:v0.5.0@sha256:d3544a4222e7efeeeb38669d8a1af0c72691c55b8f6506b15aa5920f7f31b7bc ghcr.io/github/gh-aw-node@sha256:2c2ea524e648b91c8333ce246e3838fcf5b19ac70e45baac1a51b9207299749f ghcr.io/github/github-mcp-server:v2.0.3@sha256:250bc6ce70788207608ef74cef4397230ff2e8481218da74d6093e4bd9101132 ghcr.io/oraios/serena:1.7.0@sha256:6c9459e4246a39c9deaa4f23fb05a526ac6e237b24c8e84a927a098fa1ab6730
- name: Configure Codex
run: |
set -o pipefail
codex debug models --bundled | "$(command -v node)" "${RUNNER_TEMP}/gh-aw/actions/convert_gateway_config_codex.cjs" --direct-tools
"$(command -v node)" "${RUNNER_TEMP}/gh-aw/actions/convert_gateway_config_codex.cjs" --bootstrap
env:
CODEX_HOME: /tmp/gh-aw/mcp-config
GH_AW_CODEX_CONFIG_JSON: '{"defaults":{"features":{"code_mode":false,"code_mode_only":false,"plugins":false,"shell_tool":true},"history":{"persistence":"none"},"mcp_servers":{"agenticworkflows":{"startup_timeout_sec":120,"tool_timeout_sec":60},"github":{"http_headers":{"User-Agent":"cloclo"},"startup_timeout_sec":120,"tool_timeout_sec":60},"safeoutputs":{"startup_timeout_sec":120,"tool_timeout_sec":60},"serena":{"startup_timeout_sec":120,"tool_timeout_sec":60}},"model_catalog_json":"/tmp/gh-aw/mcp-config/models.json","model_provider":"openai-proxy","model_providers":{"openai-proxy":{"base_url":"http://172.30.0.30:10002","env_key":"CODEX_API_KEY","name":"OpenAI AWF proxy","requires_openai_auth":false,"supports_websockets":false,"wire_api":"responses"}},"otel":{"metrics_exporter":"none"},"shell_environment_policy":{"ignore_default_excludes":false,"include_only":["ALL_PROXY","CURL_CA_BUNDLE","GITHUB_WORKSPACE","GIT_AUTHOR_EMAIL","GIT_AUTHOR_NAME","GIT_COMMITTER_EMAIL","GIT_COMMITTER_NAME","HOME","HTTPS_PROXY","HTTP_PROXY","LANG","LC_ALL","LC_CTYPE","LOGNAME","NODE_EXTRA_CA_CERTS","NO_PROXY","PATH","PLAYWRIGHT_BROWSERS_PATH","REQUESTS_CA_BUNDLE","RUNNER_TEMP","RUNNER_TOOL_CACHE","SHELL","SSL_CERT_DIR","SSL_CERT_FILE","TEMP","TMP","TMPDIR","USER","all_proxy","http_proxy","https_proxy","no_proxy"],"inherit":"all"}},"overrides":{},"disablePlugins":true}'
- name: Build and install gh-aw CLI from source
run: |
gh extension remove aw || true
make build
gh extension install .
gh aw version
env:
GH_TOKEN: ${{ github.token }}
- name: Copy gh-aw binary for MCP Server
run: |
bash "${RUNNER_TEMP}/gh-aw/actions/copy_gh_aw_binary_for_mcp.sh"
- name: Prepare Safe Outputs Directories
run: |
mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs"
mkdir -p /tmp/gh-aw/safeoutputs
mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs
- name: Generate Safe Outputs Config
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
GH_AW_FILE_ROOT: "${{ runner.temp }}/gh-aw"
GH_AW_FILE_CONFIG: "{\"files\":[{\"path\":\"safeoutputs/config.json\",\"content_env\":\"GH_AW_SAFE_OUTPUTS_CONFIG\"}]}"
GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"max\":1,\"target\":\"${{ inputs.issue_number || 'triggering' }}\"},\"create_pull_request\":{\"excluded_files\":[\".github/workflows/*.lock.yml\"],\"expires\":48,\"labels\":[\"automation\",\"cloclo\"],\"max\":1,\"max_patch_files\":100,\"max_patch_size\":4096,\"protect_top_level_dot_folders\":true,\"protected_files\":[\"package.json\",\"bun.lockb\",\"bunfig.toml\",\"deno.json\",\"deno.jsonc\",\"deno.lock\",\"global.json\",\"NuGet.Config\",\"Directory.Packages.props\",\"mix.exs\",\"mix.lock\",\"go.mod\",\"go.sum\",\"stack.yaml\",\"stack.yaml.lock\",\"pom.xml\",\"build.gradle\",\"build.gradle.kts\",\"settings.gradle\",\"settings.gradle.kts\",\"gradle.properties\",\"package-lock.json\",\"yarn.lock\",\"pnpm-lock.yaml\",\"npm-shrinkwrap.json\",\"requirements.txt\",\"Pipfile\",\"Pipfile.lock\",\"pyproject.toml\",\"setup.py\",\"setup.cfg\",\"Gemfile\",\"Gemfile.lock\",\"uv.lock\",\"CODEOWNERS\",\"DESIGN.md\",\"README.md\",\"CONTRIBUTING.md\",\"SECURITY.md\",\"CODE_OF_CONDUCT.md\",\"AGENTS.md\"],\"protected_files_path_exclude\":[\".changeset/*.md\"],\"protected_files_policy\":\"fallback-to-issue\",\"title_prefix\":\"[cloclo] \"},\"create_report_incomplete_issue\":{},\"noop\":{\"max\":2,\"report-as-issue\":\"false\"},\"report_incomplete\":{},\"report_missing_data\":{},\"report_missing_tool\":{}}"
with:
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
const { main } = require(path.join(actionsDir, 'create_files.cjs'));
await main();
- name: Generate Safe Outputs Tools
env:
GH_AW_TOOLS_META_JSON: |
{
"description_suffixes": {
"add_comment": " CONSTRAINTS: Maximum 1 comment(s) can be added. Target: ${GH_AW_EXPR_2F02427A}. Supports reply_to_id for discussion threading.",
"create_pull_request": " CONSTRAINTS: Maximum 1 pull request(s) can be created. Title will be prefixed with \"[cloclo] \". Labels [\"automation\" \"cloclo\"] will be automatically added."
},
"repo_params": {},
"dynamic_tools": []
}
GH_AW_VALIDATION_JSON: |
{
"add_comment": {
"defaultMax": 1,
"fields": {
"body": {
"required": true,
"type": "string",
"sanitize": true,
"maxLength": 65000
},
"comment_id": {
"optionalPositiveInteger": true
},
"item_number": {
"issueOrPRNumber": true
},
"pr": {
"issueOrPRNumber": true
},
"pr_number": {
"issueOrPRNumber": true
},
"reply_to_id": {
"type": "string",
"maxLength": 256
},
"repo": {
"type": "string",
"maxLength": 256
},
"target": {
"type": "string",
"enum": [
"status"
]
},
"temporary_id": {
"type": "string",
"pattern": "^#?aw_[A-Za-z0-9_]{3,12}$"
}
}
},
"create_pull_request": {
"defaultMax": 1,
"fields": {
"base": {
"type": "string",
"sanitize": true,
"maxLength": 128
},
"body": {
"required": true,
"type": "string",
"sanitize": true,
"maxLength": 65000
},
"branch": {
"required": true,
"type": "string",
"sanitize": true,
"maxLength": 256
},
"dependencies": {
"type": "array",
"itemType": "string",
"itemSanitize": true,
"itemMaxLength": 256
},
"draft": {
"type": "boolean"
},
"labels": {
"type": "array",
"itemType": "string",
"itemSanitize": true,
"itemMaxLength": 128
},
"repo": {
"type": "string",
"maxLength": 256
},
"stack_position": {
"optionalPositiveInteger": true
},
"stack_root": {
"type": "string",
"sanitize": true,
"maxLength": 256
},
"temporary_id": {
"type": "string",
"pattern": "^#?aw_[A-Za-z0-9_]{3,12}$"
},
"title": {
"required": true,
"type": "string",
"sanitize": true,
"maxLength": 128
}
}
},
"noop": {
"defaultMax": 2,
"fields": {
"message": {
"required": true,
"type": "string",
"sanitize": true,
"maxLength": 65000
}
}
},
"report_incomplete": {
"defaultMax": 5,
"fields": {
"details": {
"type": "string",
"sanitize": true,
"maxLength": 65000
},
"reason": {
"required": true,
"type": "string",
"sanitize": true,
"maxLength": 1024
}
}
},
"report_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
}
}
},
"report_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
}
}
}
}
GH_AW_EXPR_2F02427A: ${{ inputs.issue_number || 'triggering' }}
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
const { main } = require(path.join(actionsDir, 'generate_safe_outputs_tools.cjs'));
await main();
- name: Start MCP Gateway
id: start-mcp-gateway
env:
CODEX_HOME: /tmp/gh-aw/mcp-config
DEBUG: ${{ env.DEBUG || runner.debug == '1' && '*' || '' }}
GH_AW_OBJECT_PACK_FETCH_DEPTHS: ${{ vars.GH_AW_OBJECT_PACK_FETCH_DEPTHS }}
GH_AW_OBJECT_PACK_MAX_BYTES: ${{ vars.GH_AW_OBJECT_PACK_MAX_BYTES }}
GH_AW_OBJECT_PACK_MAX_OBJECTS: ${{ vars.GH_AW_OBJECT_PACK_MAX_OBJECTS }}
GH_AW_OBJECT_PACK_TIMEOUT_MS: ${{ vars.GH_AW_OBJECT_PACK_TIMEOUT_MS }}
GH_AW_POLICY_ALLOW_CREATE_PULL_REQUEST: ${{ vars.GH_AW_POLICY_ALLOW_CREATE_PULL_REQUEST || 'true' }}
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
GH_AW_SAFE_OUTPUTS_CONFIG_PATH: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS_CONFIG_PATH }}
GH_AW_SAFE_OUTPUTS_TOOLS_PATH: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS_TOOLS_PATH }}
GH_AW_SERENA_GO_PATH: ${{ env.GH_AW_SERENA_GO_PATH }}
GH_AW_SINK_VISIBILITY: ${{ steps.determine-automatic-lockdown.outputs.visibility }}
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 }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -eo pipefail
mkdir -p "${RUNNER_TEMP}/gh-aw/mcp-config"
if [ -n "${GITHUB_EVENT_PATH:-}" ] && [ -r "${GITHUB_EVENT_PATH}" ]; then
GH_AW_SAFEOUTPUTS_EVENT_PATH="${RUNNER_TEMP}/gh-aw/safeoutputs/github_event.json"
cp "${GITHUB_EVENT_PATH}" "${GH_AW_SAFEOUTPUTS_EVENT_PATH}"
export GITHUB_EVENT_PATH="${GH_AW_SAFEOUTPUTS_EVENT_PATH}"
fi
# Export gateway environment variables for MCP config and gateway script
export MCP_GATEWAY_PORT="8080"
export MCP_GATEWAY_DOMAIN="awmg-mcpg"
export MCP_GATEWAY_HOST_DOMAIN="localhost"
MCP_GATEWAY_AGENT_ID=$(openssl rand -base64 45 | tr -d '/+=')
echo "::add-mask::${MCP_GATEWAY_AGENT_ID}"
export MCP_GATEWAY_AGENT_ID
export MCP_GATEWAY_PAYLOAD_DIR="/tmp/gh-aw/mcp-payloads"
mkdir -p "${MCP_GATEWAY_PAYLOAD_DIR}"
export MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD="524288"
export MCP_GATEWAY_ALLOWED_MOUNT_ROOTS="${GITHUB_WORKSPACE}:rw,${RUNNER_TEMP}/gh-aw:ro,${RUNNER_TEMP}/gh-aw/safeoutputs:rw,${RUNNER_TOOL_CACHE}:ro,/opt:ro,/tmp:rw,/usr/bin/gh:ro"
export GH_AW_PR_HEAD_BASE_BRANCH="${GH_AW_PR_HEAD_BASE_BRANCH:-}"
export GH_AW_PR_HEAD_BASE_SHA="${GH_AW_PR_HEAD_BASE_SHA:-}"
export GH_AW_PR_HEAD_BASE_REPO="${GH_AW_PR_HEAD_BASE_REPO:-}"
export GH_AW_PR_HEAD_BASE_PR_NUMBER="${GH_AW_PR_HEAD_BASE_PR_NUMBER:-}"
export GH_AW_PR_HEAD_BASE_REF="${GH_AW_PR_HEAD_BASE_REF:-}"
export GH_AW_PR_HEAD_REPO="${GH_AW_PR_HEAD_REPO:-}"
export GH_AW_TARGET_REPO_SLUG="${GH_AW_TARGET_REPO_SLUG:-}"
export GH_AW_ENGINE="codex"
export GH_AW_MCP_CLI_SERVERS='["agenticworkflows","safeoutputs","serena"]'
MCP_GATEWAY_UID=$(id -u 2>/dev/null || echo '0')
MCP_GATEWAY_GID=$(id -g 2>/dev/null || echo '0')
source "${RUNNER_TEMP}/gh-aw/actions/resolve_docker_socket_gid.sh"
export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network bridge -p 127.0.0.1:'"${MCP_GATEWAY_PORT}"':'"${MCP_GATEWAY_PORT}"' --name awmg-mcpg --add-host host.docker.internal:host-gateway --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v '"${DOCKER_SOCK_PATH}"':/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_AGENT_ID -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DOCKER_HOST=unix:///var/run/docker.sock -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_TARGET_REPO_SLUG -e GH_AW_PR_HEAD_BASE_BRANCH -e GH_AW_PR_HEAD_BASE_SHA -e GH_AW_PR_HEAD_BASE_REPO -e GH_AW_PR_HEAD_BASE_PR_NUMBER -e GH_AW_PR_HEAD_BASE_REF -e GH_AW_PR_HEAD_REPO -e GH_AW_POLICY_ALLOW_CREATE_PULL_REQUEST -e GH_AW_OBJECT_PACK_MAX_BYTES -e GH_AW_OBJECT_PACK_MAX_OBJECTS -e GH_AW_OBJECT_PACK_TIMEOUT_MS -e GH_AW_OBJECT_PACK_FETCH_DEPTHS -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 GH_AW_SINK_VISIBILITY -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 RUNNER_TEMP -e RUNNER_TOOL_CACHE -e MCP_GATEWAY_ALLOWED_MOUNT_ROOTS -e GITHUB_AW_OTEL_TRACE_ID -e GITHUB_AW_OTEL_PARENT_SPAN_ID -e OTEL_EXPORTER_OTLP_HEADERS -e CODEX_HOME -e GH_AW_SERENA_GO_PATH -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 -v '"${RUNNER_TEMP}"'/gh-aw/safeoutputs:'"${RUNNER_TEMP}"'/gh-aw/safeoutputs:rw ghcr.io/github/gh-aw-mcpg:v0.5.0@sha256:d3544a4222e7efeeeb38669d8a1af0c72691c55b8f6506b15aa5920f7f31b7bc'
export GH_AW_CODEX_CONFIG="${RUNNER_TEMP}/gh-aw/mcp-config/codex-config.json"
# Generate JSON config for MCP gateway
GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node)
cat << GH_AW_MCP_CONFIG_5989682917542506_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs"
{
"mcpServers": {
"agenticworkflows": {
"container": "localhost/gh-aw:dev",
"mounts": ["\${GITHUB_WORKSPACE}:\${GITHUB_WORKSPACE}:rw", "/tmp/gh-aw:/tmp/gh-aw:rw"],
"args": ["--network", "host", "-w", "\${GITHUB_WORKSPACE}"],
"env": {
"DEBUG": "\${DEBUG}",
"GITHUB_TOKEN": "\${GITHUB_TOKEN}",
"GITHUB_ACTOR": "\${GITHUB_ACTOR}",
"GITHUB_REPOSITORY": "\${GITHUB_REPOSITORY}"
},
"guard-policies": {
"write-sink": {
"accept": [
"*"
],
"sink-visibility": "${GH_AW_SINK_VISIBILITY}"
}
}
},
"github": {
"container": "ghcr.io/github/github-mcp-server:v2.0.3",
"env": {
"GITHUB_FEATURES": "fields_param",
"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"
}
}
},
"safeoutputs": {
"container": "ghcr.io/github/gh-aw-node@sha256:2c2ea524e648b91c8333ce246e3838fcf5b19ac70e45baac1a51b9207299749f",
"mounts": ["\${GITHUB_WORKSPACE}:\${GITHUB_WORKSPACE}:rw", "${RUNNER_TEMP}/gh-aw/safeoutputs:${RUNNER_TEMP}/gh-aw/safeoutputs:rw", "/tmp/gh-aw:/tmp/gh-aw:rw"],
"args": ["-w", "\${GITHUB_WORKSPACE}"],
"entrypoint": "sh",
"entrypointArgs": ["-c", "sh ${RUNNER_TEMP}/gh-aw/safeoutputs/start_safe_outputs_mcp.sh"],
"env": {
"DEBUG": "\${DEBUG}",
"DEFAULT_BRANCH": "\${DEFAULT_BRANCH}",
"GH_AW_ASSETS_ALLOWED_EXTS": "\${GH_AW_ASSETS_ALLOWED_EXTS}",
"GH_AW_ASSETS_BRANCH": "\${GH_AW_ASSETS_BRANCH}",
"GH_AW_ASSETS_MAX_SIZE_KB": "\${GH_AW_ASSETS_MAX_SIZE_KB}",
"GH_AW_MCP_LOG_DIR": "\${GH_AW_MCP_LOG_DIR}",
"GH_AW_SAFE_OUTPUTS": "\${GH_AW_SAFE_OUTPUTS}",
"GH_AW_SAFE_OUTPUTS_CONFIG_PATH": "\${GH_AW_SAFE_OUTPUTS_CONFIG_PATH}",
"GH_AW_SAFE_OUTPUTS_TOOLS_PATH": "\${GH_AW_SAFE_OUTPUTS_TOOLS_PATH}",
"GH_AW_TARGET_REPO_SLUG": "\${GH_AW_TARGET_REPO_SLUG}",
"GH_AW_POLICY_ALLOW_CREATE_PULL_REQUEST": "\${GH_AW_POLICY_ALLOW_CREATE_PULL_REQUEST}",
"GH_AW_PR_HEAD_BASE_BRANCH": "\${GH_AW_PR_HEAD_BASE_BRANCH}",
"GH_AW_PR_HEAD_BASE_SHA": "\${GH_AW_PR_HEAD_BASE_SHA}",
"GH_AW_PR_HEAD_BASE_REPO": "\${GH_AW_PR_HEAD_BASE_REPO}",
"GH_AW_PR_HEAD_BASE_PR_NUMBER": "\${GH_AW_PR_HEAD_BASE_PR_NUMBER}",
"GH_AW_PR_HEAD_BASE_REF": "\${GH_AW_PR_HEAD_BASE_REF}",
"GH_AW_PR_HEAD_REPO": "\${GH_AW_PR_HEAD_REPO}",
"GITHUB_EVENT_NAME": "\${GITHUB_EVENT_NAME}",
"GITHUB_EVENT_PATH": "\${GITHUB_EVENT_PATH}",
"GITHUB_REPOSITORY": "\${GITHUB_REPOSITORY}",
"GITHUB_SHA": "\${GITHUB_SHA}",
"GITHUB_TOKEN": "\${GITHUB_TOKEN}",
"GITHUB_WORKSPACE": "\${GITHUB_WORKSPACE}",
"RUNNER_TEMP": "\${RUNNER_TEMP}",
"GH_AW_OBJECT_PACK_MAX_BYTES": "\${GH_AW_OBJECT_PACK_MAX_BYTES}",
"GH_AW_OBJECT_PACK_MAX_OBJECTS": "\${GH_AW_OBJECT_PACK_MAX_OBJECTS}",
"GH_AW_OBJECT_PACK_TIMEOUT_MS": "\${GH_AW_OBJECT_PACK_TIMEOUT_MS}",
"GH_AW_OBJECT_PACK_FETCH_DEPTHS": "\${GH_AW_OBJECT_PACK_FETCH_DEPTHS}"
},
"guard-policies": {
"write-sink": {
"accept": [
"*"
],
"sink-visibility": "${GH_AW_SINK_VISIBILITY}"
}
}
},
"serena": {
"type": "stdio",
"container": "ghcr.io/oraios/serena:1.7.0",
"entrypoint": "/workspaces/serena/.venv/bin/serena",
"entrypointArgs": [
"start-mcp-server",
"--context",
"codex",
"--project",
"\${GITHUB_WORKSPACE}"
],
"mounts": [
"\${GITHUB_WORKSPACE}:\${GITHUB_WORKSPACE}:rw",
"\${RUNNER_TOOL_CACHE}:\${RUNNER_TOOL_CACHE}:ro"
],
"args": [
"--network",
"host"
],
"env": {
"PATH": "\${GH_AW_SERENA_GO_PATH}:\${PATH}"
},
"guard-policies": {
"write-sink": {
"accept": [
"*"
],
"sink-visibility": "${GH_AW_SINK_VISIBILITY}"
}
}
}
},
"gateway": {
"port": $MCP_GATEWAY_PORT,
"domain": "${MCP_GATEWAY_DOMAIN}",
"agentId": "${MCP_GATEWAY_AGENT_ID}",
"payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}",
"startupTimeout": 120,
"opentelemetry": {
"endpoint": "${OTEL_EXPORTER_OTLP_ENDPOINT}",
"traceId": "${GITHUB_AW_OTEL_TRACE_ID}",
"spanId": "${GITHUB_AW_OTEL_PARENT_SPAN_ID}"
}
}
}
GH_AW_MCP_CONFIG_5989682917542506_EOF
# Sync converter output to writable CODEX_HOME for Codex
mkdir -p "${CODEX_HOME}"
if [ "${RUNNER_TEMP}/gh-aw/mcp-config/config.toml" != "${CODEX_HOME}/config.toml" ]; then cp "${RUNNER_TEMP}/gh-aw/mcp-config/config.toml" "${CODEX_HOME}/config.toml"; fi
chmod 600 "${CODEX_HOME}/config.toml"
- name: Mount MCP servers as CLIs
id: mount-mcp-clis
continue-on-error: true
env:
MCP_GATEWAY_AGENT_ID: ${{ steps.start-mcp-gateway.outputs.gateway-agent-id }}
MCP_GATEWAY_DOMAIN: ${{ steps.start-mcp-gateway.outputs.gateway-domain }}
MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }}
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io);
const { main } = require(path.join(actionsDir, 'mount_mcp_as_cli.cjs'));
await main();
- name: Clean credentials
run: |
bash "${RUNNER_TEMP}/gh-aw/actions/clean_git_credentials.sh"
bash "${RUNNER_TEMP}/gh-aw/actions/verify_git_credentials.sh"
- name: Audit pre-agent workspace
id: pre_agent_audit
continue-on-error: true
run: bash "${RUNNER_TEMP}/gh-aw/actions/audit_pre_agent_workspace.sh"
- name: Log GitHub rate limits at agent start
continue-on-error: true
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
const { fetchAndLogRateLimit } = require(path.join(actionsDir, 'github_rate_limit_logger.cjs'));
await fetchAndLogRateLimit(github, 'agent_start', true);
- name: Execute Codex CLI
id: agentic_execution
timeout-minutes: 20
run: |
set -o pipefail
gh_aw_exit_code=0
trap 'gh_aw_exit_code=$?; mkdir -p /tmp/gh-aw >/dev/null 2>&1 || true; printf "%s" "$gh_aw_exit_code" > /tmp/gh-aw/agent_execution_exit_code.txt || true; if [ "$gh_aw_exit_code" -ne 0 ]; then echo "::error::Agent execution exited with code $gh_aw_exit_code"; fi' EXIT
printf '%s' "$(date +%s%3N)" > /tmp/gh-aw/agent_cli_start_ms.txt
mkdir -p "$CODEX_HOME/logs" && touch /tmp/gh-aw/agent-step-summary.md
(umask 177 && touch /tmp/gh-aw/agent-stdio.log)
GH_AW_MAX_AI_CREDITS="${GH_AW_MAX_AI_CREDITS:-1000}"
if [[ ! "$GH_AW_MAX_AI_CREDITS" =~ ^[0-9]+$ ]]; then
GH_AW_MAX_AI_CREDITS="1000"
fi
if [[ "${GH_AW_ADMISSION_RESULT:-}" == "admitted" && -z "${GH_AW_ADMISSION_MAX_AI_CREDITS:-}" ]]; then
echo "ERR_ADMISSION: Missing required runtime admission allowance." >&2
exit 1
fi
if [[ "${GH_AW_ADMISSION_RESULT:-}" == "admitted" && -n "${GH_AW_ADMISSION_MAX_AI_CREDITS:-}" ]]; then
if [[ ! "$GH_AW_ADMISSION_MAX_AI_CREDITS" =~ ^[1-9][0-9]{0,9}$ ]] || (( GH_AW_ADMISSION_MAX_AI_CREDITS > 2147483647 )); then
echo "ERR_ADMISSION: Invalid runtime admission allowance." >&2
exit 1
fi
GH_AW_MAX_AI_CREDITS="$GH_AW_ADMISSION_MAX_AI_CREDITS"
echo "Admission allowance applied (value withheld)."
else
echo "No component admission allowance; retaining existing budget policy (value withheld)."
fi
unset GH_AW_ADMISSION_RESULT GH_AW_ADMISSION_MAX_AI_CREDITS
printf '%s\n' "{\"\$schema\":\"https://github.com/github/gh-aw-firewall/releases/download/v0.29.5/awf-config.schema.json\",\"network\":{\"allowDomains\":[\"*.grafana.net\",\"*.sentry.io\",\"api.snapcraft.io\",\"archive.ubuntu.com\",\"azure.archive.ubuntu.com\",\"cdn.playwright.dev\",\"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\",\"json-schema.org\",\"json.schemastore.org\",\"keyserver.ubuntu.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\",\"packagecloud.io\",\"packages.cloud.google.com\",\"packages.microsoft.com\",\"playwright.download.prss.microsoft.com\",\"ppa.launchpad.net\",\"s.symcb.com\",\"s.symcd.com\",\"security.ubuntu.com\",\"ts-crl.ws.symantec.com\",\"ts-ocsp.ws.symantec.com\",\"www.googleapis.com\"],\"isolation\":true,\"topologyAttach\":[\"awmg-mcpg\"]},\"apiProxy\":{\"enabled\":true,\"enableTokenSteering\":true,\"hostedWeb\":{\"codex\":{\"enabled\":false}},\"maxRuns\":100,\"maxAiCredits\":${GH_AW_MAX_AI_CREDITS},\"maxCacheMisses\":5,\"providers\":{\"github-copilot\":{\"models\":{\"gpt-5.6-terra\":{\"cost\":{\"cache_read\":\"2e-07\",\"cache_write\":\"2.5e-06\",\"input\":\"2e-06\",\"output\":\"1.2e-05\"}}}}},\"models\":{\"agent\":[\"sonnet-6x\",\"gpt-6\",\"gpt-5.4\",\"gpt-5.5\",\"gpt-5.6\",\"gpt-5.3\",\"gemini-pro\",\"any\"],\"antigravity\":[\"copilot/antigravity*\",\"google/antigravity*\",\"gemini/antigravity*\"],\"any\":[\"copilot/*\",\"anthropic/*\",\"openai/*\",\"google/*\",\"gemini/*\"],\"auto\":[\"copilot/auto\",\"large\"],\"claude\":[\"agent\"],\"codex\":[\"agent\"],\"coding\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\",\"gpt-5-codex\",\"kimi\"],\"computer-use\":[\"copilot/*computer-use*\",\"google/*computer-use*\",\"gemini/*computer-use*\",\"openai/*computer-use*\"],\"copilot\":[\"agent\"],\"deep-research\":[\"copilot/deep-research*\",\"copilot/o3-deep-research*\",\"copilot/o4-mini-deep-research*\",\"google/deep-research*\",\"gemini/deep-research*\",\"openai/o3-deep-research*\",\"openai/o4-mini-deep-research*\"],\"detection\":[\"small\"],\"evals\":[\"copilot/gpt-6-luna-decisions\"],\"fable\":[\"copilot/*fable*\",\"anthropic/*fable*\"],\"gemini\":[\"agent\"],\"gemini-3-flash\":[\"copilot/gemini-3*flash*\",\"google/gemini-3*flash*\",\"gemini/gemini-3*flash*\"],\"gemini-3-pro\":[\"copilot/gemini-3*pro*\",\"google/gemini-3*pro*\",\"google/nano-banana*\",\"gemini/gemini-3*pro*\"],\"gemini-3.1-flash\":[\"copilot/gemini-3.1*flash*\",\"google/gemini-3.1*flash*\",\"gemini/gemini-3.1*flash*\"],\"gemini-3.1-pro\":[\"copilot/gemini-3.1*pro*\",\"google/gemini-3.1*pro*\",\"gemini/gemini-3.1*pro*\"],\"gemini-3.5-flash\":[\"copilot/gemini-3.5*flash*\",\"google/gemini-3.5*flash*\",\"gemini/gemini-3.5*flash*\"],\"gemini-3.6-flash\":[\"copilot/gemini-3.6*flash*\",\"google/gemini-3.6*flash*\",\"gemini/gemini-3.6*flash*\"],\"gemini-3.7-flash\":[\"copilot/gemini-3.7*flash*\",\"google/gemini-3.7*flash*\",\"gemini/gemini-3.7*flash*\"],\"gemini-3.8-flash\":[\"copilot/gemini-3.8*flash*\",\"google/gemini-3.8*flash*\",\"gemini/gemini-3.8*flash*\"],\"gemini-flash\":[\"copilot/gemini-*flash*\",\"google/gemini-*flash*\",\"gemini/gemini-*flash*\"],\"gemini-flash-lite\":[\"copilot/gemini-*flash*lite*\",\"google/gemini-*flash*lite*\",\"gemini/gemini-*flash*lite*\"],\"gemini-omni\":[\"copilot/gemini-omni*\",\"google/gemini-omni*\",\"gemini/gemini-omni*\"],\"gemini-pro\":[\"copilot/gemini-*pro*\",\"google/gemini-*pro*\",\"gemini/gemini-*pro*\"],\"gemma\":[\"copilot/gemma*\",\"google/gemma*\",\"gemini/gemma*\"],\"gpt-5\":[\"copilot/gpt-5*\",\"openai/gpt-5*\"],\"gpt-5-codex\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\"],\"gpt-5-mini\":[\"copilot/gpt-5*mini*\",\"openai/gpt-5*mini*\"],\"gpt-5-nano\":[\"copilot/gpt-5*nano*\",\"openai/gpt-5*nano*\"],\"gpt-5-pro\":[\"copilot/gpt-5*pro*\",\"openai/gpt-5*pro*\"],\"gpt-5.1\":[\"copilot/gpt-5.1*\",\"openai/gpt-5.1*\"],\"gpt-5.2\":[\"copilot/gpt-5.2*\",\"openai/gpt-5.2*\"],\"gpt-5.3\":[\"copilot/gpt-5.3*\",\"openai/gpt-5.3*\"],\"gpt-5.4\":[\"copilot/gpt-5.4*\",\"openai/gpt-5.4*\"],\"gpt-5.5\":[\"copilot/gpt-5.5*\",\"openai/gpt-5.5*\"],\"gpt-5.6\":[\"copilot/gpt-5.6*\",\"openai/gpt-5.6*\"],\"gpt-6\":[\"copilot/gpt-6*\",\"openai/gpt-6*\"],\"grok\":[\"copilot/*grok*\",\"openai/*grok*\"],\"haiku\":[\"copilot/*haiku*\",\"anthropic/*haiku*\"],\"image-generation\":[\"copilot/gpt-image*\",\"openai/gpt-image*\",\"openai/chatgpt-image*\",\"copilot/gemini-*image*\",\"google/gemini-*image*\",\"gemini/gemini-*image*\",\"google/imagen*\"],\"kimi\":[\"copilot/kimi*\",\"openai/kimi*\"],\"kiwi\":[\"copilot/kiwi*\",\"openai/kiwi*\"],\"large\":[\"sonnet\",\"gpt-6\",\"gpt-5-pro\",\"gpt-5\",\"gemini-pro\"],\"lyria\":[\"google/lyria*\",\"gemini/lyria*\",\"copilot/lyria*\"],\"mai-code\":[\"copilot/MAI-Code*\",\"copilot/mai-code*\",\"openai/MAI-Code*\"],\"mini\":[\"haiku\",\"gpt-5-mini\",\"gpt-5-nano\",\"gemini-flash-lite\"],\"nano-banana\":[\"copilot/nano-banana*\",\"google/nano-banana*\",\"gemini/nano-banana*\"],\"opus\":[\"copilot/*opus*\",\"anthropic/*opus*\"],\"opusplan\":[\"opus?effort=high\"],\"raptor-mini\":[\"copilot/raptor*\",\"openai/raptor*\"],\"reasoning\":[\"copilot/o1*\",\"copilot/o3*\",\"copilot/o4*\",\"openai/o1*\",\"openai/o3*\",\"openai/o4*\"],\"robotics\":[\"copilot/*robotics*\",\"google/*robotics*\",\"gemini/*robotics*\"],\"small\":[\"mini\"],\"small-agent\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash\"],\"sonnet\":[\"copilot/*sonnet*\",\"anthropic/*sonnet*\"],\"sonnet-6x\":[\"copilot/*sonnet-4.5*\",\"copilot/*sonnet-4.6*\",\"copilot/*sonnet-5*\",\"copilot/*sonnet-4-5-*\",\"anthropic/*sonnet-4-5-*\",\"copilot/*sonnet-4-6*\",\"anthropic/*sonnet-4-6*\",\"anthropic/*sonnet-5*\"],\"summarization\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash-lite\",\"mini\"],\"veo\":[\"google/veo*\",\"gemini/veo*\"],\"vision\":[\"copilot/gemini-*image*\",\"google/gemini-*image*\",\"gemini/gemini-*image*\",\"copilot/gemini-*flash*\",\"google/gemini-*flash*\",\"gemini/gemini-*flash*\"]}},\"container\":{\"imageTag\":\"0.29.5,squid=sha256:34260cb89ea5d6d55b93ce13a5fe1772dbe8e1592e1200370160b7f5a0bd2ecd,agent=sha256:921e50aed7b2a67265f42ab03c7d54a32c641922cc64f0875a5ae2bcb8b37532,api-proxy=sha256:f36a9fc78aef0509ed5fa280819848cbdf099f60d7b338455ea54a5def18d6b1,cli-proxy=sha256:29781e0820de464fcc81298e5d9cb2162004d8eaad9cba75ac669a6459cac075\",\"agentTimeout\":20},\"logging\":{\"proxyLogsDir\":\"/tmp/gh-aw/sandbox/firewall/logs\",\"auditDir\":\"/tmp/gh-aw/sandbox/firewall/audit\"}}" > "${RUNNER_TEMP}/gh-aw/awf-config.json"
cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json
export GH_AW_MODELS_JSON_PATH="/tmp/gh-aw/models.json"
GH_AW_DOCKER_HOST=""
if [[ "${DOCKER_HOST:-}" =~ ^tcp:// ]]; then
GH_AW_DOCKER_HOST="${DOCKER_HOST}"
fi
if [[ "${DOCKER_HOST:-}" =~ ^tcp:// ]]; then
GH_AW_CHROOT_BINARIES_SOURCE_PATH="${RUNNER_TEMP}/gh-aw" GH_AW_CHROOT_IDENTITY_HOME="${RUNNER_TEMP}/gh-aw/home" node "${RUNNER_TEMP}/gh-aw/actions/patch_awf_chroot_config.cjs"
fi
GH_AW_TOOL_CACHE_MOUNT=""
GH_AW_TOOL_CACHE="${RUNNER_TOOL_CACHE:?RUNNER_TOOL_CACHE must be set}"
if [ -d "$GH_AW_TOOL_CACHE" ]; then
if [[ "$GH_AW_TOOL_CACHE" != /opt/* ]]; then
GH_AW_TOOL_CACHE_MOUNT="$GH_AW_TOOL_CACHE:$GH_AW_TOOL_CACHE:ro"
fi
fi
# shellcheck disable=SC1003,SC2016,SC2086
mkdir -p "/tmp/gh-aw"
evidence_tmp="/tmp/gh-aw/agent_execution.json.tmp"
printf '{"version":1,"component":"agent","run_id":%s,"run_attempt":%s,"state":"started"}\n' "$GITHUB_RUN_ID" "$GITHUB_RUN_ATTEMPT" > "$evidence_tmp"
mv "$evidence_tmp" "/tmp/gh-aw/agent_execution.json"
export GH_AW_AWF_EXECUTION_COMPONENT="agent"
export GH_AW_AWF_EXECUTION_EVIDENCE_FILE="/tmp/gh-aw/agent_execution.json"
GH_AW_AWF_ENGINE_NAME=codex \
GH_AW_AWF_HARNESS_MARKER='[codex-harness]' \
GH_AW_AWF_LOG_FILE=/tmp/gh-aw/agent-stdio.log \
GH_AW_AWF_ATTEMPT_LOG_NAME=codex \
bash "${RUNNER_TEMP}/gh-aw/actions/run_awf_with_startup_retries.sh" -- \
awf --config "${RUNNER_TEMP}/gh-aw/awf-config.json" --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" ${GH_AW_TOOL_CACHE_MOUNT:+--mount "$GH_AW_TOOL_CACHE_MOUNT"} ${GH_AW_DOCKER_HOST:+--docker-host "$GH_AW_DOCKER_HOST"} --env-all --exclude-env ACTIONS_ID_TOKEN_REQUEST_TOKEN --exclude-env ACTIONS_ID_TOKEN_REQUEST_URL --exclude-env CODEX_API_KEY --exclude-env COPILOT_GITHUB_TOKEN --exclude-env GH_AW_OTLP_ALL_HEADERS --exclude-env GH_AW_OTLP_ENDPOINTS --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_AGENT_ID --exclude-env OPENAI_API_KEY --exclude-env OTEL_EXPORTER_OTLP_ENDPOINT --exclude-env OTEL_EXPORTER_OTLP_HEADERS --mount /tmp/gh-aw:/tmp/gh-aw:rw --log-level info --skip-pull \
-- /bin/bash -c 'set +o histexpand; export CODEX_API_KEY="$COPILOT_DUMMY_BYOK" && export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && : "${RUNNER_TOOL_CACHE:?RUNNER_TOOL_CACHE must be set}"; GH_AW_TOOL_CACHE="$RUNNER_TOOL_CACHE"; GH_AW_TOOL_BINS="$(find "$GH_AW_TOOL_CACHE" -maxdepth 5 -type d -name bin 2>/dev/null | tr "\n" ":")"; GH_AW_TOOL_BINS="${GH_AW_TOOL_BINS%:}"; export PATH="$PATH${GH_AW_TOOL_BINS:+:}$GH_AW_TOOL_BINS"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true; [ -n "$ERLANG_HOME" ] && export PATH="$ERLANG_HOME/bin:$PATH" || true && GH_AW_NODE_EXEC="${GH_AW_NODE_BIN:-}"; if [ -z "$GH_AW_NODE_EXEC" ] || [ ! -x "$GH_AW_NODE_EXEC" ]; then GH_AW_NODE_EXEC="$(command -v node 2>/dev/null || true)"; fi; if [ -z "$GH_AW_NODE_EXEC" ]; then echo "node runtime missing on this runner — check runtimes.node in workflow YAML" >&2; exit 127; fi; GH_AW_NPM_GLOBAL_ROOT="$(npm root -g 2>/dev/null || true)"; if [ -n "$GH_AW_NPM_GLOBAL_ROOT" ]; then export NODE_PATH="${GH_AW_NPM_GLOBAL_ROOT}${NODE_PATH:+:${NODE_PATH}}"; fi; "$GH_AW_NODE_EXEC" ${RUNNER_TEMP}/gh-aw/actions/codex_harness.cjs codex exec${GH_AW_MODEL_AGENT_CODEX:+ --model "$GH_AW_MODEL_AGENT_CODEX"} -c web_search="disabled" --dangerously-bypass-approvals-and-sandbox --skip-git-repo-check --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt'
env:
AWF_REFLECT_ENABLED: 1
CODEX_HOME: /tmp/gh-aw/mcp-config
COPILOT_DUMMY_BYOK: dummy-byok-key-for-offline-mode
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
GH_AW_ADMISSION_MAX_AI_CREDITS: ${{ needs.activation.outputs.admission-max-ai-credits }}
GH_AW_ADMISSION_RESULT: ${{ needs.activation.outputs.admission-result }}
GH_AW_LLM_PROVIDER: github
GH_AW_LLM_PROVIDER_EXPLICIT: 1
GH_AW_MAX_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_MAX_AI_CREDITS || '1000' }}
GH_AW_MAX_TURNS: 100
GH_AW_MCP_CONFIG: ${{ runner.temp }}/gh-aw/mcp-config/config.toml
GH_AW_MODEL_AGENT_CODEX: gpt-5.6-terra
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
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]
PLAYWRIGHT_BROWSERS_PATH: ${{ runner.temp }}/gh-aw/playwright-browsers
RUNNER_TEMP: ${{ runner.temp }}
RUST_LOG: ${{ runner.debug == 1 && 'trace,hyper_util=info,mio=info,reqwest=info,os_info=info,codex_otel=warn,codex_core=debug,codex_exec=debug' || 'warn' }}
TRACEPARENT: ${{ env.GITHUB_AW_OTEL_TRACE_ID != '' && env.GITHUB_AW_OTEL_PARENT_SPAN_ID != '' && format('00-{0}-{1}-01', env.GITHUB_AW_OTEL_TRACE_ID, env.GITHUB_AW_OTEL_PARENT_SPAN_ID) || '' }}
- name: Log GitHub rate limits at agent end
if: always()
continue-on-error: true
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
const { fetchAndLogRateLimit } = require(path.join(actionsDir, 'github_rate_limit_logger.cjs'));
await fetchAndLogRateLimit(github, 'agent_end', true);
- name: Detect agent errors
if: always()
id: detect-agent-errors
continue-on-error: true
env:
GH_AW_AGENTIC_EXECUTION_OUTCOME: ${{ steps.agentic_execution.outcome }}
GH_AW_ENGINE_STEP_TIMEOUT_MINUTES: 20
GH_AW_ENGINE_INTERNAL_LOGS_DIR: /tmp/gh-aw/mcp-config/logs
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
const { main } = require(path.join(actionsDir, 'detect_agent_errors.cjs'));
await main();
- name: Configure Git credentials
env:
GITHUB_REPOSITORY: ${{ github.repository }}
GITHUB_SERVER_URL: ${{ github.server_url }}
GITHUB_TOKEN: ${{ github.token }}
run: bash "${RUNNER_TEMP}/gh-aw/actions/configure_git_credentials.sh"
- name: Stop MCP Gateway
if: always()
continue-on-error: true
env:
MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }}
MCP_GATEWAY_AGENT_ID: ${{ steps.start-mcp-gateway.outputs.gateway-agent-id }}
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
id: redact_secrets
if: always()
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
const { main } = require(path.join(actionsDir, 'redact_secrets.cjs'));
await main();
env:
GH_AW_SECRET_NAMES: 'COPILOT_GITHUB_TOKEN,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN'
SECRET_COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
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 }}
- name: Validate recovery envelopes before upload
id: validate_recovery_envelopes
if: always() && steps.redact_secrets.outcome == 'success'
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
GH_AW_OBJECT_PACK_MAX_BYTES: ${{ vars.GH_AW_OBJECT_PACK_MAX_BYTES }}
GH_AW_OBJECT_PACK_MAX_OBJECTS: ${{ vars.GH_AW_OBJECT_PACK_MAX_OBJECTS }}
GH_AW_OBJECT_PACK_TIMEOUT_MS: ${{ vars.GH_AW_OBJECT_PACK_TIMEOUT_MS }}
GH_AW_OBJECT_PACK_FETCH_DEPTHS: ${{ vars.GH_AW_OBJECT_PACK_FETCH_DEPTHS }}
GH_AW_RECOVERY_ADDITIONAL_ROOTS: '[]'
with:
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { main } = require(path.join(actionsDir, 'validate_recovery_envelopes.cjs'));
main({ core, additionalRoots: JSON.parse(process.env.GH_AW_RECOVERY_ADDITIONAL_ROOTS) });
- 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@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
GH_AW_ALLOWED_DOMAINS: "*.grafana.net,*.sentry.io,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,cdn.playwright.dev,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,json-schema.org,json.schemastore.org,keyserver.ubuntu.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,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,playwright.download.prss.microsoft.com,ppa.launchpad.net,s.symcb.com,s.symcd.com,security.ubuntu.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_COMMANDS: "[\"cloclo\"]"
GH_AW_LABEL_COMMANDS: "[\"cloclo\"]"
with:
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
const { main } = require(path.join(actionsDir, 'collect_ndjson_output.cjs'));
await main();
- name: Parse agent logs for step summary
if: always()
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
GH_AW_AGENT_OUTPUT: /tmp/gh-aw/agent-stdio.log
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
with:
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
const { main } = require(path.join(actionsDir, 'parse_codex_log.cjs'));
await main();
- name: Parse MCP Gateway logs for step summary
if: always()
id: parse-mcp-gateway
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
const { main } = require(path.join(actionsDir, '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: bash "${RUNNER_TEMP}/gh-aw/actions/print_firewall_logs.sh" --rootless
- name: Parse token usage for step summary
if: always()
id: parse-token-usage
continue-on-error: true
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
const { main } = require(path.join(actionsDir, 'parse_token_usage.cjs'));
await main();
- name: Print AWF reflect summary
if: always()
continue-on-error: true
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
const { main } = require(path.join(actionsDir, 'awf_reflect_summary.cjs'));
await main();
- name: Generate observability summary
if: always()
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
const { main } = require(path.join(actionsDir, 'generate_observability_summary.cjs'));
await main(core);
- 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: Check cache-memory git integrity
if: always()
continue-on-error: true
env:
GH_AW_CACHE_DIR: /tmp/gh-aw/cache-memory
run: bash "${RUNNER_TEMP}/gh-aw/actions/check_cache_memory_git_integrity.sh"
- name: Validate recovery envelopes before upload
id: validate_recovery_cache_default
if: always() && steps.redact_secrets.outcome == 'success'
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
GH_AW_OBJECT_PACK_MAX_BYTES: ${{ vars.GH_AW_OBJECT_PACK_MAX_BYTES }}
GH_AW_OBJECT_PACK_MAX_OBJECTS: ${{ vars.GH_AW_OBJECT_PACK_MAX_OBJECTS }}
GH_AW_OBJECT_PACK_TIMEOUT_MS: ${{ vars.GH_AW_OBJECT_PACK_TIMEOUT_MS }}
GH_AW_OBJECT_PACK_FETCH_DEPTHS: ${{ vars.GH_AW_OBJECT_PACK_FETCH_DEPTHS }}
GH_AW_RECOVERY_ADDITIONAL_ROOTS: '["/tmp/gh-aw/cache-memory"]'
with:
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { main } = require(path.join(actionsDir, 'validate_recovery_envelopes.cjs'));
main({ core, additionalRoots: JSON.parse(process.env.GH_AW_RECOVERY_ADDITIONAL_ROOTS) });
- name: Upload cache-memory data as artifact
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
if: always() && steps.redact_secrets.outcome == 'success' && steps.validate_recovery_envelopes.outcome == 'success' && steps.validate_recovery_cache_default.outcome == 'success'
with:
name: cache-memory
include-hidden-files: true
path: /tmp/gh-aw/cache-memory
retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '0' }}
- name: Validate recovery envelopes before upload
id: validate_final_recovery_envelopes
if: always() && steps.redact_secrets.outcome == 'success'
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
GH_AW_OBJECT_PACK_MAX_BYTES: ${{ vars.GH_AW_OBJECT_PACK_MAX_BYTES }}
GH_AW_OBJECT_PACK_MAX_OBJECTS: ${{ vars.GH_AW_OBJECT_PACK_MAX_OBJECTS }}
GH_AW_OBJECT_PACK_TIMEOUT_MS: ${{ vars.GH_AW_OBJECT_PACK_TIMEOUT_MS }}
GH_AW_OBJECT_PACK_FETCH_DEPTHS: ${{ vars.GH_AW_OBJECT_PACK_FETCH_DEPTHS }}
GH_AW_RECOVERY_ADDITIONAL_ROOTS: '["/tmp/gh-aw/aw-prompts/prompt.txt","/tmp/gh-aw/agent_execution.json","/tmp/gh-aw/agent_execution_exit_code.txt","/tmp/gh-aw/agent-session.jsonl","/tmp/gh-aw/agent-errors.jsonl","/tmp/gh-aw/aw-prompts/user.txt","/tmp/gh-aw/aw-prompts/system.txt","/tmp/gh-aw/skill_inventory.json","/tmp/gh-aw/mcp-config/logs/","/tmp/gh-aw/redacted-urls.log","/tmp/gh-aw/mcp-logs/","/tmp/gh-aw/agent_usage.json","/tmp/gh-aw/agent/model-resolution.json","/tmp/gh-aw/agent-stdio.log","/tmp/gh-aw/agent/harness_retry.json","/tmp/gh-aw/pre-agent-audit.txt","/tmp/gh-aw/github_rate_limits.jsonl","/tmp/gh-aw/otel.jsonl","/tmp/gh-aw/otlp-export-errors.jsonl","/tmp/gh-aw/safeoutputs.jsonl","/tmp/gh-aw/agent_output.json","/tmp/gh-aw","/tmp/gh-aw","/tmp/gh-aw/awf-config.json","/tmp/gh-aw/awf-resolved-config.json","/tmp/gh-aw/sandbox/firewall/logs/","/tmp/gh-aw/sandbox/firewall/audit/","/tmp/gh-aw/sandbox/firewall/awf-reflect.json"]'
with:
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { main } = require(path.join(actionsDir, 'validate_recovery_envelopes.cjs'));
main({ core, additionalRoots: JSON.parse(process.env.GH_AW_RECOVERY_ADDITIONAL_ROOTS) });
# Small dedicated copy of the agent output so safe-output processing
# survives a failed or timed-out upload of the larger agent artifact
- name: Upload agent output fallback artifact
if: always() && steps.redact_secrets.outcome == 'success' && steps.validate_recovery_envelopes.outcome == 'success' && steps.validate_final_recovery_envelopes.outcome == 'success'
continue-on-error: true
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: agent-output-fallback
path: |
/tmp/gh-aw/agent_output.json
/tmp/gh-aw/safeoutputs.jsonl
/tmp/gh-aw/agent_execution.json
/tmp/gh-aw/agent_execution_exit_code.txt
/tmp/gh-aw/agent_usage.jsonl
/tmp/gh-aw/agent_usage.json
/tmp/gh-aw/agent/harness_retry.json
/tmp/gh-aw/agent/model-endpoint-mismatch.json
/tmp/gh-aw/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl
/tmp/gh-aw/sandbox/firewall-audit-logs/api-proxy-logs/model-routing.jsonl
/tmp/gh-aw/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl
/tmp/gh-aw/sandbox/firewall/logs/api-proxy-logs/model-routing.jsonl
/tmp/gh-aw/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl
/tmp/gh-aw/sandbox/firewall/audit/api-proxy-logs/model-routing.jsonl
/tmp/gh-aw/awf-resolved-config.json
if-no-files-found: ignore
retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '0' }}
- name: Upload agent artifacts
if: always() && steps.redact_secrets.outcome == 'success' && steps.validate_recovery_envelopes.outcome == 'success' && steps.validate_final_recovery_envelopes.outcome == 'success'
continue-on-error: true
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: agent
path: |
/tmp/gh-aw/aw-prompts/prompt.txt
/tmp/gh-aw/agent_execution.json
/tmp/gh-aw/agent_execution_exit_code.txt
/tmp/gh-aw/agent-session.jsonl
/tmp/gh-aw/agent-errors.jsonl
/tmp/gh-aw/aw-prompts/user.txt
/tmp/gh-aw/aw-prompts/system.txt
/tmp/gh-aw/skill_inventory.json
/tmp/gh-aw/mcp-config/logs/
/tmp/gh-aw/redacted-urls.log
/tmp/gh-aw/mcp-logs/
/tmp/gh-aw/agent_usage.json
/tmp/gh-aw/agent/model-resolution.json
/tmp/gh-aw/agent-stdio.log
/tmp/gh-aw/agent/harness_retry.json
/tmp/gh-aw/pre-agent-audit.txt
/tmp/gh-aw/github_rate_limits.jsonl
/tmp/gh-aw/otel.jsonl
/tmp/gh-aw/otlp-export-errors.jsonl
/tmp/gh-aw/safeoutputs.jsonl
/tmp/gh-aw/agent_output.json
/tmp/gh-aw/aw-*.patch
/tmp/gh-aw/aw-*.bundle
/tmp/gh-aw/awf-config.json
/tmp/gh-aw/awf-resolved-config.json
/tmp/gh-aw/sandbox/firewall/logs/
/tmp/gh-aw/sandbox/firewall/audit/
/tmp/gh-aw/sandbox/firewall/awf-reflect.json
if-no-files-found: ignore
retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '0' }}
conclusion:
name: conclusion
needs:
- activation
- admission
- agent
- detection
- evals
- push_evals_state
- safe_outputs
- update_cache_memory
if: >
always() && (needs.agent.result != 'skipped' || needs.activation.outputs.lockdown_check_failed == 'true' ||
needs.activation.outputs.oauth_token_check_failed == 'true' || needs.activation.outputs.stale_lock_file_failed == 'true' ||
needs.activation.outputs.secret_verification_result == 'failed' || needs.activation.outputs.daily_ai_credits_exceeded == 'true' ||
needs.activation.outputs.daily_ai_credits_guardrail_status == 'structural_error' || needs.activation.outputs.daily_ai_credits_guardrail_status == 'transient_error' ||
needs.activation.outputs.steering_issue_number != '')
runs-on: ubuntu-slim
# Permissions for the conclusion job (workflow permissions default to none).
permissions:
actions: read
checks: read
contents: write
issues: write
pull-requests: write
concurrency:
group: "gh-aw-conclusion-cloclo-${{ inputs.issue_number || github.run_id }}"
cancel-in-progress: false
queue: max
env:
GH_AW_JOB_DISPLAY_NAMES: "{\"activation\":\"activation\",\"admission\":\"admission\",\"agent\":\"agent\",\"conclusion\":\"conclusion\",\"conclusion_admission\":\"conclusion_admission\",\"detection\":\"detection\",\"evals\":\"evals\",\"pre_activation\":\"pre_activation\",\"push_evals_state\":\"push_evals_state\",\"safe_outputs\":\"safe_outputs\",\"update_cache_memory\":\"update_cache_memory\"}"
GH_AW_JOB_RESULTS: "{\"activation\":{\"result\":\"${{ needs.activation.result }}\"},\"admission\":{\"result\":\"${{ needs.admission.result }}\"},\"agent\":{\"result\":\"${{ needs.agent.result }}\"},\"detection\":{\"result\":\"${{ needs.detection.result }}\"},\"evals\":{\"result\":\"${{ needs.evals.result }}\"},\"push_evals_state\":{\"result\":\"${{ needs.push_evals_state.result }}\"},\"safe_outputs\":{\"result\":\"${{ needs.safe_outputs.result }}\"},\"update_cache_memory\":{\"result\":\"${{ needs.update_cache_memory.result }}\"}}"
GH_AW_JOB_TIMING_ELIGIBLE: "{\"activation\":true,\"admission\":true,\"agent\":true,\"conclusion\":true,\"conclusion_admission\":true,\"detection\":true,\"evals\":true,\"pre_activation\":true,\"push_evals_state\":true,\"safe_outputs\":true,\"update_cache_memory\":true}"
GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }}
outputs:
admission_compact_session: ${{ steps.admission-conclusion-metadata.outputs.compact_session }}
incomplete_count: ${{ steps.report_incomplete.outputs.incomplete_count }}
noop_comment_body: ${{ steps.noop.outputs.noop_comment_body }}
noop_message: ${{ steps.noop.outputs.noop_message }}
tools_reported: ${{ steps.missing_tool.outputs.tools_reported }}
total_count: ${{ steps.missing_tool.outputs.total_count }}
usage_artifact_id: ${{ steps.upload-usage-artifact.outputs.artifact-id }}
usage_artifact_retry_id: ${{ steps.upload-usage-artifact-retry.outputs.artifact-id }}
steps:
- name: Checkout actions folder
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: github/gh-aw
sparse-checkout: |
actions
fetch-depth: 1
clean: false
persist-credentials: false
- name: Setup Scripts
id: setup
uses: ./actions/setup
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
trace-id: ${{ needs.activation.outputs.setup-trace-id }}
parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }}
env:
GH_AW_SETUP_WORKFLOW_NAME: "/cloclo"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/cloclo.lock.yml@${{ github.ref }}
GH_AW_INFO_VERSION: "0.165.0"
GH_AW_INFO_AWF_VERSION: "v0.29.5"
GH_AW_INFO_ENGINE_ID: "codex"
GH_AW_SETUP_AW_CONTEXT: ${{ inputs.aw_context }}
- name: Download agent output artifact
id: download-agent-output
continue-on-error: true
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
pattern: "{agent,agent-output-fallback}"
merge-multiple: true
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
if [ -f "/tmp/gh-aw/agent_output.json" ]; then
echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT"
fi
- name: Warn if threat detection produced no verdict
if: always() && needs.detection.result != 'skipped' && (needs.detection.outputs.detection_reason == 'agent_failure' || needs.detection.outputs.detection_reason == 'parse_error' || needs.detection.outputs.detection_conclusion == '')
run: echo "::warning::Threat detection produced no security verdict. Review the detection job logs before trusting the agent outputs."
- name: Download detection artifact
id: download-detection-artifact
continue-on-error: true
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: detection
path: /tmp/gh-aw/threat-detection/
- name: Download Safe Outputs Items Manifest
id: download-safe-outputs-manifest
if: always()
continue-on-error: true
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
pattern: safe-outputs-items
merge-multiple: true
path: /tmp/gh-aw/
- name: Download evals artifact
id: download-evals-artifact
if: always()
continue-on-error: true
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
pattern: evals
merge-multiple: true
path: /tmp/gh-aw/evals/
- name: Process no-op messages
id: noop
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }}
GH_AW_NOOP_MAX: "2"
GH_AW_WORKFLOW_NAME: "/cloclo"
GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/cloclo.md"
GH_AW_ENGINE_ID: "codex"
GH_AW_ENGINE_MODEL: "copilot/gpt-5.6-terra"
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: "false"
GH_AW_AIC: ${{ needs.agent.outputs.aic }}
GH_AW_THREAT_DETECTION_AIC: ${{ needs.detection.outputs.aic }}
GH_AW_EVALS_AIC: ${{ needs.evals.outputs.aic }}
GH_AW_AMBIENT_CONTEXT: ${{ needs.agent.outputs.ambient_context }}
GH_AW_WORKFLOW_ID: "cloclo"
GH_AW_STEERING_ISSUE_NUMBER: ${{ needs.activation.outputs.steering_issue_number }}
GH_AW_STEERING_ISSUE_URL: ${{ needs.activation.outputs.steering_issue_url }}
with:
github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
const { main } = require(path.join(actionsDir, 'handle_noop_message.cjs'));
await main();
- name: Log detection run
id: detection_runs
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }}
GH_AW_WORKFLOW_NAME: "/cloclo"
GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/cloclo.md"
GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
GH_AW_DETECTION_CONCLUSION: ${{ needs.detection.outputs.detection_conclusion }}
GH_AW_DETECTION_REASON: ${{ needs.detection.outputs.detection_reason }}
with:
github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
const { main } = require(path.join(actionsDir, 'handle_detection_runs.cjs'));
await main();
- name: Record missing tool
id: missing_tool
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
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: "/cloclo"
GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/cloclo.md"
GH_AW_ENGINE_ID: "codex"
GH_AW_ENGINE_MODEL: "copilot/gpt-5.6-terra"
with:
github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
const { main } = require(path.join(actionsDir, 'missing_tool.cjs'));
await main();
- name: Record incomplete
id: report_incomplete
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }}
GH_AW_REPORT_INCOMPLETE_CREATE_ISSUE: "true"
GH_AW_WORKFLOW_NAME: "/cloclo"
GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/cloclo.md"
GH_AW_ENGINE_ID: "codex"
GH_AW_ENGINE_MODEL: "copilot/gpt-5.6-terra"
with:
github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
const { main } = require(path.join(actionsDir, 'report_incomplete_handler.cjs'));
await main();
- name: Handle agent failure
id: handle_agent_failure
if: always()
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }}
GH_AW_WORKFLOW_NAME: "/cloclo"
GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/cloclo.md"
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: "cloclo"
GH_AW_ACTION_FAILURE_ISSUE_EXPIRES_HOURS: "12"
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_CHECKOUT_PR_INVALIDATED: ${{ needs.agent.outputs.checkout_pr_invalidated }}
GH_AW_AI_CREDITS_RATE_LIMIT_ERROR: ${{ needs.agent.outputs.ai_credits_rate_limit_error || 'false' }}
GH_AW_UNKNOWN_MODEL_AI_CREDITS: ${{ needs.agent.outputs.unknown_model_ai_credits || 'false' }}
GH_AW_AIC: ${{ needs.agent.outputs.aic }}
GH_AW_THREAT_DETECTION_AIC: ${{ needs.detection.outputs.aic }}
GH_AW_DETECTION_JOB_RESULT: ${{ needs.detection.result }}
GH_AW_EVALS_AIC: ${{ needs.evals.outputs.aic }}
GH_AW_MAX_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_MAX_AI_CREDITS || '1000' }}
GH_AW_DEFAULT_CHECKOUT_USES_TRIGGER_REF: "true"
GH_AW_INFERENCE_ACCESS_ERROR: ${{ needs.agent.outputs.inference_access_error }}
GH_AW_MCP_POLICY_ERROR: ${{ needs.agent.outputs.mcp_policy_error }}
GH_AW_AGENTIC_ENGINE_TIMEOUT: ${{ needs.agent.outputs.agentic_engine_timeout }}
GH_AW_MODEL_NOT_SUPPORTED_ERROR: ${{ needs.agent.outputs.model_not_supported_error }}
GH_AW_MODEL_ENDPOINT_MISMATCH_ERROR: ${{ needs.agent.outputs.model_endpoint_mismatch_error }}
GH_AW_HTTP_400_RESPONSE_ERROR: ${{ needs.agent.outputs.http_400_response_error }}
GH_AW_MAX_CACHE_MISSES_EXCEEDED: ${{ needs.agent.outputs.max_cache_misses_exceeded }}
GH_AW_MISSING_MODEL_PRICING_ERROR: ${{ needs.agent.outputs.missing_model_pricing_error }}
GH_AW_MISSING_MODEL_PRICING_MODEL_NAME: ${{ needs.agent.outputs.missing_model_pricing_model_name }}
GH_AW_SHELL_EXPANSION_GUARD_REJECTED: ${{ needs.agent.outputs.shell_expansion_guard_rejected }}
GH_AW_ENGINE_API_HOSTS: "api.enterprise.githubcopilot.com,api.githubcopilot.com,api.business.githubcopilot.com,api.individual.githubcopilot.com"
GH_AW_FAILURE_ISSUE_NUMBER: ${{ needs.activation.outputs.steering_issue_number }}
GH_AW_CODE_PUSH_FAILURE_ERRORS: ${{ needs.safe_outputs.outputs.code_push_failure_errors }}
GH_AW_CODE_PUSH_FAILURE_COUNT: ${{ needs.safe_outputs.outputs.code_push_failure_count }}
GH_AW_LOCKDOWN_CHECK_FAILED: ${{ needs.activation.outputs.lockdown_check_failed }}
GH_AW_OAUTH_TOKEN_CHECK_FAILED: ${{ needs.activation.outputs.oauth_token_check_failed }}
GH_AW_STALE_LOCK_FILE_FAILED: ${{ needs.activation.outputs.stale_lock_file_failed }}
GH_AW_DAILY_AI_CREDITS_EXCEEDED: ${{ needs.activation.outputs.daily_ai_credits_exceeded }}
GH_AW_DAILY_AI_CREDITS_GUARDRAIL_STATUS: ${{ needs.activation.outputs.daily_ai_credits_guardrail_status }}
GH_AW_DAILY_AI_CREDITS_GUARDRAIL_ERROR: ${{ needs.activation.outputs.daily_ai_credits_guardrail_error }}
GH_AW_DAILY_AI_CREDITS_TOTAL: ${{ needs.activation.outputs.daily_ai_credits_total }}
GH_AW_DAILY_AI_CREDITS_ESTIMATED: ${{ needs.activation.outputs.daily_ai_credits_estimated }}
GH_AW_DAILY_AI_CREDITS_THRESHOLD: ${{ needs.activation.outputs.daily_ai_credits_threshold }}
GH_AW_DAILY_AI_CREDITS_CONTINUE_ON_ERROR: "false"
GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"\\u003e 🎤 *Magnifique! Performance by [{workflow_name}]({run_url})*{ai_credits_suffix}{history_link}\",\"runStarted\":\"🎵 Comme d'habitude! [{workflow_name}]({run_url}) takes the stage on this {event_type}...\",\"runSuccess\":\"🎤 Bravo! [{workflow_name}]({run_url}) has delivered a stunning performance! Standing ovation! 🌟\",\"runFailure\":\"🎵 Intermission... [{workflow_name}]({run_url}) {status}. Check the [run logs]({run_url}) for details.\"}"
GH_AW_GROUP_REPORTS: "false"
GH_AW_FAILURE_REPORT_AS_ISSUE: "true"
GH_AW_MISSING_TOOL_REPORT_AS_FAILURE: "true"
GH_AW_MISSING_DATA_REPORT_AS_FAILURE: "true"
GH_AW_TIMEOUT_MINUTES: "20"
GH_AW_CACHE_MEMORY_ENABLED: "true"
GH_AW_CACHE_MEMORY_RESTORE_0_MATCHED_KEY: ${{ needs.agent.outputs.cache_memory_restore_0_matched_key || '' }}
GH_AW_CACHE_MEMORY_RESTORE_0_CACHE_HIT: ${{ needs.agent.outputs.cache_memory_restore_0_cache_hit || 'false' }}
with:
github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
const { main } = require(path.join(actionsDir, 'handle_agent_failure.cjs'));
await main();
- name: Report failed jobs
id: report_failed_jobs
if: always()
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }}
GH_AW_WORKFLOW_NAME: "/cloclo"
GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/cloclo.md"
GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
GH_AW_REPORT_FAILED_JOBS: "true"
with:
github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
const { main } = require(path.join(actionsDir, 'report_failed_jobs.cjs'));
await main();
- name: Update reaction comment with completion status
id: conclusion
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
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: "/cloclo"
GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }}
GH_AW_NOOP_COMMENT_BODY: ${{ steps.noop.outputs.noop_comment_body }}
GH_AW_SAFE_OUTPUTS_RESULT: ${{ needs.safe_outputs.result }}
GH_AW_ACTIVATION_COMMENT_LINKS: ${{ needs.safe_outputs.outputs.activation_comment_links }}
GH_AW_DETECTION_CONCLUSION: ${{ needs.detection.outputs.detection_conclusion }}
GH_AW_DETECTION_REASON: ${{ needs.detection.outputs.detection_reason }}
GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"\\u003e 🎤 *Magnifique! Performance by [{workflow_name}]({run_url})*{ai_credits_suffix}{history_link}\",\"runStarted\":\"🎵 Comme d'habitude! [{workflow_name}]({run_url}) takes the stage on this {event_type}...\",\"runSuccess\":\"🎤 Bravo! [{workflow_name}]({run_url}) has delivered a stunning performance! Standing ovation! 🌟\",\"runFailure\":\"🎵 Intermission... [{workflow_name}]({run_url}) {status}. Check the [run logs]({run_url}) for details.\"}"
with:
github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
const { main } = require(path.join(actionsDir, 'notify_comment_error.cjs'));
await main();
- name: Complete steering issue
id: complete_steering_issue
if: always()
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }}
GH_AW_STEERING_ISSUE_NUMBER: ${{ needs.activation.outputs.steering_issue_number }}
GH_AW_FAILURE_ISSUE_NUMBER: ${{ steps.handle_agent_failure.outputs.failure_issue_number }}
GH_AW_CREATED_PR_NUMBER: ${{ needs.safe_outputs.outputs.created_pr_number }}
GH_AW_CREATED_PR_URL: ${{ needs.safe_outputs.outputs.created_pr_url }}
GH_AW_NEEDS: ${{ toJSON(needs) }}
with:
github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
const { main } = require(path.join(actionsDir, 'complete_steering_issue.cjs'));
await main();
- name: Collect usage artifact files
if: always()
continue-on-error: true
env:
GH_AW_DETECTION_JOB_RESULT: ${{ needs.detection.result }}
GH_AW_DETECTION_CONCLUSION: ${{ needs.detection.outputs.detection_conclusion }}
GH_AW_DETECTION_REASON: ${{ needs.detection.outputs.detection_reason }}
run: bash "${RUNNER_TEMP}/gh-aw/actions/collect_usage_artifact_files.sh"
- name: Generate usage activity summary and unified session
if: always()
continue-on-error: true
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
GH_AW_ADMISSION_RESULT: ${{ needs.activation.outputs.admission-result }}
GH_AW_ADMISSION_MAX_AI_CREDITS: ${{ needs.activation.outputs.admission-max-ai-credits }}
GH_AW_ADMISSION_MAX_AI_CREDITS_THREAT_DETECTION: ${{ needs.activation.outputs.admission-max-ai-credits-threat-detection }}
GH_AW_ADMISSION_MAX_AI_CREDITS_EVALS: ${{ needs.activation.outputs.admission-max-ai-credits-evals }}
GH_AW_GRADER_MANIFEST_0: '{"version":2,"graders":[{"id":"recurrence-determinism","name":"Recurrence Determinism (RQA DET)","description":"RQA DET: fraction of recurrent points forming diagonal (repeated-subsequence) lines","source":"builtin","enabled":true,"unit":"ratio","direction":"lower_is_better","max":1,"min":0},{"id":"recurrence-laminarity","name":"Recurrence Laminarity (RQA LAM)","description":"RQA LAM: fraction of recurrent points forming vertical (stagnation) lines","source":"builtin","enabled":true,"unit":"ratio","direction":"lower_is_better","max":1,"min":0},{"id":"state-revisit-probability-rep","name":"State Revisit Probability REP","description":"Fraction of canonical state visits that revisit an already visited state","source":"builtin","enabled":true,"unit":"ratio","direction":"lower_is_better","max":1,"min":0}]}'
GH_AW_GRADER_MANIFEST_CHUNKS: '1'
GH_AW_JOB_DURATIONS: ${{ steps.report_failed_jobs.outputs.job_durations }}
GH_AW_DAILY_AI_CREDITS_GUARDRAIL_STATUS: ${{ needs.activation.outputs.daily_ai_credits_guardrail_status }}
GH_AW_DAILY_AI_CREDITS_EXCEEDED: ${{ needs.activation.outputs.daily_ai_credits_exceeded }}
GH_AW_DAILY_AI_CREDITS_TOTAL: ${{ needs.activation.outputs.daily_ai_credits_total }}
GH_AW_DAILY_AI_CREDITS_ESTIMATED: ${{ needs.activation.outputs.daily_ai_credits_estimated }}
GH_AW_DAILY_AI_CREDITS_THRESHOLD: ${{ needs.activation.outputs.daily_ai_credits_threshold }}
with:
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
const { main } = require(path.join(actionsDir, 'generate_usage_artifacts.cjs'));
await main();
- name: Prepare admission conclusion metadata
id: admission-conclusion-metadata
if: always() && vars.GH_AW_DEFAULT_ADMISSION_URL != ''
continue-on-error: true
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const path = require('node:path');
const { readCompactUnifiedSession } = require(path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions', 'compact_unified_session.cjs'));
const compact = readCompactUnifiedSession('/tmp/gh-aw/usage/aw_session.jsonl');
core.setOutput('compact_session', JSON.stringify({ version: compact.version, session: compact.session, included_events: compact.includedEvents, omitted_events: compact.omittedEvents, oversized_lines: compact.oversizedLines, scan_truncated: compact.scanTruncated, truncated: compact.truncated }));
- name: Upload usage artifact
id: upload-usage-artifact
if: always()
continue-on-error: true
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: usage
path: |
/tmp/gh-aw/usage/aw_session.jsonl
/tmp/gh-aw/usage/aw_info.json
/tmp/gh-aw/usage/aw-info.jsonl
/tmp/gh-aw/usage/agent_usage.json
/tmp/gh-aw/usage/agent_usage.jsonl
/tmp/gh-aw/usage/detection_usage.jsonl
/tmp/gh-aw/usage/evals.jsonl
/tmp/gh-aw/usage/graders/grader_manifest.json
/tmp/gh-aw/usage/graders/grader_results.json
/tmp/gh-aw/usage/github_rate_limits.jsonl
/tmp/gh-aw/usage/agent/token_usage.jsonl
/tmp/gh-aw/usage/agent/model-routing.jsonl
/tmp/gh-aw/usage/agent/execution.json
/tmp/gh-aw/usage/agent/harness_retry.json
/tmp/gh-aw/usage/detection/token_usage.jsonl
/tmp/gh-aw/usage/detection/execution.json
/tmp/gh-aw/usage/detection/harness_retry.json
/tmp/gh-aw/usage/detection/detection_result.json
/tmp/gh-aw/usage/evals/token_usage.jsonl
/tmp/gh-aw/usage/evals/execution.json
/tmp/gh-aw/usage/evals/evals_status.json
/tmp/gh-aw/usage/experiment/state.jsonl
/tmp/gh-aw/usage/experiment/state.json
/tmp/gh-aw/usage/experiment/assignments.json
/tmp/gh-aw/usage/activity/summary.json
if-no-files-found: ignore
retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '0' }}
- name: Wait before retrying usage artifact upload
if: always() && steps.upload-usage-artifact.outcome == 'failure'
run: sleep 10
- name: Retry upload usage artifact
id: upload-usage-artifact-retry
if: always() && steps.upload-usage-artifact.outcome == 'failure'
continue-on-error: true
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: usage
path: |
/tmp/gh-aw/usage/aw_session.jsonl
/tmp/gh-aw/usage/aw_info.json
/tmp/gh-aw/usage/aw-info.jsonl
/tmp/gh-aw/usage/agent_usage.json
/tmp/gh-aw/usage/agent_usage.jsonl
/tmp/gh-aw/usage/detection_usage.jsonl
/tmp/gh-aw/usage/evals.jsonl
/tmp/gh-aw/usage/graders/grader_manifest.json
/tmp/gh-aw/usage/graders/grader_results.json
/tmp/gh-aw/usage/github_rate_limits.jsonl
/tmp/gh-aw/usage/agent/token_usage.jsonl
/tmp/gh-aw/usage/agent/model-routing.jsonl
/tmp/gh-aw/usage/agent/execution.json
/tmp/gh-aw/usage/agent/harness_retry.json
/tmp/gh-aw/usage/detection/token_usage.jsonl
/tmp/gh-aw/usage/detection/execution.json
/tmp/gh-aw/usage/detection/harness_retry.json
/tmp/gh-aw/usage/detection/detection_result.json
/tmp/gh-aw/usage/evals/token_usage.jsonl
/tmp/gh-aw/usage/evals/execution.json
/tmp/gh-aw/usage/evals/evals_status.json
/tmp/gh-aw/usage/experiment/state.jsonl
/tmp/gh-aw/usage/experiment/state.json
/tmp/gh-aw/usage/experiment/assignments.json
/tmp/gh-aw/usage/activity/summary.json
if-no-files-found: ignore
overwrite: true
retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '0' }}
conclusion_admission:
name: conclusion_admission
needs: conclusion
if: always() && needs.conclusion.result != 'skipped' && vars.GH_AW_DEFAULT_ADMISSION_URL != ''
runs-on: ubuntu-slim
# Permissions for the conclusion_admission job (workflow permissions default to none).
permissions:
contents: read
id-token: write
timeout-minutes: 5
env:
GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }}
steps:
- name: Checkout actions folder
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: github/gh-aw
sparse-checkout: |
actions
fetch-depth: 1
clean: false
persist-credentials: false
- name: Setup Scripts
id: setup
uses: ./actions/setup
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
env:
GH_AW_SETUP_WORKFLOW_NAME: "/cloclo"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/unknown.lock.yml@${{ github.ref }}
- name: Report admission conclusion
if: always() && vars.GH_AW_DEFAULT_ADMISSION_URL != ''
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
GH_AW_DEFAULT_ADMISSION_URL: ${{ vars.GH_AW_DEFAULT_ADMISSION_URL }}
GH_AW_DEFAULT_ADMISSION_AUDIENCE: ${{ vars.GH_AW_DEFAULT_ADMISSION_AUDIENCE }}
GH_AW_DEFAULT_ADMISSION_ON_OUTAGE: ${{ vars.GH_AW_DEFAULT_ADMISSION_ON_OUTAGE }}
GH_AW_ADMISSION_WORKFLOW_HASH: "ec3efe8f7f3cc8e20f49b04164321e6e2923f0d55b80df96fbbc96638b33ade5:1577e7c80f76a3124113c4b9762a1f0094660f2ff5f8295d074879354653dfe3"
GH_AW_INFO_WORKFLOW_ID: ${{ job.workflow_ref }}
GITHUB_ACTOR: ${{ github.actor }}
GITHUB_TRIGGERING_ACTOR: ${{ github.triggering_actor }}
GH_AW_ADMISSION_COMPACT_SESSION: ${{ needs.conclusion.outputs.admission_compact_session }}
GH_AW_USAGE_ARTIFACT_ID: ${{ needs.conclusion.outputs.usage_artifact_id }}
GH_AW_USAGE_ARTIFACT_RETRY_ID: ${{ needs.conclusion.outputs.usage_artifact_retry_id }}
with:
script: |
const { setupGlobals } = require(require('node:path').join(process.env.RUNNER_TEMP, 'gh-aw', 'actions', 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
await require(require('node:path').join(process.env.RUNNER_TEMP, 'gh-aw', 'actions', 'conclusion_admission.cjs')).main(core);
detection:
name: detection
needs:
- activation
- agent
if: always() && needs.agent.result != 'skipped'
runs-on: ubuntu-latest
# Permissions for the detection job (workflow permissions default to none).
permissions:
contents: read
timeout-minutes: 10
env:
GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }}
outputs:
aic: ${{ steps.parse_detection_token_usage.outputs.aic }}
detection_conclusion: ${{ steps.detection_conclusion.outputs.conclusion }}
detection_reason: ${{ steps.detection_conclusion.outputs.reason }}
detection_success: ${{ steps.detection_conclusion.outputs.success }}
run_detection: ${{ steps.detection_guard.outputs.run_detection }}
steps:
- name: Checkout actions folder
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: github/gh-aw
sparse-checkout: |
actions
fetch-depth: 1
clean: false
persist-credentials: false
- name: Setup Scripts
id: setup
uses: ./actions/setup
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
trace-id: ${{ needs.activation.outputs.setup-trace-id }}
parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }}
env:
GH_AW_SETUP_WORKFLOW_NAME: "/cloclo"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/cloclo.lock.yml@${{ github.ref }}
GH_AW_INFO_VERSION: "0.165.0"
GH_AW_INFO_AWF_VERSION: "v0.29.5"
GH_AW_INFO_ENGINE_ID: "codex"
GH_AW_SETUP_AW_CONTEXT: ${{ inputs.aw_context }}
- name: Download activation artifact
continue-on-error: true
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: activation
path: /tmp/gh-aw
- name: Download agent output artifact
id: download-agent-output
continue-on-error: true
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
pattern: "{agent,agent-output-fallback}"
merge-multiple: true
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
if [ -f "/tmp/gh-aw/agent_output.json" ]; then
echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT"
fi
- name: Clear agent token usage
if: always()
run: rm -f /tmp/gh-aw/agent_usage.json
- name: Checkout repository for patch context
if: needs.agent.outputs.has_patch == 'true'
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
# --- Threat Detection ---
- name: Initialize detection execution evidence
run: |
mkdir -p "/tmp/gh-aw/threat-detection"
evidence_tmp="/tmp/gh-aw/threat-detection/execution.json.tmp"
printf '{"version":1,"component":"detection","run_id":%s,"run_attempt":%s,"state":"not_started"}\n' "$GITHUB_RUN_ID" "$GITHUB_RUN_ATTEMPT" > "$evidence_tmp"
mv "$evidence_tmp" "/tmp/gh-aw/threat-detection/execution.json"
- name: Clear inherited Copilot session state
run: rm -rf /tmp/gh-aw/sandbox/agent/logs/copilot-session-state
- name: Clean stale firewall files from agent artifact
run: |
rm -rf /tmp/gh-aw/sandbox/firewall/logs
rm -rf /tmp/gh-aw/sandbox/firewall/audit
- name: Download container images
run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.29.5@sha256:921e50aed7b2a67265f42ab03c7d54a32c641922cc64f0875a5ae2bcb8b37532 ghcr.io/github/gh-aw-firewall/api-proxy:0.29.5@sha256:f36a9fc78aef0509ed5fa280819848cbdf099f60d7b338455ea54a5def18d6b1 ghcr.io/github/gh-aw-firewall/squid:0.29.5@sha256:34260cb89ea5d6d55b93ce13a5fe1772dbe8e1592e1200370160b7f5a0bd2ecd
- 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 Config for detection
if: always() && steps.detection_guard.outputs.run_detection == 'true'
run: |
rm -f "${RUNNER_TEMP}/gh-aw/mcp-config/mcp-servers.json"
rm -f "$HOME/.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: |
bash "${RUNNER_TEMP}/gh-aw/actions/prepare_threat_detection_files.sh"
- name: Setup threat detection
id: detection_setup
if: always() && steps.detection_guard.outputs.run_detection == 'true'
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
WORKFLOW_NAME: "/cloclo"
WORKFLOW_DESCRIPTION: "No description provided"
HAS_PATCH: ${{ needs.agent.outputs.has_patch }}
GH_AW_DETECTION_CONTINUE_ON_ERROR: "true"
GH_AW_DETECTION_SKIP_PROMPT_SUMMARY: "true"
with:
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
const { main } = require(path.join(actionsDir, '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: Install AWF binary
env:
GH_TOKEN: ${{ github.token }}
GH_HOST: github.com
run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.29.5 --rootless
- name: Setup Node.js
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version: '24'
package-manager-cache: false
- name: Install GitHub Copilot CLI
run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.103 --checksums-sha256 26cd3e4b32cde498e4961fb4d48e7b85d7859fc69af1a645a19201fdd577bdb2 --prefer-toolcache --cooldown-days 3
env:
GH_HOST: github.com
GITHUB_TOKEN: ${{ github.token }}
GH_AW_COPILOT_MIN_VERSION: 1.0.35
- name: Install threat-detect binary
id: threat_detect_install
if: always() && steps.detection_guard.outputs.run_detection == 'true'
continue-on-error: true
run: |
bash "${RUNNER_TEMP}/gh-aw/actions/install_threat_detect_binary.sh" v0.5.3 --artifact-base-url https://github.com/github/gh-aw-threat-detection/releases/download --sha256-amd64 7cfab3bd02717968a0584ddd3790cff22550059e36d6f656c4f35e9d27851009 --sha256-arm64 6f355949af98e7b5527a958ac11431bd7867db45c0191b94c3a205c662181cc6
- name: Execute threat detection with AWF
id: detection_agentic_execution
if: always() && steps.detection_guard.outputs.run_detection == 'true' && steps.detection_setup.outcome == 'success' && steps.detection_setup.outputs.ready == 'true' && steps.threat_detect_install.outcome == 'success'
continue-on-error: true
timeout-minutes: 10
env:
AWF_REFLECT_ENABLED: 1
COPILOT_AGENT_RUNNER_TYPE: STANDALONE
COPILOT_DUMMY_BYOK: dummy-byok-key-for-offline-mode
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
COPILOT_MODEL: copilot/gpt-5.6-terra
GH_AW_ADMISSION_MAX_AI_CREDITS: ${{ needs.activation.outputs.admission-max-ai-credits-threat-detection }}
GH_AW_ADMISSION_RESULT: ${{ needs.activation.outputs.admission-result }}
GH_AW_HARNESS_MAX_RETRIES: 0
GH_AW_LLM_PROVIDER: github
GH_AW_MAX_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_DETECTION_MAX_AI_CREDITS || '400' }}
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_PHASE: detection
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_TIMEOUT_MINUTES: 10
GH_AW_VERSION: dev
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows
GITHUB_COPILOT_PROMPT_MODE_EXTENSIONS: false
GITHUB_HEAD_REF: ${{ github.head_ref }}
GITHUB_REF_NAME: ${{ github.ref_name }}
GITHUB_SERVER_URL: ${{ github.server_url }}
GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md
GITHUB_WORKSPACE: ${{ github.workspace }}
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]
RUNNER_TEMP: ${{ runner.temp }}
TRACEPARENT: ${{ env.GITHUB_AW_OTEL_TRACE_ID != '' && env.GITHUB_AW_OTEL_PARENT_SPAN_ID != '' && format('00-{0}-{1}-01', env.GITHUB_AW_OTEL_TRACE_ID, env.GITHUB_AW_OTEL_PARENT_SPAN_ID) || '' }}
WORKFLOW_NAME: "/cloclo"
WORKFLOW_DESCRIPTION: "No description provided"
HAS_PATCH: ${{ needs.agent.outputs.has_patch }}
GH_AW_DETECTION_CONTINUE_ON_ERROR: "true"
run: |
mkdir -p "/tmp/gh-aw/threat-detection"
evidence_tmp="/tmp/gh-aw/threat-detection/execution.json.tmp"
printf '{"version":1,"component":"detection","run_id":%s,"run_attempt":%s,"state":"started"}\n' "$GITHUB_RUN_ID" "$GITHUB_RUN_ATTEMPT" > "$evidence_tmp"
mv "$evidence_tmp" "/tmp/gh-aw/threat-detection/execution.json"
export GH_AW_AWF_EXECUTION_COMPONENT="detection"
export GH_AW_AWF_EXECUTION_EVIDENCE_FILE="/tmp/gh-aw/threat-detection/execution.json"
set -o pipefail
printf '%s' "$(date +%s%3N)" > /tmp/gh-aw/agent_cli_start_ms.txt
GH_AW_COPILOT_SRC="$(command -v copilot 2>/dev/null || true)"
if [ -z "$GH_AW_COPILOT_SRC" ] || [ ! -x "$GH_AW_COPILOT_SRC" ]; then
echo "GitHub Copilot CLI executable not found on PATH after installation" >&2
exit 127
fi
GH_AW_COPILOT_BIN="${RUNNER_TEMP}/gh-aw/bin/copilot"
mkdir -p "${RUNNER_TEMP}/gh-aw/bin"
if [ "$GH_AW_COPILOT_SRC" != "$GH_AW_COPILOT_BIN" ]; then
cp "$GH_AW_COPILOT_SRC" "$GH_AW_COPILOT_BIN"
fi
chmod 755 "$GH_AW_COPILOT_BIN"
(umask 177 && touch /tmp/gh-aw/threat-detection/detection.log)
GH_AW_MAX_AI_CREDITS="${GH_AW_MAX_AI_CREDITS:-400}"
if [[ ! "$GH_AW_MAX_AI_CREDITS" =~ ^[0-9]+$ ]]; then
GH_AW_MAX_AI_CREDITS="400"
fi
if [[ "${GH_AW_ADMISSION_RESULT:-}" == "admitted" && -n "${GH_AW_ADMISSION_MAX_AI_CREDITS:-}" ]]; then
if [[ ! "$GH_AW_ADMISSION_MAX_AI_CREDITS" =~ ^[1-9][0-9]{0,9}$ ]] || (( GH_AW_ADMISSION_MAX_AI_CREDITS > 2147483647 )); then
echo "ERR_ADMISSION: Invalid runtime admission allowance." >&2
exit 1
fi
GH_AW_MAX_AI_CREDITS="$GH_AW_ADMISSION_MAX_AI_CREDITS"
echo "Admission allowance applied (value withheld)."
else
echo "No component admission allowance; retaining existing budget policy (value withheld)."
fi
unset GH_AW_ADMISSION_RESULT GH_AW_ADMISSION_MAX_AI_CREDITS
printf '%s\n' "{\"\$schema\":\"https://github.com/github/gh-aw-firewall/releases/download/v0.29.5/awf-config.schema.json\",\"network\":{\"allowDomains\":[\"cdn.playwright.dev\",\"playwright.download.prss.microsoft.com\"]},\"apiProxy\":{\"enabled\":true,\"enableTokenSteering\":true,\"maxRuns\":500,\"maxAiCredits\":${GH_AW_MAX_AI_CREDITS},\"maxCacheMisses\":5,\"providers\":{\"github-copilot\":{\"models\":{\"gpt-5.6-terra\":{\"cost\":{\"cache_read\":\"2e-07\",\"cache_write\":\"2.5e-06\",\"input\":\"2e-06\",\"output\":\"1.2e-05\"}}}}},\"models\":{\"agent\":[\"sonnet-6x\",\"gpt-6\",\"gpt-5.4\",\"gpt-5.5\",\"gpt-5.6\",\"gpt-5.3\",\"gemini-pro\",\"any\"],\"antigravity\":[\"copilot/antigravity*\",\"google/antigravity*\",\"gemini/antigravity*\"],\"any\":[\"copilot/*\",\"anthropic/*\",\"openai/*\",\"google/*\",\"gemini/*\"],\"auto\":[\"copilot/auto\",\"large\"],\"claude\":[\"agent\"],\"codex\":[\"agent\"],\"coding\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\",\"gpt-5-codex\",\"kimi\"],\"computer-use\":[\"copilot/*computer-use*\",\"google/*computer-use*\",\"gemini/*computer-use*\",\"openai/*computer-use*\"],\"copilot\":[\"agent\"],\"deep-research\":[\"copilot/deep-research*\",\"copilot/o3-deep-research*\",\"copilot/o4-mini-deep-research*\",\"google/deep-research*\",\"gemini/deep-research*\",\"openai/o3-deep-research*\",\"openai/o4-mini-deep-research*\"],\"detection\":[\"small\"],\"evals\":[\"copilot/gpt-6-luna-decisions\"],\"fable\":[\"copilot/*fable*\",\"anthropic/*fable*\"],\"gemini\":[\"agent\"],\"gemini-3-flash\":[\"copilot/gemini-3*flash*\",\"google/gemini-3*flash*\",\"gemini/gemini-3*flash*\"],\"gemini-3-pro\":[\"copilot/gemini-3*pro*\",\"google/gemini-3*pro*\",\"google/nano-banana*\",\"gemini/gemini-3*pro*\"],\"gemini-3.1-flash\":[\"copilot/gemini-3.1*flash*\",\"google/gemini-3.1*flash*\",\"gemini/gemini-3.1*flash*\"],\"gemini-3.1-pro\":[\"copilot/gemini-3.1*pro*\",\"google/gemini-3.1*pro*\",\"gemini/gemini-3.1*pro*\"],\"gemini-3.5-flash\":[\"copilot/gemini-3.5*flash*\",\"google/gemini-3.5*flash*\",\"gemini/gemini-3.5*flash*\"],\"gemini-3.6-flash\":[\"copilot/gemini-3.6*flash*\",\"google/gemini-3.6*flash*\",\"gemini/gemini-3.6*flash*\"],\"gemini-3.7-flash\":[\"copilot/gemini-3.7*flash*\",\"google/gemini-3.7*flash*\",\"gemini/gemini-3.7*flash*\"],\"gemini-3.8-flash\":[\"copilot/gemini-3.8*flash*\",\"google/gemini-3.8*flash*\",\"gemini/gemini-3.8*flash*\"],\"gemini-flash\":[\"copilot/gemini-*flash*\",\"google/gemini-*flash*\",\"gemini/gemini-*flash*\"],\"gemini-flash-lite\":[\"copilot/gemini-*flash*lite*\",\"google/gemini-*flash*lite*\",\"gemini/gemini-*flash*lite*\"],\"gemini-omni\":[\"copilot/gemini-omni*\",\"google/gemini-omni*\",\"gemini/gemini-omni*\"],\"gemini-pro\":[\"copilot/gemini-*pro*\",\"google/gemini-*pro*\",\"gemini/gemini-*pro*\"],\"gemma\":[\"copilot/gemma*\",\"google/gemma*\",\"gemini/gemma*\"],\"gpt-5\":[\"copilot/gpt-5*\",\"openai/gpt-5*\"],\"gpt-5-codex\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\"],\"gpt-5-mini\":[\"copilot/gpt-5*mini*\",\"openai/gpt-5*mini*\"],\"gpt-5-nano\":[\"copilot/gpt-5*nano*\",\"openai/gpt-5*nano*\"],\"gpt-5-pro\":[\"copilot/gpt-5*pro*\",\"openai/gpt-5*pro*\"],\"gpt-5.1\":[\"copilot/gpt-5.1*\",\"openai/gpt-5.1*\"],\"gpt-5.2\":[\"copilot/gpt-5.2*\",\"openai/gpt-5.2*\"],\"gpt-5.3\":[\"copilot/gpt-5.3*\",\"openai/gpt-5.3*\"],\"gpt-5.4\":[\"copilot/gpt-5.4*\",\"openai/gpt-5.4*\"],\"gpt-5.5\":[\"copilot/gpt-5.5*\",\"openai/gpt-5.5*\"],\"gpt-5.6\":[\"copilot/gpt-5.6*\",\"openai/gpt-5.6*\"],\"gpt-6\":[\"copilot/gpt-6*\",\"openai/gpt-6*\"],\"grok\":[\"copilot/*grok*\",\"openai/*grok*\"],\"haiku\":[\"copilot/*haiku*\",\"anthropic/*haiku*\"],\"image-generation\":[\"copilot/gpt-image*\",\"openai/gpt-image*\",\"openai/chatgpt-image*\",\"copilot/gemini-*image*\",\"google/gemini-*image*\",\"gemini/gemini-*image*\",\"google/imagen*\"],\"kimi\":[\"copilot/kimi*\",\"openai/kimi*\"],\"kiwi\":[\"copilot/kiwi*\",\"openai/kiwi*\"],\"large\":[\"sonnet\",\"gpt-6\",\"gpt-5-pro\",\"gpt-5\",\"gemini-pro\"],\"lyria\":[\"google/lyria*\",\"gemini/lyria*\",\"copilot/lyria*\"],\"mai-code\":[\"copilot/MAI-Code*\",\"copilot/mai-code*\",\"openai/MAI-Code*\"],\"mini\":[\"haiku\",\"gpt-5-mini\",\"gpt-5-nano\",\"gemini-flash-lite\"],\"nano-banana\":[\"copilot/nano-banana*\",\"google/nano-banana*\",\"gemini/nano-banana*\"],\"opus\":[\"copilot/*opus*\",\"anthropic/*opus*\"],\"opusplan\":[\"opus?effort=high\"],\"raptor-mini\":[\"copilot/raptor*\",\"openai/raptor*\"],\"reasoning\":[\"copilot/o1*\",\"copilot/o3*\",\"copilot/o4*\",\"openai/o1*\",\"openai/o3*\",\"openai/o4*\"],\"robotics\":[\"copilot/*robotics*\",\"google/*robotics*\",\"gemini/*robotics*\"],\"small\":[\"mini\"],\"small-agent\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash\"],\"sonnet\":[\"copilot/*sonnet*\",\"anthropic/*sonnet*\"],\"sonnet-6x\":[\"copilot/*sonnet-4.5*\",\"copilot/*sonnet-4.6*\",\"copilot/*sonnet-5*\",\"copilot/*sonnet-4-5-*\",\"anthropic/*sonnet-4-5-*\",\"copilot/*sonnet-4-6*\",\"anthropic/*sonnet-4-6*\",\"anthropic/*sonnet-5*\"],\"summarization\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash-lite\",\"mini\"],\"veo\":[\"google/veo*\",\"gemini/veo*\"],\"vision\":[\"copilot/gemini-*image*\",\"google/gemini-*image*\",\"gemini/gemini-*image*\",\"copilot/gemini-*flash*\",\"google/gemini-*flash*\",\"gemini/gemini-*flash*\"]}},\"container\":{\"imageTag\":\"0.29.5,squid=sha256:34260cb89ea5d6d55b93ce13a5fe1772dbe8e1592e1200370160b7f5a0bd2ecd,agent=sha256:921e50aed7b2a67265f42ab03c7d54a32c641922cc64f0875a5ae2bcb8b37532,api-proxy=sha256:f36a9fc78aef0509ed5fa280819848cbdf099f60d7b338455ea54a5def18d6b1,cli-proxy=sha256:29781e0820de464fcc81298e5d9cb2162004d8eaad9cba75ac669a6459cac075\",\"agentTimeout\":10},\"logging\":{\"proxyLogsDir\":\"/tmp/gh-aw/sandbox/firewall/logs\",\"auditDir\":\"/tmp/gh-aw/sandbox/firewall/audit\"}}" > "${RUNNER_TEMP}/gh-aw/awf-config.json"
cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json
export GH_AW_MODELS_JSON_PATH="/tmp/gh-aw/models.json"
GH_AW_DOCKER_HOST=""
if [[ "${DOCKER_HOST:-}" =~ ^tcp:// ]]; then
GH_AW_DOCKER_HOST="${DOCKER_HOST}"
fi
if [[ "${DOCKER_HOST:-}" =~ ^tcp:// ]]; then
_GH_AW_CHROOT_JSON=$(jq -c --arg src "${RUNNER_TEMP}/gh-aw" --arg user "$(id -un)" --argjson uid "$(id -u)" --argjson gid "$(id -g)" --arg home "${RUNNER_TEMP}/gh-aw/home" '.chroot={"binariesSourcePath":$src,"identity":{"user":$user,"uid":$uid,"gid":$gid,"home":$home}}' "${RUNNER_TEMP}/gh-aw/awf-config.json") || { echo "chroot config patch failed" >&2; exit 1; }
printf '%s\n' "$_GH_AW_CHROOT_JSON" > "${RUNNER_TEMP}/gh-aw/awf-config.json"
fi
GH_AW_TOOL_CACHE_MOUNT=""
GH_AW_TOOL_CACHE="${RUNNER_TOOL_CACHE:?RUNNER_TOOL_CACHE must be set}"
if [ -d "$GH_AW_TOOL_CACHE" ]; then
if [[ "$GH_AW_TOOL_CACHE" != /opt/* ]]; then
GH_AW_TOOL_CACHE_MOUNT="$GH_AW_TOOL_CACHE:$GH_AW_TOOL_CACHE:ro"
fi
fi
# shellcheck disable=SC1003,SC2016,SC2086
awf --config "${RUNNER_TEMP}/gh-aw/awf-config.json" --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" ${GH_AW_TOOL_CACHE_MOUNT:+--mount "$GH_AW_TOOL_CACHE_MOUNT"} ${GH_AW_DOCKER_HOST:+--docker-host "$GH_AW_DOCKER_HOST"} --env-all --exclude-env ACTIONS_ID_TOKEN_REQUEST_TOKEN --exclude-env ACTIONS_ID_TOKEN_REQUEST_URL --exclude-env COPILOT_GITHUB_TOKEN --exclude-env GH_AW_OTLP_ALL_HEADERS --exclude-env GH_AW_OTLP_ENDPOINTS --exclude-env OTEL_EXPORTER_OTLP_ENDPOINT --exclude-env OTEL_EXPORTER_OTLP_HEADERS --mount /tmp/gh-aw:/tmp/gh-aw:rw --mount /tmp/gh-aw/threat-detection:/tmp/gh-aw/threat-detection:rw --log-level info --session-state-dir /tmp/gh-aw/sandbox/agent/session-state --skip-pull \
-- /bin/bash -c 'set +o histexpand; export PATH="${RUNNER_TEMP}/gh-aw/bin:$PATH" && : "${RUNNER_TOOL_CACHE:?RUNNER_TOOL_CACHE must be set}"; GH_AW_TOOL_CACHE="$RUNNER_TOOL_CACHE"; GH_AW_TOOL_BINS="$(find "$GH_AW_TOOL_CACHE" -maxdepth 5 -type d -name bin 2>/dev/null | tr "\n" ":")"; GH_AW_TOOL_BINS="${GH_AW_TOOL_BINS%:}"; export PATH="$PATH${GH_AW_TOOL_BINS:+:}$GH_AW_TOOL_BINS"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true; [ -n "$ERLANG_HOME" ] && export PATH="$ERLANG_HOME/bin:$PATH" || true && threat-detect --engine copilot --output /tmp/gh-aw/threat-detection/detection_result.json /tmp/gh-aw/threat-detection' 2>&1 | tee -a /tmp/gh-aw/threat-detection/detection.log
- name: Copy detection firewall logs
if: always() && steps.detection_guard.outputs.run_detection == 'true'
continue-on-error: true
run: |
mkdir -p /tmp/gh-aw/threat-detection/sandbox/firewall
if [ -d /tmp/gh-aw/sandbox/firewall/logs ]; then mkdir -p /tmp/gh-aw/threat-detection/sandbox/firewall/logs && cp -r /tmp/gh-aw/sandbox/firewall/logs/. /tmp/gh-aw/threat-detection/sandbox/firewall/logs/; fi
if [ -d /tmp/gh-aw/sandbox/firewall/audit ]; then mkdir -p /tmp/gh-aw/threat-detection/sandbox/firewall/audit && cp -r /tmp/gh-aw/sandbox/firewall/audit/. /tmp/gh-aw/threat-detection/sandbox/firewall/audit/; fi
- name: Redact secrets in detection logs
id: redact_detection_logs
if: always() && steps.detection_guard.outputs.run_detection == 'true'
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
GH_AW_SECRET_NAMES: 'COPILOT_GITHUB_TOKEN,GH_AW_OTEL_GRAFANA_AUTHORIZATION,GH_AW_OTEL_GRAFANA_ENDPOINT,GH_AW_OTEL_SENTRY_AUTHORIZATION,GH_AW_OTEL_SENTRY_ENDPOINT'
SECRET_COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
SECRET_GH_AW_OTEL_GRAFANA_AUTHORIZATION: ${{ secrets.GH_AW_OTEL_GRAFANA_AUTHORIZATION }}
SECRET_GH_AW_OTEL_GRAFANA_ENDPOINT: ${{ secrets.GH_AW_OTEL_GRAFANA_ENDPOINT }}
SECRET_GH_AW_OTEL_SENTRY_AUTHORIZATION: ${{ secrets.GH_AW_OTEL_SENTRY_AUTHORIZATION }}
SECRET_GH_AW_OTEL_SENTRY_ENDPOINT: ${{ secrets.GH_AW_OTEL_SENTRY_ENDPOINT }}
with:
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
const { main } = require(path.join(actionsDir, 'redact_secrets.cjs'));
const { persistDetectionMasks } = require(path.join(actionsDir, 'detection_mask_state.cjs'));
await main({ additionalDirectories: ["/tmp/gh-aw/threat-detection/sandbox/firewall"], persistDetectionMasks });
- name: Parse threat detection token usage for step summary
id: parse_detection_token_usage
if: always() && steps.detection_guard.outputs.run_detection == 'true' && steps.redact_detection_logs.outcome == 'success'
continue-on-error: true
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
GH_AW_TOKEN_USAGE_SUMMARY_TITLE: Threat Detection Token Usage
GH_AW_PHASE: detection
GH_AW_AGENT_USAGE_PATH: /tmp/gh-aw/threat-detection/detection_usage.json
GH_AW_AGENT_USAGE_JSONL_PATH: /tmp/gh-aw/threat-detection/detection_usage.jsonl
GH_AW_WRITE_EMPTY_USAGE: "true"
with:
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
const { main } = require(path.join(actionsDir, 'parse_token_usage.cjs'));
await main();
- name: Redact secrets in detection artifacts
id: redact_detection_artifacts
if: always() && steps.detection_guard.outputs.run_detection == 'true'
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
GH_AW_SECRET_NAMES: 'COPILOT_GITHUB_TOKEN,GH_AW_OTEL_GRAFANA_AUTHORIZATION,GH_AW_OTEL_GRAFANA_ENDPOINT,GH_AW_OTEL_SENTRY_AUTHORIZATION,GH_AW_OTEL_SENTRY_ENDPOINT'
SECRET_COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
SECRET_GH_AW_OTEL_GRAFANA_AUTHORIZATION: ${{ secrets.GH_AW_OTEL_GRAFANA_AUTHORIZATION }}
SECRET_GH_AW_OTEL_GRAFANA_ENDPOINT: ${{ secrets.GH_AW_OTEL_GRAFANA_ENDPOINT }}
SECRET_GH_AW_OTEL_SENTRY_AUTHORIZATION: ${{ secrets.GH_AW_OTEL_SENTRY_AUTHORIZATION }}
SECRET_GH_AW_OTEL_SENTRY_ENDPOINT: ${{ secrets.GH_AW_OTEL_SENTRY_ENDPOINT }}
with:
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
const { main } = require(path.join(actionsDir, 'redact_secrets.cjs'));
const { persistDetectionMasks } = require(path.join(actionsDir, 'detection_mask_state.cjs'));
await main({ additionalDirectories: ["/tmp/gh-aw/threat-detection/sandbox/firewall"], persistDetectionMasks });
- name: Render detection log
if: always() && steps.detection_guard.outputs.run_detection == 'true' && steps.redact_detection_logs.outcome == 'success' && steps.redact_detection_artifacts.outcome == 'success'
continue-on-error: true
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
const { main } = require(path.join(actionsDir, 'render_detection_log.cjs'));
await main();
- name: Upload threat detection artifact
if: always() && steps.detection_guard.outputs.run_detection == 'true' && steps.redact_detection_logs.outcome == 'success' && steps.redact_detection_artifacts.outcome == 'success'
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: detection
path: |
/tmp/gh-aw/threat-detection/detection_result.json
/tmp/gh-aw/threat-detection/execution.json
/tmp/gh-aw/threat-detection/detection_usage.json
/tmp/gh-aw/threat-detection/detection_usage.jsonl
/tmp/gh-aw/threat-detection/sandbox/firewall/logs/
/tmp/gh-aw/threat-detection/sandbox/firewall/audit/
if-no-files-found: ignore
retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '0' }}
- name: Conclude threat detection
id: detection_conclusion
if: always() && steps.detection_guard.outputs.run_detection == 'false' || (always() && steps.detection_guard.outputs.run_detection == 'true' && steps.redact_detection_logs.outcome == 'success' && steps.redact_detection_artifacts.outcome == 'success')
continue-on-error: true
env:
RUN_DETECTION: ${{ steps.detection_guard.outputs.run_detection }}
DETECTION_AGENTIC_EXECUTION_OUTCOME: ${{ steps.detection_agentic_execution.outcome }}
THREAT_DETECT_INSTALL_OUTCOME: ${{ steps.threat_detect_install.outcome }}
GH_AW_DETECTION_CONTINUE_ON_ERROR: "true"
run: |
bash "${RUNNER_TEMP}/gh-aw/actions/conclude_threat_detection.sh" /tmp/gh-aw/threat-detection/detection_result.json
- name: Upload skipped detection execution evidence
if: always() && steps.detection_guard.outputs.run_detection == 'false'
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: detection
path: /tmp/gh-aw/threat-detection/execution.json
if-no-files-found: ignore
retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '0' }}
evals:
name: evals
needs:
- activation
- agent
- detection
if: always() && needs.agent.result == 'success'
runs-on: ubuntu-latest
# Permissions for the evals job (workflow permissions default to none).
permissions:
contents: read
env:
GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }}
outputs:
aic: ${{ steps.parse_evals_token_usage.outputs.aic }}
steps:
- name: Checkout actions folder
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: github/gh-aw
sparse-checkout: |
actions
fetch-depth: 1
clean: false
persist-credentials: false
- name: Setup Scripts
id: setup
uses: ./actions/setup
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
trace-id: ${{ needs.activation.outputs.setup-trace-id }}
parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }}
env:
GH_AW_SETUP_WORKFLOW_NAME: "/cloclo"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/cloclo.lock.yml@${{ github.ref }}
GH_AW_INFO_VERSION: "0.165.0"
GH_AW_INFO_AWF_VERSION: "v0.29.5"
GH_AW_INFO_ENGINE_ID: "codex"
GH_AW_SETUP_AW_CONTEXT: ${{ inputs.aw_context }}
- name: Download agent output artifact
id: download-agent-output
continue-on-error: true
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
pattern: "{agent,agent-output-fallback}"
merge-multiple: true
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
if [ -f "/tmp/gh-aw/agent_output.json" ]; then
echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT"
fi
- name: Initialize evals execution evidence
if: always()
run: |
mkdir -p "/tmp/gh-aw/evals"
evidence_tmp="/tmp/gh-aw/evals/execution.json.tmp"
printf '{"version":1,"component":"evals","run_id":%s,"run_attempt":%s,"state":"not_started"}\n' "$GITHUB_RUN_ID" "$GITHUB_RUN_ATTEMPT" > "$evidence_tmp"
mv "$evidence_tmp" "/tmp/gh-aw/evals/execution.json"
- name: Prepare evals files
run: |
mkdir -p /tmp/gh-aw/evals
if [ -f /tmp/gh-aw/agent_output.json ]; then cp /tmp/gh-aw/agent_output.json /tmp/gh-aw/evals/agent_output.json; fi
- name: Execute BinEval Decisions
id: evals_decisions_execution
continue-on-error: true
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
GH_AW_DECISIONS_BASE_URL: https://api.githubcopilot.com/v1
GH_AW_DECISIONS_API_KEY: ${{ secrets.COPILOT_GITHUB_TOKEN }}
GH_AW_DECISIONS_PROVIDER: github-copilot
GH_AW_EVALS_QUESTIONS: '[{"id":"output-produced","question":"Did the agent create a pull request or post a comment?"},{"id":"summary-comment-added","question":"Does the agent output confirm that a summary comment was added to the original conversation thread?"}]'
GH_AW_EVALS_MODEL: "copilot/gpt-6-luna-decisions"
with:
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
const { executeMain } = require(path.join(actionsDir, 'run_evals.cjs'));
await executeMain();
- name: Parse BinEval results
if: always()
continue-on-error: true
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
GH_AW_EVALS_QUESTIONS: '[{"id":"output-produced","question":"Did the agent create a pull request or post a comment?"},{"id":"summary-comment-added","question":"Does the agent output confirm that a summary comment was added to the original conversation thread?"}]'
GH_AW_EVALS_MODEL: "copilot/gpt-6-luna-decisions"
GH_AW_EVALS_PHASE: parse
GH_AW_EVALS_EXECUTION_OUTCOME: ${{ steps.evals_decisions_execution.outcome }}
GITHUB_RUN_ID: ${{ github.run_id }}
with:
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
const { main } = require(path.join(actionsDir, 'run_evals.cjs'));
await main();
- name: Redact secrets in evals results
id: redact_evals_results
if: always()
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
const { main } = require(path.join(actionsDir, 'redact_evals_results.cjs'));
await main();
- name: Render evals results to step summary
if: always() && steps.redact_evals_results.outcome == 'success'
continue-on-error: true
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
const { main } = require(path.join(actionsDir, 'render_evals_summary.cjs'));
await main();
- name: Parse evals token usage for step summary
id: parse_evals_token_usage
if: always()
continue-on-error: true
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
const { summarizeUsageMain } = require(path.join(actionsDir, 'run_evals.cjs'));
await summarizeUsageMain();
- name: Upload evals results
if: always() && steps.redact_evals_results.outcome == 'success'
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: evals
path: |
/tmp/gh-aw/evals.jsonl
/tmp/gh-aw/evals_status.json
/tmp/gh-aw/evals_token_usage.jsonl
/tmp/gh-aw/evals/execution.json
if-no-files-found: ignore
retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '0' }}
- name: Upload evals accounting after failure
if: always() && steps.redact_evals_results.outcome != 'success'
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: evals
path: |
/tmp/gh-aw/evals_token_usage.jsonl
/tmp/gh-aw/evals/execution.json
if-no-files-found: ignore
retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '0' }}
- name: Restore actions folder
if: always()
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: github/gh-aw
sparse-checkout: |
actions/setup
sparse-checkout-cone-mode: true
fetch-depth: 1
clean: false
persist-credentials: false
pre_activation:
name: pre_activation
if: >
(fromJSON(github.event.inputs.aw_context || '{}').event_type == 'issues' || fromJSON(github.event.inputs.aw_context ||
'{}').event_type == 'pull_request' || fromJSON(github.event.inputs.aw_context || '{}').event_type == 'discussion') &&
(fromJSON(github.event.inputs.aw_context || '{}').trigger_label == 'cloclo') || !(fromJSON(github.event.inputs.aw_context ||
'{}').event_type == 'issues' || fromJSON(github.event.inputs.aw_context || '{}').event_type == 'pull_request' ||
fromJSON(github.event.inputs.aw_context || '{}').event_type == 'discussion')
runs-on: ubuntu-slim
# Permissions for the pre_activation job (workflow permissions default to none).
permissions:
contents: read
pull-requests: read
env:
GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }}
outputs:
activated: ${{ steps.check_membership.outputs.is_team_member == 'true' && steps.check_command_position.outputs.command_position_ok == 'true' }}
matched_command: ${{ steps.check_command_position.outputs.matched_command }}
setup-parent-span-id: ${{ steps.setup.outputs.parent-span-id || steps.setup.outputs.span-id }}
setup-span-id: ${{ steps.setup.outputs.span-id }}
setup-trace-id: ${{ steps.setup.outputs.trace-id }}
steps:
- name: Checkout actions folder
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: github/gh-aw
sparse-checkout: |
actions
fetch-depth: 1
clean: false
persist-credentials: false
- name: Setup Scripts
id: setup
uses: ./actions/setup
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
env:
GH_AW_SETUP_WORKFLOW_NAME: "/cloclo"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/cloclo.lock.yml@${{ github.ref }}
GH_AW_INFO_VERSION: "0.165.0"
GH_AW_INFO_AWF_VERSION: "v0.29.5"
GH_AW_INFO_ENGINE_ID: "codex"
GH_AW_SETUP_AW_CONTEXT: ${{ inputs.aw_context }}
- name: Check command position
id: check_command_position
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
GH_AW_COMMANDS: "[\"cloclo\"]"
with:
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
const { main } = require(path.join(actionsDir, 'check_command_position.cjs'));
await main();
- name: Check team membership for command workflow
id: check_membership
if: steps.check_command_position.outputs.command_position_ok == 'true'
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
GH_AW_REQUIRED_ROLES: "admin,maintainer,write"
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
const { main } = require(path.join(actionsDir, 'check_membership.cjs'));
await main();
push_evals_state:
name: push_evals_state
needs:
- activation
- evals
if: always() && (!cancelled()) && needs.evals.result != 'skipped'
runs-on: ubuntu-slim
# Permissions for the push_evals_state job (workflow permissions default to none).
permissions:
contents: write
env:
GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }}
steps:
- name: Checkout actions folder
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: github/gh-aw
sparse-checkout: |
actions
fetch-depth: 1
clean: false
persist-credentials: false
- name: Setup Scripts
id: setup
uses: ./actions/setup
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
trace-id: ${{ needs.activation.outputs.setup-trace-id }}
parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }}
env:
GH_AW_SETUP_WORKFLOW_NAME: "/cloclo"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/cloclo.lock.yml@${{ github.ref }}
GH_AW_INFO_VERSION: "0.165.0"
GH_AW_INFO_AWF_VERSION: "v0.29.5"
GH_AW_INFO_ENGINE_ID: "codex"
GH_AW_SETUP_AW_CONTEXT: ${{ inputs.aw_context }}
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
sparse-checkout: .
- name: Configure Git credentials
env:
GITHUB_REPOSITORY: ${{ github.repository }}
GITHUB_SERVER_URL: ${{ github.server_url }}
GITHUB_TOKEN: ${{ github.token }}
run: bash "${RUNNER_TEMP}/gh-aw/actions/configure_git_credentials.sh"
- name: Download evals artifact
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
continue-on-error: true
with:
pattern: evals
merge-multiple: true
path: /tmp/gh-aw/evals-state
- name: Push evals results to git
id: push_evals_state
if: always()
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
GH_TOKEN: ${{ github.token }}
GITHUB_RUN_ID: ${{ github.run_id }}
GITHUB_SERVER_URL: ${{ github.server_url }}
GH_AW_STATE_DIR: /tmp/gh-aw/evals-state
GH_AW_STATE_BRANCH: evals/cloclo
GH_AW_STATE_FILES: evals.jsonl
GH_AW_STATE_LABEL: evals results
with:
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit);
const { main } = require(path.join(actionsDir, 'push_evals_state.cjs'));
await main();
- name: Restore actions folder
if: always()
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: github/gh-aw
sparse-checkout: |
actions/setup
sparse-checkout-cone-mode: true
fetch-depth: 1
clean: false
persist-credentials: false
safe_outputs:
name: safe_outputs
needs:
- activation
- agent
- detection
if: (!cancelled()) && needs.agent.result != 'skipped' && needs.detection.result == 'success'
runs-on: ubuntu-latest # Safe-output code publication checks out repository files; ubuntu-slim is limited to 15 minutes.
# Permissions for the safe_outputs job (workflow permissions default to none).
permissions:
contents: write
issues: write
pull-requests: write
timeout-minutes: 45
env:
GH_AW_AGENT_AIC: ${{ needs.agent.outputs.aic }}
GH_AW_AIC: ${{ needs.agent.outputs.aic }}
GH_AW_AMBIENT_CONTEXT: ${{ needs.agent.outputs.ambient_context }}
GH_AW_CALLER_WORKFLOW_ID: "${{ github.repository }}/cloclo"
GH_AW_COMMANDS: "[\"cloclo\"]"
GH_AW_DETECTION_CONCLUSION: ${{ needs.detection.outputs.detection_conclusion }}
GH_AW_DETECTION_REASON: ${{ needs.detection.outputs.detection_reason }}
GH_AW_ENGINE_ID: "codex"
GH_AW_ENGINE_MODEL: "copilot/gpt-5.6-terra"
GH_AW_LABEL_COMMANDS: "[\"cloclo\"]"
GH_AW_OBJECT_PACK_FETCH_DEPTHS: ${{ vars.GH_AW_OBJECT_PACK_FETCH_DEPTHS }}
GH_AW_OBJECT_PACK_MAX_BYTES: ${{ vars.GH_AW_OBJECT_PACK_MAX_BYTES }}
GH_AW_OBJECT_PACK_MAX_OBJECTS: ${{ vars.GH_AW_OBJECT_PACK_MAX_OBJECTS }}
GH_AW_OBJECT_PACK_TIMEOUT_MS: ${{ vars.GH_AW_OBJECT_PACK_TIMEOUT_MS }}
GH_AW_PROJECT_UTC: "-08:00"
GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }}
GH_AW_RUN_DETECTION: ${{ needs.detection.outputs.run_detection }}
GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"\\u003e 🎤 *Magnifique! Performance by [{workflow_name}]({run_url})*{ai_credits_suffix}{history_link}\",\"runStarted\":\"🎵 Comme d'habitude! [{workflow_name}]({run_url}) takes the stage on this {event_type}...\",\"runSuccess\":\"🎤 Bravo! [{workflow_name}]({run_url}) has delivered a stunning performance! Standing ovation! 🌟\",\"runFailure\":\"🎵 Intermission... [{workflow_name}]({run_url}) {status}. Check the [run logs]({run_url}) for details.\"}"
GH_AW_THREAT_DETECTION_AIC: ${{ needs.detection.outputs.aic }}
GH_AW_WORKFLOW_EMOJI: "📊"
GH_AW_WORKFLOW_ID: "cloclo"
GH_AW_WORKFLOW_NAME: "/cloclo"
GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/cloclo.md"
outputs:
activation_comment_links: ${{ steps.process_safe_outputs.outputs.activation_comment_links }}
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_pr_number: ${{ steps.process_safe_outputs.outputs.created_pr_number }}
created_pr_url: ${{ steps.process_safe_outputs.outputs.created_pr_url }}
process_safe_outputs_items_applied: ${{ steps.process_safe_outputs.outputs.items_applied }}
process_safe_outputs_items_cancelled: ${{ steps.process_safe_outputs.outputs.items_cancelled }}
process_safe_outputs_items_deferred: ${{ steps.process_safe_outputs.outputs.items_deferred }}
process_safe_outputs_items_failed: ${{ steps.process_safe_outputs.outputs.items_failed }}
process_safe_outputs_items_skipped: ${{ steps.process_safe_outputs.outputs.items_skipped }}
process_safe_outputs_items_succeeded: ${{ steps.process_safe_outputs.outputs.items_succeeded }}
process_safe_outputs_items_warnings: ${{ steps.process_safe_outputs.outputs.items_warnings }}
process_safe_outputs_processed_count: ${{ steps.process_safe_outputs.outputs.processed_count }}
process_safe_outputs_status: ${{ steps.process_safe_outputs.outputs.status }}
steps:
- name: Checkout actions folder
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: github/gh-aw
sparse-checkout: |
actions
fetch-depth: 1
clean: false
persist-credentials: false
- name: Setup Scripts
id: setup
uses: ./actions/setup
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
trace-id: ${{ needs.activation.outputs.setup-trace-id }}
parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }}
env:
GH_AW_SETUP_WORKFLOW_NAME: "/cloclo"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/cloclo.lock.yml@${{ github.ref }}
GH_AW_INFO_VERSION: "0.165.0"
GH_AW_INFO_AWF_VERSION: "v0.29.5"
GH_AW_INFO_ENGINE_ID: "codex"
GH_AW_SETUP_AW_CONTEXT: ${{ inputs.aw_context }}
- name: Mask OTLP telemetry headers
run: bash "${RUNNER_TEMP}/gh-aw/actions/mask_otlp_headers.sh"
- name: Download agent output artifact
id: download-agent-output
continue-on-error: true
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
pattern: "{agent,agent-output-fallback}"
merge-multiple: true
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
if [ -f "/tmp/gh-aw/agent_output.json" ]; then
echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT"
fi
- name: Download patch artifact
continue-on-error: true
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: agent
path: /tmp/gh-aw/
- name: Checkout repository (gh-aw default)
if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request')
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: true
token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
- name: Configure Git credentials
if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request')
env:
GITHUB_REPOSITORY: ${{ github.repository }}
GITHUB_SERVER_URL: ${{ github.server_url }}
GIT_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
run: bash "${RUNNER_TEMP}/gh-aw/actions/configure_git_credentials.sh"
- name: Configure GH_HOST for enterprise compatibility
id: ghes-host-config
shell: bash
run: | # zizmor: ignore[github-env] - GITHUB_SERVER_URL is set by GitHub Actions, not user input.
# 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@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
GH_AW_JOB_CHECK_RUN_ID: ${{ job.check_run_id }}
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_MENTIONS_GITHUB_TOKEN: ${{ github.token }}
GH_AW_ALLOWED_DOMAINS: "*.grafana.net,*.sentry.io,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,cdn.playwright.dev,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,json-schema.org,json.schemastore.org,keyserver.ubuntu.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,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,playwright.download.prss.microsoft.com,ppa.launchpad.net,s.symcb.com,s.symcd.com,security.ubuntu.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_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":1,\"target\":\"${{ inputs.issue_number || 'triggering' }}\"},\"create_pull_request\":{\"excluded_files\":[\".github/workflows/*.lock.yml\"],\"expires\":48,\"labels\":[\"automation\",\"cloclo\"],\"max\":1,\"max_patch_files\":100,\"max_patch_size\":4096,\"protect_top_level_dot_folders\":true,\"protected_files\":[\"package.json\",\"bun.lockb\",\"bunfig.toml\",\"deno.json\",\"deno.jsonc\",\"deno.lock\",\"global.json\",\"NuGet.Config\",\"Directory.Packages.props\",\"mix.exs\",\"mix.lock\",\"go.mod\",\"go.sum\",\"stack.yaml\",\"stack.yaml.lock\",\"pom.xml\",\"build.gradle\",\"build.gradle.kts\",\"settings.gradle\",\"settings.gradle.kts\",\"gradle.properties\",\"package-lock.json\",\"yarn.lock\",\"pnpm-lock.yaml\",\"npm-shrinkwrap.json\",\"requirements.txt\",\"Pipfile\",\"Pipfile.lock\",\"pyproject.toml\",\"setup.py\",\"setup.cfg\",\"Gemfile\",\"Gemfile.lock\",\"uv.lock\",\"CODEOWNERS\",\"DESIGN.md\",\"README.md\",\"CONTRIBUTING.md\",\"SECURITY.md\",\"CODE_OF_CONDUCT.md\",\"AGENTS.md\"],\"protected_files_path_exclude\":[\".changeset/*.md\"],\"protected_files_policy\":\"fallback-to-issue\",\"title_prefix\":\"[cloclo] \"},\"create_report_incomplete_issue\":{},\"noop\":{\"max\":2,\"report-as-issue\":\"false\"},\"report_incomplete\":{},\"report_missing_data\":{},\"report_missing_tool\":{}}"
GH_AW_CI_TRIGGER_TOKEN: ${{ secrets.GH_AW_CI_TRIGGER_TOKEN }}
GH_AW_GITHUB_TOKEN_SOURCE: ${{ secrets.GH_AW_GITHUB_TOKEN != '' && 'pat' || 'github_actions' }}
with:
github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
script: |
const path = require('path');
const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
setupGlobals(core, github, context, exec, io, getOctokit, process.env.GH_AW_GITHUB_TOKEN_SOURCE);
const { main } = require(path.join(actionsDir, 'process_safe_outputs.cjs'));
await main();
- name: Upload Safe Outputs Items
if: always()
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: safe-outputs-items
path: |
/tmp/gh-aw/safe-output-items.jsonl
/tmp/gh-aw/safe-output-outcomes.jsonl
/tmp/gh-aw/temporary-id-map.json
/tmp/gh-aw/safe-output-errors.json
if-no-files-found: ignore
retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '0' }}
- name: Restore actions folder
if: always()
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: github/gh-aw
sparse-checkout: |
actions/setup
sparse-checkout-cone-mode: true
fetch-depth: 1
clean: false
persist-credentials: false
update_cache_memory:
name: update_cache_memory
needs:
- activation
- agent
- detection
if: >
always() && needs.detection.result == 'success' && needs.detection.outputs.detection_success == 'true' &&
needs.agent.result == 'success' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' ||
github.event_name == 'repository_dispatch' || github.event_name == 'delete' || github.event_name == 'registry_package' ||
github.event_name == 'page_build' || github.event_name == 'schedule' || github.event_name == 'pull_request')
runs-on: ubuntu-slim
# Permissions for the update_cache_memory job (workflow permissions default to none).
permissions:
actions: write
contents: read
cache-mode: write-only
env:
GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }}
GH_AW_WORKFLOW_ID_SANITIZED: cloclo
steps:
- name: Checkout actions folder
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: github/gh-aw
sparse-checkout: |
actions
fetch-depth: 1
clean: false
persist-credentials: false
- name: Setup Scripts
id: setup
uses: ./actions/setup
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
trace-id: ${{ needs.activation.outputs.setup-trace-id }}
parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }}
env:
GH_AW_SETUP_WORKFLOW_NAME: "/cloclo"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/cloclo.lock.yml@${{ github.ref }}
GH_AW_INFO_VERSION: "0.165.0"
GH_AW_INFO_AWF_VERSION: "v0.29.5"
GH_AW_INFO_ENGINE_ID: "codex"
GH_AW_SETUP_AW_CONTEXT: ${{ inputs.aw_context }}
- name: Download cache-memory artifact (default)
id: download_cache_default
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
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@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
key: memory-none-nopolicy-cloclo-memory-${{ github.workflow }}-${{ github.run_id }}
path: /tmp/gh-aw/cache-memory