From 2780b81c8641cae06a248a309ea7b0474eb36261 Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Fri, 19 Dec 2025 20:04:04 +0800 Subject: [PATCH 01/59] fixed:serial insert failed becusea lost field. --- XEngine_Release/XEngine_DataBase/SQL_User.db | Bin 53248 -> 53248 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/XEngine_Release/XEngine_DataBase/SQL_User.db b/XEngine_Release/XEngine_DataBase/SQL_User.db index 651450ed9be4ec802b95b71b5fb1e4e3c2b5d558..b1dd3321b2550c40fefab20b0e38fa439a1144f0 100644 GIT binary patch delta 526 zcmZozz}&Ead4jZ{Cj$cmFA%c=F*6WnOw=)!_his3>)>Uc$-v2Ym4UCD`4DFryBfC= zM+oCpmg}tFH`d8AGcjmRoTysgB*e@v?&-iUzAyu8Xufml$n?l zpP!QwZ)9L(YG`C=iC>n*Imp#9#8n~0(aFbEK?%QNB@Is(1y8@pUwNlZzRt3eiJ@}h z#8R#%9Zhy|U0uc&?#XL-RT()ZGcrlAK^!u z%%ap3puSWkg_6{Y5?(IN&1&q2Ss0lnH*zgptRTR&xtp(CQ0zDZ8-D-;e>#67e*pg- z{!RR|`MLSIHwy|_@J|lV_f8R&X4Vx%4?!a%VJT)!Bw?U)ii`|^Q6&n*s6a`O*^?1} bz-|7o&mq9bw3)-)>Uc$-u#Qm4UCDcM)e9yBfC= zM+oCpmg_9nH`d8AGcnq2oM^>3`8vx=CdL(;KXNZ&+^oian1zXPH;}WPk*hI{nO$60 zm$9jSG9#O+B8zj7t7C|(LWrZ2kE?=XX-P(YQD#+Yd~j+}W@3(pr_1C3Hl4{?EV-Mz z`N{>wW;3wz2Qcub^EdJb@W0~U1ccoD+?xdjEchn}=zFv9A7>Ds=qM~HEXAxTh%ha* zIJL;g0O$?ni4)~TMFg3384;2Yt2Y1F=MZ3I-pt|fLw~VggTNvIfyD|yYJmX&YLQJv From 09861d9ebad040261b505dfbb6e917f54bfcc8a0 Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Fri, 24 Apr 2026 17:34:46 +0800 Subject: [PATCH 02/59] feat: add agentic workflows for issue triage and auto fix --- .github/workflows/auto-fix.lock.yml | 1296 +++++++++++++++++++++++ .github/workflows/auto-fix.md | 45 + .github/workflows/issue-triage.lock.yml | 1225 +++++++++++++++++++++ .github/workflows/issue-triage.md | 55 + 4 files changed, 2621 insertions(+) create mode 100644 .github/workflows/auto-fix.lock.yml create mode 100644 .github/workflows/auto-fix.md create mode 100644 .github/workflows/issue-triage.lock.yml create mode 100644 .github/workflows/issue-triage.md diff --git a/.github/workflows/auto-fix.lock.yml b/.github/workflows/auto-fix.lock.yml new file mode 100644 index 00000000..7711b118 --- /dev/null +++ b/.github/workflows/auto-fix.lock.yml @@ -0,0 +1,1296 @@ +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"d398b5a11e1f028613163987ae25df914efde30b5bf11a95ca2b9fa1d2d1c02b","compiler_version":"v0.68.3","strict":true,"agent_id":"codex","agent_model":"gpt-5.4"} +# gh-aw-manifest: {"version":1,"secrets":["CODEX_API_KEY","GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/setup-node","sha":"53b83947a5a98c8d113130e565377fae1a50d02f","version":"v6.3.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"ba90f2186d7ad780ec640f364005fa24e797b360","version":"v0.68.3"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.20"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.2.19"},{"image":"ghcr.io/github/github-mcp-server:v0.32.0"},{"image":"node:lts-alpine"}]} +# ___ _ _ +# / _ \ | | (_) +# | |_| | __ _ ___ _ __ | |_ _ ___ +# | _ |/ _` |/ _ \ '_ \| __| |/ __| +# | | | | (_| | __/ | | | |_| | (__ +# \_| |_/\__, |\___|_| |_|\__|_|\___| +# __/ | +# _ _ |___/ +# | | | | / _| | +# | | | | ___ _ __ _ __| |_| | _____ ____ +# | |/\| |/ _ \ '__| |/ /| _| |/ _ \ \ /\ / / ___| +# \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ +# \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ +# +# This file was automatically generated by gh-aw (v0.68.3). DO NOT EDIT. +# +# To update this file, edit the corresponding .md file and run: +# gh aw compile +# Not all edits will cause changes to this file. +# +# For more information: https://github.github.com/gh-aw/introduction/overview/ +# +# +# Secrets used: +# - CODEX_API_KEY +# - GH_AW_CI_TRIGGER_TOKEN +# - GH_AW_GITHUB_MCP_SERVER_TOKEN +# - GH_AW_GITHUB_TOKEN +# - GITHUB_TOKEN +# - OPENAI_API_KEY +# +# Custom actions used: +# - actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 +# - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 +# - actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 +# - actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 +# - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 +# - github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 +# +# Container images used: +# - ghcr.io/github/gh-aw-firewall/agent:0.25.20 +# - ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20 +# - ghcr.io/github/gh-aw-firewall/squid:0.25.20 +# - ghcr.io/github/gh-aw-mcpg:v0.2.19 +# - ghcr.io/github/github-mcp-server:v0.32.0 +# - node:lts-alpine + +name: "自动修复 Bug" +"on": + issues: + types: + - labeled + +permissions: {} + +concurrency: + group: "gh-aw-${{ github.workflow }}-${{ github.event.issue.number || github.run_id }}" + +run-name: "自动修复 Bug" + +jobs: + activation: + needs: pre_activation + if: needs.pre_activation.outputs.activated == 'true' + runs-on: ubuntu-slim + permissions: + actions: read + contents: read + outputs: + body: ${{ steps.sanitized.outputs.body }} + comment_id: "" + comment_repo: "" + lockdown_check_failed: ${{ steps.generate_aw_info.outputs.lockdown_check_failed == 'true' }} + model: ${{ steps.generate_aw_info.outputs.model }} + secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} + setup-trace-id: ${{ steps.setup.outputs.trace-id }} + stale_lock_file_failed: ${{ steps.check-lock-file.outputs.stale_lock_file_failed == 'true' }} + text: ${{ steps.sanitized.outputs.text }} + title: ${{ steps.sanitized.outputs.title }} + steps: + - name: Setup Scripts + id: setup + uses: github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.pre_activation.outputs.setup-trace-id }} + - 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: "gpt-5.4" + GH_AW_INFO_VERSION: "0.118.0" + GH_AW_INFO_AGENT_VERSION: "0.118.0" + GH_AW_INFO_CLI_VERSION: "v0.68.3" + GH_AW_INFO_WORKFLOW_NAME: "自动修复 Bug" + GH_AW_INFO_EXPERIMENTAL: "false" + GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true" + GH_AW_INFO_STAGED: "false" + GH_AW_INFO_ALLOWED_DOMAINS: '["api.zhizengzeng.com"]' + GH_AW_INFO_FIREWALL_ENABLED: "true" + GH_AW_INFO_AWF_VERSION: "v0.25.20" + GH_AW_INFO_AWMG_VERSION: "" + GH_AW_INFO_FIREWALL_TYPE: "squid" + GH_AW_COMPILED_STRICT: "true" + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/generate_aw_info.cjs'); + await main(core, context); + - name: Validate CODEX_API_KEY or OPENAI_API_KEY secret + id: validate-secret + run: bash "${RUNNER_TEMP}/gh-aw/actions/validate_multi_secret.sh" CODEX_API_KEY OPENAI_API_KEY Codex https://github.github.com/gh-aw/reference/engines/#openai-codex + env: + CODEX_API_KEY: ${{ secrets.CODEX_API_KEY }} + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + - name: Checkout .github and .agents folders + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + sparse-checkout: | + .github + .agents + sparse-checkout-cone-mode: true + fetch-depth: 1 + - name: Check workflow lock file + id: check-lock-file + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_WORKFLOW_FILE: "auto-fix.lock.yml" + GH_AW_CONTEXT_WORKFLOW_REF: "${{ github.workflow_ref }}" + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/check_workflow_timestamp_api.cjs'); + await main(); + - name: Check compile-agentic version + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_COMPILED_VERSION: "v0.68.3" + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/check_version_updates.cjs'); + await main(); + - name: Compute current body text + id: sanitized + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/compute_text.cjs'); + await main(); + - name: Create prompt with built-in context + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_SAFE_OUTPUTS: ${{ runner.temp }}/gh-aw/safeoutputs/outputs.jsonl + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} + GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} + # poutine:ignore untrusted_checkout_exec + run: | + bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" + { + cat << 'GH_AW_PROMPT_59531e2cb7ae6a95_EOF' + + GH_AW_PROMPT_59531e2cb7ae6a95_EOF + cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" + cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" + cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" + cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" + cat << 'GH_AW_PROMPT_59531e2cb7ae6a95_EOF' + + Tools: add_comment, create_pull_request, missing_tool, missing_data, noop + GH_AW_PROMPT_59531e2cb7ae6a95_EOF + cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_create_pull_request.md" + cat << 'GH_AW_PROMPT_59531e2cb7ae6a95_EOF' + + + The following GitHub context information is available for this workflow: + {{#if __GH_AW_GITHUB_ACTOR__ }} + - **actor**: __GH_AW_GITHUB_ACTOR__ + {{/if}} + {{#if __GH_AW_GITHUB_REPOSITORY__ }} + - **repository**: __GH_AW_GITHUB_REPOSITORY__ + {{/if}} + {{#if __GH_AW_GITHUB_WORKSPACE__ }} + - **workspace**: __GH_AW_GITHUB_WORKSPACE__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ }} + - **issue-number**: #__GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ }} + - **discussion-number**: #__GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ }} + - **pull-request-number**: #__GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_COMMENT_ID__ }} + - **comment-id**: __GH_AW_GITHUB_EVENT_COMMENT_ID__ + {{/if}} + {{#if __GH_AW_GITHUB_RUN_ID__ }} + - **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__ + {{/if}} + + + GH_AW_PROMPT_59531e2cb7ae6a95_EOF + cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" + cat << 'GH_AW_PROMPT_59531e2cb7ae6a95_EOF' + + {{#runtime-import .github/workflows/auto-fix.md}} + GH_AW_PROMPT_59531e2cb7ae6a95_EOF + } > "$GH_AW_PROMPT" + - name: Interpolate variables and render templates + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/interpolate_prompt.cjs'); + await main(); + - name: Substitute placeholders + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} + GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} + GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: ${{ needs.pre_activation.outputs.activated }} + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + + const substitutePlaceholders = require('${{ runner.temp }}/gh-aw/actions/substitute_placeholders.cjs'); + + // Call the substitution function + return await substitutePlaceholders({ + file: process.env.GH_AW_PROMPT, + substitutions: { + GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR, + GH_AW_GITHUB_EVENT_COMMENT_ID: process.env.GH_AW_GITHUB_EVENT_COMMENT_ID, + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: process.env.GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER, + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: process.env.GH_AW_GITHUB_EVENT_ISSUE_NUMBER, + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: process.env.GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER, + GH_AW_GITHUB_REPOSITORY: process.env.GH_AW_GITHUB_REPOSITORY, + GH_AW_GITHUB_RUN_ID: process.env.GH_AW_GITHUB_RUN_ID, + GH_AW_GITHUB_WORKSPACE: process.env.GH_AW_GITHUB_WORKSPACE, + GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: process.env.GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED + } + }); + - name: Validate prompt placeholders + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + # poutine:ignore untrusted_checkout_exec + run: bash "${RUNNER_TEMP}/gh-aw/actions/validate_prompt_placeholders.sh" + - name: Print prompt + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + # poutine:ignore untrusted_checkout_exec + run: bash "${RUNNER_TEMP}/gh-aw/actions/print_prompt_summary.sh" + - name: Upload activation artifact + if: success() + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: activation + path: | + /tmp/gh-aw/aw_info.json + /tmp/gh-aw/aw-prompts/prompt.txt + /tmp/gh-aw/github_rate_limits.jsonl + if-no-files-found: ignore + retention-days: 1 + + agent: + needs: activation + runs-on: ubuntu-latest + permissions: + contents: read + issues: read + pull-requests: read + env: + DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + GH_AW_ASSETS_ALLOWED_EXTS: "" + GH_AW_ASSETS_BRANCH: "" + GH_AW_ASSETS_MAX_SIZE_KB: 0 + GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs + GH_AW_WORKFLOW_ID_SANITIZED: autofix + outputs: + checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} + effective_tokens: ${{ steps.parse-mcp-gateway.outputs.effective_tokens }} + has_patch: ${{ steps.collect_output.outputs.has_patch }} + model: ${{ needs.activation.outputs.model }} + output: ${{ steps.collect_output.outputs.output }} + output_types: ${{ steps.collect_output.outputs.output_types }} + setup-trace-id: ${{ steps.setup.outputs.trace-id }} + steps: + - name: Setup Scripts + id: setup + uses: github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} + - name: Set runtime paths + id: set-runtime-paths + run: | + { + 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: Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + - 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: Configure Git credentials + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + GITHUB_TOKEN: ${{ github.token }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + git config --global am.keepcr true + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Checkout PR branch + id: checkout-pr + if: | + github.event.pull_request || github.event.issue.pull_request + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + with: + github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/checkout_pr_branch.cjs'); + await main(); + - name: Setup Node.js + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 + with: + node-version: '24' + package-manager-cache: false + - name: Install Codex CLI + run: npm install --ignore-scripts -g @openai/codex@0.118.0 + - name: Install AWF binary + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.25.20 + - name: Determine automatic lockdown mode for GitHub MCP Server + id: determine-automatic-lockdown + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} + GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} + with: + script: | + const determineAutomaticLockdown = require('${{ runner.temp }}/gh-aw/actions/determine_automatic_lockdown.cjs'); + await determineAutomaticLockdown(github, context, core); + - name: Download container images + run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.25.20 ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20 ghcr.io/github/gh-aw-firewall/squid:0.25.20 ghcr.io/github/gh-aw-mcpg:v0.2.19 ghcr.io/github/github-mcp-server:v0.32.0 node:lts-alpine + - name: Write Safe Outputs Config + run: | + mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" + mkdir -p /tmp/gh-aw/safeoutputs + mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_0ff619be0f4cb7e0_EOF' + {"add_comment":{"max":1},"create_pull_request":{"base_branch":"main","max":1,"max_patch_size":1024,"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"],"protected_path_prefixes":[".github/",".agents/"]},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} + GH_AW_SAFE_OUTPUTS_CONFIG_0ff619be0f4cb7e0_EOF + - name: Write Safe Outputs Tools + env: + GH_AW_TOOLS_META_JSON: | + { + "description_suffixes": { + "add_comment": " CONSTRAINTS: Maximum 1 comment(s) can be added. Supports reply_to_id for discussion threading.", + "create_pull_request": " CONSTRAINTS: Maximum 1 pull request(s) can be created." + }, + "repo_params": {}, + "dynamic_tools": [] + } + GH_AW_VALIDATION_JSON: | + { + "add_comment": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "item_number": { + "issueOrPRNumber": true + }, + "reply_to_id": { + "type": "string", + "maxLength": 256 + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, + "create_pull_request": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "branch": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "draft": { + "type": "boolean" + }, + "labels": { + "type": "array", + "itemType": "string", + "itemSanitize": true, + "itemMaxLength": 128 + }, + "repo": { + "type": "string", + "maxLength": 256 + }, + "title": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 128 + } + } + }, + "missing_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, + "missing_tool": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 512 + }, + "reason": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "tool": { + "type": "string", + "sanitize": true, + "maxLength": 128 + } + } + }, + "noop": { + "defaultMax": 1, + "fields": { + "message": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + } + } + }, + "report_incomplete": { + "defaultMax": 5, + "fields": { + "details": { + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "reason": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 1024 + } + } + } + } + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/generate_safe_outputs_tools.cjs'); + await main(); + - name: Generate Safe Outputs MCP Server Config + id: safe-outputs-config + run: | + # Generate a secure random API key (360 bits of entropy, 40+ chars) + # Mask immediately to prevent timing vulnerabilities + API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${API_KEY}" + + PORT=3001 + + # Set outputs for next steps + { + echo "safe_outputs_api_key=${API_KEY}" + echo "safe_outputs_port=${PORT}" + } >> "$GITHUB_OUTPUT" + + echo "Safe Outputs MCP server will run on port ${PORT}" + + - name: Start Safe Outputs MCP HTTP Server + id: safe-outputs-start + env: + DEBUG: '*' + GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} + GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-config.outputs.safe_outputs_port }} + GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-config.outputs.safe_outputs_api_key }} + GH_AW_SAFE_OUTPUTS_TOOLS_PATH: ${{ runner.temp }}/gh-aw/safeoutputs/tools.json + GH_AW_SAFE_OUTPUTS_CONFIG_PATH: ${{ runner.temp }}/gh-aw/safeoutputs/config.json + GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs + run: | + # Environment variables are set above to prevent template injection + export DEBUG + export GH_AW_SAFE_OUTPUTS + export GH_AW_SAFE_OUTPUTS_PORT + export GH_AW_SAFE_OUTPUTS_API_KEY + export GH_AW_SAFE_OUTPUTS_TOOLS_PATH + export GH_AW_SAFE_OUTPUTS_CONFIG_PATH + export GH_AW_MCP_LOG_DIR + + bash "${RUNNER_TEMP}/gh-aw/actions/start_safe_outputs_server.sh" + + - name: Start MCP Gateway + id: start-mcp-gateway + env: + GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} + GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-start.outputs.api_key }} + GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-start.outputs.port }} + GITHUB_MCP_GUARD_MIN_INTEGRITY: ${{ steps.determine-automatic-lockdown.outputs.min_integrity }} + GITHUB_MCP_GUARD_REPOS: ${{ steps.determine-automatic-lockdown.outputs.repos }} + GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + run: | + set -eo pipefail + mkdir -p /tmp/gh-aw/mcp-config + + # Export gateway environment variables for MCP config and gateway script + export MCP_GATEWAY_PORT="80" + export MCP_GATEWAY_DOMAIN="host.docker.internal" + MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${MCP_GATEWAY_API_KEY}" + export MCP_GATEWAY_API_KEY + export MCP_GATEWAY_PAYLOAD_DIR="/tmp/gh-aw/mcp-payloads" + mkdir -p "${MCP_GATEWAY_PAYLOAD_DIR}" + export MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD="524288" + export DEBUG="*" + + export GH_AW_ENGINE="codex" + export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.2.19' + + cat > /tmp/gh-aw/mcp-config/config.toml << GH_AW_MCP_CONFIG_97f3a72e70f4fa1c_EOF + [history] + persistence = "none" + + [shell_environment_policy] + inherit = "core" + include_only = ["CODEX_API_KEY", "GH_AW_ASSETS_ALLOWED_EXTS", "GH_AW_ASSETS_BRANCH", "GH_AW_ASSETS_MAX_SIZE_KB", "GH_AW_SAFE_OUTPUTS", "GITHUB_PERSONAL_ACCESS_TOKEN", "GITHUB_REPOSITORY", "GITHUB_SERVER_URL", "HOME", "OPENAI_API_KEY", "PATH"] + + [mcp_servers.github] + user_agent = "bug" + startup_timeout_sec = 120 + tool_timeout_sec = 60 + container = "ghcr.io/github/github-mcp-server:v0.32.0" + env = { "GITHUB_HOST" = "$GITHUB_SERVER_URL", "GITHUB_PERSONAL_ACCESS_TOKEN" = "$GH_AW_GITHUB_TOKEN", "GITHUB_READ_ONLY" = "1", "GITHUB_TOOLSETS" = "context,repos,issues,pull_requests" } + env_vars = ["GITHUB_HOST", "GITHUB_PERSONAL_ACCESS_TOKEN", "GITHUB_READ_ONLY", "GITHUB_TOOLSETS"] + + [mcp_servers.safeoutputs] + type = "http" + url = "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT" + + [mcp_servers.safeoutputs.headers] + Authorization = "$GH_AW_SAFE_OUTPUTS_API_KEY" + + [mcp_servers.safeoutputs."guard-policies"] + + [mcp_servers.safeoutputs."guard-policies".write-sink] + accept = ["*"] + GH_AW_MCP_CONFIG_97f3a72e70f4fa1c_EOF + + # Generate JSON config for MCP gateway + cat << GH_AW_MCP_CONFIG_97f3a72e70f4fa1c_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" + { + "mcpServers": { + "github": { + "container": "ghcr.io/github/github-mcp-server:v0.32.0", + "env": { + "GITHUB_HOST": "$GITHUB_SERVER_URL", + "GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_MCP_SERVER_TOKEN", + "GITHUB_READ_ONLY": "1", + "GITHUB_TOOLSETS": "context,repos,issues,pull_requests" + }, + "guard-policies": { + "allow-only": { + "min-integrity": "$GITHUB_MCP_GUARD_MIN_INTEGRITY", + "repos": "$GITHUB_MCP_GUARD_REPOS" + } + } + }, + "safeoutputs": { + "type": "http", + "url": "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT", + "headers": { + "Authorization": "$GH_AW_SAFE_OUTPUTS_API_KEY" + }, + "guard-policies": { + "write-sink": { + "accept": [ + "*" + ] + } + } + } + }, + "gateway": { + "port": $MCP_GATEWAY_PORT, + "domain": "${MCP_GATEWAY_DOMAIN}", + "apiKey": "${MCP_GATEWAY_API_KEY}", + "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" + } + } + GH_AW_MCP_CONFIG_97f3a72e70f4fa1c_EOF + - name: Download activation artifact + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: activation + path: /tmp/gh-aw + - name: Clean git credentials + continue-on-error: true + run: bash "${RUNNER_TEMP}/gh-aw/actions/clean_git_credentials.sh" + - name: Execute Codex CLI + id: agentic_execution + run: | + set -o pipefail + mkdir -p "$CODEX_HOME/logs" && touch /tmp/gh-aw/agent-step-summary.md + (umask 177 && touch /tmp/gh-aw/agent-stdio.log) + # shellcheck disable=SC1003 + sudo -E awf --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" --env-all --exclude-env CODEX_API_KEY --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --exclude-env OPENAI_API_KEY --allow-domains 172.30.0.1,api.openai.com,api.zhizengzeng.com,host.docker.internal,openai.com --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --image-tag 0.25.20 --skip-pull --enable-api-proxy --openai-api-target api.zhizengzeng.com --openai-api-base-path /v1 \ + -- /bin/bash -c 'export PATH="$(find /opt/hostedtoolcache -maxdepth 4 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true && INSTRUCTION="$(cat /tmp/gh-aw/aw-prompts/prompt.txt)" && codex ${GH_AW_MODEL_AGENT_CODEX:+-c model="$GH_AW_MODEL_AGENT_CODEX" }exec -c web_search="disabled" -c fetch="disabled" --dangerously-bypass-approvals-and-sandbox --skip-git-repo-check "$INSTRUCTION"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + env: + CODEX_API_KEY: ${{ secrets.CODEX_API_KEY || secrets.OPENAI_API_KEY }} + CODEX_HOME: /tmp/gh-aw/mcp-config + GH_AW_MCP_CONFIG: /tmp/gh-aw/mcp-config/config.toml + GH_AW_MODEL_AGENT_CODEX: gpt-5.4 + 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: v0.68.3 + GITHUB_AW: true + GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md + GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com + GIT_AUTHOR_NAME: github-actions[bot] + GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com + GIT_COMMITTER_NAME: github-actions[bot] + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + OPENAI_BASE_URL: https://api.zhizengzeng.com/v1 + RUST_LOG: trace,hyper_util=info,mio=info,reqwest=info,os_info=info,codex_otel=warn,codex_core=debug,ocodex_exec=debug + - name: Configure Git credentials + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + GITHUB_TOKEN: ${{ github.token }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + git config --global am.keepcr true + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Stop MCP Gateway + if: always() + continue-on-error: true + env: + MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }} + MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }} + GATEWAY_PID: ${{ steps.start-mcp-gateway.outputs.gateway-pid }} + run: | + bash "${RUNNER_TEMP}/gh-aw/actions/stop_mcp_gateway.sh" "$GATEWAY_PID" + - name: Redact secrets in logs + if: always() + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/redact_secrets.cjs'); + await main(); + env: + GH_AW_SECRET_NAMES: 'CODEX_API_KEY,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN,OPENAI_API_KEY' + SECRET_CODEX_API_KEY: ${{ secrets.CODEX_API_KEY }} + SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} + SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} + SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SECRET_OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + - name: Append agent step summary + if: always() + run: bash "${RUNNER_TEMP}/gh-aw/actions/append_agent_step_summary.sh" + - name: Copy Safe Outputs + if: always() + env: + GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} + run: | + mkdir -p /tmp/gh-aw + cp "$GH_AW_SAFE_OUTPUTS" /tmp/gh-aw/safeoutputs.jsonl 2>/dev/null || true + - name: Ingest agent output + id: collect_output + if: always() + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} + GH_AW_ALLOWED_DOMAINS: "172.30.0.1,api.openai.com,api.zhizengzeng.com,host.docker.internal,openai.com" + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_API_URL: ${{ github.api_url }} + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/collect_ndjson_output.cjs'); + await main(); + - name: Parse agent logs for step summary + if: always() + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_AGENT_OUTPUT: /tmp/gh-aw/agent-stdio.log + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_codex_log.cjs'); + await main(); + - name: Parse MCP Gateway logs for step summary + if: always() + id: parse-mcp-gateway + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_mcp_gateway_log.cjs'); + await main(); + - name: Print firewall logs + if: always() + continue-on-error: true + env: + AWF_LOGS_DIR: /tmp/gh-aw/sandbox/firewall/logs + run: | + # Fix permissions on firewall logs so they can be uploaded as artifacts + # AWF runs with sudo, creating files owned by root + sudo chmod -R a+r /tmp/gh-aw/sandbox/firewall/logs 2>/dev/null || true + # Only run awf logs summary if awf command exists (it may not be installed if workflow failed before install step) + if command -v awf &> /dev/null; then + awf logs summary | tee -a "$GITHUB_STEP_SUMMARY" + else + echo 'AWF binary not installed, skipping firewall log summary' + fi + - name: Parse token usage for step summary + if: always() + continue-on-error: true + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_token_usage.cjs'); + await main(); + - 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: Upload agent artifacts + if: always() + continue-on-error: true + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: agent + path: | + /tmp/gh-aw/aw-prompts/prompt.txt + /tmp/gh-aw/mcp-config/logs/ + /tmp/gh-aw/redacted-urls.log + /tmp/gh-aw/mcp-logs/ + /tmp/gh-aw/agent_usage.json + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/agent/ + /tmp/gh-aw/github_rate_limits.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/sandbox/firewall/logs/ + /tmp/gh-aw/sandbox/firewall/audit/ + if-no-files-found: ignore + + conclusion: + needs: + - activation + - agent + - detection + - safe_outputs + if: > + always() && (needs.agent.result != 'skipped' || needs.activation.outputs.lockdown_check_failed == 'true' || + needs.activation.outputs.stale_lock_file_failed == 'true') + runs-on: ubuntu-slim + permissions: + contents: write + discussions: write + issues: write + pull-requests: write + concurrency: + group: "gh-aw-conclusion-auto-fix" + cancel-in-progress: false + outputs: + incomplete_count: ${{ steps.report_incomplete.outputs.incomplete_count }} + noop_message: ${{ steps.noop.outputs.noop_message }} + tools_reported: ${{ steps.missing_tool.outputs.tools_reported }} + total_count: ${{ steps.missing_tool.outputs.total_count }} + steps: + - name: Setup Scripts + id: setup + uses: github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} + - name: Download agent output artifact + id: download-agent-output + continue-on-error: true + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: agent + path: /tmp/gh-aw/ + - name: Setup agent output environment variable + id: setup-agent-output-env + if: steps.download-agent-output.outcome == 'success' + run: | + mkdir -p /tmp/gh-aw/ + find "/tmp/gh-aw/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT" + - name: Process no-op messages + id: noop + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} + GH_AW_NOOP_MAX: "1" + GH_AW_WORKFLOW_NAME: "自动修复 Bug" + GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} + GH_AW_NOOP_REPORT_AS_ISSUE: "true" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_noop_message.cjs'); + await main(); + - name: Log detection run + id: detection_runs + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "自动修复 Bug" + 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 { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_detection_runs.cjs'); + await main(); + - name: Record missing tool + id: missing_tool + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + 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: "自动修复 Bug" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/missing_tool.cjs'); + await main(); + - name: Record incomplete + id: report_incomplete + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + 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: "自动修复 Bug" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/report_incomplete_handler.cjs'); + await main(); + - name: Handle agent failure + id: handle_agent_failure + if: always() + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "自动修复 Bug" + 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: "auto-fix" + 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_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_STALE_LOCK_FILE_FAILED: ${{ needs.activation.outputs.stale_lock_file_failed }} + GH_AW_GROUP_REPORTS: "false" + GH_AW_FAILURE_REPORT_AS_ISSUE: "true" + GH_AW_TIMEOUT_MINUTES: "20" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_agent_failure.cjs'); + await main(); + + detection: + needs: + - activation + - agent + if: > + always() && needs.agent.result != 'skipped' && (needs.agent.outputs.output_types != '' || needs.agent.outputs.has_patch == 'true') + runs-on: ubuntu-latest + permissions: + contents: read + outputs: + detection_conclusion: ${{ steps.detection_conclusion.outputs.conclusion }} + detection_reason: ${{ steps.detection_conclusion.outputs.reason }} + detection_success: ${{ steps.detection_conclusion.outputs.success }} + steps: + - name: Setup Scripts + id: setup + uses: github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} + - name: Download agent output artifact + id: download-agent-output + continue-on-error: true + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: agent + path: /tmp/gh-aw/ + - name: Setup agent output environment variable + id: setup-agent-output-env + if: steps.download-agent-output.outcome == 'success' + run: | + mkdir -p /tmp/gh-aw/ + find "/tmp/gh-aw/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT" + - name: Checkout repository for patch context + if: needs.agent.outputs.has_patch == 'true' + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + # --- Threat Detection --- + - name: 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.25.20 ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20 ghcr.io/github/gh-aw-firewall/squid:0.25.20 + - name: Check if detection needed + id: detection_guard + if: always() + env: + OUTPUT_TYPES: ${{ needs.agent.outputs.output_types }} + HAS_PATCH: ${{ needs.agent.outputs.has_patch }} + run: | + if [[ -n "$OUTPUT_TYPES" || "$HAS_PATCH" == "true" ]]; then + echo "run_detection=true" >> "$GITHUB_OUTPUT" + echo "Detection will run: output_types=$OUTPUT_TYPES, has_patch=$HAS_PATCH" + else + echo "run_detection=false" >> "$GITHUB_OUTPUT" + echo "Detection skipped: no agent outputs or patches to analyze" + fi + - name: Clear MCP configuration for detection + if: always() && steps.detection_guard.outputs.run_detection == 'true' + run: | + rm -f /tmp/gh-aw/mcp-config/mcp-servers.json + rm -f /home/runner/.copilot/mcp-config.json + rm -f "$GITHUB_WORKSPACE/.gemini/settings.json" + - name: Prepare threat detection files + if: always() && steps.detection_guard.outputs.run_detection == 'true' + run: | + mkdir -p /tmp/gh-aw/threat-detection/aw-prompts + cp /tmp/gh-aw/aw-prompts/prompt.txt /tmp/gh-aw/threat-detection/aw-prompts/prompt.txt 2>/dev/null || true + cp /tmp/gh-aw/agent_output.json /tmp/gh-aw/threat-detection/agent_output.json 2>/dev/null || true + for f in /tmp/gh-aw/aw-*.patch; do + [ -f "$f" ] && cp "$f" /tmp/gh-aw/threat-detection/ 2>/dev/null || true + done + for f in /tmp/gh-aw/aw-*.bundle; do + [ -f "$f" ] && cp "$f" /tmp/gh-aw/threat-detection/ 2>/dev/null || true + done + echo "Prepared threat detection files:" + ls -la /tmp/gh-aw/threat-detection/ 2>/dev/null || true + - name: Setup threat detection + if: always() && steps.detection_guard.outputs.run_detection == 'true' + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + WORKFLOW_NAME: "自动修复 Bug" + WORKFLOW_DESCRIPTION: "No description provided" + HAS_PATCH: ${{ needs.agent.outputs.has_patch }} + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/setup_threat_detection.cjs'); + await main(); + - name: Ensure threat-detection directory and log + if: always() && steps.detection_guard.outputs.run_detection == 'true' + run: | + mkdir -p /tmp/gh-aw/threat-detection + touch /tmp/gh-aw/threat-detection/detection.log + - name: Setup Node.js + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 + with: + node-version: '24' + package-manager-cache: false + - name: Install Codex CLI + run: npm install --ignore-scripts -g @openai/codex@0.118.0 + - name: Install AWF binary + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.25.20 + - name: Execute Codex CLI + if: always() && steps.detection_guard.outputs.run_detection == 'true' + id: detection_agentic_execution + run: | + set -o pipefail + mkdir -p "$CODEX_HOME/logs" && touch /tmp/gh-aw/agent-step-summary.md + (umask 177 && touch /tmp/gh-aw/threat-detection/detection.log) + # shellcheck disable=SC1003 + sudo -E awf --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" --env-all --exclude-env CODEX_API_KEY --exclude-env OPENAI_API_KEY --allow-domains 172.30.0.1,api.openai.com,host.docker.internal,openai.com --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --image-tag 0.25.20 --skip-pull --enable-api-proxy --openai-api-target api.zhizengzeng.com --openai-api-base-path /v1 \ + -- /bin/bash -c 'export PATH="$(find /opt/hostedtoolcache -maxdepth 4 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true && INSTRUCTION="$(cat /tmp/gh-aw/aw-prompts/prompt.txt)" && codex ${GH_AW_MODEL_DETECTION_CODEX:+-c model="$GH_AW_MODEL_DETECTION_CODEX" }exec -c web_search="disabled" -c fetch="disabled" --dangerously-bypass-approvals-and-sandbox --skip-git-repo-check "$INSTRUCTION"' 2>&1 | tee -a /tmp/gh-aw/threat-detection/detection.log + env: + CODEX_API_KEY: ${{ secrets.CODEX_API_KEY || secrets.OPENAI_API_KEY }} + CODEX_HOME: /tmp/gh-aw/mcp-config + GH_AW_MCP_CONFIG: /tmp/gh-aw/mcp-config/config.toml + GH_AW_MODEL_DETECTION_CODEX: gpt-5.4 + GH_AW_PHASE: detection + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_VERSION: v0.68.3 + GITHUB_AW: true + GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md + GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com + GIT_AUTHOR_NAME: github-actions[bot] + GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com + GIT_COMMITTER_NAME: github-actions[bot] + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + OPENAI_BASE_URL: https://api.zhizengzeng.com/v1 + RUST_LOG: trace,hyper_util=info,mio=info,reqwest=info,os_info=info,codex_otel=warn,codex_core=debug,ocodex_exec=debug + - name: Upload threat detection log + if: always() && steps.detection_guard.outputs.run_detection == 'true' + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: detection + path: /tmp/gh-aw/threat-detection/detection.log + if-no-files-found: ignore + - name: Parse and conclude threat detection + id: detection_conclusion + if: always() + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + RUN_DETECTION: ${{ steps.detection_guard.outputs.run_detection }} + GH_AW_DETECTION_CONTINUE_ON_ERROR: "true" + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_threat_detection_results.cjs'); + await main(); + + pre_activation: + runs-on: ubuntu-slim + outputs: + activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} + matched_command: '' + setup-trace-id: ${{ steps.setup.outputs.trace-id }} + steps: + - name: Setup Scripts + id: setup + uses: github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + - name: Check team membership for workflow + id: check_membership + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_REQUIRED_ROLES: "admin,maintainer,write" + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/check_membership.cjs'); + await main(); + + safe_outputs: + needs: + - activation + - agent + - detection + if: (!cancelled()) && needs.agent.result != 'skipped' && needs.detection.result == 'success' + runs-on: ubuntu-slim + permissions: + contents: write + discussions: write + issues: write + pull-requests: write + timeout-minutes: 15 + env: + GH_AW_CALLER_WORKFLOW_ID: "${{ github.repository }}/auto-fix" + GH_AW_DETECTION_CONCLUSION: ${{ needs.detection.outputs.detection_conclusion }} + GH_AW_DETECTION_REASON: ${{ needs.detection.outputs.detection_reason }} + GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens }} + GH_AW_ENGINE_ID: "codex" + GH_AW_ENGINE_MODEL: "gpt-5.4" + GH_AW_WORKFLOW_ID: "auto-fix" + GH_AW_WORKFLOW_NAME: "自动修复 Bug" + outputs: + code_push_failure_count: ${{ steps.process_safe_outputs.outputs.code_push_failure_count }} + code_push_failure_errors: ${{ steps.process_safe_outputs.outputs.code_push_failure_errors }} + comment_id: ${{ steps.process_safe_outputs.outputs.comment_id }} + comment_url: ${{ steps.process_safe_outputs.outputs.comment_url }} + create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }} + create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }} + created_pr_number: ${{ steps.process_safe_outputs.outputs.created_pr_number }} + created_pr_url: ${{ steps.process_safe_outputs.outputs.created_pr_url }} + process_safe_outputs_processed_count: ${{ steps.process_safe_outputs.outputs.processed_count }} + process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }} + steps: + - name: Setup Scripts + id: setup + uses: github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} + - name: Download agent output artifact + id: download-agent-output + continue-on-error: true + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: agent + path: /tmp/gh-aw/ + - name: Setup agent output environment variable + id: setup-agent-output-env + if: steps.download-agent-output.outcome == 'success' + run: | + mkdir -p /tmp/gh-aw/ + find "/tmp/gh-aw/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT" + - name: Download patch artifact + continue-on-error: true + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: agent + path: /tmp/gh-aw/ + - name: Checkout repository + if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + ref: main + token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + persist-credentials: false + fetch-depth: 1 + - name: Configure Git credentials + if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + GIT_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + git config --global am.keepcr true + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${GIT_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Configure GH_HOST for enterprise compatibility + id: ghes-host-config + shell: bash + run: | + # Derive GH_HOST from GITHUB_SERVER_URL so the gh CLI targets the correct + # GitHub instance (GHES/GHEC). On github.com this is a harmless no-op. + GH_HOST="${GITHUB_SERVER_URL#https://}" + GH_HOST="${GH_HOST#http://}" + echo "GH_HOST=${GH_HOST}" >> "$GITHUB_ENV" + - name: Process Safe Outputs + id: process_safe_outputs + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} + GH_AW_ALLOWED_DOMAINS: "172.30.0.1,api.openai.com,api.zhizengzeng.com,host.docker.internal,openai.com" + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_API_URL: ${{ github.api_url }} + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":1},\"create_pull_request\":{\"base_branch\":\"main\",\"max\":1,\"max_patch_size\":1024,\"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\",\"AGENTS.md\"],\"protected_path_prefixes\":[\".github/\",\".agents/\",\".codex/\"]},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"report_incomplete\":{}}" + GH_AW_CI_TRIGGER_TOKEN: ${{ secrets.GH_AW_CI_TRIGGER_TOKEN }} + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/safe_output_handler_manager.cjs'); + await main(); + - name: Upload Safe Outputs Items + if: always() + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: safe-outputs-items + path: | + /tmp/gh-aw/safe-output-items.jsonl + /tmp/gh-aw/temporary-id-map.json + if-no-files-found: ignore + diff --git a/.github/workflows/auto-fix.md b/.github/workflows/auto-fix.md new file mode 100644 index 00000000..ab3cf86e --- /dev/null +++ b/.github/workflows/auto-fix.md @@ -0,0 +1,45 @@ +--- +on: + issues: + types: [labeled] + +engine: + id: codex + model: gpt-5.4 + env: + OPENAI_BASE_URL: "https://api.zhizengzeng.com/v1" + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + +network: + allowed: + - api.zhizengzeng.com + +permissions: + contents: read + issues: read + pull-requests: read + +safe-outputs: + create-pull-request: + base-branch: main + add-comment: + max: 1 +--- + +# 自动修复 Bug + +当 Issue 被打上 `bug` 标签时触发。 + +## 任务 + +1. 阅读 Issue #${{ github.event.issue.number }} 的完整内容 +2. 在仓库代码中定位问题所在的文件和函数 +3. 分析根本原因 +4. 实现修复方案,注意: + - 保持代码风格与现有代码一致 + - 只修改必要的部分,不做无关改动 + - 如果涉及多个文件,逐一修改 +5. 创建一个 Pull Request,标题格式:`fix: ` +6. 在原 Issue 下回复一条中文评论,说明已提交 PR 及修复思路 + +如果问题过于复杂或信息不足,在 Issue 下用中文说明原因,不要创建 PR。 \ No newline at end of file diff --git a/.github/workflows/issue-triage.lock.yml b/.github/workflows/issue-triage.lock.yml new file mode 100644 index 00000000..b33c321d --- /dev/null +++ b/.github/workflows/issue-triage.lock.yml @@ -0,0 +1,1225 @@ +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"5bb61465040f50022c019312920d003bccae1eb18d272aebf623ab2ca0a81b4c","compiler_version":"v0.68.3","strict":true,"agent_id":"codex","agent_model":"gpt-5.4"} +# gh-aw-manifest: {"version":1,"secrets":["CODEX_API_KEY","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/setup-node","sha":"53b83947a5a98c8d113130e565377fae1a50d02f","version":"v6.3.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"ba90f2186d7ad780ec640f364005fa24e797b360","version":"v0.68.3"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.20"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.2.19"},{"image":"ghcr.io/github/github-mcp-server:v0.32.0"},{"image":"node:lts-alpine"}]} +# ___ _ _ +# / _ \ | | (_) +# | |_| | __ _ ___ _ __ | |_ _ ___ +# | _ |/ _` |/ _ \ '_ \| __| |/ __| +# | | | | (_| | __/ | | | |_| | (__ +# \_| |_/\__, |\___|_| |_|\__|_|\___| +# __/ | +# _ _ |___/ +# | | | | / _| | +# | | | | ___ _ __ _ __| |_| | _____ ____ +# | |/\| |/ _ \ '__| |/ /| _| |/ _ \ \ /\ / / ___| +# \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ +# \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ +# +# This file was automatically generated by gh-aw (v0.68.3). DO NOT EDIT. +# +# To update this file, edit the corresponding .md file and run: +# gh aw compile +# Not all edits will cause changes to this file. +# +# For more information: https://github.github.com/gh-aw/introduction/overview/ +# +# +# Secrets used: +# - CODEX_API_KEY +# - GH_AW_GITHUB_MCP_SERVER_TOKEN +# - GH_AW_GITHUB_TOKEN +# - GITHUB_TOKEN +# - OPENAI_API_KEY +# +# Custom actions used: +# - actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 +# - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 +# - actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 +# - actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 +# - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 +# - github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 +# +# Container images used: +# - ghcr.io/github/gh-aw-firewall/agent:0.25.20 +# - ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20 +# - ghcr.io/github/gh-aw-firewall/squid:0.25.20 +# - ghcr.io/github/gh-aw-mcpg:v0.2.19 +# - ghcr.io/github/github-mcp-server:v0.32.0 +# - node:lts-alpine + +name: "Issue 自动分类与回复" +"on": + issues: + types: + - opened + - reopened + +permissions: {} + +concurrency: + group: "gh-aw-${{ github.workflow }}-${{ github.event.issue.number || github.run_id }}" + +run-name: "Issue 自动分类与回复" + +jobs: + activation: + needs: pre_activation + if: needs.pre_activation.outputs.activated == 'true' + runs-on: ubuntu-slim + permissions: + actions: read + contents: read + outputs: + body: ${{ steps.sanitized.outputs.body }} + comment_id: "" + comment_repo: "" + lockdown_check_failed: ${{ steps.generate_aw_info.outputs.lockdown_check_failed == 'true' }} + model: ${{ steps.generate_aw_info.outputs.model }} + secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} + setup-trace-id: ${{ steps.setup.outputs.trace-id }} + stale_lock_file_failed: ${{ steps.check-lock-file.outputs.stale_lock_file_failed == 'true' }} + text: ${{ steps.sanitized.outputs.text }} + title: ${{ steps.sanitized.outputs.title }} + steps: + - name: Setup Scripts + id: setup + uses: github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.pre_activation.outputs.setup-trace-id }} + - 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: "gpt-5.4" + GH_AW_INFO_VERSION: "0.118.0" + GH_AW_INFO_AGENT_VERSION: "0.118.0" + GH_AW_INFO_CLI_VERSION: "v0.68.3" + GH_AW_INFO_WORKFLOW_NAME: "Issue 自动分类与回复" + GH_AW_INFO_EXPERIMENTAL: "false" + GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true" + GH_AW_INFO_STAGED: "false" + GH_AW_INFO_ALLOWED_DOMAINS: '["api.zhizengzeng.com"]' + GH_AW_INFO_FIREWALL_ENABLED: "true" + GH_AW_INFO_AWF_VERSION: "v0.25.20" + GH_AW_INFO_AWMG_VERSION: "" + GH_AW_INFO_FIREWALL_TYPE: "squid" + GH_AW_COMPILED_STRICT: "true" + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/generate_aw_info.cjs'); + await main(core, context); + - name: Validate CODEX_API_KEY or OPENAI_API_KEY secret + id: validate-secret + run: bash "${RUNNER_TEMP}/gh-aw/actions/validate_multi_secret.sh" CODEX_API_KEY OPENAI_API_KEY Codex https://github.github.com/gh-aw/reference/engines/#openai-codex + env: + CODEX_API_KEY: ${{ secrets.CODEX_API_KEY }} + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + - name: Checkout .github and .agents folders + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + sparse-checkout: | + .github + .agents + sparse-checkout-cone-mode: true + fetch-depth: 1 + - name: Check workflow lock file + id: check-lock-file + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_WORKFLOW_FILE: "issue-triage.lock.yml" + GH_AW_CONTEXT_WORKFLOW_REF: "${{ github.workflow_ref }}" + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/check_workflow_timestamp_api.cjs'); + await main(); + - name: Check compile-agentic version + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_COMPILED_VERSION: "v0.68.3" + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/check_version_updates.cjs'); + await main(); + - name: Compute current body text + id: sanitized + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/compute_text.cjs'); + await main(); + - name: Create prompt with built-in context + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_SAFE_OUTPUTS: ${{ runner.temp }}/gh-aw/safeoutputs/outputs.jsonl + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} + GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} + # poutine:ignore untrusted_checkout_exec + run: | + bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" + { + cat << 'GH_AW_PROMPT_fbc3aadb8c4cd61c_EOF' + + GH_AW_PROMPT_fbc3aadb8c4cd61c_EOF + cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" + cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" + cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" + cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" + cat << 'GH_AW_PROMPT_fbc3aadb8c4cd61c_EOF' + + Tools: add_comment, add_labels, missing_tool, missing_data, noop + + + The following GitHub context information is available for this workflow: + {{#if __GH_AW_GITHUB_ACTOR__ }} + - **actor**: __GH_AW_GITHUB_ACTOR__ + {{/if}} + {{#if __GH_AW_GITHUB_REPOSITORY__ }} + - **repository**: __GH_AW_GITHUB_REPOSITORY__ + {{/if}} + {{#if __GH_AW_GITHUB_WORKSPACE__ }} + - **workspace**: __GH_AW_GITHUB_WORKSPACE__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ }} + - **issue-number**: #__GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ }} + - **discussion-number**: #__GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ }} + - **pull-request-number**: #__GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_COMMENT_ID__ }} + - **comment-id**: __GH_AW_GITHUB_EVENT_COMMENT_ID__ + {{/if}} + {{#if __GH_AW_GITHUB_RUN_ID__ }} + - **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__ + {{/if}} + + + GH_AW_PROMPT_fbc3aadb8c4cd61c_EOF + cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" + cat << 'GH_AW_PROMPT_fbc3aadb8c4cd61c_EOF' + + {{#runtime-import .github/workflows/issue-triage.md}} + GH_AW_PROMPT_fbc3aadb8c4cd61c_EOF + } > "$GH_AW_PROMPT" + - name: Interpolate variables and render templates + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/interpolate_prompt.cjs'); + await main(); + - name: Substitute placeholders + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} + GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} + GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: ${{ needs.pre_activation.outputs.activated }} + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + + const substitutePlaceholders = require('${{ runner.temp }}/gh-aw/actions/substitute_placeholders.cjs'); + + // Call the substitution function + return await substitutePlaceholders({ + file: process.env.GH_AW_PROMPT, + substitutions: { + GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR, + GH_AW_GITHUB_EVENT_COMMENT_ID: process.env.GH_AW_GITHUB_EVENT_COMMENT_ID, + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: process.env.GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER, + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: process.env.GH_AW_GITHUB_EVENT_ISSUE_NUMBER, + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: process.env.GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER, + GH_AW_GITHUB_REPOSITORY: process.env.GH_AW_GITHUB_REPOSITORY, + GH_AW_GITHUB_RUN_ID: process.env.GH_AW_GITHUB_RUN_ID, + GH_AW_GITHUB_WORKSPACE: process.env.GH_AW_GITHUB_WORKSPACE, + GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: process.env.GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED + } + }); + - name: Validate prompt placeholders + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + # poutine:ignore untrusted_checkout_exec + run: bash "${RUNNER_TEMP}/gh-aw/actions/validate_prompt_placeholders.sh" + - name: Print prompt + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + # poutine:ignore untrusted_checkout_exec + run: bash "${RUNNER_TEMP}/gh-aw/actions/print_prompt_summary.sh" + - name: Upload activation artifact + if: success() + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: activation + path: | + /tmp/gh-aw/aw_info.json + /tmp/gh-aw/aw-prompts/prompt.txt + /tmp/gh-aw/github_rate_limits.jsonl + if-no-files-found: ignore + retention-days: 1 + + agent: + needs: activation + runs-on: ubuntu-latest + permissions: + issues: read + env: + DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + GH_AW_ASSETS_ALLOWED_EXTS: "" + GH_AW_ASSETS_BRANCH: "" + GH_AW_ASSETS_MAX_SIZE_KB: 0 + GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs + GH_AW_WORKFLOW_ID_SANITIZED: issuetriage + outputs: + effective_tokens: ${{ steps.parse-mcp-gateway.outputs.effective_tokens }} + has_patch: ${{ steps.collect_output.outputs.has_patch }} + model: ${{ needs.activation.outputs.model }} + output: ${{ steps.collect_output.outputs.output }} + output_types: ${{ steps.collect_output.outputs.output_types }} + setup-trace-id: ${{ steps.setup.outputs.trace-id }} + steps: + - name: Setup Scripts + id: setup + uses: github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} + - name: Set runtime paths + id: set-runtime-paths + run: | + { + 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: Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + - 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: Configure Git credentials + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + GITHUB_TOKEN: ${{ github.token }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + git config --global am.keepcr true + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Setup Node.js + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 + with: + node-version: '24' + package-manager-cache: false + - name: Install Codex CLI + run: npm install --ignore-scripts -g @openai/codex@0.118.0 + - name: Install AWF binary + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.25.20 + - name: Determine automatic lockdown mode for GitHub MCP Server + id: determine-automatic-lockdown + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} + GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} + with: + script: | + const determineAutomaticLockdown = require('${{ runner.temp }}/gh-aw/actions/determine_automatic_lockdown.cjs'); + await determineAutomaticLockdown(github, context, core); + - name: Download container images + run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.25.20 ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20 ghcr.io/github/gh-aw-firewall/squid:0.25.20 ghcr.io/github/gh-aw-mcpg:v0.2.19 ghcr.io/github/github-mcp-server:v0.32.0 node:lts-alpine + - name: Write Safe Outputs Config + run: | + mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" + mkdir -p /tmp/gh-aw/safeoutputs + mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_5230ac32a09b70bb_EOF' + {"add_comment":{"max":1},"add_labels":{"allowed":["bug","feature","enhancement","documentation","question","duplicate","invalid"]},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} + GH_AW_SAFE_OUTPUTS_CONFIG_5230ac32a09b70bb_EOF + - name: Write Safe Outputs Tools + env: + GH_AW_TOOLS_META_JSON: | + { + "description_suffixes": { + "add_comment": " CONSTRAINTS: Maximum 1 comment(s) can be added. Supports reply_to_id for discussion threading.", + "add_labels": " CONSTRAINTS: Only these labels are allowed: [\"bug\" \"feature\" \"enhancement\" \"documentation\" \"question\" \"duplicate\" \"invalid\"]." + }, + "repo_params": {}, + "dynamic_tools": [] + } + GH_AW_VALIDATION_JSON: | + { + "add_comment": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "item_number": { + "issueOrPRNumber": true + }, + "reply_to_id": { + "type": "string", + "maxLength": 256 + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, + "add_labels": { + "defaultMax": 5, + "fields": { + "item_number": { + "issueNumberOrTemporaryId": true + }, + "labels": { + "required": true, + "type": "array", + "itemType": "string", + "itemSanitize": true, + "itemMaxLength": 128 + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, + "missing_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, + "missing_tool": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 512 + }, + "reason": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "tool": { + "type": "string", + "sanitize": true, + "maxLength": 128 + } + } + }, + "noop": { + "defaultMax": 1, + "fields": { + "message": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + } + } + }, + "report_incomplete": { + "defaultMax": 5, + "fields": { + "details": { + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "reason": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 1024 + } + } + } + } + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/generate_safe_outputs_tools.cjs'); + await main(); + - name: Generate Safe Outputs MCP Server Config + id: safe-outputs-config + run: | + # Generate a secure random API key (360 bits of entropy, 40+ chars) + # Mask immediately to prevent timing vulnerabilities + API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${API_KEY}" + + PORT=3001 + + # Set outputs for next steps + { + echo "safe_outputs_api_key=${API_KEY}" + echo "safe_outputs_port=${PORT}" + } >> "$GITHUB_OUTPUT" + + echo "Safe Outputs MCP server will run on port ${PORT}" + + - name: Start Safe Outputs MCP HTTP Server + id: safe-outputs-start + env: + DEBUG: '*' + GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} + GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-config.outputs.safe_outputs_port }} + GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-config.outputs.safe_outputs_api_key }} + GH_AW_SAFE_OUTPUTS_TOOLS_PATH: ${{ runner.temp }}/gh-aw/safeoutputs/tools.json + GH_AW_SAFE_OUTPUTS_CONFIG_PATH: ${{ runner.temp }}/gh-aw/safeoutputs/config.json + GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs + run: | + # Environment variables are set above to prevent template injection + export DEBUG + export GH_AW_SAFE_OUTPUTS + export GH_AW_SAFE_OUTPUTS_PORT + export GH_AW_SAFE_OUTPUTS_API_KEY + export GH_AW_SAFE_OUTPUTS_TOOLS_PATH + export GH_AW_SAFE_OUTPUTS_CONFIG_PATH + export GH_AW_MCP_LOG_DIR + + bash "${RUNNER_TEMP}/gh-aw/actions/start_safe_outputs_server.sh" + + - name: Start MCP Gateway + id: start-mcp-gateway + env: + GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} + GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-start.outputs.api_key }} + GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-start.outputs.port }} + GITHUB_MCP_GUARD_MIN_INTEGRITY: ${{ steps.determine-automatic-lockdown.outputs.min_integrity }} + GITHUB_MCP_GUARD_REPOS: ${{ steps.determine-automatic-lockdown.outputs.repos }} + GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + run: | + set -eo pipefail + mkdir -p /tmp/gh-aw/mcp-config + + # Export gateway environment variables for MCP config and gateway script + export MCP_GATEWAY_PORT="80" + export MCP_GATEWAY_DOMAIN="host.docker.internal" + MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${MCP_GATEWAY_API_KEY}" + export MCP_GATEWAY_API_KEY + export MCP_GATEWAY_PAYLOAD_DIR="/tmp/gh-aw/mcp-payloads" + mkdir -p "${MCP_GATEWAY_PAYLOAD_DIR}" + export MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD="524288" + export DEBUG="*" + + export GH_AW_ENGINE="codex" + export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.2.19' + + cat > /tmp/gh-aw/mcp-config/config.toml << GH_AW_MCP_CONFIG_b40fbf99f5f15c9e_EOF + [history] + persistence = "none" + + [shell_environment_policy] + inherit = "core" + include_only = ["CODEX_API_KEY", "GH_AW_ASSETS_ALLOWED_EXTS", "GH_AW_ASSETS_BRANCH", "GH_AW_ASSETS_MAX_SIZE_KB", "GH_AW_SAFE_OUTPUTS", "GITHUB_PERSONAL_ACCESS_TOKEN", "GITHUB_REPOSITORY", "GITHUB_SERVER_URL", "HOME", "OPENAI_API_KEY", "PATH"] + + [mcp_servers.github] + user_agent = "issue" + startup_timeout_sec = 120 + tool_timeout_sec = 60 + container = "ghcr.io/github/github-mcp-server:v0.32.0" + env = { "GITHUB_HOST" = "$GITHUB_SERVER_URL", "GITHUB_PERSONAL_ACCESS_TOKEN" = "$GH_AW_GITHUB_TOKEN", "GITHUB_READ_ONLY" = "1", "GITHUB_TOOLSETS" = "context,repos,issues,pull_requests" } + env_vars = ["GITHUB_HOST", "GITHUB_PERSONAL_ACCESS_TOKEN", "GITHUB_READ_ONLY", "GITHUB_TOOLSETS"] + + [mcp_servers.safeoutputs] + type = "http" + url = "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT" + + [mcp_servers.safeoutputs.headers] + Authorization = "$GH_AW_SAFE_OUTPUTS_API_KEY" + + [mcp_servers.safeoutputs."guard-policies"] + + [mcp_servers.safeoutputs."guard-policies".write-sink] + accept = ["*"] + GH_AW_MCP_CONFIG_b40fbf99f5f15c9e_EOF + + # Generate JSON config for MCP gateway + cat << GH_AW_MCP_CONFIG_b40fbf99f5f15c9e_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" + { + "mcpServers": { + "github": { + "container": "ghcr.io/github/github-mcp-server:v0.32.0", + "env": { + "GITHUB_HOST": "$GITHUB_SERVER_URL", + "GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_MCP_SERVER_TOKEN", + "GITHUB_READ_ONLY": "1", + "GITHUB_TOOLSETS": "context,repos,issues,pull_requests" + }, + "guard-policies": { + "allow-only": { + "min-integrity": "$GITHUB_MCP_GUARD_MIN_INTEGRITY", + "repos": "$GITHUB_MCP_GUARD_REPOS" + } + } + }, + "safeoutputs": { + "type": "http", + "url": "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT", + "headers": { + "Authorization": "$GH_AW_SAFE_OUTPUTS_API_KEY" + }, + "guard-policies": { + "write-sink": { + "accept": [ + "*" + ] + } + } + } + }, + "gateway": { + "port": $MCP_GATEWAY_PORT, + "domain": "${MCP_GATEWAY_DOMAIN}", + "apiKey": "${MCP_GATEWAY_API_KEY}", + "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" + } + } + GH_AW_MCP_CONFIG_b40fbf99f5f15c9e_EOF + - name: Download activation artifact + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: activation + path: /tmp/gh-aw + - name: Clean git credentials + continue-on-error: true + run: bash "${RUNNER_TEMP}/gh-aw/actions/clean_git_credentials.sh" + - name: Execute Codex CLI + id: agentic_execution + run: | + set -o pipefail + mkdir -p "$CODEX_HOME/logs" && touch /tmp/gh-aw/agent-step-summary.md + (umask 177 && touch /tmp/gh-aw/agent-stdio.log) + # shellcheck disable=SC1003 + sudo -E awf --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" --env-all --exclude-env CODEX_API_KEY --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --exclude-env OPENAI_API_KEY --allow-domains 172.30.0.1,api.openai.com,api.zhizengzeng.com,host.docker.internal,openai.com --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --image-tag 0.25.20 --skip-pull --enable-api-proxy --openai-api-target api.zhizengzeng.com --openai-api-base-path /v1 \ + -- /bin/bash -c 'export PATH="$(find /opt/hostedtoolcache -maxdepth 4 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true && INSTRUCTION="$(cat /tmp/gh-aw/aw-prompts/prompt.txt)" && codex ${GH_AW_MODEL_AGENT_CODEX:+-c model="$GH_AW_MODEL_AGENT_CODEX" }exec -c web_search="disabled" -c fetch="disabled" --dangerously-bypass-approvals-and-sandbox --skip-git-repo-check "$INSTRUCTION"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + env: + CODEX_API_KEY: ${{ secrets.CODEX_API_KEY || secrets.OPENAI_API_KEY }} + CODEX_HOME: /tmp/gh-aw/mcp-config + GH_AW_MCP_CONFIG: /tmp/gh-aw/mcp-config/config.toml + GH_AW_MODEL_AGENT_CODEX: gpt-5.4 + 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: v0.68.3 + GITHUB_AW: true + GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md + GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com + GIT_AUTHOR_NAME: github-actions[bot] + GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com + GIT_COMMITTER_NAME: github-actions[bot] + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + OPENAI_BASE_URL: https://api.zhizengzeng.com/v1 + RUST_LOG: trace,hyper_util=info,mio=info,reqwest=info,os_info=info,codex_otel=warn,codex_core=debug,ocodex_exec=debug + - name: Configure Git credentials + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + GITHUB_TOKEN: ${{ github.token }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + git config --global am.keepcr true + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Stop MCP Gateway + if: always() + continue-on-error: true + env: + MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }} + MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }} + GATEWAY_PID: ${{ steps.start-mcp-gateway.outputs.gateway-pid }} + run: | + bash "${RUNNER_TEMP}/gh-aw/actions/stop_mcp_gateway.sh" "$GATEWAY_PID" + - name: Redact secrets in logs + if: always() + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/redact_secrets.cjs'); + await main(); + env: + GH_AW_SECRET_NAMES: 'CODEX_API_KEY,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN,OPENAI_API_KEY' + SECRET_CODEX_API_KEY: ${{ secrets.CODEX_API_KEY }} + SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} + SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} + SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SECRET_OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + - name: Append agent step summary + if: always() + run: bash "${RUNNER_TEMP}/gh-aw/actions/append_agent_step_summary.sh" + - name: Copy Safe Outputs + if: always() + env: + GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} + run: | + mkdir -p /tmp/gh-aw + cp "$GH_AW_SAFE_OUTPUTS" /tmp/gh-aw/safeoutputs.jsonl 2>/dev/null || true + - name: Ingest agent output + id: collect_output + if: always() + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} + GH_AW_ALLOWED_DOMAINS: "172.30.0.1,api.openai.com,api.zhizengzeng.com,host.docker.internal,openai.com" + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_API_URL: ${{ github.api_url }} + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/collect_ndjson_output.cjs'); + await main(); + - name: Parse agent logs for step summary + if: always() + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_AGENT_OUTPUT: /tmp/gh-aw/agent-stdio.log + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_codex_log.cjs'); + await main(); + - name: Parse MCP Gateway logs for step summary + if: always() + id: parse-mcp-gateway + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_mcp_gateway_log.cjs'); + await main(); + - name: Print firewall logs + if: always() + continue-on-error: true + env: + AWF_LOGS_DIR: /tmp/gh-aw/sandbox/firewall/logs + run: | + # Fix permissions on firewall logs so they can be uploaded as artifacts + # AWF runs with sudo, creating files owned by root + sudo chmod -R a+r /tmp/gh-aw/sandbox/firewall/logs 2>/dev/null || true + # Only run awf logs summary if awf command exists (it may not be installed if workflow failed before install step) + if command -v awf &> /dev/null; then + awf logs summary | tee -a "$GITHUB_STEP_SUMMARY" + else + echo 'AWF binary not installed, skipping firewall log summary' + fi + - name: Parse token usage for step summary + if: always() + continue-on-error: true + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_token_usage.cjs'); + await main(); + - 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: Upload agent artifacts + if: always() + continue-on-error: true + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: agent + path: | + /tmp/gh-aw/aw-prompts/prompt.txt + /tmp/gh-aw/mcp-config/logs/ + /tmp/gh-aw/redacted-urls.log + /tmp/gh-aw/mcp-logs/ + /tmp/gh-aw/agent_usage.json + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/agent/ + /tmp/gh-aw/github_rate_limits.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/sandbox/firewall/logs/ + /tmp/gh-aw/sandbox/firewall/audit/ + if-no-files-found: ignore + + conclusion: + needs: + - activation + - agent + - detection + - safe_outputs + if: > + always() && (needs.agent.result != 'skipped' || needs.activation.outputs.lockdown_check_failed == 'true' || + needs.activation.outputs.stale_lock_file_failed == 'true') + runs-on: ubuntu-slim + permissions: + contents: read + discussions: write + issues: write + pull-requests: write + concurrency: + group: "gh-aw-conclusion-issue-triage" + cancel-in-progress: false + outputs: + incomplete_count: ${{ steps.report_incomplete.outputs.incomplete_count }} + noop_message: ${{ steps.noop.outputs.noop_message }} + tools_reported: ${{ steps.missing_tool.outputs.tools_reported }} + total_count: ${{ steps.missing_tool.outputs.total_count }} + steps: + - name: Setup Scripts + id: setup + uses: github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} + - name: Download agent output artifact + id: download-agent-output + continue-on-error: true + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: agent + path: /tmp/gh-aw/ + - name: Setup agent output environment variable + id: setup-agent-output-env + if: steps.download-agent-output.outcome == 'success' + run: | + mkdir -p /tmp/gh-aw/ + find "/tmp/gh-aw/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT" + - name: Process no-op messages + id: noop + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} + GH_AW_NOOP_MAX: "1" + GH_AW_WORKFLOW_NAME: "Issue 自动分类与回复" + GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} + GH_AW_NOOP_REPORT_AS_ISSUE: "true" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_noop_message.cjs'); + await main(); + - name: Log detection run + id: detection_runs + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Issue 自动分类与回复" + 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 { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_detection_runs.cjs'); + await main(); + - name: Record missing tool + id: missing_tool + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + 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: "Issue 自动分类与回复" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/missing_tool.cjs'); + await main(); + - name: Record incomplete + id: report_incomplete + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + 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: "Issue 自动分类与回复" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/report_incomplete_handler.cjs'); + await main(); + - name: Handle agent failure + id: handle_agent_failure + if: always() + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Issue 自动分类与回复" + 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: "issue-triage" + GH_AW_ENGINE_ID: "codex" + GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.activation.outputs.secret_verification_result }} + GH_AW_LOCKDOWN_CHECK_FAILED: ${{ needs.activation.outputs.lockdown_check_failed }} + GH_AW_STALE_LOCK_FILE_FAILED: ${{ needs.activation.outputs.stale_lock_file_failed }} + GH_AW_GROUP_REPORTS: "false" + GH_AW_FAILURE_REPORT_AS_ISSUE: "true" + GH_AW_TIMEOUT_MINUTES: "20" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_agent_failure.cjs'); + await main(); + + detection: + needs: + - activation + - agent + if: > + always() && needs.agent.result != 'skipped' && (needs.agent.outputs.output_types != '' || needs.agent.outputs.has_patch == 'true') + runs-on: ubuntu-latest + permissions: + contents: read + outputs: + detection_conclusion: ${{ steps.detection_conclusion.outputs.conclusion }} + detection_reason: ${{ steps.detection_conclusion.outputs.reason }} + detection_success: ${{ steps.detection_conclusion.outputs.success }} + steps: + - name: Setup Scripts + id: setup + uses: github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} + - name: Download agent output artifact + id: download-agent-output + continue-on-error: true + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: agent + path: /tmp/gh-aw/ + - name: Setup agent output environment variable + id: setup-agent-output-env + if: steps.download-agent-output.outcome == 'success' + run: | + mkdir -p /tmp/gh-aw/ + find "/tmp/gh-aw/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT" + - name: Checkout repository for patch context + if: needs.agent.outputs.has_patch == 'true' + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + # --- Threat Detection --- + - name: 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.25.20 ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20 ghcr.io/github/gh-aw-firewall/squid:0.25.20 + - name: Check if detection needed + id: detection_guard + if: always() + env: + OUTPUT_TYPES: ${{ needs.agent.outputs.output_types }} + HAS_PATCH: ${{ needs.agent.outputs.has_patch }} + run: | + if [[ -n "$OUTPUT_TYPES" || "$HAS_PATCH" == "true" ]]; then + echo "run_detection=true" >> "$GITHUB_OUTPUT" + echo "Detection will run: output_types=$OUTPUT_TYPES, has_patch=$HAS_PATCH" + else + echo "run_detection=false" >> "$GITHUB_OUTPUT" + echo "Detection skipped: no agent outputs or patches to analyze" + fi + - name: Clear MCP configuration for detection + if: always() && steps.detection_guard.outputs.run_detection == 'true' + run: | + rm -f /tmp/gh-aw/mcp-config/mcp-servers.json + rm -f /home/runner/.copilot/mcp-config.json + rm -f "$GITHUB_WORKSPACE/.gemini/settings.json" + - name: Prepare threat detection files + if: always() && steps.detection_guard.outputs.run_detection == 'true' + run: | + mkdir -p /tmp/gh-aw/threat-detection/aw-prompts + cp /tmp/gh-aw/aw-prompts/prompt.txt /tmp/gh-aw/threat-detection/aw-prompts/prompt.txt 2>/dev/null || true + cp /tmp/gh-aw/agent_output.json /tmp/gh-aw/threat-detection/agent_output.json 2>/dev/null || true + for f in /tmp/gh-aw/aw-*.patch; do + [ -f "$f" ] && cp "$f" /tmp/gh-aw/threat-detection/ 2>/dev/null || true + done + for f in /tmp/gh-aw/aw-*.bundle; do + [ -f "$f" ] && cp "$f" /tmp/gh-aw/threat-detection/ 2>/dev/null || true + done + echo "Prepared threat detection files:" + ls -la /tmp/gh-aw/threat-detection/ 2>/dev/null || true + - name: Setup threat detection + if: always() && steps.detection_guard.outputs.run_detection == 'true' + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + WORKFLOW_NAME: "Issue 自动分类与回复" + WORKFLOW_DESCRIPTION: "No description provided" + HAS_PATCH: ${{ needs.agent.outputs.has_patch }} + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/setup_threat_detection.cjs'); + await main(); + - name: Ensure threat-detection directory and log + if: always() && steps.detection_guard.outputs.run_detection == 'true' + run: | + mkdir -p /tmp/gh-aw/threat-detection + touch /tmp/gh-aw/threat-detection/detection.log + - name: Setup Node.js + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 + with: + node-version: '24' + package-manager-cache: false + - name: Install Codex CLI + run: npm install --ignore-scripts -g @openai/codex@0.118.0 + - name: Install AWF binary + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.25.20 + - name: Execute Codex CLI + if: always() && steps.detection_guard.outputs.run_detection == 'true' + id: detection_agentic_execution + run: | + set -o pipefail + mkdir -p "$CODEX_HOME/logs" && touch /tmp/gh-aw/agent-step-summary.md + (umask 177 && touch /tmp/gh-aw/threat-detection/detection.log) + # shellcheck disable=SC1003 + sudo -E awf --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" --env-all --exclude-env CODEX_API_KEY --exclude-env OPENAI_API_KEY --allow-domains 172.30.0.1,api.openai.com,host.docker.internal,openai.com --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --image-tag 0.25.20 --skip-pull --enable-api-proxy --openai-api-target api.zhizengzeng.com --openai-api-base-path /v1 \ + -- /bin/bash -c 'export PATH="$(find /opt/hostedtoolcache -maxdepth 4 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true && INSTRUCTION="$(cat /tmp/gh-aw/aw-prompts/prompt.txt)" && codex ${GH_AW_MODEL_DETECTION_CODEX:+-c model="$GH_AW_MODEL_DETECTION_CODEX" }exec -c web_search="disabled" -c fetch="disabled" --dangerously-bypass-approvals-and-sandbox --skip-git-repo-check "$INSTRUCTION"' 2>&1 | tee -a /tmp/gh-aw/threat-detection/detection.log + env: + CODEX_API_KEY: ${{ secrets.CODEX_API_KEY || secrets.OPENAI_API_KEY }} + CODEX_HOME: /tmp/gh-aw/mcp-config + GH_AW_MCP_CONFIG: /tmp/gh-aw/mcp-config/config.toml + GH_AW_MODEL_DETECTION_CODEX: gpt-5.4 + GH_AW_PHASE: detection + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_VERSION: v0.68.3 + GITHUB_AW: true + GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md + GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com + GIT_AUTHOR_NAME: github-actions[bot] + GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com + GIT_COMMITTER_NAME: github-actions[bot] + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + OPENAI_BASE_URL: https://api.zhizengzeng.com/v1 + RUST_LOG: trace,hyper_util=info,mio=info,reqwest=info,os_info=info,codex_otel=warn,codex_core=debug,ocodex_exec=debug + - name: Upload threat detection log + if: always() && steps.detection_guard.outputs.run_detection == 'true' + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: detection + path: /tmp/gh-aw/threat-detection/detection.log + if-no-files-found: ignore + - name: Parse and conclude threat detection + id: detection_conclusion + if: always() + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + RUN_DETECTION: ${{ steps.detection_guard.outputs.run_detection }} + GH_AW_DETECTION_CONTINUE_ON_ERROR: "true" + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_threat_detection_results.cjs'); + await main(); + + pre_activation: + runs-on: ubuntu-slim + outputs: + activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} + matched_command: '' + setup-trace-id: ${{ steps.setup.outputs.trace-id }} + steps: + - name: Setup Scripts + id: setup + uses: github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + - name: Check team membership for workflow + id: check_membership + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_REQUIRED_ROLES: "admin,maintainer,write" + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/check_membership.cjs'); + await main(); + + safe_outputs: + needs: + - activation + - agent + - detection + if: (!cancelled()) && needs.agent.result != 'skipped' && needs.detection.result == 'success' + runs-on: ubuntu-slim + permissions: + contents: read + discussions: write + issues: write + pull-requests: write + timeout-minutes: 15 + env: + GH_AW_CALLER_WORKFLOW_ID: "${{ github.repository }}/issue-triage" + GH_AW_DETECTION_CONCLUSION: ${{ needs.detection.outputs.detection_conclusion }} + GH_AW_DETECTION_REASON: ${{ needs.detection.outputs.detection_reason }} + GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens }} + GH_AW_ENGINE_ID: "codex" + GH_AW_ENGINE_MODEL: "gpt-5.4" + GH_AW_WORKFLOW_ID: "issue-triage" + GH_AW_WORKFLOW_NAME: "Issue 自动分类与回复" + outputs: + code_push_failure_count: ${{ steps.process_safe_outputs.outputs.code_push_failure_count }} + code_push_failure_errors: ${{ steps.process_safe_outputs.outputs.code_push_failure_errors }} + comment_id: ${{ steps.process_safe_outputs.outputs.comment_id }} + comment_url: ${{ steps.process_safe_outputs.outputs.comment_url }} + create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }} + create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }} + process_safe_outputs_processed_count: ${{ steps.process_safe_outputs.outputs.processed_count }} + process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }} + steps: + - name: Setup Scripts + id: setup + uses: github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} + - name: Download agent output artifact + id: download-agent-output + continue-on-error: true + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: agent + path: /tmp/gh-aw/ + - name: Setup agent output environment variable + id: setup-agent-output-env + if: steps.download-agent-output.outcome == 'success' + run: | + mkdir -p /tmp/gh-aw/ + find "/tmp/gh-aw/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT" + - name: Configure GH_HOST for enterprise compatibility + id: ghes-host-config + shell: bash + run: | + # Derive GH_HOST from GITHUB_SERVER_URL so the gh CLI targets the correct + # GitHub instance (GHES/GHEC). On github.com this is a harmless no-op. + GH_HOST="${GITHUB_SERVER_URL#https://}" + GH_HOST="${GH_HOST#http://}" + echo "GH_HOST=${GH_HOST}" >> "$GITHUB_ENV" + - name: Process Safe Outputs + id: process_safe_outputs + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} + GH_AW_ALLOWED_DOMAINS: "172.30.0.1,api.openai.com,api.zhizengzeng.com,host.docker.internal,openai.com" + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_API_URL: ${{ github.api_url }} + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":1},\"add_labels\":{\"allowed\":[\"bug\",\"feature\",\"enhancement\",\"documentation\",\"question\",\"duplicate\",\"invalid\"]},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"report_incomplete\":{}}" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/safe_output_handler_manager.cjs'); + await main(); + - name: Upload Safe Outputs Items + if: always() + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: safe-outputs-items + path: | + /tmp/gh-aw/safe-output-items.jsonl + /tmp/gh-aw/temporary-id-map.json + if-no-files-found: ignore + diff --git a/.github/workflows/issue-triage.md b/.github/workflows/issue-triage.md new file mode 100644 index 00000000..47db7e75 --- /dev/null +++ b/.github/workflows/issue-triage.md @@ -0,0 +1,55 @@ +--- +on: + issues: + types: [opened, reopened] + +engine: + id: codex + model: gpt-5.4 + env: + OPENAI_BASE_URL: "https://api.zhizengzeng.com/v1" + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + +network: + allowed: + - api.zhizengzeng.com + +permissions: + issues: read + +safe-outputs: + add-comment: + max: 1 + add-labels: + allowed: + - bug + - feature + - enhancement + - documentation + - question + - duplicate + - invalid +--- + +# Issue 自动分类与回复 + +分析仓库 ${{ github.repository }} 中新开的 Issue。 + +## 任务 + +1. 阅读 Issue 的标题和正文 +2. 判断类型,添加合适的标签: + - `bug`:程序出错、功能异常 + - `feature`:新功能请求 + - `enhancement`:改进现有功能 + - `documentation`:文档问题 + - `question`:使用疑问 + - `duplicate`:与已有 Issue 重复 + - `invalid`:信息不完整或无效 + +3. 用中文回复一条友好的评论,包含: + - 感谢用户提交 Issue + - 说明你打的标签和原因 + - 如果是 bug,请用户补充:复现步骤、环境信息、错误日志 + - 如果是 question,尝试根据仓库代码给出初步解答 + - 预计处理时间(普通问题 3 个工作日内) \ No newline at end of file From 59f74efd90e55ad5038555ca56658a6abfc63bd2 Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Mon, 27 Apr 2026 14:34:09 +0800 Subject: [PATCH 03/59] fix: update model name --- .github/workflows/issue-triage.lock.yml | 34 ++++++++++++------------- .github/workflows/issue-triage.md | 2 +- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/workflows/issue-triage.lock.yml b/.github/workflows/issue-triage.lock.yml index b33c321d..18ab2d69 100644 --- a/.github/workflows/issue-triage.lock.yml +++ b/.github/workflows/issue-triage.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"5bb61465040f50022c019312920d003bccae1eb18d272aebf623ab2ca0a81b4c","compiler_version":"v0.68.3","strict":true,"agent_id":"codex","agent_model":"gpt-5.4"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"0b5f1deb08909e468f8983e4e0a08e560904debd3af5596dd98d99c463e6b16b","compiler_version":"v0.68.3","strict":true,"agent_id":"codex","agent_model":"gpt-5.3"} # gh-aw-manifest: {"version":1,"secrets":["CODEX_API_KEY","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/setup-node","sha":"53b83947a5a98c8d113130e565377fae1a50d02f","version":"v6.3.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"ba90f2186d7ad780ec640f364005fa24e797b360","version":"v0.68.3"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.20"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.2.19"},{"image":"ghcr.io/github/github-mcp-server:v0.32.0"},{"image":"node:lts-alpine"}]} # ___ _ _ # / _ \ | | (_) @@ -92,7 +92,7 @@ jobs: env: GH_AW_INFO_ENGINE_ID: "codex" GH_AW_INFO_ENGINE_NAME: "Codex" - GH_AW_INFO_MODEL: "gpt-5.4" + GH_AW_INFO_MODEL: "gpt-5.3" GH_AW_INFO_VERSION: "0.118.0" GH_AW_INFO_AGENT_VERSION: "0.118.0" GH_AW_INFO_CLI_VERSION: "v0.68.3" @@ -175,14 +175,14 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_fbc3aadb8c4cd61c_EOF' + cat << 'GH_AW_PROMPT_0b6277bd1b564cfa_EOF' - GH_AW_PROMPT_fbc3aadb8c4cd61c_EOF + GH_AW_PROMPT_0b6277bd1b564cfa_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_fbc3aadb8c4cd61c_EOF' + cat << 'GH_AW_PROMPT_0b6277bd1b564cfa_EOF' Tools: add_comment, add_labels, missing_tool, missing_data, noop @@ -214,12 +214,12 @@ jobs: {{/if}} - GH_AW_PROMPT_fbc3aadb8c4cd61c_EOF + GH_AW_PROMPT_0b6277bd1b564cfa_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_fbc3aadb8c4cd61c_EOF' + cat << 'GH_AW_PROMPT_0b6277bd1b564cfa_EOF' {{#runtime-import .github/workflows/issue-triage.md}} - GH_AW_PROMPT_fbc3aadb8c4cd61c_EOF + GH_AW_PROMPT_0b6277bd1b564cfa_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 @@ -373,9 +373,9 @@ jobs: mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs - cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_5230ac32a09b70bb_EOF' + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_c48a16ad381955ee_EOF' {"add_comment":{"max":1},"add_labels":{"allowed":["bug","feature","enhancement","documentation","question","duplicate","invalid"]},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} - GH_AW_SAFE_OUTPUTS_CONFIG_5230ac32a09b70bb_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_c48a16ad381955ee_EOF - name: Write Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -578,7 +578,7 @@ jobs: export GH_AW_ENGINE="codex" export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.2.19' - cat > /tmp/gh-aw/mcp-config/config.toml << GH_AW_MCP_CONFIG_b40fbf99f5f15c9e_EOF + cat > /tmp/gh-aw/mcp-config/config.toml << GH_AW_MCP_CONFIG_1c3fd8845aaab39f_EOF [history] persistence = "none" @@ -605,10 +605,10 @@ jobs: [mcp_servers.safeoutputs."guard-policies".write-sink] accept = ["*"] - GH_AW_MCP_CONFIG_b40fbf99f5f15c9e_EOF + GH_AW_MCP_CONFIG_1c3fd8845aaab39f_EOF # Generate JSON config for MCP gateway - cat << GH_AW_MCP_CONFIG_b40fbf99f5f15c9e_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" + cat << GH_AW_MCP_CONFIG_1c3fd8845aaab39f_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" { "mcpServers": { "github": { @@ -648,7 +648,7 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_b40fbf99f5f15c9e_EOF + GH_AW_MCP_CONFIG_1c3fd8845aaab39f_EOF - name: Download activation artifact uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: @@ -670,7 +670,7 @@ jobs: CODEX_API_KEY: ${{ secrets.CODEX_API_KEY || secrets.OPENAI_API_KEY }} CODEX_HOME: /tmp/gh-aw/mcp-config GH_AW_MCP_CONFIG: /tmp/gh-aw/mcp-config/config.toml - GH_AW_MODEL_AGENT_CODEX: gpt-5.4 + GH_AW_MODEL_AGENT_CODEX: gpt-5.3 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 }} @@ -1075,7 +1075,7 @@ jobs: CODEX_API_KEY: ${{ secrets.CODEX_API_KEY || secrets.OPENAI_API_KEY }} CODEX_HOME: /tmp/gh-aw/mcp-config GH_AW_MCP_CONFIG: /tmp/gh-aw/mcp-config/config.toml - GH_AW_MODEL_DETECTION_CODEX: gpt-5.4 + GH_AW_MODEL_DETECTION_CODEX: gpt-5.3 GH_AW_PHASE: detection GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_VERSION: v0.68.3 @@ -1154,7 +1154,7 @@ jobs: GH_AW_DETECTION_REASON: ${{ needs.detection.outputs.detection_reason }} GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens }} GH_AW_ENGINE_ID: "codex" - GH_AW_ENGINE_MODEL: "gpt-5.4" + GH_AW_ENGINE_MODEL: "gpt-5.3" GH_AW_WORKFLOW_ID: "issue-triage" GH_AW_WORKFLOW_NAME: "Issue 自动分类与回复" outputs: diff --git a/.github/workflows/issue-triage.md b/.github/workflows/issue-triage.md index 47db7e75..1ba52697 100644 --- a/.github/workflows/issue-triage.md +++ b/.github/workflows/issue-triage.md @@ -5,7 +5,7 @@ on: engine: id: codex - model: gpt-5.4 + model: gpt-5.3 env: OPENAI_BASE_URL: "https://api.zhizengzeng.com/v1" OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} From 51d7a2bfb6c6e26ef9a655e646593c828d8a9c0a Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Mon, 27 Apr 2026 16:15:21 +0800 Subject: [PATCH 04/59] fix: disable sandbox to use custom API endpoint --- .github/workflows/issue-triage.lock.yml | 276 +++--------------------- .github/workflows/issue-triage.md | 7 +- 2 files changed, 36 insertions(+), 247 deletions(-) diff --git a/.github/workflows/issue-triage.lock.yml b/.github/workflows/issue-triage.lock.yml index 18ab2d69..d43803a7 100644 --- a/.github/workflows/issue-triage.lock.yml +++ b/.github/workflows/issue-triage.lock.yml @@ -1,5 +1,5 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"0b5f1deb08909e468f8983e4e0a08e560904debd3af5596dd98d99c463e6b16b","compiler_version":"v0.68.3","strict":true,"agent_id":"codex","agent_model":"gpt-5.3"} -# gh-aw-manifest: {"version":1,"secrets":["CODEX_API_KEY","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/setup-node","sha":"53b83947a5a98c8d113130e565377fae1a50d02f","version":"v6.3.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"ba90f2186d7ad780ec640f364005fa24e797b360","version":"v0.68.3"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.20"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.2.19"},{"image":"ghcr.io/github/github-mcp-server:v0.32.0"},{"image":"node:lts-alpine"}]} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"3490689ea862dba5da342751a4e24dfea74a8367df0700a9cf323ff6f4b87f60","compiler_version":"v0.68.3","agent_id":"codex","agent_model":"gpt-5.3-codex"} +# gh-aw-manifest: {"version":1,"secrets":["CODEX_API_KEY","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/setup-node","sha":"53b83947a5a98c8d113130e565377fae1a50d02f","version":"v6.3.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"ba90f2186d7ad780ec640f364005fa24e797b360","version":"v0.68.3"}],"containers":[{"image":"ghcr.io/github/github-mcp-server:v0.32.0"},{"image":"node:lts-alpine"}]} # ___ _ _ # / _ \ | | (_) # | |_| | __ _ ___ _ __ | |_ _ ___ @@ -39,10 +39,6 @@ # - github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 # # Container images used: -# - ghcr.io/github/gh-aw-firewall/agent:0.25.20 -# - ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20 -# - ghcr.io/github/gh-aw-firewall/squid:0.25.20 -# - ghcr.io/github/gh-aw-mcpg:v0.2.19 # - ghcr.io/github/github-mcp-server:v0.32.0 # - node:lts-alpine @@ -92,7 +88,7 @@ jobs: env: GH_AW_INFO_ENGINE_ID: "codex" GH_AW_INFO_ENGINE_NAME: "Codex" - GH_AW_INFO_MODEL: "gpt-5.3" + GH_AW_INFO_MODEL: "gpt-5.3-codex" GH_AW_INFO_VERSION: "0.118.0" GH_AW_INFO_AGENT_VERSION: "0.118.0" GH_AW_INFO_CLI_VERSION: "v0.68.3" @@ -101,11 +97,11 @@ jobs: GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true" GH_AW_INFO_STAGED: "false" GH_AW_INFO_ALLOWED_DOMAINS: '["api.zhizengzeng.com"]' - GH_AW_INFO_FIREWALL_ENABLED: "true" - GH_AW_INFO_AWF_VERSION: "v0.25.20" + GH_AW_INFO_FIREWALL_ENABLED: "false" + GH_AW_INFO_AWF_VERSION: "" GH_AW_INFO_AWMG_VERSION: "" - GH_AW_INFO_FIREWALL_TYPE: "squid" - GH_AW_COMPILED_STRICT: "true" + GH_AW_INFO_FIREWALL_TYPE: "" + GH_AW_COMPILED_STRICT: "false" uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 with: script: | @@ -175,14 +171,14 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_0b6277bd1b564cfa_EOF' + cat << 'GH_AW_PROMPT_32cb1af60213c743_EOF' - GH_AW_PROMPT_0b6277bd1b564cfa_EOF + GH_AW_PROMPT_32cb1af60213c743_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_0b6277bd1b564cfa_EOF' + cat << 'GH_AW_PROMPT_32cb1af60213c743_EOF' Tools: add_comment, add_labels, missing_tool, missing_data, noop @@ -214,12 +210,12 @@ jobs: {{/if}} - GH_AW_PROMPT_0b6277bd1b564cfa_EOF + GH_AW_PROMPT_32cb1af60213c743_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_0b6277bd1b564cfa_EOF' + cat << 'GH_AW_PROMPT_32cb1af60213c743_EOF' {{#runtime-import .github/workflows/issue-triage.md}} - GH_AW_PROMPT_0b6277bd1b564cfa_EOF + GH_AW_PROMPT_32cb1af60213c743_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 @@ -354,8 +350,6 @@ jobs: package-manager-cache: false - name: Install Codex CLI run: npm install --ignore-scripts -g @openai/codex@0.118.0 - - name: Install AWF binary - run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.25.20 - name: Determine automatic lockdown mode for GitHub MCP Server id: determine-automatic-lockdown uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 @@ -367,15 +361,15 @@ jobs: const determineAutomaticLockdown = require('${{ runner.temp }}/gh-aw/actions/determine_automatic_lockdown.cjs'); await determineAutomaticLockdown(github, context, core); - name: Download container images - run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.25.20 ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20 ghcr.io/github/gh-aw-firewall/squid:0.25.20 ghcr.io/github/gh-aw-mcpg:v0.2.19 ghcr.io/github/github-mcp-server:v0.32.0 node:lts-alpine + run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/github-mcp-server:v0.32.0 node:lts-alpine - name: Write Safe Outputs Config run: | mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs - cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_c48a16ad381955ee_EOF' + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_a5c4c11137a888d8_EOF' {"add_comment":{"max":1},"add_labels":{"allowed":["bug","feature","enhancement","documentation","question","duplicate","invalid"]},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} - GH_AW_SAFE_OUTPUTS_CONFIG_c48a16ad381955ee_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_a5c4c11137a888d8_EOF - name: Write Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -566,7 +560,7 @@ jobs: # Export gateway environment variables for MCP config and gateway script export MCP_GATEWAY_PORT="80" - export MCP_GATEWAY_DOMAIN="host.docker.internal" + export MCP_GATEWAY_DOMAIN="localhost" MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=') echo "::add-mask::${MCP_GATEWAY_API_KEY}" export MCP_GATEWAY_API_KEY @@ -578,7 +572,7 @@ jobs: export GH_AW_ENGINE="codex" export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.2.19' - cat > /tmp/gh-aw/mcp-config/config.toml << GH_AW_MCP_CONFIG_1c3fd8845aaab39f_EOF + cat > /tmp/gh-aw/mcp-config/config.toml << GH_AW_MCP_CONFIG_7ab0b468f68178ce_EOF [history] persistence = "none" @@ -596,7 +590,7 @@ jobs: [mcp_servers.safeoutputs] type = "http" - url = "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT" + url = "http://localhost:$GH_AW_SAFE_OUTPUTS_PORT" [mcp_servers.safeoutputs.headers] Authorization = "$GH_AW_SAFE_OUTPUTS_API_KEY" @@ -605,10 +599,10 @@ jobs: [mcp_servers.safeoutputs."guard-policies".write-sink] accept = ["*"] - GH_AW_MCP_CONFIG_1c3fd8845aaab39f_EOF + GH_AW_MCP_CONFIG_7ab0b468f68178ce_EOF # Generate JSON config for MCP gateway - cat << GH_AW_MCP_CONFIG_1c3fd8845aaab39f_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" + cat << GH_AW_MCP_CONFIG_7ab0b468f68178ce_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" { "mcpServers": { "github": { @@ -628,7 +622,7 @@ jobs: }, "safeoutputs": { "type": "http", - "url": "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT", + "url": "http://localhost:$GH_AW_SAFE_OUTPUTS_PORT", "headers": { "Authorization": "$GH_AW_SAFE_OUTPUTS_API_KEY" }, @@ -648,7 +642,7 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_1c3fd8845aaab39f_EOF + GH_AW_MCP_CONFIG_7ab0b468f68178ce_EOF - name: Download activation artifact uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: @@ -661,26 +655,22 @@ jobs: id: agentic_execution run: | set -o pipefail - mkdir -p "$CODEX_HOME/logs" && touch /tmp/gh-aw/agent-step-summary.md + touch /tmp/gh-aw/agent-step-summary.md (umask 177 && touch /tmp/gh-aw/agent-stdio.log) - # shellcheck disable=SC1003 - sudo -E awf --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" --env-all --exclude-env CODEX_API_KEY --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --exclude-env OPENAI_API_KEY --allow-domains 172.30.0.1,api.openai.com,api.zhizengzeng.com,host.docker.internal,openai.com --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --image-tag 0.25.20 --skip-pull --enable-api-proxy --openai-api-target api.zhizengzeng.com --openai-api-base-path /v1 \ - -- /bin/bash -c 'export PATH="$(find /opt/hostedtoolcache -maxdepth 4 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true && INSTRUCTION="$(cat /tmp/gh-aw/aw-prompts/prompt.txt)" && codex ${GH_AW_MODEL_AGENT_CODEX:+-c model="$GH_AW_MODEL_AGENT_CODEX" }exec -c web_search="disabled" -c fetch="disabled" --dangerously-bypass-approvals-and-sandbox --skip-git-repo-check "$INSTRUCTION"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + INSTRUCTION="$(cat "$GH_AW_PROMPT")" + mkdir -p "$CODEX_HOME/logs" + codex ${GH_AW_MODEL_AGENT_CODEX:+-c model="$GH_AW_MODEL_AGENT_CODEX" }exec -c web_search="disabled" -c fetch="disabled" --dangerously-bypass-approvals-and-sandbox --skip-git-repo-check "$INSTRUCTION" 2>&1 | tee /tmp/gh-aw/agent-stdio.log env: CODEX_API_KEY: ${{ secrets.CODEX_API_KEY || secrets.OPENAI_API_KEY }} CODEX_HOME: /tmp/gh-aw/mcp-config GH_AW_MCP_CONFIG: /tmp/gh-aw/mcp-config/config.toml - GH_AW_MODEL_AGENT_CODEX: gpt-5.3 + GH_AW_MODEL_AGENT_CODEX: gpt-5.3-codex GH_AW_PHASE: agent GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} GH_AW_VERSION: v0.68.3 GITHUB_AW: true GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md - GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com - GIT_AUTHOR_NAME: github-actions[bot] - GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com - GIT_COMMITTER_NAME: github-actions[bot] OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} OPENAI_BASE_URL: https://api.zhizengzeng.com/v1 RUST_LOG: trace,hyper_util=info,mio=info,reqwest=info,os_info=info,codex_otel=warn,codex_core=debug,ocodex_exec=debug @@ -768,31 +758,6 @@ jobs: setupGlobals(core, github, context, exec, io, getOctokit); const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_mcp_gateway_log.cjs'); await main(); - - name: Print firewall logs - if: always() - continue-on-error: true - env: - AWF_LOGS_DIR: /tmp/gh-aw/sandbox/firewall/logs - run: | - # Fix permissions on firewall logs so they can be uploaded as artifacts - # AWF runs with sudo, creating files owned by root - sudo chmod -R a+r /tmp/gh-aw/sandbox/firewall/logs 2>/dev/null || true - # Only run awf logs summary if awf command exists (it may not be installed if workflow failed before install step) - if command -v awf &> /dev/null; then - awf logs summary | tee -a "$GITHUB_STEP_SUMMARY" - else - echo 'AWF binary not installed, skipping firewall log summary' - fi - - name: Parse token usage for step summary - if: always() - continue-on-error: true - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 - with: - script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_token_usage.cjs'); - await main(); - name: Write agent output placeholder if missing if: always() run: | @@ -810,23 +775,17 @@ jobs: /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-stdio.log /tmp/gh-aw/agent/ /tmp/gh-aw/github_rate_limits.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/sandbox/firewall/logs/ - /tmp/gh-aw/sandbox/firewall/audit/ if-no-files-found: ignore conclusion: needs: - activation - agent - - detection - safe_outputs if: > always() && (needs.agent.result != 'skipped' || needs.activation.outputs.lockdown_check_failed == 'true' || @@ -884,22 +843,6 @@ jobs: setupGlobals(core, github, context, exec, io, getOctokit); const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_noop_message.cjs'); await main(); - - name: Log detection run - id: detection_runs - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 - env: - GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Issue 自动分类与回复" - 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 { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_detection_runs.cjs'); - await main(); - name: Record missing tool id: missing_tool uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 @@ -953,162 +896,6 @@ jobs: const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_agent_failure.cjs'); await main(); - detection: - needs: - - activation - - agent - if: > - always() && needs.agent.result != 'skipped' && (needs.agent.outputs.output_types != '' || needs.agent.outputs.has_patch == 'true') - runs-on: ubuntu-latest - permissions: - contents: read - outputs: - detection_conclusion: ${{ steps.detection_conclusion.outputs.conclusion }} - detection_reason: ${{ steps.detection_conclusion.outputs.reason }} - detection_success: ${{ steps.detection_conclusion.outputs.success }} - steps: - - name: Setup Scripts - id: setup - uses: github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 - with: - destination: ${{ runner.temp }}/gh-aw/actions - job-name: ${{ github.job }} - trace-id: ${{ needs.activation.outputs.setup-trace-id }} - - name: Download agent output artifact - id: download-agent-output - continue-on-error: true - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - with: - name: agent - path: /tmp/gh-aw/ - - name: Setup agent output environment variable - id: setup-agent-output-env - if: steps.download-agent-output.outcome == 'success' - run: | - mkdir -p /tmp/gh-aw/ - find "/tmp/gh-aw/" -type f -print - echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT" - - name: Checkout repository for patch context - if: needs.agent.outputs.has_patch == 'true' - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - persist-credentials: false - # --- Threat Detection --- - - name: 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.25.20 ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20 ghcr.io/github/gh-aw-firewall/squid:0.25.20 - - name: Check if detection needed - id: detection_guard - if: always() - env: - OUTPUT_TYPES: ${{ needs.agent.outputs.output_types }} - HAS_PATCH: ${{ needs.agent.outputs.has_patch }} - run: | - if [[ -n "$OUTPUT_TYPES" || "$HAS_PATCH" == "true" ]]; then - echo "run_detection=true" >> "$GITHUB_OUTPUT" - echo "Detection will run: output_types=$OUTPUT_TYPES, has_patch=$HAS_PATCH" - else - echo "run_detection=false" >> "$GITHUB_OUTPUT" - echo "Detection skipped: no agent outputs or patches to analyze" - fi - - name: Clear MCP configuration for detection - if: always() && steps.detection_guard.outputs.run_detection == 'true' - run: | - rm -f /tmp/gh-aw/mcp-config/mcp-servers.json - rm -f /home/runner/.copilot/mcp-config.json - rm -f "$GITHUB_WORKSPACE/.gemini/settings.json" - - name: Prepare threat detection files - if: always() && steps.detection_guard.outputs.run_detection == 'true' - run: | - mkdir -p /tmp/gh-aw/threat-detection/aw-prompts - cp /tmp/gh-aw/aw-prompts/prompt.txt /tmp/gh-aw/threat-detection/aw-prompts/prompt.txt 2>/dev/null || true - cp /tmp/gh-aw/agent_output.json /tmp/gh-aw/threat-detection/agent_output.json 2>/dev/null || true - for f in /tmp/gh-aw/aw-*.patch; do - [ -f "$f" ] && cp "$f" /tmp/gh-aw/threat-detection/ 2>/dev/null || true - done - for f in /tmp/gh-aw/aw-*.bundle; do - [ -f "$f" ] && cp "$f" /tmp/gh-aw/threat-detection/ 2>/dev/null || true - done - echo "Prepared threat detection files:" - ls -la /tmp/gh-aw/threat-detection/ 2>/dev/null || true - - name: Setup threat detection - if: always() && steps.detection_guard.outputs.run_detection == 'true' - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 - env: - WORKFLOW_NAME: "Issue 自动分类与回复" - WORKFLOW_DESCRIPTION: "No description provided" - HAS_PATCH: ${{ needs.agent.outputs.has_patch }} - with: - script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/setup_threat_detection.cjs'); - await main(); - - name: Ensure threat-detection directory and log - if: always() && steps.detection_guard.outputs.run_detection == 'true' - run: | - mkdir -p /tmp/gh-aw/threat-detection - touch /tmp/gh-aw/threat-detection/detection.log - - name: Setup Node.js - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 - with: - node-version: '24' - package-manager-cache: false - - name: Install Codex CLI - run: npm install --ignore-scripts -g @openai/codex@0.118.0 - - name: Install AWF binary - run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.25.20 - - name: Execute Codex CLI - if: always() && steps.detection_guard.outputs.run_detection == 'true' - id: detection_agentic_execution - run: | - set -o pipefail - mkdir -p "$CODEX_HOME/logs" && touch /tmp/gh-aw/agent-step-summary.md - (umask 177 && touch /tmp/gh-aw/threat-detection/detection.log) - # shellcheck disable=SC1003 - sudo -E awf --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" --env-all --exclude-env CODEX_API_KEY --exclude-env OPENAI_API_KEY --allow-domains 172.30.0.1,api.openai.com,host.docker.internal,openai.com --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --image-tag 0.25.20 --skip-pull --enable-api-proxy --openai-api-target api.zhizengzeng.com --openai-api-base-path /v1 \ - -- /bin/bash -c 'export PATH="$(find /opt/hostedtoolcache -maxdepth 4 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true && INSTRUCTION="$(cat /tmp/gh-aw/aw-prompts/prompt.txt)" && codex ${GH_AW_MODEL_DETECTION_CODEX:+-c model="$GH_AW_MODEL_DETECTION_CODEX" }exec -c web_search="disabled" -c fetch="disabled" --dangerously-bypass-approvals-and-sandbox --skip-git-repo-check "$INSTRUCTION"' 2>&1 | tee -a /tmp/gh-aw/threat-detection/detection.log - env: - CODEX_API_KEY: ${{ secrets.CODEX_API_KEY || secrets.OPENAI_API_KEY }} - CODEX_HOME: /tmp/gh-aw/mcp-config - GH_AW_MCP_CONFIG: /tmp/gh-aw/mcp-config/config.toml - GH_AW_MODEL_DETECTION_CODEX: gpt-5.3 - GH_AW_PHASE: detection - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GH_AW_VERSION: v0.68.3 - GITHUB_AW: true - GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md - GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com - GIT_AUTHOR_NAME: github-actions[bot] - GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com - GIT_COMMITTER_NAME: github-actions[bot] - OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - OPENAI_BASE_URL: https://api.zhizengzeng.com/v1 - RUST_LOG: trace,hyper_util=info,mio=info,reqwest=info,os_info=info,codex_otel=warn,codex_core=debug,ocodex_exec=debug - - name: Upload threat detection log - if: always() && steps.detection_guard.outputs.run_detection == 'true' - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: detection - path: /tmp/gh-aw/threat-detection/detection.log - if-no-files-found: ignore - - name: Parse and conclude threat detection - id: detection_conclusion - if: always() - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 - env: - RUN_DETECTION: ${{ steps.detection_guard.outputs.run_detection }} - GH_AW_DETECTION_CONTINUE_ON_ERROR: "true" - with: - script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_threat_detection_results.cjs'); - await main(); - pre_activation: runs-on: ubuntu-slim outputs: @@ -1139,8 +926,7 @@ jobs: needs: - activation - agent - - detection - if: (!cancelled()) && needs.agent.result != 'skipped' && needs.detection.result == 'success' + if: (!cancelled()) && needs.agent.result != 'skipped' runs-on: ubuntu-slim permissions: contents: read @@ -1150,11 +936,9 @@ jobs: timeout-minutes: 15 env: GH_AW_CALLER_WORKFLOW_ID: "${{ github.repository }}/issue-triage" - GH_AW_DETECTION_CONCLUSION: ${{ needs.detection.outputs.detection_conclusion }} - GH_AW_DETECTION_REASON: ${{ needs.detection.outputs.detection_reason }} GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens }} GH_AW_ENGINE_ID: "codex" - GH_AW_ENGINE_MODEL: "gpt-5.3" + GH_AW_ENGINE_MODEL: "gpt-5.3-codex" GH_AW_WORKFLOW_ID: "issue-triage" GH_AW_WORKFLOW_NAME: "Issue 自动分类与回复" outputs: diff --git a/.github/workflows/issue-triage.md b/.github/workflows/issue-triage.md index 1ba52697..94ef8a95 100644 --- a/.github/workflows/issue-triage.md +++ b/.github/workflows/issue-triage.md @@ -5,7 +5,7 @@ on: engine: id: codex - model: gpt-5.3 + model: gpt-5.3-codex env: OPENAI_BASE_URL: "https://api.zhizengzeng.com/v1" OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} @@ -14,10 +14,15 @@ network: allowed: - api.zhizengzeng.com +sandbox: + agent: false +strict: false + permissions: issues: read safe-outputs: + threat-detection: false add-comment: max: 1 add-labels: From dd2e02d24a27a740024a83a04bf9f294ea5e1929 Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Mon, 27 Apr 2026 16:29:01 +0800 Subject: [PATCH 05/59] fix: add missing permissions --- .github/workflows/issue-triage.lock.yml | 70 ++++++++++++++++--------- .github/workflows/issue-triage.md | 7 +++ 2 files changed, 51 insertions(+), 26 deletions(-) diff --git a/.github/workflows/issue-triage.lock.yml b/.github/workflows/issue-triage.lock.yml index d43803a7..5d5c62e6 100644 --- a/.github/workflows/issue-triage.lock.yml +++ b/.github/workflows/issue-triage.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"3490689ea862dba5da342751a4e24dfea74a8367df0700a9cf323ff6f4b87f60","compiler_version":"v0.68.3","agent_id":"codex","agent_model":"gpt-5.3-codex"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"c77cf1c7a513394cceedc693f93692d1f0017c13c2fce6c6c81b2363245aebb2","compiler_version":"v0.68.3","agent_id":"codex","agent_model":"gpt-5.3-codex"} # gh-aw-manifest: {"version":1,"secrets":["CODEX_API_KEY","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/setup-node","sha":"53b83947a5a98c8d113130e565377fae1a50d02f","version":"v6.3.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"ba90f2186d7ad780ec640f364005fa24e797b360","version":"v0.68.3"}],"containers":[{"image":"ghcr.io/github/github-mcp-server:v0.32.0"},{"image":"node:lts-alpine"}]} # ___ _ _ # / _ \ | | (_) @@ -171,14 +171,14 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_32cb1af60213c743_EOF' + cat << 'GH_AW_PROMPT_74dabe01380845dd_EOF' - GH_AW_PROMPT_32cb1af60213c743_EOF + GH_AW_PROMPT_74dabe01380845dd_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_32cb1af60213c743_EOF' + cat << 'GH_AW_PROMPT_74dabe01380845dd_EOF' Tools: add_comment, add_labels, missing_tool, missing_data, noop @@ -210,12 +210,12 @@ jobs: {{/if}} - GH_AW_PROMPT_32cb1af60213c743_EOF + GH_AW_PROMPT_74dabe01380845dd_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_32cb1af60213c743_EOF' + cat << 'GH_AW_PROMPT_74dabe01380845dd_EOF' {{#runtime-import .github/workflows/issue-triage.md}} - GH_AW_PROMPT_32cb1af60213c743_EOF + GH_AW_PROMPT_74dabe01380845dd_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 @@ -289,7 +289,9 @@ jobs: needs: activation runs-on: ubuntu-latest permissions: + contents: read issues: read + pull-requests: read env: DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} GH_AW_ASSETS_ALLOWED_EXTS: "" @@ -298,6 +300,7 @@ jobs: GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs GH_AW_WORKFLOW_ID_SANITIZED: issuetriage outputs: + checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} effective_tokens: ${{ steps.parse-mcp-gateway.outputs.effective_tokens }} has_patch: ${{ steps.collect_output.outputs.has_patch }} model: ${{ needs.activation.outputs.model }} @@ -343,6 +346,20 @@ jobs: SERVER_URL_STRIPPED="${SERVER_URL#https://}" git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" echo "Git configured with standard GitHub Actions identity" + - name: Checkout PR branch + id: checkout-pr + if: | + github.event.pull_request || github.event.issue.pull_request + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + with: + github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/checkout_pr_branch.cjs'); + await main(); - name: Setup Node.js uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: @@ -350,16 +367,13 @@ jobs: package-manager-cache: false - name: Install Codex CLI run: npm install --ignore-scripts -g @openai/codex@0.118.0 - - name: Determine automatic lockdown mode for GitHub MCP Server - id: determine-automatic-lockdown - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + - name: Parse integrity filter lists + id: parse-guard-vars env: - GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} - GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} - with: - script: | - const determineAutomaticLockdown = require('${{ runner.temp }}/gh-aw/actions/determine_automatic_lockdown.cjs'); - await determineAutomaticLockdown(github, context, core); + GH_AW_BLOCKED_USERS_VAR: ${{ vars.GH_AW_GITHUB_BLOCKED_USERS || '' }} + GH_AW_TRUSTED_USERS_VAR: ${{ vars.GH_AW_GITHUB_TRUSTED_USERS || '' }} + GH_AW_APPROVAL_LABELS_VAR: ${{ vars.GH_AW_GITHUB_APPROVAL_LABELS || '' }} + run: bash "${RUNNER_TEMP}/gh-aw/actions/parse_guard_list.sh" - name: Download container images run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/github-mcp-server:v0.32.0 node:lts-alpine - name: Write Safe Outputs Config @@ -367,9 +381,9 @@ jobs: mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs - cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_a5c4c11137a888d8_EOF' + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_2caa0dae86f4499b_EOF' {"add_comment":{"max":1},"add_labels":{"allowed":["bug","feature","enhancement","documentation","question","duplicate","invalid"]},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} - GH_AW_SAFE_OUTPUTS_CONFIG_a5c4c11137a888d8_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_2caa0dae86f4499b_EOF - name: Write Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -551,8 +565,6 @@ jobs: GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-start.outputs.api_key }} GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-start.outputs.port }} - GITHUB_MCP_GUARD_MIN_INTEGRITY: ${{ steps.determine-automatic-lockdown.outputs.min_integrity }} - GITHUB_MCP_GUARD_REPOS: ${{ steps.determine-automatic-lockdown.outputs.repos }} GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} run: | set -eo pipefail @@ -572,7 +584,7 @@ jobs: export GH_AW_ENGINE="codex" export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.2.19' - cat > /tmp/gh-aw/mcp-config/config.toml << GH_AW_MCP_CONFIG_7ab0b468f68178ce_EOF + cat > /tmp/gh-aw/mcp-config/config.toml << GH_AW_MCP_CONFIG_70937a147e264612_EOF [history] persistence = "none" @@ -599,10 +611,10 @@ jobs: [mcp_servers.safeoutputs."guard-policies".write-sink] accept = ["*"] - GH_AW_MCP_CONFIG_7ab0b468f68178ce_EOF + GH_AW_MCP_CONFIG_70937a147e264612_EOF # Generate JSON config for MCP gateway - cat << GH_AW_MCP_CONFIG_7ab0b468f68178ce_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" + cat << GH_AW_MCP_CONFIG_70937a147e264612_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" { "mcpServers": { "github": { @@ -615,8 +627,11 @@ jobs: }, "guard-policies": { "allow-only": { - "min-integrity": "$GITHUB_MCP_GUARD_MIN_INTEGRITY", - "repos": "$GITHUB_MCP_GUARD_REPOS" + "approval-labels": ${{ steps.parse-guard-vars.outputs.approval_labels }}, + "blocked-users": ${{ steps.parse-guard-vars.outputs.blocked_users }}, + "min-integrity": "none", + "repos": "all", + "trusted-users": ${{ steps.parse-guard-vars.outputs.trusted_users }} } } }, @@ -642,7 +657,7 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_7ab0b468f68178ce_EOF + GH_AW_MCP_CONFIG_70937a147e264612_EOF - name: Download activation artifact uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: @@ -775,6 +790,8 @@ jobs: /tmp/gh-aw/mcp-config/logs/ /tmp/gh-aw/redacted-urls.log /tmp/gh-aw/mcp-logs/ + /tmp/gh-aw/proxy-logs/ + !/tmp/gh-aw/proxy-logs/proxy-tls/ /tmp/gh-aw/agent-stdio.log /tmp/gh-aw/agent/ /tmp/gh-aw/github_rate_limits.jsonl @@ -883,6 +900,7 @@ jobs: GH_AW_WORKFLOW_ID: "issue-triage" GH_AW_ENGINE_ID: "codex" GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.activation.outputs.secret_verification_result }} + GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} GH_AW_LOCKDOWN_CHECK_FAILED: ${{ needs.activation.outputs.lockdown_check_failed }} GH_AW_STALE_LOCK_FILE_FAILED: ${{ needs.activation.outputs.stale_lock_file_failed }} GH_AW_GROUP_REPORTS: "false" diff --git a/.github/workflows/issue-triage.md b/.github/workflows/issue-triage.md index 94ef8a95..7c6cfb4c 100644 --- a/.github/workflows/issue-triage.md +++ b/.github/workflows/issue-triage.md @@ -16,10 +16,17 @@ network: sandbox: agent: false + strict: false +tools: + github: + min-integrity: none + permissions: issues: read + contents: read + pull-requests: read safe-outputs: threat-detection: false From 8de124c01287d66031222f0b8572488fb09b7164 Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Mon, 27 Apr 2026 17:16:16 +0800 Subject: [PATCH 06/59] refactor: merge auto-fix and auto-feature into auto-code --- .github/workflows/auto-code.lock.yml | 1082 +++++++++++++++++++++++ .github/workflows/auto-code.md | 87 ++ .github/workflows/auto-fix.md | 45 - .github/workflows/issue-triage.lock.yml | 26 +- .github/workflows/issue-triage.md | 3 +- 5 files changed, 1183 insertions(+), 60 deletions(-) create mode 100644 .github/workflows/auto-code.lock.yml create mode 100644 .github/workflows/auto-code.md delete mode 100644 .github/workflows/auto-fix.md diff --git a/.github/workflows/auto-code.lock.yml b/.github/workflows/auto-code.lock.yml new file mode 100644 index 00000000..9e107834 --- /dev/null +++ b/.github/workflows/auto-code.lock.yml @@ -0,0 +1,1082 @@ +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"c3f4c5f63fbb5f81f3b96a004386e91dd5572ded66b0b7fa8a545eb5aea77e19","compiler_version":"v0.68.3","agent_id":"codex","agent_model":"gpt-5.3-codex"} +# gh-aw-manifest: {"version":1,"secrets":["CODEX_API_KEY","GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/setup-node","sha":"53b83947a5a98c8d113130e565377fae1a50d02f","version":"v6.3.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"ba90f2186d7ad780ec640f364005fa24e797b360","version":"v0.68.3"}],"containers":[{"image":"ghcr.io/github/github-mcp-server:v0.32.0"},{"image":"node:lts-alpine"}]} +# ___ _ _ +# / _ \ | | (_) +# | |_| | __ _ ___ _ __ | |_ _ ___ +# | _ |/ _` |/ _ \ '_ \| __| |/ __| +# | | | | (_| | __/ | | | |_| | (__ +# \_| |_/\__, |\___|_| |_|\__|_|\___| +# __/ | +# _ _ |___/ +# | | | | / _| | +# | | | | ___ _ __ _ __| |_| | _____ ____ +# | |/\| |/ _ \ '__| |/ /| _| |/ _ \ \ /\ / / ___| +# \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ +# \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ +# +# This file was automatically generated by gh-aw (v0.68.3). DO NOT EDIT. +# +# To update this file, edit the corresponding .md file and run: +# gh aw compile +# Not all edits will cause changes to this file. +# +# For more information: https://github.github.com/gh-aw/introduction/overview/ +# +# +# Secrets used: +# - CODEX_API_KEY +# - GH_AW_CI_TRIGGER_TOKEN +# - GH_AW_GITHUB_MCP_SERVER_TOKEN +# - GH_AW_GITHUB_TOKEN +# - GITHUB_TOKEN +# - OPENAI_API_KEY +# +# Custom actions used: +# - actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 +# - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 +# - actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 +# - actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 +# - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 +# - github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 +# +# Container images used: +# - ghcr.io/github/github-mcp-server:v0.32.0 +# - node:lts-alpine + +name: "自动处理 Issue" +"on": + issues: + types: + - labeled + +permissions: {} + +concurrency: + group: "gh-aw-${{ github.workflow }}-${{ github.event.issue.number || github.run_id }}" + +run-name: "自动处理 Issue" + +jobs: + activation: + needs: pre_activation + if: needs.pre_activation.outputs.activated == 'true' + runs-on: ubuntu-slim + permissions: + actions: read + contents: read + outputs: + body: ${{ steps.sanitized.outputs.body }} + comment_id: "" + comment_repo: "" + lockdown_check_failed: ${{ steps.generate_aw_info.outputs.lockdown_check_failed == 'true' }} + model: ${{ steps.generate_aw_info.outputs.model }} + secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} + setup-trace-id: ${{ steps.setup.outputs.trace-id }} + stale_lock_file_failed: ${{ steps.check-lock-file.outputs.stale_lock_file_failed == 'true' }} + text: ${{ steps.sanitized.outputs.text }} + title: ${{ steps.sanitized.outputs.title }} + steps: + - name: Setup Scripts + id: setup + uses: github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.pre_activation.outputs.setup-trace-id }} + - 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: "gpt-5.3-codex" + GH_AW_INFO_VERSION: "0.118.0" + GH_AW_INFO_AGENT_VERSION: "0.118.0" + GH_AW_INFO_CLI_VERSION: "v0.68.3" + GH_AW_INFO_WORKFLOW_NAME: "自动处理 Issue" + GH_AW_INFO_EXPERIMENTAL: "false" + GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true" + GH_AW_INFO_STAGED: "false" + GH_AW_INFO_ALLOWED_DOMAINS: '["api.zhizengzeng.com"]' + GH_AW_INFO_FIREWALL_ENABLED: "false" + GH_AW_INFO_AWF_VERSION: "" + GH_AW_INFO_AWMG_VERSION: "" + GH_AW_INFO_FIREWALL_TYPE: "" + GH_AW_COMPILED_STRICT: "false" + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/generate_aw_info.cjs'); + await main(core, context); + - name: Validate CODEX_API_KEY or OPENAI_API_KEY secret + id: validate-secret + run: bash "${RUNNER_TEMP}/gh-aw/actions/validate_multi_secret.sh" CODEX_API_KEY OPENAI_API_KEY Codex https://github.github.com/gh-aw/reference/engines/#openai-codex + env: + CODEX_API_KEY: ${{ secrets.CODEX_API_KEY }} + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + - name: Checkout .github and .agents folders + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + sparse-checkout: | + .github + .agents + sparse-checkout-cone-mode: true + fetch-depth: 1 + - name: Check workflow lock file + id: check-lock-file + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_WORKFLOW_FILE: "auto-code.lock.yml" + GH_AW_CONTEXT_WORKFLOW_REF: "${{ github.workflow_ref }}" + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/check_workflow_timestamp_api.cjs'); + await main(); + - name: Check compile-agentic version + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_COMPILED_VERSION: "v0.68.3" + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/check_version_updates.cjs'); + await main(); + - name: Compute current body text + id: sanitized + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/compute_text.cjs'); + await main(); + - name: Create prompt with built-in context + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_SAFE_OUTPUTS: ${{ runner.temp }}/gh-aw/safeoutputs/outputs.jsonl + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} + GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} + # poutine:ignore untrusted_checkout_exec + run: | + bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" + { + cat << 'GH_AW_PROMPT_5258e6a960ff65c1_EOF' + + GH_AW_PROMPT_5258e6a960ff65c1_EOF + cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" + cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" + cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" + cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" + cat << 'GH_AW_PROMPT_5258e6a960ff65c1_EOF' + + Tools: add_comment, create_pull_request, missing_tool, missing_data, noop + GH_AW_PROMPT_5258e6a960ff65c1_EOF + cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_create_pull_request.md" + cat << 'GH_AW_PROMPT_5258e6a960ff65c1_EOF' + + + The following GitHub context information is available for this workflow: + {{#if __GH_AW_GITHUB_ACTOR__ }} + - **actor**: __GH_AW_GITHUB_ACTOR__ + {{/if}} + {{#if __GH_AW_GITHUB_REPOSITORY__ }} + - **repository**: __GH_AW_GITHUB_REPOSITORY__ + {{/if}} + {{#if __GH_AW_GITHUB_WORKSPACE__ }} + - **workspace**: __GH_AW_GITHUB_WORKSPACE__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ }} + - **issue-number**: #__GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ }} + - **discussion-number**: #__GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ }} + - **pull-request-number**: #__GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_COMMENT_ID__ }} + - **comment-id**: __GH_AW_GITHUB_EVENT_COMMENT_ID__ + {{/if}} + {{#if __GH_AW_GITHUB_RUN_ID__ }} + - **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__ + {{/if}} + + + GH_AW_PROMPT_5258e6a960ff65c1_EOF + cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" + cat << 'GH_AW_PROMPT_5258e6a960ff65c1_EOF' + + {{#runtime-import .github/workflows/auto-code.md}} + GH_AW_PROMPT_5258e6a960ff65c1_EOF + } > "$GH_AW_PROMPT" + - name: Interpolate variables and render templates + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/interpolate_prompt.cjs'); + await main(); + - name: Substitute placeholders + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} + GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} + GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: ${{ needs.pre_activation.outputs.activated }} + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + + const substitutePlaceholders = require('${{ runner.temp }}/gh-aw/actions/substitute_placeholders.cjs'); + + // Call the substitution function + return await substitutePlaceholders({ + file: process.env.GH_AW_PROMPT, + substitutions: { + GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR, + GH_AW_GITHUB_EVENT_COMMENT_ID: process.env.GH_AW_GITHUB_EVENT_COMMENT_ID, + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: process.env.GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER, + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: process.env.GH_AW_GITHUB_EVENT_ISSUE_NUMBER, + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: process.env.GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER, + GH_AW_GITHUB_REPOSITORY: process.env.GH_AW_GITHUB_REPOSITORY, + GH_AW_GITHUB_RUN_ID: process.env.GH_AW_GITHUB_RUN_ID, + GH_AW_GITHUB_WORKSPACE: process.env.GH_AW_GITHUB_WORKSPACE, + GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: process.env.GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED + } + }); + - name: Validate prompt placeholders + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + # poutine:ignore untrusted_checkout_exec + run: bash "${RUNNER_TEMP}/gh-aw/actions/validate_prompt_placeholders.sh" + - name: Print prompt + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + # poutine:ignore untrusted_checkout_exec + run: bash "${RUNNER_TEMP}/gh-aw/actions/print_prompt_summary.sh" + - name: Upload activation artifact + if: success() + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: activation + path: | + /tmp/gh-aw/aw_info.json + /tmp/gh-aw/aw-prompts/prompt.txt + /tmp/gh-aw/github_rate_limits.jsonl + if-no-files-found: ignore + retention-days: 1 + + agent: + needs: activation + runs-on: ubuntu-latest + permissions: + contents: read + issues: read + pull-requests: read + env: + DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + GH_AW_ASSETS_ALLOWED_EXTS: "" + GH_AW_ASSETS_BRANCH: "" + GH_AW_ASSETS_MAX_SIZE_KB: 0 + GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs + GH_AW_WORKFLOW_ID_SANITIZED: autocode + outputs: + checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} + effective_tokens: ${{ steps.parse-mcp-gateway.outputs.effective_tokens }} + has_patch: ${{ steps.collect_output.outputs.has_patch }} + model: ${{ needs.activation.outputs.model }} + output: ${{ steps.collect_output.outputs.output }} + output_types: ${{ steps.collect_output.outputs.output_types }} + setup-trace-id: ${{ steps.setup.outputs.trace-id }} + steps: + - name: Setup Scripts + id: setup + uses: github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} + - name: Set runtime paths + id: set-runtime-paths + run: | + { + 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: Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + - 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: Configure Git credentials + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + GITHUB_TOKEN: ${{ github.token }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + git config --global am.keepcr true + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Checkout PR branch + id: checkout-pr + if: | + github.event.pull_request || github.event.issue.pull_request + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + with: + github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/checkout_pr_branch.cjs'); + await main(); + - name: Setup Node.js + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 + with: + node-version: '24' + package-manager-cache: false + - name: Install Codex CLI + run: npm install --ignore-scripts -g @openai/codex@0.118.0 + - name: Parse integrity filter lists + id: parse-guard-vars + env: + GH_AW_BLOCKED_USERS_VAR: ${{ vars.GH_AW_GITHUB_BLOCKED_USERS || '' }} + GH_AW_TRUSTED_USERS_VAR: ${{ vars.GH_AW_GITHUB_TRUSTED_USERS || '' }} + GH_AW_APPROVAL_LABELS_VAR: ${{ vars.GH_AW_GITHUB_APPROVAL_LABELS || '' }} + run: bash "${RUNNER_TEMP}/gh-aw/actions/parse_guard_list.sh" + - name: Download container images + run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/github-mcp-server:v0.32.0 node:lts-alpine + - name: Write Safe Outputs Config + run: | + mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" + mkdir -p /tmp/gh-aw/safeoutputs + mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_4193c32f65e9b5fd_EOF' + {"add_comment":{"max":1},"create_pull_request":{"base_branch":"develop","max":1,"max_patch_size":1024,"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"],"protected_path_prefixes":[".github/",".agents/"]},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} + GH_AW_SAFE_OUTPUTS_CONFIG_4193c32f65e9b5fd_EOF + - name: Write Safe Outputs Tools + env: + GH_AW_TOOLS_META_JSON: | + { + "description_suffixes": { + "add_comment": " CONSTRAINTS: Maximum 1 comment(s) can be added. Supports reply_to_id for discussion threading.", + "create_pull_request": " CONSTRAINTS: Maximum 1 pull request(s) can be created." + }, + "repo_params": {}, + "dynamic_tools": [] + } + GH_AW_VALIDATION_JSON: | + { + "add_comment": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "item_number": { + "issueOrPRNumber": true + }, + "reply_to_id": { + "type": "string", + "maxLength": 256 + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, + "create_pull_request": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "branch": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "draft": { + "type": "boolean" + }, + "labels": { + "type": "array", + "itemType": "string", + "itemSanitize": true, + "itemMaxLength": 128 + }, + "repo": { + "type": "string", + "maxLength": 256 + }, + "title": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 128 + } + } + }, + "missing_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, + "missing_tool": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 512 + }, + "reason": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "tool": { + "type": "string", + "sanitize": true, + "maxLength": 128 + } + } + }, + "noop": { + "defaultMax": 1, + "fields": { + "message": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + } + } + }, + "report_incomplete": { + "defaultMax": 5, + "fields": { + "details": { + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "reason": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 1024 + } + } + } + } + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/generate_safe_outputs_tools.cjs'); + await main(); + - name: Generate Safe Outputs MCP Server Config + id: safe-outputs-config + run: | + # Generate a secure random API key (360 bits of entropy, 40+ chars) + # Mask immediately to prevent timing vulnerabilities + API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${API_KEY}" + + PORT=3001 + + # Set outputs for next steps + { + echo "safe_outputs_api_key=${API_KEY}" + echo "safe_outputs_port=${PORT}" + } >> "$GITHUB_OUTPUT" + + echo "Safe Outputs MCP server will run on port ${PORT}" + + - name: Start Safe Outputs MCP HTTP Server + id: safe-outputs-start + env: + DEBUG: '*' + GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} + GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-config.outputs.safe_outputs_port }} + GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-config.outputs.safe_outputs_api_key }} + GH_AW_SAFE_OUTPUTS_TOOLS_PATH: ${{ runner.temp }}/gh-aw/safeoutputs/tools.json + GH_AW_SAFE_OUTPUTS_CONFIG_PATH: ${{ runner.temp }}/gh-aw/safeoutputs/config.json + GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs + run: | + # Environment variables are set above to prevent template injection + export DEBUG + export GH_AW_SAFE_OUTPUTS + export GH_AW_SAFE_OUTPUTS_PORT + export GH_AW_SAFE_OUTPUTS_API_KEY + export GH_AW_SAFE_OUTPUTS_TOOLS_PATH + export GH_AW_SAFE_OUTPUTS_CONFIG_PATH + export GH_AW_MCP_LOG_DIR + + bash "${RUNNER_TEMP}/gh-aw/actions/start_safe_outputs_server.sh" + + - name: Start MCP Gateway + id: start-mcp-gateway + env: + GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} + GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-start.outputs.api_key }} + GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-start.outputs.port }} + GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + run: | + set -eo pipefail + mkdir -p /tmp/gh-aw/mcp-config + + # Export gateway environment variables for MCP config and gateway script + export MCP_GATEWAY_PORT="80" + export MCP_GATEWAY_DOMAIN="localhost" + MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${MCP_GATEWAY_API_KEY}" + export MCP_GATEWAY_API_KEY + export MCP_GATEWAY_PAYLOAD_DIR="/tmp/gh-aw/mcp-payloads" + mkdir -p "${MCP_GATEWAY_PAYLOAD_DIR}" + export MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD="524288" + export DEBUG="*" + + export GH_AW_ENGINE="codex" + export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.2.19' + + cat > /tmp/gh-aw/mcp-config/config.toml << GH_AW_MCP_CONFIG_8d05bb28961e7647_EOF + [history] + persistence = "none" + + [shell_environment_policy] + inherit = "core" + include_only = ["CODEX_API_KEY", "GH_AW_ASSETS_ALLOWED_EXTS", "GH_AW_ASSETS_BRANCH", "GH_AW_ASSETS_MAX_SIZE_KB", "GH_AW_SAFE_OUTPUTS", "GITHUB_PERSONAL_ACCESS_TOKEN", "GITHUB_REPOSITORY", "GITHUB_SERVER_URL", "HOME", "OPENAI_API_KEY", "PATH"] + + [mcp_servers.github] + user_agent = "issue" + startup_timeout_sec = 120 + tool_timeout_sec = 60 + container = "ghcr.io/github/github-mcp-server:v0.32.0" + env = { "GITHUB_HOST" = "$GITHUB_SERVER_URL", "GITHUB_PERSONAL_ACCESS_TOKEN" = "$GH_AW_GITHUB_TOKEN", "GITHUB_READ_ONLY" = "1", "GITHUB_TOOLSETS" = "context,repos,issues,pull_requests" } + env_vars = ["GITHUB_HOST", "GITHUB_PERSONAL_ACCESS_TOKEN", "GITHUB_READ_ONLY", "GITHUB_TOOLSETS"] + + [mcp_servers.safeoutputs] + type = "http" + url = "http://localhost:$GH_AW_SAFE_OUTPUTS_PORT" + + [mcp_servers.safeoutputs.headers] + Authorization = "$GH_AW_SAFE_OUTPUTS_API_KEY" + + [mcp_servers.safeoutputs."guard-policies"] + + [mcp_servers.safeoutputs."guard-policies".write-sink] + accept = ["*"] + GH_AW_MCP_CONFIG_8d05bb28961e7647_EOF + + # Generate JSON config for MCP gateway + cat << GH_AW_MCP_CONFIG_8d05bb28961e7647_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" + { + "mcpServers": { + "github": { + "container": "ghcr.io/github/github-mcp-server:v0.32.0", + "env": { + "GITHUB_HOST": "$GITHUB_SERVER_URL", + "GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_MCP_SERVER_TOKEN", + "GITHUB_READ_ONLY": "1", + "GITHUB_TOOLSETS": "context,repos,issues,pull_requests" + }, + "guard-policies": { + "allow-only": { + "approval-labels": ${{ steps.parse-guard-vars.outputs.approval_labels }}, + "blocked-users": ${{ steps.parse-guard-vars.outputs.blocked_users }}, + "min-integrity": "none", + "repos": "all", + "trusted-users": ${{ steps.parse-guard-vars.outputs.trusted_users }} + } + } + }, + "safeoutputs": { + "type": "http", + "url": "http://localhost:$GH_AW_SAFE_OUTPUTS_PORT", + "headers": { + "Authorization": "$GH_AW_SAFE_OUTPUTS_API_KEY" + }, + "guard-policies": { + "write-sink": { + "accept": [ + "*" + ] + } + } + } + }, + "gateway": { + "port": $MCP_GATEWAY_PORT, + "domain": "${MCP_GATEWAY_DOMAIN}", + "apiKey": "${MCP_GATEWAY_API_KEY}", + "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" + } + } + GH_AW_MCP_CONFIG_8d05bb28961e7647_EOF + - name: Download activation artifact + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: activation + path: /tmp/gh-aw + - name: Clean git credentials + continue-on-error: true + run: bash "${RUNNER_TEMP}/gh-aw/actions/clean_git_credentials.sh" + - name: Execute Codex CLI + id: agentic_execution + run: | + set -o pipefail + touch /tmp/gh-aw/agent-step-summary.md + (umask 177 && touch /tmp/gh-aw/agent-stdio.log) + INSTRUCTION="$(cat "$GH_AW_PROMPT")" + mkdir -p "$CODEX_HOME/logs" + codex ${GH_AW_MODEL_AGENT_CODEX:+-c model="$GH_AW_MODEL_AGENT_CODEX" }exec -c web_search="disabled" -c fetch="disabled" --dangerously-bypass-approvals-and-sandbox --skip-git-repo-check "$INSTRUCTION" 2>&1 | tee /tmp/gh-aw/agent-stdio.log + env: + CODEX_API_KEY: ${{ secrets.CODEX_API_KEY || secrets.OPENAI_API_KEY }} + CODEX_HOME: /tmp/gh-aw/mcp-config + GH_AW_MCP_CONFIG: /tmp/gh-aw/mcp-config/config.toml + GH_AW_MODEL_AGENT_CODEX: gpt-5.3-codex + GH_AW_PHASE: agent + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} + GH_AW_VERSION: v0.68.3 + GITHUB_AW: true + GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + OPENAI_BASE_URL: https://api.zhizengzeng.com/v1 + RUST_LOG: trace,hyper_util=info,mio=info,reqwest=info,os_info=info,codex_otel=warn,codex_core=debug,ocodex_exec=debug + - name: Configure Git credentials + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + GITHUB_TOKEN: ${{ github.token }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + git config --global am.keepcr true + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Stop MCP Gateway + if: always() + continue-on-error: true + env: + MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }} + MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }} + GATEWAY_PID: ${{ steps.start-mcp-gateway.outputs.gateway-pid }} + run: | + bash "${RUNNER_TEMP}/gh-aw/actions/stop_mcp_gateway.sh" "$GATEWAY_PID" + - name: Redact secrets in logs + if: always() + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/redact_secrets.cjs'); + await main(); + env: + GH_AW_SECRET_NAMES: 'CODEX_API_KEY,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN,OPENAI_API_KEY' + SECRET_CODEX_API_KEY: ${{ secrets.CODEX_API_KEY }} + SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} + SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} + SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SECRET_OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + - name: Append agent step summary + if: always() + run: bash "${RUNNER_TEMP}/gh-aw/actions/append_agent_step_summary.sh" + - name: Copy Safe Outputs + if: always() + env: + GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} + run: | + mkdir -p /tmp/gh-aw + cp "$GH_AW_SAFE_OUTPUTS" /tmp/gh-aw/safeoutputs.jsonl 2>/dev/null || true + - name: Ingest agent output + id: collect_output + if: always() + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} + GH_AW_ALLOWED_DOMAINS: "172.30.0.1,api.openai.com,api.zhizengzeng.com,host.docker.internal,openai.com" + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_API_URL: ${{ github.api_url }} + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/collect_ndjson_output.cjs'); + await main(); + - name: Parse agent logs for step summary + if: always() + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_AGENT_OUTPUT: /tmp/gh-aw/agent-stdio.log + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_codex_log.cjs'); + await main(); + - name: Parse MCP Gateway logs for step summary + if: always() + id: parse-mcp-gateway + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_mcp_gateway_log.cjs'); + await main(); + - 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: Upload agent artifacts + if: always() + continue-on-error: true + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: agent + path: | + /tmp/gh-aw/aw-prompts/prompt.txt + /tmp/gh-aw/mcp-config/logs/ + /tmp/gh-aw/redacted-urls.log + /tmp/gh-aw/mcp-logs/ + /tmp/gh-aw/proxy-logs/ + !/tmp/gh-aw/proxy-logs/proxy-tls/ + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/agent/ + /tmp/gh-aw/github_rate_limits.jsonl + /tmp/gh-aw/safeoutputs.jsonl + /tmp/gh-aw/agent_output.json + /tmp/gh-aw/aw-*.patch + /tmp/gh-aw/aw-*.bundle + if-no-files-found: ignore + + conclusion: + needs: + - activation + - agent + - safe_outputs + if: > + always() && (needs.agent.result != 'skipped' || needs.activation.outputs.lockdown_check_failed == 'true' || + needs.activation.outputs.stale_lock_file_failed == 'true') + runs-on: ubuntu-slim + permissions: + contents: write + discussions: write + issues: write + pull-requests: write + concurrency: + group: "gh-aw-conclusion-auto-code" + cancel-in-progress: false + outputs: + incomplete_count: ${{ steps.report_incomplete.outputs.incomplete_count }} + noop_message: ${{ steps.noop.outputs.noop_message }} + tools_reported: ${{ steps.missing_tool.outputs.tools_reported }} + total_count: ${{ steps.missing_tool.outputs.total_count }} + steps: + - name: Setup Scripts + id: setup + uses: github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} + - name: Download agent output artifact + id: download-agent-output + continue-on-error: true + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: agent + path: /tmp/gh-aw/ + - name: Setup agent output environment variable + id: setup-agent-output-env + if: steps.download-agent-output.outcome == 'success' + run: | + mkdir -p /tmp/gh-aw/ + find "/tmp/gh-aw/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT" + - name: Process no-op messages + id: noop + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} + GH_AW_NOOP_MAX: "1" + GH_AW_WORKFLOW_NAME: "自动处理 Issue" + GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} + GH_AW_NOOP_REPORT_AS_ISSUE: "true" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_noop_message.cjs'); + await main(); + - name: Record missing tool + id: missing_tool + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + 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: "自动处理 Issue" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/missing_tool.cjs'); + await main(); + - name: Record incomplete + id: report_incomplete + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + 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: "自动处理 Issue" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/report_incomplete_handler.cjs'); + await main(); + - name: Handle agent failure + id: handle_agent_failure + if: always() + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "自动处理 Issue" + 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: "auto-code" + 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_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_STALE_LOCK_FILE_FAILED: ${{ needs.activation.outputs.stale_lock_file_failed }} + GH_AW_GROUP_REPORTS: "false" + GH_AW_FAILURE_REPORT_AS_ISSUE: "true" + GH_AW_TIMEOUT_MINUTES: "20" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_agent_failure.cjs'); + await main(); + + pre_activation: + runs-on: ubuntu-slim + outputs: + activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} + matched_command: '' + setup-trace-id: ${{ steps.setup.outputs.trace-id }} + steps: + - name: Setup Scripts + id: setup + uses: github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + - name: Check team membership for workflow + id: check_membership + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_REQUIRED_ROLES: "admin,maintainer,write" + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/check_membership.cjs'); + await main(); + + safe_outputs: + needs: + - activation + - agent + if: (!cancelled()) && needs.agent.result != 'skipped' + runs-on: ubuntu-slim + permissions: + contents: write + discussions: write + issues: write + pull-requests: write + timeout-minutes: 15 + env: + GH_AW_CALLER_WORKFLOW_ID: "${{ github.repository }}/auto-code" + GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens }} + GH_AW_ENGINE_ID: "codex" + GH_AW_ENGINE_MODEL: "gpt-5.3-codex" + GH_AW_WORKFLOW_ID: "auto-code" + GH_AW_WORKFLOW_NAME: "自动处理 Issue" + outputs: + code_push_failure_count: ${{ steps.process_safe_outputs.outputs.code_push_failure_count }} + code_push_failure_errors: ${{ steps.process_safe_outputs.outputs.code_push_failure_errors }} + comment_id: ${{ steps.process_safe_outputs.outputs.comment_id }} + comment_url: ${{ steps.process_safe_outputs.outputs.comment_url }} + create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }} + create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }} + created_pr_number: ${{ steps.process_safe_outputs.outputs.created_pr_number }} + created_pr_url: ${{ steps.process_safe_outputs.outputs.created_pr_url }} + process_safe_outputs_processed_count: ${{ steps.process_safe_outputs.outputs.processed_count }} + process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }} + steps: + - name: Setup Scripts + id: setup + uses: github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} + - name: Download agent output artifact + id: download-agent-output + continue-on-error: true + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: agent + path: /tmp/gh-aw/ + - name: Setup agent output environment variable + id: setup-agent-output-env + if: steps.download-agent-output.outcome == 'success' + run: | + mkdir -p /tmp/gh-aw/ + find "/tmp/gh-aw/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT" + - name: Download patch artifact + continue-on-error: true + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: agent + path: /tmp/gh-aw/ + - name: Checkout repository + if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + ref: develop + token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + persist-credentials: false + fetch-depth: 1 + - name: Configure Git credentials + if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + GIT_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + git config --global am.keepcr true + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${GIT_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Configure GH_HOST for enterprise compatibility + id: ghes-host-config + shell: bash + run: | + # Derive GH_HOST from GITHUB_SERVER_URL so the gh CLI targets the correct + # GitHub instance (GHES/GHEC). On github.com this is a harmless no-op. + GH_HOST="${GITHUB_SERVER_URL#https://}" + GH_HOST="${GH_HOST#http://}" + echo "GH_HOST=${GH_HOST}" >> "$GITHUB_ENV" + - name: Process Safe Outputs + id: process_safe_outputs + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} + GH_AW_ALLOWED_DOMAINS: "172.30.0.1,api.openai.com,api.zhizengzeng.com,host.docker.internal,openai.com" + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_API_URL: ${{ github.api_url }} + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":1},\"create_pull_request\":{\"base_branch\":\"develop\",\"max\":1,\"max_patch_size\":1024,\"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\",\"AGENTS.md\"],\"protected_path_prefixes\":[\".github/\",\".agents/\",\".codex/\"]},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"report_incomplete\":{}}" + GH_AW_CI_TRIGGER_TOKEN: ${{ secrets.GH_AW_CI_TRIGGER_TOKEN }} + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/safe_output_handler_manager.cjs'); + await main(); + - name: Upload Safe Outputs Items + if: always() + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: safe-outputs-items + path: | + /tmp/gh-aw/safe-output-items.jsonl + /tmp/gh-aw/temporary-id-map.json + if-no-files-found: ignore + diff --git a/.github/workflows/auto-code.md b/.github/workflows/auto-code.md new file mode 100644 index 00000000..205c22f6 --- /dev/null +++ b/.github/workflows/auto-code.md @@ -0,0 +1,87 @@ +--- +on: + issues: + types: [labeled] + +engine: + id: codex + model: gpt-5.3-codex + env: + OPENAI_BASE_URL: "https://api.zhizengzeng.com/v1" + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + +network: + allowed: + - api.zhizengzeng.com + +sandbox: + agent: false + +strict: false + +tools: + github: + min-integrity: none + +permissions: + contents: read + issues: read + pull-requests: read + +safe-outputs: + threat-detection: false + create-pull-request: + base-branch: develop + add-comment: + max: 1 +--- + +# 自动处理 Issue + +当 Issue 被打上 `bug` 或 `enhancement` 标签时触发。其他标签直接退出,不做任何操作。 + +## 判断任务类型 + +读取 Issue #${{ github.event.issue.number }} 当前的标签: +- 如果包含 `bug` 标签 → 执行【Bug 修复流程】 +- 如果包含 `enhancement` 标签 → 执行【新功能开发流程】 +- 其他情况 → 直接退出 + +--- + +## Bug 修复流程 + +1. 阅读 Issue 的完整标题和正文,理解问题现象 +2. 浏览仓库代码,定位问题所在的文件和函数 +3. 分析根本原因 +4. 实现修复方案,注意: + - 保持与现有代码风格一致 + - 只修改必要的部分,不做无关改动 +5. 创建 Pull Request,标题格式:`fix: `,描述中说明: + - 问题根因 + - 修复方式 + - 如何验证 +6. 在原 Issue 下用中文回复,说明已提交 PR 及修复思路 + +如果问题过于复杂或信息不足,在 Issue 下用中文说明原因,不创建 PR。 + +--- + +## 新功能开发流程 + +1. 阅读 Issue 的完整标题和正文,理解需求目标 +2. 浏览仓库现有代码结构,找到最相关的模块和文件 +3. 制定实现方案: + - 需要新增哪些文件或函数 + - 需要修改哪些现有文件 +4. 按方案实现代码,注意: + - 保持与现有代码风格一致 + - 新增函数/类需要添加注释 + - 如果涉及接口变更,同步更新相关调用方 +5. 创建 Pull Request,标题格式:`feat: `,描述中说明: + - 实现了哪些功能 + - 涉及哪些文件改动 + - 如何验证/测试 +6. 在原 Issue 下用中文回复,说明已提交 PR、实现思路和测试建议 + +如果需求描述不清晰或实现风险过大,在 Issue 下用中文说明原因,不创建 PR。 \ No newline at end of file diff --git a/.github/workflows/auto-fix.md b/.github/workflows/auto-fix.md deleted file mode 100644 index ab3cf86e..00000000 --- a/.github/workflows/auto-fix.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -on: - issues: - types: [labeled] - -engine: - id: codex - model: gpt-5.4 - env: - OPENAI_BASE_URL: "https://api.zhizengzeng.com/v1" - OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - -network: - allowed: - - api.zhizengzeng.com - -permissions: - contents: read - issues: read - pull-requests: read - -safe-outputs: - create-pull-request: - base-branch: main - add-comment: - max: 1 ---- - -# 自动修复 Bug - -当 Issue 被打上 `bug` 标签时触发。 - -## 任务 - -1. 阅读 Issue #${{ github.event.issue.number }} 的完整内容 -2. 在仓库代码中定位问题所在的文件和函数 -3. 分析根本原因 -4. 实现修复方案,注意: - - 保持代码风格与现有代码一致 - - 只修改必要的部分,不做无关改动 - - 如果涉及多个文件,逐一修改 -5. 创建一个 Pull Request,标题格式:`fix: ` -6. 在原 Issue 下回复一条中文评论,说明已提交 PR 及修复思路 - -如果问题过于复杂或信息不足,在 Issue 下用中文说明原因,不要创建 PR。 \ No newline at end of file diff --git a/.github/workflows/issue-triage.lock.yml b/.github/workflows/issue-triage.lock.yml index 5d5c62e6..3aec2247 100644 --- a/.github/workflows/issue-triage.lock.yml +++ b/.github/workflows/issue-triage.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"c77cf1c7a513394cceedc693f93692d1f0017c13c2fce6c6c81b2363245aebb2","compiler_version":"v0.68.3","agent_id":"codex","agent_model":"gpt-5.3-codex"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"c0c5f2c83f233a2b2d7053d2e39295f1b1e4c15c8d47f623444564b774958447","compiler_version":"v0.68.3","agent_id":"codex","agent_model":"gpt-5.3-codex"} # gh-aw-manifest: {"version":1,"secrets":["CODEX_API_KEY","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/setup-node","sha":"53b83947a5a98c8d113130e565377fae1a50d02f","version":"v6.3.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"ba90f2186d7ad780ec640f364005fa24e797b360","version":"v0.68.3"}],"containers":[{"image":"ghcr.io/github/github-mcp-server:v0.32.0"},{"image":"node:lts-alpine"}]} # ___ _ _ # / _ \ | | (_) @@ -171,14 +171,14 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_74dabe01380845dd_EOF' + cat << 'GH_AW_PROMPT_5c03d90267ba9511_EOF' - GH_AW_PROMPT_74dabe01380845dd_EOF + GH_AW_PROMPT_5c03d90267ba9511_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_74dabe01380845dd_EOF' + cat << 'GH_AW_PROMPT_5c03d90267ba9511_EOF' Tools: add_comment, add_labels, missing_tool, missing_data, noop @@ -210,12 +210,12 @@ jobs: {{/if}} - GH_AW_PROMPT_74dabe01380845dd_EOF + GH_AW_PROMPT_5c03d90267ba9511_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_74dabe01380845dd_EOF' + cat << 'GH_AW_PROMPT_5c03d90267ba9511_EOF' {{#runtime-import .github/workflows/issue-triage.md}} - GH_AW_PROMPT_74dabe01380845dd_EOF + GH_AW_PROMPT_5c03d90267ba9511_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 @@ -381,9 +381,9 @@ jobs: mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs - cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_2caa0dae86f4499b_EOF' + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_50d51e89b299db31_EOF' {"add_comment":{"max":1},"add_labels":{"allowed":["bug","feature","enhancement","documentation","question","duplicate","invalid"]},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} - GH_AW_SAFE_OUTPUTS_CONFIG_2caa0dae86f4499b_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_50d51e89b299db31_EOF - name: Write Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -584,7 +584,7 @@ jobs: export GH_AW_ENGINE="codex" export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.2.19' - cat > /tmp/gh-aw/mcp-config/config.toml << GH_AW_MCP_CONFIG_70937a147e264612_EOF + cat > /tmp/gh-aw/mcp-config/config.toml << GH_AW_MCP_CONFIG_7c4481f6a1c5dec4_EOF [history] persistence = "none" @@ -611,10 +611,10 @@ jobs: [mcp_servers.safeoutputs."guard-policies".write-sink] accept = ["*"] - GH_AW_MCP_CONFIG_70937a147e264612_EOF + GH_AW_MCP_CONFIG_7c4481f6a1c5dec4_EOF # Generate JSON config for MCP gateway - cat << GH_AW_MCP_CONFIG_70937a147e264612_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" + cat << GH_AW_MCP_CONFIG_7c4481f6a1c5dec4_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" { "mcpServers": { "github": { @@ -657,7 +657,7 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_70937a147e264612_EOF + GH_AW_MCP_CONFIG_7c4481f6a1c5dec4_EOF - name: Download activation artifact uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: diff --git a/.github/workflows/issue-triage.md b/.github/workflows/issue-triage.md index 7c6cfb4c..c040be9d 100644 --- a/.github/workflows/issue-triage.md +++ b/.github/workflows/issue-triage.md @@ -16,7 +16,6 @@ network: sandbox: agent: false - strict: false tools: @@ -63,5 +62,5 @@ safe-outputs: - 感谢用户提交 Issue - 说明你打的标签和原因 - 如果是 bug,请用户补充:复现步骤、环境信息、错误日志 - - 如果是 question,尝试根据仓库代码给出初步解答 + - 如果是 question,尝试根据仓库代码和文档给出初步解答 - 预计处理时间(普通问题 3 个工作日内) \ No newline at end of file From 548dfa2b2abfd2d5c576e4e1f8f3d047950c2515 Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Mon, 27 Apr 2026 17:18:05 +0800 Subject: [PATCH 07/59] refactor: merge auto-fix and auto-feature into auto-code --- .github/workflows/auto-fix.lock.yml | 1296 --------------------------- 1 file changed, 1296 deletions(-) delete mode 100644 .github/workflows/auto-fix.lock.yml diff --git a/.github/workflows/auto-fix.lock.yml b/.github/workflows/auto-fix.lock.yml deleted file mode 100644 index 7711b118..00000000 --- a/.github/workflows/auto-fix.lock.yml +++ /dev/null @@ -1,1296 +0,0 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"d398b5a11e1f028613163987ae25df914efde30b5bf11a95ca2b9fa1d2d1c02b","compiler_version":"v0.68.3","strict":true,"agent_id":"codex","agent_model":"gpt-5.4"} -# gh-aw-manifest: {"version":1,"secrets":["CODEX_API_KEY","GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/setup-node","sha":"53b83947a5a98c8d113130e565377fae1a50d02f","version":"v6.3.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"ba90f2186d7ad780ec640f364005fa24e797b360","version":"v0.68.3"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.20"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.2.19"},{"image":"ghcr.io/github/github-mcp-server:v0.32.0"},{"image":"node:lts-alpine"}]} -# ___ _ _ -# / _ \ | | (_) -# | |_| | __ _ ___ _ __ | |_ _ ___ -# | _ |/ _` |/ _ \ '_ \| __| |/ __| -# | | | | (_| | __/ | | | |_| | (__ -# \_| |_/\__, |\___|_| |_|\__|_|\___| -# __/ | -# _ _ |___/ -# | | | | / _| | -# | | | | ___ _ __ _ __| |_| | _____ ____ -# | |/\| |/ _ \ '__| |/ /| _| |/ _ \ \ /\ / / ___| -# \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ -# \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ -# -# This file was automatically generated by gh-aw (v0.68.3). DO NOT EDIT. -# -# To update this file, edit the corresponding .md file and run: -# gh aw compile -# Not all edits will cause changes to this file. -# -# For more information: https://github.github.com/gh-aw/introduction/overview/ -# -# -# Secrets used: -# - CODEX_API_KEY -# - GH_AW_CI_TRIGGER_TOKEN -# - GH_AW_GITHUB_MCP_SERVER_TOKEN -# - GH_AW_GITHUB_TOKEN -# - GITHUB_TOKEN -# - OPENAI_API_KEY -# -# Custom actions used: -# - actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 -# - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 -# - actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 -# - actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 -# - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 -# - github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 -# -# Container images used: -# - ghcr.io/github/gh-aw-firewall/agent:0.25.20 -# - ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20 -# - ghcr.io/github/gh-aw-firewall/squid:0.25.20 -# - ghcr.io/github/gh-aw-mcpg:v0.2.19 -# - ghcr.io/github/github-mcp-server:v0.32.0 -# - node:lts-alpine - -name: "自动修复 Bug" -"on": - issues: - types: - - labeled - -permissions: {} - -concurrency: - group: "gh-aw-${{ github.workflow }}-${{ github.event.issue.number || github.run_id }}" - -run-name: "自动修复 Bug" - -jobs: - activation: - needs: pre_activation - if: needs.pre_activation.outputs.activated == 'true' - runs-on: ubuntu-slim - permissions: - actions: read - contents: read - outputs: - body: ${{ steps.sanitized.outputs.body }} - comment_id: "" - comment_repo: "" - lockdown_check_failed: ${{ steps.generate_aw_info.outputs.lockdown_check_failed == 'true' }} - model: ${{ steps.generate_aw_info.outputs.model }} - secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} - setup-trace-id: ${{ steps.setup.outputs.trace-id }} - stale_lock_file_failed: ${{ steps.check-lock-file.outputs.stale_lock_file_failed == 'true' }} - text: ${{ steps.sanitized.outputs.text }} - title: ${{ steps.sanitized.outputs.title }} - steps: - - name: Setup Scripts - id: setup - uses: github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 - with: - destination: ${{ runner.temp }}/gh-aw/actions - job-name: ${{ github.job }} - trace-id: ${{ needs.pre_activation.outputs.setup-trace-id }} - - 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: "gpt-5.4" - GH_AW_INFO_VERSION: "0.118.0" - GH_AW_INFO_AGENT_VERSION: "0.118.0" - GH_AW_INFO_CLI_VERSION: "v0.68.3" - GH_AW_INFO_WORKFLOW_NAME: "自动修复 Bug" - GH_AW_INFO_EXPERIMENTAL: "false" - GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true" - GH_AW_INFO_STAGED: "false" - GH_AW_INFO_ALLOWED_DOMAINS: '["api.zhizengzeng.com"]' - GH_AW_INFO_FIREWALL_ENABLED: "true" - GH_AW_INFO_AWF_VERSION: "v0.25.20" - GH_AW_INFO_AWMG_VERSION: "" - GH_AW_INFO_FIREWALL_TYPE: "squid" - GH_AW_COMPILED_STRICT: "true" - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 - with: - script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/generate_aw_info.cjs'); - await main(core, context); - - name: Validate CODEX_API_KEY or OPENAI_API_KEY secret - id: validate-secret - run: bash "${RUNNER_TEMP}/gh-aw/actions/validate_multi_secret.sh" CODEX_API_KEY OPENAI_API_KEY Codex https://github.github.com/gh-aw/reference/engines/#openai-codex - env: - CODEX_API_KEY: ${{ secrets.CODEX_API_KEY }} - OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - - name: Checkout .github and .agents folders - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - persist-credentials: false - sparse-checkout: | - .github - .agents - sparse-checkout-cone-mode: true - fetch-depth: 1 - - name: Check workflow lock file - id: check-lock-file - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 - env: - GH_AW_WORKFLOW_FILE: "auto-fix.lock.yml" - GH_AW_CONTEXT_WORKFLOW_REF: "${{ github.workflow_ref }}" - with: - script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/check_workflow_timestamp_api.cjs'); - await main(); - - name: Check compile-agentic version - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 - env: - GH_AW_COMPILED_VERSION: "v0.68.3" - with: - script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/check_version_updates.cjs'); - await main(); - - name: Compute current body text - id: sanitized - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 - with: - script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/compute_text.cjs'); - await main(); - - name: Create prompt with built-in context - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GH_AW_SAFE_OUTPUTS: ${{ runner.temp }}/gh-aw/safeoutputs/outputs.jsonl - GH_AW_GITHUB_ACTOR: ${{ github.actor }} - GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} - GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} - GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} - GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} - GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} - GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} - GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} - # poutine:ignore untrusted_checkout_exec - run: | - bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" - { - cat << 'GH_AW_PROMPT_59531e2cb7ae6a95_EOF' - - GH_AW_PROMPT_59531e2cb7ae6a95_EOF - cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" - cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" - cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" - cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_59531e2cb7ae6a95_EOF' - - Tools: add_comment, create_pull_request, missing_tool, missing_data, noop - GH_AW_PROMPT_59531e2cb7ae6a95_EOF - cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_create_pull_request.md" - cat << 'GH_AW_PROMPT_59531e2cb7ae6a95_EOF' - - - The following GitHub context information is available for this workflow: - {{#if __GH_AW_GITHUB_ACTOR__ }} - - **actor**: __GH_AW_GITHUB_ACTOR__ - {{/if}} - {{#if __GH_AW_GITHUB_REPOSITORY__ }} - - **repository**: __GH_AW_GITHUB_REPOSITORY__ - {{/if}} - {{#if __GH_AW_GITHUB_WORKSPACE__ }} - - **workspace**: __GH_AW_GITHUB_WORKSPACE__ - {{/if}} - {{#if __GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ }} - - **issue-number**: #__GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ - {{/if}} - {{#if __GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ }} - - **discussion-number**: #__GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ - {{/if}} - {{#if __GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ }} - - **pull-request-number**: #__GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ - {{/if}} - {{#if __GH_AW_GITHUB_EVENT_COMMENT_ID__ }} - - **comment-id**: __GH_AW_GITHUB_EVENT_COMMENT_ID__ - {{/if}} - {{#if __GH_AW_GITHUB_RUN_ID__ }} - - **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__ - {{/if}} - - - GH_AW_PROMPT_59531e2cb7ae6a95_EOF - cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_59531e2cb7ae6a95_EOF' - - {{#runtime-import .github/workflows/auto-fix.md}} - GH_AW_PROMPT_59531e2cb7ae6a95_EOF - } > "$GH_AW_PROMPT" - - name: Interpolate variables and render templates - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} - with: - script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/interpolate_prompt.cjs'); - await main(); - - name: Substitute placeholders - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GH_AW_GITHUB_ACTOR: ${{ github.actor }} - GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} - GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} - GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} - GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} - GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} - GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} - GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} - GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: ${{ needs.pre_activation.outputs.activated }} - with: - script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io, getOctokit); - - const substitutePlaceholders = require('${{ runner.temp }}/gh-aw/actions/substitute_placeholders.cjs'); - - // Call the substitution function - return await substitutePlaceholders({ - file: process.env.GH_AW_PROMPT, - substitutions: { - GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR, - GH_AW_GITHUB_EVENT_COMMENT_ID: process.env.GH_AW_GITHUB_EVENT_COMMENT_ID, - GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: process.env.GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER, - GH_AW_GITHUB_EVENT_ISSUE_NUMBER: process.env.GH_AW_GITHUB_EVENT_ISSUE_NUMBER, - GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: process.env.GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER, - GH_AW_GITHUB_REPOSITORY: process.env.GH_AW_GITHUB_REPOSITORY, - GH_AW_GITHUB_RUN_ID: process.env.GH_AW_GITHUB_RUN_ID, - GH_AW_GITHUB_WORKSPACE: process.env.GH_AW_GITHUB_WORKSPACE, - GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: process.env.GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED - } - }); - - name: Validate prompt placeholders - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - # poutine:ignore untrusted_checkout_exec - run: bash "${RUNNER_TEMP}/gh-aw/actions/validate_prompt_placeholders.sh" - - name: Print prompt - env: - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - # poutine:ignore untrusted_checkout_exec - run: bash "${RUNNER_TEMP}/gh-aw/actions/print_prompt_summary.sh" - - name: Upload activation artifact - if: success() - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: activation - path: | - /tmp/gh-aw/aw_info.json - /tmp/gh-aw/aw-prompts/prompt.txt - /tmp/gh-aw/github_rate_limits.jsonl - if-no-files-found: ignore - retention-days: 1 - - agent: - needs: activation - runs-on: ubuntu-latest - permissions: - contents: read - issues: read - pull-requests: read - env: - DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} - GH_AW_ASSETS_ALLOWED_EXTS: "" - GH_AW_ASSETS_BRANCH: "" - GH_AW_ASSETS_MAX_SIZE_KB: 0 - GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs - GH_AW_WORKFLOW_ID_SANITIZED: autofix - outputs: - checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} - effective_tokens: ${{ steps.parse-mcp-gateway.outputs.effective_tokens }} - has_patch: ${{ steps.collect_output.outputs.has_patch }} - model: ${{ needs.activation.outputs.model }} - output: ${{ steps.collect_output.outputs.output }} - output_types: ${{ steps.collect_output.outputs.output_types }} - setup-trace-id: ${{ steps.setup.outputs.trace-id }} - steps: - - name: Setup Scripts - id: setup - uses: github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 - with: - destination: ${{ runner.temp }}/gh-aw/actions - job-name: ${{ github.job }} - trace-id: ${{ needs.activation.outputs.setup-trace-id }} - - name: Set runtime paths - id: set-runtime-paths - run: | - { - 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: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - persist-credentials: false - - 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: Configure Git credentials - env: - REPO_NAME: ${{ github.repository }} - SERVER_URL: ${{ github.server_url }} - GITHUB_TOKEN: ${{ github.token }} - run: | - git config --global user.email "github-actions[bot]@users.noreply.github.com" - git config --global user.name "github-actions[bot]" - git config --global am.keepcr true - # Re-authenticate git with GitHub token - SERVER_URL_STRIPPED="${SERVER_URL#https://}" - git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" - echo "Git configured with standard GitHub Actions identity" - - name: Checkout PR branch - id: checkout-pr - if: | - github.event.pull_request || github.event.issue.pull_request - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 - env: - GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - with: - github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/checkout_pr_branch.cjs'); - await main(); - - name: Setup Node.js - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 - with: - node-version: '24' - package-manager-cache: false - - name: Install Codex CLI - run: npm install --ignore-scripts -g @openai/codex@0.118.0 - - name: Install AWF binary - run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.25.20 - - name: Determine automatic lockdown mode for GitHub MCP Server - id: determine-automatic-lockdown - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 - env: - GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} - GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} - with: - script: | - const determineAutomaticLockdown = require('${{ runner.temp }}/gh-aw/actions/determine_automatic_lockdown.cjs'); - await determineAutomaticLockdown(github, context, core); - - name: Download container images - run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.25.20 ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20 ghcr.io/github/gh-aw-firewall/squid:0.25.20 ghcr.io/github/gh-aw-mcpg:v0.2.19 ghcr.io/github/github-mcp-server:v0.32.0 node:lts-alpine - - name: Write Safe Outputs Config - run: | - mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" - mkdir -p /tmp/gh-aw/safeoutputs - mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs - cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_0ff619be0f4cb7e0_EOF' - {"add_comment":{"max":1},"create_pull_request":{"base_branch":"main","max":1,"max_patch_size":1024,"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"],"protected_path_prefixes":[".github/",".agents/"]},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} - GH_AW_SAFE_OUTPUTS_CONFIG_0ff619be0f4cb7e0_EOF - - name: Write Safe Outputs Tools - env: - GH_AW_TOOLS_META_JSON: | - { - "description_suffixes": { - "add_comment": " CONSTRAINTS: Maximum 1 comment(s) can be added. Supports reply_to_id for discussion threading.", - "create_pull_request": " CONSTRAINTS: Maximum 1 pull request(s) can be created." - }, - "repo_params": {}, - "dynamic_tools": [] - } - GH_AW_VALIDATION_JSON: | - { - "add_comment": { - "defaultMax": 1, - "fields": { - "body": { - "required": true, - "type": "string", - "sanitize": true, - "maxLength": 65000 - }, - "item_number": { - "issueOrPRNumber": true - }, - "reply_to_id": { - "type": "string", - "maxLength": 256 - }, - "repo": { - "type": "string", - "maxLength": 256 - } - } - }, - "create_pull_request": { - "defaultMax": 1, - "fields": { - "body": { - "required": true, - "type": "string", - "sanitize": true, - "maxLength": 65000 - }, - "branch": { - "required": true, - "type": "string", - "sanitize": true, - "maxLength": 256 - }, - "draft": { - "type": "boolean" - }, - "labels": { - "type": "array", - "itemType": "string", - "itemSanitize": true, - "itemMaxLength": 128 - }, - "repo": { - "type": "string", - "maxLength": 256 - }, - "title": { - "required": true, - "type": "string", - "sanitize": true, - "maxLength": 128 - } - } - }, - "missing_data": { - "defaultMax": 20, - "fields": { - "alternatives": { - "type": "string", - "sanitize": true, - "maxLength": 256 - }, - "context": { - "type": "string", - "sanitize": true, - "maxLength": 256 - }, - "data_type": { - "type": "string", - "sanitize": true, - "maxLength": 128 - }, - "reason": { - "type": "string", - "sanitize": true, - "maxLength": 256 - } - } - }, - "missing_tool": { - "defaultMax": 20, - "fields": { - "alternatives": { - "type": "string", - "sanitize": true, - "maxLength": 512 - }, - "reason": { - "required": true, - "type": "string", - "sanitize": true, - "maxLength": 256 - }, - "tool": { - "type": "string", - "sanitize": true, - "maxLength": 128 - } - } - }, - "noop": { - "defaultMax": 1, - "fields": { - "message": { - "required": true, - "type": "string", - "sanitize": true, - "maxLength": 65000 - } - } - }, - "report_incomplete": { - "defaultMax": 5, - "fields": { - "details": { - "type": "string", - "sanitize": true, - "maxLength": 65000 - }, - "reason": { - "required": true, - "type": "string", - "sanitize": true, - "maxLength": 1024 - } - } - } - } - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 - with: - script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/generate_safe_outputs_tools.cjs'); - await main(); - - name: Generate Safe Outputs MCP Server Config - id: safe-outputs-config - run: | - # Generate a secure random API key (360 bits of entropy, 40+ chars) - # Mask immediately to prevent timing vulnerabilities - API_KEY=$(openssl rand -base64 45 | tr -d '/+=') - echo "::add-mask::${API_KEY}" - - PORT=3001 - - # Set outputs for next steps - { - echo "safe_outputs_api_key=${API_KEY}" - echo "safe_outputs_port=${PORT}" - } >> "$GITHUB_OUTPUT" - - echo "Safe Outputs MCP server will run on port ${PORT}" - - - name: Start Safe Outputs MCP HTTP Server - id: safe-outputs-start - env: - DEBUG: '*' - GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-config.outputs.safe_outputs_port }} - GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-config.outputs.safe_outputs_api_key }} - GH_AW_SAFE_OUTPUTS_TOOLS_PATH: ${{ runner.temp }}/gh-aw/safeoutputs/tools.json - GH_AW_SAFE_OUTPUTS_CONFIG_PATH: ${{ runner.temp }}/gh-aw/safeoutputs/config.json - GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs - run: | - # Environment variables are set above to prevent template injection - export DEBUG - export GH_AW_SAFE_OUTPUTS - export GH_AW_SAFE_OUTPUTS_PORT - export GH_AW_SAFE_OUTPUTS_API_KEY - export GH_AW_SAFE_OUTPUTS_TOOLS_PATH - export GH_AW_SAFE_OUTPUTS_CONFIG_PATH - export GH_AW_MCP_LOG_DIR - - bash "${RUNNER_TEMP}/gh-aw/actions/start_safe_outputs_server.sh" - - - name: Start MCP Gateway - id: start-mcp-gateway - env: - GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} - GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-start.outputs.api_key }} - GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-start.outputs.port }} - GITHUB_MCP_GUARD_MIN_INTEGRITY: ${{ steps.determine-automatic-lockdown.outputs.min_integrity }} - GITHUB_MCP_GUARD_REPOS: ${{ steps.determine-automatic-lockdown.outputs.repos }} - GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - run: | - set -eo pipefail - mkdir -p /tmp/gh-aw/mcp-config - - # Export gateway environment variables for MCP config and gateway script - export MCP_GATEWAY_PORT="80" - export MCP_GATEWAY_DOMAIN="host.docker.internal" - MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=') - echo "::add-mask::${MCP_GATEWAY_API_KEY}" - export MCP_GATEWAY_API_KEY - export MCP_GATEWAY_PAYLOAD_DIR="/tmp/gh-aw/mcp-payloads" - mkdir -p "${MCP_GATEWAY_PAYLOAD_DIR}" - export MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD="524288" - export DEBUG="*" - - export GH_AW_ENGINE="codex" - export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.2.19' - - cat > /tmp/gh-aw/mcp-config/config.toml << GH_AW_MCP_CONFIG_97f3a72e70f4fa1c_EOF - [history] - persistence = "none" - - [shell_environment_policy] - inherit = "core" - include_only = ["CODEX_API_KEY", "GH_AW_ASSETS_ALLOWED_EXTS", "GH_AW_ASSETS_BRANCH", "GH_AW_ASSETS_MAX_SIZE_KB", "GH_AW_SAFE_OUTPUTS", "GITHUB_PERSONAL_ACCESS_TOKEN", "GITHUB_REPOSITORY", "GITHUB_SERVER_URL", "HOME", "OPENAI_API_KEY", "PATH"] - - [mcp_servers.github] - user_agent = "bug" - startup_timeout_sec = 120 - tool_timeout_sec = 60 - container = "ghcr.io/github/github-mcp-server:v0.32.0" - env = { "GITHUB_HOST" = "$GITHUB_SERVER_URL", "GITHUB_PERSONAL_ACCESS_TOKEN" = "$GH_AW_GITHUB_TOKEN", "GITHUB_READ_ONLY" = "1", "GITHUB_TOOLSETS" = "context,repos,issues,pull_requests" } - env_vars = ["GITHUB_HOST", "GITHUB_PERSONAL_ACCESS_TOKEN", "GITHUB_READ_ONLY", "GITHUB_TOOLSETS"] - - [mcp_servers.safeoutputs] - type = "http" - url = "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT" - - [mcp_servers.safeoutputs.headers] - Authorization = "$GH_AW_SAFE_OUTPUTS_API_KEY" - - [mcp_servers.safeoutputs."guard-policies"] - - [mcp_servers.safeoutputs."guard-policies".write-sink] - accept = ["*"] - GH_AW_MCP_CONFIG_97f3a72e70f4fa1c_EOF - - # Generate JSON config for MCP gateway - cat << GH_AW_MCP_CONFIG_97f3a72e70f4fa1c_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" - { - "mcpServers": { - "github": { - "container": "ghcr.io/github/github-mcp-server:v0.32.0", - "env": { - "GITHUB_HOST": "$GITHUB_SERVER_URL", - "GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_MCP_SERVER_TOKEN", - "GITHUB_READ_ONLY": "1", - "GITHUB_TOOLSETS": "context,repos,issues,pull_requests" - }, - "guard-policies": { - "allow-only": { - "min-integrity": "$GITHUB_MCP_GUARD_MIN_INTEGRITY", - "repos": "$GITHUB_MCP_GUARD_REPOS" - } - } - }, - "safeoutputs": { - "type": "http", - "url": "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT", - "headers": { - "Authorization": "$GH_AW_SAFE_OUTPUTS_API_KEY" - }, - "guard-policies": { - "write-sink": { - "accept": [ - "*" - ] - } - } - } - }, - "gateway": { - "port": $MCP_GATEWAY_PORT, - "domain": "${MCP_GATEWAY_DOMAIN}", - "apiKey": "${MCP_GATEWAY_API_KEY}", - "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" - } - } - GH_AW_MCP_CONFIG_97f3a72e70f4fa1c_EOF - - name: Download activation artifact - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - with: - name: activation - path: /tmp/gh-aw - - name: Clean git credentials - continue-on-error: true - run: bash "${RUNNER_TEMP}/gh-aw/actions/clean_git_credentials.sh" - - name: Execute Codex CLI - id: agentic_execution - run: | - set -o pipefail - mkdir -p "$CODEX_HOME/logs" && touch /tmp/gh-aw/agent-step-summary.md - (umask 177 && touch /tmp/gh-aw/agent-stdio.log) - # shellcheck disable=SC1003 - sudo -E awf --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" --env-all --exclude-env CODEX_API_KEY --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --exclude-env OPENAI_API_KEY --allow-domains 172.30.0.1,api.openai.com,api.zhizengzeng.com,host.docker.internal,openai.com --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --image-tag 0.25.20 --skip-pull --enable-api-proxy --openai-api-target api.zhizengzeng.com --openai-api-base-path /v1 \ - -- /bin/bash -c 'export PATH="$(find /opt/hostedtoolcache -maxdepth 4 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true && INSTRUCTION="$(cat /tmp/gh-aw/aw-prompts/prompt.txt)" && codex ${GH_AW_MODEL_AGENT_CODEX:+-c model="$GH_AW_MODEL_AGENT_CODEX" }exec -c web_search="disabled" -c fetch="disabled" --dangerously-bypass-approvals-and-sandbox --skip-git-repo-check "$INSTRUCTION"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log - env: - CODEX_API_KEY: ${{ secrets.CODEX_API_KEY || secrets.OPENAI_API_KEY }} - CODEX_HOME: /tmp/gh-aw/mcp-config - GH_AW_MCP_CONFIG: /tmp/gh-aw/mcp-config/config.toml - GH_AW_MODEL_AGENT_CODEX: gpt-5.4 - 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: v0.68.3 - GITHUB_AW: true - GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md - GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com - GIT_AUTHOR_NAME: github-actions[bot] - GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com - GIT_COMMITTER_NAME: github-actions[bot] - OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - OPENAI_BASE_URL: https://api.zhizengzeng.com/v1 - RUST_LOG: trace,hyper_util=info,mio=info,reqwest=info,os_info=info,codex_otel=warn,codex_core=debug,ocodex_exec=debug - - name: Configure Git credentials - env: - REPO_NAME: ${{ github.repository }} - SERVER_URL: ${{ github.server_url }} - GITHUB_TOKEN: ${{ github.token }} - run: | - git config --global user.email "github-actions[bot]@users.noreply.github.com" - git config --global user.name "github-actions[bot]" - git config --global am.keepcr true - # Re-authenticate git with GitHub token - SERVER_URL_STRIPPED="${SERVER_URL#https://}" - git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" - echo "Git configured with standard GitHub Actions identity" - - name: Stop MCP Gateway - if: always() - continue-on-error: true - env: - MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }} - MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }} - GATEWAY_PID: ${{ steps.start-mcp-gateway.outputs.gateway-pid }} - run: | - bash "${RUNNER_TEMP}/gh-aw/actions/stop_mcp_gateway.sh" "$GATEWAY_PID" - - name: Redact secrets in logs - if: always() - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 - with: - script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/redact_secrets.cjs'); - await main(); - env: - GH_AW_SECRET_NAMES: 'CODEX_API_KEY,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN,OPENAI_API_KEY' - SECRET_CODEX_API_KEY: ${{ secrets.CODEX_API_KEY }} - SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} - SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} - SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SECRET_OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - - name: Append agent step summary - if: always() - run: bash "${RUNNER_TEMP}/gh-aw/actions/append_agent_step_summary.sh" - - name: Copy Safe Outputs - if: always() - env: - GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} - run: | - mkdir -p /tmp/gh-aw - cp "$GH_AW_SAFE_OUTPUTS" /tmp/gh-aw/safeoutputs.jsonl 2>/dev/null || true - - name: Ingest agent output - id: collect_output - if: always() - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 - env: - GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} - GH_AW_ALLOWED_DOMAINS: "172.30.0.1,api.openai.com,api.zhizengzeng.com,host.docker.internal,openai.com" - GITHUB_SERVER_URL: ${{ github.server_url }} - GITHUB_API_URL: ${{ github.api_url }} - with: - script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/collect_ndjson_output.cjs'); - await main(); - - name: Parse agent logs for step summary - if: always() - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 - env: - GH_AW_AGENT_OUTPUT: /tmp/gh-aw/agent-stdio.log - with: - script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_codex_log.cjs'); - await main(); - - name: Parse MCP Gateway logs for step summary - if: always() - id: parse-mcp-gateway - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 - with: - script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_mcp_gateway_log.cjs'); - await main(); - - name: Print firewall logs - if: always() - continue-on-error: true - env: - AWF_LOGS_DIR: /tmp/gh-aw/sandbox/firewall/logs - run: | - # Fix permissions on firewall logs so they can be uploaded as artifacts - # AWF runs with sudo, creating files owned by root - sudo chmod -R a+r /tmp/gh-aw/sandbox/firewall/logs 2>/dev/null || true - # Only run awf logs summary if awf command exists (it may not be installed if workflow failed before install step) - if command -v awf &> /dev/null; then - awf logs summary | tee -a "$GITHUB_STEP_SUMMARY" - else - echo 'AWF binary not installed, skipping firewall log summary' - fi - - name: Parse token usage for step summary - if: always() - continue-on-error: true - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 - with: - script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_token_usage.cjs'); - await main(); - - 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: Upload agent artifacts - if: always() - continue-on-error: true - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: agent - path: | - /tmp/gh-aw/aw-prompts/prompt.txt - /tmp/gh-aw/mcp-config/logs/ - /tmp/gh-aw/redacted-urls.log - /tmp/gh-aw/mcp-logs/ - /tmp/gh-aw/agent_usage.json - /tmp/gh-aw/agent-stdio.log - /tmp/gh-aw/agent/ - /tmp/gh-aw/github_rate_limits.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/sandbox/firewall/logs/ - /tmp/gh-aw/sandbox/firewall/audit/ - if-no-files-found: ignore - - conclusion: - needs: - - activation - - agent - - detection - - safe_outputs - if: > - always() && (needs.agent.result != 'skipped' || needs.activation.outputs.lockdown_check_failed == 'true' || - needs.activation.outputs.stale_lock_file_failed == 'true') - runs-on: ubuntu-slim - permissions: - contents: write - discussions: write - issues: write - pull-requests: write - concurrency: - group: "gh-aw-conclusion-auto-fix" - cancel-in-progress: false - outputs: - incomplete_count: ${{ steps.report_incomplete.outputs.incomplete_count }} - noop_message: ${{ steps.noop.outputs.noop_message }} - tools_reported: ${{ steps.missing_tool.outputs.tools_reported }} - total_count: ${{ steps.missing_tool.outputs.total_count }} - steps: - - name: Setup Scripts - id: setup - uses: github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 - with: - destination: ${{ runner.temp }}/gh-aw/actions - job-name: ${{ github.job }} - trace-id: ${{ needs.activation.outputs.setup-trace-id }} - - name: Download agent output artifact - id: download-agent-output - continue-on-error: true - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - with: - name: agent - path: /tmp/gh-aw/ - - name: Setup agent output environment variable - id: setup-agent-output-env - if: steps.download-agent-output.outcome == 'success' - run: | - mkdir -p /tmp/gh-aw/ - find "/tmp/gh-aw/" -type f -print - echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT" - - name: Process no-op messages - id: noop - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 - env: - GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} - GH_AW_NOOP_MAX: "1" - GH_AW_WORKFLOW_NAME: "自动修复 Bug" - GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} - GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} - GH_AW_NOOP_REPORT_AS_ISSUE: "true" - with: - github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_noop_message.cjs'); - await main(); - - name: Log detection run - id: detection_runs - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 - env: - GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "自动修复 Bug" - 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 { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_detection_runs.cjs'); - await main(); - - name: Record missing tool - id: missing_tool - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 - 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: "自动修复 Bug" - with: - github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/missing_tool.cjs'); - await main(); - - name: Record incomplete - id: report_incomplete - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 - 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: "自动修复 Bug" - with: - github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/report_incomplete_handler.cjs'); - await main(); - - name: Handle agent failure - id: handle_agent_failure - if: always() - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 - env: - GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "自动修复 Bug" - 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: "auto-fix" - 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_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_STALE_LOCK_FILE_FAILED: ${{ needs.activation.outputs.stale_lock_file_failed }} - GH_AW_GROUP_REPORTS: "false" - GH_AW_FAILURE_REPORT_AS_ISSUE: "true" - GH_AW_TIMEOUT_MINUTES: "20" - with: - github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_agent_failure.cjs'); - await main(); - - detection: - needs: - - activation - - agent - if: > - always() && needs.agent.result != 'skipped' && (needs.agent.outputs.output_types != '' || needs.agent.outputs.has_patch == 'true') - runs-on: ubuntu-latest - permissions: - contents: read - outputs: - detection_conclusion: ${{ steps.detection_conclusion.outputs.conclusion }} - detection_reason: ${{ steps.detection_conclusion.outputs.reason }} - detection_success: ${{ steps.detection_conclusion.outputs.success }} - steps: - - name: Setup Scripts - id: setup - uses: github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 - with: - destination: ${{ runner.temp }}/gh-aw/actions - job-name: ${{ github.job }} - trace-id: ${{ needs.activation.outputs.setup-trace-id }} - - name: Download agent output artifact - id: download-agent-output - continue-on-error: true - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - with: - name: agent - path: /tmp/gh-aw/ - - name: Setup agent output environment variable - id: setup-agent-output-env - if: steps.download-agent-output.outcome == 'success' - run: | - mkdir -p /tmp/gh-aw/ - find "/tmp/gh-aw/" -type f -print - echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT" - - name: Checkout repository for patch context - if: needs.agent.outputs.has_patch == 'true' - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - persist-credentials: false - # --- Threat Detection --- - - name: 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.25.20 ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20 ghcr.io/github/gh-aw-firewall/squid:0.25.20 - - name: Check if detection needed - id: detection_guard - if: always() - env: - OUTPUT_TYPES: ${{ needs.agent.outputs.output_types }} - HAS_PATCH: ${{ needs.agent.outputs.has_patch }} - run: | - if [[ -n "$OUTPUT_TYPES" || "$HAS_PATCH" == "true" ]]; then - echo "run_detection=true" >> "$GITHUB_OUTPUT" - echo "Detection will run: output_types=$OUTPUT_TYPES, has_patch=$HAS_PATCH" - else - echo "run_detection=false" >> "$GITHUB_OUTPUT" - echo "Detection skipped: no agent outputs or patches to analyze" - fi - - name: Clear MCP configuration for detection - if: always() && steps.detection_guard.outputs.run_detection == 'true' - run: | - rm -f /tmp/gh-aw/mcp-config/mcp-servers.json - rm -f /home/runner/.copilot/mcp-config.json - rm -f "$GITHUB_WORKSPACE/.gemini/settings.json" - - name: Prepare threat detection files - if: always() && steps.detection_guard.outputs.run_detection == 'true' - run: | - mkdir -p /tmp/gh-aw/threat-detection/aw-prompts - cp /tmp/gh-aw/aw-prompts/prompt.txt /tmp/gh-aw/threat-detection/aw-prompts/prompt.txt 2>/dev/null || true - cp /tmp/gh-aw/agent_output.json /tmp/gh-aw/threat-detection/agent_output.json 2>/dev/null || true - for f in /tmp/gh-aw/aw-*.patch; do - [ -f "$f" ] && cp "$f" /tmp/gh-aw/threat-detection/ 2>/dev/null || true - done - for f in /tmp/gh-aw/aw-*.bundle; do - [ -f "$f" ] && cp "$f" /tmp/gh-aw/threat-detection/ 2>/dev/null || true - done - echo "Prepared threat detection files:" - ls -la /tmp/gh-aw/threat-detection/ 2>/dev/null || true - - name: Setup threat detection - if: always() && steps.detection_guard.outputs.run_detection == 'true' - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 - env: - WORKFLOW_NAME: "自动修复 Bug" - WORKFLOW_DESCRIPTION: "No description provided" - HAS_PATCH: ${{ needs.agent.outputs.has_patch }} - with: - script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/setup_threat_detection.cjs'); - await main(); - - name: Ensure threat-detection directory and log - if: always() && steps.detection_guard.outputs.run_detection == 'true' - run: | - mkdir -p /tmp/gh-aw/threat-detection - touch /tmp/gh-aw/threat-detection/detection.log - - name: Setup Node.js - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 - with: - node-version: '24' - package-manager-cache: false - - name: Install Codex CLI - run: npm install --ignore-scripts -g @openai/codex@0.118.0 - - name: Install AWF binary - run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.25.20 - - name: Execute Codex CLI - if: always() && steps.detection_guard.outputs.run_detection == 'true' - id: detection_agentic_execution - run: | - set -o pipefail - mkdir -p "$CODEX_HOME/logs" && touch /tmp/gh-aw/agent-step-summary.md - (umask 177 && touch /tmp/gh-aw/threat-detection/detection.log) - # shellcheck disable=SC1003 - sudo -E awf --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" --env-all --exclude-env CODEX_API_KEY --exclude-env OPENAI_API_KEY --allow-domains 172.30.0.1,api.openai.com,host.docker.internal,openai.com --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --image-tag 0.25.20 --skip-pull --enable-api-proxy --openai-api-target api.zhizengzeng.com --openai-api-base-path /v1 \ - -- /bin/bash -c 'export PATH="$(find /opt/hostedtoolcache -maxdepth 4 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true && INSTRUCTION="$(cat /tmp/gh-aw/aw-prompts/prompt.txt)" && codex ${GH_AW_MODEL_DETECTION_CODEX:+-c model="$GH_AW_MODEL_DETECTION_CODEX" }exec -c web_search="disabled" -c fetch="disabled" --dangerously-bypass-approvals-and-sandbox --skip-git-repo-check "$INSTRUCTION"' 2>&1 | tee -a /tmp/gh-aw/threat-detection/detection.log - env: - CODEX_API_KEY: ${{ secrets.CODEX_API_KEY || secrets.OPENAI_API_KEY }} - CODEX_HOME: /tmp/gh-aw/mcp-config - GH_AW_MCP_CONFIG: /tmp/gh-aw/mcp-config/config.toml - GH_AW_MODEL_DETECTION_CODEX: gpt-5.4 - GH_AW_PHASE: detection - GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GH_AW_VERSION: v0.68.3 - GITHUB_AW: true - GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md - GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com - GIT_AUTHOR_NAME: github-actions[bot] - GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com - GIT_COMMITTER_NAME: github-actions[bot] - OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - OPENAI_BASE_URL: https://api.zhizengzeng.com/v1 - RUST_LOG: trace,hyper_util=info,mio=info,reqwest=info,os_info=info,codex_otel=warn,codex_core=debug,ocodex_exec=debug - - name: Upload threat detection log - if: always() && steps.detection_guard.outputs.run_detection == 'true' - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: detection - path: /tmp/gh-aw/threat-detection/detection.log - if-no-files-found: ignore - - name: Parse and conclude threat detection - id: detection_conclusion - if: always() - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 - env: - RUN_DETECTION: ${{ steps.detection_guard.outputs.run_detection }} - GH_AW_DETECTION_CONTINUE_ON_ERROR: "true" - with: - script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_threat_detection_results.cjs'); - await main(); - - pre_activation: - runs-on: ubuntu-slim - outputs: - activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} - matched_command: '' - setup-trace-id: ${{ steps.setup.outputs.trace-id }} - steps: - - name: Setup Scripts - id: setup - uses: github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 - with: - destination: ${{ runner.temp }}/gh-aw/actions - job-name: ${{ github.job }} - - name: Check team membership for workflow - id: check_membership - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 - env: - GH_AW_REQUIRED_ROLES: "admin,maintainer,write" - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/check_membership.cjs'); - await main(); - - safe_outputs: - needs: - - activation - - agent - - detection - if: (!cancelled()) && needs.agent.result != 'skipped' && needs.detection.result == 'success' - runs-on: ubuntu-slim - permissions: - contents: write - discussions: write - issues: write - pull-requests: write - timeout-minutes: 15 - env: - GH_AW_CALLER_WORKFLOW_ID: "${{ github.repository }}/auto-fix" - GH_AW_DETECTION_CONCLUSION: ${{ needs.detection.outputs.detection_conclusion }} - GH_AW_DETECTION_REASON: ${{ needs.detection.outputs.detection_reason }} - GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens }} - GH_AW_ENGINE_ID: "codex" - GH_AW_ENGINE_MODEL: "gpt-5.4" - GH_AW_WORKFLOW_ID: "auto-fix" - GH_AW_WORKFLOW_NAME: "自动修复 Bug" - outputs: - code_push_failure_count: ${{ steps.process_safe_outputs.outputs.code_push_failure_count }} - code_push_failure_errors: ${{ steps.process_safe_outputs.outputs.code_push_failure_errors }} - comment_id: ${{ steps.process_safe_outputs.outputs.comment_id }} - comment_url: ${{ steps.process_safe_outputs.outputs.comment_url }} - create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }} - create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }} - created_pr_number: ${{ steps.process_safe_outputs.outputs.created_pr_number }} - created_pr_url: ${{ steps.process_safe_outputs.outputs.created_pr_url }} - process_safe_outputs_processed_count: ${{ steps.process_safe_outputs.outputs.processed_count }} - process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }} - steps: - - name: Setup Scripts - id: setup - uses: github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 - with: - destination: ${{ runner.temp }}/gh-aw/actions - job-name: ${{ github.job }} - trace-id: ${{ needs.activation.outputs.setup-trace-id }} - - name: Download agent output artifact - id: download-agent-output - continue-on-error: true - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - with: - name: agent - path: /tmp/gh-aw/ - - name: Setup agent output environment variable - id: setup-agent-output-env - if: steps.download-agent-output.outcome == 'success' - run: | - mkdir -p /tmp/gh-aw/ - find "/tmp/gh-aw/" -type f -print - echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT" - - name: Download patch artifact - continue-on-error: true - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - with: - name: agent - path: /tmp/gh-aw/ - - name: Checkout repository - if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - ref: main - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - persist-credentials: false - fetch-depth: 1 - - name: Configure Git credentials - if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') - env: - REPO_NAME: ${{ github.repository }} - SERVER_URL: ${{ github.server_url }} - GIT_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - run: | - git config --global user.email "github-actions[bot]@users.noreply.github.com" - git config --global user.name "github-actions[bot]" - git config --global am.keepcr true - # Re-authenticate git with GitHub token - SERVER_URL_STRIPPED="${SERVER_URL#https://}" - git remote set-url origin "https://x-access-token:${GIT_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" - echo "Git configured with standard GitHub Actions identity" - - name: Configure GH_HOST for enterprise compatibility - id: ghes-host-config - shell: bash - run: | - # Derive GH_HOST from GITHUB_SERVER_URL so the gh CLI targets the correct - # GitHub instance (GHES/GHEC). On github.com this is a harmless no-op. - GH_HOST="${GITHUB_SERVER_URL#https://}" - GH_HOST="${GH_HOST#http://}" - echo "GH_HOST=${GH_HOST}" >> "$GITHUB_ENV" - - name: Process Safe Outputs - id: process_safe_outputs - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 - env: - GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} - GH_AW_ALLOWED_DOMAINS: "172.30.0.1,api.openai.com,api.zhizengzeng.com,host.docker.internal,openai.com" - GITHUB_SERVER_URL: ${{ github.server_url }} - GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":1},\"create_pull_request\":{\"base_branch\":\"main\",\"max\":1,\"max_patch_size\":1024,\"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\",\"AGENTS.md\"],\"protected_path_prefixes\":[\".github/\",\".agents/\",\".codex/\"]},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"report_incomplete\":{}}" - GH_AW_CI_TRIGGER_TOKEN: ${{ secrets.GH_AW_CI_TRIGGER_TOKEN }} - with: - github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/safe_output_handler_manager.cjs'); - await main(); - - name: Upload Safe Outputs Items - if: always() - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: safe-outputs-items - path: | - /tmp/gh-aw/safe-output-items.jsonl - /tmp/gh-aw/temporary-id-map.json - if-no-files-found: ignore - From e8b18913359122f9114c69f5a14d1dc8ba5f60fb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2026 09:28:52 +0000 Subject: [PATCH 08/59] feat: pay user auto adjust level --- .../DBModule_MySQL/DBModule_MySQL.cpp | 21 +++++++++++++++++- .../DBModule_SQLite/DBModule_SQLite.cpp | 22 ++++++++++++++++++- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.cpp b/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.cpp index 800e8477..83544b31 100644 --- a/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.cpp +++ b/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.cpp @@ -297,6 +297,7 @@ bool CDBModule_MySQL::DBModule_MySQL_UserQuery(LPCXSTR lpszUserName, AUTHREG_USE bool CDBModule_MySQL::DBModule_MySQL_UserPay(LPCXSTR lpszUserName, LPCXSTR lpszSerialName) { SQLPacket_IsErrorOccur = false; + const int nVipUserLevel = 0; AUTHREG_SERIALTABLE st_SerialTable; AUTHREG_USERTABLE st_UserTable; @@ -361,6 +362,14 @@ bool CDBModule_MySQL::DBModule_MySQL_UserPay(LPCXSTR lpszUserName, LPCXSTR lpszS SQLPacket_dwErrorCode = ERROR_AUTHORIZE_MODULE_DATABASE_NOTSUPPORT; return false; } + //充值成功后自动升级为可登录等级 + _xstprintf(tszSQLStatement, _X("UPDATE `Authorize_User` SET nUserLevel = '%d' WHERE UserName = '%s'"), nVipUserLevel, lpszUserName); + if (!DataBase_MySQL_Execute(xhData, tszSQLStatement)) + { + SQLPacket_IsErrorOccur = true; + SQLPacket_dwErrorCode = ERROR_AUTHORIZE_MODULE_DATABASE_UPDATA; + return false; + } _xstprintf(tszSQLStatement, _X("UPDATE `Authorize_Serial` SET UserName = '%s',bIsUsed = '1' WHERE SerialNumber = '%s'"), lpszUserName, lpszSerialName); if (!DataBase_MySQL_Execute(xhData, tszSQLStatement)) { @@ -386,6 +395,7 @@ bool CDBModule_MySQL::DBModule_MySQL_UserPay(LPCXSTR lpszUserName, LPCXSTR lpszS bool CDBModule_MySQL::DBModule_MySQL_UserLeave(AUTHREG_PROTOCOL_TIME* pSt_TimeProtocol) { SQLPacket_IsErrorOccur = false; + const int nNormalUserLevel = 20; XCHAR tszSQLStatement[1024]; //SQL语句 memset(tszSQLStatement, '\0', 1024); @@ -426,6 +436,16 @@ bool CDBModule_MySQL::DBModule_MySQL_UserLeave(AUTHREG_PROTOCOL_TIME* pSt_TimePr SQLPacket_dwErrorCode = ERROR_AUTHORIZE_MODULE_DATABASE_UPDATA; return false; } + if (pSt_TimeProtocol->nTimeLeft <= 0) + { + _xstprintf(tszSQLStatement, _X("UPDATE `Authorize_User` SET nUserLevel = '%d' WHERE UserName = '%s'"), nNormalUserLevel, pSt_TimeProtocol->tszUserName); + if (!DataBase_MySQL_Execute(xhData, tszSQLStatement)) + { + SQLPacket_IsErrorOccur = true; + SQLPacket_dwErrorCode = ERROR_AUTHORIZE_MODULE_DATABASE_UPDATA; + return false; + } + } return true; } /******************************************************************** @@ -2015,4 +2035,3 @@ bool CDBModule_MySQL::DBModule_MySQL_UserPayTime(LPCXSTR lpszUserName, LPCXSTR l } return true; } - diff --git a/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.cpp b/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.cpp index 2de361b8..981c04f4 100644 --- a/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.cpp +++ b/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.cpp @@ -257,6 +257,7 @@ bool CDBModule_SQLite::DBModule_SQLite_UserQuery(LPCXSTR lpszUserName, AUTHREG_U bool CDBModule_SQLite::DBModule_SQLite_UserPay(LPCXSTR lpszUserName, LPCXSTR lpszSerialName) { SQLPacket_IsErrorOccur = false; + const int nVipUserLevel = 0; AUTHREG_SERIALTABLE st_SerialTable; AUTHREG_USERTABLE st_UserTable; @@ -321,6 +322,14 @@ bool CDBModule_SQLite::DBModule_SQLite_UserPay(LPCXSTR lpszUserName, LPCXSTR lps SQLPacket_dwErrorCode = ERROR_AUTHORIZE_MODULE_DATABASE_NOTSUPPORT; return false; } + //充值成功后自动升级为可登录等级 + _xstprintf(tszSQLStatement, _X("UPDATE Authorize_User SET nUserLevel = '%d' WHERE UserName = '%s'"), nVipUserLevel, lpszUserName); + if (!DataBase_SQLite_Exec(xhData, tszSQLStatement)) + { + SQLPacket_IsErrorOccur = true; + SQLPacket_dwErrorCode = ERROR_AUTHORIZE_MODULE_DATABASE_UPDATA; + return false; + } _xstprintf(tszSQLStatement, _X("UPDATE Authorize_Serial SET UserName = '%s',bIsUsed = '1' WHERE SerialNumber = '%s'"), lpszUserName, lpszSerialName); if (!DataBase_SQLite_Exec(xhData, tszSQLStatement)) { @@ -346,6 +355,7 @@ bool CDBModule_SQLite::DBModule_SQLite_UserPay(LPCXSTR lpszUserName, LPCXSTR lps bool CDBModule_SQLite::DBModule_SQLite_UserLeave(AUTHREG_PROTOCOL_TIME* pSt_TimeProtocol) { SQLPacket_IsErrorOccur = false; + const int nNormalUserLevel = 20; XCHAR tszSQLStatement[1024]; //SQL语句 memset(tszSQLStatement, '\0', 1024); @@ -385,6 +395,16 @@ bool CDBModule_SQLite::DBModule_SQLite_UserLeave(AUTHREG_PROTOCOL_TIME* pSt_Time SQLPacket_dwErrorCode = ERROR_AUTHORIZE_MODULE_DATABASE_UPDATA; return false; } + if (pSt_TimeProtocol->nTimeLeft <= 0) + { + _xstprintf(tszSQLStatement, _X("UPDATE Authorize_User SET nUserLevel = '%d' WHERE UserName = '%s'"), nNormalUserLevel, pSt_TimeProtocol->tszUserName); + if (!DataBase_SQLite_Exec(xhData, tszSQLStatement)) + { + SQLPacket_IsErrorOccur = true; + SQLPacket_dwErrorCode = ERROR_AUTHORIZE_MODULE_DATABASE_UPDATA; + return false; + } + } return true; } /******************************************************************** @@ -1875,4 +1895,4 @@ bool CDBModule_SQLite::DBModule_SQLite_UserPayTime(LPCXSTR lpszUserName, LPCXSTR return false; } return true; -} \ No newline at end of file +} From e622032c71aab042d04dfde43e7992550e30ecec Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Fri, 1 May 2026 09:58:01 +0800 Subject: [PATCH 09/59] ci:delete cpp check and update codeql.yml ci:add codeql-to-commit.yml --- .github/workflows/codeql-to-commit.yml | 179 +++++++++++++++++++++++++ .github/workflows/codeql.yml | 41 ++++-- .github/workflows/cppcheck.yml | 35 ----- 3 files changed, 206 insertions(+), 49 deletions(-) create mode 100644 .github/workflows/codeql-to-commit.yml delete mode 100644 .github/workflows/cppcheck.yml diff --git a/.github/workflows/codeql-to-commit.yml b/.github/workflows/codeql-to-commit.yml new file mode 100644 index 00000000..7a35e9b0 --- /dev/null +++ b/.github/workflows/codeql-to-commit.yml @@ -0,0 +1,179 @@ +name: Auto Copilot Autofix (High & Medium Only) + +on: + workflow_dispatch: + workflow_run: + workflows: ["CodeQL Advanced"] + types: [completed] + +jobs: + auto-fix: + runs-on: ubuntu-latest + if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' }} + permissions: + security-events: read + contents: write + pull-requests: write + + steps: + - name: Trigger Autofix for High & Medium alerts + env: + GH_TOKEN: ${{ secrets.AUTOFIX_TOKEN }} + OWNER: ${{ github.repository_owner }} + REPO: ${{ github.event.repository.name }} + run: | + DEFAULT_BRANCH=$(gh api /repos/$OWNER/$REPO --jq '.default_branch') + echo "Default branch: $DEFAULT_BRANCH" + + # 获取所有 open alert,用 jq 过滤 security_severity_level 为 high 或 medium 的 + ALERTS=$(gh api \ + "/repos/$OWNER/$REPO/code-scanning/alerts?state=open&per_page=100" \ + --jq '[.[] | select(.rule.security_severity_level == "high" or .rule.security_severity_level == "medium") | {number: .number, level: .rule.security_severity_level}]') + + COUNT=$(echo $ALERTS | jq 'length') + echo "Found $COUNT alerts with security_severity_level high or medium" + echo "$ALERTS" | jq -r '.[] | " Alert #\(.number) [\(.level)]"' + + if [ "$COUNT" -eq 0 ]; then + echo "No alerts to process, exiting." + exit 0 + fi + + for ROW in $(echo $ALERTS | jq -r '.[] | @base64'); do + _jq() { echo "$ROW" | base64 -d | jq -r "$1"; } + + NUMBER=$(_jq '.number') + SEC_LEVEL=$(_jq '.level') + + echo "--- Alert #$NUMBER [$SEC_LEVEL] ---" + + EXISTING=$(gh api \ + /repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER/autofix \ + --jq '.status' 2>/dev/null || echo "none") + + if [ "$EXISTING" = "success" ]; then + echo "✅ Fix already exists, committing directly..." + else + echo "⏳ Generating fix..." + gh api -X POST \ + /repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER/autofix || { + echo "⚠️ Failed to trigger autofix for #$NUMBER, skipping" + continue + } + + for i in 1 2 3; do + sleep 30 + EXISTING=$(gh api \ + /repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER/autofix \ + --jq '.status' 2>/dev/null || echo "none") + echo " Attempt $i: status = $EXISTING" + [ "$EXISTING" = "success" ] && break + done + fi + + if [ "$EXISTING" = "success" ]; then + BRANCH="autofix/${SEC_LEVEL}/alert-${NUMBER}" + + # 检查分支是否已存在 + BRANCH_STATUS=$(gh api \ + /repos/$OWNER/$REPO/git/refs/heads/$BRANCH \ + --silent 2>/dev/null && echo "exists" || echo "not_found") + echo "DEBUG branch status: $BRANCH_STATUS" + + if [ "$BRANCH_STATUS" = "exists" ]; then + echo "⏭️ Branch $BRANCH already exists, skipping" + continue + fi + + SHA=$(gh api /repos/$OWNER/$REPO/git/refs/heads/$DEFAULT_BRANCH \ + --jq '.object.sha') + + # 创建分支 + gh api -X POST /repos/$OWNER/$REPO/git/refs \ + -f ref="refs/heads/$BRANCH" \ + -f sha="$SHA" 2>/dev/null && \ + echo "🌿 Created branch: $BRANCH" || \ + echo "🌿 Branch already exists: $BRANCH" + + # 提交 fix + gh api -X POST \ + /repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER/autofix/commits \ + -f target_ref="$BRANCH" || { + echo "❌ Failed to commit fix for alert #$NUMBER" + continue + } + echo "✅ Committed fix to branch: $BRANCH" + + # 获取 alert 详情 + ALERT_INFO=$(gh api \ + /repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER) + + ALERT_TITLE=$(echo $ALERT_INFO | jq -r '.rule.description') + ALERT_HELP=$(echo $ALERT_INFO | jq -r '.rule.help // "暂无详细说明"' | head -c 800) + ALERT_TAGS=$(echo $ALERT_INFO | jq -r '.rule.tags // [] | join(", ")') + ALERT_FILE=$(echo $ALERT_INFO | jq -r '.most_recent_instance.location.path // "未知文件"') + ALERT_LINE=$(echo $ALERT_INFO | jq -r '.most_recent_instance.location.start_line // "未知行"') + ALERT_URL=$(echo $ALERT_INFO | jq -r '.html_url') + CWE_TAGS=$(echo $ALERT_INFO | jq -r '[.rule.tags[] | select(startswith("external/cwe/"))] | join(", ")') + + # 获取 Autofix AI 修复说明 + AUTOFIX_DESC=$(gh api \ + /repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER/autofix \ + --jq '.description // "暂无 AI 修复说明"') + + # 创建 Draft PR + gh pr create \ + --repo "$OWNER/$REPO" \ + --base "$DEFAULT_BRANCH" \ + --head "$BRANCH" \ + --draft \ + --title "[Autofix][$SEC_LEVEL] Alert #$NUMBER: $ALERT_TITLE" \ + --body "## 🤖 Copilot Autofix 自动修复报告 + + --- + + ### 📋 基本信息 + + | 字段 | 内容 | + |------|------| + | **Alert ID** | [#$NUMBER]($ALERT_URL) | + | **安全级别** | $SEC_LEVEL | + | **规则名称** | $ALERT_TITLE | + | **问题文件** | \`$ALERT_FILE\` 第 $ALERT_LINE 行 | + | **CWE 分类** | $CWE_TAGS | + | **规则标签** | $ALERT_TAGS | + + --- + + ### 🔍 问题说明 + + $ALERT_HELP + + --- + + ### 🤖 AI 修复思路 + + $AUTOFIX_DESC + + --- + + ### ✅ Review 检查清单 + + - [ ] 理解了漏洞的成因和影响范围 + - [ ] 确认 AI 修复逻辑正确,没有遗漏边界情况 + - [ ] 确认修复没有改变原有业务逻辑 + - [ ] 确认没有引入新的安全问题 + - [ ] CI / 单元测试全部通过 + - [ ] 如有必要,已补充对应的测试用例 + + --- + + > 此 PR 由 GitHub Copilot Autofix 自动生成,请仔细审核后再 merge。" && \ + echo "🎉 PR created for alert #$NUMBER" || \ + echo "⚠️ PR already exists for alert #$NUMBER" + + else + echo "⚠️ Autofix not available for alert #$NUMBER (status: $EXISTING), skipping" + fi + + done \ No newline at end of file diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 603dd33a..02e447f2 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -3,11 +3,7 @@ name: CodeQL Advanced on: push: branches: - - 'develop' - paths: - - 'XEngine_Source/**' - - 'XEngine_Release/**' - - '.github/**' + - 'master' jobs: analyze: @@ -26,8 +22,6 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v6 - with: - ref: 'develop' - name: Checkout dependency repository (xengine) uses: actions/checkout@v6 @@ -35,11 +29,6 @@ jobs: repository: libxengine/libxengine path: libxengine - - name: sub module checkout (opensource) - run: | - git submodule init - git submodule update - - name: Set TERM variable run: echo "TERM=xterm" >> $GITHUB_ENV @@ -53,11 +42,35 @@ jobs: uses: github/codeql-action/init@v4 with: languages: ${{ matrix.language }} + build-mode: manual + queries: security-and-quality - name: make run: | - cd XEngine_Source - make + cd XEngine_Module + cd jsoncpp + make + cd .. + cd tinyxml2 + make + cd .. + cd XEngine_InfoReport + make + cd .. + cd XEngine_Token + make + cd .. + cd XEngine_MSGNotify + make + cd .. + cd XEngine_AIApi + make + cd .. + cd XEngine_Verification + make + cd .. + cd XEngine_PluginExtension + make - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v4 diff --git a/.github/workflows/cppcheck.yml b/.github/workflows/cppcheck.yml deleted file mode 100644 index 0a6eb20c..00000000 --- a/.github/workflows/cppcheck.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: cpp check workflows - -on: - push: - branches: - - 'develop' - paths: - - 'XEngine_Source/**' - - 'XEngine_Release/**' - - '.github/**' - -jobs: - build: - runs-on: ubuntu-latest - - steps: - - name: Checkout main repository code - uses: actions/checkout@v6 - with: - ref: 'develop' - - - name: Create static_analysis directory - run: mkdir -p static_analysis - - - name: Run Cppcheck - run: | - sudo apt-get install -y cppcheck - cppcheck --enable=all --language=c++ --std=c++20 ./XEngine_Source/ --output-file=static_analysis/log.xml --xml - continue-on-error: true - - - name: Upload Cppcheck Results - uses: actions/upload-artifact@v6 - with: - name: cppcheck_results - path: static_analysis/log.xml \ No newline at end of file From b5a34b6dc243b2dc542e5c862208f0eb666c0b5b Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Fri, 1 May 2026 10:11:30 +0800 Subject: [PATCH 10/59] ci:delete codeql.yml --- .github/workflows/codeql.yml | 78 ------------------------------------ 1 file changed, 78 deletions(-) delete mode 100644 .github/workflows/codeql.yml diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml deleted file mode 100644 index 02e447f2..00000000 --- a/.github/workflows/codeql.yml +++ /dev/null @@ -1,78 +0,0 @@ -name: CodeQL Advanced - -on: - push: - branches: - - 'master' - -jobs: - analyze: - runs-on: ubuntu-24.04 - permissions: - security-events: write - packages: read - actions: read - contents: read - - strategy: - fail-fast: false - matrix: - include: - - language: c-cpp - steps: - - name: Checkout repository - uses: actions/checkout@v6 - - - name: Checkout dependency repository (xengine) - uses: actions/checkout@v6 - with: - repository: libxengine/libxengine - path: libxengine - - - name: Set TERM variable - run: echo "TERM=xterm" >> $GITHUB_ENV - - - name: Set up Dependency Environment - run: | - cd libxengine - chmod +x ./XEngine_LINEnv.sh - sudo ./XEngine_LINEnv.sh -i 3 - - - name: Initialize CodeQL - uses: github/codeql-action/init@v4 - with: - languages: ${{ matrix.language }} - build-mode: manual - queries: security-and-quality - - - name: make - run: | - cd XEngine_Module - cd jsoncpp - make - cd .. - cd tinyxml2 - make - cd .. - cd XEngine_InfoReport - make - cd .. - cd XEngine_Token - make - cd .. - cd XEngine_MSGNotify - make - cd .. - cd XEngine_AIApi - make - cd .. - cd XEngine_Verification - make - cd .. - cd XEngine_PluginExtension - make - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v4 - with: - category: "/language:${{ matrix.language }}" From d87e1ec01f87e098b590e4e9a10e1165c9e47f2d Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Fri, 1 May 2026 10:17:15 +0800 Subject: [PATCH 11/59] Update CodeQL workflow configuration --- .github/workflows/codeql.yml | 67 ++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 .github/workflows/codeql.yml diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 00000000..2a851db7 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,67 @@ +name: CodeQL Advanced + +on: + push: + branches: + - 'develop' + paths: + - 'XEngine_Source/**' + - 'XEngine_Release/**' + - '.github/**' + +jobs: + analyze: + runs-on: ubuntu-24.04 + permissions: + security-events: write + packages: read + actions: read + contents: read + + strategy: + fail-fast: false + matrix: + include: + - language: c-cpp + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + ref: 'develop' + + - name: Checkout dependency repository (xengine) + uses: actions/checkout@v6 + with: + repository: libxengine/libxengine + path: libxengine + + - name: sub module checkout (opensource) + run: | + git submodule init + git submodule update + + - name: Set TERM variable + run: echo "TERM=xterm" >> $GITHUB_ENV + + - name: Set up Dependency Environment + run: | + cd libxengine + chmod +x ./XEngine_LINEnv.sh + sudo ./XEngine_LINEnv.sh -i 3 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v4 + with: + languages: ${{ matrix.language }} + build-mode: manual + queries: security-and-quality + + - name: make + run: | + cd XEngine_Source + make + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v4 + with: + category: "/language:${{ matrix.language }}" From 65d9dbd5f2792e885952c6a56234e844a8dbb094 Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Fri, 1 May 2026 10:40:13 +0800 Subject: [PATCH 12/59] ci:update --- .github/workflows/codeql-to-commit.yml | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/workflows/codeql-to-commit.yml b/.github/workflows/codeql-to-commit.yml index 7a35e9b0..837987d6 100644 --- a/.github/workflows/codeql-to-commit.yml +++ b/.github/workflows/codeql-to-commit.yml @@ -96,14 +96,17 @@ jobs: echo "🌿 Branch already exists: $BRANCH" # 提交 fix - gh api -X POST \ + COMMIT_RESULT=$(gh api -X POST \ /repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER/autofix/commits \ - -f target_ref="$BRANCH" || { + -f target_ref="$BRANCH" 2>&1) + echo "DEBUG commit result: $COMMIT_RESULT" + + if echo "$COMMIT_RESULT" | grep -q "target_ref"; then + echo "✅ Committed fix to branch: $BRANCH" + else echo "❌ Failed to commit fix for alert #$NUMBER" continue - } - echo "✅ Committed fix to branch: $BRANCH" - + fi # 获取 alert 详情 ALERT_INFO=$(gh api \ /repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER) From 1e29f5a3657584bacd0c4aa388aebb73c2bfbab1 Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Fri, 1 May 2026 10:50:23 +0800 Subject: [PATCH 13/59] Refactor branch creation in CodeQL workflow Update branch creation logic to handle existing branches gracefully. --- .github/workflows/codeql-to-commit.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-to-commit.yml b/.github/workflows/codeql-to-commit.yml index 837987d6..4a6f7270 100644 --- a/.github/workflows/codeql-to-commit.yml +++ b/.github/workflows/codeql-to-commit.yml @@ -22,6 +22,7 @@ jobs: OWNER: ${{ github.repository_owner }} REPO: ${{ github.event.repository.name }} run: | + set +e DEFAULT_BRANCH=$(gh api /repos/$OWNER/$REPO --jq '.default_branch') echo "Default branch: $DEFAULT_BRANCH" @@ -91,9 +92,8 @@ jobs: # 创建分支 gh api -X POST /repos/$OWNER/$REPO/git/refs \ -f ref="refs/heads/$BRANCH" \ - -f sha="$SHA" 2>/dev/null && \ - echo "🌿 Created branch: $BRANCH" || \ - echo "🌿 Branch already exists: $BRANCH" + -f sha="$SHA" 2>/dev/null || true + echo "🌿 Branch created or already exists: $BRANCH" # 提交 fix COMMIT_RESULT=$(gh api -X POST \ @@ -179,4 +179,4 @@ jobs: echo "⚠️ Autofix not available for alert #$NUMBER (status: $EXISTING), skipping" fi - done \ No newline at end of file + done From 1a12f577a5debb9af87cdf67965ad19065c0a4a8 Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Fri, 1 May 2026 11:19:40 +0800 Subject: [PATCH 14/59] ci:improved --- .github/workflows/codeql-to-commit.yml | 24 +++++++++++++++++++++++- .github/workflows/codeql.yml | 3 +++ XEngine_Source/XEngine_DependLibrary | 2 +- 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql-to-commit.yml b/.github/workflows/codeql-to-commit.yml index 4a6f7270..9af70f87 100644 --- a/.github/workflows/codeql-to-commit.yml +++ b/.github/workflows/codeql-to-commit.yml @@ -107,6 +107,22 @@ jobs: echo "❌ Failed to commit fix for alert #$NUMBER" continue fi + + # 提交 fix + COMMIT_RESULT=$(gh api -X POST \ + /repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER/autofix/commits \ + -f target_ref="$BRANCH" 2>&1) + echo "DEBUG commit result: $COMMIT_RESULT" + + # 判断是否有实际代码改动 + if echo "$COMMIT_RESULT" | grep -q "target_ref"; then + echo "✅ Committed fix to branch: $BRANCH" + HAS_CODE_FIX=true + else + echo "⚠️ No code changes generated, will create advisory PR only" + HAS_CODE_FIX=false + fi + # 获取 alert 详情 ALERT_INFO=$(gh api \ /repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER) @@ -119,11 +135,17 @@ jobs: ALERT_URL=$(echo $ALERT_INFO | jq -r '.html_url') CWE_TAGS=$(echo $ALERT_INFO | jq -r '[.rule.tags[] | select(startswith("external/cwe/"))] | join(", ")') - # 获取 Autofix AI 修复说明 AUTOFIX_DESC=$(gh api \ /repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER/autofix \ --jq '.description // "暂无 AI 修复说明"') + # 根据是否有代码改动决定 PR body 提示 + if [ "$HAS_CODE_FIX" = "true" ]; then + FIX_NOTE="> 此 PR 包含 Copilot Autofix 自动生成的代码修复,请审核后 merge。" + else + FIX_NOTE="> ⚠️ **此 alert 没有自动代码修复**,AI 仅提供了修复建议,需要**手动按照上方 AI 修复思路修改代码**后再 merge。" + fi + # 创建 Draft PR gh pr create \ --repo "$OWNER/$REPO" \ diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 2a851db7..57cb9afd 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -55,6 +55,9 @@ jobs: languages: ${{ matrix.language }} build-mode: manual queries: security-and-quality + config: | + paths-ignore: + - 'XEngine_Source/XEngine_DependLibrary' - name: make run: | diff --git a/XEngine_Source/XEngine_DependLibrary b/XEngine_Source/XEngine_DependLibrary index 207abe8b..112ce75d 160000 --- a/XEngine_Source/XEngine_DependLibrary +++ b/XEngine_Source/XEngine_DependLibrary @@ -1 +1 @@ -Subproject commit 207abe8b617744e35bf1438a03536d898ddc93fd +Subproject commit 112ce75d4f7a284ee58c4e1e6c551e2807033365 From f54918ed140ed1504c03b2212d566251dbdddba9 Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Fri, 1 May 2026 12:09:00 +0800 Subject: [PATCH 15/59] ci:fixed --- .github/workflows/codeql-to-commit.yml | 82 ++++++++++++++------------ 1 file changed, 44 insertions(+), 38 deletions(-) diff --git a/.github/workflows/codeql-to-commit.yml b/.github/workflows/codeql-to-commit.yml index 9af70f87..6a7390dd 100644 --- a/.github/workflows/codeql-to-commit.yml +++ b/.github/workflows/codeql-to-commit.yml @@ -81,46 +81,54 @@ jobs: --silent 2>/dev/null && echo "exists" || echo "not_found") echo "DEBUG branch status: $BRANCH_STATUS" - if [ "$BRANCH_STATUS" = "exists" ]; then - echo "⏭️ Branch $BRANCH already exists, skipping" - continue - fi - - SHA=$(gh api /repos/$OWNER/$REPO/git/refs/heads/$DEFAULT_BRANCH \ - --jq '.object.sha') - - # 创建分支 - gh api -X POST /repos/$OWNER/$REPO/git/refs \ - -f ref="refs/heads/$BRANCH" \ - -f sha="$SHA" 2>/dev/null || true - echo "🌿 Branch created or already exists: $BRANCH" + if [ "$EXISTING" = "success" ]; then + BRANCH="autofix/${SEC_LEVEL}/alert-${NUMBER}" - # 提交 fix - COMMIT_RESULT=$(gh api -X POST \ - /repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER/autofix/commits \ - -f target_ref="$BRANCH" 2>&1) - echo "DEBUG commit result: $COMMIT_RESULT" + # 检查分支是否已存在 + BRANCH_STATUS=$(gh api \ + /repos/$OWNER/$REPO/git/refs/heads/$BRANCH \ + --silent 2>/dev/null && echo "exists" || echo "not_found") + echo "DEBUG branch status: $BRANCH_STATUS" - if echo "$COMMIT_RESULT" | grep -q "target_ref"; then - echo "✅ Committed fix to branch: $BRANCH" + if [ "$BRANCH_STATUS" = "not_found" ]; then + # 分支不存在,创建分支 + SHA=$(gh api /repos/$OWNER/$REPO/git/refs/heads/$DEFAULT_BRANCH \ + --jq '.object.sha') + + gh api -X POST /repos/$OWNER/$REPO/git/refs \ + -f ref="refs/heads/$BRANCH" \ + -f sha="$SHA" 2>/dev/null || true + echo "🌿 Created branch: $BRANCH" + + # 提交 fix + COMMIT_RESULT=$(gh api -X POST \ + /repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER/autofix/commits \ + -f target_ref="$BRANCH" 2>&1) + echo "DEBUG commit result: $COMMIT_RESULT" + + if echo "$COMMIT_RESULT" | grep -q "target_ref"; then + echo "✅ Committed fix to branch: $BRANCH" + HAS_CODE_FIX=true + else + echo "⚠️ No code changes, advisory PR only" + HAS_CODE_FIX=false + fi else - echo "❌ Failed to commit fix for alert #$NUMBER" - continue - fi - - # 提交 fix - COMMIT_RESULT=$(gh api -X POST \ - /repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER/autofix/commits \ - -f target_ref="$BRANCH" 2>&1) - echo "DEBUG commit result: $COMMIT_RESULT" - - # 判断是否有实际代码改动 - if echo "$COMMIT_RESULT" | grep -q "target_ref"; then - echo "✅ Committed fix to branch: $BRANCH" + # 分支已存在,检查是否已有 open PR + EXISTING_PR=$(gh pr list \ + --repo "$OWNER/$REPO" \ + --head "$BRANCH" \ + --state open \ + --json number \ + --jq '.[0].number // empty') + + if [ -n "$EXISTING_PR" ]; then + echo "⏭️ PR #$EXISTING_PR already exists, skipping" + continue + fi + + echo "🌿 Branch exists, creating PR with existing branch" HAS_CODE_FIX=true - else - echo "⚠️ No code changes generated, will create advisory PR only" - HAS_CODE_FIX=false fi # 获取 alert 详情 @@ -139,14 +147,12 @@ jobs: /repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER/autofix \ --jq '.description // "暂无 AI 修复说明"') - # 根据是否有代码改动决定 PR body 提示 if [ "$HAS_CODE_FIX" = "true" ]; then FIX_NOTE="> 此 PR 包含 Copilot Autofix 自动生成的代码修复,请审核后 merge。" else FIX_NOTE="> ⚠️ **此 alert 没有自动代码修复**,AI 仅提供了修复建议,需要**手动按照上方 AI 修复思路修改代码**后再 merge。" fi - # 创建 Draft PR gh pr create \ --repo "$OWNER/$REPO" \ --base "$DEFAULT_BRANCH" \ From 5bb45170e66e8d81420137fc7e0d5b0afbd5840d Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Fri, 1 May 2026 12:40:30 +0800 Subject: [PATCH 16/59] ci:fixed --- .github/workflows/codeql-to-commit.yml | 170 ++++++++++++------------- 1 file changed, 80 insertions(+), 90 deletions(-) diff --git a/.github/workflows/codeql-to-commit.yml b/.github/workflows/codeql-to-commit.yml index 6a7390dd..740026b3 100644 --- a/.github/workflows/codeql-to-commit.yml +++ b/.github/workflows/codeql-to-commit.yml @@ -26,7 +26,6 @@ jobs: DEFAULT_BRANCH=$(gh api /repos/$OWNER/$REPO --jq '.default_branch') echo "Default branch: $DEFAULT_BRANCH" - # 获取所有 open alert,用 jq 过滤 security_severity_level 为 high 或 medium 的 ALERTS=$(gh api \ "/repos/$OWNER/$REPO/code-scanning/alerts?state=open&per_page=100" \ --jq '[.[] | select(.rule.security_severity_level == "high" or .rule.security_severity_level == "medium") | {number: .number, level: .rule.security_severity_level}]') @@ -45,15 +44,17 @@ jobs: NUMBER=$(_jq '.number') SEC_LEVEL=$(_jq '.level') + BRANCH="autofix/${SEC_LEVEL}/alert-${NUMBER}" echo "--- Alert #$NUMBER [$SEC_LEVEL] ---" + # 检查是否已有 autofix EXISTING=$(gh api \ /repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER/autofix \ --jq '.status' 2>/dev/null || echo "none") if [ "$EXISTING" = "success" ]; then - echo "✅ Fix already exists, committing directly..." + echo "✅ Fix already exists" else echo "⏳ Generating fix..." gh api -X POST \ @@ -72,94 +73,89 @@ jobs: done fi - if [ "$EXISTING" = "success" ]; then - BRANCH="autofix/${SEC_LEVEL}/alert-${NUMBER}" - - # 检查分支是否已存在 - BRANCH_STATUS=$(gh api \ - /repos/$OWNER/$REPO/git/refs/heads/$BRANCH \ - --silent 2>/dev/null && echo "exists" || echo "not_found") - echo "DEBUG branch status: $BRANCH_STATUS" - - if [ "$EXISTING" = "success" ]; then - BRANCH="autofix/${SEC_LEVEL}/alert-${NUMBER}" - - # 检查分支是否已存在 - BRANCH_STATUS=$(gh api \ - /repos/$OWNER/$REPO/git/refs/heads/$BRANCH \ - --silent 2>/dev/null && echo "exists" || echo "not_found") - echo "DEBUG branch status: $BRANCH_STATUS" - - if [ "$BRANCH_STATUS" = "not_found" ]; then - # 分支不存在,创建分支 - SHA=$(gh api /repos/$OWNER/$REPO/git/refs/heads/$DEFAULT_BRANCH \ - --jq '.object.sha') - - gh api -X POST /repos/$OWNER/$REPO/git/refs \ - -f ref="refs/heads/$BRANCH" \ - -f sha="$SHA" 2>/dev/null || true - echo "🌿 Created branch: $BRANCH" - - # 提交 fix - COMMIT_RESULT=$(gh api -X POST \ - /repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER/autofix/commits \ - -f target_ref="$BRANCH" 2>&1) - echo "DEBUG commit result: $COMMIT_RESULT" - - if echo "$COMMIT_RESULT" | grep -q "target_ref"; then - echo "✅ Committed fix to branch: $BRANCH" - HAS_CODE_FIX=true - else - echo "⚠️ No code changes, advisory PR only" - HAS_CODE_FIX=false - fi - else - # 分支已存在,检查是否已有 open PR - EXISTING_PR=$(gh pr list \ - --repo "$OWNER/$REPO" \ - --head "$BRANCH" \ - --state open \ - --json number \ - --jq '.[0].number // empty') - - if [ -n "$EXISTING_PR" ]; then - echo "⏭️ PR #$EXISTING_PR already exists, skipping" - continue - fi - - echo "🌿 Branch exists, creating PR with existing branch" - HAS_CODE_FIX=true - fi + if [ "$EXISTING" != "success" ]; then + echo "⚠️ Autofix not available for alert #$NUMBER (status: $EXISTING), skipping" + continue + fi + + # 检查分支是否已存在 + BRANCH_STATUS=$(gh api \ + /repos/$OWNER/$REPO/git/refs/heads/$BRANCH \ + --silent 2>/dev/null && echo "exists" || echo "not_found") + echo "DEBUG branch status: $BRANCH_STATUS" + + HAS_CODE_FIX=false - # 获取 alert 详情 - ALERT_INFO=$(gh api \ - /repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER) + if [ "$BRANCH_STATUS" = "not_found" ]; then + # 分支不存在,创建分支并提交 fix + SHA=$(gh api /repos/$OWNER/$REPO/git/refs/heads/$DEFAULT_BRANCH \ + --jq '.object.sha') - ALERT_TITLE=$(echo $ALERT_INFO | jq -r '.rule.description') - ALERT_HELP=$(echo $ALERT_INFO | jq -r '.rule.help // "暂无详细说明"' | head -c 800) - ALERT_TAGS=$(echo $ALERT_INFO | jq -r '.rule.tags // [] | join(", ")') - ALERT_FILE=$(echo $ALERT_INFO | jq -r '.most_recent_instance.location.path // "未知文件"') - ALERT_LINE=$(echo $ALERT_INFO | jq -r '.most_recent_instance.location.start_line // "未知行"') - ALERT_URL=$(echo $ALERT_INFO | jq -r '.html_url') - CWE_TAGS=$(echo $ALERT_INFO | jq -r '[.rule.tags[] | select(startswith("external/cwe/"))] | join(", ")') + gh api -X POST /repos/$OWNER/$REPO/git/refs \ + -f ref="refs/heads/$BRANCH" \ + -f sha="$SHA" 2>/dev/null || true + echo "🌿 Created branch: $BRANCH" - AUTOFIX_DESC=$(gh api \ - /repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER/autofix \ - --jq '.description // "暂无 AI 修复说明"') + COMMIT_RESULT=$(gh api -X POST \ + /repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER/autofix/commits \ + -f target_ref="$BRANCH" 2>&1) + echo "DEBUG commit result: $COMMIT_RESULT" - if [ "$HAS_CODE_FIX" = "true" ]; then - FIX_NOTE="> 此 PR 包含 Copilot Autofix 自动生成的代码修复,请审核后 merge。" + if echo "$COMMIT_RESULT" | grep -q "target_ref"; then + echo "✅ Committed fix to branch: $BRANCH" + HAS_CODE_FIX=true else - FIX_NOTE="> ⚠️ **此 alert 没有自动代码修复**,AI 仅提供了修复建议,需要**手动按照上方 AI 修复思路修改代码**后再 merge。" + echo "⚠️ No code changes generated, advisory PR only" + HAS_CODE_FIX=false fi - - gh pr create \ + else + # 分支已存在,检查是否已有 open PR + EXISTING_PR=$(gh pr list \ --repo "$OWNER/$REPO" \ - --base "$DEFAULT_BRANCH" \ --head "$BRANCH" \ - --draft \ - --title "[Autofix][$SEC_LEVEL] Alert #$NUMBER: $ALERT_TITLE" \ - --body "## 🤖 Copilot Autofix 自动修复报告 + --state open \ + --json number \ + --jq '.[0].number // empty') + + if [ -n "$EXISTING_PR" ]; then + echo "⏭️ PR #$EXISTING_PR already exists, skipping" + continue + fi + + echo "🌿 Branch exists, creating PR with existing branch" + HAS_CODE_FIX=true + fi + + # 获取 alert 详情 + ALERT_INFO=$(gh api \ + /repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER) + + ALERT_TITLE=$(echo $ALERT_INFO | jq -r '.rule.description') + ALERT_HELP=$(echo $ALERT_INFO | jq -r '.rule.help // "暂无详细说明"' | head -c 800) + ALERT_TAGS=$(echo $ALERT_INFO | jq -r '.rule.tags // [] | join(", ")') + ALERT_FILE=$(echo $ALERT_INFO | jq -r '.most_recent_instance.location.path // "未知文件"') + ALERT_LINE=$(echo $ALERT_INFO | jq -r '.most_recent_instance.location.start_line // "未知行"') + ALERT_URL=$(echo $ALERT_INFO | jq -r '.html_url') + CWE_TAGS=$(echo $ALERT_INFO | jq -r '[.rule.tags[] | select(startswith("external/cwe/"))] | join(", ")') + + AUTOFIX_DESC=$(gh api \ + /repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER/autofix \ + --jq '.description // "暂无 AI 修复说明"') + + if [ "$HAS_CODE_FIX" = "true" ]; then + FIX_NOTE="> 此 PR 包含 Copilot Autofix 自动生成的代码修复,请审核后 merge。" + else + FIX_NOTE="> ⚠️ **此 alert 没有自动代码修复**,AI 仅提供了修复建议,需要**手动按照上方 AI 修复思路修改代码**后再 merge。" + fi + + # 创建 Draft PR + gh pr create \ + --repo "$OWNER/$REPO" \ + --base "$DEFAULT_BRANCH" \ + --head "$BRANCH" \ + --draft \ + --title "[Autofix][$SEC_LEVEL] Alert #$NUMBER: $ALERT_TITLE" \ + --body "## 🤖 Copilot Autofix 自动修复报告 --- @@ -199,12 +195,6 @@ jobs: --- - > 此 PR 由 GitHub Copilot Autofix 自动生成,请仔细审核后再 merge。" && \ + $FIX_NOTE" && \ echo "🎉 PR created for alert #$NUMBER" || \ - echo "⚠️ PR already exists for alert #$NUMBER" - - else - echo "⚠️ Autofix not available for alert #$NUMBER (status: $EXISTING), skipping" - fi - - done + echo "❌ Failed to create PR for alert #$NUMBER" From b3046e3c7169bfd36dd620f1d8b27889d508c96e Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Fri, 1 May 2026 13:02:57 +0800 Subject: [PATCH 17/59] ci update --- .github/workflows/codeql-to-commit.yml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/.github/workflows/codeql-to-commit.yml b/.github/workflows/codeql-to-commit.yml index 740026b3..0a6fa8e2 100644 --- a/.github/workflows/codeql-to-commit.yml +++ b/.github/workflows/codeql-to-commit.yml @@ -48,7 +48,6 @@ jobs: echo "--- Alert #$NUMBER [$SEC_LEVEL] ---" - # 检查是否已有 autofix EXISTING=$(gh api \ /repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER/autofix \ --jq '.status' 2>/dev/null || echo "none") @@ -78,7 +77,6 @@ jobs: continue fi - # 检查分支是否已存在 BRANCH_STATUS=$(gh api \ /repos/$OWNER/$REPO/git/refs/heads/$BRANCH \ --silent 2>/dev/null && echo "exists" || echo "not_found") @@ -87,7 +85,6 @@ jobs: HAS_CODE_FIX=false if [ "$BRANCH_STATUS" = "not_found" ]; then - # 分支不存在,创建分支并提交 fix SHA=$(gh api /repos/$OWNER/$REPO/git/refs/heads/$DEFAULT_BRANCH \ --jq '.object.sha') @@ -109,7 +106,6 @@ jobs: HAS_CODE_FIX=false fi else - # 分支已存在,检查是否已有 open PR EXISTING_PR=$(gh pr list \ --repo "$OWNER/$REPO" \ --head "$BRANCH" \ @@ -126,7 +122,6 @@ jobs: HAS_CODE_FIX=true fi - # 获取 alert 详情 ALERT_INFO=$(gh api \ /repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER) @@ -148,7 +143,6 @@ jobs: FIX_NOTE="> ⚠️ **此 alert 没有自动代码修复**,AI 仅提供了修复建议,需要**手动按照上方 AI 修复思路修改代码**后再 merge。" fi - # 创建 Draft PR gh pr create \ --repo "$OWNER/$REPO" \ --base "$DEFAULT_BRANCH" \ @@ -198,3 +192,5 @@ jobs: $FIX_NOTE" && \ echo "🎉 PR created for alert #$NUMBER" || \ echo "❌ Failed to create PR for alert #$NUMBER" + + done From f066aed57d930c79da2c931c554f0f59cc2a31dd Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Fri, 1 May 2026 13:36:45 +0800 Subject: [PATCH 18/59] ci:improved --- .github/workflows/codeql-to-commit.yml | 33 +++++++++++++------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/.github/workflows/codeql-to-commit.yml b/.github/workflows/codeql-to-commit.yml index 0a6fa8e2..149e7395 100644 --- a/.github/workflows/codeql-to-commit.yml +++ b/.github/workflows/codeql-to-commit.yml @@ -48,6 +48,7 @@ jobs: echo "--- Alert #$NUMBER [$SEC_LEVEL] ---" + # 检查是否已有 autofix EXISTING=$(gh api \ /repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER/autofix \ --jq '.status' 2>/dev/null || echo "none") @@ -77,14 +78,14 @@ jobs: continue fi + # 检查分支是否已存在 BRANCH_STATUS=$(gh api \ /repos/$OWNER/$REPO/git/refs/heads/$BRANCH \ --silent 2>/dev/null && echo "exists" || echo "not_found") echo "DEBUG branch status: $BRANCH_STATUS" - HAS_CODE_FIX=false - if [ "$BRANCH_STATUS" = "not_found" ]; then + # 创建分支 SHA=$(gh api /repos/$OWNER/$REPO/git/refs/heads/$DEFAULT_BRANCH \ --jq '.object.sha') @@ -93,6 +94,7 @@ jobs: -f sha="$SHA" 2>/dev/null || true echo "🌿 Created branch: $BRANCH" + # 提交 fix COMMIT_RESULT=$(gh api -X POST \ /repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER/autofix/commits \ -f target_ref="$BRANCH" 2>&1) @@ -100,12 +102,14 @@ jobs: if echo "$COMMIT_RESULT" | grep -q "target_ref"; then echo "✅ Committed fix to branch: $BRANCH" - HAS_CODE_FIX=true else - echo "⚠️ No code changes generated, advisory PR only" - HAS_CODE_FIX=false + echo "⚠️ No code changes generated, deleting branch and skipping" + gh api -X DELETE \ + /repos/$OWNER/$REPO/git/refs/heads/$BRANCH 2>/dev/null || true + continue fi else + # 分支已存在,检查是否已有 open PR EXISTING_PR=$(gh pr list \ --repo "$OWNER/$REPO" \ --head "$BRANCH" \ @@ -119,9 +123,9 @@ jobs: fi echo "🌿 Branch exists, creating PR with existing branch" - HAS_CODE_FIX=true fi + # 获取 alert 详情 ALERT_INFO=$(gh api \ /repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER) @@ -137,12 +141,7 @@ jobs: /repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER/autofix \ --jq '.description // "暂无 AI 修复说明"') - if [ "$HAS_CODE_FIX" = "true" ]; then - FIX_NOTE="> 此 PR 包含 Copilot Autofix 自动生成的代码修复,请审核后 merge。" - else - FIX_NOTE="> ⚠️ **此 alert 没有自动代码修复**,AI 仅提供了修复建议,需要**手动按照上方 AI 修复思路修改代码**后再 merge。" - fi - + # 创建 Draft PR gh pr create \ --repo "$OWNER/$REPO" \ --base "$DEFAULT_BRANCH" \ @@ -189,8 +188,8 @@ jobs: --- - $FIX_NOTE" && \ - echo "🎉 PR created for alert #$NUMBER" || \ - echo "❌ Failed to create PR for alert #$NUMBER" - - done + > 此 PR 由 GitHub Copilot Autofix 自动生成,请仔细审核后再 merge。" && \ + echo "🎉 PR created for alert #$NUMBER" || \ + echo "❌ Failed to create PR for alert #$NUMBER" + + done From d922ecc464dca5e02c8030fad48bedfbef8def6a Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Fri, 1 May 2026 05:43:36 +0000 Subject: [PATCH 19/59] Potential fix for code scanning alert no. 62 Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> --- .../ModuleConfigure_Json/ModuleConfigure_Json.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/XEngine_Source/AuthorizeModule_Configure/ModuleConfigure_Json/ModuleConfigure_Json.cpp b/XEngine_Source/AuthorizeModule_Configure/ModuleConfigure_Json/ModuleConfigure_Json.cpp index 904cea7d..8415d37e 100644 --- a/XEngine_Source/AuthorizeModule_Configure/ModuleConfigure_Json/ModuleConfigure_Json.cpp +++ b/XEngine_Source/AuthorizeModule_Configure/ModuleConfigure_Json/ModuleConfigure_Json.cpp @@ -1,5 +1,6 @@ #include "pch.h" #include "ModuleConfigure_Json.h" +#include /******************************************************************** // Created: 2021/12/02 16:14:11 // File Name: D:\XEngine_ServiceApp\XEngine_Source\XEngine_ModuleConfigure\ModuleConfigure_Json\ModuleConfigure_Json.cpp @@ -284,7 +285,7 @@ bool CModuleConfigure_Json::ModuleConfigure_Json_Versions(LPCXSTR lpszConfigFile return false; } Json::Value st_JsonXVer = st_JsonRoot["XVer"]; - pSt_ServerConfig->st_XVer.pStl_ListVer = new list; + pSt_ServerConfig->st_XVer.pStl_ListVer = new (std::nothrow) list; if (NULL == pSt_ServerConfig->st_XVer.pStl_ListVer) { Config_IsErrorOccur = true; From d2720a51cb24c9e91effe1566b27c36d09baea1b Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Fri, 12 Jun 2026 15:22:50 +0800 Subject: [PATCH 20/59] update:vs to 2026 --- .../AuthorizeModule_Configure.vcxproj | 12 ++++++------ .../AuthorizeModule_Database.vcxproj | 12 ++++++------ .../AuthorizeModule_Help.vcxproj | 12 ++++++------ .../AuthorizeModule_Protocol.vcxproj | 12 ++++++------ .../AuthorizeModule_Session.vcxproj | 12 ++++++------ .../XEngine_AuthorizeApp.vcxproj | 12 ++++++------ .../XEngine_AuthorizeService.vcxproj | 12 ++++++------ XEngine_Source/XEngine_DependLibrary | 2 +- 8 files changed, 43 insertions(+), 43 deletions(-) diff --git a/XEngine_Source/AuthorizeModule_Configure/AuthorizeModule_Configure.vcxproj b/XEngine_Source/AuthorizeModule_Configure/AuthorizeModule_Configure.vcxproj index 4fcbc8a7..59deec7a 100644 --- a/XEngine_Source/AuthorizeModule_Configure/AuthorizeModule_Configure.vcxproj +++ b/XEngine_Source/AuthorizeModule_Configure/AuthorizeModule_Configure.vcxproj @@ -37,39 +37,39 @@ DynamicLibrary true - v143 + v145 Unicode DynamicLibrary false - v143 + v145 true Unicode DynamicLibrary true - v143 + v145 MultiByte DynamicLibrary true - v143 + v145 MultiByte DynamicLibrary false - v143 + v145 true Unicode DynamicLibrary false - v143 + v145 true Unicode diff --git a/XEngine_Source/AuthorizeModule_Database/AuthorizeModule_Database.vcxproj b/XEngine_Source/AuthorizeModule_Database/AuthorizeModule_Database.vcxproj index 9fc66506..05b07435 100644 --- a/XEngine_Source/AuthorizeModule_Database/AuthorizeModule_Database.vcxproj +++ b/XEngine_Source/AuthorizeModule_Database/AuthorizeModule_Database.vcxproj @@ -37,39 +37,39 @@ DynamicLibrary true - v143 + v145 Unicode DynamicLibrary false - v143 + v145 true Unicode DynamicLibrary true - v143 + v145 MultiByte DynamicLibrary true - v143 + v145 MultiByte DynamicLibrary false - v143 + v145 true Unicode DynamicLibrary false - v143 + v145 true Unicode diff --git a/XEngine_Source/AuthorizeModule_Help/AuthorizeModule_Help.vcxproj b/XEngine_Source/AuthorizeModule_Help/AuthorizeModule_Help.vcxproj index 2d8e1b60..2c016fbb 100644 --- a/XEngine_Source/AuthorizeModule_Help/AuthorizeModule_Help.vcxproj +++ b/XEngine_Source/AuthorizeModule_Help/AuthorizeModule_Help.vcxproj @@ -37,39 +37,39 @@ DynamicLibrary true - v143 + v145 Unicode DynamicLibrary false - v143 + v145 true Unicode DynamicLibrary true - v143 + v145 MultiByte DynamicLibrary true - v143 + v145 MultiByte DynamicLibrary false - v143 + v145 true Unicode DynamicLibrary false - v143 + v145 true Unicode diff --git a/XEngine_Source/AuthorizeModule_Protocol/AuthorizeModule_Protocol.vcxproj b/XEngine_Source/AuthorizeModule_Protocol/AuthorizeModule_Protocol.vcxproj index 693e0fd2..429463c4 100644 --- a/XEngine_Source/AuthorizeModule_Protocol/AuthorizeModule_Protocol.vcxproj +++ b/XEngine_Source/AuthorizeModule_Protocol/AuthorizeModule_Protocol.vcxproj @@ -37,39 +37,39 @@ DynamicLibrary true - v143 + v145 Unicode DynamicLibrary false - v143 + v145 true Unicode DynamicLibrary true - v143 + v145 MultiByte DynamicLibrary true - v143 + v145 MultiByte DynamicLibrary false - v143 + v145 true Unicode DynamicLibrary false - v143 + v145 true Unicode diff --git a/XEngine_Source/AuthorizeModule_Session/AuthorizeModule_Session.vcxproj b/XEngine_Source/AuthorizeModule_Session/AuthorizeModule_Session.vcxproj index 68c2dfa0..30589c5f 100644 --- a/XEngine_Source/AuthorizeModule_Session/AuthorizeModule_Session.vcxproj +++ b/XEngine_Source/AuthorizeModule_Session/AuthorizeModule_Session.vcxproj @@ -37,39 +37,39 @@ DynamicLibrary true - v143 + v145 Unicode DynamicLibrary false - v143 + v145 true Unicode DynamicLibrary true - v143 + v145 MultiByte DynamicLibrary true - v143 + v145 MultiByte DynamicLibrary false - v143 + v145 true Unicode DynamicLibrary false - v143 + v145 true Unicode diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/XEngine_AuthorizeApp.vcxproj b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/XEngine_AuthorizeApp.vcxproj index 16cc6b90..5b1f6e3d 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/XEngine_AuthorizeApp.vcxproj +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/XEngine_AuthorizeApp.vcxproj @@ -37,14 +37,14 @@ Application true - v143 + v145 Unicode Dynamic Application false - v143 + v145 true Unicode Static @@ -52,21 +52,21 @@ Application true - v143 + v145 Unicode Static Application true - v143 + v145 Unicode Static Application false - v143 + v145 true Unicode Static @@ -74,7 +74,7 @@ Application false - v143 + v145 true Unicode Static diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/XEngine_AuthorizeService.vcxproj b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/XEngine_AuthorizeService.vcxproj index bdd8488b..f5d112df 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/XEngine_AuthorizeService.vcxproj +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/XEngine_AuthorizeService.vcxproj @@ -37,39 +37,39 @@ Application true - v143 + v145 Unicode Application false - v143 + v145 true Unicode Application true - v143 + v145 MultiByte Application true - v143 + v145 MultiByte Application false - v143 + v145 true Unicode Application false - v143 + v145 true Unicode diff --git a/XEngine_Source/XEngine_DependLibrary b/XEngine_Source/XEngine_DependLibrary index 207abe8b..8b6a9413 160000 --- a/XEngine_Source/XEngine_DependLibrary +++ b/XEngine_Source/XEngine_DependLibrary @@ -1 +1 @@ -Subproject commit 207abe8b617744e35bf1438a03536d898ddc93fd +Subproject commit 8b6a9413ad3407b06abea611a7b89a0e968e36c0 From e2aec4ca2002a908d5af5d091c1a359f7e7d39a6 Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Fri, 12 Jun 2026 15:28:13 +0800 Subject: [PATCH 21/59] ci:delete cppcheck.yml and issue-translator.yml --- .github/workflows/cppcheck.yml | 35 -------------------------- .github/workflows/issue-translator.yml | 15 ----------- 2 files changed, 50 deletions(-) delete mode 100644 .github/workflows/cppcheck.yml delete mode 100644 .github/workflows/issue-translator.yml diff --git a/.github/workflows/cppcheck.yml b/.github/workflows/cppcheck.yml deleted file mode 100644 index 0a6eb20c..00000000 --- a/.github/workflows/cppcheck.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: cpp check workflows - -on: - push: - branches: - - 'develop' - paths: - - 'XEngine_Source/**' - - 'XEngine_Release/**' - - '.github/**' - -jobs: - build: - runs-on: ubuntu-latest - - steps: - - name: Checkout main repository code - uses: actions/checkout@v6 - with: - ref: 'develop' - - - name: Create static_analysis directory - run: mkdir -p static_analysis - - - name: Run Cppcheck - run: | - sudo apt-get install -y cppcheck - cppcheck --enable=all --language=c++ --std=c++20 ./XEngine_Source/ --output-file=static_analysis/log.xml --xml - continue-on-error: true - - - name: Upload Cppcheck Results - uses: actions/upload-artifact@v6 - with: - name: cppcheck_results - path: static_analysis/log.xml \ No newline at end of file diff --git a/.github/workflows/issue-translator.yml b/.github/workflows/issue-translator.yml deleted file mode 100644 index d9fdac8f..00000000 --- a/.github/workflows/issue-translator.yml +++ /dev/null @@ -1,15 +0,0 @@ -name: Issue Translator -on: - issue_comment: - types: [created] - issues: - types: [opened] - -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: usthe/issues-translate-action@v2.7 - with: - IS_MODIFY_TITLE: false - CUSTOM_BOT_NOTE: Bot detected the issue body's language is not English, translate it automatically. \ No newline at end of file From 98a663eeebecbfa05d60d74a16e2db343aadacb3 Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Fri, 12 Jun 2026 15:28:27 +0800 Subject: [PATCH 22/59] ci:update --- .github/workflows/Centos_build.yml | 2 +- .github/workflows/Rocky_build.yml | 2 +- .github/workflows/Ubuntu_build.yml | 8 ++++---- .github/workflows/auto-code.md | 17 +++++++++-------- .github/workflows/debian_build.yml | 2 +- .github/workflows/fedora_build.yml | 7 ++++++- .github/workflows/issue-triage.md | 12 +++++++----- .github/workflows/macbuild.yml | 4 ++-- .github/workflows/msbuild.yml | 8 ++++---- 9 files changed, 35 insertions(+), 27 deletions(-) diff --git a/.github/workflows/Centos_build.yml b/.github/workflows/Centos_build.yml index 24f0c2ca..5b0ce688 100644 --- a/.github/workflows/Centos_build.yml +++ b/.github/workflows/Centos_build.yml @@ -93,7 +93,7 @@ jobs: ./XEngine_AuthorizeService -t - name: Upload folder as artifact - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: XEngine_AuthorizeService-CentOS_${{ matrix.version }}_${{ matrix.artifact }} path: XEngine_Release/ \ No newline at end of file diff --git a/.github/workflows/Rocky_build.yml b/.github/workflows/Rocky_build.yml index 96a5b7d3..0ff263d1 100644 --- a/.github/workflows/Rocky_build.yml +++ b/.github/workflows/Rocky_build.yml @@ -95,7 +95,7 @@ jobs: ./XEngine_AuthorizeService -t - name: Upload folder as artifact with RockyLinux - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: XEngine_AuthorizeService-RockyLinux_${{ matrix.version }}_${{ matrix.artifact }} path: XEngine_Release/ diff --git a/.github/workflows/Ubuntu_build.yml b/.github/workflows/Ubuntu_build.yml index 3eea97a5..c500ad31 100644 --- a/.github/workflows/Ubuntu_build.yml +++ b/.github/workflows/Ubuntu_build.yml @@ -102,28 +102,28 @@ jobs: - name: Upload folder as artifact with ubuntu22.04 if: matrix.os == 'ubuntu-22.04' - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: XEngine_AuthorizeService-Ubuntu_22.04_x86-64 path: XEngine_Release/ retention-days: 1 - name: Upload folder as artifact with ubuntu24.04 if: matrix.os == 'ubuntu-24.04' - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: XEngine_AuthorizeService-Ubuntu_24.04_x86-64 path: XEngine_Release/ retention-days: 1 - name: Upload folder as artifact with ubuntu24.04 arm64 if: matrix.os == 'ubuntu-24.04-arm' - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: XEngine_AuthorizeService-Ubuntu_24.04_Arm64 path: XEngine_Release/ retention-days: 1 - name: Upload folder as artifact with ubuntu22.04 arm64 if: matrix.os == 'ubuntu-22.04-arm' - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: XEngine_AuthorizeService-Ubuntu_22.04_Arm64 path: XEngine_Release/ diff --git a/.github/workflows/auto-code.md b/.github/workflows/auto-code.md index 205c22f6..84eb1258 100644 --- a/.github/workflows/auto-code.md +++ b/.github/workflows/auto-code.md @@ -4,19 +4,20 @@ on: types: [labeled] engine: - id: codex - model: gpt-5.3-codex + id: copilot env: - OPENAI_BASE_URL: "https://api.zhizengzeng.com/v1" - OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + COPILOT_PROVIDER_BASE_URL: "https://ark.cn-beijing.volces.com/api/v3" + COPILOT_MODEL: doubao-seed-2-0-code-preview-260215 + COPILOT_PROVIDER_API_KEY: ${{ secrets.OPENAI_API_KEY }} + COPILOT_PROVIDER_TYPE: openai network: allowed: - - api.zhizengzeng.com + - defaults + - ark.cn-beijing.volces.com sandbox: agent: false - strict: false tools: @@ -52,7 +53,7 @@ safe-outputs: ## Bug 修复流程 1. 阅读 Issue 的完整标题和正文,理解问题现象 -2. 浏览仓库代码,定位问题所在的文件和函数 +2. 浏览仓库代码和文档,定位问题所在的文件和函数 3. 分析根本原因 4. 实现修复方案,注意: - 保持与现有代码风格一致 @@ -70,7 +71,7 @@ safe-outputs: ## 新功能开发流程 1. 阅读 Issue 的完整标题和正文,理解需求目标 -2. 浏览仓库现有代码结构,找到最相关的模块和文件 +2. 浏览仓库现有代码结构和文档,找到最相关的模块和文件 3. 制定实现方案: - 需要新增哪些文件或函数 - 需要修改哪些现有文件 diff --git a/.github/workflows/debian_build.yml b/.github/workflows/debian_build.yml index b7bd871f..3b39b1b6 100644 --- a/.github/workflows/debian_build.yml +++ b/.github/workflows/debian_build.yml @@ -81,7 +81,7 @@ jobs: ./XEngine_AuthorizeService -t - name: Upload folder as artifact - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: XEngine_AuthorizeService-Debian_${{ matrix.version }}_x86-64 path: XEngine_Release/ diff --git a/.github/workflows/fedora_build.yml b/.github/workflows/fedora_build.yml index 22966aa2..494e8476 100644 --- a/.github/workflows/fedora_build.yml +++ b/.github/workflows/fedora_build.yml @@ -21,6 +21,11 @@ jobs: strategy: matrix: include: + - arch: amd64 + runner: ubuntu-24.04 + platform: linux/amd64 + fedora-version: 43 + artifact: x86-64 - arch: amd64 runner: ubuntu-24.04 platform: linux/amd64 @@ -82,7 +87,7 @@ jobs: ./XEngine_AuthorizeService -t - name: Upload folder as artifact - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: XEngine_AuthorizeService-Fedora_${{ matrix.fedora-version }}_${{ matrix.artifact }} path: XEngine_Release/ diff --git a/.github/workflows/issue-triage.md b/.github/workflows/issue-triage.md index c040be9d..0b491b11 100644 --- a/.github/workflows/issue-triage.md +++ b/.github/workflows/issue-triage.md @@ -4,15 +4,17 @@ on: types: [opened, reopened] engine: - id: codex - model: gpt-5.3-codex + id: copilot env: - OPENAI_BASE_URL: "https://api.zhizengzeng.com/v1" - OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + COPILOT_PROVIDER_BASE_URL: "https://ark.cn-beijing.volces.com/api/v3" + COPILOT_MODEL: doubao-seed-2-0-code-preview-260215 + COPILOT_PROVIDER_API_KEY: ${{ secrets.OPENAI_API_KEY }} + COPILOT_PROVIDER_TYPE: openai network: allowed: - - api.zhizengzeng.com + - defaults + - ark.cn-beijing.volces.com sandbox: agent: false diff --git a/.github/workflows/macbuild.yml b/.github/workflows/macbuild.yml index 911b9418..f026f4b1 100644 --- a/.github/workflows/macbuild.yml +++ b/.github/workflows/macbuild.yml @@ -85,14 +85,14 @@ jobs: - name: Upload folder as artifact with mac x64 if: matrix.os == 'macos-15-intel' - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: XEngine_AuthorizeService-Mac_x86-64 path: XEngine_Release/ retention-days: 1 - name: Upload folder as artifact with mac arm if: matrix.os == 'macos-15' - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: XEngine_AuthorizeService-Mac_Arm64 path: XEngine_Release/ diff --git a/.github/workflows/msbuild.yml b/.github/workflows/msbuild.yml index 55ff8d28..ce077eca 100644 --- a/.github/workflows/msbuild.yml +++ b/.github/workflows/msbuild.yml @@ -16,7 +16,7 @@ jobs: matrix: configuration: [Debug ,Release] platform: [x86 ,x64 ,ARM64] - runs-on: windows-latest # 最新的 Windows 环境 + runs-on: windows-2025-vs2026 steps: # 检出您的主仓库代码 @@ -110,21 +110,21 @@ jobs: - name: Upload folder as artifact with x86 if: matrix.configuration == 'Release' && matrix.platform == 'x86' - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: XEngine_AuthorizeService-Windows_x86-32 path: XEngine_Release/ retention-days: 1 - name: Upload folder as artifact with x64 if: matrix.configuration == 'Release' && matrix.platform == 'x64' - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: XEngine_AuthorizeService-Windows_x86-64 path: XEngine_Release/ retention-days: 1 - name: Upload folder as artifact with Arm64 if: matrix.configuration == 'Release' && matrix.platform == 'Arm64' - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: XEngine_AuthorizeService-Windows_Arm64 path: XEngine_Release/ From 075f305ad21e235ea6eaff17c3300831dce3c737 Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Fri, 12 Jun 2026 16:03:21 +0800 Subject: [PATCH 23/59] feat: add agentic workflows for issue triage and auto fix --- .github/workflows/agentics-maintenance.yml | 607 ++++++++++++++++++++ .github/workflows/auto-code.lock.yml | 637 +++++++++++++++------ .github/workflows/auto-code.md | 4 - .github/workflows/codeql-to-commit.yml | 194 +++++++ .github/workflows/codeql.yml | 16 +- .github/workflows/issue-triage.lock.yml | 605 +++++++++++++------ .github/workflows/issue-triage.md | 4 - 7 files changed, 1714 insertions(+), 353 deletions(-) create mode 100644 .github/workflows/agentics-maintenance.yml create mode 100644 .github/workflows/codeql-to-commit.yml diff --git a/.github/workflows/agentics-maintenance.yml b/.github/workflows/agentics-maintenance.yml new file mode 100644 index 00000000..6bd015f5 --- /dev/null +++ b/.github/workflows/agentics-maintenance.yml @@ -0,0 +1,607 @@ +# ___ _ _ +# / _ \ | | (_) +# | |_| | __ _ ___ _ __ | |_ _ ___ +# | _ |/ _` |/ _ \ '_ \| __| |/ __| +# | | | | (_| | __/ | | | |_| | (__ +# \_| |_/\__, |\___|_| |_|\__|_|\___| +# __/ | +# _ _ |___/ +# | | | | / _| | +# | | | | ___ _ __ _ __| |_| | _____ ____ +# | |/\| |/ _ \ '__| |/ /| _| |/ _ \ \ /\ / / ___| +# \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ +# \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ +# +# This file was automatically generated by pkg/workflow/maintenance_workflow.go (v0.79.6). DO NOT EDIT. +# +# To regenerate this workflow, run: +# gh aw compile +# Not all edits will cause changes to this file. +# +# For more information: https://github.github.com/gh-aw/introduction/overview/ +# +# Alternative regeneration methods: +# make recompile +# +# Or use the gh-aw CLI directly: +# ./gh-aw compile --validate --verbose +# +# The workflow is generated when any workflow uses the 'expires' field +# in create-discussions, create-issues, or create-pull-request safe-outputs configuration. +# Schedule frequency is automatically determined by the shortest expiration time. +# +name: Agentic Maintenance + +on: + schedule: + - cron: "37 0 * * *" # Daily (based on minimum expires: 30 days) + workflow_dispatch: + inputs: + operation: + description: 'Optional maintenance operation to run' + required: false + type: choice + default: '' + options: + - '' + - 'disable' + - 'enable' + - 'update' + - 'upgrade' + - 'safe_outputs' + - 'create_labels' + - 'activity_report' + - 'close_agentic_workflows_issues' + - 'clean_cache_memories' + - 'update_pull_request_branches' + - 'validate' + - 'forecast' + run_url: + description: 'Run URL or run ID to replay safe outputs from (e.g. https://github.com/owner/repo/actions/runs/12345 or 12345). Required when operation is safe_outputs.' + required: false + type: string + default: '' + workflow_call: + inputs: + operation: + description: 'Optional maintenance operation to run (disable, enable, update, upgrade, safe_outputs, create_labels, activity_report, close_agentic_workflows_issues, clean_cache_memories, update_pull_request_branches, validate, forecast)' + required: false + type: string + default: '' + run_url: + description: 'Run URL or run ID to replay safe outputs from (e.g. https://github.com/owner/repo/actions/runs/12345 or 12345). Required when operation is safe_outputs.' + required: false + type: string + default: '' + outputs: + operation_completed: + description: 'The maintenance operation that was completed (empty when none ran or a scheduled job ran)' + value: ${{ jobs.run_operation.outputs.operation || inputs.operation }} + applied_run_url: + description: 'The run URL that safe outputs were applied from' + value: ${{ jobs.apply_safe_outputs.outputs.run_url }} + +permissions: {} + +jobs: + close-expired-entities: + if: ${{ (!(github.event.repository.fork)) && github.event_name != 'push' && (github.event_name != 'workflow_dispatch' && github.event_name != 'workflow_call' || inputs.operation == '') }} + runs-on: ubuntu-slim + permissions: + discussions: write + issues: write + pull-requests: write + steps: + - name: Setup Scripts + uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 + with: + destination: ${{ runner.temp }}/gh-aw/actions + + - name: Close expired discussions + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/close_expired_discussions.cjs'); + await main(); + + - name: Close expired issues + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/close_expired_issues.cjs'); + await main(); + + - name: Close expired pull requests + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/close_expired_pull_requests.cjs'); + await main(); + + cleanup-cache-memory: + if: ${{ (!(github.event.repository.fork)) && github.event_name != 'push' && (github.event_name != 'workflow_dispatch' && github.event_name != 'workflow_call' || inputs.operation == '' || inputs.operation == 'clean_cache_memories') }} + runs-on: ubuntu-slim + permissions: + actions: write + steps: + - name: Setup Scripts + uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 + with: + destination: ${{ runner.temp }}/gh-aw/actions + + - name: Cleanup outdated cache-memory entries + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/cleanup_cache_memory.cjs'); + await main(); + + run_operation: + if: ${{ (github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation != '' && inputs.operation != 'safe_outputs' && inputs.operation != 'create_labels' && inputs.operation != 'activity_report' && inputs.operation != 'close_agentic_workflows_issues' && inputs.operation != 'clean_cache_memories' && inputs.operation != 'update_pull_request_branches' && inputs.operation != 'validate' && inputs.operation != 'forecast' && (!(github.event.repository.fork)) }} + runs-on: ubuntu-slim + permissions: + actions: write + contents: write + pull-requests: write + outputs: + operation: ${{ steps.record.outputs.operation }} + steps: + - name: Checkout repository + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + persist-credentials: false + + - name: Setup Scripts + uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 + with: + destination: ${{ runner.temp }}/gh-aw/actions + + - name: Check admin/maintainer permissions + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/check_team_member.cjs'); + await main(); + + - name: Install gh-aw + uses: github/gh-aw-actions/setup-cli@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 + with: + version: v0.79.6 + + - name: Run operation + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_AW_OPERATION: ${{ inputs.operation }} + GH_AW_CMD_PREFIX: gh aw + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/run_operation_update_upgrade.cjs'); + await main(); + + - name: Record outputs + id: record + run: echo "operation=${{ inputs.operation }}" >> "$GITHUB_OUTPUT" + + update_pull_request_branches: + if: ${{ (github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation == 'update_pull_request_branches' && (!(github.event.repository.fork)) }} + runs-on: ubuntu-slim + permissions: + contents: write + pull-requests: write + steps: + - name: Setup Scripts + uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 + with: + destination: ${{ runner.temp }}/gh-aw/actions + + - name: Check admin/maintainer permissions + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/check_team_member.cjs'); + await main(); + + - name: Update pull request branches + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/update_pull_request_branches.cjs'); + await main(); + + apply_safe_outputs: + if: ${{ (github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation == 'safe_outputs' && (!(github.event.repository.fork)) }} + runs-on: ubuntu-slim + permissions: + actions: read + contents: write + discussions: write + issues: write + pull-requests: write + outputs: + run_url: ${{ steps.record.outputs.run_url }} + steps: + - name: Checkout actions folder + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + sparse-checkout: | + actions + persist-credentials: false + + - name: Setup Scripts + uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 + with: + destination: ${{ runner.temp }}/gh-aw/actions + + - name: Check admin/maintainer permissions + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/check_team_member.cjs'); + await main(); + + - name: Apply Safe Outputs + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_AW_RUN_URL: ${{ inputs.run_url }} + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/apply_safe_outputs_replay.cjs'); + await main(); + + - name: Record outputs + id: record + run: echo "run_url=${{ inputs.run_url }}" >> "$GITHUB_OUTPUT" + + create_labels: + if: ${{ (github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation == 'create_labels' && (!(github.event.repository.fork)) }} + runs-on: ubuntu-slim + permissions: + contents: read + issues: write + steps: + - name: Checkout repository + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + persist-credentials: false + + - name: Setup Scripts + uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 + with: + destination: ${{ runner.temp }}/gh-aw/actions + + - name: Check admin/maintainer permissions + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/check_team_member.cjs'); + await main(); + + - name: Install gh-aw + uses: github/gh-aw-actions/setup-cli@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 + with: + version: v0.79.6 + + - name: Create missing labels + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_CMD_PREFIX: gh aw + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/create_labels.cjs'); + await main(); + + activity_report: + if: ${{ (github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation == 'activity_report' && (!(github.event.repository.fork)) }} + runs-on: ubuntu-slim + timeout-minutes: 120 + permissions: + actions: read + contents: read + issues: write + steps: + - name: Checkout repository + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + persist-credentials: false + + - name: Setup Scripts + uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 + with: + destination: ${{ runner.temp }}/gh-aw/actions + + - name: Check admin/maintainer permissions + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/check_team_member.cjs'); + await main(); + + - name: Install gh-aw + uses: github/gh-aw-actions/setup-cli@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 + with: + version: v0.79.6 + + - name: Restore activity report logs cache + id: activity_report_logs_cache + uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + path: ./.cache/gh-aw/activity-report-logs + key: ${{ runner.os }}-activity-report-logs-${{ github.repository }}-${{ github.ref_name }}-${{ github.run_id }} + restore-keys: | + ${{ runner.os }}-activity-report-logs-${{ github.repository }}- + ${{ runner.os }}-activity-report-logs- + - name: Download activity report logs + timeout-minutes: 20 + shell: bash + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_AW_CMD_PREFIX: gh aw + run: | + ${GH_AW_CMD_PREFIX} logs \ + --repo "${{ github.repository }}" \ + --start-date -1w \ + --count 100 \ + --output ./.cache/gh-aw/activity-report-logs \ + --format markdown \ + > ./.cache/gh-aw/activity-report-logs/report.md + + - name: Save activity report logs cache + if: ${{ always() }} + uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + path: ./.cache/gh-aw/activity-report-logs + key: ${{ steps.activity_report_logs_cache.outputs.cache-primary-key }} + + - name: Generate activity report issue + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const fs = require('node:fs'); + const reportPath = './.cache/gh-aw/activity-report-logs/report.md'; + if (!fs.existsSync(reportPath)) { + core.warning('Activity report markdown not found at ' + reportPath + '; skipping issue creation.'); + return; + } + let reportBody = ''; + try { + reportBody = fs.readFileSync(reportPath, 'utf8').trim(); + } catch (error) { + core.warning('Failed to read activity report markdown at ' + reportPath + ': ' + error.message); + return; + } + if (!reportBody) { + core.warning('Activity report markdown is empty at ' + reportPath + '; skipping issue creation.'); + return; + } + const repoSlug = context.repo.owner + '/' + context.repo.repo; + const body = [ + '### Agentic workflow activity report', + '', + 'Repository: ' + repoSlug, + 'Generated at: ' + new Date().toISOString(), + '', + reportBody, + ].join('\n'); + const createdIssue = await github.rest.issues.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title: '[aw] agentic status report', + body, + labels: ['agentic-workflows'], + }); + core.info('Created issue #' + createdIssue.data.number + ': ' + createdIssue.data.html_url); + + forecast_report: + if: ${{ (github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation == 'forecast' && (!(github.event.repository.fork)) }} + runs-on: ubuntu-slim + timeout-minutes: 60 + permissions: + actions: read + contents: read + issues: write + steps: + - name: Checkout repository + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + persist-credentials: false + + - name: Setup Scripts + uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 + with: + destination: ${{ runner.temp }}/gh-aw/actions + + - name: Check admin/maintainer permissions + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/check_team_member.cjs'); + await main(); + + - name: Install gh-aw + uses: github/gh-aw-actions/setup-cli@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 + with: + version: v0.79.6 + + - name: Restore forecast report logs cache + id: forecast_report_logs_cache + uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + path: ./.github/aw/logs + key: ${{ runner.os }}-forecast-report-logs-${{ github.repository }}-${{ github.ref_name }}-${{ github.run_id }} + restore-keys: | + ${{ runner.os }}-forecast-report-logs-${{ github.repository }}- + ${{ runner.os }}-forecast-report-logs- + + - name: Generate forecast report + id: generate_forecast_report + timeout-minutes: 30 + shell: bash + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + DEBUG: "*" + GH_AW_CMD_PREFIX: gh aw + run: | + mkdir -p ./.cache/gh-aw/forecast + set +e + ${GH_AW_CMD_PREFIX} forecast --repo "${{ github.repository }}" --timeout 30 --verbose --json > ./.cache/gh-aw/forecast/report.json + forecast_exit_code=$? + set -e + if [ "${forecast_exit_code}" -eq 124 ]; then + echo '{"outcome":"timeout","message":"Forecast computation timed out after 30 minutes."}' > ./.cache/gh-aw/forecast/error.json + echo "::error::Forecast computation timed out after 30 minutes." + exit 1 + fi + if [ "${forecast_exit_code}" -ne 0 ]; then + echo '{"outcome":"error","message":"Forecast computation failed before producing a report."}' > ./.cache/gh-aw/forecast/error.json + echo "::error::Forecast computation failed with exit code ${forecast_exit_code}." + exit 1 + fi + + - name: Debug forecast logs folder + if: ${{ always() }} + shell: bash + run: | + if [ ! -d ./.github/aw/logs ]; then + echo "Logs directory not found: ./.github/aw/logs" + exit 0 + fi + echo "Files under ./.github/aw/logs:" + find ./.github/aw/logs -type f | sort + + - name: Save forecast report logs cache + if: ${{ always() }} + uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + path: ./.github/aw/logs + key: ${{ runner.os }}-forecast-report-logs-${{ github.repository }}-${{ github.ref_name }}-${{ github.run_id }} + + - name: Generate forecast issue + if: ${{ always() }} + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + FORECAST_STEP_OUTCOME: ${{ steps.generate_forecast_report.outcome }} + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/create_forecast_issue.cjs'); + await main(); + + close_agentic_workflows_issues: + if: ${{ (github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation == 'close_agentic_workflows_issues' && (!(github.event.repository.fork)) }} + runs-on: ubuntu-slim + permissions: + issues: write + steps: + - name: Setup Scripts + uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 + with: + destination: ${{ runner.temp }}/gh-aw/actions + + - name: Check admin/maintainer permissions + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/check_team_member.cjs'); + await main(); + + - name: Close no-repro agentic-workflows issues + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/close_agentic_workflows_issues.cjs'); + await main(); + + validate_workflows: + if: ${{ (github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation == 'validate' && (!(github.event.repository.fork)) }} + runs-on: ubuntu-latest + permissions: + contents: read + issues: write + steps: + - name: Checkout repository + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + persist-credentials: false + + - name: Setup Scripts + uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 + with: + destination: ${{ runner.temp }}/gh-aw/actions + + - name: Check admin/maintainer permissions + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/check_team_member.cjs'); + await main(); + + - name: Install gh-aw + uses: github/gh-aw-actions/setup-cli@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 + with: + version: v0.79.6 + + - name: Validate workflows and file issue on findings + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_CMD_PREFIX: gh aw + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/run_validate_workflows.cjs'); + await main(); diff --git a/.github/workflows/auto-code.lock.yml b/.github/workflows/auto-code.lock.yml index 9e107834..a986bab2 100644 --- a/.github/workflows/auto-code.lock.yml +++ b/.github/workflows/auto-code.lock.yml @@ -1,5 +1,5 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"c3f4c5f63fbb5f81f3b96a004386e91dd5572ded66b0b7fa8a545eb5aea77e19","compiler_version":"v0.68.3","agent_id":"codex","agent_model":"gpt-5.3-codex"} -# gh-aw-manifest: {"version":1,"secrets":["CODEX_API_KEY","GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/setup-node","sha":"53b83947a5a98c8d113130e565377fae1a50d02f","version":"v6.3.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"ba90f2186d7ad780ec640f364005fa24e797b360","version":"v0.68.3"}],"containers":[{"image":"ghcr.io/github/github-mcp-server:v0.32.0"},{"image":"node:lts-alpine"}]} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"f34010347cc4a69b71b53db22f8dc512613b8882c182be2d39f5926593e3272a","body_hash":"9959a757362d73cb28768bc2f9a90afc30a49f61e3226f922c791d0cbf387678","compiler_version":"v0.79.6","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}} +# gh-aw-manifest: {"version":1,"secrets":["GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"5c2fe865bb4dc46e1450f6ee0d0541d759aea73a","version":"v0.79.6"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2","digest":"sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2","digest":"sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2@sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2","digest":"sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2@sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.25","digest":"sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.25@sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa"},{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]} # ___ _ _ # / _ \ | | (_) # | |_| | __ _ ___ _ __ | |_ _ ___ @@ -14,7 +14,7 @@ # \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ # \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ # -# This file was automatically generated by gh-aw (v0.68.3). DO NOT EDIT. +# This file was automatically generated by gh-aw (v0.79.6). DO NOT EDIT. # # To update this file, edit the corresponding .md file and run: # gh aw compile @@ -24,7 +24,6 @@ # # # Secrets used: -# - CODEX_API_KEY # - GH_AW_CI_TRIGGER_TOKEN # - GH_AW_GITHUB_MCP_SERVER_TOKEN # - GH_AW_GITHUB_TOKEN @@ -32,19 +31,21 @@ # - OPENAI_API_KEY # # Custom actions used: -# - actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 +# - actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 # - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 -# - actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 -# - actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 +# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 # - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 -# - github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 +# - github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 # # Container images used: -# - ghcr.io/github/github-mcp-server:v0.32.0 -# - node:lts-alpine +# - ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6 +# - ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2@sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4 +# - ghcr.io/github/gh-aw-firewall/squid:0.27.2@sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591 +# - ghcr.io/github/gh-aw-mcpg:v0.3.25@sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa +# - ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c name: "自动处理 Issue" -"on": +on: issues: types: - labeled @@ -64,13 +65,20 @@ jobs: permissions: actions: read contents: read + env: + GH_AW_MAX_DAILY_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_MAX_DAILY_AI_CREDITS || '5000' }} outputs: body: ${{ steps.sanitized.outputs.body }} comment_id: "" comment_repo: "" + daily_effective_workflow_exceeded: ${{ steps.daily-effective-workflow-guardrail.outputs.daily_effective_workflow_exceeded == 'true' }} + daily_effective_workflow_threshold: ${{ steps.daily-effective-workflow-guardrail.outputs.daily_effective_workflow_threshold || '' }} + daily_effective_workflow_total_effective_tokens: ${{ steps.daily-effective-workflow-guardrail.outputs.daily_effective_workflow_total_effective_tokens || '' }} + engine_id: ${{ steps.generate_aw_info.outputs.engine_id }} lockdown_check_failed: ${{ steps.generate_aw_info.outputs.lockdown_check_failed == 'true' }} model: ${{ steps.generate_aw_info.outputs.model }} - secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} + 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 }} stale_lock_file_failed: ${{ steps.check-lock-file.outputs.stale_lock_file_failed == 'true' }} text: ${{ steps.sanitized.outputs.text }} @@ -78,55 +86,88 @@ jobs: steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 + uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 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 }} + safe-output-artifact-client: ${{ env.GH_AW_MAX_DAILY_AI_CREDITS != '' }} + env: + GH_AW_SETUP_WORKFLOW_NAME: "自动处理 Issue" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/auto-code.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_AWF_VERSION: "v0.27.2" + GH_AW_INFO_ENGINE_ID: "copilot" - 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: "gpt-5.3-codex" - GH_AW_INFO_VERSION: "0.118.0" - GH_AW_INFO_AGENT_VERSION: "0.118.0" - GH_AW_INFO_CLI_VERSION: "v0.68.3" + GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_INFO_ENGINE_NAME: "GitHub Copilot CLI" + GH_AW_INFO_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || vars.GH_AW_DEFAULT_MODEL_COPILOT || 'claude-sonnet-4.6' }} + GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_AGENT_VERSION: "1.0.60" + GH_AW_INFO_CLI_VERSION: "v0.79.6" GH_AW_INFO_WORKFLOW_NAME: "自动处理 Issue" GH_AW_INFO_EXPERIMENTAL: "false" GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true" GH_AW_INFO_STAGED: "false" - GH_AW_INFO_ALLOWED_DOMAINS: '["api.zhizengzeng.com"]' - GH_AW_INFO_FIREWALL_ENABLED: "false" - GH_AW_INFO_AWF_VERSION: "" + GH_AW_INFO_ALLOWED_DOMAINS: '["defaults","ark.cn-beijing.volces.com"]' + GH_AW_INFO_FIREWALL_ENABLED: "true" + GH_AW_INFO_AWF_VERSION: "v0.27.2" GH_AW_INFO_AWMG_VERSION: "" - GH_AW_INFO_FIREWALL_TYPE: "" - GH_AW_COMPILED_STRICT: "false" - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + GH_AW_INFO_FIREWALL_TYPE: "squid" + GH_AW_COMPILED_STRICT: "true" + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); setupGlobals(core, github, context, exec, io, getOctokit); const { main } = require('${{ runner.temp }}/gh-aw/actions/generate_aw_info.cjs'); await main(core, context); - - name: Validate CODEX_API_KEY or OPENAI_API_KEY secret - id: validate-secret - run: bash "${RUNNER_TEMP}/gh-aw/actions/validate_multi_secret.sh" CODEX_API_KEY OPENAI_API_KEY Codex https://github.github.com/gh-aw/reference/engines/#openai-codex + - name: Check daily workflow token guardrail + id: daily-effective-workflow-guardrail + if: ${{ env.GH_AW_MAX_DAILY_AI_CREDITS != '' }} + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: - CODEX_API_KEY: ${{ secrets.CODEX_API_KEY }} - OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + GH_AW_WORKFLOW_NAME: "自动处理 Issue" + GH_AW_WORKFLOW_ID: "auto-code" + 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_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_AW_MAX_DAILY_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_MAX_DAILY_AI_CREDITS || '5000' }} + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/check_daily_aic_workflow_guardrail.cjs'); + await main(); - name: Checkout .github and .agents folders - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: persist-credentials: false sparse-checkout: | .github .agents + .antigravity + .claude + .codex + .crush + .gemini + .opencode + .pi sparse-checkout-cone-mode: true fetch-depth: 1 + - name: Save agent config folders for base branch restoration + env: + GH_AW_AGENT_FOLDERS: ".agents .antigravity .claude .codex .crush .gemini .github .opencode .pi" + GH_AW_AGENT_FILES: ".crush.json AGENTS.md ANTIGRAVITY.md CLAUDE.md GEMINI.md PI.md opencode.jsonc" + # poutine:ignore untrusted_checkout_exec + run: bash "${RUNNER_TEMP}/gh-aw/actions/save_base_github_folders.sh" - name: Check workflow lock file id: check-lock-file - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_WORKFLOW_FILE: "auto-code.lock.yml" GH_AW_CONTEXT_WORKFLOW_REF: "${{ github.workflow_ref }}" @@ -137,9 +178,9 @@ jobs: const { main } = require('${{ runner.temp }}/gh-aw/actions/check_workflow_timestamp_api.cjs'); await main(); - name: Check compile-agentic version - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: - GH_AW_COMPILED_VERSION: "v0.68.3" + GH_AW_COMPILED_VERSION: "v0.79.6" with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); @@ -148,7 +189,9 @@ jobs: await main(); - name: Compute current body text id: sanitized - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,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,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); @@ -159,11 +202,12 @@ jobs: env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ runner.temp }}/gh-aw/safeoutputs/outputs.jsonl + GH_AW_EXPR_1A3A194A: ${{ github.event.discussion.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'discussion' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} + GH_AW_EXPR_463A214A: ${{ github.event.pull_request.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'pull_request' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} + GH_AW_EXPR_802A9F6A: ${{ github.event.issue.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'issue' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} + GH_AW_EXPR_FF1D34CE: ${{ github.event.comment.id || fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').comment_id }} GH_AW_GITHUB_ACTOR: ${{ github.actor }} - GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} - GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} - GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} @@ -171,59 +215,63 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_5258e6a960ff65c1_EOF' + cat << 'GH_AW_PROMPT_791c723be483e095_EOF' - GH_AW_PROMPT_5258e6a960ff65c1_EOF + GH_AW_PROMPT_791c723be483e095_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_5258e6a960ff65c1_EOF' + cat << 'GH_AW_PROMPT_791c723be483e095_EOF' Tools: add_comment, create_pull_request, missing_tool, missing_data, noop - GH_AW_PROMPT_5258e6a960ff65c1_EOF + GH_AW_PROMPT_791c723be483e095_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_create_pull_request.md" - cat << 'GH_AW_PROMPT_5258e6a960ff65c1_EOF' + cat << 'GH_AW_PROMPT_791c723be483e095_EOF' + GH_AW_PROMPT_791c723be483e095_EOF + cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" + cat << 'GH_AW_PROMPT_791c723be483e095_EOF' The following GitHub context information is available for this workflow: - {{#if __GH_AW_GITHUB_ACTOR__ }} + {{#if github.actor}} - **actor**: __GH_AW_GITHUB_ACTOR__ {{/if}} - {{#if __GH_AW_GITHUB_REPOSITORY__ }} + {{#if github.repository}} - **repository**: __GH_AW_GITHUB_REPOSITORY__ {{/if}} - {{#if __GH_AW_GITHUB_WORKSPACE__ }} + {{#if github.workspace}} - **workspace**: __GH_AW_GITHUB_WORKSPACE__ {{/if}} - {{#if __GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ }} - - **issue-number**: #__GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ + {{#if github.event.issue.number || (github.aw.context.item_type == 'issue' && github.aw.context.item_number)}} + - **issue-number**: #__GH_AW_EXPR_802A9F6A__ {{/if}} - {{#if __GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ }} - - **discussion-number**: #__GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ + {{#if github.event.discussion.number || (github.aw.context.item_type == 'discussion' && github.aw.context.item_number)}} + - **discussion-number**: #__GH_AW_EXPR_1A3A194A__ {{/if}} - {{#if __GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ }} - - **pull-request-number**: #__GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ + {{#if github.event.pull_request.number || (github.aw.context.item_type == 'pull_request' && github.aw.context.item_number)}} + - **pull-request-number**: #__GH_AW_EXPR_463A214A__ {{/if}} - {{#if __GH_AW_GITHUB_EVENT_COMMENT_ID__ }} - - **comment-id**: __GH_AW_GITHUB_EVENT_COMMENT_ID__ + {{#if github.event.comment.id || github.aw.context.comment_id}} + - **comment-id**: __GH_AW_EXPR_FF1D34CE__ {{/if}} - {{#if __GH_AW_GITHUB_RUN_ID__ }} + {{#if github.run_id}} - **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__ {{/if}} - GH_AW_PROMPT_5258e6a960ff65c1_EOF + GH_AW_PROMPT_791c723be483e095_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_5258e6a960ff65c1_EOF' + cat << 'GH_AW_PROMPT_791c723be483e095_EOF' {{#runtime-import .github/workflows/auto-code.md}} - GH_AW_PROMPT_5258e6a960ff65c1_EOF + GH_AW_PROMPT_791c723be483e095_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_ENGINE_ID: "copilot" GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} with: script: | @@ -232,17 +280,19 @@ jobs: const { main } = require('${{ runner.temp }}/gh-aw/actions/interpolate_prompt.cjs'); await main(); - name: Substitute placeholders - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_EXPR_1A3A194A: ${{ github.event.discussion.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'discussion' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} + GH_AW_EXPR_463A214A: ${{ github.event.pull_request.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'pull_request' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} + GH_AW_EXPR_802A9F6A: ${{ github.event.issue.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'issue' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} + GH_AW_EXPR_FF1D34CE: ${{ github.event.comment.id || fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').comment_id }} GH_AW_GITHUB_ACTOR: ${{ github.actor }} - GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} - GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} - GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} + GH_AW_MCP_CLI_SERVERS_LIST: '- `safeoutputs` — run `safeoutputs --help` to see available tools' GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: ${{ needs.pre_activation.outputs.activated }} with: script: | @@ -255,14 +305,16 @@ jobs: return await substitutePlaceholders({ file: process.env.GH_AW_PROMPT, substitutions: { + GH_AW_EXPR_1A3A194A: process.env.GH_AW_EXPR_1A3A194A, + GH_AW_EXPR_463A214A: process.env.GH_AW_EXPR_463A214A, + GH_AW_EXPR_802A9F6A: process.env.GH_AW_EXPR_802A9F6A, + GH_AW_EXPR_FF1D34CE: process.env.GH_AW_EXPR_FF1D34CE, GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR, - GH_AW_GITHUB_EVENT_COMMENT_ID: process.env.GH_AW_GITHUB_EVENT_COMMENT_ID, - GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: process.env.GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER, GH_AW_GITHUB_EVENT_ISSUE_NUMBER: process.env.GH_AW_GITHUB_EVENT_ISSUE_NUMBER, - GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: process.env.GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER, GH_AW_GITHUB_REPOSITORY: process.env.GH_AW_GITHUB_REPOSITORY, GH_AW_GITHUB_RUN_ID: process.env.GH_AW_GITHUB_RUN_ID, GH_AW_GITHUB_WORKSPACE: process.env.GH_AW_GITHUB_WORKSPACE, + GH_AW_MCP_CLI_SERVERS_LIST: process.env.GH_AW_MCP_CLI_SERVERS_LIST, GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: process.env.GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED } }); @@ -281,15 +333,24 @@ jobs: uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: activation + include-hidden-files: true path: | /tmp/gh-aw/aw_info.json + /tmp/gh-aw/model_multipliers.json + /tmp/gh-aw/models.json /tmp/gh-aw/aw-prompts/prompt.txt + /tmp/gh-aw/aw-prompts/prompt-template.txt + /tmp/gh-aw/aw-prompts/prompt-import-tree.json /tmp/gh-aw/github_rate_limits.jsonl + /tmp/gh-aw/base + /tmp/gh-aw/.github/agents + /tmp/gh-aw/.github/skills if-no-files-found: ignore retention-days: 1 agent: needs: activation + if: needs.activation.outputs.daily_effective_workflow_exceeded != 'true' runs-on: ubuntu-latest permissions: contents: read @@ -303,21 +364,38 @@ jobs: GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs GH_AW_WORKFLOW_ID_SANITIZED: autocode 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-mcp-gateway.outputs.aic }} + ambient_context: ${{ steps.parse-mcp-gateway.outputs.ambient_context }} checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} effective_tokens: ${{ steps.parse-mcp-gateway.outputs.effective_tokens }} has_patch: ${{ steps.collect_output.outputs.has_patch }} + inference_access_error: ${{ steps.detect-agent-errors.outputs.inference_access_error || 'false' }} + mcp_policy_error: ${{ steps.detect-agent-errors.outputs.mcp_policy_error || 'false' }} model: ${{ needs.activation.outputs.model }} + 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 }} + unknown_model_ai_credits: ${{ steps.parse-mcp-gateway.outputs.unknown_model_ai_credits || 'false' }} steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 + uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 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: "自动处理 Issue" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/auto-code.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_AWF_VERSION: "v0.27.2" + GH_AW_INFO_ENGINE_ID: "copilot" - name: Set runtime paths id: set-runtime-paths run: | @@ -327,7 +405,7 @@ jobs: echo "GH_AW_SAFE_OUTPUTS_TOOLS_PATH=${RUNNER_TEMP}/gh-aw/safeoutputs/tools.json" } >> "$GITHUB_OUTPUT" - name: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: persist-credentials: false - name: Create gh-aw temp directory @@ -352,8 +430,8 @@ jobs: - name: Checkout PR branch id: checkout-pr if: | - github.event.pull_request || github.event.issue.pull_request - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + github.event.pull_request || github.event.issue.pull_request || github.event_name == 'workflow_dispatch' && fromJSON(github.event.inputs.aw_context || '{}').item_type == 'pull_request' + 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: @@ -363,13 +441,12 @@ jobs: setupGlobals(core, github, context, exec, io, getOctokit); const { main } = require('${{ runner.temp }}/gh-aw/actions/checkout_pr_branch.cjs'); await main(); - - name: Setup Node.js - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 - with: - node-version: '24' - package-manager-cache: false - - name: Install Codex CLI - run: npm install --ignore-scripts -g @openai/codex@0.118.0 + - name: Install GitHub Copilot CLI + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.60 + env: + GH_HOST: github.com + - name: Install AWF binary + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.27.2 - name: Parse integrity filter lists id: parse-guard-vars env: @@ -377,17 +454,37 @@ jobs: GH_AW_TRUSTED_USERS_VAR: ${{ vars.GH_AW_GITHUB_TRUSTED_USERS || '' }} GH_AW_APPROVAL_LABELS_VAR: ${{ vars.GH_AW_GITHUB_APPROVAL_LABELS || '' }} run: bash "${RUNNER_TEMP}/gh-aw/actions/parse_guard_list.sh" + - name: Download activation artifact + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: activation + path: /tmp/gh-aw + - name: Restore agent config folders from base branch + if: steps.checkout-pr.outcome == 'success' + env: + GH_AW_AGENT_FOLDERS: ".agents .antigravity .claude .codex .crush .gemini .github .opencode .pi" + GH_AW_AGENT_FILES: ".crush.json AGENTS.md ANTIGRAVITY.md CLAUDE.md GEMINI.md PI.md opencode.jsonc" + 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: ".github/agents" + GH_AW_SUB_AGENT_EXT: ".agent.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: ".github/skills" + run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_inline_skills.sh" - name: Download container images - run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/github-mcp-server:v0.32.0 node:lts-alpine - - name: Write Safe Outputs Config + run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6 ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2@sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4 ghcr.io/github/gh-aw-firewall/squid:0.27.2@sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591 ghcr.io/github/gh-aw-mcpg:v0.3.25@sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c + - name: Generate Safe Outputs Config run: | mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs - cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_4193c32f65e9b5fd_EOF' - {"add_comment":{"max":1},"create_pull_request":{"base_branch":"develop","max":1,"max_patch_size":1024,"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"],"protected_path_prefixes":[".github/",".agents/"]},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} - GH_AW_SAFE_OUTPUTS_CONFIG_4193c32f65e9b5fd_EOF - - name: Write Safe Outputs Tools + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_8796a8c61fc66972_EOF' + {"add_comment":{"max":1},"create_pull_request":{"base_branch":"develop","max":1,"max_patch_files":100,"max_patch_size":1024,"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","CHANGELOG.md","SECURITY.md","CODE_OF_CONDUCT.md","AGENTS.md","CLAUDE.md","GEMINI.md"],"protected_files_policy":"request_review"},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} + GH_AW_SAFE_OUTPUTS_CONFIG_8796a8c61fc66972_EOF + - name: Generate Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | { @@ -425,6 +522,11 @@ jobs: "create_pull_request": { "defaultMax": 1, "fields": { + "base": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, "body": { "required": true, "type": "string", @@ -532,7 +634,7 @@ jobs: } } } - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); @@ -588,11 +690,12 @@ jobs: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} run: | set -eo pipefail - mkdir -p /tmp/gh-aw/mcp-config + mkdir -p "${RUNNER_TEMP}/gh-aw/mcp-config" # Export gateway environment variables for MCP config and gateway script - export MCP_GATEWAY_PORT="80" - export MCP_GATEWAY_DOMAIN="localhost" + export MCP_GATEWAY_PORT="8080" + export MCP_GATEWAY_DOMAIN="host.docker.internal" + export MCP_GATEWAY_HOST_DOMAIN="localhost" MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=') echo "::add-mask::${MCP_GATEWAY_API_KEY}" export MCP_GATEWAY_API_KEY @@ -601,47 +704,28 @@ jobs: export MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD="524288" export DEBUG="*" - export GH_AW_ENGINE="codex" - export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.2.19' - - cat > /tmp/gh-aw/mcp-config/config.toml << GH_AW_MCP_CONFIG_8d05bb28961e7647_EOF - [history] - persistence = "none" - - [shell_environment_policy] - inherit = "core" - include_only = ["CODEX_API_KEY", "GH_AW_ASSETS_ALLOWED_EXTS", "GH_AW_ASSETS_BRANCH", "GH_AW_ASSETS_MAX_SIZE_KB", "GH_AW_SAFE_OUTPUTS", "GITHUB_PERSONAL_ACCESS_TOKEN", "GITHUB_REPOSITORY", "GITHUB_SERVER_URL", "HOME", "OPENAI_API_KEY", "PATH"] - - [mcp_servers.github] - user_agent = "issue" - startup_timeout_sec = 120 - tool_timeout_sec = 60 - container = "ghcr.io/github/github-mcp-server:v0.32.0" - env = { "GITHUB_HOST" = "$GITHUB_SERVER_URL", "GITHUB_PERSONAL_ACCESS_TOKEN" = "$GH_AW_GITHUB_TOKEN", "GITHUB_READ_ONLY" = "1", "GITHUB_TOOLSETS" = "context,repos,issues,pull_requests" } - env_vars = ["GITHUB_HOST", "GITHUB_PERSONAL_ACCESS_TOKEN", "GITHUB_READ_ONLY", "GITHUB_TOOLSETS"] + export GH_AW_ENGINE="copilot" + MCP_GATEWAY_UID=$(id -u 2>/dev/null || echo '0') + MCP_GATEWAY_GID=$(id -g 2>/dev/null || echo '0') + case "${DOCKER_HOST:-}" in + unix://* ) DOCKER_SOCK_PATH="${DOCKER_HOST#unix://}" ;; + /* ) DOCKER_SOCK_PATH="$DOCKER_HOST" ;; + * ) DOCKER_SOCK_PATH=/var/run/docker.sock ;; + esac + DOCKER_SOCK_GID=$(stat -c '%g' "$DOCKER_SOCK_PATH" 2>/dev/null || echo '0') + export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --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_API_KEY -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_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.3.25' - [mcp_servers.safeoutputs] - type = "http" - url = "http://localhost:$GH_AW_SAFE_OUTPUTS_PORT" - - [mcp_servers.safeoutputs.headers] - Authorization = "$GH_AW_SAFE_OUTPUTS_API_KEY" - - [mcp_servers.safeoutputs."guard-policies"] - - [mcp_servers.safeoutputs."guard-policies".write-sink] - accept = ["*"] - GH_AW_MCP_CONFIG_8d05bb28961e7647_EOF - - # Generate JSON config for MCP gateway - cat << GH_AW_MCP_CONFIG_8d05bb28961e7647_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" + mkdir -p /home/runner/.copilot + GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) + cat << GH_AW_MCP_CONFIG_920bb1916fcb7fc4_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "github": { - "container": "ghcr.io/github/github-mcp-server:v0.32.0", + "type": "stdio", + "container": "ghcr.io/github/github-mcp-server:v1.1.2", "env": { - "GITHUB_HOST": "$GITHUB_SERVER_URL", - "GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_MCP_SERVER_TOKEN", + "GITHUB_HOST": "\${GITHUB_SERVER_URL}", + "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}", "GITHUB_READ_ONLY": "1", "GITHUB_TOOLSETS": "context,repos,issues,pull_requests" }, @@ -657,9 +741,9 @@ jobs: }, "safeoutputs": { "type": "http", - "url": "http://localhost:$GH_AW_SAFE_OUTPUTS_PORT", + "url": "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT", "headers": { - "Authorization": "$GH_AW_SAFE_OUTPUTS_API_KEY" + "Authorization": "\${GH_AW_SAFE_OUTPUTS_API_KEY}" }, "guard-policies": { "write-sink": { @@ -677,38 +761,99 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_8d05bb28961e7647_EOF - - name: Download activation artifact - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + GH_AW_MCP_CONFIG_920bb1916fcb7fc4_EOF + - name: Mount MCP servers as CLIs + id: mount-mcp-clis + continue-on-error: true + env: + MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }} + 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: - name: activation - path: /tmp/gh-aw - - name: Clean git credentials + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('${{ runner.temp }}/gh-aw/actions/mount_mcp_as_cli.cjs'); + await main(); + - name: Clean credentials continue-on-error: true run: bash "${RUNNER_TEMP}/gh-aw/actions/clean_git_credentials.sh" - - name: Execute Codex CLI + - 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: Execute GitHub Copilot CLI id: agentic_execution + # Copilot CLI tool arguments (sorted): + timeout-minutes: 20 run: | set -o pipefail + printf '%s' "$(date +%s%3N)" > /tmp/gh-aw/agent_cli_start_ms.txt + trap 'rm -f /home/runner/.copilot/settings.json' EXIT + mkdir -p /home/runner/.copilot + printf '%s' '{"builtInAgents":{"rubberDuck":false}}' > /home/runner/.copilot/settings.json touch /tmp/gh-aw/agent-step-summary.md + GH_AW_NODE_BIN=$(command -v node 2>/dev/null || true) + export GH_AW_NODE_BIN + export COPILOT_API_KEY="$COPILOT_DUMMY_BYOK" (umask 177 && touch /tmp/gh-aw/agent-stdio.log) - INSTRUCTION="$(cat "$GH_AW_PROMPT")" - mkdir -p "$CODEX_HOME/logs" - codex ${GH_AW_MODEL_AGENT_CODEX:+-c model="$GH_AW_MODEL_AGENT_CODEX" }exec -c web_search="disabled" -c fetch="disabled" --dangerously-bypass-approvals-and-sandbox --skip-git-repo-check "$INSTRUCTION" 2>&1 | tee /tmp/gh-aw/agent-stdio.log + GH_AW_MAX_AI_CREDITS="${{ vars.GH_AW_DEFAULT_MAX_AI_CREDITS || '1000' }}" + printf '%s\n' "{\"\$schema\":\"https://github.com/github/gh-aw-firewall/releases/download/v0.27.2/awf-config.schema.json\",\"network\":{\"allowDomains\":[\"api.business.githubcopilot.com\",\"api.enterprise.githubcopilot.com\",\"api.github.com\",\"api.githubcopilot.com\",\"api.individual.githubcopilot.com\",\"api.snapcraft.io\",\"archive.ubuntu.com\",\"ark.cn-beijing.volces.com\",\"azure.archive.ubuntu.com\",\"crl.geotrust.com\",\"crl.globalsign.com\",\"crl.identrust.com\",\"crl.sectigo.com\",\"crl.thawte.com\",\"crl.usertrust.com\",\"crl.verisign.com\",\"crl3.digicert.com\",\"crl4.digicert.com\",\"crls.ssl.com\",\"github.com\",\"host.docker.internal\",\"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\",\"ppa.launchpad.net\",\"raw.githubusercontent.com\",\"registry.npmjs.org\",\"s.symcb.com\",\"s.symcd.com\",\"security.ubuntu.com\",\"telemetry.enterprise.githubcopilot.com\",\"ts-crl.ws.symantec.com\",\"ts-ocsp.ws.symantec.com\",\"www.googleapis.com\"]},\"apiProxy\":{\"enabled\":true,\"enableTokenSteering\":true,\"maxRuns\":500,\"maxAiCredits\":${GH_AW_MAX_AI_CREDITS},\"models\":{\"agent\":[\"sonnet-6x\",\"gpt-5.4\",\"gpt-5.3\",\"gemini-pro\",\"any\"],\"antigravity\":[\"copilot/antigravity*\",\"google/antigravity*\",\"gemini/antigravity*\"],\"any\":[\"copilot/*\",\"anthropic/*\",\"openai/*\",\"google/*\",\"gemini/*\"],\"claude\":[\"agent\"],\"codex\":[\"agent\"],\"coding\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\",\"gpt-5-codex\"],\"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*\"],\"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-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-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.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*\"],\"haiku\":[\"copilot/*haiku*\",\"anthropic/*haiku*\"],\"large\":[\"sonnet\",\"gpt-5-pro\",\"gpt-5\",\"gemini-pro\"],\"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\"],\"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-4-5-*\",\"anthropic/*sonnet-4-5-*\",\"copilot/*sonnet-4-6*\",\"anthropic/*sonnet-4-6*\"],\"summarization\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash-lite\",\"mini\"],\"vision\":[\"copilot/gemini-*image*\",\"gemini/gemini-*image*\",\"copilot/gemini-*flash*\",\"gemini/gemini-*flash*\"]}},\"container\":{\"imageTag\":\"0.27.2,squid=sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591,agent=sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6,api-proxy=sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4,cli-proxy=sha256:02f3ec08f32dc26c5427920c6a2e2f3036238fce44802f2f11ef49ed8621b5d0\"}}" > "${RUNNER_TEMP}/gh-aw/awf-config.json" + GH_AW_MODEL_MULTIPLIERS_PATH="/tmp/gh-aw/model_multipliers.json" node "${RUNNER_TEMP}/gh-aw/actions/merge_awf_model_multipliers.cjs" + 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_PATH_PREFIX_ARGS="" + if [[ "${DOCKER_HOST:-}" =~ ^tcp:// ]]; then + GH_AW_DOCKER_HOST_PATH_PREFIX_ARGS="--docker-host-path-prefix /tmp/gh-aw" + fi + GH_AW_TOOL_CACHE_MOUNT="" + GH_AW_TOOL_CACHE="${RUNNER_TOOL_CACHE:-/opt/hostedtoolcache}" + 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 + elif [ -d "/home/runner/work/_tool" ]; then + GH_AW_TOOL_CACHE_MOUNT="/home/runner/work/_tool:/home/runner/work/_tool:ro" + fi + # shellcheck disable=SC1003 + sudo -E 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_PATH_PREFIX_ARGS} --env-all --exclude-env COPILOT_PROVIDER_API_KEY --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull \ + -- /bin/bash -c 'set +o histexpand; export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && GH_AW_TOOL_CACHE="${RUNNER_TOOL_CACHE:-/opt/hostedtoolcache}"; export PATH="$(find "$GH_AW_TOOL_CACHE" /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 5 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/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/copilot_harness.cjs /usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-all-tools --allow-all-paths --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log env: - CODEX_API_KEY: ${{ secrets.CODEX_API_KEY || secrets.OPENAI_API_KEY }} - CODEX_HOME: /tmp/gh-aw/mcp-config - GH_AW_MCP_CONFIG: /tmp/gh-aw/mcp-config/config.toml - GH_AW_MODEL_AGENT_CODEX: gpt-5.3-codex + AWF_REFLECT_ENABLED: 1 + COPILOT_AGENT_RUNNER_TYPE: STANDALONE + COPILOT_DUMMY_BYOK: dummy-byok-key-for-offline-mode + COPILOT_MODEL: doubao-seed-2-0-code-preview-260215 + COPILOT_PROVIDER_API_KEY: ${{ secrets.OPENAI_API_KEY }} + COPILOT_PROVIDER_BASE_URL: https://ark.cn-beijing.volces.com/api/v3 + COPILOT_PROVIDER_TYPE: openai + GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }} + GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json 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: v0.68.3 + GH_AW_TIMEOUT_MINUTES: 20 + GH_AW_VERSION: v0.79.6 + GITHUB_API_URL: ${{ github.api_url }} GITHUB_AW: true + GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows + GITHUB_HEAD_REF: ${{ github.head_ref }} + GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + GITHUB_REF_NAME: ${{ github.ref_name }} + GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md - OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - OPENAI_BASE_URL: https://api.zhizengzeng.com/v1 - RUST_LOG: trace,hyper_util=info,mio=info,reqwest=info,os_info=info,codex_otel=warn,codex_core=debug,ocodex_exec=debug + 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 }} + XDG_CONFIG_HOME: /home/runner + - name: Detect agent errors + if: always() + id: detect-agent-errors + continue-on-error: true + run: node "${RUNNER_TEMP}/gh-aw/actions/detect_agent_errors.cjs" - name: Configure Git credentials env: REPO_NAME: ${{ github.repository }} @@ -722,6 +867,10 @@ jobs: SERVER_URL_STRIPPED="${SERVER_URL#https://}" git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" echo "Git configured with standard GitHub Actions identity" + - name: Copy Copilot session state files to logs + if: always() + continue-on-error: true + run: bash "${RUNNER_TEMP}/gh-aw/actions/copy_copilot_session_state.sh" - name: Stop MCP Gateway if: always() continue-on-error: true @@ -733,7 +882,7 @@ jobs: bash "${RUNNER_TEMP}/gh-aw/actions/stop_mcp_gateway.sh" "$GATEWAY_PID" - name: Redact secrets in logs if: always() - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); @@ -741,8 +890,7 @@ jobs: const { main } = require('${{ runner.temp }}/gh-aw/actions/redact_secrets.cjs'); await main(); env: - GH_AW_SECRET_NAMES: 'CODEX_API_KEY,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN,OPENAI_API_KEY' - SECRET_CODEX_API_KEY: ${{ secrets.CODEX_API_KEY }} + GH_AW_SECRET_NAMES: 'GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN,OPENAI_API_KEY' SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -760,10 +908,10 @@ jobs: - name: Ingest agent output id: collect_output if: always() - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + 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: "172.30.0.1,api.openai.com,api.zhizengzeng.com,host.docker.internal,openai.com" + GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,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,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} with: @@ -774,25 +922,60 @@ jobs: await main(); - name: Parse agent logs for step summary if: always() - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: - GH_AW_AGENT_OUTPUT: /tmp/gh-aw/agent-stdio.log + GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/ with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_codex_log.cjs'); + const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_copilot_log.cjs'); await main(); - name: Parse MCP Gateway logs for step summary if: always() id: parse-mcp-gateway - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); setupGlobals(core, github, context, exec, io, getOctokit); const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_mcp_gateway_log.cjs'); await main(); + - name: Print firewall logs + if: always() + continue-on-error: true + env: + AWF_LOGS_DIR: /tmp/gh-aw/sandbox/firewall/logs + run: | + # Fix permissions on firewall logs/audit dirs so they can be uploaded as artifacts + # AWF runs with sudo, creating files owned by root + sudo chmod -R a+rX /tmp/gh-aw/sandbox/firewall 2>/dev/null || true + # Only run awf logs summary if awf command exists (it may not be installed if workflow failed before install step) + if command -v awf &> /dev/null; then + awf logs summary | tee -a "$GITHUB_STEP_SUMMARY" + else + echo 'AWF binary not installed, skipping firewall log summary' + fi + - name: Parse token usage for step summary + if: always() + continue-on-error: true + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/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 { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/awf_reflect_summary.cjs'); + await main(); - name: Write agent output placeholder if missing if: always() run: | @@ -807,18 +990,24 @@ jobs: name: agent path: | /tmp/gh-aw/aw-prompts/prompt.txt - /tmp/gh-aw/mcp-config/logs/ + /tmp/gh-aw/sandbox/agent/logs/ /tmp/gh-aw/redacted-urls.log /tmp/gh-aw/mcp-logs/ /tmp/gh-aw/proxy-logs/ !/tmp/gh-aw/proxy-logs/proxy-tls/ + /tmp/gh-aw/agent_usage.json /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/pre-agent-audit.txt /tmp/gh-aw/agent/ /tmp/gh-aw/github_rate_limits.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/sandbox/firewall/logs/ + /tmp/gh-aw/sandbox/firewall/audit/ + /tmp/gh-aw/sandbox/firewall/awf-reflect.json if-no-files-found: ignore conclusion: @@ -828,7 +1017,7 @@ jobs: - safe_outputs if: > always() && (needs.agent.result != 'skipped' || needs.activation.outputs.lockdown_check_failed == 'true' || - needs.activation.outputs.stale_lock_file_failed == 'true') + needs.activation.outputs.stale_lock_file_failed == 'true' || needs.activation.outputs.daily_effective_workflow_exceeded == 'true') runs-on: ubuntu-slim permissions: contents: write @@ -838,6 +1027,7 @@ jobs: concurrency: group: "gh-aw-conclusion-auto-code" cancel-in-progress: false + queue: max outputs: incomplete_count: ${{ steps.report_incomplete.outputs.incomplete_count }} noop_message: ${{ steps.noop.outputs.noop_message }} @@ -846,11 +1036,18 @@ jobs: steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 + uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 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: "自动处理 Issue" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/auto-code.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_AWF_VERSION: "v0.27.2" + GH_AW_INFO_ENGINE_ID: "copilot" - name: Download agent output artifact id: download-agent-output continue-on-error: true @@ -865,16 +1062,54 @@ jobs: mkdir -p /tmp/gh-aw/ find "/tmp/gh-aw/" -type f -print echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT" + - name: Collect usage artifact files + if: always() + continue-on-error: true + run: | + mkdir -p /tmp/gh-aw/usage/agent /tmp/gh-aw/usage/detection + echo "Usage artifact source file status:" + for file in /tmp/gh-aw/aw-info.jsonl /tmp/gh-aw/agent_usage.jsonl /tmp/gh-aw/detection_usage.jsonl /tmp/gh-aw/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/threat-detection/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/threat-detection/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/threat-detection/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl; do + [ -f "$file" ] && echo "FOUND: $file" || echo "MISSING: $file" + done + [ -f /tmp/gh-aw/aw-info.jsonl ] && cp /tmp/gh-aw/aw-info.jsonl /tmp/gh-aw/usage/aw-info.jsonl || true + [ -f /tmp/gh-aw/agent_usage.jsonl ] && cp /tmp/gh-aw/agent_usage.jsonl /tmp/gh-aw/usage/agent_usage.jsonl || true + [ -f /tmp/gh-aw/detection_usage.jsonl ] && cp /tmp/gh-aw/detection_usage.jsonl /tmp/gh-aw/usage/detection_usage.jsonl || true + [ -f /tmp/gh-aw/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl ] && cp /tmp/gh-aw/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/usage/agent/token_usage.jsonl || true + [ -f /tmp/gh-aw/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl ] && cp /tmp/gh-aw/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/usage/agent/token_usage.jsonl || true + [ -f /tmp/gh-aw/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl ] && cp /tmp/gh-aw/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/usage/agent/token_usage.jsonl || true + [ -f /tmp/gh-aw/threat-detection/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl ] && cp /tmp/gh-aw/threat-detection/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/usage/detection/token_usage.jsonl || true + [ -f /tmp/gh-aw/threat-detection/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl ] && cp /tmp/gh-aw/threat-detection/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/usage/detection/token_usage.jsonl || true + [ -f /tmp/gh-aw/threat-detection/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl ] && cp /tmp/gh-aw/threat-detection/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/usage/detection/token_usage.jsonl || true + [ -f /tmp/gh-aw/usage/agent/token_usage.jsonl ] || : > /tmp/gh-aw/usage/agent/token_usage.jsonl + [ -f /tmp/gh-aw/usage/detection/token_usage.jsonl ] || : > /tmp/gh-aw/usage/detection/token_usage.jsonl + find /tmp/gh-aw/usage -type f -print | sort + - name: Upload usage artifact + if: always() + continue-on-error: true + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: usage + path: | + /tmp/gh-aw/usage/aw-info.jsonl + /tmp/gh-aw/usage/agent_usage.jsonl + /tmp/gh-aw/usage/detection_usage.jsonl + /tmp/gh-aw/usage/agent/token_usage.jsonl + /tmp/gh-aw/usage/detection/token_usage.jsonl + if-no-files-found: ignore - name: Process no-op messages id: noop - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + 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: "1" GH_AW_WORKFLOW_NAME: "自动处理 Issue" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/auto-code.md" GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} GH_AW_NOOP_REPORT_AS_ISSUE: "true" + GH_AW_AIC: ${{ needs.agent.outputs.aic }} + GH_AW_AMBIENT_CONTEXT: ${{ needs.agent.outputs.ambient_context }} + GH_AW_WORKFLOW_ID: "auto-code" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -884,11 +1119,12 @@ jobs: await main(); - name: Record missing tool id: missing_tool - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + 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: "自动处理 Issue" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/auto-code.md" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -898,11 +1134,12 @@ jobs: await main(); - name: Record incomplete id: report_incomplete - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + 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: "自动处理 Issue" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/auto-code.md" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -913,22 +1150,38 @@ jobs: - name: Handle agent failure id: handle_agent_failure if: always() - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + 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: "自动处理 Issue" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/auto-code.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: "auto-code" - GH_AW_ENGINE_ID: "codex" - GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.activation.outputs.secret_verification_result }} + GH_AW_ACTION_FAILURE_ISSUE_EXPIRES_HOURS: "168" + GH_AW_ENGINE_ID: "copilot" GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} + GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens || '' }} + 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_MAX_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_MAX_AI_CREDITS || '1000' }} + 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_ENGINE_API_HOSTS: "api.enterprise.githubcopilot.com,api.githubcopilot.com,api.business.githubcopilot.com,api.individual.githubcopilot.com" 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_STALE_LOCK_FILE_FAILED: ${{ needs.activation.outputs.stale_lock_file_failed }} + GH_AW_DAILY_EFFECTIVE_WORKFLOW_EXCEEDED: ${{ needs.activation.outputs.daily_effective_workflow_exceeded }} + GH_AW_DAILY_EFFECTIVE_WORKFLOW_TOTAL_EFFECTIVE_TOKENS: ${{ needs.activation.outputs.daily_effective_workflow_total_effective_tokens }} + GH_AW_DAILY_EFFECTIVE_WORKFLOW_THRESHOLD: ${{ needs.activation.outputs.daily_effective_workflow_threshold }} 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" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} @@ -943,17 +1196,25 @@ jobs: outputs: activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} 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: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 + uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} + env: + GH_AW_SETUP_WORKFLOW_NAME: "自动处理 Issue" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/auto-code.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_AWF_VERSION: "v0.27.2" + GH_AW_INFO_ENGINE_ID: "copilot" - name: Check team membership for workflow id: check_membership - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_REQUIRED_ROLES: "admin,maintainer,write" with: @@ -975,14 +1236,19 @@ jobs: discussions: write issues: write pull-requests: write - timeout-minutes: 15 + 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 }}/auto-code" GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens }} - GH_AW_ENGINE_ID: "codex" - GH_AW_ENGINE_MODEL: "gpt-5.3-codex" + GH_AW_ENGINE_ID: "copilot" + GH_AW_ENGINE_MODEL: ${{ needs.agent.outputs.model }} + GH_AW_ENGINE_VERSION: "1.0.60" GH_AW_WORKFLOW_ID: "auto-code" GH_AW_WORKFLOW_NAME: "自动处理 Issue" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/auto-code.md" outputs: code_push_failure_count: ${{ steps.process_safe_outputs.outputs.code_push_failure_count }} code_push_failure_errors: ${{ steps.process_safe_outputs.outputs.code_push_failure_errors }} @@ -997,11 +1263,18 @@ jobs: steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 + uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 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: "自动处理 Issue" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/auto-code.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_AWF_VERSION: "v0.27.2" + GH_AW_INFO_ENGINE_ID: "copilot" - name: Download agent output artifact id: download-agent-output continue-on-error: true @@ -1022,9 +1295,27 @@ jobs: with: name: agent path: /tmp/gh-aw/ + - name: Extract base branch from agent output + id: extract-base-branch + if: steps.download-agent-output.outcome == 'success' + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/extract_base_branch_from_agent_output.cjs'); + await main(); + - name: Checkout repository (trusted default branch for comment events) + if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') && (github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment') + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + ref: ${{ github.event.repository.default_branch }} + token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + persist-credentials: false + fetch-depth: 1 - name: Checkout repository - if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') && github.event_name != 'issue_comment' && github.event_name != 'pull_request_review_comment' + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: ref: develop token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} @@ -1047,6 +1338,7 @@ jobs: - name: Configure GH_HOST for enterprise compatibility id: ghes-host-config shell: bash + # zizmor: ignore[github-env] - GITHUB_SERVER_URL is set by GitHub Actions, not user input. run: | # Derive GH_HOST from GITHUB_SERVER_URL so the gh CLI targets the correct # GitHub instance (GHES/GHEC). On github.com this is a harmless no-op. @@ -1055,13 +1347,14 @@ jobs: echo "GH_HOST=${GH_HOST}" >> "$GITHUB_ENV" - name: Process Safe Outputs id: process_safe_outputs - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + 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_ALLOWED_DOMAINS: "172.30.0.1,api.openai.com,api.zhizengzeng.com,host.docker.internal,openai.com" + GH_AW_COMMENT_ID: ${{ needs.activation.outputs.comment_id }} + GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,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,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.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},\"create_pull_request\":{\"base_branch\":\"develop\",\"max\":1,\"max_patch_size\":1024,\"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\",\"AGENTS.md\"],\"protected_path_prefixes\":[\".github/\",\".agents/\",\".codex/\"]},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"report_incomplete\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":1},\"create_pull_request\":{\"base_branch\":\"develop\",\"max\":1,\"max_patch_files\":100,\"max_patch_size\":1024,\"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\",\"CHANGELOG.md\",\"SECURITY.md\",\"CODE_OF_CONDUCT.md\",\"AGENTS.md\",\"CLAUDE.md\",\"GEMINI.md\"],\"protected_files_policy\":\"request_review\"},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"report_incomplete\":{}}" GH_AW_CI_TRIGGER_TOKEN: ${{ secrets.GH_AW_CI_TRIGGER_TOKEN }} with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/auto-code.md b/.github/workflows/auto-code.md index 84eb1258..a81501de 100644 --- a/.github/workflows/auto-code.md +++ b/.github/workflows/auto-code.md @@ -16,10 +16,6 @@ network: - defaults - ark.cn-beijing.volces.com -sandbox: - agent: false -strict: false - tools: github: min-integrity: none diff --git a/.github/workflows/codeql-to-commit.yml b/.github/workflows/codeql-to-commit.yml new file mode 100644 index 00000000..98ab97f9 --- /dev/null +++ b/.github/workflows/codeql-to-commit.yml @@ -0,0 +1,194 @@ +name: Auto Copilot Autofix (High & Medium Only) + +on: + workflow_dispatch: + workflow_run: + workflows: ["CodeQL Advanced"] + types: [completed] + +jobs: + auto-fix: + runs-on: ubuntu-latest + if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' }} + permissions: + security-events: read + contents: write + pull-requests: write + + steps: + - name: Trigger Autofix for High & Medium alerts + env: + GH_TOKEN: ${{ secrets.AUTOFIX_TOKEN }} + OWNER: ${{ github.repository_owner }} + REPO: ${{ github.event.repository.name }} + run: | + set +e + DEFAULT_BRANCH=$(gh api /repos/$OWNER/$REPO --jq '.default_branch') + echo "Default branch: $DEFAULT_BRANCH" + + ALERTS=$(gh api "/repos/$OWNER/$REPO/code-scanning/alerts?state=open&per_page=100" \ + --jq '[.[] | select(.rule.security_severity_level == "critical" or .rule.security_severity_level == "high" or .rule.security_severity_level == "medium" or .rule.severity == "warning") | {number: .number, level: (.rule.security_severity_level // .rule.severity)}]') + + COUNT=$(echo $ALERTS | jq 'length') + echo "Found $COUNT alerts with high / medium / warning" + echo "$ALERTS" | jq -r '.[] | " Alert #\(.number) [\(.level)]"' + + if [ "$COUNT" -eq 0 ]; then + echo "No alerts to process, exiting." + exit 0 + fi + + for ROW in $(echo $ALERTS | jq -r '.[] | @base64'); do + _jq() { echo "$ROW" | base64 -d | jq -r "$1"; } + + NUMBER=$(_jq '.number') + SEC_LEVEL=$(_jq '.level') + BRANCH="autofix/${SEC_LEVEL}/alert-${NUMBER}" + + echo "--- Alert #$NUMBER [$SEC_LEVEL] ---" + + # 检查是否已有 autofix + EXISTING=$(gh api \ + /repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER/autofix \ + --jq '.status' 2>/dev/null || echo "none") + + if [ "$EXISTING" = "success" ]; then + echo "✅ Fix already exists" + else + echo "⏳ Generating fix..." + gh api -X POST \ + /repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER/autofix || { + echo "⚠️ Failed to trigger autofix for #$NUMBER, skipping" + continue + } + + for i in 1 2 3; do + sleep 30 + EXISTING=$(gh api \ + /repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER/autofix \ + --jq '.status' 2>/dev/null || echo "none") + echo " Attempt $i: status = $EXISTING" + [ "$EXISTING" = "success" ] && break + done + fi + + if [ "$EXISTING" != "success" ]; then + echo "⚠️ Autofix not available for alert #$NUMBER (status: $EXISTING), skipping" + continue + fi + + # 检查分支是否已存在 + BRANCH_STATUS=$(gh api \ + /repos/$OWNER/$REPO/git/refs/heads/$BRANCH \ + --silent 2>/dev/null && echo "exists" || echo "not_found") + echo "DEBUG branch status: $BRANCH_STATUS" + + if [ "$BRANCH_STATUS" = "not_found" ]; then + # 创建分支 + SHA=$(gh api /repos/$OWNER/$REPO/git/refs/heads/$DEFAULT_BRANCH \ + --jq '.object.sha') + + gh api -X POST /repos/$OWNER/$REPO/git/refs \ + -f ref="refs/heads/$BRANCH" \ + -f sha="$SHA" 2>/dev/null || true + echo "🌿 Created branch: $BRANCH" + + # 提交 fix + COMMIT_RESULT=$(gh api -X POST \ + /repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER/autofix/commits \ + -f target_ref="$BRANCH" 2>&1) + echo "DEBUG commit result: $COMMIT_RESULT" + + if echo "$COMMIT_RESULT" | grep -q "target_ref"; then + echo "✅ Committed fix to branch: $BRANCH" + else + echo "⚠️ No code changes generated, deleting branch and skipping" + gh api -X DELETE \ + /repos/$OWNER/$REPO/git/refs/heads/$BRANCH 2>/dev/null || true + continue + fi + else + # 分支已存在,检查是否已有 open PR + EXISTING_PR=$(gh pr list \ + --repo "$OWNER/$REPO" \ + --head "$BRANCH" \ + --state open \ + --json number \ + --jq '.[0].number // empty') + + if [ -n "$EXISTING_PR" ]; then + echo "⏭️ PR #$EXISTING_PR already exists, skipping" + continue + fi + + echo "🌿 Branch exists, creating PR with existing branch" + fi + + # 获取 alert 详情 + ALERT_INFO=$(gh api \ + /repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER) + + ALERT_TITLE=$(echo $ALERT_INFO | jq -r '.rule.description') + ALERT_HELP=$(echo $ALERT_INFO | jq -r '.rule.help // "暂无详细说明"' | head -c 800) + ALERT_TAGS=$(echo $ALERT_INFO | jq -r '.rule.tags // [] | join(", ")') + ALERT_FILE=$(echo $ALERT_INFO | jq -r '.most_recent_instance.location.path // "未知文件"') + ALERT_LINE=$(echo $ALERT_INFO | jq -r '.most_recent_instance.location.start_line // "未知行"') + ALERT_URL=$(echo $ALERT_INFO | jq -r '.html_url') + CWE_TAGS=$(echo $ALERT_INFO | jq -r '[.rule.tags[] | select(startswith("external/cwe/"))] | join(", ")') + + AUTOFIX_DESC=$(gh api \ + /repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER/autofix \ + --jq '.description // "暂无 AI 修复说明"') + + # 创建 Draft PR + gh pr create \ + --repo "$OWNER/$REPO" \ + --base "$DEFAULT_BRANCH" \ + --head "$BRANCH" \ + --draft \ + --title "[Autofix][$SEC_LEVEL] Alert #$NUMBER: $ALERT_TITLE" \ + --body "## 🤖 Copilot Autofix 自动修复报告 + + --- + + ### 📋 基本信息 + + | 字段 | 内容 | + |------|------| + | **Alert ID** | [#$NUMBER]($ALERT_URL) | + | **安全级别** | $SEC_LEVEL | + | **规则名称** | $ALERT_TITLE | + | **问题文件** | \`$ALERT_FILE\` 第 $ALERT_LINE 行 | + | **CWE 分类** | $CWE_TAGS | + | **规则标签** | $ALERT_TAGS | + + --- + + ### 🔍 问题说明 + + $ALERT_HELP + + --- + + ### 🤖 AI 修复思路 + + $AUTOFIX_DESC + + --- + + ### ✅ Review 检查清单 + + - [ ] 理解了漏洞的成因和影响范围 + - [ ] 确认 AI 修复逻辑正确,没有遗漏边界情况 + - [ ] 确认修复没有改变原有业务逻辑 + - [ ] 确认没有引入新的安全问题 + - [ ] CI / 单元测试全部通过 + - [ ] 如有必要,已补充对应的测试用例 + + --- + + > 此 PR 由 GitHub Copilot Autofix 自动生成,请仔细审核后再 merge。" && \ + echo "🎉 PR created for alert #$NUMBER" || \ + echo "❌ Failed to create PR for alert #$NUMBER" + + done diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 603dd33a..598759b4 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -11,7 +11,7 @@ on: jobs: analyze: - runs-on: ubuntu-24.04 + runs-on: ubuntu-latest permissions: security-events: write packages: read @@ -23,6 +23,7 @@ jobs: matrix: include: - language: c-cpp + build-mode: manual steps: - name: Checkout repository uses: actions/checkout@v6 @@ -42,22 +43,29 @@ jobs: - name: Set TERM variable run: echo "TERM=xterm" >> $GITHUB_ENV - + - name: Set up Dependency Environment run: | cd libxengine chmod +x ./XEngine_LINEnv.sh sudo ./XEngine_LINEnv.sh -i 3 + - name: make pre + run: | + cd XEngine_Source + make BUILDTYPE=1 + - name: Initialize CodeQL uses: github/codeql-action/init@v4 with: languages: ${{ matrix.language }} + build-mode: manual + queries: security-and-quality - - name: make + - name: make check run: | cd XEngine_Source - make + make BUILDTYPE=2 - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v4 diff --git a/.github/workflows/issue-triage.lock.yml b/.github/workflows/issue-triage.lock.yml index 3aec2247..aa4e7c0d 100644 --- a/.github/workflows/issue-triage.lock.yml +++ b/.github/workflows/issue-triage.lock.yml @@ -1,5 +1,5 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"c0c5f2c83f233a2b2d7053d2e39295f1b1e4c15c8d47f623444564b774958447","compiler_version":"v0.68.3","agent_id":"codex","agent_model":"gpt-5.3-codex"} -# gh-aw-manifest: {"version":1,"secrets":["CODEX_API_KEY","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/setup-node","sha":"53b83947a5a98c8d113130e565377fae1a50d02f","version":"v6.3.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"ba90f2186d7ad780ec640f364005fa24e797b360","version":"v0.68.3"}],"containers":[{"image":"ghcr.io/github/github-mcp-server:v0.32.0"},{"image":"node:lts-alpine"}]} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"4c520dacbaee7bcbc706d7c10c4a7a33d6bf61ada259b815aa34aa9b3078f9c3","body_hash":"bf4f8784cdac578e246f253a70aa7f7acce80a6fcf1c9116a0f5867b9ece3260","compiler_version":"v0.79.6","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}} +# gh-aw-manifest: {"version":1,"secrets":["GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"5c2fe865bb4dc46e1450f6ee0d0541d759aea73a","version":"v0.79.6"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2","digest":"sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2","digest":"sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2@sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2","digest":"sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2@sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.25","digest":"sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.25@sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa"},{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]} # ___ _ _ # / _ \ | | (_) # | |_| | __ _ ___ _ __ | |_ _ ___ @@ -14,7 +14,7 @@ # \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ # \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ # -# This file was automatically generated by gh-aw (v0.68.3). DO NOT EDIT. +# This file was automatically generated by gh-aw (v0.79.6). DO NOT EDIT. # # To update this file, edit the corresponding .md file and run: # gh aw compile @@ -24,26 +24,27 @@ # # # Secrets used: -# - CODEX_API_KEY # - GH_AW_GITHUB_MCP_SERVER_TOKEN # - GH_AW_GITHUB_TOKEN # - GITHUB_TOKEN # - OPENAI_API_KEY # # Custom actions used: -# - actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 +# - actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 # - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 -# - actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 -# - actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 +# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 # - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 -# - github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 +# - github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 # # Container images used: -# - ghcr.io/github/github-mcp-server:v0.32.0 -# - node:lts-alpine +# - ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6 +# - ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2@sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4 +# - ghcr.io/github/gh-aw-firewall/squid:0.27.2@sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591 +# - ghcr.io/github/gh-aw-mcpg:v0.3.25@sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa +# - ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c name: "Issue 自动分类与回复" -"on": +on: issues: types: - opened @@ -64,13 +65,20 @@ jobs: permissions: actions: read contents: read + env: + GH_AW_MAX_DAILY_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_MAX_DAILY_AI_CREDITS || '5000' }} outputs: body: ${{ steps.sanitized.outputs.body }} comment_id: "" comment_repo: "" + daily_effective_workflow_exceeded: ${{ steps.daily-effective-workflow-guardrail.outputs.daily_effective_workflow_exceeded == 'true' }} + daily_effective_workflow_threshold: ${{ steps.daily-effective-workflow-guardrail.outputs.daily_effective_workflow_threshold || '' }} + daily_effective_workflow_total_effective_tokens: ${{ steps.daily-effective-workflow-guardrail.outputs.daily_effective_workflow_total_effective_tokens || '' }} + engine_id: ${{ steps.generate_aw_info.outputs.engine_id }} lockdown_check_failed: ${{ steps.generate_aw_info.outputs.lockdown_check_failed == 'true' }} model: ${{ steps.generate_aw_info.outputs.model }} - secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} + 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 }} stale_lock_file_failed: ${{ steps.check-lock-file.outputs.stale_lock_file_failed == 'true' }} text: ${{ steps.sanitized.outputs.text }} @@ -78,55 +86,88 @@ jobs: steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 + uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 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 }} + safe-output-artifact-client: ${{ env.GH_AW_MAX_DAILY_AI_CREDITS != '' }} + env: + GH_AW_SETUP_WORKFLOW_NAME: "Issue 自动分类与回复" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_AWF_VERSION: "v0.27.2" + GH_AW_INFO_ENGINE_ID: "copilot" - 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: "gpt-5.3-codex" - GH_AW_INFO_VERSION: "0.118.0" - GH_AW_INFO_AGENT_VERSION: "0.118.0" - GH_AW_INFO_CLI_VERSION: "v0.68.3" + GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_INFO_ENGINE_NAME: "GitHub Copilot CLI" + GH_AW_INFO_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || vars.GH_AW_DEFAULT_MODEL_COPILOT || 'claude-sonnet-4.6' }} + GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_AGENT_VERSION: "1.0.60" + GH_AW_INFO_CLI_VERSION: "v0.79.6" GH_AW_INFO_WORKFLOW_NAME: "Issue 自动分类与回复" GH_AW_INFO_EXPERIMENTAL: "false" GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true" GH_AW_INFO_STAGED: "false" - GH_AW_INFO_ALLOWED_DOMAINS: '["api.zhizengzeng.com"]' - GH_AW_INFO_FIREWALL_ENABLED: "false" - GH_AW_INFO_AWF_VERSION: "" + GH_AW_INFO_ALLOWED_DOMAINS: '["defaults","ark.cn-beijing.volces.com"]' + GH_AW_INFO_FIREWALL_ENABLED: "true" + GH_AW_INFO_AWF_VERSION: "v0.27.2" GH_AW_INFO_AWMG_VERSION: "" - GH_AW_INFO_FIREWALL_TYPE: "" - GH_AW_COMPILED_STRICT: "false" - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + GH_AW_INFO_FIREWALL_TYPE: "squid" + GH_AW_COMPILED_STRICT: "true" + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); setupGlobals(core, github, context, exec, io, getOctokit); const { main } = require('${{ runner.temp }}/gh-aw/actions/generate_aw_info.cjs'); await main(core, context); - - name: Validate CODEX_API_KEY or OPENAI_API_KEY secret - id: validate-secret - run: bash "${RUNNER_TEMP}/gh-aw/actions/validate_multi_secret.sh" CODEX_API_KEY OPENAI_API_KEY Codex https://github.github.com/gh-aw/reference/engines/#openai-codex + - name: Check daily workflow token guardrail + id: daily-effective-workflow-guardrail + if: ${{ env.GH_AW_MAX_DAILY_AI_CREDITS != '' }} + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: - CODEX_API_KEY: ${{ secrets.CODEX_API_KEY }} - OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + GH_AW_WORKFLOW_NAME: "Issue 自动分类与回复" + GH_AW_WORKFLOW_ID: "issue-triage" + 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_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_AW_MAX_DAILY_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_MAX_DAILY_AI_CREDITS || '5000' }} + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/check_daily_aic_workflow_guardrail.cjs'); + await main(); - name: Checkout .github and .agents folders - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: persist-credentials: false sparse-checkout: | .github .agents + .antigravity + .claude + .codex + .crush + .gemini + .opencode + .pi sparse-checkout-cone-mode: true fetch-depth: 1 + - name: Save agent config folders for base branch restoration + env: + GH_AW_AGENT_FOLDERS: ".agents .antigravity .claude .codex .crush .gemini .github .opencode .pi" + GH_AW_AGENT_FILES: ".crush.json AGENTS.md ANTIGRAVITY.md CLAUDE.md GEMINI.md PI.md opencode.jsonc" + # poutine:ignore untrusted_checkout_exec + run: bash "${RUNNER_TEMP}/gh-aw/actions/save_base_github_folders.sh" - name: Check workflow lock file id: check-lock-file - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_WORKFLOW_FILE: "issue-triage.lock.yml" GH_AW_CONTEXT_WORKFLOW_REF: "${{ github.workflow_ref }}" @@ -137,9 +178,9 @@ jobs: const { main } = require('${{ runner.temp }}/gh-aw/actions/check_workflow_timestamp_api.cjs'); await main(); - name: Check compile-agentic version - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: - GH_AW_COMPILED_VERSION: "v0.68.3" + GH_AW_COMPILED_VERSION: "v0.79.6" with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); @@ -148,7 +189,9 @@ jobs: await main(); - name: Compute current body text id: sanitized - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,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,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); @@ -159,11 +202,11 @@ jobs: env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ runner.temp }}/gh-aw/safeoutputs/outputs.jsonl + GH_AW_EXPR_1A3A194A: ${{ github.event.discussion.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'discussion' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} + GH_AW_EXPR_463A214A: ${{ github.event.pull_request.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'pull_request' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} + GH_AW_EXPR_802A9F6A: ${{ github.event.issue.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'issue' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} + GH_AW_EXPR_FF1D34CE: ${{ github.event.comment.id || fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').comment_id }} GH_AW_GITHUB_ACTOR: ${{ github.actor }} - GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} - GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} - GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} - GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} @@ -171,56 +214,60 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_5c03d90267ba9511_EOF' + cat << 'GH_AW_PROMPT_72243dd344875363_EOF' - GH_AW_PROMPT_5c03d90267ba9511_EOF + GH_AW_PROMPT_72243dd344875363_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_5c03d90267ba9511_EOF' + cat << 'GH_AW_PROMPT_72243dd344875363_EOF' Tools: add_comment, add_labels, missing_tool, missing_data, noop + GH_AW_PROMPT_72243dd344875363_EOF + cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" + cat << 'GH_AW_PROMPT_72243dd344875363_EOF' The following GitHub context information is available for this workflow: - {{#if __GH_AW_GITHUB_ACTOR__ }} + {{#if github.actor}} - **actor**: __GH_AW_GITHUB_ACTOR__ {{/if}} - {{#if __GH_AW_GITHUB_REPOSITORY__ }} + {{#if github.repository}} - **repository**: __GH_AW_GITHUB_REPOSITORY__ {{/if}} - {{#if __GH_AW_GITHUB_WORKSPACE__ }} + {{#if github.workspace}} - **workspace**: __GH_AW_GITHUB_WORKSPACE__ {{/if}} - {{#if __GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ }} - - **issue-number**: #__GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ + {{#if github.event.issue.number || (github.aw.context.item_type == 'issue' && github.aw.context.item_number)}} + - **issue-number**: #__GH_AW_EXPR_802A9F6A__ {{/if}} - {{#if __GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ }} - - **discussion-number**: #__GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ + {{#if github.event.discussion.number || (github.aw.context.item_type == 'discussion' && github.aw.context.item_number)}} + - **discussion-number**: #__GH_AW_EXPR_1A3A194A__ {{/if}} - {{#if __GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ }} - - **pull-request-number**: #__GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ + {{#if github.event.pull_request.number || (github.aw.context.item_type == 'pull_request' && github.aw.context.item_number)}} + - **pull-request-number**: #__GH_AW_EXPR_463A214A__ {{/if}} - {{#if __GH_AW_GITHUB_EVENT_COMMENT_ID__ }} - - **comment-id**: __GH_AW_GITHUB_EVENT_COMMENT_ID__ + {{#if github.event.comment.id || github.aw.context.comment_id}} + - **comment-id**: __GH_AW_EXPR_FF1D34CE__ {{/if}} - {{#if __GH_AW_GITHUB_RUN_ID__ }} + {{#if github.run_id}} - **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__ {{/if}} - GH_AW_PROMPT_5c03d90267ba9511_EOF + GH_AW_PROMPT_72243dd344875363_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_5c03d90267ba9511_EOF' + cat << 'GH_AW_PROMPT_72243dd344875363_EOF' {{#runtime-import .github/workflows/issue-triage.md}} - GH_AW_PROMPT_5c03d90267ba9511_EOF + GH_AW_PROMPT_72243dd344875363_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_ENGINE_ID: "copilot" GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} with: script: | @@ -229,17 +276,18 @@ jobs: const { main } = require('${{ runner.temp }}/gh-aw/actions/interpolate_prompt.cjs'); await main(); - name: Substitute placeholders - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_EXPR_1A3A194A: ${{ github.event.discussion.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'discussion' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} + GH_AW_EXPR_463A214A: ${{ github.event.pull_request.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'pull_request' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} + GH_AW_EXPR_802A9F6A: ${{ github.event.issue.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'issue' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} + GH_AW_EXPR_FF1D34CE: ${{ github.event.comment.id || fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').comment_id }} GH_AW_GITHUB_ACTOR: ${{ github.actor }} - GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} - GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} - GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} - GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} + GH_AW_MCP_CLI_SERVERS_LIST: '- `safeoutputs` — run `safeoutputs --help` to see available tools' GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: ${{ needs.pre_activation.outputs.activated }} with: script: | @@ -252,14 +300,15 @@ jobs: return await substitutePlaceholders({ file: process.env.GH_AW_PROMPT, substitutions: { + GH_AW_EXPR_1A3A194A: process.env.GH_AW_EXPR_1A3A194A, + GH_AW_EXPR_463A214A: process.env.GH_AW_EXPR_463A214A, + GH_AW_EXPR_802A9F6A: process.env.GH_AW_EXPR_802A9F6A, + GH_AW_EXPR_FF1D34CE: process.env.GH_AW_EXPR_FF1D34CE, GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR, - GH_AW_GITHUB_EVENT_COMMENT_ID: process.env.GH_AW_GITHUB_EVENT_COMMENT_ID, - GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: process.env.GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER, - GH_AW_GITHUB_EVENT_ISSUE_NUMBER: process.env.GH_AW_GITHUB_EVENT_ISSUE_NUMBER, - GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: process.env.GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER, GH_AW_GITHUB_REPOSITORY: process.env.GH_AW_GITHUB_REPOSITORY, GH_AW_GITHUB_RUN_ID: process.env.GH_AW_GITHUB_RUN_ID, GH_AW_GITHUB_WORKSPACE: process.env.GH_AW_GITHUB_WORKSPACE, + GH_AW_MCP_CLI_SERVERS_LIST: process.env.GH_AW_MCP_CLI_SERVERS_LIST, GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: process.env.GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED } }); @@ -278,15 +327,24 @@ jobs: uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: activation + include-hidden-files: true path: | /tmp/gh-aw/aw_info.json + /tmp/gh-aw/model_multipliers.json + /tmp/gh-aw/models.json /tmp/gh-aw/aw-prompts/prompt.txt + /tmp/gh-aw/aw-prompts/prompt-template.txt + /tmp/gh-aw/aw-prompts/prompt-import-tree.json /tmp/gh-aw/github_rate_limits.jsonl + /tmp/gh-aw/base + /tmp/gh-aw/.github/agents + /tmp/gh-aw/.github/skills if-no-files-found: ignore retention-days: 1 agent: needs: activation + if: needs.activation.outputs.daily_effective_workflow_exceeded != 'true' runs-on: ubuntu-latest permissions: contents: read @@ -300,21 +358,38 @@ jobs: GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs GH_AW_WORKFLOW_ID_SANITIZED: issuetriage 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-mcp-gateway.outputs.aic }} + ambient_context: ${{ steps.parse-mcp-gateway.outputs.ambient_context }} checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} effective_tokens: ${{ steps.parse-mcp-gateway.outputs.effective_tokens }} has_patch: ${{ steps.collect_output.outputs.has_patch }} + inference_access_error: ${{ steps.detect-agent-errors.outputs.inference_access_error || 'false' }} + mcp_policy_error: ${{ steps.detect-agent-errors.outputs.mcp_policy_error || 'false' }} model: ${{ needs.activation.outputs.model }} + 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 }} + unknown_model_ai_credits: ${{ steps.parse-mcp-gateway.outputs.unknown_model_ai_credits || 'false' }} steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 + uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 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: "Issue 自动分类与回复" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_AWF_VERSION: "v0.27.2" + GH_AW_INFO_ENGINE_ID: "copilot" - name: Set runtime paths id: set-runtime-paths run: | @@ -324,7 +399,7 @@ jobs: echo "GH_AW_SAFE_OUTPUTS_TOOLS_PATH=${RUNNER_TEMP}/gh-aw/safeoutputs/tools.json" } >> "$GITHUB_OUTPUT" - name: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: persist-credentials: false - name: Create gh-aw temp directory @@ -349,8 +424,8 @@ jobs: - name: Checkout PR branch id: checkout-pr if: | - github.event.pull_request || github.event.issue.pull_request - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + github.event.pull_request || github.event.issue.pull_request || github.event_name == 'workflow_dispatch' && fromJSON(github.event.inputs.aw_context || '{}').item_type == 'pull_request' + 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: @@ -360,13 +435,12 @@ jobs: setupGlobals(core, github, context, exec, io, getOctokit); const { main } = require('${{ runner.temp }}/gh-aw/actions/checkout_pr_branch.cjs'); await main(); - - name: Setup Node.js - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 - with: - node-version: '24' - package-manager-cache: false - - name: Install Codex CLI - run: npm install --ignore-scripts -g @openai/codex@0.118.0 + - name: Install GitHub Copilot CLI + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.60 + env: + GH_HOST: github.com + - name: Install AWF binary + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.27.2 - name: Parse integrity filter lists id: parse-guard-vars env: @@ -374,17 +448,37 @@ jobs: GH_AW_TRUSTED_USERS_VAR: ${{ vars.GH_AW_GITHUB_TRUSTED_USERS || '' }} GH_AW_APPROVAL_LABELS_VAR: ${{ vars.GH_AW_GITHUB_APPROVAL_LABELS || '' }} run: bash "${RUNNER_TEMP}/gh-aw/actions/parse_guard_list.sh" + - name: Download activation artifact + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: activation + path: /tmp/gh-aw + - name: Restore agent config folders from base branch + if: steps.checkout-pr.outcome == 'success' + env: + GH_AW_AGENT_FOLDERS: ".agents .antigravity .claude .codex .crush .gemini .github .opencode .pi" + GH_AW_AGENT_FILES: ".crush.json AGENTS.md ANTIGRAVITY.md CLAUDE.md GEMINI.md PI.md opencode.jsonc" + 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: ".github/agents" + GH_AW_SUB_AGENT_EXT: ".agent.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: ".github/skills" + run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_inline_skills.sh" - name: Download container images - run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/github-mcp-server:v0.32.0 node:lts-alpine - - name: Write Safe Outputs Config + run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6 ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2@sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4 ghcr.io/github/gh-aw-firewall/squid:0.27.2@sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591 ghcr.io/github/gh-aw-mcpg:v0.3.25@sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c + - name: Generate Safe Outputs Config run: | mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs - cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_50d51e89b299db31_EOF' + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_33a8e71ee9b45c67_EOF' {"add_comment":{"max":1},"add_labels":{"allowed":["bug","feature","enhancement","documentation","question","duplicate","invalid"]},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} - GH_AW_SAFE_OUTPUTS_CONFIG_50d51e89b299db31_EOF - - name: Write Safe Outputs Tools + GH_AW_SAFE_OUTPUTS_CONFIG_33a8e71ee9b45c67_EOF + - name: Generate Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | { @@ -512,7 +606,7 @@ jobs: } } } - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); @@ -568,11 +662,12 @@ jobs: GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} run: | set -eo pipefail - mkdir -p /tmp/gh-aw/mcp-config + mkdir -p "${RUNNER_TEMP}/gh-aw/mcp-config" # Export gateway environment variables for MCP config and gateway script - export MCP_GATEWAY_PORT="80" - export MCP_GATEWAY_DOMAIN="localhost" + export MCP_GATEWAY_PORT="8080" + export MCP_GATEWAY_DOMAIN="host.docker.internal" + export MCP_GATEWAY_HOST_DOMAIN="localhost" MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=') echo "::add-mask::${MCP_GATEWAY_API_KEY}" export MCP_GATEWAY_API_KEY @@ -581,47 +676,28 @@ jobs: export MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD="524288" export DEBUG="*" - export GH_AW_ENGINE="codex" - export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.2.19' - - cat > /tmp/gh-aw/mcp-config/config.toml << GH_AW_MCP_CONFIG_7c4481f6a1c5dec4_EOF - [history] - persistence = "none" - - [shell_environment_policy] - inherit = "core" - include_only = ["CODEX_API_KEY", "GH_AW_ASSETS_ALLOWED_EXTS", "GH_AW_ASSETS_BRANCH", "GH_AW_ASSETS_MAX_SIZE_KB", "GH_AW_SAFE_OUTPUTS", "GITHUB_PERSONAL_ACCESS_TOKEN", "GITHUB_REPOSITORY", "GITHUB_SERVER_URL", "HOME", "OPENAI_API_KEY", "PATH"] - - [mcp_servers.github] - user_agent = "issue" - startup_timeout_sec = 120 - tool_timeout_sec = 60 - container = "ghcr.io/github/github-mcp-server:v0.32.0" - env = { "GITHUB_HOST" = "$GITHUB_SERVER_URL", "GITHUB_PERSONAL_ACCESS_TOKEN" = "$GH_AW_GITHUB_TOKEN", "GITHUB_READ_ONLY" = "1", "GITHUB_TOOLSETS" = "context,repos,issues,pull_requests" } - env_vars = ["GITHUB_HOST", "GITHUB_PERSONAL_ACCESS_TOKEN", "GITHUB_READ_ONLY", "GITHUB_TOOLSETS"] + export GH_AW_ENGINE="copilot" + MCP_GATEWAY_UID=$(id -u 2>/dev/null || echo '0') + MCP_GATEWAY_GID=$(id -g 2>/dev/null || echo '0') + case "${DOCKER_HOST:-}" in + unix://* ) DOCKER_SOCK_PATH="${DOCKER_HOST#unix://}" ;; + /* ) DOCKER_SOCK_PATH="$DOCKER_HOST" ;; + * ) DOCKER_SOCK_PATH=/var/run/docker.sock ;; + esac + DOCKER_SOCK_GID=$(stat -c '%g' "$DOCKER_SOCK_PATH" 2>/dev/null || echo '0') + export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --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_API_KEY -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_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.3.25' - [mcp_servers.safeoutputs] - type = "http" - url = "http://localhost:$GH_AW_SAFE_OUTPUTS_PORT" - - [mcp_servers.safeoutputs.headers] - Authorization = "$GH_AW_SAFE_OUTPUTS_API_KEY" - - [mcp_servers.safeoutputs."guard-policies"] - - [mcp_servers.safeoutputs."guard-policies".write-sink] - accept = ["*"] - GH_AW_MCP_CONFIG_7c4481f6a1c5dec4_EOF - - # Generate JSON config for MCP gateway - cat << GH_AW_MCP_CONFIG_7c4481f6a1c5dec4_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" + mkdir -p /home/runner/.copilot + GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) + cat << GH_AW_MCP_CONFIG_920bb1916fcb7fc4_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "github": { - "container": "ghcr.io/github/github-mcp-server:v0.32.0", + "type": "stdio", + "container": "ghcr.io/github/github-mcp-server:v1.1.2", "env": { - "GITHUB_HOST": "$GITHUB_SERVER_URL", - "GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_MCP_SERVER_TOKEN", + "GITHUB_HOST": "\${GITHUB_SERVER_URL}", + "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}", "GITHUB_READ_ONLY": "1", "GITHUB_TOOLSETS": "context,repos,issues,pull_requests" }, @@ -637,9 +713,9 @@ jobs: }, "safeoutputs": { "type": "http", - "url": "http://localhost:$GH_AW_SAFE_OUTPUTS_PORT", + "url": "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT", "headers": { - "Authorization": "$GH_AW_SAFE_OUTPUTS_API_KEY" + "Authorization": "\${GH_AW_SAFE_OUTPUTS_API_KEY}" }, "guard-policies": { "write-sink": { @@ -657,38 +733,99 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_7c4481f6a1c5dec4_EOF - - name: Download activation artifact - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + GH_AW_MCP_CONFIG_920bb1916fcb7fc4_EOF + - name: Mount MCP servers as CLIs + id: mount-mcp-clis + continue-on-error: true + env: + MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }} + 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: - name: activation - path: /tmp/gh-aw - - name: Clean git credentials + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('${{ runner.temp }}/gh-aw/actions/mount_mcp_as_cli.cjs'); + await main(); + - name: Clean credentials continue-on-error: true run: bash "${RUNNER_TEMP}/gh-aw/actions/clean_git_credentials.sh" - - name: Execute Codex CLI + - 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: Execute GitHub Copilot CLI id: agentic_execution + # Copilot CLI tool arguments (sorted): + timeout-minutes: 20 run: | set -o pipefail + printf '%s' "$(date +%s%3N)" > /tmp/gh-aw/agent_cli_start_ms.txt + trap 'rm -f /home/runner/.copilot/settings.json' EXIT + mkdir -p /home/runner/.copilot + printf '%s' '{"builtInAgents":{"rubberDuck":false}}' > /home/runner/.copilot/settings.json touch /tmp/gh-aw/agent-step-summary.md + GH_AW_NODE_BIN=$(command -v node 2>/dev/null || true) + export GH_AW_NODE_BIN + export COPILOT_API_KEY="$COPILOT_DUMMY_BYOK" (umask 177 && touch /tmp/gh-aw/agent-stdio.log) - INSTRUCTION="$(cat "$GH_AW_PROMPT")" - mkdir -p "$CODEX_HOME/logs" - codex ${GH_AW_MODEL_AGENT_CODEX:+-c model="$GH_AW_MODEL_AGENT_CODEX" }exec -c web_search="disabled" -c fetch="disabled" --dangerously-bypass-approvals-and-sandbox --skip-git-repo-check "$INSTRUCTION" 2>&1 | tee /tmp/gh-aw/agent-stdio.log + GH_AW_MAX_AI_CREDITS="${{ vars.GH_AW_DEFAULT_MAX_AI_CREDITS || '1000' }}" + printf '%s\n' "{\"\$schema\":\"https://github.com/github/gh-aw-firewall/releases/download/v0.27.2/awf-config.schema.json\",\"network\":{\"allowDomains\":[\"api.business.githubcopilot.com\",\"api.enterprise.githubcopilot.com\",\"api.github.com\",\"api.githubcopilot.com\",\"api.individual.githubcopilot.com\",\"api.snapcraft.io\",\"archive.ubuntu.com\",\"ark.cn-beijing.volces.com\",\"azure.archive.ubuntu.com\",\"crl.geotrust.com\",\"crl.globalsign.com\",\"crl.identrust.com\",\"crl.sectigo.com\",\"crl.thawte.com\",\"crl.usertrust.com\",\"crl.verisign.com\",\"crl3.digicert.com\",\"crl4.digicert.com\",\"crls.ssl.com\",\"github.com\",\"host.docker.internal\",\"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\",\"ppa.launchpad.net\",\"raw.githubusercontent.com\",\"registry.npmjs.org\",\"s.symcb.com\",\"s.symcd.com\",\"security.ubuntu.com\",\"telemetry.enterprise.githubcopilot.com\",\"ts-crl.ws.symantec.com\",\"ts-ocsp.ws.symantec.com\",\"www.googleapis.com\"]},\"apiProxy\":{\"enabled\":true,\"enableTokenSteering\":true,\"maxRuns\":500,\"maxAiCredits\":${GH_AW_MAX_AI_CREDITS},\"models\":{\"agent\":[\"sonnet-6x\",\"gpt-5.4\",\"gpt-5.3\",\"gemini-pro\",\"any\"],\"antigravity\":[\"copilot/antigravity*\",\"google/antigravity*\",\"gemini/antigravity*\"],\"any\":[\"copilot/*\",\"anthropic/*\",\"openai/*\",\"google/*\",\"gemini/*\"],\"claude\":[\"agent\"],\"codex\":[\"agent\"],\"coding\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\",\"gpt-5-codex\"],\"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*\"],\"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-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-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.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*\"],\"haiku\":[\"copilot/*haiku*\",\"anthropic/*haiku*\"],\"large\":[\"sonnet\",\"gpt-5-pro\",\"gpt-5\",\"gemini-pro\"],\"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\"],\"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-4-5-*\",\"anthropic/*sonnet-4-5-*\",\"copilot/*sonnet-4-6*\",\"anthropic/*sonnet-4-6*\"],\"summarization\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash-lite\",\"mini\"],\"vision\":[\"copilot/gemini-*image*\",\"gemini/gemini-*image*\",\"copilot/gemini-*flash*\",\"gemini/gemini-*flash*\"]}},\"container\":{\"imageTag\":\"0.27.2,squid=sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591,agent=sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6,api-proxy=sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4,cli-proxy=sha256:02f3ec08f32dc26c5427920c6a2e2f3036238fce44802f2f11ef49ed8621b5d0\"}}" > "${RUNNER_TEMP}/gh-aw/awf-config.json" + GH_AW_MODEL_MULTIPLIERS_PATH="/tmp/gh-aw/model_multipliers.json" node "${RUNNER_TEMP}/gh-aw/actions/merge_awf_model_multipliers.cjs" + 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_PATH_PREFIX_ARGS="" + if [[ "${DOCKER_HOST:-}" =~ ^tcp:// ]]; then + GH_AW_DOCKER_HOST_PATH_PREFIX_ARGS="--docker-host-path-prefix /tmp/gh-aw" + fi + GH_AW_TOOL_CACHE_MOUNT="" + GH_AW_TOOL_CACHE="${RUNNER_TOOL_CACHE:-/opt/hostedtoolcache}" + 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 + elif [ -d "/home/runner/work/_tool" ]; then + GH_AW_TOOL_CACHE_MOUNT="/home/runner/work/_tool:/home/runner/work/_tool:ro" + fi + # shellcheck disable=SC1003 + sudo -E 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_PATH_PREFIX_ARGS} --env-all --exclude-env COPILOT_PROVIDER_API_KEY --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull \ + -- /bin/bash -c 'set +o histexpand; export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && GH_AW_TOOL_CACHE="${RUNNER_TOOL_CACHE:-/opt/hostedtoolcache}"; export PATH="$(find "$GH_AW_TOOL_CACHE" /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 5 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/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/copilot_harness.cjs /usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-all-tools --allow-all-paths --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log env: - CODEX_API_KEY: ${{ secrets.CODEX_API_KEY || secrets.OPENAI_API_KEY }} - CODEX_HOME: /tmp/gh-aw/mcp-config - GH_AW_MCP_CONFIG: /tmp/gh-aw/mcp-config/config.toml - GH_AW_MODEL_AGENT_CODEX: gpt-5.3-codex + AWF_REFLECT_ENABLED: 1 + COPILOT_AGENT_RUNNER_TYPE: STANDALONE + COPILOT_DUMMY_BYOK: dummy-byok-key-for-offline-mode + COPILOT_MODEL: doubao-seed-2-0-code-preview-260215 + COPILOT_PROVIDER_API_KEY: ${{ secrets.OPENAI_API_KEY }} + COPILOT_PROVIDER_BASE_URL: https://ark.cn-beijing.volces.com/api/v3 + COPILOT_PROVIDER_TYPE: openai + GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }} + GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json 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: v0.68.3 + GH_AW_TIMEOUT_MINUTES: 20 + GH_AW_VERSION: v0.79.6 + GITHUB_API_URL: ${{ github.api_url }} GITHUB_AW: true + GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows + GITHUB_HEAD_REF: ${{ github.head_ref }} + GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + GITHUB_REF_NAME: ${{ github.ref_name }} + GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md - OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - OPENAI_BASE_URL: https://api.zhizengzeng.com/v1 - RUST_LOG: trace,hyper_util=info,mio=info,reqwest=info,os_info=info,codex_otel=warn,codex_core=debug,ocodex_exec=debug + 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 }} + XDG_CONFIG_HOME: /home/runner + - name: Detect agent errors + if: always() + id: detect-agent-errors + continue-on-error: true + run: node "${RUNNER_TEMP}/gh-aw/actions/detect_agent_errors.cjs" - name: Configure Git credentials env: REPO_NAME: ${{ github.repository }} @@ -702,6 +839,10 @@ jobs: SERVER_URL_STRIPPED="${SERVER_URL#https://}" git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" echo "Git configured with standard GitHub Actions identity" + - name: Copy Copilot session state files to logs + if: always() + continue-on-error: true + run: bash "${RUNNER_TEMP}/gh-aw/actions/copy_copilot_session_state.sh" - name: Stop MCP Gateway if: always() continue-on-error: true @@ -713,7 +854,7 @@ jobs: bash "${RUNNER_TEMP}/gh-aw/actions/stop_mcp_gateway.sh" "$GATEWAY_PID" - name: Redact secrets in logs if: always() - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); @@ -721,8 +862,7 @@ jobs: const { main } = require('${{ runner.temp }}/gh-aw/actions/redact_secrets.cjs'); await main(); env: - GH_AW_SECRET_NAMES: 'CODEX_API_KEY,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN,OPENAI_API_KEY' - SECRET_CODEX_API_KEY: ${{ secrets.CODEX_API_KEY }} + GH_AW_SECRET_NAMES: 'GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN,OPENAI_API_KEY' SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -740,10 +880,10 @@ jobs: - name: Ingest agent output id: collect_output if: always() - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + 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: "172.30.0.1,api.openai.com,api.zhizengzeng.com,host.docker.internal,openai.com" + GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,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,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} with: @@ -754,25 +894,60 @@ jobs: await main(); - name: Parse agent logs for step summary if: always() - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: - GH_AW_AGENT_OUTPUT: /tmp/gh-aw/agent-stdio.log + GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/ with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_codex_log.cjs'); + const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_copilot_log.cjs'); await main(); - name: Parse MCP Gateway logs for step summary if: always() id: parse-mcp-gateway - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); setupGlobals(core, github, context, exec, io, getOctokit); const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_mcp_gateway_log.cjs'); await main(); + - name: Print firewall logs + if: always() + continue-on-error: true + env: + AWF_LOGS_DIR: /tmp/gh-aw/sandbox/firewall/logs + run: | + # Fix permissions on firewall logs/audit dirs so they can be uploaded as artifacts + # AWF runs with sudo, creating files owned by root + sudo chmod -R a+rX /tmp/gh-aw/sandbox/firewall 2>/dev/null || true + # Only run awf logs summary if awf command exists (it may not be installed if workflow failed before install step) + if command -v awf &> /dev/null; then + awf logs summary | tee -a "$GITHUB_STEP_SUMMARY" + else + echo 'AWF binary not installed, skipping firewall log summary' + fi + - name: Parse token usage for step summary + if: always() + continue-on-error: true + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/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 { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/awf_reflect_summary.cjs'); + await main(); - name: Write agent output placeholder if missing if: always() run: | @@ -787,16 +962,22 @@ jobs: name: agent path: | /tmp/gh-aw/aw-prompts/prompt.txt - /tmp/gh-aw/mcp-config/logs/ + /tmp/gh-aw/sandbox/agent/logs/ /tmp/gh-aw/redacted-urls.log /tmp/gh-aw/mcp-logs/ /tmp/gh-aw/proxy-logs/ !/tmp/gh-aw/proxy-logs/proxy-tls/ + /tmp/gh-aw/agent_usage.json /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/pre-agent-audit.txt /tmp/gh-aw/agent/ /tmp/gh-aw/github_rate_limits.jsonl /tmp/gh-aw/safeoutputs.jsonl /tmp/gh-aw/agent_output.json + /tmp/gh-aw/awf-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 conclusion: @@ -806,7 +987,7 @@ jobs: - safe_outputs if: > always() && (needs.agent.result != 'skipped' || needs.activation.outputs.lockdown_check_failed == 'true' || - needs.activation.outputs.stale_lock_file_failed == 'true') + needs.activation.outputs.stale_lock_file_failed == 'true' || needs.activation.outputs.daily_effective_workflow_exceeded == 'true') runs-on: ubuntu-slim permissions: contents: read @@ -816,6 +997,7 @@ jobs: concurrency: group: "gh-aw-conclusion-issue-triage" cancel-in-progress: false + queue: max outputs: incomplete_count: ${{ steps.report_incomplete.outputs.incomplete_count }} noop_message: ${{ steps.noop.outputs.noop_message }} @@ -824,11 +1006,18 @@ jobs: steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 + uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 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: "Issue 自动分类与回复" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_AWF_VERSION: "v0.27.2" + GH_AW_INFO_ENGINE_ID: "copilot" - name: Download agent output artifact id: download-agent-output continue-on-error: true @@ -843,16 +1032,54 @@ jobs: mkdir -p /tmp/gh-aw/ find "/tmp/gh-aw/" -type f -print echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT" + - name: Collect usage artifact files + if: always() + continue-on-error: true + run: | + mkdir -p /tmp/gh-aw/usage/agent /tmp/gh-aw/usage/detection + echo "Usage artifact source file status:" + for file in /tmp/gh-aw/aw-info.jsonl /tmp/gh-aw/agent_usage.jsonl /tmp/gh-aw/detection_usage.jsonl /tmp/gh-aw/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/threat-detection/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/threat-detection/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/threat-detection/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl; do + [ -f "$file" ] && echo "FOUND: $file" || echo "MISSING: $file" + done + [ -f /tmp/gh-aw/aw-info.jsonl ] && cp /tmp/gh-aw/aw-info.jsonl /tmp/gh-aw/usage/aw-info.jsonl || true + [ -f /tmp/gh-aw/agent_usage.jsonl ] && cp /tmp/gh-aw/agent_usage.jsonl /tmp/gh-aw/usage/agent_usage.jsonl || true + [ -f /tmp/gh-aw/detection_usage.jsonl ] && cp /tmp/gh-aw/detection_usage.jsonl /tmp/gh-aw/usage/detection_usage.jsonl || true + [ -f /tmp/gh-aw/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl ] && cp /tmp/gh-aw/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/usage/agent/token_usage.jsonl || true + [ -f /tmp/gh-aw/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl ] && cp /tmp/gh-aw/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/usage/agent/token_usage.jsonl || true + [ -f /tmp/gh-aw/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl ] && cp /tmp/gh-aw/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/usage/agent/token_usage.jsonl || true + [ -f /tmp/gh-aw/threat-detection/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl ] && cp /tmp/gh-aw/threat-detection/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/usage/detection/token_usage.jsonl || true + [ -f /tmp/gh-aw/threat-detection/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl ] && cp /tmp/gh-aw/threat-detection/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/usage/detection/token_usage.jsonl || true + [ -f /tmp/gh-aw/threat-detection/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl ] && cp /tmp/gh-aw/threat-detection/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/usage/detection/token_usage.jsonl || true + [ -f /tmp/gh-aw/usage/agent/token_usage.jsonl ] || : > /tmp/gh-aw/usage/agent/token_usage.jsonl + [ -f /tmp/gh-aw/usage/detection/token_usage.jsonl ] || : > /tmp/gh-aw/usage/detection/token_usage.jsonl + find /tmp/gh-aw/usage -type f -print | sort + - name: Upload usage artifact + if: always() + continue-on-error: true + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: usage + path: | + /tmp/gh-aw/usage/aw-info.jsonl + /tmp/gh-aw/usage/agent_usage.jsonl + /tmp/gh-aw/usage/detection_usage.jsonl + /tmp/gh-aw/usage/agent/token_usage.jsonl + /tmp/gh-aw/usage/detection/token_usage.jsonl + if-no-files-found: ignore - name: Process no-op messages id: noop - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + 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: "1" GH_AW_WORKFLOW_NAME: "Issue 自动分类与回复" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-triage.md" GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} GH_AW_NOOP_REPORT_AS_ISSUE: "true" + GH_AW_AIC: ${{ needs.agent.outputs.aic }} + GH_AW_AMBIENT_CONTEXT: ${{ needs.agent.outputs.ambient_context }} + GH_AW_WORKFLOW_ID: "issue-triage" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -862,11 +1089,12 @@ jobs: await main(); - name: Record missing tool id: missing_tool - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + 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: "Issue 自动分类与回复" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-triage.md" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -876,11 +1104,12 @@ jobs: await main(); - name: Record incomplete id: report_incomplete - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + 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: "Issue 自动分类与回复" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-triage.md" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -891,20 +1120,36 @@ jobs: - name: Handle agent failure id: handle_agent_failure if: always() - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + 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: "Issue 自动分类与回复" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-triage.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: "issue-triage" - GH_AW_ENGINE_ID: "codex" - GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.activation.outputs.secret_verification_result }} + GH_AW_ACTION_FAILURE_ISSUE_EXPIRES_HOURS: "168" + GH_AW_ENGINE_ID: "copilot" GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} + GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens || '' }} + 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_MAX_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_MAX_AI_CREDITS || '1000' }} + 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_ENGINE_API_HOSTS: "api.enterprise.githubcopilot.com,api.githubcopilot.com,api.business.githubcopilot.com,api.individual.githubcopilot.com" GH_AW_LOCKDOWN_CHECK_FAILED: ${{ needs.activation.outputs.lockdown_check_failed }} GH_AW_STALE_LOCK_FILE_FAILED: ${{ needs.activation.outputs.stale_lock_file_failed }} + GH_AW_DAILY_EFFECTIVE_WORKFLOW_EXCEEDED: ${{ needs.activation.outputs.daily_effective_workflow_exceeded }} + GH_AW_DAILY_EFFECTIVE_WORKFLOW_TOTAL_EFFECTIVE_TOKENS: ${{ needs.activation.outputs.daily_effective_workflow_total_effective_tokens }} + GH_AW_DAILY_EFFECTIVE_WORKFLOW_THRESHOLD: ${{ needs.activation.outputs.daily_effective_workflow_threshold }} 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" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} @@ -919,17 +1164,25 @@ jobs: outputs: activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} 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: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 + uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} + env: + GH_AW_SETUP_WORKFLOW_NAME: "Issue 自动分类与回复" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_AWF_VERSION: "v0.27.2" + GH_AW_INFO_ENGINE_ID: "copilot" - name: Check team membership for workflow id: check_membership - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_REQUIRED_ROLES: "admin,maintainer,write" with: @@ -951,14 +1204,19 @@ jobs: discussions: write issues: write pull-requests: write - timeout-minutes: 15 + 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 }}/issue-triage" GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens }} - GH_AW_ENGINE_ID: "codex" - GH_AW_ENGINE_MODEL: "gpt-5.3-codex" + GH_AW_ENGINE_ID: "copilot" + GH_AW_ENGINE_MODEL: ${{ needs.agent.outputs.model }} + GH_AW_ENGINE_VERSION: "1.0.60" GH_AW_WORKFLOW_ID: "issue-triage" GH_AW_WORKFLOW_NAME: "Issue 自动分类与回复" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-triage.md" outputs: code_push_failure_count: ${{ steps.process_safe_outputs.outputs.code_push_failure_count }} code_push_failure_errors: ${{ steps.process_safe_outputs.outputs.code_push_failure_errors }} @@ -971,11 +1229,18 @@ jobs: steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 + uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 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: "Issue 自动分类与回复" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_AWF_VERSION: "v0.27.2" + GH_AW_INFO_ENGINE_ID: "copilot" - name: Download agent output artifact id: download-agent-output continue-on-error: true @@ -993,6 +1258,7 @@ jobs: - name: Configure GH_HOST for enterprise compatibility id: ghes-host-config shell: bash + # zizmor: ignore[github-env] - GITHUB_SERVER_URL is set by GitHub Actions, not user input. run: | # Derive GH_HOST from GITHUB_SERVER_URL so the gh CLI targets the correct # GitHub instance (GHES/GHEC). On github.com this is a harmless no-op. @@ -1001,10 +1267,11 @@ jobs: echo "GH_HOST=${GH_HOST}" >> "$GITHUB_ENV" - name: Process Safe Outputs id: process_safe_outputs - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + 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_ALLOWED_DOMAINS: "172.30.0.1,api.openai.com,api.zhizengzeng.com,host.docker.internal,openai.com" + GH_AW_COMMENT_ID: ${{ needs.activation.outputs.comment_id }} + GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,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,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.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},\"add_labels\":{\"allowed\":[\"bug\",\"feature\",\"enhancement\",\"documentation\",\"question\",\"duplicate\",\"invalid\"]},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"report_incomplete\":{}}" diff --git a/.github/workflows/issue-triage.md b/.github/workflows/issue-triage.md index 0b491b11..f0e5b220 100644 --- a/.github/workflows/issue-triage.md +++ b/.github/workflows/issue-triage.md @@ -16,10 +16,6 @@ network: - defaults - ark.cn-beijing.volces.com -sandbox: - agent: false -strict: false - tools: github: min-integrity: none From 03b1eb55ef8518415bb89e11f42d041c3c1c068d Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Fri, 12 Jun 2026 08:13:05 +0000 Subject: [PATCH 24/59] Potential fix for code scanning alert no. 65 Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> --- .../XEngine_AuthorizeService.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/XEngine_AuthorizeService.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/XEngine_AuthorizeService.cpp index 1cde9f1d..6598e5d2 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/XEngine_AuthorizeService.cpp +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/XEngine_AuthorizeService.cpp @@ -126,14 +126,31 @@ LONG WINAPI Coredump_ExceptionFilter(EXCEPTION_POINTERS* pExceptionPointers) return EXCEPTION_EXECUTE_HANDLER; } #endif +/** + * @brief Authorize service process entry point. + * + * This function coordinates the full service lifecycle: + * 1) platform/runtime bootstrap (network stack, locale, crash handler), + * 2) configuration and parameter handling, + * 3) initialization of logging, protocol stacks, and worker components, + * 4) service run loop and signal-controlled shutdown, + * 5) orderly release of all allocated resources. + * + * Notes: + * - Platform-specific startup paths are guarded by compile-time macros. + * - Error paths return early to avoid continuing in a partially initialized state. + */ int main(int argc, char** argv) { #ifdef _WINDOWS + // Initialize Winsock for all subsequent socket-based modules. WSADATA st_WSAData; WSAStartup(MAKEWORD(2, 2), &st_WSAData); + // Register unhandled exception filter to generate a dump file on crash. SetUnhandledExceptionFilter(Coredump_ExceptionFilter); #ifndef _DEBUG + // Ensure UTF-8 locale in release builds for consistent text processing/logging. if (setlocale(LC_ALL, ".UTF8") == NULL) { fprintf(stderr, "Error setting locale.\n"); From 45273419865a7f23a56decea8a7bfdcacd0d7582 Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Fri, 12 Jun 2026 08:14:10 +0000 Subject: [PATCH 25/59] Potential fix for code scanning alert no. 64 Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> --- .../AuthorizeHTTP_Post/AuthorizeHTTP_Serial.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_Serial.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_Serial.cpp index 308baf15..704898c3 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_Serial.cpp +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_Serial.cpp @@ -1,5 +1,14 @@ #include "../Authorize_Hdr.h" +// Handle HTTP serial-number related APIs. +// Supported operations: +// 1) list : query serials by page/range and return packed HTTP response. +// 2) delete : parse serial list from request and delete each entry. +// 3) insert : parse and insert serial entries (handled in the insert branch below). +// Notes: +// - Database backend is selected by st_AuthConfig.st_XSql.nDBType. +// - Response data is sent back through XEngine_Client_TaskSend. +// - Dynamically allocated parse/query buffers must be released after use. bool XEngine_AuthorizeHTTP_Serial(LPCXSTR lpszClientAddr, LPCXSTR lpszAPIName, LPCXSTR lpszMsgBuffer, int nMsgLen) { int nSDLen = 0; @@ -8,6 +17,7 @@ bool XEngine_AuthorizeHTTP_Serial(LPCXSTR lpszClientAddr, LPCXSTR lpszAPIName, L LPCXSTR lpszAPIDelete = _X("delete"); CHttpMemory_PoolEx m_MemoryPool(XENGINE_MEMORY_SIZE_MAX); + // list: parse paging range, query DB, package list response, then return to client. if (0 == _tcsxncmp(lpszAPIList, lpszAPIName, _tcsxlen(lpszAPIList))) { int nPosStart = 0; @@ -20,6 +30,7 @@ bool XEngine_AuthorizeHTTP_Serial(LPCXSTR lpszClientAddr, LPCXSTR lpszAPIName, L } memset(ptszMsgBuffer, '\0', XENGINE_MEMORY_SIZE_MAX); + // Read list window from HTTP payload and limit single request size. Protocol_Parse_HttpParsePos(lpszMsgBuffer, nMsgLen, &nPosStart, &nPosEnd); if ((nPosEnd - nPosStart) > 100) { @@ -44,6 +55,7 @@ bool XEngine_AuthorizeHTTP_Serial(LPCXSTR lpszClientAddr, LPCXSTR lpszAPIName, L ptszMsgBuffer = NULL; XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("HTTP客户端:%s,请求序列号列表成功,个数:%d"), lpszClientAddr, nListCount); } + // delete: parse requested serials and delete one-by-one in configured DB backend. else if (0 == _tcsxncmp(lpszAPIDelete, lpszAPIName, _tcsxlen(lpszAPIDelete))) { int nListCount = 0; @@ -64,11 +76,13 @@ bool XEngine_AuthorizeHTTP_Serial(LPCXSTR lpszClientAddr, LPCXSTR lpszAPIName, L DBModule_MySQL_SerialDelete(ppSt_SerialTable[i]->tszSerialNumber); } } + // Release parsed serial table and return common success response. BaseLib_Memory_Free((XPPPMEM)&ppSt_SerialTable, nListCount); Protocol_Packet_HttpComm(m_MemoryPool.get(), &nSDLen); XEngine_Client_TaskSend(lpszClientAddr, m_MemoryPool.get(), nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP); XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("HTTP客户端:%s,请求删除序列号成功,删除个数:%d"), lpszClientAddr, nListCount); } + // insert: parse and insert serial data, then reply to client (implementation below). else if (0 == _tcsxncmp(lpszAPIInsert, lpszAPIName, _tcsxlen(lpszAPIInsert))) { int nSerialCount = 0; From 2b37c1330970dc9fd9fee33937bfc7f8ab2297b0 Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Fri, 12 Jun 2026 16:53:36 +0800 Subject: [PATCH 26/59] ci:cancel centos release --- .github/workflows/Centos_build.yml | 2 +- .github/workflows/release.yml | 9 --------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/.github/workflows/Centos_build.yml b/.github/workflows/Centos_build.yml index 5b0ce688..debcdf7c 100644 --- a/.github/workflows/Centos_build.yml +++ b/.github/workflows/Centos_build.yml @@ -3,7 +3,7 @@ name: centos build workflows on: push: branches: - - 'develop' + - 'develop1' paths: - 'XEngine_Source/**' - 'XEngine_Release/**' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 87617504..d06224fd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -79,15 +79,6 @@ jobs: skip_unpack: true if_no_artifact_found: fail path: ./XRelease/ - - name: Download CentOS - uses: dawidd6/action-download-artifact@v16 - with: - workflow: Centos_build.yml - workflow_conclusion: success - check_artifacts: false - skip_unpack: true - if_no_artifact_found: fail - path: ./XRelease/ - name: Display structure of downloaded files run: ls -al ./XRelease/ From da8c7d61bb880d4d0750f8c019aed29380134e80 Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Thu, 18 Jun 2026 11:38:30 +0800 Subject: [PATCH 27/59] added:email notify after user pay --- .../AuthorizeModule_Configure/Config_Define.h | 11 +++++++++ .../AuthorizeModule_Configure/Config_Error.h | 3 ++- .../ModuleConfigure_Json.cpp | 14 +++++++++++ .../DBModule_MySQL/DBModule_MySQL.cpp | 4 ++-- .../DBModule_SQLite/DBModule_SQLite.cpp | 4 ++-- XEngine_Source/Makefile | 9 ++++++- XEngine_Source/XEngine.sln | 19 +++++++++++++-- .../AuthorizeHTTP_Post/AuthorizeHTTP_User.cpp | 24 +++++++++++++++---- .../XEngine_AuthorizeService/Authorize_Hdr.h | 8 +++++++ 9 files changed, 83 insertions(+), 13 deletions(-) diff --git a/XEngine_Source/AuthorizeModule_Configure/Config_Define.h b/XEngine_Source/AuthorizeModule_Configure/Config_Define.h index 08015036..59dbbb1e 100644 --- a/XEngine_Source/AuthorizeModule_Configure/Config_Define.h +++ b/XEngine_Source/AuthorizeModule_Configure/Config_Define.h @@ -122,6 +122,17 @@ typedef struct int nLogType; //日志类型 bool bLogStorage; //强日志 }st_XLog; + struct + { + struct + { + bool bEnable; + XCHAR tszServiceAddr[XPATH_MAX]; + XCHAR tszUser[128]; + XCHAR tszPass[128]; + XCHAR tszSendAddr[128]; + }st_EMailNotify; + }st_XNotify; struct { bool bEnable; diff --git a/XEngine_Source/AuthorizeModule_Configure/Config_Error.h b/XEngine_Source/AuthorizeModule_Configure/Config_Error.h index 25f1a8a3..15f7e27b 100644 --- a/XEngine_Source/AuthorizeModule_Configure/Config_Error.h +++ b/XEngine_Source/AuthorizeModule_Configure/Config_Error.h @@ -21,4 +21,5 @@ #define ERROR_AUTHORIZE_MODULE_CONFIGURE_MALLOC 0x0010009 #define ERROR_AUTHORIZE_MODULE_CONFIGURE_REPORT 0x0010010 #define ERROR_AUTHORIZE_MODULE_CONFIGURE_XTIME 0x0010011 -#define ERROR_AUTHORIZE_MODULE_CONFIGURE_XAPIVER 0x0010012 \ No newline at end of file +#define ERROR_AUTHORIZE_MODULE_CONFIGURE_XAPIVER 0x0010012 +#define ERROR_AUTHORIZE_MODULE_CONFIGURE_NOTIFY 0x0010013 \ No newline at end of file diff --git a/XEngine_Source/AuthorizeModule_Configure/ModuleConfigure_Json/ModuleConfigure_Json.cpp b/XEngine_Source/AuthorizeModule_Configure/ModuleConfigure_Json/ModuleConfigure_Json.cpp index 8415d37e..3039b57f 100644 --- a/XEngine_Source/AuthorizeModule_Configure/ModuleConfigure_Json/ModuleConfigure_Json.cpp +++ b/XEngine_Source/AuthorizeModule_Configure/ModuleConfigure_Json/ModuleConfigure_Json.cpp @@ -205,6 +205,20 @@ bool CModuleConfigure_Json::ModuleConfigure_Json_File(LPCXSTR lpszConfigFile, XE pSt_ServerConfig->st_XLog.bLogStorage = st_JsonXLog["bLogStorage"].asBool(); _tcsxcpy(pSt_ServerConfig->st_XLog.tszLogFile, st_JsonXLog["tszLogFile"].asCString()); _tcsxcpy(pSt_ServerConfig->st_XLog.tszKeyFile, st_JsonXLog["tszKeyFile"].asCString()); + //信息通知 + if (st_JsonRoot["XNotify"].empty()) + { + Config_IsErrorOccur = true; + Config_dwErrorCode = ERROR_AUTHORIZE_MODULE_CONFIGURE_NOTIFY; + return false; + } + Json::Value st_JsonXNotify = st_JsonRoot["XNotify"]; + Json::Value st_JsonXEmail = st_JsonXNotify["XEmail"]; + pSt_ServerConfig->st_XNotify.st_EMailNotify.bEnable = st_JsonXEmail["bEnable"].asBool(); + _tcsxcpy(pSt_ServerConfig->st_XNotify.st_EMailNotify.tszServiceAddr, st_JsonXEmail["tszServiceAddr"].asCString()); + _tcsxcpy(pSt_ServerConfig->st_XNotify.st_EMailNotify.tszUser, st_JsonXEmail["tszUser"].asCString()); + _tcsxcpy(pSt_ServerConfig->st_XNotify.st_EMailNotify.tszPass, st_JsonXEmail["tszPass"].asCString()); + _tcsxcpy(pSt_ServerConfig->st_XNotify.st_EMailNotify.tszSendAddr, st_JsonXEmail["tszSendAddr"].asCString()); if (st_JsonRoot["XReport"].empty() || (3 != st_JsonRoot["XReport"].size())) { diff --git a/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.cpp b/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.cpp index 83544b31..7f427e80 100644 --- a/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.cpp +++ b/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.cpp @@ -297,7 +297,7 @@ bool CDBModule_MySQL::DBModule_MySQL_UserQuery(LPCXSTR lpszUserName, AUTHREG_USE bool CDBModule_MySQL::DBModule_MySQL_UserPay(LPCXSTR lpszUserName, LPCXSTR lpszSerialName) { SQLPacket_IsErrorOccur = false; - const int nVipUserLevel = 0; + const int nVipUserLevel = ENUM_XENGINE_PROTOCOLHDR_LEVEL_TYPE_VIP; AUTHREG_SERIALTABLE st_SerialTable; AUTHREG_USERTABLE st_UserTable; @@ -395,7 +395,7 @@ bool CDBModule_MySQL::DBModule_MySQL_UserPay(LPCXSTR lpszUserName, LPCXSTR lpszS bool CDBModule_MySQL::DBModule_MySQL_UserLeave(AUTHREG_PROTOCOL_TIME* pSt_TimeProtocol) { SQLPacket_IsErrorOccur = false; - const int nNormalUserLevel = 20; + const int nNormalUserLevel = ENUM_XENGINE_PROTOCOLHDR_LEVEL_TYPE_USER; XCHAR tszSQLStatement[1024]; //SQL语句 memset(tszSQLStatement, '\0', 1024); diff --git a/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.cpp b/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.cpp index 981c04f4..56ff3dc7 100644 --- a/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.cpp +++ b/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.cpp @@ -257,7 +257,7 @@ bool CDBModule_SQLite::DBModule_SQLite_UserQuery(LPCXSTR lpszUserName, AUTHREG_U bool CDBModule_SQLite::DBModule_SQLite_UserPay(LPCXSTR lpszUserName, LPCXSTR lpszSerialName) { SQLPacket_IsErrorOccur = false; - const int nVipUserLevel = 0; + const int nVipUserLevel = ENUM_XENGINE_PROTOCOLHDR_LEVEL_TYPE_VIP; AUTHREG_SERIALTABLE st_SerialTable; AUTHREG_USERTABLE st_UserTable; @@ -355,7 +355,7 @@ bool CDBModule_SQLite::DBModule_SQLite_UserPay(LPCXSTR lpszUserName, LPCXSTR lps bool CDBModule_SQLite::DBModule_SQLite_UserLeave(AUTHREG_PROTOCOL_TIME* pSt_TimeProtocol) { SQLPacket_IsErrorOccur = false; - const int nNormalUserLevel = 20; + const int nNormalUserLevel = ENUM_XENGINE_PROTOCOLHDR_LEVEL_TYPE_USER; XCHAR tszSQLStatement[1024]; //SQL语句 memset(tszSQLStatement, '\0', 1024); diff --git a/XEngine_Source/Makefile b/XEngine_Source/Makefile index ced50073..a2e79cea 100644 --- a/XEngine_Source/Makefile +++ b/XEngine_Source/Makefile @@ -7,6 +7,7 @@ FLAGS= DEPEND_JSONCPP_PATH = ./XEngine_DependLibrary/XEngine_Module/jsoncpp DEPEND_REPORT_PATH = ./XEngine_DependLibrary/XEngine_Module/XEngine_InfoReport DEPEND_VERIFICATION_PATH = ./XEngine_DependLibrary/XEngine_Module/XEngine_Verification +DEPEND_MSGNOTIFY_PATH = ./XEngine_DependLibrary/XEngine_Module/XEngine_MSGNotify AUTH_SESSION_PATH = ./AuthorizeModule_Session AUTH_DATABASE_PATH = ./AuthorizeModule_Database @@ -23,7 +24,7 @@ else ifeq ($(PLATFORM),mac) endif # 第三方库模块 -MODULES_THIRD = libjsoncpp.so libXEngine_InfoReport.so libXEngine_Verification.so \ +MODULES_THIRD = libjsoncpp.so libXEngine_InfoReport.so libXEngine_Verification.so libXEngine_MSGNotify.so \ # 业务模块 + 应用 MODULES_APP = libAuthorizeModule_Session.so libAuthorizeModule_Database.so libAuthorizeModule_Protocol.so libAuthorizeModule_Configure.so libAuthorizeModule_Help.so \ XEngine_AuthorizeApp.exe @@ -59,6 +60,12 @@ ifeq ($(FLAGS), InstallAll) else make -C $(DEPEND_VERIFICATION_PATH) PLATFORM=$(PLATFORM) $(FLAGS) endif +libXEngine_MSGNotify.so: +ifeq ($(FLAGS), InstallAll) + cp $(DEPEND_MSGNOTIFY_PATH)/libXEngine_MSGNotify.$(FILEEXT) ../XEngine_Release/ +else + make -C $(DEPEND_MSGNOTIFY_PATH) PLATFORM=$(PLATFORM) $(FLAGS) +endif libAuthorizeModule_Session.so: make -C $(AUTH_SESSION_PATH) PLATFORM=$(PLATFORM) UNICODE=$(UNICODE) $(FLAGS) diff --git a/XEngine_Source/XEngine.sln b/XEngine_Source/XEngine.sln index 33e44b34..6c1d83db 100644 --- a/XEngine_Source/XEngine.sln +++ b/XEngine_Source/XEngine.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.2.32519.379 +# Visual Studio Version 18 +VisualStudioVersion = 18.7.11911.148 stable MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "XEngine_HDRFile", "XEngine_HDRFile", "{D3A33095-8584-4EFB-9411-EBC38407E7B9}" ProjectSection(SolutionItems) = preProject @@ -73,6 +73,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XEngine_Verification", "XEn {F1736B3F-03A2-4FC7-B045-A12BA8D724FB} = {F1736B3F-03A2-4FC7-B045-A12BA8D724FB} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XEngine_MSGNotify", "XEngine_DependLibrary\XEngine_Module\XEngine_MSGNotify\XEngine_MSGNotify.vcxproj", "{E1087BA3-1074-4C6A-B770-A53B7BA1F4EA}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|ARM64 = Debug|ARM64 @@ -203,6 +205,18 @@ Global {A8E43EC0-698A-4807-8A61-B2BE5FAB7256}.Release|x64.Build.0 = Release|x64 {A8E43EC0-698A-4807-8A61-B2BE5FAB7256}.Release|x86.ActiveCfg = Release|Win32 {A8E43EC0-698A-4807-8A61-B2BE5FAB7256}.Release|x86.Build.0 = Release|Win32 + {E1087BA3-1074-4C6A-B770-A53B7BA1F4EA}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {E1087BA3-1074-4C6A-B770-A53B7BA1F4EA}.Debug|ARM64.Build.0 = Debug|ARM64 + {E1087BA3-1074-4C6A-B770-A53B7BA1F4EA}.Debug|x64.ActiveCfg = Debug|x64 + {E1087BA3-1074-4C6A-B770-A53B7BA1F4EA}.Debug|x64.Build.0 = Debug|x64 + {E1087BA3-1074-4C6A-B770-A53B7BA1F4EA}.Debug|x86.ActiveCfg = Debug|Win32 + {E1087BA3-1074-4C6A-B770-A53B7BA1F4EA}.Debug|x86.Build.0 = Debug|Win32 + {E1087BA3-1074-4C6A-B770-A53B7BA1F4EA}.Release|ARM64.ActiveCfg = Release|ARM64 + {E1087BA3-1074-4C6A-B770-A53B7BA1F4EA}.Release|ARM64.Build.0 = Release|ARM64 + {E1087BA3-1074-4C6A-B770-A53B7BA1F4EA}.Release|x64.ActiveCfg = Release|x64 + {E1087BA3-1074-4C6A-B770-A53B7BA1F4EA}.Release|x64.Build.0 = Release|x64 + {E1087BA3-1074-4C6A-B770-A53B7BA1F4EA}.Release|x86.ActiveCfg = Release|Win32 + {E1087BA3-1074-4C6A-B770-A53B7BA1F4EA}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -213,6 +227,7 @@ Global {F1736B3F-03A2-4FC7-B045-A12BA8D724FB} = {6444F125-63DE-4120-98B3-DF097A9758FA} {F6520D2C-BB8E-45BB-964B-F5D6A4318A89} = {6444F125-63DE-4120-98B3-DF097A9758FA} {A8E43EC0-698A-4807-8A61-B2BE5FAB7256} = {6444F125-63DE-4120-98B3-DF097A9758FA} + {E1087BA3-1074-4C6A-B770-A53B7BA1F4EA} = {6444F125-63DE-4120-98B3-DF097A9758FA} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {E1F1DDE3-8949-41AF-84D6-03CB7CAA03AB} diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_User.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_User.cpp index 2d148832..fa438c96 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_User.cpp +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_User.cpp @@ -156,11 +156,8 @@ bool XEngine_AuthorizeHTTP_User(XNETHANDLE xhToken, LPCXSTR lpszClientAddr, LPCX } else if (0 == _tcsxncmp(lpszAPIName, lpszAPIPay, _tcsxlen(lpszAPIName))) { - AUTHREG_PROTOCOL_USERPAY st_UserPay; - AUTHREG_USERTABLE st_UserInfo; - - memset(&st_UserInfo, '\0', sizeof(AUTHREG_USERTABLE)); - memset(&st_UserPay, '\0', sizeof(AUTHREG_PROTOCOL_USERPAY)); + AUTHREG_PROTOCOL_USERPAY st_UserPay = {}; + AUTHREG_USERTABLE st_UserInfo = {}; if (!st_FunSwitch.bSwitchPay) { @@ -221,6 +218,23 @@ bool XEngine_AuthorizeHTTP_User(XNETHANDLE xhToken, LPCXSTR lpszClientAddr, LPCX Session_Authorize_SetUser(&st_UserInfo); Protocol_Packet_HttpComm(tszSDBuffer, &nSDLen); XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP); + + if (st_AuthConfig.st_XNotify.st_EMailNotify.bEnable) + { + LPCXSTR lpszSubject = _X("XEngine_AuthorizeService User Pay notify!"); + XCHAR tszPayload[1024] = {}; + XCHAR tszTimeStr[128] = {}; + BaseLib_Time_TimeToStr(tszTimeStr); + _xstprintf(tszPayload, _X("http client:%s ,user name:%s ,user pay serial number:%s time on %s"), lpszClientAddr, st_UserPay.tszUserName, st_UserPay.tszSerialNumber, tszTimeStr); + if (MSGNotify_EMail_Send(st_AuthConfig.st_XNotify.st_EMailNotify.tszServiceAddr, st_AuthConfig.st_XNotify.st_EMailNotify.tszUser, st_AuthConfig.st_XNotify.st_EMailNotify.tszPass, st_AuthConfig.st_XNotify.st_EMailNotify.tszSendAddr, lpszSubject, tszPayload)) + { + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("HTTP客户端:%s,消息通知发送成功"), lpszClientAddr); + } + else + { + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("HTTP客户端:%s,消息通知发送失败,错误:%lX"), lpszClientAddr, MSGNotify_GetLastError()); + } + } XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_NOTICE, _X("HTTP客户端:%s,用户名:%s,充值成功,序列号:%s"), lpszClientAddr, st_UserPay.tszUserName, st_UserPay.tszSerialNumber); } else if (0 == _tcsxncmp(lpszAPIName, lpszAPIPass, _tcsxlen(lpszAPIName))) diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Hdr.h b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Hdr.h index 150c60d5..93c5a658 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Hdr.h +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Hdr.h @@ -52,6 +52,8 @@ using namespace std; #include "../../XEngine_DependLibrary/XEngine_Module/XEngine_InfoReport/InfoReport_Error.h" #include "../../XEngine_DependLibrary/XEngine_Module/XEngine_Verification/Verification_Define.h" #include "../../XEngine_DependLibrary/XEngine_Module/XEngine_Verification/Verification_Error.h" +#include "../../XEngine_DependLibrary/XEngine_Module/XEngine_MSGNotify/MSGNotify_Define.h" +#include "../../XEngine_DependLibrary/XEngine_Module/XEngine_MSGNotify/MSGNotify_Error.h" #include "../../XAuth_Protocol.h" #include "../../AuthorizeModule_Configure/Config_Define.h" #include "../../AuthorizeModule_Configure/Config_Error.h" @@ -133,6 +135,7 @@ extern XENGINE_FUNCTIONSWITCH st_FunSwitch; #pragma comment(lib,"../../x64/Debug/AuthorizeModule_Help.lib") #pragma comment(lib,"../../x64/Debug/XEngine_InfoReport.lib") #pragma comment(lib,"../../x64/Debug/XEngine_Verification.lib") +#pragma comment(lib,"../../x64/Debug/XEngine_MSGNotify.lib") #elif _M_ARM64 #pragma comment(lib,"../../ARM64/Debug/AuthorizeModule_Configure.lib") #pragma comment(lib,"../../ARM64/Debug/AuthorizeModule_Protocol.lib") @@ -141,6 +144,7 @@ extern XENGINE_FUNCTIONSWITCH st_FunSwitch; #pragma comment(lib,"../../ARM64/Debug/AuthorizeModule_Help.lib") #pragma comment(lib,"../../ARM64/Debug/XEngine_InfoReport.lib") #pragma comment(lib,"../../ARM64/Debug/XEngine_Verification.lib") +#pragma comment(lib,"../../ARM64/Debug/XEngine_MSGNotify.lib") #elif _M_IX86 #pragma comment(lib,"../../Debug/AuthorizeModule_Configure.lib") #pragma comment(lib,"../../Debug/AuthorizeModule_Protocol.lib") @@ -149,6 +153,7 @@ extern XENGINE_FUNCTIONSWITCH st_FunSwitch; #pragma comment(lib,"../../Debug/AuthorizeModule_Help.lib") #pragma comment(lib,"../../Debug/XEngine_InfoReport.lib") #pragma comment(lib,"../../Debug/XEngine_Verification.lib") +#pragma comment(lib,"../../Debug/XEngine_MSGNotify.lib") #endif #else #ifdef _M_X64 @@ -159,6 +164,7 @@ extern XENGINE_FUNCTIONSWITCH st_FunSwitch; #pragma comment(lib,"../../x64/Release/AuthorizeModule_Help.lib") #pragma comment(lib,"../../x64/Release/XEngine_InfoReport.lib") #pragma comment(lib,"../../x64/Release/XEngine_Verification.lib") +#pragma comment(lib,"../../x64/Release/XEngine_MSGNotify.lib") #elif _M_ARM64 #pragma comment(lib,"../../ARM64/Release/AuthorizeModule_Configure.lib") #pragma comment(lib,"../../ARM64/Release/AuthorizeModule_Protocol.lib") @@ -167,6 +173,7 @@ extern XENGINE_FUNCTIONSWITCH st_FunSwitch; #pragma comment(lib,"../../ARM64/Release/AuthorizeModule_Help.lib") #pragma comment(lib,"../../ARM64/Release/XEngine_InfoReport.lib") #pragma comment(lib,"../../ARM64/Release/XEngine_Verification.lib") +#pragma comment(lib,"../../ARM64/Release/XEngine_MSGNotify.lib") #elif _M_IX86 #pragma comment(lib,"../../Release/AuthorizeModule_Configure.lib") #pragma comment(lib,"../../Release/AuthorizeModule_Protocol.lib") @@ -175,6 +182,7 @@ extern XENGINE_FUNCTIONSWITCH st_FunSwitch; #pragma comment(lib,"../../Release/AuthorizeModule_Help.lib") #pragma comment(lib,"../../Release/XEngine_InfoReport.lib") #pragma comment(lib,"../../Release/XEngine_Verification.lib") +#pragma comment(lib,"../../Release/XEngine_MSGNotify.lib") #endif #endif #endif \ No newline at end of file From 960ed5e332a15b5ec415840dd8f218150c999151 Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Thu, 18 Jun 2026 15:26:56 +0800 Subject: [PATCH 28/59] modify:token of session module instead depend session module --- .../XEngine_Config/XEngine_Config.json | 9 + .../AuthorizeModule_Session.def | 13 +- .../AuthorizeModule_Session.vcxproj | 1 - .../AuthorizeModule_Session.vcxproj.filters | 6 - .../AuthorizeModule_Session/Makefile | 4 +- .../AuthorizeModule_Session/Session_Define.h | 149 +------ .../Session_Token/Session_Token.cpp | 375 ------------------ .../Session_Token/Session_Token.h | 48 --- .../AuthorizeModule_Session/pch.cpp | 39 +- XEngine_Source/XEngine.sln | 17 +- .../AuthorizeHTTP_GetTask.cpp | 14 +- .../AuthorizeHTTP_Get/AuthorizeHTTP_Token.cpp | 19 +- .../XEngine_AuthorizeService/Authorize_Hdr.h | 8 + .../Authorize_HttpTask.cpp | 2 +- .../Authorize_TCPTask.cpp | 2 +- .../Authorize_Task.cpp | 15 +- .../XEngine_AuthorizeService/Authorize_Task.h | 2 +- .../XEngine_AuthorizeService/Makefile | 4 +- .../XEngine_AuthorizeService.cpp | 2 +- 19 files changed, 66 insertions(+), 663 deletions(-) delete mode 100644 XEngine_Source/AuthorizeModule_Session/Session_Token/Session_Token.cpp delete mode 100644 XEngine_Source/AuthorizeModule_Session/Session_Token/Session_Token.h diff --git a/XEngine_Release/XEngine_Config/XEngine_Config.json b/XEngine_Release/XEngine_Config/XEngine_Config.json index 955e13e9..ceaff53d 100644 --- a/XEngine_Release/XEngine_Config/XEngine_Config.json +++ b/XEngine_Release/XEngine_Config/XEngine_Config.json @@ -82,6 +82,15 @@ "nLogType": 17, "bLogStorage": true }, + "XNotify": { + "XEmail": { + "bEnable": false, + "tszServiceAddr": "smtp://smtp.163.com", + "tszUser": "ggqytgodlove@163.com", + "tszPass": "1", + "tszSendAddr": "486179@qq.com" + } + }, "XReport": { "bEnable": true, "tszServiceName": "XEngine_Authorize", diff --git a/XEngine_Source/AuthorizeModule_Session/AuthorizeModule_Session.def b/XEngine_Source/AuthorizeModule_Session/AuthorizeModule_Session.def index 467624a6..be950a99 100644 --- a/XEngine_Source/AuthorizeModule_Session/AuthorizeModule_Session.def +++ b/XEngine_Source/AuthorizeModule_Session/AuthorizeModule_Session.def @@ -1,7 +1,7 @@ LIBRARY EXPORTS - Session_GetLastError + AuthSession_GetLastError Session_Authorize_Init Session_Authorize_GetClient @@ -9,13 +9,4 @@ EXPORTS Session_Authorize_CloseAddr Session_Authorize_Destroy Session_Authorize_Insert - Session_Authorize_SetUser - - Session_Token_Init - Session_Token_Destroy - Session_Token_Insert - Session_Token_Delete - Session_Token_UPDate - Session_Token_Get - Session_Token_GetUser - Session_Token_RenewalTime \ No newline at end of file + Session_Authorize_SetUser \ No newline at end of file diff --git a/XEngine_Source/AuthorizeModule_Session/AuthorizeModule_Session.vcxproj b/XEngine_Source/AuthorizeModule_Session/AuthorizeModule_Session.vcxproj index 30589c5f..3f4c74ea 100644 --- a/XEngine_Source/AuthorizeModule_Session/AuthorizeModule_Session.vcxproj +++ b/XEngine_Source/AuthorizeModule_Session/AuthorizeModule_Session.vcxproj @@ -253,7 +253,6 @@ - diff --git a/XEngine_Source/AuthorizeModule_Session/AuthorizeModule_Session.vcxproj.filters b/XEngine_Source/AuthorizeModule_Session/AuthorizeModule_Session.vcxproj.filters index a46b6995..e944e072 100644 --- a/XEngine_Source/AuthorizeModule_Session/AuthorizeModule_Session.vcxproj.filters +++ b/XEngine_Source/AuthorizeModule_Session/AuthorizeModule_Session.vcxproj.filters @@ -19,9 +19,6 @@ {98019e80-6680-48fa-a755-702b5b3aab78} - - {5ad6d359-09c2-4995-82f6-e5f2e32a14c1} - {0b721944-f23e-4671-81dc-beb1970fe840} @@ -42,9 +39,6 @@ 头文件\Session_Authorize - - 头文件\Session_Token - diff --git a/XEngine_Source/AuthorizeModule_Session/Makefile b/XEngine_Source/AuthorizeModule_Session/Makefile index b25b0a9c..7d462870 100644 --- a/XEngine_Source/AuthorizeModule_Session/Makefile +++ b/XEngine_Source/AuthorizeModule_Session/Makefile @@ -6,7 +6,7 @@ LOADHDR = -I ./ LOADSO = LIB = -lXEngine_BaseLib LIBEX = -OBJECTS = Session_Authorize.o Session_Token.o pch.o +OBJECTS = Session_Authorize.o pch.o ifeq ($(RELEASE),1) FLAGS = -c -D _RELEASE @@ -51,8 +51,6 @@ all:$(OBJECTS) Session_Authorize.o:./Session_Authorize/Session_Authorize.cpp $(CC) $(DEBUG) $(FLAGS) $(UNICODE) $(PLATVER) $(LOADHDR) ./Session_Authorize/Session_Authorize.cpp -Session_Token.o:./Session_Token/Session_Token.cpp - $(CC) $(DEBUG) $(FLAGS) $(UNICODE) $(PLATVER) $(LOADHDR) ./Session_Token/Session_Token.cpp pch.o:pch.cpp $(CC) $(DEBUG) $(FLAGS) $(UNICODE) $(PLATVER) $(LOADHDR) pch.cpp diff --git a/XEngine_Source/AuthorizeModule_Session/Session_Define.h b/XEngine_Source/AuthorizeModule_Session/Session_Define.h index 8192c686..c81115f7 100644 --- a/XEngine_Source/AuthorizeModule_Session/Session_Define.h +++ b/XEngine_Source/AuthorizeModule_Session/Session_Define.h @@ -30,7 +30,7 @@ typedef void(XCALLBACK* CALLBACK_XENGIEN_AUTHORIZE_SESSION_TOKEN_EVENTS)(XNETHAN ////////////////////////////////////////////////////////////////////////// // 导出的函数 ////////////////////////////////////////////////////////////////////////// -extern "C" XLONG Session_GetLastError(int *pInt_SysError = NULL); +extern "C" XLONG AuthSession_GetLastError(int *pInt_SysError = NULL); /************************************************************************/ /* 网络验证导出函数 */ /************************************************************************/ @@ -161,149 +161,4 @@ extern "C" bool Session_Authorize_Insert(LPCXSTR lpszClientAddr, AUTHREG_USERTAB 意思:是否成功 备注: *********************************************************************/ -extern "C" bool Session_Authorize_SetUser(AUTHREG_USERTABLE* pSt_UserTable); -/************************************************************************/ -/* TOKEN会话导出函数 */ -/************************************************************************/ -/******************************************************************** -函数名称:Session_Token_Init -函数功能:初始化会话 - 参数.一:nTimeout - In/Out:In - 类型:整数型 - 可空:N - 意思:超时时间,单位秒 - 参数.二:fpCall_AuthEvent - In/Out:In/Out - 类型:回调函数 - 可空:N - 意思:TOKEN登录的客户端连接超时回调 - 参数.三:lParam - In/Out:In/Out - 类型:无类型指针 - 可空:Y - 意思:回调函数自定义参数 -返回值 - 类型:逻辑型 - 意思:是否初始化成功 -备注: -*********************************************************************/ -extern "C" bool Session_Token_Init(int nTimeout, CALLBACK_XENGIEN_AUTHORIZE_SESSION_TOKEN_EVENTS fpCall_AuthEvent, XPVOID lParam = NULL); -/******************************************************************** -函数名称:Session_Token_Destroy -函数功能:销毁服务 -返回值 - 类型:逻辑型 - 意思:是否销毁成功 -备注: -*********************************************************************/ -extern "C" bool Session_Token_Destroy(); -/******************************************************************** -函数名称:Session_Authorize_Insert -函数功能:用户登陆协议分析 - 参数.一:xhToken - In/Out:In - 类型:句柄 - 可空:N - 意思:要操作的客户端 - 参数.二:pSt_UserTable - In/Out:In - 类型:数据结构指针 - 可空:N - 意思:用户信息表 -返回值 - 类型:逻辑型 - 意思:是否允许登陆 -备注: -*********************************************************************/ -extern "C" bool Session_Token_Insert(XNETHANDLE xhToken, AUTHREG_USERTABLE* pSt_UserTable); -/******************************************************************** -函数名称:Session_Token_Delete -函数功能:移除一个客户端 - 参数.一:xhToken - In/Out:In - 类型:句柄 - 可空:N - 意思:要操作的客户端 -返回值 - 类型:逻辑型 - 意思:是否移除成功 -备注: -*********************************************************************/ -extern "C" bool Session_Token_Delete(XNETHANDLE xhToken); -/******************************************************************** -函数名称:Session_Token_UPDate -函数功能:更新一个客户端的TOKEN时间 - 参数.一:xhToken - In/Out:In - 类型:句柄 - 可空:N - 意思:要操作的客户端 -返回值 - 类型:逻辑型 - 意思:是否成功 -备注: -*********************************************************************/ -extern "C" bool Session_Token_UPDate(XNETHANDLE xhToken); -/******************************************************************** -函数名称:Session_Token_Get -函数功能:获取客户端信息 - 参数.一:xhToken - In/Out:In - 类型:句柄 - 可空:N - 意思:要操作的客户端 - 参数.二:pSt_UserTable - In/Out:Out - 类型:数据结构指针 - 可空:Y - 意思:输出TOKEN对应的信息 -返回值 - 类型:逻辑型 - 意思:是否成功 -备注: -*********************************************************************/ -extern "C" bool Session_Token_Get(XNETHANDLE xhToken, AUTHREG_USERTABLE* pSt_UserTable = NULL); -/******************************************************************** -函数名称:Session_Token_GetUser -函数功能:获取用户是否存在 - 参数.一:lpszUser - In/Out:In - 类型:常量字符指针 - 可空:N - 意思:用户名 - 参数.二:lpszPass - In/Out:In - 类型:常量字符指针 - 可空:N - 意思:密码 - 参数.三:pxhToken - In/Out:Out - 类型:句柄 - 可空:N - 意思:导出获取到的句柄 -返回值 - 类型:逻辑型 - 意思:是否成功 -备注: -*********************************************************************/ -extern "C" bool Session_Token_GetUser(LPCXSTR lpszUser, LPCXSTR lpszPass, XNETHANDLE * pxhToken); -/******************************************************************** -函数名称:Session_Token_RenewalTime -函数功能:续期时间 - 参数.一:xhToken - In/Out:In - 类型:句柄 - 可空:N - 意思:输入要操作的TOKEN - 参数.二:pInt_RenewalTime - In/Out:Out - 类型:整数型指针 - 可空:N - 意思:输出续期的次数 -返回值 - 类型:逻辑型 - 意思:是否成功 -备注: -*********************************************************************/ -extern "C" bool Session_Token_RenewalTime(XNETHANDLE xhToken, int* pInt_RenewalTime); \ No newline at end of file +extern "C" bool Session_Authorize_SetUser(AUTHREG_USERTABLE* pSt_UserTable); \ No newline at end of file diff --git a/XEngine_Source/AuthorizeModule_Session/Session_Token/Session_Token.cpp b/XEngine_Source/AuthorizeModule_Session/Session_Token/Session_Token.cpp deleted file mode 100644 index 5e6f7430..00000000 --- a/XEngine_Source/AuthorizeModule_Session/Session_Token/Session_Token.cpp +++ /dev/null @@ -1,375 +0,0 @@ -#include "pch.h" -#include "Session_Token.h" -/******************************************************************** -// Created: 2022/08/18 14:43:33 -// File Name: D:\XEngine_Authorize\XEngine_Source\AuthorizeModule_Session\Session_Token\Session_Token.cpp -// File Path: D:\XEngine_Authorize\XEngine_Source\AuthorizeModule_Session\Session_Token -// File Base: Session_Token -// File Ext: cpp -// Project: XEngine(网络通信引擎) -// Author: qyt -// Purpose: TOKEN会话管理 -// History: -*********************************************************************/ -CSession_Token::CSession_Token() -{ - bIsRun = false; -} -CSession_Token::~CSession_Token() -{ -} -////////////////////////////////////////////////////////////////////////// -// 公有函数 -////////////////////////////////////////////////////////////////////////// -/******************************************************************** -函数名称:Session_Token_Init -函数功能:初始化会话 - 参数.一:nTimeout - In/Out:In - 类型:整数型 - 可空:N - 意思:超时时间,单位秒 - 参数.二:fpCall_AuthEvent - In/Out:In/Out - 类型:回调函数 - 可空:N - 意思:TOKEN登录的客户端连接超时回调 - 参数.三:lParam - In/Out:In/Out - 类型:无类型指针 - 可空:Y - 意思:回调函数自定义参数 -返回值 - 类型:逻辑型 - 意思:是否初始化成功 -备注: -*********************************************************************/ -bool CSession_Token::Session_Token_Init(int nTimeout, CALLBACK_XENGIEN_AUTHORIZE_SESSION_TOKEN_EVENTS fpCall_AuthEvent, XPVOID lParam /* = NULL */) -{ - Session_IsErrorOccur = false; - - if (NULL == fpCall_AuthEvent) - { - Session_IsErrorOccur = true; - Session_dwErrorCode = ERROR_AUTHORIZE_MODULE_SESSION_PARAMENT; - return false; - } - m_nTimeout = nTimeout; - m_lParam = lParam; - lpCall_AuthregEvents = fpCall_AuthEvent; - - bIsRun = true; - //创建线程 - pSTDThread_hActive = make_shared(Session_Token_Thread, this); - if (!pSTDThread_hActive->joinable()) - { - bIsRun = false; - Session_IsErrorOccur = true; - Session_dwErrorCode = ERROR_AUTHORIZE_MODULE_SESSION_CREATETHREAD; - return false; - } - return true; -} -/******************************************************************** -函数名称:Session_Token_Destroy -函数功能:销毁服务 -返回值 - 类型:逻辑型 - 意思:是否销毁成功 -备注: -*********************************************************************/ -bool CSession_Token::Session_Token_Destroy() -{ - Session_IsErrorOccur = false; - - bIsRun = false; - //结束线程 - if (NULL != pSTDThread_hActive) - { - pSTDThread_hActive->join(); - } - //释放客户端资源 - st_Locker.lock(); - stl_MapToken.clear(); - st_Locker.unlock(); - return true; -} -/******************************************************************** -函数名称:Session_Authorize_Insert -函数功能:用户登陆协议分析 - 参数.一:xhToken - In/Out:In - 类型:句柄 - 可空:N - 意思:要操作的客户端 - 参数.二:pSt_UserTable - In/Out:In - 类型:数据结构指针 - 可空:N - 意思:用户信息表 -返回值 - 类型:逻辑型 - 意思:是否允许登陆 -备注: -*********************************************************************/ -bool CSession_Token::Session_Token_Insert(XNETHANDLE xhToken, AUTHREG_USERTABLE* pSt_UserTable) -{ - Session_IsErrorOccur = false; - - if (NULL == pSt_UserTable) - { - Session_IsErrorOccur = true; - Session_dwErrorCode = ERROR_AUTHORIZE_MODULE_SESSION_PARAMENT; - return false; - } - AUTHSESSION_TOKENCLIENT st_TokenClient; - memset(&st_TokenClient,'\0',sizeof(AUTHSESSION_TOKENCLIENT)); - - BaseLib_Time_GetSysTime(&st_TokenClient.st_LibTimer); - memcpy(&st_TokenClient.st_UserTable, pSt_UserTable, sizeof(AUTHREG_USERTABLE)); - - st_Locker.lock(); - stl_MapToken.insert(make_pair(xhToken, st_TokenClient)); - st_Locker.unlock(); - return true; -} -/******************************************************************** -函数名称:Session_Token_Delete -函数功能:移除一个客户端 - 参数.一:xhToken - In/Out:In - 类型:句柄 - 可空:N - 意思:要操作的客户端 -返回值 - 类型:逻辑型 - 意思:是否移除成功 -备注: -*********************************************************************/ -bool CSession_Token::Session_Token_Delete(XNETHANDLE xhToken) -{ - Session_IsErrorOccur = false; - - st_Locker.lock(); - unordered_map::iterator stl_MapIterator = stl_MapToken.find(xhToken); - if (stl_MapIterator != stl_MapToken.end()) - { - //移除元素 - stl_MapToken.erase(stl_MapIterator); - } - st_Locker.unlock(); - return true; -} -/******************************************************************** -函数名称:Session_Token_UPDate -函数功能:更新一个客户端的TOKEN时间 - 参数.一:xhToken - In/Out:In - 类型:句柄 - 可空:N - 意思:要操作的客户端 -返回值 - 类型:逻辑型 - 意思:是否成功 -备注: -*********************************************************************/ -bool CSession_Token::Session_Token_UPDate(XNETHANDLE xhToken) -{ - Session_IsErrorOccur = false; - - st_Locker.lock_shared(); - unordered_map::iterator stl_MapIterator = stl_MapToken.find(xhToken); - if (stl_MapIterator == stl_MapToken.end()) - { - Session_IsErrorOccur = true; - Session_dwErrorCode = ERROR_AUTHORIZE_MODULE_SESSION_PARAMENT; - st_Locker.unlock_shared(); - return false; - } - BaseLib_Time_GetSysTime(&stl_MapIterator->second.st_LibTimer); - st_Locker.unlock_shared(); - return true; -} -/******************************************************************** -函数名称:Session_Token_Get -函数功能:获取客户端信息 - 参数.一:xhToken - In/Out:In - 类型:句柄 - 可空:N - 意思:要操作的客户端 - 参数.二:pSt_UserTable - In/Out:Out - 类型:数据结构指针 - 可空:Y - 意思:输出TOKEN对应的信息 -返回值 - 类型:逻辑型 - 意思:是否成功 -备注: -*********************************************************************/ -bool CSession_Token::Session_Token_Get(XNETHANDLE xhToken, AUTHREG_USERTABLE* pSt_UserTable /* = NULL */) -{ - Session_IsErrorOccur = false; - - st_Locker.lock_shared(); - unordered_map::iterator stl_MapIterator = stl_MapToken.find(xhToken); - if (stl_MapIterator == stl_MapToken.end()) - { - Session_IsErrorOccur = true; - Session_dwErrorCode = ERROR_AUTHORIZE_MODULE_SESSION_NOTFOUND; - st_Locker.unlock_shared(); - return false; - } - if (NULL != pSt_UserTable) - { - *pSt_UserTable = stl_MapIterator->second.st_UserTable; - } - st_Locker.unlock_shared(); - return true; -} -/******************************************************************** -函数名称:Session_Token_GetUser -函数功能:获取用户的TOKEN - 参数.一:lpszUser - In/Out:In - 类型:常量字符指针 - 可空:N - 意思:用户名 - 参数.二:lpszPass - In/Out:In - 类型:常量字符指针 - 可空:N - 意思:密码 - 参数.三:pxhToken - In/Out:Out - 类型:句柄 - 可空:N - 意思:导出获取到的句柄 -返回值 - 类型:逻辑型 - 意思:是否成功 -备注: -*********************************************************************/ -bool CSession_Token::Session_Token_GetUser(LPCXSTR lpszUser, LPCXSTR lpszPass, XNETHANDLE* pxhToken) -{ - Session_IsErrorOccur = false; - - if ((NULL == lpszUser) || (NULL == lpszPass)) - { - Session_IsErrorOccur = true; - Session_dwErrorCode = ERROR_AUTHORIZE_MODULE_SESSION_PARAMENT; - return false; - } - bool bFound = false; - st_Locker.lock_shared(); - unordered_map::iterator stl_MapIterator = stl_MapToken.begin(); - for (; stl_MapIterator != stl_MapToken.end(); stl_MapIterator++) - { - //用户名 - if (0 == _tcsxncmp(lpszUser, stl_MapIterator->second.st_UserTable.st_UserInfo.tszUserName, _tcsxlen(lpszUser))) - { - //密码,验证密码防治冲突 - if (0 == _tcsxncmp(lpszPass, stl_MapIterator->second.st_UserTable.st_UserInfo.tszUserPass, _tcsxlen(lpszPass))) - { - *pxhToken = stl_MapIterator->first; - bFound = true; - break; - } - } - } - st_Locker.unlock_shared(); - if (!bFound) - { - Session_IsErrorOccur = true; - Session_dwErrorCode = ERROR_AUTHORIZE_MODULE_SESSION_NOTFOUND; - return false; - } - return true; -} -/******************************************************************** -函数名称:Session_Token_RenewalTime -函数功能:续期时间 - 参数.一:xhToken - In/Out:In - 类型:句柄 - 可空:N - 意思:输入要操作的TOKEN - 参数.二:pInt_RenewalTime - In/Out:Out - 类型:整数型指针 - 可空:N - 意思:输出续期的次数 -返回值 - 类型:逻辑型 - 意思:是否成功 -备注: -*********************************************************************/ -bool CSession_Token::Session_Token_RenewalTime(XNETHANDLE xhToken, int* pInt_RenewalTime) -{ - Session_IsErrorOccur = false; - - st_Locker.lock_shared(); - unordered_map::iterator stl_MapIterator = stl_MapToken.find(xhToken); - if (stl_MapIterator == stl_MapToken.end()) - { - Session_IsErrorOccur = true; - Session_dwErrorCode = ERROR_AUTHORIZE_MODULE_SESSION_PARAMENT; - st_Locker.unlock_shared(); - return false; - } - stl_MapIterator->second.nRenewalTime++; - *pInt_RenewalTime = stl_MapIterator->second.nRenewalTime; - st_Locker.unlock_shared(); - return true; -} -////////////////////////////////////////////////////////////////////////// -// 线程函数 -////////////////////////////////////////////////////////////////////////// -XHTHREAD CSession_Token::Session_Token_Thread(XPVOID lParam) -{ - CSession_Token *pClass_This = (CSession_Token *)lParam; - XENGINE_LIBTIME st_LibTimer; - list stl_ListNotify; - - while (pClass_This->bIsRun) - { - //开始轮训用户 - pClass_This->st_Locker.lock_shared(); - unordered_map::iterator stl_MapIterator = pClass_This->stl_MapToken.begin(); - for (; stl_MapIterator != pClass_This->stl_MapToken.end(); stl_MapIterator++) - { - BaseLib_Time_GetSysTime(&st_LibTimer); //获取现在的系统时间 - __int64x nOnlineSpan = 0; //在线时间 - //用户登录了多少秒 - BaseLib_TimeSpan_GetForStu(&stl_MapIterator->second.st_LibTimer, &st_LibTimer, &nOnlineSpan, ENUM_XENGINE_BASELIB_TIME_TYPE_SECOND); - if (stl_MapIterator->second.nTimeout > 0) - { - if (nOnlineSpan > stl_MapIterator->second.nTimeout) - { - stl_ListNotify.push_back(stl_MapIterator->first); - } - } - else - { - if (nOnlineSpan > pClass_This->m_nTimeout) - { - stl_ListNotify.push_back(stl_MapIterator->first); - } - } - } - pClass_This->st_Locker.unlock_shared(); - //判断是否有需要关闭的客户端 - if (!stl_ListNotify.empty()) - { - list::iterator stl_ListIterator = stl_ListNotify.begin(); - for (; stl_ListIterator != stl_ListNotify.end(); stl_ListIterator++) - { - pClass_This->lpCall_AuthregEvents(*stl_ListIterator, pClass_This->m_lParam); - } - stl_ListNotify.clear(); //清理元素 - } - std::this_thread::sleep_for(std::chrono::seconds(1)); - } - return 0; -} diff --git a/XEngine_Source/AuthorizeModule_Session/Session_Token/Session_Token.h b/XEngine_Source/AuthorizeModule_Session/Session_Token/Session_Token.h deleted file mode 100644 index 9ab54a2f..00000000 --- a/XEngine_Source/AuthorizeModule_Session/Session_Token/Session_Token.h +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once -/******************************************************************** -// Created: 2022/08/18 14:29:38 -// File Name: D:\XEngine_Authorize\XEngine_Source\AuthorizeModule_Session\Session_Token\Session_Token.h -// File Path: D:\XEngine_Authorize\XEngine_Source\AuthorizeModule_Session\Session_Token -// File Base: Session_Token -// File Ext: h -// Project: XEngine(网络通信引擎) -// Author: qyt -// Purpose: TOKEN会话 -// History: -*********************************************************************/ -typedef struct -{ - AUTHREG_USERTABLE st_UserTable; //用户表 - XENGINE_LIBTIME st_LibTimer; //登录时间结构 - int nTimeout; //单独指定超时 - int nRenewalTime; //自动续期次数 -}AUTHSESSION_TOKENCLIENT, * LPAUTHSESSION_TOKENCLIENT; -////////////////////////////////////////////////////////////////////////// -class CSession_Token -{ -public: - CSession_Token(); - ~CSession_Token(); -public: - bool Session_Token_Init(int nTimeout, CALLBACK_XENGIEN_AUTHORIZE_SESSION_TOKEN_EVENTS fpCall_AuthEvent, XPVOID lParam = NULL); - bool Session_Token_Destroy(); - bool Session_Token_Insert(XNETHANDLE xhToken, AUTHREG_USERTABLE* pSt_UserTable); - bool Session_Token_Delete(XNETHANDLE xhToken); - bool Session_Token_UPDate(XNETHANDLE xhToken); - bool Session_Token_Get(XNETHANDLE xhToken, AUTHREG_USERTABLE* pSt_UserTable = NULL); - bool Session_Token_GetUser(LPCXSTR lpszUser, LPCXSTR lpszPass, XNETHANDLE* pxhToken); - bool Session_Token_RenewalTime(XNETHANDLE xhToken, int* pInt_RenewalTime); -protected: - static XHTHREAD Session_Token_Thread(XPVOID lParam); -private: - int m_nTimeout; - bool bIsRun; - shared_ptr pSTDThread_hActive; -private: - XPVOID m_lParam; - CALLBACK_XENGIEN_AUTHORIZE_SESSION_TOKEN_EVENTS lpCall_AuthregEvents; -private: - shared_mutex st_Locker; -private: - unordered_map stl_MapToken; -}; diff --git a/XEngine_Source/AuthorizeModule_Session/pch.cpp b/XEngine_Source/AuthorizeModule_Session/pch.cpp index 8082f0bc..7f968dc6 100644 --- a/XEngine_Source/AuthorizeModule_Session/pch.cpp +++ b/XEngine_Source/AuthorizeModule_Session/pch.cpp @@ -1,6 +1,5 @@ #include "pch.h" #include "Session_Authorize/Session_Authorize.h" -#include "Session_Token/Session_Token.h" /******************************************************************** // Created: 2022/05/26 10:53:58 // File Name: D:\XEngine_Authorize\XEngine_Source\AuthorizeModule_Session\pch.cpp @@ -16,11 +15,10 @@ bool Session_IsErrorOccur = false; XLONG Session_dwErrorCode = 0; ////////////////////////////////////////////////////////////////////////// CSession_Authorize m_SessionAuth; -CSession_Token m_SessionToken; ////////////////////////////////////////////////////////////////////////// // 导出的函数 ////////////////////////////////////////////////////////////////////////// -extern "C" XLONG Session_GetLastError(int* pInt_SysError) +extern "C" XLONG AuthSession_GetLastError(int* pInt_SysError) { if (NULL != pInt_SysError) { @@ -58,39 +56,4 @@ extern "C" bool Session_Authorize_Insert(LPCXSTR lpszClientAddr, AUTHREG_USERTAB extern "C" bool Session_Authorize_SetUser(AUTHREG_USERTABLE * pSt_UserTable) { return m_SessionAuth.Session_Authorize_SetUser(pSt_UserTable); -} -/************************************************************************/ -/* TOKEN会话导出函数 */ -/************************************************************************/ -extern "C" bool Session_Token_Init(int nTimeout, CALLBACK_XENGIEN_AUTHORIZE_SESSION_TOKEN_EVENTS fpCall_AuthEvent, XPVOID lParam) -{ - return m_SessionToken.Session_Token_Init(nTimeout, fpCall_AuthEvent, lParam); -} -extern "C" bool Session_Token_Destroy() -{ - return m_SessionToken.Session_Token_Destroy(); -} -extern "C" bool Session_Token_Insert(XNETHANDLE xhToken, AUTHREG_USERTABLE * pSt_UserTable) -{ - return m_SessionToken.Session_Token_Insert(xhToken, pSt_UserTable); -} -extern "C" bool Session_Token_Delete(XNETHANDLE xhToken) -{ - return m_SessionToken.Session_Token_Delete(xhToken); -} -extern "C" bool Session_Token_UPDate(XNETHANDLE xhToken) -{ - return m_SessionToken.Session_Token_UPDate(xhToken); -} -extern "C" bool Session_Token_Get(XNETHANDLE xhToken, AUTHREG_USERTABLE * pSt_UserTable) -{ - return m_SessionToken.Session_Token_Get(xhToken, pSt_UserTable); -} -extern "C" bool Session_Token_GetUser(LPCXSTR lpszUser, LPCXSTR lpszPass, XNETHANDLE * pxhToken) -{ - return m_SessionToken.Session_Token_GetUser(lpszUser, lpszPass, pxhToken); -} -extern "C" bool Session_Token_RenewalTime(XNETHANDLE xhToken, int* pInt_RenewalTime) -{ - return m_SessionToken.Session_Token_RenewalTime(xhToken, pInt_RenewalTime); } \ No newline at end of file diff --git a/XEngine_Source/XEngine.sln b/XEngine_Source/XEngine.sln index 6c1d83db..2379ca89 100644 --- a/XEngine_Source/XEngine.sln +++ b/XEngine_Source/XEngine.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 18 -VisualStudioVersion = 18.7.11911.148 stable +VisualStudioVersion = 18.7.11911.148 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "XEngine_HDRFile", "XEngine_HDRFile", "{D3A33095-8584-4EFB-9411-EBC38407E7B9}" ProjectSection(SolutionItems) = preProject @@ -75,6 +75,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XEngine_Verification", "XEn EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XEngine_MSGNotify", "XEngine_DependLibrary\XEngine_Module\XEngine_MSGNotify\XEngine_MSGNotify.vcxproj", "{E1087BA3-1074-4C6A-B770-A53B7BA1F4EA}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XEngine_Token", "XEngine_DependLibrary\XEngine_Module\XEngine_Token\XEngine_Token.vcxproj", "{E17E889F-D826-413F-854E-DBA6000B4DA7}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|ARM64 = Debug|ARM64 @@ -217,6 +219,18 @@ Global {E1087BA3-1074-4C6A-B770-A53B7BA1F4EA}.Release|x64.Build.0 = Release|x64 {E1087BA3-1074-4C6A-B770-A53B7BA1F4EA}.Release|x86.ActiveCfg = Release|Win32 {E1087BA3-1074-4C6A-B770-A53B7BA1F4EA}.Release|x86.Build.0 = Release|Win32 + {E17E889F-D826-413F-854E-DBA6000B4DA7}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {E17E889F-D826-413F-854E-DBA6000B4DA7}.Debug|ARM64.Build.0 = Debug|ARM64 + {E17E889F-D826-413F-854E-DBA6000B4DA7}.Debug|x64.ActiveCfg = Debug|x64 + {E17E889F-D826-413F-854E-DBA6000B4DA7}.Debug|x64.Build.0 = Debug|x64 + {E17E889F-D826-413F-854E-DBA6000B4DA7}.Debug|x86.ActiveCfg = Debug|Win32 + {E17E889F-D826-413F-854E-DBA6000B4DA7}.Debug|x86.Build.0 = Debug|Win32 + {E17E889F-D826-413F-854E-DBA6000B4DA7}.Release|ARM64.ActiveCfg = Release|ARM64 + {E17E889F-D826-413F-854E-DBA6000B4DA7}.Release|ARM64.Build.0 = Release|ARM64 + {E17E889F-D826-413F-854E-DBA6000B4DA7}.Release|x64.ActiveCfg = Release|x64 + {E17E889F-D826-413F-854E-DBA6000B4DA7}.Release|x64.Build.0 = Release|x64 + {E17E889F-D826-413F-854E-DBA6000B4DA7}.Release|x86.ActiveCfg = Release|Win32 + {E17E889F-D826-413F-854E-DBA6000B4DA7}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -228,6 +242,7 @@ Global {F6520D2C-BB8E-45BB-964B-F5D6A4318A89} = {6444F125-63DE-4120-98B3-DF097A9758FA} {A8E43EC0-698A-4807-8A61-B2BE5FAB7256} = {6444F125-63DE-4120-98B3-DF097A9758FA} {E1087BA3-1074-4C6A-B770-A53B7BA1F4EA} = {6444F125-63DE-4120-98B3-DF097A9758FA} + {E17E889F-D826-413F-854E-DBA6000B4DA7} = {6444F125-63DE-4120-98B3-DF097A9758FA} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {E1F1DDE3-8949-41AF-84D6-03CB7CAA03AB} diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Get/AuthorizeHTTP_GetTask.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Get/AuthorizeHTTP_GetTask.cpp index f0080dd1..a6af387e 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Get/AuthorizeHTTP_GetTask.cpp +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Get/AuthorizeHTTP_GetTask.cpp @@ -19,8 +19,8 @@ bool XEngine_AuthorizeHTTP_GetTask(LPCXSTR lpszClientAddr, XCHAR** pptszList, in memset(tszUserToken, '\0', sizeof(tszUserToken)); BaseLib_String_GetKeyValue(pptszList[1], "=", tszURLKey, tszUserToken); - AUTHREG_USERTABLE st_UserTable = {}; - if (!Session_Token_Get(_ttxoll(tszUserToken), &st_UserTable)) + XENGINE_PROTOCOL_USERINFO st_UserInfo = {}; + if (!Session_Token_Get(_ttxoll(tszUserToken), &st_UserInfo)) { Protocol_Packet_HttpComm(tszSDBuffer, &nSDLen, ERROR_AUTHORIZE_PROTOCOL_NOTFOUND, "user not found"); XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP); @@ -29,17 +29,17 @@ bool XEngine_AuthorizeHTTP_GetTask(LPCXSTR lpszClientAddr, XCHAR** pptszList, in } int nListCount = 0; AUTHSESSION_NETCLIENT** ppSt_ListClient; - if (!Session_Authorize_GetClient(&ppSt_ListClient, &nListCount, st_UserTable.st_UserInfo.tszUserName)) + if (!Session_Authorize_GetClient(&ppSt_ListClient, &nListCount, st_UserInfo.tszUserName)) { Protocol_Packet_HttpComm(tszSDBuffer, &nSDLen, ERROR_AUTHORIZE_PROTOCOL_NOTFOUND, "user not found"); XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP); - XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("HTTP客户端:%s,用户名:%s,获取时间失败,无法继续,错误:%X"), lpszClientAddr, st_UserTable.st_UserInfo.tszUserName, Session_GetLastError()); + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("HTTP客户端:%s,用户名:%s,获取时间失败,无法继续,错误:%X"), lpszClientAddr, st_UserInfo.tszUserName, Session_GetLastError()); return false; } Protocol_Packet_UserTime(tszSDBuffer, &nSDLen, &ppSt_ListClient, nListCount); BaseLib_Memory_Free((XPPPMEM)&ppSt_ListClient, nListCount); XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP); - XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("HTTP客户端:%s,用户名:%s,获取时间成功,用户同时在线数:%d"), lpszClientAddr, st_UserTable.st_UserInfo.tszUserName, nListCount); + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("HTTP客户端:%s,用户名:%s,获取时间成功,用户同时在线数:%d"), lpszClientAddr, st_UserInfo.tszUserName, nListCount); } else if (0 == _tcsxncmp(lpszAPIDCode, tszURLValue, _tcsxlen(lpszAPIDCode))) { @@ -64,8 +64,8 @@ bool XEngine_AuthorizeHTTP_GetTask(LPCXSTR lpszClientAddr, XCHAR** pptszList, in memset(tszUserToken, '\0', sizeof(tszUserToken)); BaseLib_String_GetKeyValue(pptszList[1], "=", tszURLKey, tszUserToken); - AUTHREG_USERTABLE st_UserTable = {}; - if (!Session_Token_Get(_ttxoll(tszUserToken), &st_UserTable)) + XENGINE_PROTOCOL_USERINFO st_UserInfo = {}; + if (!Session_Token_Get(_ttxoll(tszUserToken), &st_UserInfo)) { Protocol_Packet_HttpComm(tszSDBuffer, &nSDLen, ERROR_AUTHORIZE_PROTOCOL_NOTFOUND, "user not found"); XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP); diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Get/AuthorizeHTTP_Token.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Get/AuthorizeHTTP_Token.cpp index a5fdb8e6..eb5e9def 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Get/AuthorizeHTTP_Token.cpp +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Get/AuthorizeHTTP_Token.cpp @@ -18,16 +18,11 @@ bool XEngine_AuthorizeHTTP_Token(LPCXSTR lpszClientAddr, XCHAR** pptszList, int if (0 == _tcsxncmp(lpszAPILogin, tszURLValue, _tcsxlen(lpszAPILogin))) { //http://app.xyry.org:5302/api?function=login&user=123123aa&pass=123123&device=1 - XCHAR tszUserName[128]; - XCHAR tszUserPass[128]; - XCHAR tszDeviceType[128]; + XCHAR tszUserName[128] = {}; + XCHAR tszUserPass[128] = {}; + XCHAR tszDeviceType[128] = {}; XNETHANDLE xhToken = 0; - AUTHREG_USERTABLE st_UserTable; - - memset(tszUserName, '\0', sizeof(tszUserName)); - memset(tszUserPass, '\0', sizeof(tszUserPass)); - memset(tszDeviceType, '\0', sizeof(tszDeviceType)); - memset(&st_UserTable, '\0', sizeof(AUTHREG_USERTABLE)); + AUTHREG_USERTABLE st_UserTable = {}; if (nListCount < 4) { @@ -111,7 +106,7 @@ bool XEngine_AuthorizeHTTP_Token(LPCXSTR lpszClientAddr, XCHAR** pptszList, int { BaseLib_Handle_Create(&xhToken); } - Session_Token_Insert(xhToken, &st_UserTable); + Session_Token_Insert(xhToken, &st_UserTable.st_UserInfo); Protocol_Packet_HttpToken(tszSDBuffer, &nSDLen, xhToken, st_AuthConfig.st_XVerification.nTokenTimeout); XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP); XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("HTTP客户端:%s,请求登录获得TOKEN:%lld 成功,用户级别:%d"), lpszClientAddr, xhToken, st_UserTable.st_UserInfo.nUserLevel); @@ -124,7 +119,7 @@ bool XEngine_AuthorizeHTTP_Token(LPCXSTR lpszClientAddr, XCHAR** pptszList, int BaseLib_String_GetKeyValue(pptszList[1], "=", tszURLKey, tszUserToken); - if (!Session_Token_UPDate(_ttxoll(tszUserToken))) + if (!Session_Token_UPDateStr(tszUserToken)) { Protocol_Packet_HttpComm(tszSDBuffer, &nSDLen, ERROR_AUTHORIZE_PROTOCOL_NOTFOUND, "user not found"); XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP); @@ -143,7 +138,7 @@ bool XEngine_AuthorizeHTTP_Token(LPCXSTR lpszClientAddr, XCHAR** pptszList, int BaseLib_String_GetKeyValue(pptszList[1], "=", tszURLKey, tszUserToken); //主动关闭 - Session_Token_Delete(_ttxoll(tszUserToken)); + Session_Token_DeleteStr(tszUserToken); Protocol_Packet_HttpComm(tszSDBuffer, &nSDLen); XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP); XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("HTTP客户端:%s,请求关闭TOKEN:%s 成功"), lpszClientAddr, tszUserToken); diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Hdr.h b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Hdr.h index 93c5a658..c36870ca 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Hdr.h +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Hdr.h @@ -54,6 +54,8 @@ using namespace std; #include "../../XEngine_DependLibrary/XEngine_Module/XEngine_Verification/Verification_Error.h" #include "../../XEngine_DependLibrary/XEngine_Module/XEngine_MSGNotify/MSGNotify_Define.h" #include "../../XEngine_DependLibrary/XEngine_Module/XEngine_MSGNotify/MSGNotify_Error.h" +#include "../../XEngine_DependLibrary/XEngine_Module/XEngine_Token/Session_Define.h" +#include "../../XEngine_DependLibrary/XEngine_Module/XEngine_Token/Session_Error.h" #include "../../XAuth_Protocol.h" #include "../../AuthorizeModule_Configure/Config_Define.h" #include "../../AuthorizeModule_Configure/Config_Error.h" @@ -136,6 +138,7 @@ extern XENGINE_FUNCTIONSWITCH st_FunSwitch; #pragma comment(lib,"../../x64/Debug/XEngine_InfoReport.lib") #pragma comment(lib,"../../x64/Debug/XEngine_Verification.lib") #pragma comment(lib,"../../x64/Debug/XEngine_MSGNotify.lib") +#pragma comment(lib,"../../x64/Debug/XEngine_Token.lib") #elif _M_ARM64 #pragma comment(lib,"../../ARM64/Debug/AuthorizeModule_Configure.lib") #pragma comment(lib,"../../ARM64/Debug/AuthorizeModule_Protocol.lib") @@ -145,6 +148,7 @@ extern XENGINE_FUNCTIONSWITCH st_FunSwitch; #pragma comment(lib,"../../ARM64/Debug/XEngine_InfoReport.lib") #pragma comment(lib,"../../ARM64/Debug/XEngine_Verification.lib") #pragma comment(lib,"../../ARM64/Debug/XEngine_MSGNotify.lib") +#pragma comment(lib,"../../ARM64/Debug/XEngine_Token.lib") #elif _M_IX86 #pragma comment(lib,"../../Debug/AuthorizeModule_Configure.lib") #pragma comment(lib,"../../Debug/AuthorizeModule_Protocol.lib") @@ -154,6 +158,7 @@ extern XENGINE_FUNCTIONSWITCH st_FunSwitch; #pragma comment(lib,"../../Debug/XEngine_InfoReport.lib") #pragma comment(lib,"../../Debug/XEngine_Verification.lib") #pragma comment(lib,"../../Debug/XEngine_MSGNotify.lib") +#pragma comment(lib,"../../Debug/XEngine_Token.lib") #endif #else #ifdef _M_X64 @@ -165,6 +170,7 @@ extern XENGINE_FUNCTIONSWITCH st_FunSwitch; #pragma comment(lib,"../../x64/Release/XEngine_InfoReport.lib") #pragma comment(lib,"../../x64/Release/XEngine_Verification.lib") #pragma comment(lib,"../../x64/Release/XEngine_MSGNotify.lib") +#pragma comment(lib,"../../x64/Release/XEngine_Token.lib") #elif _M_ARM64 #pragma comment(lib,"../../ARM64/Release/AuthorizeModule_Configure.lib") #pragma comment(lib,"../../ARM64/Release/AuthorizeModule_Protocol.lib") @@ -174,6 +180,7 @@ extern XENGINE_FUNCTIONSWITCH st_FunSwitch; #pragma comment(lib,"../../ARM64/Release/XEngine_InfoReport.lib") #pragma comment(lib,"../../ARM64/Release/XEngine_Verification.lib") #pragma comment(lib,"../../ARM64/Release/XEngine_MSGNotify.lib") +#pragma comment(lib,"../../ARM64/Release/XEngine_Token.lib") #elif _M_IX86 #pragma comment(lib,"../../Release/AuthorizeModule_Configure.lib") #pragma comment(lib,"../../Release/AuthorizeModule_Protocol.lib") @@ -183,6 +190,7 @@ extern XENGINE_FUNCTIONSWITCH st_FunSwitch; #pragma comment(lib,"../../Release/XEngine_InfoReport.lib") #pragma comment(lib,"../../Release/XEngine_Verification.lib") #pragma comment(lib,"../../Release/XEngine_MSGNotify.lib") +#pragma comment(lib,"../../Release/XEngine_Token.lib") #endif #endif #endif \ No newline at end of file diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_HttpTask.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_HttpTask.cpp index 411c9b3a..551c309c 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_HttpTask.cpp +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_HttpTask.cpp @@ -208,7 +208,7 @@ bool XEngine_Client_HttpTask(LPCXSTR lpszClientAddr, LPCXSTR lpszMsgBuffer, int //得到TOKEN if (Protocol_Parse_HttpParseToken(lpszMsgBuffer, nMsgLen, &xhToken)) { - if (!Session_Token_Get(xhToken, &st_UserTable)) + if (!Session_Token_Get(xhToken, &st_UserTable.st_UserInfo)) { Protocol_Packet_HttpComm(tszSDBuffer, &nSDLen, ERROR_AUTHORIZE_PROTOCOL_UNAUTHORIZE, "Unauthorized"); XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP); diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_TCPTask.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_TCPTask.cpp index e5b8d274..e6ef312d 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_TCPTask.cpp +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_TCPTask.cpp @@ -381,7 +381,7 @@ bool XEngine_Client_TCPTask(LPCXSTR lpszClientAddr, LPCXSTR lpszMsgBuffer, int n } if (st_FunSwitch.bSwitchTokenLogin) { - Session_Token_Insert(pSt_ProtocolHdr->xhToken, &st_UserTable); + Session_Token_Insert(pSt_ProtocolHdr->xhToken, &st_UserTable.st_UserInfo); } //记录每次登陆 XCHAR tszIPAddr[128] = {}; diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Task.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Task.cpp index ab1114bf..1917b6e0 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Task.cpp +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Task.cpp @@ -61,19 +61,18 @@ void XCALLBACK XEngine_TaskEvent_Client(LPCXSTR lpszUserAddr, LPCXSTR lpszUserNa DBModule_MySQL_UserLeave(&st_AuthTime); } } -void XCALLBACK XEngine_TaskEvent_Token(XNETHANDLE xhToken, XPVOID lParam) +void XCALLBACK XEngine_TaskEvent_Token(LPCXSTR lpszTokenStr, int nTimeout, int nTimerenewal, XENGINE_LIBTIME* pSt_LibTime, XENGINE_PROTOCOL_USERINFO* pSt_UserInfo, XPVOID lParam) { bool bRemove = true; - AUTHREG_USERTABLE st_UserTable; - memset(&st_UserTable, '\0', sizeof(AUTHREG_USERTABLE)); + XENGINE_PROTOCOL_USERINFO st_UserInfo; - Session_Token_Get(xhToken, &st_UserTable); + Session_Token_GetStr(lpszTokenStr, &st_UserInfo); //自动续期? if (st_AuthConfig.st_XVerification.st_XToken.bAutoRenewal) { int nRenewalTime = 0; - Session_Token_RenewalTime(xhToken, &nRenewalTime); - + Session_Token_UPDateStr(lpszTokenStr); + Session_Token_GetTimeRenewalStr(lpszTokenStr, &nRenewalTime); if (-1 == st_AuthConfig.st_XVerification.st_XToken.nRenewalTime) { bRemove = false; @@ -89,7 +88,7 @@ void XCALLBACK XEngine_TaskEvent_Token(XNETHANDLE xhToken, XPVOID lParam) if (bRemove) { - Session_Token_Delete(xhToken); - XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("Token:%lld,用户名:%s,已经超时,权限级别:%d,被移除服务器"), xhToken, st_UserTable.st_UserInfo.tszUserName, st_UserTable.st_UserInfo.nUserLevel); + Session_Token_DeleteStr(lpszTokenStr); + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("Token:%s,用户名:%s,已经超时,权限级别:%d,被移除服务器"), lpszTokenStr, st_UserInfo.tszUserName, st_UserInfo.nUserLevel); } } \ No newline at end of file diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Task.h b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Task.h index c71acacd..84c11e56 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Task.h +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Task.h @@ -1,4 +1,4 @@ #pragma once void XCALLBACK XEngine_TaskEvent_Client(LPCXSTR lpszUserAddr, LPCXSTR lpszUserName, __int64x nOnlineTimer, __int64x nLeftTimer, LPCXSTR lpszLeftDate, ENUM_VERIFICATION_MODULE_SERIAL_TYPE enSerialType, ENUM_PROTOCOLDEVICE_TYPE enDeviceType, int nNetType, XPVOID lParam); -void XCALLBACK XEngine_TaskEvent_Token(XNETHANDLE xhToken, XPVOID lParam); \ No newline at end of file +void XCALLBACK XEngine_TaskEvent_Token(LPCXSTR lpszTokenStr, int nTimeout, int nTimerenewal, XENGINE_LIBTIME* pSt_LibTime, XENGINE_PROTOCOL_USERINFO* pSt_UserInfo, XPVOID lParam); \ No newline at end of file diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Makefile b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Makefile index 386b47b1..5bc02e1a 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Makefile +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Makefile @@ -3,9 +3,9 @@ PLATVER = FILEEXT = LIBFLAG = LOADHDR = -I ./ -LOADSO = -L ../../XEngine_DependLibrary/XEngine_Module/jsoncpp -L ../../XEngine_DependLibrary/XEngine_Module/XEngine_InfoReport -L ../../XEngine_DependLibrary/XEngine_Module/XEngine_Verification \ +LOADSO = -L ../../XEngine_DependLibrary/XEngine_Module/jsoncpp -L ../../XEngine_DependLibrary/XEngine_Module/XEngine_InfoReport -L ../../XEngine_DependLibrary/XEngine_Module/XEngine_Verification -L ../../XEngine_DependLibrary/XEngine_Module/XEngine_MSGNotify \ -L ../../AuthorizeModule_Session -L ../../AuthorizeModule_Database -L ../../AuthorizeModule_Protocol -L ../../AuthorizeModule_Configure -L ../../AuthorizeModule_Help -L ../../AuthorizeModule_CDKey -LIB = -lXEngine_InfoReport -ljsoncpp -lXEngine_Verification \ +LIB = -lXEngine_InfoReport -ljsoncpp -lXEngine_Verification -lXEngine_MSGNotify \ -lXEngine_BaseLib -lXEngine_Algorithm -lXEngine_Core -lXEngine_ManagePool -lXEngine_Cryption -lXClient_APIHelp -lNetHelp_APIAddr -lHelpComponents_Packets -lHelpComponents_DataBase -lHelpComponents_XLog -lRfcComponents_WSProtocol -lRfcComponents_HttpProtocol -lRfcComponents_MQTTProtocol -lXEngine_SystemApi \ -lAuthorizeModule_Session -lAuthorizeModule_Database -lAuthorizeModule_Protocol -lAuthorizeModule_Configure -lAuthorizeModule_Help LIBEX = diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/XEngine_AuthorizeService.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/XEngine_AuthorizeService.cpp index 6598e5d2..421bb356 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/XEngine_AuthorizeService.cpp +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/XEngine_AuthorizeService.cpp @@ -243,7 +243,7 @@ int main(int argc, char** argv) goto XENGINE_EXITAPP; } XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("启动服务中,初始化会话客户端服务成功")); - if (!Session_Token_Init(st_AuthConfig.st_XVerification.nTokenTimeout, XEngine_TaskEvent_Token)) + if (!Session_Token_Init(st_AuthConfig.st_XVerification.nTokenTimeout, true, XEngine_TaskEvent_Token)) { XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("启动服务中,初始化会话TOKEN服务失败,错误:%lX"), Session_GetLastError()); goto XENGINE_EXITAPP; From 29fa1362d7b5c1979b1dd866f1f80c5fd92a324a Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Thu, 18 Jun 2026 15:33:47 +0800 Subject: [PATCH 29/59] fixed:build failure --- .../AuthorizeModule_Session/AuthorizeModule_Session.vcxproj | 1 - .../AuthorizeModule_Session.vcxproj.filters | 6 ------ .../XEngine_APPService/XEngine_AuthorizeService/Makefile | 4 ++-- 3 files changed, 2 insertions(+), 9 deletions(-) diff --git a/XEngine_Source/AuthorizeModule_Session/AuthorizeModule_Session.vcxproj b/XEngine_Source/AuthorizeModule_Session/AuthorizeModule_Session.vcxproj index 3f4c74ea..5dd11d2b 100644 --- a/XEngine_Source/AuthorizeModule_Session/AuthorizeModule_Session.vcxproj +++ b/XEngine_Source/AuthorizeModule_Session/AuthorizeModule_Session.vcxproj @@ -265,7 +265,6 @@ Create - diff --git a/XEngine_Source/AuthorizeModule_Session/AuthorizeModule_Session.vcxproj.filters b/XEngine_Source/AuthorizeModule_Session/AuthorizeModule_Session.vcxproj.filters index e944e072..3b6482ba 100644 --- a/XEngine_Source/AuthorizeModule_Session/AuthorizeModule_Session.vcxproj.filters +++ b/XEngine_Source/AuthorizeModule_Session/AuthorizeModule_Session.vcxproj.filters @@ -19,9 +19,6 @@ {98019e80-6680-48fa-a755-702b5b3aab78} - - {0b721944-f23e-4671-81dc-beb1970fe840} - @@ -50,9 +47,6 @@ 源文件\Session_Authorize - - 源文件\Session_Token - diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Makefile b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Makefile index 5bc02e1a..b3816500 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Makefile +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Makefile @@ -3,9 +3,9 @@ PLATVER = FILEEXT = LIBFLAG = LOADHDR = -I ./ -LOADSO = -L ../../XEngine_DependLibrary/XEngine_Module/jsoncpp -L ../../XEngine_DependLibrary/XEngine_Module/XEngine_InfoReport -L ../../XEngine_DependLibrary/XEngine_Module/XEngine_Verification -L ../../XEngine_DependLibrary/XEngine_Module/XEngine_MSGNotify \ +LOADSO = -L ../../XEngine_DependLibrary/XEngine_Module/jsoncpp -L ../../XEngine_DependLibrary/XEngine_Module/XEngine_InfoReport -L ../../XEngine_DependLibrary/XEngine_Module/XEngine_Verification -L ../../XEngine_DependLibrary/XEngine_Module/XEngine_MSGNotify -L ../../XEngine_DependLibrary/XEngine_Module/XEngine_Token \ -L ../../AuthorizeModule_Session -L ../../AuthorizeModule_Database -L ../../AuthorizeModule_Protocol -L ../../AuthorizeModule_Configure -L ../../AuthorizeModule_Help -L ../../AuthorizeModule_CDKey -LIB = -lXEngine_InfoReport -ljsoncpp -lXEngine_Verification -lXEngine_MSGNotify \ +LIB = -lXEngine_InfoReport -ljsoncpp -lXEngine_Verification -lXEngine_MSGNotify -lXEngine_Token \ -lXEngine_BaseLib -lXEngine_Algorithm -lXEngine_Core -lXEngine_ManagePool -lXEngine_Cryption -lXClient_APIHelp -lNetHelp_APIAddr -lHelpComponents_Packets -lHelpComponents_DataBase -lHelpComponents_XLog -lRfcComponents_WSProtocol -lRfcComponents_HttpProtocol -lRfcComponents_MQTTProtocol -lXEngine_SystemApi \ -lAuthorizeModule_Session -lAuthorizeModule_Database -lAuthorizeModule_Protocol -lAuthorizeModule_Configure -lAuthorizeModule_Help LIBEX = From d767ac83aeae7b4c064bf5fb9e112e23ac8c2c13 Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Thu, 18 Jun 2026 15:39:29 +0800 Subject: [PATCH 30/59] fixed:build error --- XEngine_Source/Makefile | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/XEngine_Source/Makefile b/XEngine_Source/Makefile index a2e79cea..93b9b217 100644 --- a/XEngine_Source/Makefile +++ b/XEngine_Source/Makefile @@ -8,6 +8,7 @@ DEPEND_JSONCPP_PATH = ./XEngine_DependLibrary/XEngine_Module/jsoncpp DEPEND_REPORT_PATH = ./XEngine_DependLibrary/XEngine_Module/XEngine_InfoReport DEPEND_VERIFICATION_PATH = ./XEngine_DependLibrary/XEngine_Module/XEngine_Verification DEPEND_MSGNOTIFY_PATH = ./XEngine_DependLibrary/XEngine_Module/XEngine_MSGNotify +DEPEND_TOKEN_PATH = ./XEngine_DependLibrary/XEngine_Module/XEngine_Token AUTH_SESSION_PATH = ./AuthorizeModule_Session AUTH_DATABASE_PATH = ./AuthorizeModule_Database @@ -24,7 +25,7 @@ else ifeq ($(PLATFORM),mac) endif # 第三方库模块 -MODULES_THIRD = libjsoncpp.so libXEngine_InfoReport.so libXEngine_Verification.so libXEngine_MSGNotify.so \ +MODULES_THIRD = libjsoncpp.so libXEngine_InfoReport.so libXEngine_Verification.so libXEngine_MSGNotify.so libXEngine_Token.so \ # 业务模块 + 应用 MODULES_APP = libAuthorizeModule_Session.so libAuthorizeModule_Database.so libAuthorizeModule_Protocol.so libAuthorizeModule_Configure.so libAuthorizeModule_Help.so \ XEngine_AuthorizeApp.exe @@ -66,6 +67,12 @@ ifeq ($(FLAGS), InstallAll) else make -C $(DEPEND_MSGNOTIFY_PATH) PLATFORM=$(PLATFORM) $(FLAGS) endif +libXEngine_Token.so: +ifeq ($(FLAGS), InstallAll) + cp $(DEPEND_TOKEN_PATH)/libXEngine_Token.$(FILEEXT) ../XEngine_Release/ +else + make -C $(DEPEND_TOKEN_PATH) PLATFORM=$(PLATFORM) $(FLAGS) +endif libAuthorizeModule_Session.so: make -C $(AUTH_SESSION_PATH) PLATFORM=$(PLATFORM) UNICODE=$(UNICODE) $(FLAGS) From 551acd0c7371157525864958cc217e708ae3d541 Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Thu, 18 Jun 2026 15:49:38 +0800 Subject: [PATCH 31/59] modify:adjust order build --- XEngine_Source/XEngine.sln | 2 ++ 1 file changed, 2 insertions(+) diff --git a/XEngine_Source/XEngine.sln b/XEngine_Source/XEngine.sln index 2379ca89..396adf12 100644 --- a/XEngine_Source/XEngine.sln +++ b/XEngine_Source/XEngine.sln @@ -38,6 +38,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XEngine_AuthorizeService", {A8E43EC0-698A-4807-8A61-B2BE5FAB7256} = {A8E43EC0-698A-4807-8A61-B2BE5FAB7256} {AB3DB24C-E1B3-41CF-B2F4-6C12E13C2894} = {AB3DB24C-E1B3-41CF-B2F4-6C12E13C2894} {CB9138DF-789D-459F-AD43-4095B22A487F} = {CB9138DF-789D-459F-AD43-4095B22A487F} + {E1087BA3-1074-4C6A-B770-A53B7BA1F4EA} = {E1087BA3-1074-4C6A-B770-A53B7BA1F4EA} + {E17E889F-D826-413F-854E-DBA6000B4DA7} = {E17E889F-D826-413F-854E-DBA6000B4DA7} {F1736B3F-03A2-4FC7-B045-A12BA8D724FB} = {F1736B3F-03A2-4FC7-B045-A12BA8D724FB} {F6520D2C-BB8E-45BB-964B-F5D6A4318A89} = {F6520D2C-BB8E-45BB-964B-F5D6A4318A89} EndProjectSection From 6f2eef7ae0ce3f9c0ad89d4769203d507e549f25 Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Thu, 18 Jun 2026 16:17:13 +0800 Subject: [PATCH 32/59] delete:get notice of task code and modify notice permission --- XEngine_Docment/Docment_en.docx | Bin 155896 -> 155965 bytes XEngine_Docment/Docment_zh.docx | Bin 158924 -> 160793 bytes .../AuthorizeHTTP_GetTask.cpp | 17 ----------------- .../Authorize_HttpTask.cpp | 15 ++++++++------- 4 files changed, 8 insertions(+), 24 deletions(-) diff --git a/XEngine_Docment/Docment_en.docx b/XEngine_Docment/Docment_en.docx index dc9ebac0269252cdd4d63776729d91776485bd2f..575294e856c991ae8c0bcf6179a4a89c0fa19697 100644 GIT binary patch delta 135972 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

7P8AEJKj9sS*U*W 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 LmW17462$)i2U}~) diff --git a/XEngine_Docment/Docment_zh.docx b/XEngine_Docment/Docment_zh.docx index b7884fdd3b60f250cc40cd70117f9a6442faa366..4553a3fdf4623849494c0f47f4efd67507a1f4ce 100644 GIT binary patch delta 141428 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

2mrpj_7M9e= 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 delta 139456 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 diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Get/AuthorizeHTTP_GetTask.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Get/AuthorizeHTTP_GetTask.cpp index a6af387e..1a8c843e 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Get/AuthorizeHTTP_GetTask.cpp +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Get/AuthorizeHTTP_GetTask.cpp @@ -58,22 +58,5 @@ bool XEngine_AuthorizeHTTP_GetTask(LPCXSTR lpszClientAddr, XCHAR** pptszList, in XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP); XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("HTTP客户端:%s,请求获得动态验证码成功,TOKEN:%lld,验证码:%d"), lpszClientAddr, xhToken, nDCode); } - else if (0 == _tcsxncmp(lpszAPINotice, tszURLValue, _tcsxlen(lpszAPINotice))) - { - XCHAR tszUserToken[128]; - memset(tszUserToken, '\0', sizeof(tszUserToken)); - BaseLib_String_GetKeyValue(pptszList[1], "=", tszURLKey, tszUserToken); - - XENGINE_PROTOCOL_USERINFO st_UserInfo = {}; - if (!Session_Token_Get(_ttxoll(tszUserToken), &st_UserInfo)) - { - Protocol_Packet_HttpComm(tszSDBuffer, &nSDLen, ERROR_AUTHORIZE_PROTOCOL_NOTFOUND, "user not found"); - XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP); - XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("HTTP客户端:%s,获取通告失败,无法继续,错误:%X"), lpszClientAddr, Session_GetLastError()); - return false; - } - //http://app.xyry.org:5302/api?function=notice - XEngine_AuthorizeHTTP_Announcement(lpszClientAddr, _X("list"), NULL, 0); - } return true; } \ No newline at end of file diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_HttpTask.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_HttpTask.cpp index 551c309c..d8c7a7a6 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_HttpTask.cpp +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_HttpTask.cpp @@ -269,10 +269,13 @@ bool XEngine_Client_HttpTask(LPCXSTR lpszClientAddr, LPCXSTR lpszMsgBuffer, int //验证权限 if (0 != st_UserTable.st_UserInfo.nUserLevel) { - Protocol_Packet_HttpComm(tszSDBuffer, &nSDLen, ERROR_AUTHORIZE_PROTOCOL_UNAUTHORIZE, "permission is failed"); - XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP); - XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("HTTP客户端:%s,请求的API:%s 失败,因为TOKEN权限不足"), lpszClientAddr, pSt_HTTPParament->tszHttpUri); - return false; + if (0 != _tcsxncmp(_X("list"), tszAPIName, 4)) + { + Protocol_Packet_HttpComm(tszSDBuffer, &nSDLen, ERROR_AUTHORIZE_PROTOCOL_UNAUTHORIZE, "permission is failed"); + XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP); + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("HTTP客户端:%s,请求的API:%s 失败,因为TOKEN权限不足"), lpszClientAddr, pSt_HTTPParament->tszHttpUri); + return false; + } } XEngine_AuthorizeHTTP_Announcement(lpszClientAddr, tszAPIName, lpszMsgBuffer, nMsgLen); } @@ -327,7 +330,6 @@ bool XEngine_Client_HttpTask(LPCXSTR lpszClientAddr, LPCXSTR lpszMsgBuffer, int LPCXSTR lpszFuncName = _X("api"); LPCXSTR lpszAPIVerDCode = _X("dcode"); LPCXSTR lpszAPIVerTime = _X("time"); - LPCXSTR lpszAPIVerNotice = _X("notice"); memset(tszUrlName, '\0', sizeof(tszUrlName)); HttpProtocol_ServerHelp_GetParament(pSt_HTTPParament->tszHttpUri, &pptszList, &nListCount, tszUrlName); @@ -346,8 +348,7 @@ bool XEngine_Client_HttpTask(LPCXSTR lpszClientAddr, LPCXSTR lpszMsgBuffer, int memset(tszURLValue, '\0', sizeof(tszURLValue)); BaseLib_String_GetKeyValue(pptszList[0], "=", tszURLKey, tszURLValue); - if (0 == _tcsxncmp(lpszAPIVerDCode, tszURLValue, _tcsxlen(lpszAPIVerDCode)) || 0 == _tcsxncmp(lpszAPIVerTime, tszURLValue, _tcsxlen(lpszAPIVerTime)) || - 0 == _tcsxncmp(lpszAPIVerNotice, tszURLValue, _tcsxlen(lpszAPIVerNotice))) + if (0 == _tcsxncmp(lpszAPIVerDCode, tszURLValue, _tcsxlen(lpszAPIVerDCode)) || 0 == _tcsxncmp(lpszAPIVerTime, tszURLValue, _tcsxlen(lpszAPIVerTime))) { XEngine_AuthorizeHTTP_GetTask(lpszClientAddr, pptszList, nListCount); } From ba5c818d902bedc1f98cb6033c776c994b4bc436 Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Mon, 22 Jun 2026 17:17:14 +0800 Subject: [PATCH 33/59] feat: add agentic workflows for issue triage and auto fix --- .github/workflows/auto-code.lock.yml | 210 +++++++++++++++--------- .github/workflows/auto-code.md | 9 +- .github/workflows/issue-triage.lock.yml | 210 +++++++++++++++--------- .github/workflows/issue-triage.md | 9 +- 4 files changed, 266 insertions(+), 172 deletions(-) diff --git a/.github/workflows/auto-code.lock.yml b/.github/workflows/auto-code.lock.yml index a986bab2..2f5a1c52 100644 --- a/.github/workflows/auto-code.lock.yml +++ b/.github/workflows/auto-code.lock.yml @@ -1,5 +1,5 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"f34010347cc4a69b71b53db22f8dc512613b8882c182be2d39f5926593e3272a","body_hash":"9959a757362d73cb28768bc2f9a90afc30a49f61e3226f922c791d0cbf387678","compiler_version":"v0.79.6","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}} -# gh-aw-manifest: {"version":1,"secrets":["GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"5c2fe865bb4dc46e1450f6ee0d0541d759aea73a","version":"v0.79.6"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2","digest":"sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2","digest":"sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2@sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2","digest":"sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2@sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.25","digest":"sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.25@sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa"},{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"07e5ed7d15413c222090f5a372855d48af5672ce5695f4d9d2726a8d9e46f08b","body_hash":"9959a757362d73cb28768bc2f9a90afc30a49f61e3226f922c791d0cbf387678","compiler_version":"v0.79.6","strict":true,"agent_id":"codex","engine_versions":{"codex":"0.137.0"}} +# gh-aw-manifest: {"version":1,"secrets":["CODEX_API_KEY","GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"5c2fe865bb4dc46e1450f6ee0d0541d759aea73a","version":"v0.79.6"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2","digest":"sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2","digest":"sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2@sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2","digest":"sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2@sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.25","digest":"sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.25@sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa"},{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]} # ___ _ _ # / _ \ | | (_) # | |_| | __ _ ___ _ __ | |_ _ ___ @@ -24,6 +24,7 @@ # # # Secrets used: +# - CODEX_API_KEY # - GH_AW_CI_TRIGGER_TOKEN # - GH_AW_GITHUB_MCP_SERVER_TOKEN # - GH_AW_GITHUB_TOKEN @@ -34,6 +35,7 @@ # - actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 # - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 # - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 +# - actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 # - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 # - github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 # @@ -77,6 +79,7 @@ jobs: engine_id: ${{ steps.generate_aw_info.outputs.engine_id }} lockdown_check_failed: ${{ steps.generate_aw_info.outputs.lockdown_check_failed == 'true' }} model: ${{ steps.generate_aw_info.outputs.model }} + secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} 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 }} @@ -96,17 +99,17 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "自动处理 Issue" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/auto-code.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_VERSION: "0.137.0" GH_AW_INFO_AWF_VERSION: "v0.27.2" - GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_INFO_ENGINE_ID: "codex" - name: Generate agentic run info id: generate_aw_info env: - GH_AW_INFO_ENGINE_ID: "copilot" - GH_AW_INFO_ENGINE_NAME: "GitHub Copilot CLI" - GH_AW_INFO_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || vars.GH_AW_DEFAULT_MODEL_COPILOT || 'claude-sonnet-4.6' }} - GH_AW_INFO_VERSION: "1.0.60" - GH_AW_INFO_AGENT_VERSION: "1.0.60" + GH_AW_INFO_ENGINE_ID: "codex" + GH_AW_INFO_ENGINE_NAME: "Codex" + GH_AW_INFO_MODEL: ${{ vars.GH_AW_MODEL_AGENT_CODEX || vars.GH_AW_DEFAULT_MODEL_CODEX || 'gpt-5.4' }} + GH_AW_INFO_VERSION: "0.137.0" + GH_AW_INFO_AGENT_VERSION: "0.137.0" GH_AW_INFO_CLI_VERSION: "v0.79.6" GH_AW_INFO_WORKFLOW_NAME: "自动处理 Issue" GH_AW_INFO_EXPERIMENTAL: "false" @@ -143,6 +146,12 @@ jobs: setupGlobals(core, github, context, exec, io, getOctokit); const { main } = require('${{ runner.temp }}/gh-aw/actions/check_daily_aic_workflow_guardrail.cjs'); await main(); + - name: Validate CODEX_API_KEY or OPENAI_API_KEY secret + id: validate-secret + run: bash "${RUNNER_TEMP}/gh-aw/actions/validate_multi_secret.sh" CODEX_API_KEY OPENAI_API_KEY Codex https://github.github.com/gh-aw/reference/engines/#openai-codex + env: + CODEX_API_KEY: ${{ secrets.CODEX_API_KEY }} + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - name: Checkout .github and .agents folders uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: @@ -191,7 +200,7 @@ jobs: id: sanitized uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: - GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,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,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" + GH_AW_ALLOWED_DOMAINS: "172.30.0.1,api.openai.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,chatgpt.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,host.docker.internal,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,openai.com,packagecloud.io,packages.cloud.google.com,packages.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 { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); @@ -271,7 +280,7 @@ jobs: uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GH_AW_ENGINE_ID: "copilot" + GH_AW_ENGINE_ID: "codex" GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} with: script: | @@ -343,8 +352,8 @@ jobs: /tmp/gh-aw/aw-prompts/prompt-import-tree.json /tmp/gh-aw/github_rate_limits.jsonl /tmp/gh-aw/base - /tmp/gh-aw/.github/agents - /tmp/gh-aw/.github/skills + /tmp/gh-aw/.codex/agents + /tmp/gh-aw/.codex/skills if-no-files-found: ignore retention-days: 1 @@ -393,9 +402,9 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "自动处理 Issue" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/auto-code.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_VERSION: "0.137.0" GH_AW_INFO_AWF_VERSION: "v0.27.2" - GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_INFO_ENGINE_ID: "codex" - name: Set runtime paths id: set-runtime-paths run: | @@ -441,10 +450,13 @@ jobs: setupGlobals(core, github, context, exec, io, getOctokit); const { main } = require('${{ runner.temp }}/gh-aw/actions/checkout_pr_branch.cjs'); await main(); - - name: Install GitHub Copilot CLI - run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.60 - env: - GH_HOST: github.com + - name: Setup Node.js + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + with: + node-version: '24' + package-manager-cache: false + - name: Install Codex CLI + run: npm install --ignore-scripts -g @openai/codex@0.137.0 - name: Install AWF binary run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.27.2 - name: Parse integrity filter lists @@ -467,12 +479,12 @@ jobs: 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: ".github/agents" - GH_AW_SUB_AGENT_EXT: ".agent.md" + 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: ".github/skills" + GH_AW_SKILL_DIR: ".codex/skills" run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_inline_skills.sh" - name: Download container images run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6 ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2@sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4 ghcr.io/github/gh-aw-firewall/squid:0.27.2@sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591 ghcr.io/github/gh-aw-mcpg:v0.3.25@sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c @@ -684,6 +696,7 @@ jobs: - name: Start MCP Gateway id: start-mcp-gateway env: + CODEX_HOME: /tmp/gh-aw/mcp-config GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-start.outputs.api_key }} GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-start.outputs.port }} @@ -704,7 +717,7 @@ jobs: export MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD="524288" export DEBUG="*" - export GH_AW_ENGINE="copilot" + export GH_AW_ENGINE="codex" MCP_GATEWAY_UID=$(id -u 2>/dev/null || echo '0') MCP_GATEWAY_GID=$(id -g 2>/dev/null || echo '0') case "${DOCKER_HOST:-}" in @@ -713,19 +726,47 @@ jobs: * ) DOCKER_SOCK_PATH=/var/run/docker.sock ;; esac DOCKER_SOCK_GID=$(stat -c '%g' "$DOCKER_SOCK_PATH" 2>/dev/null || echo '0') - export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --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_API_KEY -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_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.3.25' + export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --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_API_KEY -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_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -e CODEX_HOME -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.3.25' + + cat > "${RUNNER_TEMP}/gh-aw/mcp-config/config.toml" << GH_AW_MCP_CONFIG_d9dc58ce079498af_EOF + [history] + persistence = "none" + + [shell_environment_policy] + inherit = "core" + include_only = ["^CODEX_API_KEY$", "^GH_AW_ASSETS_ALLOWED_EXTS$", "^GH_AW_ASSETS_BRANCH$", "^GH_AW_ASSETS_MAX_SIZE_KB$", "^GH_AW_SAFE_OUTPUTS$", "^GITHUB_PERSONAL_ACCESS_TOKEN$", "^GITHUB_REPOSITORY$", "^GITHUB_SERVER_URL$", "^HOME$", "^OPENAI_API_KEY$", "^PATH$"] + + [mcp_servers.github] + user_agent = "issue" + startup_timeout_sec = 120 + tool_timeout_sec = 60 + container = "ghcr.io/github/github-mcp-server:v1.1.2" + env = { "GITHUB_HOST" = "$GITHUB_SERVER_URL", "GITHUB_PERSONAL_ACCESS_TOKEN" = "$GH_AW_GITHUB_TOKEN", "GITHUB_READ_ONLY" = "1", "GITHUB_TOOLSETS" = "context,repos,issues,pull_requests" } + env_vars = ["GITHUB_HOST", "GITHUB_PERSONAL_ACCESS_TOKEN", "GITHUB_READ_ONLY", "GITHUB_TOOLSETS"] + + [mcp_servers.safeoutputs] + type = "http" + url = "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT" + + [mcp_servers.safeoutputs.headers] + Authorization = "$GH_AW_SAFE_OUTPUTS_API_KEY" + + [mcp_servers.safeoutputs."guard-policies"] - mkdir -p /home/runner/.copilot + [mcp_servers.safeoutputs."guard-policies".write-sink] + accept = ["*"] + GH_AW_MCP_CONFIG_d9dc58ce079498af_EOF + + # 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_920bb1916fcb7fc4_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_ca772287f17ffc28_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "github": { - "type": "stdio", "container": "ghcr.io/github/github-mcp-server:v1.1.2", "env": { - "GITHUB_HOST": "\${GITHUB_SERVER_URL}", - "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}", + "GITHUB_HOST": "$GITHUB_SERVER_URL", + "GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_MCP_SERVER_TOKEN", "GITHUB_READ_ONLY": "1", "GITHUB_TOOLSETS": "context,repos,issues,pull_requests" }, @@ -743,7 +784,7 @@ jobs: "type": "http", "url": "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT", "headers": { - "Authorization": "\${GH_AW_SAFE_OUTPUTS_API_KEY}" + "Authorization": "$GH_AW_SAFE_OUTPUTS_API_KEY" }, "guard-policies": { "write-sink": { @@ -761,7 +802,34 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_920bb1916fcb7fc4_EOF + GH_AW_MCP_CONFIG_ca772287f17ffc28_EOF + + # Sync converter output to writable CODEX_HOME for Codex + mkdir -p /tmp/gh-aw/mcp-config + cat > "/tmp/gh-aw/mcp-config/config.toml" << GH_AW_CODEX_SHELL_POLICY_929fca99db4cd5ec_EOF + + model_provider = "openai-proxy" + + [model_providers.openai-proxy] + name = "OpenAI AWF proxy" + base_url = "http://172.30.0.30:10000" + env_key = "OPENAI_API_KEY" + supports_websockets = false + [shell_environment_policy] + inherit = "core" + include_only = ["^CODEX_API_KEY$", "^GH_AW_ASSETS_ALLOWED_EXTS$", "^GH_AW_ASSETS_BRANCH$", "^GH_AW_ASSETS_MAX_SIZE_KB$", "^GH_AW_SAFE_OUTPUTS$", "^GITHUB_PERSONAL_ACCESS_TOKEN$", "^GITHUB_REPOSITORY$", "^GITHUB_SERVER_URL$", "^HOME$", "^OPENAI_API_KEY$", "^PATH$"] + GH_AW_CODEX_SHELL_POLICY_929fca99db4cd5ec_EOF + awk ' + BEGIN { skip_openai_proxy = 0 } + /^[[:space:]]*model_provider[[:space:]]*=/ { next } + /^\[model_providers\.openai-proxy\][[:space:]]*$/ { skip_openai_proxy = 1; next } + /^\[/ { skip_openai_proxy = 0 } + !skip_openai_proxy { print } + ' "${RUNNER_TEMP}/gh-aw/mcp-config/config.toml" >> "/tmp/gh-aw/mcp-config/config.toml" + chmod 600 "/tmp/gh-aw/mcp-config/config.toml" + mkdir -p "${CODEX_HOME}" + if [ "/tmp/gh-aw/mcp-config/config.toml" != "${CODEX_HOME}/config.toml" ]; then cp "/tmp/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 @@ -783,23 +851,15 @@ jobs: id: pre_agent_audit continue-on-error: true run: bash "${RUNNER_TEMP}/gh-aw/actions/audit_pre_agent_workspace.sh" - - name: Execute GitHub Copilot CLI + - name: Execute Codex CLI id: agentic_execution - # Copilot CLI tool arguments (sorted): - timeout-minutes: 20 run: | set -o pipefail printf '%s' "$(date +%s%3N)" > /tmp/gh-aw/agent_cli_start_ms.txt - trap 'rm -f /home/runner/.copilot/settings.json' EXIT - mkdir -p /home/runner/.copilot - printf '%s' '{"builtInAgents":{"rubberDuck":false}}' > /home/runner/.copilot/settings.json - touch /tmp/gh-aw/agent-step-summary.md - GH_AW_NODE_BIN=$(command -v node 2>/dev/null || true) - export GH_AW_NODE_BIN - export COPILOT_API_KEY="$COPILOT_DUMMY_BYOK" + 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="${{ vars.GH_AW_DEFAULT_MAX_AI_CREDITS || '1000' }}" - printf '%s\n' "{\"\$schema\":\"https://github.com/github/gh-aw-firewall/releases/download/v0.27.2/awf-config.schema.json\",\"network\":{\"allowDomains\":[\"api.business.githubcopilot.com\",\"api.enterprise.githubcopilot.com\",\"api.github.com\",\"api.githubcopilot.com\",\"api.individual.githubcopilot.com\",\"api.snapcraft.io\",\"archive.ubuntu.com\",\"ark.cn-beijing.volces.com\",\"azure.archive.ubuntu.com\",\"crl.geotrust.com\",\"crl.globalsign.com\",\"crl.identrust.com\",\"crl.sectigo.com\",\"crl.thawte.com\",\"crl.usertrust.com\",\"crl.verisign.com\",\"crl3.digicert.com\",\"crl4.digicert.com\",\"crls.ssl.com\",\"github.com\",\"host.docker.internal\",\"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\",\"ppa.launchpad.net\",\"raw.githubusercontent.com\",\"registry.npmjs.org\",\"s.symcb.com\",\"s.symcd.com\",\"security.ubuntu.com\",\"telemetry.enterprise.githubcopilot.com\",\"ts-crl.ws.symantec.com\",\"ts-ocsp.ws.symantec.com\",\"www.googleapis.com\"]},\"apiProxy\":{\"enabled\":true,\"enableTokenSteering\":true,\"maxRuns\":500,\"maxAiCredits\":${GH_AW_MAX_AI_CREDITS},\"models\":{\"agent\":[\"sonnet-6x\",\"gpt-5.4\",\"gpt-5.3\",\"gemini-pro\",\"any\"],\"antigravity\":[\"copilot/antigravity*\",\"google/antigravity*\",\"gemini/antigravity*\"],\"any\":[\"copilot/*\",\"anthropic/*\",\"openai/*\",\"google/*\",\"gemini/*\"],\"claude\":[\"agent\"],\"codex\":[\"agent\"],\"coding\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\",\"gpt-5-codex\"],\"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*\"],\"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-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-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.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*\"],\"haiku\":[\"copilot/*haiku*\",\"anthropic/*haiku*\"],\"large\":[\"sonnet\",\"gpt-5-pro\",\"gpt-5\",\"gemini-pro\"],\"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\"],\"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-4-5-*\",\"anthropic/*sonnet-4-5-*\",\"copilot/*sonnet-4-6*\",\"anthropic/*sonnet-4-6*\"],\"summarization\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash-lite\",\"mini\"],\"vision\":[\"copilot/gemini-*image*\",\"gemini/gemini-*image*\",\"copilot/gemini-*flash*\",\"gemini/gemini-*flash*\"]}},\"container\":{\"imageTag\":\"0.27.2,squid=sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591,agent=sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6,api-proxy=sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4,cli-proxy=sha256:02f3ec08f32dc26c5427920c6a2e2f3036238fce44802f2f11ef49ed8621b5d0\"}}" > "${RUNNER_TEMP}/gh-aw/awf-config.json" + printf '%s\n' "{\"\$schema\":\"https://github.com/github/gh-aw-firewall/releases/download/v0.27.2/awf-config.schema.json\",\"network\":{\"allowDomains\":[\"172.30.0.1\",\"api.openai.com\",\"api.snapcraft.io\",\"archive.ubuntu.com\",\"ark.cn-beijing.volces.com\",\"azure.archive.ubuntu.com\",\"chatgpt.com\",\"crl.geotrust.com\",\"crl.globalsign.com\",\"crl.identrust.com\",\"crl.sectigo.com\",\"crl.thawte.com\",\"crl.usertrust.com\",\"crl.verisign.com\",\"crl3.digicert.com\",\"crl4.digicert.com\",\"crls.ssl.com\",\"host.docker.internal\",\"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\",\"openai.com\",\"packagecloud.io\",\"packages.cloud.google.com\",\"packages.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\"]},\"apiProxy\":{\"enabled\":true,\"enableTokenSteering\":true,\"maxRuns\":500,\"maxAiCredits\":${GH_AW_MAX_AI_CREDITS},\"targets\":{\"openai\":{\"host\":\"ark.cn-beijing.volces.com\"}},\"models\":{\"agent\":[\"sonnet-6x\",\"gpt-5.4\",\"gpt-5.3\",\"gemini-pro\",\"any\"],\"antigravity\":[\"copilot/antigravity*\",\"google/antigravity*\",\"gemini/antigravity*\"],\"any\":[\"copilot/*\",\"anthropic/*\",\"openai/*\",\"google/*\",\"gemini/*\"],\"claude\":[\"agent\"],\"codex\":[\"agent\"],\"coding\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\",\"gpt-5-codex\"],\"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*\"],\"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-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-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.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*\"],\"haiku\":[\"copilot/*haiku*\",\"anthropic/*haiku*\"],\"large\":[\"sonnet\",\"gpt-5-pro\",\"gpt-5\",\"gemini-pro\"],\"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\"],\"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-4-5-*\",\"anthropic/*sonnet-4-5-*\",\"copilot/*sonnet-4-6*\",\"anthropic/*sonnet-4-6*\"],\"summarization\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash-lite\",\"mini\"],\"vision\":[\"copilot/gemini-*image*\",\"gemini/gemini-*image*\",\"copilot/gemini-*flash*\",\"gemini/gemini-*flash*\"]}},\"container\":{\"imageTag\":\"0.27.2,squid=sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591,agent=sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6,api-proxy=sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4,cli-proxy=sha256:02f3ec08f32dc26c5427920c6a2e2f3036238fce44802f2f11ef49ed8621b5d0\"}}" > "${RUNNER_TEMP}/gh-aw/awf-config.json" GH_AW_MODEL_MULTIPLIERS_PATH="/tmp/gh-aw/model_multipliers.json" node "${RUNNER_TEMP}/gh-aw/actions/merge_awf_model_multipliers.cjs" 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" @@ -817,38 +877,29 @@ jobs: GH_AW_TOOL_CACHE_MOUNT="/home/runner/work/_tool:/home/runner/work/_tool:ro" fi # shellcheck disable=SC1003 - sudo -E 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_PATH_PREFIX_ARGS} --env-all --exclude-env COPILOT_PROVIDER_API_KEY --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull \ - -- /bin/bash -c 'set +o histexpand; export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && GH_AW_TOOL_CACHE="${RUNNER_TOOL_CACHE:-/opt/hostedtoolcache}"; export PATH="$(find "$GH_AW_TOOL_CACHE" /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 5 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/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/copilot_harness.cjs /usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-all-tools --allow-all-paths --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + sudo -E 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_PATH_PREFIX_ARGS} --env-all --exclude-env CODEX_API_KEY --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --exclude-env OPENAI_API_KEY --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull --openai-api-base-path /api/v3 \ + -- /bin/bash -c 'set +o histexpand; export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && GH_AW_TOOL_CACHE="${RUNNER_TOOL_CACHE:-/opt/hostedtoolcache}"; export PATH="$(find "$GH_AW_TOOL_CACHE" /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 5 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/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" -c fetch="disabled" --dangerously-bypass-approvals-and-sandbox --skip-git-repo-check --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log env: - AWF_REFLECT_ENABLED: 1 - COPILOT_AGENT_RUNNER_TYPE: STANDALONE - COPILOT_DUMMY_BYOK: dummy-byok-key-for-offline-mode - COPILOT_MODEL: doubao-seed-2-0-code-preview-260215 - COPILOT_PROVIDER_API_KEY: ${{ secrets.OPENAI_API_KEY }} - COPILOT_PROVIDER_BASE_URL: https://ark.cn-beijing.volces.com/api/v3 - COPILOT_PROVIDER_TYPE: openai + CODEX_API_KEY: ${{ secrets.CODEX_API_KEY || secrets.OPENAI_API_KEY }} + CODEX_HOME: /tmp/gh-aw/mcp-config + CODEX_MODEL: doubao-seed-2-0-code-preview-260215 GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }} - GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json + GH_AW_MCP_CONFIG: ${{ runner.temp }}/gh-aw/mcp-config/config.toml + GH_AW_MODEL_AGENT_CODEX: ${{ vars.GH_AW_MODEL_AGENT_CODEX || vars.GH_AW_DEFAULT_MODEL_CODEX || 'gpt-5.4' }} 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_TIMEOUT_MINUTES: 20 GH_AW_VERSION: v0.79.6 - GITHUB_API_URL: ${{ github.api_url }} GITHUB_AW: true - GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows - GITHUB_HEAD_REF: ${{ github.head_ref }} - GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - 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] + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + OPENAI_BASE_URL: https://ark.cn-beijing.volces.com/api/v3 RUNNER_TEMP: ${{ runner.temp }} - XDG_CONFIG_HOME: /home/runner + RUST_LOG: ${{ runner.debug == 1 && 'trace,hyper_util=info,mio=info,reqwest=info,os_info=info,codex_otel=warn,codex_core=debug,ocodex_exec=debug' || 'warn' }} - name: Detect agent errors if: always() id: detect-agent-errors @@ -867,10 +918,6 @@ jobs: SERVER_URL_STRIPPED="${SERVER_URL#https://}" git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" echo "Git configured with standard GitHub Actions identity" - - name: Copy Copilot session state files to logs - if: always() - continue-on-error: true - run: bash "${RUNNER_TEMP}/gh-aw/actions/copy_copilot_session_state.sh" - name: Stop MCP Gateway if: always() continue-on-error: true @@ -890,7 +937,8 @@ jobs: const { main } = require('${{ runner.temp }}/gh-aw/actions/redact_secrets.cjs'); await main(); env: - GH_AW_SECRET_NAMES: 'GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN,OPENAI_API_KEY' + GH_AW_SECRET_NAMES: 'CODEX_API_KEY,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN,OPENAI_API_KEY' + SECRET_CODEX_API_KEY: ${{ secrets.CODEX_API_KEY }} SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -911,7 +959,7 @@ jobs: 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: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,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,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" + GH_AW_ALLOWED_DOMAINS: "172.30.0.1,api.openai.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,chatgpt.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,host.docker.internal,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,openai.com,packagecloud.io,packages.cloud.google.com,packages.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 }} with: @@ -924,12 +972,12 @@ jobs: if: always() uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: - GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/ + GH_AW_AGENT_OUTPUT: /tmp/gh-aw/agent-stdio.log with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_copilot_log.cjs'); + const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_codex_log.cjs'); await main(); - name: Parse MCP Gateway logs for step summary if: always() @@ -990,7 +1038,7 @@ jobs: name: agent path: | /tmp/gh-aw/aw-prompts/prompt.txt - /tmp/gh-aw/sandbox/agent/logs/ + /tmp/gh-aw/mcp-config/logs/ /tmp/gh-aw/redacted-urls.log /tmp/gh-aw/mcp-logs/ /tmp/gh-aw/proxy-logs/ @@ -1045,9 +1093,9 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "自动处理 Issue" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/auto-code.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_VERSION: "0.137.0" GH_AW_INFO_AWF_VERSION: "v0.27.2" - GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_INFO_ENGINE_ID: "codex" - name: Download agent output artifact id: download-agent-output continue-on-error: true @@ -1159,7 +1207,8 @@ jobs: GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} GH_AW_WORKFLOW_ID: "auto-code" GH_AW_ACTION_FAILURE_ISSUE_EXPIRES_HOURS: "168" - GH_AW_ENGINE_ID: "copilot" + 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_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens || '' }} GH_AW_AI_CREDITS_RATE_LIMIT_ERROR: ${{ needs.agent.outputs.ai_credits_rate_limit_error || 'false' }} @@ -1170,7 +1219,7 @@ jobs: 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_ENGINE_API_HOSTS: "api.enterprise.githubcopilot.com,api.githubcopilot.com,api.business.githubcopilot.com,api.individual.githubcopilot.com" + GH_AW_ENGINE_API_HOSTS: "api.openai.com" 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 }} @@ -1209,9 +1258,9 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "自动处理 Issue" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/auto-code.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_VERSION: "0.137.0" GH_AW_INFO_AWF_VERSION: "v0.27.2" - GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_INFO_ENGINE_ID: "codex" - name: Check team membership for workflow id: check_membership uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -1243,9 +1292,8 @@ jobs: GH_AW_AMBIENT_CONTEXT: ${{ needs.agent.outputs.ambient_context }} GH_AW_CALLER_WORKFLOW_ID: "${{ github.repository }}/auto-code" GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens }} - GH_AW_ENGINE_ID: "copilot" + GH_AW_ENGINE_ID: "codex" GH_AW_ENGINE_MODEL: ${{ needs.agent.outputs.model }} - GH_AW_ENGINE_VERSION: "1.0.60" GH_AW_WORKFLOW_ID: "auto-code" GH_AW_WORKFLOW_NAME: "自动处理 Issue" GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/auto-code.md" @@ -1272,9 +1320,9 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "自动处理 Issue" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/auto-code.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_VERSION: "0.137.0" GH_AW_INFO_AWF_VERSION: "v0.27.2" - GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_INFO_ENGINE_ID: "codex" - name: Download agent output artifact id: download-agent-output continue-on-error: true @@ -1351,7 +1399,7 @@ jobs: 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_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,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,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" + GH_AW_ALLOWED_DOMAINS: "172.30.0.1,api.openai.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,chatgpt.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,host.docker.internal,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,openai.com,packagecloud.io,packages.cloud.google.com,packages.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},\"create_pull_request\":{\"base_branch\":\"develop\",\"max\":1,\"max_patch_files\":100,\"max_patch_size\":1024,\"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\",\"CHANGELOG.md\",\"SECURITY.md\",\"CODE_OF_CONDUCT.md\",\"AGENTS.md\",\"CLAUDE.md\",\"GEMINI.md\"],\"protected_files_policy\":\"request_review\"},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"report_incomplete\":{}}" diff --git a/.github/workflows/auto-code.md b/.github/workflows/auto-code.md index a81501de..65c68c1f 100644 --- a/.github/workflows/auto-code.md +++ b/.github/workflows/auto-code.md @@ -4,12 +4,11 @@ on: types: [labeled] engine: - id: copilot + id: codex env: - COPILOT_PROVIDER_BASE_URL: "https://ark.cn-beijing.volces.com/api/v3" - COPILOT_MODEL: doubao-seed-2-0-code-preview-260215 - COPILOT_PROVIDER_API_KEY: ${{ secrets.OPENAI_API_KEY }} - COPILOT_PROVIDER_TYPE: openai + OPENAI_BASE_URL: "https://ark.cn-beijing.volces.com/api/v3" + CODEX_MODEL: doubao-seed-2-0-code-preview-260215 + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} network: allowed: diff --git a/.github/workflows/issue-triage.lock.yml b/.github/workflows/issue-triage.lock.yml index aa4e7c0d..8f4dd354 100644 --- a/.github/workflows/issue-triage.lock.yml +++ b/.github/workflows/issue-triage.lock.yml @@ -1,5 +1,5 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"4c520dacbaee7bcbc706d7c10c4a7a33d6bf61ada259b815aa34aa9b3078f9c3","body_hash":"bf4f8784cdac578e246f253a70aa7f7acce80a6fcf1c9116a0f5867b9ece3260","compiler_version":"v0.79.6","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}} -# gh-aw-manifest: {"version":1,"secrets":["GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"5c2fe865bb4dc46e1450f6ee0d0541d759aea73a","version":"v0.79.6"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2","digest":"sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2","digest":"sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2@sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2","digest":"sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2@sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.25","digest":"sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.25@sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa"},{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"c3021f9226662718b4a7c4bdbd044adfb968111217051e1c5cdfe9e999375b84","body_hash":"bf4f8784cdac578e246f253a70aa7f7acce80a6fcf1c9116a0f5867b9ece3260","compiler_version":"v0.79.6","strict":true,"agent_id":"codex","engine_versions":{"codex":"0.137.0"}} +# gh-aw-manifest: {"version":1,"secrets":["CODEX_API_KEY","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"5c2fe865bb4dc46e1450f6ee0d0541d759aea73a","version":"v0.79.6"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2","digest":"sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2","digest":"sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2@sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2","digest":"sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2@sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.25","digest":"sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.25@sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa"},{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]} # ___ _ _ # / _ \ | | (_) # | |_| | __ _ ___ _ __ | |_ _ ___ @@ -24,6 +24,7 @@ # # # Secrets used: +# - CODEX_API_KEY # - GH_AW_GITHUB_MCP_SERVER_TOKEN # - GH_AW_GITHUB_TOKEN # - GITHUB_TOKEN @@ -33,6 +34,7 @@ # - actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 # - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 # - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 +# - actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 # - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 # - github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 # @@ -77,6 +79,7 @@ jobs: engine_id: ${{ steps.generate_aw_info.outputs.engine_id }} lockdown_check_failed: ${{ steps.generate_aw_info.outputs.lockdown_check_failed == 'true' }} model: ${{ steps.generate_aw_info.outputs.model }} + secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} 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 }} @@ -96,17 +99,17 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "Issue 自动分类与回复" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_VERSION: "0.137.0" GH_AW_INFO_AWF_VERSION: "v0.27.2" - GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_INFO_ENGINE_ID: "codex" - name: Generate agentic run info id: generate_aw_info env: - GH_AW_INFO_ENGINE_ID: "copilot" - GH_AW_INFO_ENGINE_NAME: "GitHub Copilot CLI" - GH_AW_INFO_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || vars.GH_AW_DEFAULT_MODEL_COPILOT || 'claude-sonnet-4.6' }} - GH_AW_INFO_VERSION: "1.0.60" - GH_AW_INFO_AGENT_VERSION: "1.0.60" + GH_AW_INFO_ENGINE_ID: "codex" + GH_AW_INFO_ENGINE_NAME: "Codex" + GH_AW_INFO_MODEL: ${{ vars.GH_AW_MODEL_AGENT_CODEX || vars.GH_AW_DEFAULT_MODEL_CODEX || 'gpt-5.4' }} + GH_AW_INFO_VERSION: "0.137.0" + GH_AW_INFO_AGENT_VERSION: "0.137.0" GH_AW_INFO_CLI_VERSION: "v0.79.6" GH_AW_INFO_WORKFLOW_NAME: "Issue 自动分类与回复" GH_AW_INFO_EXPERIMENTAL: "false" @@ -143,6 +146,12 @@ jobs: setupGlobals(core, github, context, exec, io, getOctokit); const { main } = require('${{ runner.temp }}/gh-aw/actions/check_daily_aic_workflow_guardrail.cjs'); await main(); + - name: Validate CODEX_API_KEY or OPENAI_API_KEY secret + id: validate-secret + run: bash "${RUNNER_TEMP}/gh-aw/actions/validate_multi_secret.sh" CODEX_API_KEY OPENAI_API_KEY Codex https://github.github.com/gh-aw/reference/engines/#openai-codex + env: + CODEX_API_KEY: ${{ secrets.CODEX_API_KEY }} + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - name: Checkout .github and .agents folders uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: @@ -191,7 +200,7 @@ jobs: id: sanitized uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: - GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,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,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" + GH_AW_ALLOWED_DOMAINS: "172.30.0.1,api.openai.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,chatgpt.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,host.docker.internal,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,openai.com,packagecloud.io,packages.cloud.google.com,packages.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 { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); @@ -267,7 +276,7 @@ jobs: uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GH_AW_ENGINE_ID: "copilot" + GH_AW_ENGINE_ID: "codex" GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} with: script: | @@ -337,8 +346,8 @@ jobs: /tmp/gh-aw/aw-prompts/prompt-import-tree.json /tmp/gh-aw/github_rate_limits.jsonl /tmp/gh-aw/base - /tmp/gh-aw/.github/agents - /tmp/gh-aw/.github/skills + /tmp/gh-aw/.codex/agents + /tmp/gh-aw/.codex/skills if-no-files-found: ignore retention-days: 1 @@ -387,9 +396,9 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "Issue 自动分类与回复" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_VERSION: "0.137.0" GH_AW_INFO_AWF_VERSION: "v0.27.2" - GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_INFO_ENGINE_ID: "codex" - name: Set runtime paths id: set-runtime-paths run: | @@ -435,10 +444,13 @@ jobs: setupGlobals(core, github, context, exec, io, getOctokit); const { main } = require('${{ runner.temp }}/gh-aw/actions/checkout_pr_branch.cjs'); await main(); - - name: Install GitHub Copilot CLI - run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.60 - env: - GH_HOST: github.com + - name: Setup Node.js + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + with: + node-version: '24' + package-manager-cache: false + - name: Install Codex CLI + run: npm install --ignore-scripts -g @openai/codex@0.137.0 - name: Install AWF binary run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.27.2 - name: Parse integrity filter lists @@ -461,12 +473,12 @@ jobs: 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: ".github/agents" - GH_AW_SUB_AGENT_EXT: ".agent.md" + 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: ".github/skills" + GH_AW_SKILL_DIR: ".codex/skills" run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_inline_skills.sh" - name: Download container images run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6 ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2@sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4 ghcr.io/github/gh-aw-firewall/squid:0.27.2@sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591 ghcr.io/github/gh-aw-mcpg:v0.3.25@sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c @@ -656,6 +668,7 @@ jobs: - name: Start MCP Gateway id: start-mcp-gateway env: + CODEX_HOME: /tmp/gh-aw/mcp-config GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-start.outputs.api_key }} GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-start.outputs.port }} @@ -676,7 +689,7 @@ jobs: export MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD="524288" export DEBUG="*" - export GH_AW_ENGINE="copilot" + export GH_AW_ENGINE="codex" MCP_GATEWAY_UID=$(id -u 2>/dev/null || echo '0') MCP_GATEWAY_GID=$(id -g 2>/dev/null || echo '0') case "${DOCKER_HOST:-}" in @@ -685,19 +698,47 @@ jobs: * ) DOCKER_SOCK_PATH=/var/run/docker.sock ;; esac DOCKER_SOCK_GID=$(stat -c '%g' "$DOCKER_SOCK_PATH" 2>/dev/null || echo '0') - export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --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_API_KEY -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_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.3.25' + export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --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_API_KEY -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_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -e CODEX_HOME -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.3.25' + + cat > "${RUNNER_TEMP}/gh-aw/mcp-config/config.toml" << GH_AW_MCP_CONFIG_d9dc58ce079498af_EOF + [history] + persistence = "none" + + [shell_environment_policy] + inherit = "core" + include_only = ["^CODEX_API_KEY$", "^GH_AW_ASSETS_ALLOWED_EXTS$", "^GH_AW_ASSETS_BRANCH$", "^GH_AW_ASSETS_MAX_SIZE_KB$", "^GH_AW_SAFE_OUTPUTS$", "^GITHUB_PERSONAL_ACCESS_TOKEN$", "^GITHUB_REPOSITORY$", "^GITHUB_SERVER_URL$", "^HOME$", "^OPENAI_API_KEY$", "^PATH$"] + + [mcp_servers.github] + user_agent = "issue" + startup_timeout_sec = 120 + tool_timeout_sec = 60 + container = "ghcr.io/github/github-mcp-server:v1.1.2" + env = { "GITHUB_HOST" = "$GITHUB_SERVER_URL", "GITHUB_PERSONAL_ACCESS_TOKEN" = "$GH_AW_GITHUB_TOKEN", "GITHUB_READ_ONLY" = "1", "GITHUB_TOOLSETS" = "context,repos,issues,pull_requests" } + env_vars = ["GITHUB_HOST", "GITHUB_PERSONAL_ACCESS_TOKEN", "GITHUB_READ_ONLY", "GITHUB_TOOLSETS"] + + [mcp_servers.safeoutputs] + type = "http" + url = "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT" + + [mcp_servers.safeoutputs.headers] + Authorization = "$GH_AW_SAFE_OUTPUTS_API_KEY" + + [mcp_servers.safeoutputs."guard-policies"] - mkdir -p /home/runner/.copilot + [mcp_servers.safeoutputs."guard-policies".write-sink] + accept = ["*"] + GH_AW_MCP_CONFIG_d9dc58ce079498af_EOF + + # 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_920bb1916fcb7fc4_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_ca772287f17ffc28_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "github": { - "type": "stdio", "container": "ghcr.io/github/github-mcp-server:v1.1.2", "env": { - "GITHUB_HOST": "\${GITHUB_SERVER_URL}", - "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}", + "GITHUB_HOST": "$GITHUB_SERVER_URL", + "GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_MCP_SERVER_TOKEN", "GITHUB_READ_ONLY": "1", "GITHUB_TOOLSETS": "context,repos,issues,pull_requests" }, @@ -715,7 +756,7 @@ jobs: "type": "http", "url": "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT", "headers": { - "Authorization": "\${GH_AW_SAFE_OUTPUTS_API_KEY}" + "Authorization": "$GH_AW_SAFE_OUTPUTS_API_KEY" }, "guard-policies": { "write-sink": { @@ -733,7 +774,34 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_920bb1916fcb7fc4_EOF + GH_AW_MCP_CONFIG_ca772287f17ffc28_EOF + + # Sync converter output to writable CODEX_HOME for Codex + mkdir -p /tmp/gh-aw/mcp-config + cat > "/tmp/gh-aw/mcp-config/config.toml" << GH_AW_CODEX_SHELL_POLICY_929fca99db4cd5ec_EOF + + model_provider = "openai-proxy" + + [model_providers.openai-proxy] + name = "OpenAI AWF proxy" + base_url = "http://172.30.0.30:10000" + env_key = "OPENAI_API_KEY" + supports_websockets = false + [shell_environment_policy] + inherit = "core" + include_only = ["^CODEX_API_KEY$", "^GH_AW_ASSETS_ALLOWED_EXTS$", "^GH_AW_ASSETS_BRANCH$", "^GH_AW_ASSETS_MAX_SIZE_KB$", "^GH_AW_SAFE_OUTPUTS$", "^GITHUB_PERSONAL_ACCESS_TOKEN$", "^GITHUB_REPOSITORY$", "^GITHUB_SERVER_URL$", "^HOME$", "^OPENAI_API_KEY$", "^PATH$"] + GH_AW_CODEX_SHELL_POLICY_929fca99db4cd5ec_EOF + awk ' + BEGIN { skip_openai_proxy = 0 } + /^[[:space:]]*model_provider[[:space:]]*=/ { next } + /^\[model_providers\.openai-proxy\][[:space:]]*$/ { skip_openai_proxy = 1; next } + /^\[/ { skip_openai_proxy = 0 } + !skip_openai_proxy { print } + ' "${RUNNER_TEMP}/gh-aw/mcp-config/config.toml" >> "/tmp/gh-aw/mcp-config/config.toml" + chmod 600 "/tmp/gh-aw/mcp-config/config.toml" + mkdir -p "${CODEX_HOME}" + if [ "/tmp/gh-aw/mcp-config/config.toml" != "${CODEX_HOME}/config.toml" ]; then cp "/tmp/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 @@ -755,23 +823,15 @@ jobs: id: pre_agent_audit continue-on-error: true run: bash "${RUNNER_TEMP}/gh-aw/actions/audit_pre_agent_workspace.sh" - - name: Execute GitHub Copilot CLI + - name: Execute Codex CLI id: agentic_execution - # Copilot CLI tool arguments (sorted): - timeout-minutes: 20 run: | set -o pipefail printf '%s' "$(date +%s%3N)" > /tmp/gh-aw/agent_cli_start_ms.txt - trap 'rm -f /home/runner/.copilot/settings.json' EXIT - mkdir -p /home/runner/.copilot - printf '%s' '{"builtInAgents":{"rubberDuck":false}}' > /home/runner/.copilot/settings.json - touch /tmp/gh-aw/agent-step-summary.md - GH_AW_NODE_BIN=$(command -v node 2>/dev/null || true) - export GH_AW_NODE_BIN - export COPILOT_API_KEY="$COPILOT_DUMMY_BYOK" + 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="${{ vars.GH_AW_DEFAULT_MAX_AI_CREDITS || '1000' }}" - printf '%s\n' "{\"\$schema\":\"https://github.com/github/gh-aw-firewall/releases/download/v0.27.2/awf-config.schema.json\",\"network\":{\"allowDomains\":[\"api.business.githubcopilot.com\",\"api.enterprise.githubcopilot.com\",\"api.github.com\",\"api.githubcopilot.com\",\"api.individual.githubcopilot.com\",\"api.snapcraft.io\",\"archive.ubuntu.com\",\"ark.cn-beijing.volces.com\",\"azure.archive.ubuntu.com\",\"crl.geotrust.com\",\"crl.globalsign.com\",\"crl.identrust.com\",\"crl.sectigo.com\",\"crl.thawte.com\",\"crl.usertrust.com\",\"crl.verisign.com\",\"crl3.digicert.com\",\"crl4.digicert.com\",\"crls.ssl.com\",\"github.com\",\"host.docker.internal\",\"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\",\"ppa.launchpad.net\",\"raw.githubusercontent.com\",\"registry.npmjs.org\",\"s.symcb.com\",\"s.symcd.com\",\"security.ubuntu.com\",\"telemetry.enterprise.githubcopilot.com\",\"ts-crl.ws.symantec.com\",\"ts-ocsp.ws.symantec.com\",\"www.googleapis.com\"]},\"apiProxy\":{\"enabled\":true,\"enableTokenSteering\":true,\"maxRuns\":500,\"maxAiCredits\":${GH_AW_MAX_AI_CREDITS},\"models\":{\"agent\":[\"sonnet-6x\",\"gpt-5.4\",\"gpt-5.3\",\"gemini-pro\",\"any\"],\"antigravity\":[\"copilot/antigravity*\",\"google/antigravity*\",\"gemini/antigravity*\"],\"any\":[\"copilot/*\",\"anthropic/*\",\"openai/*\",\"google/*\",\"gemini/*\"],\"claude\":[\"agent\"],\"codex\":[\"agent\"],\"coding\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\",\"gpt-5-codex\"],\"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*\"],\"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-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-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.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*\"],\"haiku\":[\"copilot/*haiku*\",\"anthropic/*haiku*\"],\"large\":[\"sonnet\",\"gpt-5-pro\",\"gpt-5\",\"gemini-pro\"],\"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\"],\"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-4-5-*\",\"anthropic/*sonnet-4-5-*\",\"copilot/*sonnet-4-6*\",\"anthropic/*sonnet-4-6*\"],\"summarization\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash-lite\",\"mini\"],\"vision\":[\"copilot/gemini-*image*\",\"gemini/gemini-*image*\",\"copilot/gemini-*flash*\",\"gemini/gemini-*flash*\"]}},\"container\":{\"imageTag\":\"0.27.2,squid=sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591,agent=sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6,api-proxy=sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4,cli-proxy=sha256:02f3ec08f32dc26c5427920c6a2e2f3036238fce44802f2f11ef49ed8621b5d0\"}}" > "${RUNNER_TEMP}/gh-aw/awf-config.json" + printf '%s\n' "{\"\$schema\":\"https://github.com/github/gh-aw-firewall/releases/download/v0.27.2/awf-config.schema.json\",\"network\":{\"allowDomains\":[\"172.30.0.1\",\"api.openai.com\",\"api.snapcraft.io\",\"archive.ubuntu.com\",\"ark.cn-beijing.volces.com\",\"azure.archive.ubuntu.com\",\"chatgpt.com\",\"crl.geotrust.com\",\"crl.globalsign.com\",\"crl.identrust.com\",\"crl.sectigo.com\",\"crl.thawte.com\",\"crl.usertrust.com\",\"crl.verisign.com\",\"crl3.digicert.com\",\"crl4.digicert.com\",\"crls.ssl.com\",\"host.docker.internal\",\"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\",\"openai.com\",\"packagecloud.io\",\"packages.cloud.google.com\",\"packages.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\"]},\"apiProxy\":{\"enabled\":true,\"enableTokenSteering\":true,\"maxRuns\":500,\"maxAiCredits\":${GH_AW_MAX_AI_CREDITS},\"targets\":{\"openai\":{\"host\":\"ark.cn-beijing.volces.com\"}},\"models\":{\"agent\":[\"sonnet-6x\",\"gpt-5.4\",\"gpt-5.3\",\"gemini-pro\",\"any\"],\"antigravity\":[\"copilot/antigravity*\",\"google/antigravity*\",\"gemini/antigravity*\"],\"any\":[\"copilot/*\",\"anthropic/*\",\"openai/*\",\"google/*\",\"gemini/*\"],\"claude\":[\"agent\"],\"codex\":[\"agent\"],\"coding\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\",\"gpt-5-codex\"],\"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*\"],\"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-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-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.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*\"],\"haiku\":[\"copilot/*haiku*\",\"anthropic/*haiku*\"],\"large\":[\"sonnet\",\"gpt-5-pro\",\"gpt-5\",\"gemini-pro\"],\"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\"],\"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-4-5-*\",\"anthropic/*sonnet-4-5-*\",\"copilot/*sonnet-4-6*\",\"anthropic/*sonnet-4-6*\"],\"summarization\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash-lite\",\"mini\"],\"vision\":[\"copilot/gemini-*image*\",\"gemini/gemini-*image*\",\"copilot/gemini-*flash*\",\"gemini/gemini-*flash*\"]}},\"container\":{\"imageTag\":\"0.27.2,squid=sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591,agent=sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6,api-proxy=sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4,cli-proxy=sha256:02f3ec08f32dc26c5427920c6a2e2f3036238fce44802f2f11ef49ed8621b5d0\"}}" > "${RUNNER_TEMP}/gh-aw/awf-config.json" GH_AW_MODEL_MULTIPLIERS_PATH="/tmp/gh-aw/model_multipliers.json" node "${RUNNER_TEMP}/gh-aw/actions/merge_awf_model_multipliers.cjs" 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" @@ -789,38 +849,29 @@ jobs: GH_AW_TOOL_CACHE_MOUNT="/home/runner/work/_tool:/home/runner/work/_tool:ro" fi # shellcheck disable=SC1003 - sudo -E 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_PATH_PREFIX_ARGS} --env-all --exclude-env COPILOT_PROVIDER_API_KEY --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull \ - -- /bin/bash -c 'set +o histexpand; export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && GH_AW_TOOL_CACHE="${RUNNER_TOOL_CACHE:-/opt/hostedtoolcache}"; export PATH="$(find "$GH_AW_TOOL_CACHE" /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 5 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/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/copilot_harness.cjs /usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-all-tools --allow-all-paths --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + sudo -E 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_PATH_PREFIX_ARGS} --env-all --exclude-env CODEX_API_KEY --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --exclude-env OPENAI_API_KEY --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull --openai-api-base-path /api/v3 \ + -- /bin/bash -c 'set +o histexpand; export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && GH_AW_TOOL_CACHE="${RUNNER_TOOL_CACHE:-/opt/hostedtoolcache}"; export PATH="$(find "$GH_AW_TOOL_CACHE" /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 5 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/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" -c fetch="disabled" --dangerously-bypass-approvals-and-sandbox --skip-git-repo-check --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log env: - AWF_REFLECT_ENABLED: 1 - COPILOT_AGENT_RUNNER_TYPE: STANDALONE - COPILOT_DUMMY_BYOK: dummy-byok-key-for-offline-mode - COPILOT_MODEL: doubao-seed-2-0-code-preview-260215 - COPILOT_PROVIDER_API_KEY: ${{ secrets.OPENAI_API_KEY }} - COPILOT_PROVIDER_BASE_URL: https://ark.cn-beijing.volces.com/api/v3 - COPILOT_PROVIDER_TYPE: openai + CODEX_API_KEY: ${{ secrets.CODEX_API_KEY || secrets.OPENAI_API_KEY }} + CODEX_HOME: /tmp/gh-aw/mcp-config + CODEX_MODEL: doubao-seed-2-0-code-preview-260215 GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }} - GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json + GH_AW_MCP_CONFIG: ${{ runner.temp }}/gh-aw/mcp-config/config.toml + GH_AW_MODEL_AGENT_CODEX: ${{ vars.GH_AW_MODEL_AGENT_CODEX || vars.GH_AW_DEFAULT_MODEL_CODEX || 'gpt-5.4' }} 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_TIMEOUT_MINUTES: 20 GH_AW_VERSION: v0.79.6 - GITHUB_API_URL: ${{ github.api_url }} GITHUB_AW: true - GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows - GITHUB_HEAD_REF: ${{ github.head_ref }} - GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - 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] + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + OPENAI_BASE_URL: https://ark.cn-beijing.volces.com/api/v3 RUNNER_TEMP: ${{ runner.temp }} - XDG_CONFIG_HOME: /home/runner + RUST_LOG: ${{ runner.debug == 1 && 'trace,hyper_util=info,mio=info,reqwest=info,os_info=info,codex_otel=warn,codex_core=debug,ocodex_exec=debug' || 'warn' }} - name: Detect agent errors if: always() id: detect-agent-errors @@ -839,10 +890,6 @@ jobs: SERVER_URL_STRIPPED="${SERVER_URL#https://}" git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" echo "Git configured with standard GitHub Actions identity" - - name: Copy Copilot session state files to logs - if: always() - continue-on-error: true - run: bash "${RUNNER_TEMP}/gh-aw/actions/copy_copilot_session_state.sh" - name: Stop MCP Gateway if: always() continue-on-error: true @@ -862,7 +909,8 @@ jobs: const { main } = require('${{ runner.temp }}/gh-aw/actions/redact_secrets.cjs'); await main(); env: - GH_AW_SECRET_NAMES: 'GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN,OPENAI_API_KEY' + GH_AW_SECRET_NAMES: 'CODEX_API_KEY,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN,OPENAI_API_KEY' + SECRET_CODEX_API_KEY: ${{ secrets.CODEX_API_KEY }} SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -883,7 +931,7 @@ jobs: 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: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,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,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" + GH_AW_ALLOWED_DOMAINS: "172.30.0.1,api.openai.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,chatgpt.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,host.docker.internal,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,openai.com,packagecloud.io,packages.cloud.google.com,packages.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 }} with: @@ -896,12 +944,12 @@ jobs: if: always() uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: - GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/ + GH_AW_AGENT_OUTPUT: /tmp/gh-aw/agent-stdio.log with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_copilot_log.cjs'); + const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_codex_log.cjs'); await main(); - name: Parse MCP Gateway logs for step summary if: always() @@ -962,7 +1010,7 @@ jobs: name: agent path: | /tmp/gh-aw/aw-prompts/prompt.txt - /tmp/gh-aw/sandbox/agent/logs/ + /tmp/gh-aw/mcp-config/logs/ /tmp/gh-aw/redacted-urls.log /tmp/gh-aw/mcp-logs/ /tmp/gh-aw/proxy-logs/ @@ -1015,9 +1063,9 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "Issue 自动分类与回复" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_VERSION: "0.137.0" GH_AW_INFO_AWF_VERSION: "v0.27.2" - GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_INFO_ENGINE_ID: "codex" - name: Download agent output artifact id: download-agent-output continue-on-error: true @@ -1129,7 +1177,8 @@ jobs: GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} GH_AW_WORKFLOW_ID: "issue-triage" GH_AW_ACTION_FAILURE_ISSUE_EXPIRES_HOURS: "168" - GH_AW_ENGINE_ID: "copilot" + 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_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens || '' }} GH_AW_AI_CREDITS_RATE_LIMIT_ERROR: ${{ needs.agent.outputs.ai_credits_rate_limit_error || 'false' }} @@ -1140,7 +1189,7 @@ jobs: 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_ENGINE_API_HOSTS: "api.enterprise.githubcopilot.com,api.githubcopilot.com,api.business.githubcopilot.com,api.individual.githubcopilot.com" + GH_AW_ENGINE_API_HOSTS: "api.openai.com" GH_AW_LOCKDOWN_CHECK_FAILED: ${{ needs.activation.outputs.lockdown_check_failed }} GH_AW_STALE_LOCK_FILE_FAILED: ${{ needs.activation.outputs.stale_lock_file_failed }} GH_AW_DAILY_EFFECTIVE_WORKFLOW_EXCEEDED: ${{ needs.activation.outputs.daily_effective_workflow_exceeded }} @@ -1177,9 +1226,9 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "Issue 自动分类与回复" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_VERSION: "0.137.0" GH_AW_INFO_AWF_VERSION: "v0.27.2" - GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_INFO_ENGINE_ID: "codex" - name: Check team membership for workflow id: check_membership uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -1211,9 +1260,8 @@ jobs: GH_AW_AMBIENT_CONTEXT: ${{ needs.agent.outputs.ambient_context }} GH_AW_CALLER_WORKFLOW_ID: "${{ github.repository }}/issue-triage" GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens }} - GH_AW_ENGINE_ID: "copilot" + GH_AW_ENGINE_ID: "codex" GH_AW_ENGINE_MODEL: ${{ needs.agent.outputs.model }} - GH_AW_ENGINE_VERSION: "1.0.60" GH_AW_WORKFLOW_ID: "issue-triage" GH_AW_WORKFLOW_NAME: "Issue 自动分类与回复" GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-triage.md" @@ -1238,9 +1286,9 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "Issue 自动分类与回复" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_VERSION: "0.137.0" GH_AW_INFO_AWF_VERSION: "v0.27.2" - GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_INFO_ENGINE_ID: "codex" - name: Download agent output artifact id: download-agent-output continue-on-error: true @@ -1271,7 +1319,7 @@ jobs: 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_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,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,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" + GH_AW_ALLOWED_DOMAINS: "172.30.0.1,api.openai.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,chatgpt.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,host.docker.internal,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,openai.com,packagecloud.io,packages.cloud.google.com,packages.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},\"add_labels\":{\"allowed\":[\"bug\",\"feature\",\"enhancement\",\"documentation\",\"question\",\"duplicate\",\"invalid\"]},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"report_incomplete\":{}}" diff --git a/.github/workflows/issue-triage.md b/.github/workflows/issue-triage.md index f0e5b220..de82018e 100644 --- a/.github/workflows/issue-triage.md +++ b/.github/workflows/issue-triage.md @@ -4,12 +4,11 @@ on: types: [opened, reopened] engine: - id: copilot + id: codex env: - COPILOT_PROVIDER_BASE_URL: "https://ark.cn-beijing.volces.com/api/v3" - COPILOT_MODEL: doubao-seed-2-0-code-preview-260215 - COPILOT_PROVIDER_API_KEY: ${{ secrets.OPENAI_API_KEY }} - COPILOT_PROVIDER_TYPE: openai + OPENAI_BASE_URL: "https://ark.cn-beijing.volces.com/api/v3" + CODEX_MODEL: doubao-seed-2-0-code-preview-260215 + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} network: allowed: From 1a7a3735c79ba137d4b639bcf69401162ce2311e Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Tue, 23 Jun 2026 09:50:43 +0800 Subject: [PATCH 34/59] feat: add agentic workflows for issue triage and auto fix --- .github/workflows/auto-code.lock.yml | 8 ++++---- .github/workflows/auto-code.md | 3 ++- .github/workflows/issue-triage.lock.yml | 8 ++++---- .github/workflows/issue-triage.md | 3 ++- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/.github/workflows/auto-code.lock.yml b/.github/workflows/auto-code.lock.yml index 2f5a1c52..cc8f1989 100644 --- a/.github/workflows/auto-code.lock.yml +++ b/.github/workflows/auto-code.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"07e5ed7d15413c222090f5a372855d48af5672ce5695f4d9d2726a8d9e46f08b","body_hash":"9959a757362d73cb28768bc2f9a90afc30a49f61e3226f922c791d0cbf387678","compiler_version":"v0.79.6","strict":true,"agent_id":"codex","engine_versions":{"codex":"0.137.0"}} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"379ddfe130a1c0cb713f795f724a4d2226e2f6c40c8ccb6db5b54ff6f035958d","body_hash":"9959a757362d73cb28768bc2f9a90afc30a49f61e3226f922c791d0cbf387678","compiler_version":"v0.79.6","strict":true,"agent_id":"codex","agent_model":"doubao-seed-2-0-code-preview-260215","engine_versions":{"codex":"0.137.0"}} # gh-aw-manifest: {"version":1,"secrets":["CODEX_API_KEY","GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"5c2fe865bb4dc46e1450f6ee0d0541d759aea73a","version":"v0.79.6"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2","digest":"sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2","digest":"sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2@sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2","digest":"sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2@sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.25","digest":"sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.25@sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa"},{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]} # ___ _ _ # / _ \ | | (_) @@ -107,7 +107,7 @@ jobs: env: GH_AW_INFO_ENGINE_ID: "codex" GH_AW_INFO_ENGINE_NAME: "Codex" - GH_AW_INFO_MODEL: ${{ vars.GH_AW_MODEL_AGENT_CODEX || vars.GH_AW_DEFAULT_MODEL_CODEX || 'gpt-5.4' }} + GH_AW_INFO_MODEL: "doubao-seed-2-0-code-preview-260215" GH_AW_INFO_VERSION: "0.137.0" GH_AW_INFO_AGENT_VERSION: "0.137.0" GH_AW_INFO_CLI_VERSION: "v0.79.6" @@ -885,7 +885,7 @@ jobs: CODEX_MODEL: doubao-seed-2-0-code-preview-260215 GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }} GH_AW_MCP_CONFIG: ${{ runner.temp }}/gh-aw/mcp-config/config.toml - GH_AW_MODEL_AGENT_CODEX: ${{ vars.GH_AW_MODEL_AGENT_CODEX || vars.GH_AW_DEFAULT_MODEL_CODEX || 'gpt-5.4' }} + GH_AW_MODEL_AGENT_CODEX: doubao-seed-2-0-code-preview-260215 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 }} @@ -1293,7 +1293,7 @@ jobs: GH_AW_CALLER_WORKFLOW_ID: "${{ github.repository }}/auto-code" GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens }} GH_AW_ENGINE_ID: "codex" - GH_AW_ENGINE_MODEL: ${{ needs.agent.outputs.model }} + GH_AW_ENGINE_MODEL: "doubao-seed-2-0-code-preview-260215" GH_AW_WORKFLOW_ID: "auto-code" GH_AW_WORKFLOW_NAME: "自动处理 Issue" GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/auto-code.md" diff --git a/.github/workflows/auto-code.md b/.github/workflows/auto-code.md index 65c68c1f..384b9711 100644 --- a/.github/workflows/auto-code.md +++ b/.github/workflows/auto-code.md @@ -7,8 +7,9 @@ engine: id: codex env: OPENAI_BASE_URL: "https://ark.cn-beijing.volces.com/api/v3" - CODEX_MODEL: doubao-seed-2-0-code-preview-260215 OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + CODEX_MODEL: doubao-seed-2-0-code-preview-260215 + model: doubao-seed-2-0-code-preview-260215 network: allowed: diff --git a/.github/workflows/issue-triage.lock.yml b/.github/workflows/issue-triage.lock.yml index 8f4dd354..de2e491f 100644 --- a/.github/workflows/issue-triage.lock.yml +++ b/.github/workflows/issue-triage.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"c3021f9226662718b4a7c4bdbd044adfb968111217051e1c5cdfe9e999375b84","body_hash":"bf4f8784cdac578e246f253a70aa7f7acce80a6fcf1c9116a0f5867b9ece3260","compiler_version":"v0.79.6","strict":true,"agent_id":"codex","engine_versions":{"codex":"0.137.0"}} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"5c7eddfd02afac9f7dd0d5ca4c24ffc1f6911842dc72dbd5bf0540d30b43955a","body_hash":"bf4f8784cdac578e246f253a70aa7f7acce80a6fcf1c9116a0f5867b9ece3260","compiler_version":"v0.79.6","strict":true,"agent_id":"codex","agent_model":"doubao-seed-2-0-code-preview-260215","engine_versions":{"codex":"0.137.0"}} # gh-aw-manifest: {"version":1,"secrets":["CODEX_API_KEY","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"5c2fe865bb4dc46e1450f6ee0d0541d759aea73a","version":"v0.79.6"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2","digest":"sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2","digest":"sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2@sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2","digest":"sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2@sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.25","digest":"sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.25@sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa"},{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]} # ___ _ _ # / _ \ | | (_) @@ -107,7 +107,7 @@ jobs: env: GH_AW_INFO_ENGINE_ID: "codex" GH_AW_INFO_ENGINE_NAME: "Codex" - GH_AW_INFO_MODEL: ${{ vars.GH_AW_MODEL_AGENT_CODEX || vars.GH_AW_DEFAULT_MODEL_CODEX || 'gpt-5.4' }} + GH_AW_INFO_MODEL: "doubao-seed-2-0-code-preview-260215" GH_AW_INFO_VERSION: "0.137.0" GH_AW_INFO_AGENT_VERSION: "0.137.0" GH_AW_INFO_CLI_VERSION: "v0.79.6" @@ -857,7 +857,7 @@ jobs: CODEX_MODEL: doubao-seed-2-0-code-preview-260215 GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }} GH_AW_MCP_CONFIG: ${{ runner.temp }}/gh-aw/mcp-config/config.toml - GH_AW_MODEL_AGENT_CODEX: ${{ vars.GH_AW_MODEL_AGENT_CODEX || vars.GH_AW_DEFAULT_MODEL_CODEX || 'gpt-5.4' }} + GH_AW_MODEL_AGENT_CODEX: doubao-seed-2-0-code-preview-260215 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 }} @@ -1261,7 +1261,7 @@ jobs: GH_AW_CALLER_WORKFLOW_ID: "${{ github.repository }}/issue-triage" GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens }} GH_AW_ENGINE_ID: "codex" - GH_AW_ENGINE_MODEL: ${{ needs.agent.outputs.model }} + GH_AW_ENGINE_MODEL: "doubao-seed-2-0-code-preview-260215" GH_AW_WORKFLOW_ID: "issue-triage" GH_AW_WORKFLOW_NAME: "Issue 自动分类与回复" GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-triage.md" diff --git a/.github/workflows/issue-triage.md b/.github/workflows/issue-triage.md index de82018e..0b234a94 100644 --- a/.github/workflows/issue-triage.md +++ b/.github/workflows/issue-triage.md @@ -7,8 +7,9 @@ engine: id: codex env: OPENAI_BASE_URL: "https://ark.cn-beijing.volces.com/api/v3" - CODEX_MODEL: doubao-seed-2-0-code-preview-260215 OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + CODEX_MODEL: doubao-seed-2-0-code-preview-260215 + model: doubao-seed-2-0-code-preview-260215 network: allowed: From af4636491d4471a40ab3a25ed1fc45bd7420ee57 Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Tue, 23 Jun 2026 10:12:20 +0800 Subject: [PATCH 35/59] feat: add agentic workflows for issue triage and auto fix --- .github/workflows/auto-code.lock.yml | 13 +++++++------ .github/workflows/auto-code.md | 5 +++++ .github/workflows/issue-triage.lock.yml | 13 +++++++------ .github/workflows/issue-triage.md | 5 +++++ 4 files changed, 24 insertions(+), 12 deletions(-) diff --git a/.github/workflows/auto-code.lock.yml b/.github/workflows/auto-code.lock.yml index cc8f1989..c41cf285 100644 --- a/.github/workflows/auto-code.lock.yml +++ b/.github/workflows/auto-code.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"379ddfe130a1c0cb713f795f724a4d2226e2f6c40c8ccb6db5b54ff6f035958d","body_hash":"9959a757362d73cb28768bc2f9a90afc30a49f61e3226f922c791d0cbf387678","compiler_version":"v0.79.6","strict":true,"agent_id":"codex","agent_model":"doubao-seed-2-0-code-preview-260215","engine_versions":{"codex":"0.137.0"}} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"1883cf08233ac6269970aae96ec73b20118a2b2d94bd30c6cb60395e375fd7ee","body_hash":"9959a757362d73cb28768bc2f9a90afc30a49f61e3226f922c791d0cbf387678","compiler_version":"v0.79.6","strict":true,"agent_id":"codex","agent_model":"doubao-seed-2-0-code-preview-260215","engine_versions":{"codex":"0.137.0"}} # gh-aw-manifest: {"version":1,"secrets":["CODEX_API_KEY","GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"5c2fe865bb4dc46e1450f6ee0d0541d759aea73a","version":"v0.79.6"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2","digest":"sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2","digest":"sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2@sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2","digest":"sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2@sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.25","digest":"sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.25@sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa"},{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]} # ___ _ _ # / _ \ | | (_) @@ -115,12 +115,13 @@ jobs: GH_AW_INFO_EXPERIMENTAL: "false" GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true" GH_AW_INFO_STAGED: "false" - GH_AW_INFO_ALLOWED_DOMAINS: '["defaults","ark.cn-beijing.volces.com"]' + GH_AW_INFO_ALLOWED_DOMAINS: '["defaults","ark.cn-beijing.volces.com","github.com","api.github.com"]' GH_AW_INFO_FIREWALL_ENABLED: "true" GH_AW_INFO_AWF_VERSION: "v0.27.2" GH_AW_INFO_AWMG_VERSION: "" GH_AW_INFO_FIREWALL_TYPE: "squid" GH_AW_COMPILED_STRICT: "true" + GH_AW_INFO_TOKEN_WEIGHTS: '{"multipliers":{"doubao":0.5}}' uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | @@ -200,7 +201,7 @@ jobs: id: sanitized uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: - GH_AW_ALLOWED_DOMAINS: "172.30.0.1,api.openai.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,chatgpt.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,host.docker.internal,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,openai.com,packagecloud.io,packages.cloud.google.com,packages.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" + GH_AW_ALLOWED_DOMAINS: "172.30.0.1,api.github.com,api.openai.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,chatgpt.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,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,openai.com,packagecloud.io,packages.cloud.google.com,packages.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 { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); @@ -859,7 +860,7 @@ jobs: 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="${{ vars.GH_AW_DEFAULT_MAX_AI_CREDITS || '1000' }}" - printf '%s\n' "{\"\$schema\":\"https://github.com/github/gh-aw-firewall/releases/download/v0.27.2/awf-config.schema.json\",\"network\":{\"allowDomains\":[\"172.30.0.1\",\"api.openai.com\",\"api.snapcraft.io\",\"archive.ubuntu.com\",\"ark.cn-beijing.volces.com\",\"azure.archive.ubuntu.com\",\"chatgpt.com\",\"crl.geotrust.com\",\"crl.globalsign.com\",\"crl.identrust.com\",\"crl.sectigo.com\",\"crl.thawte.com\",\"crl.usertrust.com\",\"crl.verisign.com\",\"crl3.digicert.com\",\"crl4.digicert.com\",\"crls.ssl.com\",\"host.docker.internal\",\"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\",\"openai.com\",\"packagecloud.io\",\"packages.cloud.google.com\",\"packages.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\"]},\"apiProxy\":{\"enabled\":true,\"enableTokenSteering\":true,\"maxRuns\":500,\"maxAiCredits\":${GH_AW_MAX_AI_CREDITS},\"targets\":{\"openai\":{\"host\":\"ark.cn-beijing.volces.com\"}},\"models\":{\"agent\":[\"sonnet-6x\",\"gpt-5.4\",\"gpt-5.3\",\"gemini-pro\",\"any\"],\"antigravity\":[\"copilot/antigravity*\",\"google/antigravity*\",\"gemini/antigravity*\"],\"any\":[\"copilot/*\",\"anthropic/*\",\"openai/*\",\"google/*\",\"gemini/*\"],\"claude\":[\"agent\"],\"codex\":[\"agent\"],\"coding\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\",\"gpt-5-codex\"],\"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*\"],\"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-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-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.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*\"],\"haiku\":[\"copilot/*haiku*\",\"anthropic/*haiku*\"],\"large\":[\"sonnet\",\"gpt-5-pro\",\"gpt-5\",\"gemini-pro\"],\"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\"],\"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-4-5-*\",\"anthropic/*sonnet-4-5-*\",\"copilot/*sonnet-4-6*\",\"anthropic/*sonnet-4-6*\"],\"summarization\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash-lite\",\"mini\"],\"vision\":[\"copilot/gemini-*image*\",\"gemini/gemini-*image*\",\"copilot/gemini-*flash*\",\"gemini/gemini-*flash*\"]}},\"container\":{\"imageTag\":\"0.27.2,squid=sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591,agent=sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6,api-proxy=sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4,cli-proxy=sha256:02f3ec08f32dc26c5427920c6a2e2f3036238fce44802f2f11ef49ed8621b5d0\"}}" > "${RUNNER_TEMP}/gh-aw/awf-config.json" + printf '%s\n' "{\"\$schema\":\"https://github.com/github/gh-aw-firewall/releases/download/v0.27.2/awf-config.schema.json\",\"network\":{\"allowDomains\":[\"172.30.0.1\",\"api.github.com\",\"api.openai.com\",\"api.snapcraft.io\",\"archive.ubuntu.com\",\"ark.cn-beijing.volces.com\",\"azure.archive.ubuntu.com\",\"chatgpt.com\",\"crl.geotrust.com\",\"crl.globalsign.com\",\"crl.identrust.com\",\"crl.sectigo.com\",\"crl.thawte.com\",\"crl.usertrust.com\",\"crl.verisign.com\",\"crl3.digicert.com\",\"crl4.digicert.com\",\"crls.ssl.com\",\"github.com\",\"host.docker.internal\",\"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\",\"openai.com\",\"packagecloud.io\",\"packages.cloud.google.com\",\"packages.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\"]},\"apiProxy\":{\"enabled\":true,\"enableTokenSteering\":true,\"maxRuns\":500,\"maxAiCredits\":${GH_AW_MAX_AI_CREDITS},\"targets\":{\"openai\":{\"host\":\"ark.cn-beijing.volces.com\"}},\"models\":{\"agent\":[\"sonnet-6x\",\"gpt-5.4\",\"gpt-5.3\",\"gemini-pro\",\"any\"],\"antigravity\":[\"copilot/antigravity*\",\"google/antigravity*\",\"gemini/antigravity*\"],\"any\":[\"copilot/*\",\"anthropic/*\",\"openai/*\",\"google/*\",\"gemini/*\"],\"claude\":[\"agent\"],\"codex\":[\"agent\"],\"coding\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\",\"gpt-5-codex\"],\"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*\"],\"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-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-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.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*\"],\"haiku\":[\"copilot/*haiku*\",\"anthropic/*haiku*\"],\"large\":[\"sonnet\",\"gpt-5-pro\",\"gpt-5\",\"gemini-pro\"],\"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\"],\"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-4-5-*\",\"anthropic/*sonnet-4-5-*\",\"copilot/*sonnet-4-6*\",\"anthropic/*sonnet-4-6*\"],\"summarization\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash-lite\",\"mini\"],\"vision\":[\"copilot/gemini-*image*\",\"gemini/gemini-*image*\",\"copilot/gemini-*flash*\",\"gemini/gemini-*flash*\"]}},\"container\":{\"imageTag\":\"0.27.2,squid=sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591,agent=sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6,api-proxy=sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4,cli-proxy=sha256:02f3ec08f32dc26c5427920c6a2e2f3036238fce44802f2f11ef49ed8621b5d0\"}}" > "${RUNNER_TEMP}/gh-aw/awf-config.json" GH_AW_MODEL_MULTIPLIERS_PATH="/tmp/gh-aw/model_multipliers.json" node "${RUNNER_TEMP}/gh-aw/actions/merge_awf_model_multipliers.cjs" 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" @@ -959,7 +960,7 @@ jobs: 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: "172.30.0.1,api.openai.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,chatgpt.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,host.docker.internal,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,openai.com,packagecloud.io,packages.cloud.google.com,packages.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" + GH_AW_ALLOWED_DOMAINS: "172.30.0.1,api.github.com,api.openai.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,chatgpt.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,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,openai.com,packagecloud.io,packages.cloud.google.com,packages.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 }} with: @@ -1399,7 +1400,7 @@ jobs: 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_ALLOWED_DOMAINS: "172.30.0.1,api.openai.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,chatgpt.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,host.docker.internal,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,openai.com,packagecloud.io,packages.cloud.google.com,packages.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" + GH_AW_ALLOWED_DOMAINS: "172.30.0.1,api.github.com,api.openai.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,chatgpt.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,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,openai.com,packagecloud.io,packages.cloud.google.com,packages.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},\"create_pull_request\":{\"base_branch\":\"develop\",\"max\":1,\"max_patch_files\":100,\"max_patch_size\":1024,\"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\",\"CHANGELOG.md\",\"SECURITY.md\",\"CODE_OF_CONDUCT.md\",\"AGENTS.md\",\"CLAUDE.md\",\"GEMINI.md\"],\"protected_files_policy\":\"request_review\"},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"report_incomplete\":{}}" diff --git a/.github/workflows/auto-code.md b/.github/workflows/auto-code.md index 384b9711..13ac6436 100644 --- a/.github/workflows/auto-code.md +++ b/.github/workflows/auto-code.md @@ -10,11 +10,16 @@ engine: OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} CODEX_MODEL: doubao-seed-2-0-code-preview-260215 model: doubao-seed-2-0-code-preview-260215 + token-weights: + multipliers: + doubao: 0.5 network: allowed: - defaults - ark.cn-beijing.volces.com + - github.com + - api.github.com tools: github: diff --git a/.github/workflows/issue-triage.lock.yml b/.github/workflows/issue-triage.lock.yml index de2e491f..a767a10c 100644 --- a/.github/workflows/issue-triage.lock.yml +++ b/.github/workflows/issue-triage.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"5c7eddfd02afac9f7dd0d5ca4c24ffc1f6911842dc72dbd5bf0540d30b43955a","body_hash":"bf4f8784cdac578e246f253a70aa7f7acce80a6fcf1c9116a0f5867b9ece3260","compiler_version":"v0.79.6","strict":true,"agent_id":"codex","agent_model":"doubao-seed-2-0-code-preview-260215","engine_versions":{"codex":"0.137.0"}} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"885bf9f72552ed45f06fdaaf564a46ab0c267327a99cabcd2eec09a84a4c5503","body_hash":"bf4f8784cdac578e246f253a70aa7f7acce80a6fcf1c9116a0f5867b9ece3260","compiler_version":"v0.79.6","strict":true,"agent_id":"codex","agent_model":"doubao-seed-2-0-code-preview-260215","engine_versions":{"codex":"0.137.0"}} # gh-aw-manifest: {"version":1,"secrets":["CODEX_API_KEY","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"5c2fe865bb4dc46e1450f6ee0d0541d759aea73a","version":"v0.79.6"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2","digest":"sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2","digest":"sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2@sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2","digest":"sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2@sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.25","digest":"sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.25@sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa"},{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]} # ___ _ _ # / _ \ | | (_) @@ -115,12 +115,13 @@ jobs: GH_AW_INFO_EXPERIMENTAL: "false" GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true" GH_AW_INFO_STAGED: "false" - GH_AW_INFO_ALLOWED_DOMAINS: '["defaults","ark.cn-beijing.volces.com"]' + GH_AW_INFO_ALLOWED_DOMAINS: '["defaults","ark.cn-beijing.volces.com","github.com","api.github.com"]' GH_AW_INFO_FIREWALL_ENABLED: "true" GH_AW_INFO_AWF_VERSION: "v0.27.2" GH_AW_INFO_AWMG_VERSION: "" GH_AW_INFO_FIREWALL_TYPE: "squid" GH_AW_COMPILED_STRICT: "true" + GH_AW_INFO_TOKEN_WEIGHTS: '{"multipliers":{"doubao":0.5}}' uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | @@ -200,7 +201,7 @@ jobs: id: sanitized uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: - GH_AW_ALLOWED_DOMAINS: "172.30.0.1,api.openai.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,chatgpt.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,host.docker.internal,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,openai.com,packagecloud.io,packages.cloud.google.com,packages.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" + GH_AW_ALLOWED_DOMAINS: "172.30.0.1,api.github.com,api.openai.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,chatgpt.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,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,openai.com,packagecloud.io,packages.cloud.google.com,packages.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 { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); @@ -831,7 +832,7 @@ jobs: 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="${{ vars.GH_AW_DEFAULT_MAX_AI_CREDITS || '1000' }}" - printf '%s\n' "{\"\$schema\":\"https://github.com/github/gh-aw-firewall/releases/download/v0.27.2/awf-config.schema.json\",\"network\":{\"allowDomains\":[\"172.30.0.1\",\"api.openai.com\",\"api.snapcraft.io\",\"archive.ubuntu.com\",\"ark.cn-beijing.volces.com\",\"azure.archive.ubuntu.com\",\"chatgpt.com\",\"crl.geotrust.com\",\"crl.globalsign.com\",\"crl.identrust.com\",\"crl.sectigo.com\",\"crl.thawte.com\",\"crl.usertrust.com\",\"crl.verisign.com\",\"crl3.digicert.com\",\"crl4.digicert.com\",\"crls.ssl.com\",\"host.docker.internal\",\"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\",\"openai.com\",\"packagecloud.io\",\"packages.cloud.google.com\",\"packages.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\"]},\"apiProxy\":{\"enabled\":true,\"enableTokenSteering\":true,\"maxRuns\":500,\"maxAiCredits\":${GH_AW_MAX_AI_CREDITS},\"targets\":{\"openai\":{\"host\":\"ark.cn-beijing.volces.com\"}},\"models\":{\"agent\":[\"sonnet-6x\",\"gpt-5.4\",\"gpt-5.3\",\"gemini-pro\",\"any\"],\"antigravity\":[\"copilot/antigravity*\",\"google/antigravity*\",\"gemini/antigravity*\"],\"any\":[\"copilot/*\",\"anthropic/*\",\"openai/*\",\"google/*\",\"gemini/*\"],\"claude\":[\"agent\"],\"codex\":[\"agent\"],\"coding\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\",\"gpt-5-codex\"],\"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*\"],\"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-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-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.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*\"],\"haiku\":[\"copilot/*haiku*\",\"anthropic/*haiku*\"],\"large\":[\"sonnet\",\"gpt-5-pro\",\"gpt-5\",\"gemini-pro\"],\"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\"],\"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-4-5-*\",\"anthropic/*sonnet-4-5-*\",\"copilot/*sonnet-4-6*\",\"anthropic/*sonnet-4-6*\"],\"summarization\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash-lite\",\"mini\"],\"vision\":[\"copilot/gemini-*image*\",\"gemini/gemini-*image*\",\"copilot/gemini-*flash*\",\"gemini/gemini-*flash*\"]}},\"container\":{\"imageTag\":\"0.27.2,squid=sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591,agent=sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6,api-proxy=sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4,cli-proxy=sha256:02f3ec08f32dc26c5427920c6a2e2f3036238fce44802f2f11ef49ed8621b5d0\"}}" > "${RUNNER_TEMP}/gh-aw/awf-config.json" + printf '%s\n' "{\"\$schema\":\"https://github.com/github/gh-aw-firewall/releases/download/v0.27.2/awf-config.schema.json\",\"network\":{\"allowDomains\":[\"172.30.0.1\",\"api.github.com\",\"api.openai.com\",\"api.snapcraft.io\",\"archive.ubuntu.com\",\"ark.cn-beijing.volces.com\",\"azure.archive.ubuntu.com\",\"chatgpt.com\",\"crl.geotrust.com\",\"crl.globalsign.com\",\"crl.identrust.com\",\"crl.sectigo.com\",\"crl.thawte.com\",\"crl.usertrust.com\",\"crl.verisign.com\",\"crl3.digicert.com\",\"crl4.digicert.com\",\"crls.ssl.com\",\"github.com\",\"host.docker.internal\",\"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\",\"openai.com\",\"packagecloud.io\",\"packages.cloud.google.com\",\"packages.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\"]},\"apiProxy\":{\"enabled\":true,\"enableTokenSteering\":true,\"maxRuns\":500,\"maxAiCredits\":${GH_AW_MAX_AI_CREDITS},\"targets\":{\"openai\":{\"host\":\"ark.cn-beijing.volces.com\"}},\"models\":{\"agent\":[\"sonnet-6x\",\"gpt-5.4\",\"gpt-5.3\",\"gemini-pro\",\"any\"],\"antigravity\":[\"copilot/antigravity*\",\"google/antigravity*\",\"gemini/antigravity*\"],\"any\":[\"copilot/*\",\"anthropic/*\",\"openai/*\",\"google/*\",\"gemini/*\"],\"claude\":[\"agent\"],\"codex\":[\"agent\"],\"coding\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\",\"gpt-5-codex\"],\"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*\"],\"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-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-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.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*\"],\"haiku\":[\"copilot/*haiku*\",\"anthropic/*haiku*\"],\"large\":[\"sonnet\",\"gpt-5-pro\",\"gpt-5\",\"gemini-pro\"],\"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\"],\"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-4-5-*\",\"anthropic/*sonnet-4-5-*\",\"copilot/*sonnet-4-6*\",\"anthropic/*sonnet-4-6*\"],\"summarization\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash-lite\",\"mini\"],\"vision\":[\"copilot/gemini-*image*\",\"gemini/gemini-*image*\",\"copilot/gemini-*flash*\",\"gemini/gemini-*flash*\"]}},\"container\":{\"imageTag\":\"0.27.2,squid=sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591,agent=sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6,api-proxy=sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4,cli-proxy=sha256:02f3ec08f32dc26c5427920c6a2e2f3036238fce44802f2f11ef49ed8621b5d0\"}}" > "${RUNNER_TEMP}/gh-aw/awf-config.json" GH_AW_MODEL_MULTIPLIERS_PATH="/tmp/gh-aw/model_multipliers.json" node "${RUNNER_TEMP}/gh-aw/actions/merge_awf_model_multipliers.cjs" 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" @@ -931,7 +932,7 @@ jobs: 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: "172.30.0.1,api.openai.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,chatgpt.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,host.docker.internal,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,openai.com,packagecloud.io,packages.cloud.google.com,packages.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" + GH_AW_ALLOWED_DOMAINS: "172.30.0.1,api.github.com,api.openai.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,chatgpt.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,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,openai.com,packagecloud.io,packages.cloud.google.com,packages.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 }} with: @@ -1319,7 +1320,7 @@ jobs: 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_ALLOWED_DOMAINS: "172.30.0.1,api.openai.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,chatgpt.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,host.docker.internal,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,openai.com,packagecloud.io,packages.cloud.google.com,packages.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" + GH_AW_ALLOWED_DOMAINS: "172.30.0.1,api.github.com,api.openai.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,chatgpt.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,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,openai.com,packagecloud.io,packages.cloud.google.com,packages.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},\"add_labels\":{\"allowed\":[\"bug\",\"feature\",\"enhancement\",\"documentation\",\"question\",\"duplicate\",\"invalid\"]},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"report_incomplete\":{}}" diff --git a/.github/workflows/issue-triage.md b/.github/workflows/issue-triage.md index 0b234a94..264acb08 100644 --- a/.github/workflows/issue-triage.md +++ b/.github/workflows/issue-triage.md @@ -10,11 +10,16 @@ engine: OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} CODEX_MODEL: doubao-seed-2-0-code-preview-260215 model: doubao-seed-2-0-code-preview-260215 + token-weights: + multipliers: + doubao: 0.5 network: allowed: - defaults - ark.cn-beijing.volces.com + - github.com + - api.github.com tools: github: From 7355bf5f7456fa115bf155d42e79bca06bd8f572 Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Tue, 23 Jun 2026 10:32:44 +0800 Subject: [PATCH 36/59] feat: add agentic workflows for issue triage and auto fix --- .github/workflows/issue-triage.lock.yml | 215 +++++++++--------------- .github/workflows/issue-triage.md | 14 +- 2 files changed, 90 insertions(+), 139 deletions(-) diff --git a/.github/workflows/issue-triage.lock.yml b/.github/workflows/issue-triage.lock.yml index a767a10c..1d24f5e1 100644 --- a/.github/workflows/issue-triage.lock.yml +++ b/.github/workflows/issue-triage.lock.yml @@ -1,5 +1,5 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"885bf9f72552ed45f06fdaaf564a46ab0c267327a99cabcd2eec09a84a4c5503","body_hash":"bf4f8784cdac578e246f253a70aa7f7acce80a6fcf1c9116a0f5867b9ece3260","compiler_version":"v0.79.6","strict":true,"agent_id":"codex","agent_model":"doubao-seed-2-0-code-preview-260215","engine_versions":{"codex":"0.137.0"}} -# gh-aw-manifest: {"version":1,"secrets":["CODEX_API_KEY","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"5c2fe865bb4dc46e1450f6ee0d0541d759aea73a","version":"v0.79.6"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2","digest":"sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2","digest":"sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2@sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2","digest":"sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2@sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.25","digest":"sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.25@sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa"},{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"ec6a9f2b8248fd660c86ffd2700c27809d68642b0f21eeedce74bad9812e7a97","body_hash":"bf4f8784cdac578e246f253a70aa7f7acce80a6fcf1c9116a0f5867b9ece3260","compiler_version":"v0.79.6","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}} +# gh-aw-manifest: {"version":1,"secrets":["GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"5c2fe865bb4dc46e1450f6ee0d0541d759aea73a","version":"v0.79.6"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2","digest":"sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2","digest":"sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2@sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2","digest":"sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2@sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.25","digest":"sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.25@sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa"},{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]} # ___ _ _ # / _ \ | | (_) # | |_| | __ _ ___ _ __ | |_ _ ___ @@ -24,7 +24,6 @@ # # # Secrets used: -# - CODEX_API_KEY # - GH_AW_GITHUB_MCP_SERVER_TOKEN # - GH_AW_GITHUB_TOKEN # - GITHUB_TOKEN @@ -34,7 +33,6 @@ # - actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 # - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 # - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 -# - actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 # - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 # - github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 # @@ -79,7 +77,6 @@ jobs: engine_id: ${{ steps.generate_aw_info.outputs.engine_id }} lockdown_check_failed: ${{ steps.generate_aw_info.outputs.lockdown_check_failed == 'true' }} model: ${{ steps.generate_aw_info.outputs.model }} - secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} 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 }} @@ -99,17 +96,17 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "Issue 自动分类与回复" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "0.137.0" + GH_AW_INFO_VERSION: "1.0.60" GH_AW_INFO_AWF_VERSION: "v0.27.2" - GH_AW_INFO_ENGINE_ID: "codex" + GH_AW_INFO_ENGINE_ID: "copilot" - 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: "doubao-seed-2-0-code-preview-260215" - GH_AW_INFO_VERSION: "0.137.0" - GH_AW_INFO_AGENT_VERSION: "0.137.0" + GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_INFO_ENGINE_NAME: "GitHub Copilot CLI" + GH_AW_INFO_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || vars.GH_AW_DEFAULT_MODEL_COPILOT || 'claude-sonnet-4.6' }} + GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_AGENT_VERSION: "1.0.60" GH_AW_INFO_CLI_VERSION: "v0.79.6" GH_AW_INFO_WORKFLOW_NAME: "Issue 自动分类与回复" GH_AW_INFO_EXPERIMENTAL: "false" @@ -121,7 +118,6 @@ jobs: GH_AW_INFO_AWMG_VERSION: "" GH_AW_INFO_FIREWALL_TYPE: "squid" GH_AW_COMPILED_STRICT: "true" - GH_AW_INFO_TOKEN_WEIGHTS: '{"multipliers":{"doubao":0.5}}' uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | @@ -147,12 +143,6 @@ jobs: setupGlobals(core, github, context, exec, io, getOctokit); const { main } = require('${{ runner.temp }}/gh-aw/actions/check_daily_aic_workflow_guardrail.cjs'); await main(); - - name: Validate CODEX_API_KEY or OPENAI_API_KEY secret - id: validate-secret - run: bash "${RUNNER_TEMP}/gh-aw/actions/validate_multi_secret.sh" CODEX_API_KEY OPENAI_API_KEY Codex https://github.github.com/gh-aw/reference/engines/#openai-codex - env: - CODEX_API_KEY: ${{ secrets.CODEX_API_KEY }} - OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - name: Checkout .github and .agents folders uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: @@ -201,7 +191,7 @@ jobs: id: sanitized uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: - GH_AW_ALLOWED_DOMAINS: "172.30.0.1,api.github.com,api.openai.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,chatgpt.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,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,openai.com,packagecloud.io,packages.cloud.google.com,packages.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" + GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,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,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); @@ -277,7 +267,7 @@ jobs: uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GH_AW_ENGINE_ID: "codex" + GH_AW_ENGINE_ID: "copilot" GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} with: script: | @@ -347,8 +337,8 @@ jobs: /tmp/gh-aw/aw-prompts/prompt-import-tree.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/.github/agents + /tmp/gh-aw/.github/skills if-no-files-found: ignore retention-days: 1 @@ -358,6 +348,7 @@ jobs: runs-on: ubuntu-latest permissions: contents: read + copilot-requests: write issues: read pull-requests: read env: @@ -397,9 +388,9 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "Issue 自动分类与回复" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "0.137.0" + GH_AW_INFO_VERSION: "1.0.60" GH_AW_INFO_AWF_VERSION: "v0.27.2" - GH_AW_INFO_ENGINE_ID: "codex" + GH_AW_INFO_ENGINE_ID: "copilot" - name: Set runtime paths id: set-runtime-paths run: | @@ -445,13 +436,10 @@ jobs: setupGlobals(core, github, context, exec, io, getOctokit); const { main } = require('${{ runner.temp }}/gh-aw/actions/checkout_pr_branch.cjs'); await main(); - - name: Setup Node.js - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 - with: - node-version: '24' - package-manager-cache: false - - name: Install Codex CLI - run: npm install --ignore-scripts -g @openai/codex@0.137.0 + - name: Install GitHub Copilot CLI + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.60 + env: + GH_HOST: github.com - name: Install AWF binary run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.27.2 - name: Parse integrity filter lists @@ -474,12 +462,12 @@ jobs: 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" + GH_AW_SUB_AGENT_DIR: ".github/agents" + GH_AW_SUB_AGENT_EXT: ".agent.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" + GH_AW_SKILL_DIR: ".github/skills" run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_inline_skills.sh" - name: Download container images run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6 ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2@sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4 ghcr.io/github/gh-aw-firewall/squid:0.27.2@sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591 ghcr.io/github/gh-aw-mcpg:v0.3.25@sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c @@ -669,7 +657,6 @@ jobs: - name: Start MCP Gateway id: start-mcp-gateway env: - CODEX_HOME: /tmp/gh-aw/mcp-config GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-start.outputs.api_key }} GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-start.outputs.port }} @@ -690,7 +677,7 @@ jobs: export MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD="524288" export DEBUG="*" - export GH_AW_ENGINE="codex" + export GH_AW_ENGINE="copilot" MCP_GATEWAY_UID=$(id -u 2>/dev/null || echo '0') MCP_GATEWAY_GID=$(id -g 2>/dev/null || echo '0') case "${DOCKER_HOST:-}" in @@ -699,47 +686,19 @@ jobs: * ) DOCKER_SOCK_PATH=/var/run/docker.sock ;; esac DOCKER_SOCK_GID=$(stat -c '%g' "$DOCKER_SOCK_PATH" 2>/dev/null || echo '0') - export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --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_API_KEY -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_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -e CODEX_HOME -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.3.25' - - cat > "${RUNNER_TEMP}/gh-aw/mcp-config/config.toml" << GH_AW_MCP_CONFIG_d9dc58ce079498af_EOF - [history] - persistence = "none" - - [shell_environment_policy] - inherit = "core" - include_only = ["^CODEX_API_KEY$", "^GH_AW_ASSETS_ALLOWED_EXTS$", "^GH_AW_ASSETS_BRANCH$", "^GH_AW_ASSETS_MAX_SIZE_KB$", "^GH_AW_SAFE_OUTPUTS$", "^GITHUB_PERSONAL_ACCESS_TOKEN$", "^GITHUB_REPOSITORY$", "^GITHUB_SERVER_URL$", "^HOME$", "^OPENAI_API_KEY$", "^PATH$"] - - [mcp_servers.github] - user_agent = "issue" - startup_timeout_sec = 120 - tool_timeout_sec = 60 - container = "ghcr.io/github/github-mcp-server:v1.1.2" - env = { "GITHUB_HOST" = "$GITHUB_SERVER_URL", "GITHUB_PERSONAL_ACCESS_TOKEN" = "$GH_AW_GITHUB_TOKEN", "GITHUB_READ_ONLY" = "1", "GITHUB_TOOLSETS" = "context,repos,issues,pull_requests" } - env_vars = ["GITHUB_HOST", "GITHUB_PERSONAL_ACCESS_TOKEN", "GITHUB_READ_ONLY", "GITHUB_TOOLSETS"] - - [mcp_servers.safeoutputs] - type = "http" - url = "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT" - - [mcp_servers.safeoutputs.headers] - Authorization = "$GH_AW_SAFE_OUTPUTS_API_KEY" - - [mcp_servers.safeoutputs."guard-policies"] + export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --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_API_KEY -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_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.3.25' - [mcp_servers.safeoutputs."guard-policies".write-sink] - accept = ["*"] - GH_AW_MCP_CONFIG_d9dc58ce079498af_EOF - - # Generate JSON config for MCP gateway + mkdir -p /home/runner/.copilot GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_ca772287f17ffc28_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_920bb1916fcb7fc4_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "github": { + "type": "stdio", "container": "ghcr.io/github/github-mcp-server:v1.1.2", "env": { - "GITHUB_HOST": "$GITHUB_SERVER_URL", - "GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_MCP_SERVER_TOKEN", + "GITHUB_HOST": "\${GITHUB_SERVER_URL}", + "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}", "GITHUB_READ_ONLY": "1", "GITHUB_TOOLSETS": "context,repos,issues,pull_requests" }, @@ -757,7 +716,7 @@ jobs: "type": "http", "url": "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT", "headers": { - "Authorization": "$GH_AW_SAFE_OUTPUTS_API_KEY" + "Authorization": "\${GH_AW_SAFE_OUTPUTS_API_KEY}" }, "guard-policies": { "write-sink": { @@ -775,34 +734,7 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_ca772287f17ffc28_EOF - - # Sync converter output to writable CODEX_HOME for Codex - mkdir -p /tmp/gh-aw/mcp-config - cat > "/tmp/gh-aw/mcp-config/config.toml" << GH_AW_CODEX_SHELL_POLICY_929fca99db4cd5ec_EOF - - model_provider = "openai-proxy" - - [model_providers.openai-proxy] - name = "OpenAI AWF proxy" - base_url = "http://172.30.0.30:10000" - env_key = "OPENAI_API_KEY" - supports_websockets = false - [shell_environment_policy] - inherit = "core" - include_only = ["^CODEX_API_KEY$", "^GH_AW_ASSETS_ALLOWED_EXTS$", "^GH_AW_ASSETS_BRANCH$", "^GH_AW_ASSETS_MAX_SIZE_KB$", "^GH_AW_SAFE_OUTPUTS$", "^GITHUB_PERSONAL_ACCESS_TOKEN$", "^GITHUB_REPOSITORY$", "^GITHUB_SERVER_URL$", "^HOME$", "^OPENAI_API_KEY$", "^PATH$"] - GH_AW_CODEX_SHELL_POLICY_929fca99db4cd5ec_EOF - awk ' - BEGIN { skip_openai_proxy = 0 } - /^[[:space:]]*model_provider[[:space:]]*=/ { next } - /^\[model_providers\.openai-proxy\][[:space:]]*$/ { skip_openai_proxy = 1; next } - /^\[/ { skip_openai_proxy = 0 } - !skip_openai_proxy { print } - ' "${RUNNER_TEMP}/gh-aw/mcp-config/config.toml" >> "/tmp/gh-aw/mcp-config/config.toml" - chmod 600 "/tmp/gh-aw/mcp-config/config.toml" - mkdir -p "${CODEX_HOME}" - if [ "/tmp/gh-aw/mcp-config/config.toml" != "${CODEX_HOME}/config.toml" ]; then cp "/tmp/gh-aw/mcp-config/config.toml" "${CODEX_HOME}/config.toml"; fi - chmod 600 "${CODEX_HOME}/config.toml" + GH_AW_MCP_CONFIG_920bb1916fcb7fc4_EOF - name: Mount MCP servers as CLIs id: mount-mcp-clis continue-on-error: true @@ -824,15 +756,23 @@ jobs: id: pre_agent_audit continue-on-error: true run: bash "${RUNNER_TEMP}/gh-aw/actions/audit_pre_agent_workspace.sh" - - name: Execute Codex CLI + - name: Execute GitHub Copilot CLI id: agentic_execution + # Copilot CLI tool arguments (sorted): + timeout-minutes: 20 run: | set -o pipefail 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 + trap 'rm -f /home/runner/.copilot/settings.json' EXIT + mkdir -p /home/runner/.copilot + printf '%s' '{"builtInAgents":{"rubberDuck":false}}' > /home/runner/.copilot/settings.json + touch /tmp/gh-aw/agent-step-summary.md + GH_AW_NODE_BIN=$(command -v node 2>/dev/null || true) + export GH_AW_NODE_BIN + export COPILOT_API_KEY="$COPILOT_DUMMY_BYOK" (umask 177 && touch /tmp/gh-aw/agent-stdio.log) GH_AW_MAX_AI_CREDITS="${{ vars.GH_AW_DEFAULT_MAX_AI_CREDITS || '1000' }}" - printf '%s\n' "{\"\$schema\":\"https://github.com/github/gh-aw-firewall/releases/download/v0.27.2/awf-config.schema.json\",\"network\":{\"allowDomains\":[\"172.30.0.1\",\"api.github.com\",\"api.openai.com\",\"api.snapcraft.io\",\"archive.ubuntu.com\",\"ark.cn-beijing.volces.com\",\"azure.archive.ubuntu.com\",\"chatgpt.com\",\"crl.geotrust.com\",\"crl.globalsign.com\",\"crl.identrust.com\",\"crl.sectigo.com\",\"crl.thawte.com\",\"crl.usertrust.com\",\"crl.verisign.com\",\"crl3.digicert.com\",\"crl4.digicert.com\",\"crls.ssl.com\",\"github.com\",\"host.docker.internal\",\"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\",\"openai.com\",\"packagecloud.io\",\"packages.cloud.google.com\",\"packages.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\"]},\"apiProxy\":{\"enabled\":true,\"enableTokenSteering\":true,\"maxRuns\":500,\"maxAiCredits\":${GH_AW_MAX_AI_CREDITS},\"targets\":{\"openai\":{\"host\":\"ark.cn-beijing.volces.com\"}},\"models\":{\"agent\":[\"sonnet-6x\",\"gpt-5.4\",\"gpt-5.3\",\"gemini-pro\",\"any\"],\"antigravity\":[\"copilot/antigravity*\",\"google/antigravity*\",\"gemini/antigravity*\"],\"any\":[\"copilot/*\",\"anthropic/*\",\"openai/*\",\"google/*\",\"gemini/*\"],\"claude\":[\"agent\"],\"codex\":[\"agent\"],\"coding\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\",\"gpt-5-codex\"],\"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*\"],\"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-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-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.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*\"],\"haiku\":[\"copilot/*haiku*\",\"anthropic/*haiku*\"],\"large\":[\"sonnet\",\"gpt-5-pro\",\"gpt-5\",\"gemini-pro\"],\"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\"],\"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-4-5-*\",\"anthropic/*sonnet-4-5-*\",\"copilot/*sonnet-4-6*\",\"anthropic/*sonnet-4-6*\"],\"summarization\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash-lite\",\"mini\"],\"vision\":[\"copilot/gemini-*image*\",\"gemini/gemini-*image*\",\"copilot/gemini-*flash*\",\"gemini/gemini-*flash*\"]}},\"container\":{\"imageTag\":\"0.27.2,squid=sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591,agent=sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6,api-proxy=sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4,cli-proxy=sha256:02f3ec08f32dc26c5427920c6a2e2f3036238fce44802f2f11ef49ed8621b5d0\"}}" > "${RUNNER_TEMP}/gh-aw/awf-config.json" + printf '%s\n' "{\"\$schema\":\"https://github.com/github/gh-aw-firewall/releases/download/v0.27.2/awf-config.schema.json\",\"network\":{\"allowDomains\":[\"api.business.githubcopilot.com\",\"api.enterprise.githubcopilot.com\",\"api.github.com\",\"api.githubcopilot.com\",\"api.individual.githubcopilot.com\",\"api.snapcraft.io\",\"archive.ubuntu.com\",\"ark.cn-beijing.volces.com\",\"azure.archive.ubuntu.com\",\"crl.geotrust.com\",\"crl.globalsign.com\",\"crl.identrust.com\",\"crl.sectigo.com\",\"crl.thawte.com\",\"crl.usertrust.com\",\"crl.verisign.com\",\"crl3.digicert.com\",\"crl4.digicert.com\",\"crls.ssl.com\",\"github.com\",\"host.docker.internal\",\"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\",\"ppa.launchpad.net\",\"raw.githubusercontent.com\",\"registry.npmjs.org\",\"s.symcb.com\",\"s.symcd.com\",\"security.ubuntu.com\",\"telemetry.enterprise.githubcopilot.com\",\"ts-crl.ws.symantec.com\",\"ts-ocsp.ws.symantec.com\",\"www.googleapis.com\"]},\"apiProxy\":{\"enabled\":true,\"enableTokenSteering\":true,\"maxRuns\":500,\"maxAiCredits\":${GH_AW_MAX_AI_CREDITS},\"models\":{\"agent\":[\"sonnet-6x\",\"gpt-5.4\",\"gpt-5.3\",\"gemini-pro\",\"any\"],\"antigravity\":[\"copilot/antigravity*\",\"google/antigravity*\",\"gemini/antigravity*\"],\"any\":[\"copilot/*\",\"anthropic/*\",\"openai/*\",\"google/*\",\"gemini/*\"],\"claude\":[\"agent\"],\"codex\":[\"agent\"],\"coding\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\",\"gpt-5-codex\"],\"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*\"],\"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-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-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.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*\"],\"haiku\":[\"copilot/*haiku*\",\"anthropic/*haiku*\"],\"large\":[\"sonnet\",\"gpt-5-pro\",\"gpt-5\",\"gemini-pro\"],\"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\"],\"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-4-5-*\",\"anthropic/*sonnet-4-5-*\",\"copilot/*sonnet-4-6*\",\"anthropic/*sonnet-4-6*\"],\"summarization\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash-lite\",\"mini\"],\"vision\":[\"copilot/gemini-*image*\",\"gemini/gemini-*image*\",\"copilot/gemini-*flash*\",\"gemini/gemini-*flash*\"]}},\"container\":{\"imageTag\":\"0.27.2,squid=sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591,agent=sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6,api-proxy=sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4,cli-proxy=sha256:02f3ec08f32dc26c5427920c6a2e2f3036238fce44802f2f11ef49ed8621b5d0\"}}" > "${RUNNER_TEMP}/gh-aw/awf-config.json" GH_AW_MODEL_MULTIPLIERS_PATH="/tmp/gh-aw/model_multipliers.json" node "${RUNNER_TEMP}/gh-aw/actions/merge_awf_model_multipliers.cjs" 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" @@ -850,29 +790,39 @@ jobs: GH_AW_TOOL_CACHE_MOUNT="/home/runner/work/_tool:/home/runner/work/_tool:ro" fi # shellcheck disable=SC1003 - sudo -E 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_PATH_PREFIX_ARGS} --env-all --exclude-env CODEX_API_KEY --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --exclude-env OPENAI_API_KEY --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull --openai-api-base-path /api/v3 \ - -- /bin/bash -c 'set +o histexpand; export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && GH_AW_TOOL_CACHE="${RUNNER_TOOL_CACHE:-/opt/hostedtoolcache}"; export PATH="$(find "$GH_AW_TOOL_CACHE" /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 5 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/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" -c fetch="disabled" --dangerously-bypass-approvals-and-sandbox --skip-git-repo-check --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + sudo -E 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_PATH_PREFIX_ARGS} --env-all --exclude-env COPILOT_PROVIDER_API_KEY --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull \ + -- /bin/bash -c 'set +o histexpand; export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && GH_AW_TOOL_CACHE="${RUNNER_TOOL_CACHE:-/opt/hostedtoolcache}"; export PATH="$(find "$GH_AW_TOOL_CACHE" /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 5 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/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/copilot_harness.cjs /usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-all-tools --allow-all-paths --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log env: - CODEX_API_KEY: ${{ secrets.CODEX_API_KEY || secrets.OPENAI_API_KEY }} - CODEX_HOME: /tmp/gh-aw/mcp-config - CODEX_MODEL: doubao-seed-2-0-code-preview-260215 + AWF_REFLECT_ENABLED: 1 + COPILOT_AGENT_RUNNER_TYPE: STANDALONE + COPILOT_DUMMY_BYOK: dummy-byok-key-for-offline-mode + COPILOT_MODEL: doubao-seed-2-0-code-preview-260215 + COPILOT_PROVIDER_API_KEY: ${{ secrets.OPENAI_API_KEY }} + COPILOT_PROVIDER_BASE_URL: https://ark.cn-beijing.volces.com/api/v3 + COPILOT_PROVIDER_TYPE: openai GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }} - GH_AW_MCP_CONFIG: ${{ runner.temp }}/gh-aw/mcp-config/config.toml - GH_AW_MODEL_AGENT_CODEX: doubao-seed-2-0-code-preview-260215 + GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json 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_TIMEOUT_MINUTES: 20 GH_AW_VERSION: v0.79.6 + GITHUB_API_URL: ${{ github.api_url }} GITHUB_AW: true + GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows + GITHUB_HEAD_REF: ${{ github.head_ref }} + GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + 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] - OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - OPENAI_BASE_URL: https://ark.cn-beijing.volces.com/api/v3 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,ocodex_exec=debug' || 'warn' }} + S2STOKENS: true + XDG_CONFIG_HOME: /home/runner - name: Detect agent errors if: always() id: detect-agent-errors @@ -891,6 +841,10 @@ jobs: SERVER_URL_STRIPPED="${SERVER_URL#https://}" git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" echo "Git configured with standard GitHub Actions identity" + - name: Copy Copilot session state files to logs + if: always() + continue-on-error: true + run: bash "${RUNNER_TEMP}/gh-aw/actions/copy_copilot_session_state.sh" - name: Stop MCP Gateway if: always() continue-on-error: true @@ -910,8 +864,7 @@ jobs: const { main } = require('${{ runner.temp }}/gh-aw/actions/redact_secrets.cjs'); await main(); env: - GH_AW_SECRET_NAMES: 'CODEX_API_KEY,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN,OPENAI_API_KEY' - SECRET_CODEX_API_KEY: ${{ secrets.CODEX_API_KEY }} + GH_AW_SECRET_NAMES: 'GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN,OPENAI_API_KEY' SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -932,7 +885,7 @@ jobs: 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: "172.30.0.1,api.github.com,api.openai.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,chatgpt.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,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,openai.com,packagecloud.io,packages.cloud.google.com,packages.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" + GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,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,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} with: @@ -945,12 +898,12 @@ jobs: if: always() uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: - GH_AW_AGENT_OUTPUT: /tmp/gh-aw/agent-stdio.log + GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/ with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_codex_log.cjs'); + const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_copilot_log.cjs'); await main(); - name: Parse MCP Gateway logs for step summary if: always() @@ -1011,7 +964,7 @@ jobs: name: agent path: | /tmp/gh-aw/aw-prompts/prompt.txt - /tmp/gh-aw/mcp-config/logs/ + /tmp/gh-aw/sandbox/agent/logs/ /tmp/gh-aw/redacted-urls.log /tmp/gh-aw/mcp-logs/ /tmp/gh-aw/proxy-logs/ @@ -1064,9 +1017,9 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "Issue 自动分类与回复" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "0.137.0" + GH_AW_INFO_VERSION: "1.0.60" GH_AW_INFO_AWF_VERSION: "v0.27.2" - GH_AW_INFO_ENGINE_ID: "codex" + GH_AW_INFO_ENGINE_ID: "copilot" - name: Download agent output artifact id: download-agent-output continue-on-error: true @@ -1178,8 +1131,7 @@ jobs: GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} GH_AW_WORKFLOW_ID: "issue-triage" GH_AW_ACTION_FAILURE_ISSUE_EXPIRES_HOURS: "168" - GH_AW_ENGINE_ID: "codex" - GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.activation.outputs.secret_verification_result }} + GH_AW_ENGINE_ID: "copilot" GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens || '' }} GH_AW_AI_CREDITS_RATE_LIMIT_ERROR: ${{ needs.agent.outputs.ai_credits_rate_limit_error || 'false' }} @@ -1190,7 +1142,7 @@ jobs: 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_ENGINE_API_HOSTS: "api.openai.com" + GH_AW_ENGINE_API_HOSTS: "api.enterprise.githubcopilot.com,api.githubcopilot.com,api.business.githubcopilot.com,api.individual.githubcopilot.com" GH_AW_LOCKDOWN_CHECK_FAILED: ${{ needs.activation.outputs.lockdown_check_failed }} GH_AW_STALE_LOCK_FILE_FAILED: ${{ needs.activation.outputs.stale_lock_file_failed }} GH_AW_DAILY_EFFECTIVE_WORKFLOW_EXCEEDED: ${{ needs.activation.outputs.daily_effective_workflow_exceeded }} @@ -1227,9 +1179,9 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "Issue 自动分类与回复" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "0.137.0" + GH_AW_INFO_VERSION: "1.0.60" GH_AW_INFO_AWF_VERSION: "v0.27.2" - GH_AW_INFO_ENGINE_ID: "codex" + GH_AW_INFO_ENGINE_ID: "copilot" - name: Check team membership for workflow id: check_membership uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -1261,8 +1213,9 @@ jobs: GH_AW_AMBIENT_CONTEXT: ${{ needs.agent.outputs.ambient_context }} GH_AW_CALLER_WORKFLOW_ID: "${{ github.repository }}/issue-triage" GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens }} - GH_AW_ENGINE_ID: "codex" - GH_AW_ENGINE_MODEL: "doubao-seed-2-0-code-preview-260215" + GH_AW_ENGINE_ID: "copilot" + GH_AW_ENGINE_MODEL: ${{ needs.agent.outputs.model }} + GH_AW_ENGINE_VERSION: "1.0.60" GH_AW_WORKFLOW_ID: "issue-triage" GH_AW_WORKFLOW_NAME: "Issue 自动分类与回复" GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-triage.md" @@ -1287,9 +1240,9 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "Issue 自动分类与回复" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "0.137.0" + GH_AW_INFO_VERSION: "1.0.60" GH_AW_INFO_AWF_VERSION: "v0.27.2" - GH_AW_INFO_ENGINE_ID: "codex" + GH_AW_INFO_ENGINE_ID: "copilot" - name: Download agent output artifact id: download-agent-output continue-on-error: true @@ -1320,7 +1273,7 @@ jobs: 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_ALLOWED_DOMAINS: "172.30.0.1,api.github.com,api.openai.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,chatgpt.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,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,openai.com,packagecloud.io,packages.cloud.google.com,packages.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" + GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,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,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.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},\"add_labels\":{\"allowed\":[\"bug\",\"feature\",\"enhancement\",\"documentation\",\"question\",\"duplicate\",\"invalid\"]},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"report_incomplete\":{}}" diff --git a/.github/workflows/issue-triage.md b/.github/workflows/issue-triage.md index 264acb08..fc53ba22 100644 --- a/.github/workflows/issue-triage.md +++ b/.github/workflows/issue-triage.md @@ -4,15 +4,12 @@ on: types: [opened, reopened] engine: - id: codex + id: copilot env: - OPENAI_BASE_URL: "https://ark.cn-beijing.volces.com/api/v3" - OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - CODEX_MODEL: doubao-seed-2-0-code-preview-260215 - model: doubao-seed-2-0-code-preview-260215 - token-weights: - multipliers: - doubao: 0.5 + COPILOT_PROVIDER_BASE_URL: "https://ark.cn-beijing.volces.com/api/v3" + COPILOT_PROVIDER_API_KEY: ${{ secrets.OPENAI_API_KEY }} + COPILOT_MODEL: doubao-seed-2-0-code-preview-260215 + COPILOT_PROVIDER_TYPE: openai network: allowed: @@ -29,6 +26,7 @@ permissions: issues: read contents: read pull-requests: read + copilot-requests: write safe-outputs: threat-detection: false From a5bee0842a041910491ce90c763e73c3f1ec4c37 Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Tue, 23 Jun 2026 10:44:24 +0800 Subject: [PATCH 37/59] feat: add agentic workflows for issue triage and auto fix --- .github/workflows/issue-triage.lock.yml | 217 ++++++++++++++---------- .github/workflows/issue-triage.md | 15 +- 2 files changed, 142 insertions(+), 90 deletions(-) diff --git a/.github/workflows/issue-triage.lock.yml b/.github/workflows/issue-triage.lock.yml index 1d24f5e1..247c41f5 100644 --- a/.github/workflows/issue-triage.lock.yml +++ b/.github/workflows/issue-triage.lock.yml @@ -1,5 +1,5 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"ec6a9f2b8248fd660c86ffd2700c27809d68642b0f21eeedce74bad9812e7a97","body_hash":"bf4f8784cdac578e246f253a70aa7f7acce80a6fcf1c9116a0f5867b9ece3260","compiler_version":"v0.79.6","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}} -# gh-aw-manifest: {"version":1,"secrets":["GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"5c2fe865bb4dc46e1450f6ee0d0541d759aea73a","version":"v0.79.6"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2","digest":"sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2","digest":"sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2@sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2","digest":"sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2@sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.25","digest":"sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.25@sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa"},{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"e6a07d96980634a1a2111053d5f6c7730d58b061ab526999db283d0bb8e0f78c","body_hash":"bf4f8784cdac578e246f253a70aa7f7acce80a6fcf1c9116a0f5867b9ece3260","compiler_version":"v0.79.6","strict":true,"agent_id":"codex","agent_model":"doubao-seed-2-0-code-preview-260215","engine_versions":{"codex":"0.137.0"}} +# gh-aw-manifest: {"version":1,"secrets":["CODEX_API_KEY","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"5c2fe865bb4dc46e1450f6ee0d0541d759aea73a","version":"v0.79.6"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2","digest":"sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2","digest":"sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2@sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2","digest":"sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2@sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.25","digest":"sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.25@sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa"},{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]} # ___ _ _ # / _ \ | | (_) # | |_| | __ _ ___ _ __ | |_ _ ___ @@ -24,6 +24,7 @@ # # # Secrets used: +# - CODEX_API_KEY # - GH_AW_GITHUB_MCP_SERVER_TOKEN # - GH_AW_GITHUB_TOKEN # - GITHUB_TOKEN @@ -33,6 +34,7 @@ # - actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 # - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 # - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 +# - actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 # - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 # - github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 # @@ -77,6 +79,7 @@ jobs: engine_id: ${{ steps.generate_aw_info.outputs.engine_id }} lockdown_check_failed: ${{ steps.generate_aw_info.outputs.lockdown_check_failed == 'true' }} model: ${{ steps.generate_aw_info.outputs.model }} + secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} 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 }} @@ -96,17 +99,17 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "Issue 自动分类与回复" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_VERSION: "0.137.0" GH_AW_INFO_AWF_VERSION: "v0.27.2" - GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_INFO_ENGINE_ID: "codex" - name: Generate agentic run info id: generate_aw_info env: - GH_AW_INFO_ENGINE_ID: "copilot" - GH_AW_INFO_ENGINE_NAME: "GitHub Copilot CLI" - GH_AW_INFO_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || vars.GH_AW_DEFAULT_MODEL_COPILOT || 'claude-sonnet-4.6' }} - GH_AW_INFO_VERSION: "1.0.60" - GH_AW_INFO_AGENT_VERSION: "1.0.60" + GH_AW_INFO_ENGINE_ID: "codex" + GH_AW_INFO_ENGINE_NAME: "Codex" + GH_AW_INFO_MODEL: "doubao-seed-2-0-code-preview-260215" + GH_AW_INFO_VERSION: "0.137.0" + GH_AW_INFO_AGENT_VERSION: "0.137.0" GH_AW_INFO_CLI_VERSION: "v0.79.6" GH_AW_INFO_WORKFLOW_NAME: "Issue 自动分类与回复" GH_AW_INFO_EXPERIMENTAL: "false" @@ -118,6 +121,7 @@ jobs: GH_AW_INFO_AWMG_VERSION: "" GH_AW_INFO_FIREWALL_TYPE: "squid" GH_AW_COMPILED_STRICT: "true" + GH_AW_INFO_TOKEN_WEIGHTS: '{"multipliers":{"doubao":1}}' uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | @@ -143,6 +147,12 @@ jobs: setupGlobals(core, github, context, exec, io, getOctokit); const { main } = require('${{ runner.temp }}/gh-aw/actions/check_daily_aic_workflow_guardrail.cjs'); await main(); + - name: Validate CODEX_API_KEY or OPENAI_API_KEY secret + id: validate-secret + run: bash "${RUNNER_TEMP}/gh-aw/actions/validate_multi_secret.sh" CODEX_API_KEY OPENAI_API_KEY Codex https://github.github.com/gh-aw/reference/engines/#openai-codex + env: + CODEX_API_KEY: ${{ secrets.CODEX_API_KEY }} + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - name: Checkout .github and .agents folders uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: @@ -191,7 +201,7 @@ jobs: id: sanitized uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: - GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,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,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" + GH_AW_ALLOWED_DOMAINS: "172.30.0.1,api.github.com,api.openai.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,chatgpt.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,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,openai.com,packagecloud.io,packages.cloud.google.com,packages.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 { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); @@ -267,7 +277,7 @@ jobs: uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GH_AW_ENGINE_ID: "copilot" + GH_AW_ENGINE_ID: "codex" GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} with: script: | @@ -337,8 +347,8 @@ jobs: /tmp/gh-aw/aw-prompts/prompt-import-tree.json /tmp/gh-aw/github_rate_limits.jsonl /tmp/gh-aw/base - /tmp/gh-aw/.github/agents - /tmp/gh-aw/.github/skills + /tmp/gh-aw/.codex/agents + /tmp/gh-aw/.codex/skills if-no-files-found: ignore retention-days: 1 @@ -388,9 +398,9 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "Issue 自动分类与回复" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_VERSION: "0.137.0" GH_AW_INFO_AWF_VERSION: "v0.27.2" - GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_INFO_ENGINE_ID: "codex" - name: Set runtime paths id: set-runtime-paths run: | @@ -436,10 +446,13 @@ jobs: setupGlobals(core, github, context, exec, io, getOctokit); const { main } = require('${{ runner.temp }}/gh-aw/actions/checkout_pr_branch.cjs'); await main(); - - name: Install GitHub Copilot CLI - run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.60 - env: - GH_HOST: github.com + - name: Setup Node.js + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + with: + node-version: '24' + package-manager-cache: false + - name: Install Codex CLI + run: npm install --ignore-scripts -g @openai/codex@0.137.0 - name: Install AWF binary run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.27.2 - name: Parse integrity filter lists @@ -462,12 +475,12 @@ jobs: 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: ".github/agents" - GH_AW_SUB_AGENT_EXT: ".agent.md" + 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: ".github/skills" + GH_AW_SKILL_DIR: ".codex/skills" run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_inline_skills.sh" - name: Download container images run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6 ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2@sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4 ghcr.io/github/gh-aw-firewall/squid:0.27.2@sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591 ghcr.io/github/gh-aw-mcpg:v0.3.25@sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c @@ -657,6 +670,7 @@ jobs: - name: Start MCP Gateway id: start-mcp-gateway env: + CODEX_HOME: /tmp/gh-aw/mcp-config GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-start.outputs.api_key }} GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-start.outputs.port }} @@ -677,7 +691,7 @@ jobs: export MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD="524288" export DEBUG="*" - export GH_AW_ENGINE="copilot" + export GH_AW_ENGINE="codex" MCP_GATEWAY_UID=$(id -u 2>/dev/null || echo '0') MCP_GATEWAY_GID=$(id -g 2>/dev/null || echo '0') case "${DOCKER_HOST:-}" in @@ -686,19 +700,47 @@ jobs: * ) DOCKER_SOCK_PATH=/var/run/docker.sock ;; esac DOCKER_SOCK_GID=$(stat -c '%g' "$DOCKER_SOCK_PATH" 2>/dev/null || echo '0') - export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --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_API_KEY -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_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.3.25' + export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --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_API_KEY -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_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -e CODEX_HOME -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.3.25' + + cat > "${RUNNER_TEMP}/gh-aw/mcp-config/config.toml" << GH_AW_MCP_CONFIG_d9dc58ce079498af_EOF + [history] + persistence = "none" + + [shell_environment_policy] + inherit = "core" + include_only = ["^CODEX_API_KEY$", "^GH_AW_ASSETS_ALLOWED_EXTS$", "^GH_AW_ASSETS_BRANCH$", "^GH_AW_ASSETS_MAX_SIZE_KB$", "^GH_AW_SAFE_OUTPUTS$", "^GITHUB_PERSONAL_ACCESS_TOKEN$", "^GITHUB_REPOSITORY$", "^GITHUB_SERVER_URL$", "^HOME$", "^OPENAI_API_KEY$", "^PATH$"] + + [mcp_servers.github] + user_agent = "issue" + startup_timeout_sec = 120 + tool_timeout_sec = 60 + container = "ghcr.io/github/github-mcp-server:v1.1.2" + env = { "GITHUB_HOST" = "$GITHUB_SERVER_URL", "GITHUB_PERSONAL_ACCESS_TOKEN" = "$GH_AW_GITHUB_TOKEN", "GITHUB_READ_ONLY" = "1", "GITHUB_TOOLSETS" = "context,repos,issues,pull_requests" } + env_vars = ["GITHUB_HOST", "GITHUB_PERSONAL_ACCESS_TOKEN", "GITHUB_READ_ONLY", "GITHUB_TOOLSETS"] + + [mcp_servers.safeoutputs] + type = "http" + url = "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT" + + [mcp_servers.safeoutputs.headers] + Authorization = "$GH_AW_SAFE_OUTPUTS_API_KEY" + + [mcp_servers.safeoutputs."guard-policies"] - mkdir -p /home/runner/.copilot + [mcp_servers.safeoutputs."guard-policies".write-sink] + accept = ["*"] + GH_AW_MCP_CONFIG_d9dc58ce079498af_EOF + + # 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_920bb1916fcb7fc4_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_ca772287f17ffc28_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "github": { - "type": "stdio", "container": "ghcr.io/github/github-mcp-server:v1.1.2", "env": { - "GITHUB_HOST": "\${GITHUB_SERVER_URL}", - "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}", + "GITHUB_HOST": "$GITHUB_SERVER_URL", + "GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_MCP_SERVER_TOKEN", "GITHUB_READ_ONLY": "1", "GITHUB_TOOLSETS": "context,repos,issues,pull_requests" }, @@ -716,7 +758,7 @@ jobs: "type": "http", "url": "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT", "headers": { - "Authorization": "\${GH_AW_SAFE_OUTPUTS_API_KEY}" + "Authorization": "$GH_AW_SAFE_OUTPUTS_API_KEY" }, "guard-policies": { "write-sink": { @@ -734,7 +776,34 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_920bb1916fcb7fc4_EOF + GH_AW_MCP_CONFIG_ca772287f17ffc28_EOF + + # Sync converter output to writable CODEX_HOME for Codex + mkdir -p /tmp/gh-aw/mcp-config + cat > "/tmp/gh-aw/mcp-config/config.toml" << GH_AW_CODEX_SHELL_POLICY_929fca99db4cd5ec_EOF + + model_provider = "openai-proxy" + + [model_providers.openai-proxy] + name = "OpenAI AWF proxy" + base_url = "http://172.30.0.30:10000" + env_key = "OPENAI_API_KEY" + supports_websockets = false + [shell_environment_policy] + inherit = "core" + include_only = ["^CODEX_API_KEY$", "^GH_AW_ASSETS_ALLOWED_EXTS$", "^GH_AW_ASSETS_BRANCH$", "^GH_AW_ASSETS_MAX_SIZE_KB$", "^GH_AW_SAFE_OUTPUTS$", "^GITHUB_PERSONAL_ACCESS_TOKEN$", "^GITHUB_REPOSITORY$", "^GITHUB_SERVER_URL$", "^HOME$", "^OPENAI_API_KEY$", "^PATH$"] + GH_AW_CODEX_SHELL_POLICY_929fca99db4cd5ec_EOF + awk ' + BEGIN { skip_openai_proxy = 0 } + /^[[:space:]]*model_provider[[:space:]]*=/ { next } + /^\[model_providers\.openai-proxy\][[:space:]]*$/ { skip_openai_proxy = 1; next } + /^\[/ { skip_openai_proxy = 0 } + !skip_openai_proxy { print } + ' "${RUNNER_TEMP}/gh-aw/mcp-config/config.toml" >> "/tmp/gh-aw/mcp-config/config.toml" + chmod 600 "/tmp/gh-aw/mcp-config/config.toml" + mkdir -p "${CODEX_HOME}" + if [ "/tmp/gh-aw/mcp-config/config.toml" != "${CODEX_HOME}/config.toml" ]; then cp "/tmp/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 @@ -756,23 +825,14 @@ jobs: id: pre_agent_audit continue-on-error: true run: bash "${RUNNER_TEMP}/gh-aw/actions/audit_pre_agent_workspace.sh" - - name: Execute GitHub Copilot CLI + - name: Execute Codex CLI id: agentic_execution - # Copilot CLI tool arguments (sorted): - timeout-minutes: 20 run: | set -o pipefail printf '%s' "$(date +%s%3N)" > /tmp/gh-aw/agent_cli_start_ms.txt - trap 'rm -f /home/runner/.copilot/settings.json' EXIT - mkdir -p /home/runner/.copilot - printf '%s' '{"builtInAgents":{"rubberDuck":false}}' > /home/runner/.copilot/settings.json - touch /tmp/gh-aw/agent-step-summary.md - GH_AW_NODE_BIN=$(command -v node 2>/dev/null || true) - export GH_AW_NODE_BIN - export COPILOT_API_KEY="$COPILOT_DUMMY_BYOK" + 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="${{ vars.GH_AW_DEFAULT_MAX_AI_CREDITS || '1000' }}" - printf '%s\n' "{\"\$schema\":\"https://github.com/github/gh-aw-firewall/releases/download/v0.27.2/awf-config.schema.json\",\"network\":{\"allowDomains\":[\"api.business.githubcopilot.com\",\"api.enterprise.githubcopilot.com\",\"api.github.com\",\"api.githubcopilot.com\",\"api.individual.githubcopilot.com\",\"api.snapcraft.io\",\"archive.ubuntu.com\",\"ark.cn-beijing.volces.com\",\"azure.archive.ubuntu.com\",\"crl.geotrust.com\",\"crl.globalsign.com\",\"crl.identrust.com\",\"crl.sectigo.com\",\"crl.thawte.com\",\"crl.usertrust.com\",\"crl.verisign.com\",\"crl3.digicert.com\",\"crl4.digicert.com\",\"crls.ssl.com\",\"github.com\",\"host.docker.internal\",\"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\",\"ppa.launchpad.net\",\"raw.githubusercontent.com\",\"registry.npmjs.org\",\"s.symcb.com\",\"s.symcd.com\",\"security.ubuntu.com\",\"telemetry.enterprise.githubcopilot.com\",\"ts-crl.ws.symantec.com\",\"ts-ocsp.ws.symantec.com\",\"www.googleapis.com\"]},\"apiProxy\":{\"enabled\":true,\"enableTokenSteering\":true,\"maxRuns\":500,\"maxAiCredits\":${GH_AW_MAX_AI_CREDITS},\"models\":{\"agent\":[\"sonnet-6x\",\"gpt-5.4\",\"gpt-5.3\",\"gemini-pro\",\"any\"],\"antigravity\":[\"copilot/antigravity*\",\"google/antigravity*\",\"gemini/antigravity*\"],\"any\":[\"copilot/*\",\"anthropic/*\",\"openai/*\",\"google/*\",\"gemini/*\"],\"claude\":[\"agent\"],\"codex\":[\"agent\"],\"coding\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\",\"gpt-5-codex\"],\"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*\"],\"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-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-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.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*\"],\"haiku\":[\"copilot/*haiku*\",\"anthropic/*haiku*\"],\"large\":[\"sonnet\",\"gpt-5-pro\",\"gpt-5\",\"gemini-pro\"],\"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\"],\"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-4-5-*\",\"anthropic/*sonnet-4-5-*\",\"copilot/*sonnet-4-6*\",\"anthropic/*sonnet-4-6*\"],\"summarization\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash-lite\",\"mini\"],\"vision\":[\"copilot/gemini-*image*\",\"gemini/gemini-*image*\",\"copilot/gemini-*flash*\",\"gemini/gemini-*flash*\"]}},\"container\":{\"imageTag\":\"0.27.2,squid=sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591,agent=sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6,api-proxy=sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4,cli-proxy=sha256:02f3ec08f32dc26c5427920c6a2e2f3036238fce44802f2f11ef49ed8621b5d0\"}}" > "${RUNNER_TEMP}/gh-aw/awf-config.json" + printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.27.2/awf-config.schema.json","network":{"allowDomains":["172.30.0.1","api.github.com","api.openai.com","api.snapcraft.io","archive.ubuntu.com","ark.cn-beijing.volces.com","azure.archive.ubuntu.com","chatgpt.com","crl.geotrust.com","crl.globalsign.com","crl.identrust.com","crl.sectigo.com","crl.thawte.com","crl.usertrust.com","crl.verisign.com","crl3.digicert.com","crl4.digicert.com","crls.ssl.com","github.com","host.docker.internal","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","openai.com","packagecloud.io","packages.cloud.google.com","packages.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"]},"apiProxy":{"enabled":true,"maxRuns":500,"targets":{"openai":{"host":"ark.cn-beijing.volces.com"}},"models":{"agent":["sonnet-6x","gpt-5.4","gpt-5.3","gemini-pro","any"],"antigravity":["copilot/antigravity*","google/antigravity*","gemini/antigravity*"],"any":["copilot/*","anthropic/*","openai/*","google/*","gemini/*"],"claude":["agent"],"codex":["agent"],"coding":["copilot/gpt-5*codex*","openai/gpt-5*codex*","gpt-5-codex"],"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*"],"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-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-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.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*"],"haiku":["copilot/*haiku*","anthropic/*haiku*"],"large":["sonnet","gpt-5-pro","gpt-5","gemini-pro"],"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"],"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-4-5-*","anthropic/*sonnet-4-5-*","copilot/*sonnet-4-6*","anthropic/*sonnet-4-6*"],"summarization":["haiku","gpt-5-mini","gemini-flash-lite","mini"],"vision":["copilot/gemini-*image*","gemini/gemini-*image*","copilot/gemini-*flash*","gemini/gemini-*flash*"]}},"container":{"imageTag":"0.27.2,squid=sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591,agent=sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6,api-proxy=sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4,cli-proxy=sha256:02f3ec08f32dc26c5427920c6a2e2f3036238fce44802f2f11ef49ed8621b5d0"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json" GH_AW_MODEL_MULTIPLIERS_PATH="/tmp/gh-aw/model_multipliers.json" node "${RUNNER_TEMP}/gh-aw/actions/merge_awf_model_multipliers.cjs" 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" @@ -790,39 +850,29 @@ jobs: GH_AW_TOOL_CACHE_MOUNT="/home/runner/work/_tool:/home/runner/work/_tool:ro" fi # shellcheck disable=SC1003 - sudo -E 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_PATH_PREFIX_ARGS} --env-all --exclude-env COPILOT_PROVIDER_API_KEY --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull \ - -- /bin/bash -c 'set +o histexpand; export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && GH_AW_TOOL_CACHE="${RUNNER_TOOL_CACHE:-/opt/hostedtoolcache}"; export PATH="$(find "$GH_AW_TOOL_CACHE" /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 5 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/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/copilot_harness.cjs /usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-all-tools --allow-all-paths --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + sudo -E 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_PATH_PREFIX_ARGS} --env-all --exclude-env CODEX_API_KEY --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --exclude-env OPENAI_API_KEY --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull --openai-api-base-path /api/v3 \ + -- /bin/bash -c 'set +o histexpand; export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && GH_AW_TOOL_CACHE="${RUNNER_TOOL_CACHE:-/opt/hostedtoolcache}"; export PATH="$(find "$GH_AW_TOOL_CACHE" /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 5 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/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" -c fetch="disabled" --dangerously-bypass-approvals-and-sandbox --skip-git-repo-check --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log env: - AWF_REFLECT_ENABLED: 1 - COPILOT_AGENT_RUNNER_TYPE: STANDALONE - COPILOT_DUMMY_BYOK: dummy-byok-key-for-offline-mode - COPILOT_MODEL: doubao-seed-2-0-code-preview-260215 - COPILOT_PROVIDER_API_KEY: ${{ secrets.OPENAI_API_KEY }} - COPILOT_PROVIDER_BASE_URL: https://ark.cn-beijing.volces.com/api/v3 - COPILOT_PROVIDER_TYPE: openai + CODEX_API_KEY: ${{ secrets.CODEX_API_KEY || secrets.OPENAI_API_KEY }} + CODEX_HOME: /tmp/gh-aw/mcp-config + CODEX_MODEL: doubao-seed-2-0-code-preview-260215 GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }} - GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json + GH_AW_MCP_CONFIG: ${{ runner.temp }}/gh-aw/mcp-config/config.toml + GH_AW_MODEL_AGENT_CODEX: doubao-seed-2-0-code-preview-260215 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_TIMEOUT_MINUTES: 20 GH_AW_VERSION: v0.79.6 - GITHUB_API_URL: ${{ github.api_url }} GITHUB_AW: true - GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows - GITHUB_HEAD_REF: ${{ github.head_ref }} - GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - 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] + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + OPENAI_BASE_URL: https://ark.cn-beijing.volces.com/api/v3 RUNNER_TEMP: ${{ runner.temp }} - S2STOKENS: true - XDG_CONFIG_HOME: /home/runner + RUST_LOG: ${{ runner.debug == 1 && 'trace,hyper_util=info,mio=info,reqwest=info,os_info=info,codex_otel=warn,codex_core=debug,ocodex_exec=debug' || 'warn' }} - name: Detect agent errors if: always() id: detect-agent-errors @@ -841,10 +891,6 @@ jobs: SERVER_URL_STRIPPED="${SERVER_URL#https://}" git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" echo "Git configured with standard GitHub Actions identity" - - name: Copy Copilot session state files to logs - if: always() - continue-on-error: true - run: bash "${RUNNER_TEMP}/gh-aw/actions/copy_copilot_session_state.sh" - name: Stop MCP Gateway if: always() continue-on-error: true @@ -864,7 +910,8 @@ jobs: const { main } = require('${{ runner.temp }}/gh-aw/actions/redact_secrets.cjs'); await main(); env: - GH_AW_SECRET_NAMES: 'GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN,OPENAI_API_KEY' + GH_AW_SECRET_NAMES: 'CODEX_API_KEY,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN,OPENAI_API_KEY' + SECRET_CODEX_API_KEY: ${{ secrets.CODEX_API_KEY }} SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -885,7 +932,7 @@ jobs: 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: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,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,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" + GH_AW_ALLOWED_DOMAINS: "172.30.0.1,api.github.com,api.openai.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,chatgpt.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,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,openai.com,packagecloud.io,packages.cloud.google.com,packages.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 }} with: @@ -898,12 +945,12 @@ jobs: if: always() uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: - GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/ + GH_AW_AGENT_OUTPUT: /tmp/gh-aw/agent-stdio.log with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_copilot_log.cjs'); + const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_codex_log.cjs'); await main(); - name: Parse MCP Gateway logs for step summary if: always() @@ -964,7 +1011,7 @@ jobs: name: agent path: | /tmp/gh-aw/aw-prompts/prompt.txt - /tmp/gh-aw/sandbox/agent/logs/ + /tmp/gh-aw/mcp-config/logs/ /tmp/gh-aw/redacted-urls.log /tmp/gh-aw/mcp-logs/ /tmp/gh-aw/proxy-logs/ @@ -1017,9 +1064,9 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "Issue 自动分类与回复" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_VERSION: "0.137.0" GH_AW_INFO_AWF_VERSION: "v0.27.2" - GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_INFO_ENGINE_ID: "codex" - name: Download agent output artifact id: download-agent-output continue-on-error: true @@ -1131,18 +1178,19 @@ jobs: GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} GH_AW_WORKFLOW_ID: "issue-triage" GH_AW_ACTION_FAILURE_ISSUE_EXPIRES_HOURS: "168" - GH_AW_ENGINE_ID: "copilot" + 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_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens || '' }} 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_MAX_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_MAX_AI_CREDITS || '1000' }} + GH_AW_MAX_AI_CREDITS: "-1" 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_ENGINE_API_HOSTS: "api.enterprise.githubcopilot.com,api.githubcopilot.com,api.business.githubcopilot.com,api.individual.githubcopilot.com" + GH_AW_ENGINE_API_HOSTS: "api.openai.com" GH_AW_LOCKDOWN_CHECK_FAILED: ${{ needs.activation.outputs.lockdown_check_failed }} GH_AW_STALE_LOCK_FILE_FAILED: ${{ needs.activation.outputs.stale_lock_file_failed }} GH_AW_DAILY_EFFECTIVE_WORKFLOW_EXCEEDED: ${{ needs.activation.outputs.daily_effective_workflow_exceeded }} @@ -1179,9 +1227,9 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "Issue 自动分类与回复" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_VERSION: "0.137.0" GH_AW_INFO_AWF_VERSION: "v0.27.2" - GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_INFO_ENGINE_ID: "codex" - name: Check team membership for workflow id: check_membership uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -1213,9 +1261,8 @@ jobs: GH_AW_AMBIENT_CONTEXT: ${{ needs.agent.outputs.ambient_context }} GH_AW_CALLER_WORKFLOW_ID: "${{ github.repository }}/issue-triage" GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens }} - GH_AW_ENGINE_ID: "copilot" - GH_AW_ENGINE_MODEL: ${{ needs.agent.outputs.model }} - GH_AW_ENGINE_VERSION: "1.0.60" + GH_AW_ENGINE_ID: "codex" + GH_AW_ENGINE_MODEL: "doubao-seed-2-0-code-preview-260215" GH_AW_WORKFLOW_ID: "issue-triage" GH_AW_WORKFLOW_NAME: "Issue 自动分类与回复" GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-triage.md" @@ -1240,9 +1287,9 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "Issue 自动分类与回复" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_VERSION: "0.137.0" GH_AW_INFO_AWF_VERSION: "v0.27.2" - GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_INFO_ENGINE_ID: "codex" - name: Download agent output artifact id: download-agent-output continue-on-error: true @@ -1273,7 +1320,7 @@ jobs: 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_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,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,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" + GH_AW_ALLOWED_DOMAINS: "172.30.0.1,api.github.com,api.openai.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,chatgpt.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,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,openai.com,packagecloud.io,packages.cloud.google.com,packages.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},\"add_labels\":{\"allowed\":[\"bug\",\"feature\",\"enhancement\",\"documentation\",\"question\",\"duplicate\",\"invalid\"]},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"report_incomplete\":{}}" diff --git a/.github/workflows/issue-triage.md b/.github/workflows/issue-triage.md index fc53ba22..48a54a26 100644 --- a/.github/workflows/issue-triage.md +++ b/.github/workflows/issue-triage.md @@ -4,12 +4,17 @@ on: types: [opened, reopened] engine: - id: copilot + id: codex env: - COPILOT_PROVIDER_BASE_URL: "https://ark.cn-beijing.volces.com/api/v3" - COPILOT_PROVIDER_API_KEY: ${{ secrets.OPENAI_API_KEY }} - COPILOT_MODEL: doubao-seed-2-0-code-preview-260215 - COPILOT_PROVIDER_TYPE: openai + OPENAI_BASE_URL: "https://ark.cn-beijing.volces.com/api/v3" + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + CODEX_MODEL: doubao-seed-2-0-code-preview-260215 + model: doubao-seed-2-0-code-preview-260215 + token-weights: + multipliers: + doubao: 1.0 + +max-ai-credits: -1 network: allowed: From 0cfcf4875db960431ec41eec9b53a564c5e4d206 Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Tue, 23 Jun 2026 11:22:44 +0800 Subject: [PATCH 38/59] feat: add agentic workflows for issue triage and auto fix --- .github/workflows/issue-triage.lock.yml | 129 ++++-------------------- .github/workflows/issue-triage.md | 8 +- 2 files changed, 28 insertions(+), 109 deletions(-) diff --git a/.github/workflows/issue-triage.lock.yml b/.github/workflows/issue-triage.lock.yml index 247c41f5..4169d09f 100644 --- a/.github/workflows/issue-triage.lock.yml +++ b/.github/workflows/issue-triage.lock.yml @@ -1,5 +1,5 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"e6a07d96980634a1a2111053d5f6c7730d58b061ab526999db283d0bb8e0f78c","body_hash":"bf4f8784cdac578e246f253a70aa7f7acce80a6fcf1c9116a0f5867b9ece3260","compiler_version":"v0.79.6","strict":true,"agent_id":"codex","agent_model":"doubao-seed-2-0-code-preview-260215","engine_versions":{"codex":"0.137.0"}} -# gh-aw-manifest: {"version":1,"secrets":["CODEX_API_KEY","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"5c2fe865bb4dc46e1450f6ee0d0541d759aea73a","version":"v0.79.6"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2","digest":"sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2","digest":"sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2@sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2","digest":"sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2@sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.25","digest":"sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.25@sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa"},{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"4eba86fa909777f0a6038b0e48c6c9be43657266fd1eef63de8afb40e77b0023","body_hash":"bf4f8784cdac578e246f253a70aa7f7acce80a6fcf1c9116a0f5867b9ece3260","compiler_version":"v0.79.6","agent_id":"codex","agent_model":"doubao-seed-2-0-code-preview-260215","engine_versions":{"codex":"0.137.0"}} +# gh-aw-manifest: {"version":1,"secrets":["CODEX_API_KEY","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"5c2fe865bb4dc46e1450f6ee0d0541d759aea73a","version":"v0.79.6"}],"containers":[{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]} # ___ _ _ # / _ \ | | (_) # | |_| | __ _ ___ _ __ | |_ _ ___ @@ -39,10 +39,6 @@ # - github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 # # Container images used: -# - ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6 -# - ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2@sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4 -# - ghcr.io/github/gh-aw-firewall/squid:0.27.2@sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591 -# - ghcr.io/github/gh-aw-mcpg:v0.3.25@sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa # - ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c name: "Issue 自动分类与回复" @@ -100,7 +96,6 @@ jobs: GH_AW_SETUP_WORKFLOW_NAME: "Issue 自动分类与回复" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }} GH_AW_INFO_VERSION: "0.137.0" - GH_AW_INFO_AWF_VERSION: "v0.27.2" GH_AW_INFO_ENGINE_ID: "codex" - name: Generate agentic run info id: generate_aw_info @@ -116,11 +111,11 @@ jobs: GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true" GH_AW_INFO_STAGED: "false" GH_AW_INFO_ALLOWED_DOMAINS: '["defaults","ark.cn-beijing.volces.com","github.com","api.github.com"]' - GH_AW_INFO_FIREWALL_ENABLED: "true" - GH_AW_INFO_AWF_VERSION: "v0.27.2" + GH_AW_INFO_FIREWALL_ENABLED: "false" + GH_AW_INFO_AWF_VERSION: "" GH_AW_INFO_AWMG_VERSION: "" - GH_AW_INFO_FIREWALL_TYPE: "squid" - GH_AW_COMPILED_STRICT: "true" + GH_AW_INFO_FIREWALL_TYPE: "" + GH_AW_COMPILED_STRICT: "false" GH_AW_INFO_TOKEN_WEIGHTS: '{"multipliers":{"doubao":1}}' uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: @@ -399,7 +394,6 @@ jobs: GH_AW_SETUP_WORKFLOW_NAME: "Issue 自动分类与回复" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }} GH_AW_INFO_VERSION: "0.137.0" - GH_AW_INFO_AWF_VERSION: "v0.27.2" GH_AW_INFO_ENGINE_ID: "codex" - name: Set runtime paths id: set-runtime-paths @@ -453,8 +447,6 @@ jobs: package-manager-cache: false - name: Install Codex CLI run: npm install --ignore-scripts -g @openai/codex@0.137.0 - - name: Install AWF binary - run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.27.2 - name: Parse integrity filter lists id: parse-guard-vars env: @@ -483,7 +475,7 @@ jobs: GH_AW_SKILL_DIR: ".codex/skills" run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_inline_skills.sh" - name: Download container images - run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6 ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2@sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4 ghcr.io/github/gh-aw-firewall/squid:0.27.2@sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591 ghcr.io/github/gh-aw-mcpg:v0.3.25@sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c + run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c - name: Generate Safe Outputs Config run: | mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" @@ -681,7 +673,7 @@ jobs: # Export gateway environment variables for MCP config and gateway script export MCP_GATEWAY_PORT="8080" - export MCP_GATEWAY_DOMAIN="host.docker.internal" + export MCP_GATEWAY_DOMAIN="localhost" export MCP_GATEWAY_HOST_DOMAIN="localhost" MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=') echo "::add-mask::${MCP_GATEWAY_API_KEY}" @@ -702,7 +694,7 @@ jobs: DOCKER_SOCK_GID=$(stat -c '%g' "$DOCKER_SOCK_PATH" 2>/dev/null || echo '0') export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --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_API_KEY -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_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -e CODEX_HOME -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.3.25' - cat > "${RUNNER_TEMP}/gh-aw/mcp-config/config.toml" << GH_AW_MCP_CONFIG_d9dc58ce079498af_EOF + cat > "${RUNNER_TEMP}/gh-aw/mcp-config/config.toml" << GH_AW_MCP_CONFIG_7602cb776b25e54a_EOF [history] persistence = "none" @@ -720,7 +712,7 @@ jobs: [mcp_servers.safeoutputs] type = "http" - url = "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT" + url = "http://localhost:$GH_AW_SAFE_OUTPUTS_PORT" [mcp_servers.safeoutputs.headers] Authorization = "$GH_AW_SAFE_OUTPUTS_API_KEY" @@ -729,11 +721,11 @@ jobs: [mcp_servers.safeoutputs."guard-policies".write-sink] accept = ["*"] - GH_AW_MCP_CONFIG_d9dc58ce079498af_EOF + GH_AW_MCP_CONFIG_7602cb776b25e54a_EOF # 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_ca772287f17ffc28_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_bb2cc39de9e76341_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "github": { @@ -756,7 +748,7 @@ jobs: }, "safeoutputs": { "type": "http", - "url": "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT", + "url": "http://localhost:$GH_AW_SAFE_OUTPUTS_PORT", "headers": { "Authorization": "$GH_AW_SAFE_OUTPUTS_API_KEY" }, @@ -776,30 +768,16 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_ca772287f17ffc28_EOF + GH_AW_MCP_CONFIG_bb2cc39de9e76341_EOF # Sync converter output to writable CODEX_HOME for Codex mkdir -p /tmp/gh-aw/mcp-config - cat > "/tmp/gh-aw/mcp-config/config.toml" << GH_AW_CODEX_SHELL_POLICY_929fca99db4cd5ec_EOF - - model_provider = "openai-proxy" - - [model_providers.openai-proxy] - name = "OpenAI AWF proxy" - base_url = "http://172.30.0.30:10000" - env_key = "OPENAI_API_KEY" - supports_websockets = false + cat > "/tmp/gh-aw/mcp-config/config.toml" << GH_AW_CODEX_SHELL_POLICY_eead21463895a36c_EOF [shell_environment_policy] inherit = "core" include_only = ["^CODEX_API_KEY$", "^GH_AW_ASSETS_ALLOWED_EXTS$", "^GH_AW_ASSETS_BRANCH$", "^GH_AW_ASSETS_MAX_SIZE_KB$", "^GH_AW_SAFE_OUTPUTS$", "^GITHUB_PERSONAL_ACCESS_TOKEN$", "^GITHUB_REPOSITORY$", "^GITHUB_SERVER_URL$", "^HOME$", "^OPENAI_API_KEY$", "^PATH$"] - GH_AW_CODEX_SHELL_POLICY_929fca99db4cd5ec_EOF - awk ' - BEGIN { skip_openai_proxy = 0 } - /^[[:space:]]*model_provider[[:space:]]*=/ { next } - /^\[model_providers\.openai-proxy\][[:space:]]*$/ { skip_openai_proxy = 1; next } - /^\[/ { skip_openai_proxy = 0 } - !skip_openai_proxy { print } - ' "${RUNNER_TEMP}/gh-aw/mcp-config/config.toml" >> "/tmp/gh-aw/mcp-config/config.toml" + GH_AW_CODEX_SHELL_POLICY_eead21463895a36c_EOF + cat "${RUNNER_TEMP}/gh-aw/mcp-config/config.toml" >> "/tmp/gh-aw/mcp-config/config.toml" chmod 600 "/tmp/gh-aw/mcp-config/config.toml" mkdir -p "${CODEX_HOME}" if [ "/tmp/gh-aw/mcp-config/config.toml" != "${CODEX_HOME}/config.toml" ]; then cp "/tmp/gh-aw/mcp-config/config.toml" "${CODEX_HOME}/config.toml"; fi @@ -830,28 +808,10 @@ jobs: run: | set -o pipefail 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 + touch /tmp/gh-aw/agent-step-summary.md (umask 177 && touch /tmp/gh-aw/agent-stdio.log) - printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.27.2/awf-config.schema.json","network":{"allowDomains":["172.30.0.1","api.github.com","api.openai.com","api.snapcraft.io","archive.ubuntu.com","ark.cn-beijing.volces.com","azure.archive.ubuntu.com","chatgpt.com","crl.geotrust.com","crl.globalsign.com","crl.identrust.com","crl.sectigo.com","crl.thawte.com","crl.usertrust.com","crl.verisign.com","crl3.digicert.com","crl4.digicert.com","crls.ssl.com","github.com","host.docker.internal","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","openai.com","packagecloud.io","packages.cloud.google.com","packages.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"]},"apiProxy":{"enabled":true,"maxRuns":500,"targets":{"openai":{"host":"ark.cn-beijing.volces.com"}},"models":{"agent":["sonnet-6x","gpt-5.4","gpt-5.3","gemini-pro","any"],"antigravity":["copilot/antigravity*","google/antigravity*","gemini/antigravity*"],"any":["copilot/*","anthropic/*","openai/*","google/*","gemini/*"],"claude":["agent"],"codex":["agent"],"coding":["copilot/gpt-5*codex*","openai/gpt-5*codex*","gpt-5-codex"],"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*"],"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-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-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.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*"],"haiku":["copilot/*haiku*","anthropic/*haiku*"],"large":["sonnet","gpt-5-pro","gpt-5","gemini-pro"],"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"],"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-4-5-*","anthropic/*sonnet-4-5-*","copilot/*sonnet-4-6*","anthropic/*sonnet-4-6*"],"summarization":["haiku","gpt-5-mini","gemini-flash-lite","mini"],"vision":["copilot/gemini-*image*","gemini/gemini-*image*","copilot/gemini-*flash*","gemini/gemini-*flash*"]}},"container":{"imageTag":"0.27.2,squid=sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591,agent=sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6,api-proxy=sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4,cli-proxy=sha256:02f3ec08f32dc26c5427920c6a2e2f3036238fce44802f2f11ef49ed8621b5d0"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json" - GH_AW_MODEL_MULTIPLIERS_PATH="/tmp/gh-aw/model_multipliers.json" node "${RUNNER_TEMP}/gh-aw/actions/merge_awf_model_multipliers.cjs" - 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_PATH_PREFIX_ARGS="" - if [[ "${DOCKER_HOST:-}" =~ ^tcp:// ]]; then - GH_AW_DOCKER_HOST_PATH_PREFIX_ARGS="--docker-host-path-prefix /tmp/gh-aw" - fi - GH_AW_TOOL_CACHE_MOUNT="" - GH_AW_TOOL_CACHE="${RUNNER_TOOL_CACHE:-/opt/hostedtoolcache}" - 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 - elif [ -d "/home/runner/work/_tool" ]; then - GH_AW_TOOL_CACHE_MOUNT="/home/runner/work/_tool:/home/runner/work/_tool:ro" - fi - # shellcheck disable=SC1003 - sudo -E 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_PATH_PREFIX_ARGS} --env-all --exclude-env CODEX_API_KEY --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --exclude-env OPENAI_API_KEY --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull --openai-api-base-path /api/v3 \ - -- /bin/bash -c 'set +o histexpand; export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && GH_AW_TOOL_CACHE="${RUNNER_TOOL_CACHE:-/opt/hostedtoolcache}"; export PATH="$(find "$GH_AW_TOOL_CACHE" /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 5 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/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" -c fetch="disabled" --dangerously-bypass-approvals-and-sandbox --skip-git-repo-check --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + mkdir -p "$CODEX_HOME/logs" + 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" -c fetch="disabled" --sandbox workspace-write --skip-git-repo-check -c approval_policy="never" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt 2>&1 | tee /tmp/gh-aw/agent-stdio.log env: CODEX_API_KEY: ${{ secrets.CODEX_API_KEY || secrets.OPENAI_API_KEY }} CODEX_HOME: /tmp/gh-aw/mcp-config @@ -865,12 +825,8 @@ jobs: GH_AW_VERSION: v0.79.6 GITHUB_AW: true GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md - GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com - GIT_AUTHOR_NAME: github-actions[bot] - GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com - GIT_COMMITTER_NAME: github-actions[bot] OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - OPENAI_BASE_URL: https://ark.cn-beijing.volces.com/api/v3 + OPENAI_BASE_URL: https://ark.cn-beijing.volces.com/api/v3/responses 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,ocodex_exec=debug' || 'warn' }} - name: Detect agent errors @@ -962,41 +918,6 @@ jobs: setupGlobals(core, github, context, exec, io, getOctokit); const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_mcp_gateway_log.cjs'); await main(); - - name: Print firewall logs - if: always() - continue-on-error: true - env: - AWF_LOGS_DIR: /tmp/gh-aw/sandbox/firewall/logs - run: | - # Fix permissions on firewall logs/audit dirs so they can be uploaded as artifacts - # AWF runs with sudo, creating files owned by root - sudo chmod -R a+rX /tmp/gh-aw/sandbox/firewall 2>/dev/null || true - # Only run awf logs summary if awf command exists (it may not be installed if workflow failed before install step) - if command -v awf &> /dev/null; then - awf logs summary | tee -a "$GITHUB_STEP_SUMMARY" - else - echo 'AWF binary not installed, skipping firewall log summary' - fi - - name: Parse token usage for step summary - if: always() - continue-on-error: true - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 - with: - script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/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 { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/awf_reflect_summary.cjs'); - await main(); - name: Write agent output placeholder if missing if: always() run: | @@ -1016,17 +937,12 @@ jobs: /tmp/gh-aw/mcp-logs/ /tmp/gh-aw/proxy-logs/ !/tmp/gh-aw/proxy-logs/proxy-tls/ - /tmp/gh-aw/agent_usage.json /tmp/gh-aw/agent-stdio.log /tmp/gh-aw/pre-agent-audit.txt /tmp/gh-aw/agent/ /tmp/gh-aw/github_rate_limits.jsonl /tmp/gh-aw/safeoutputs.jsonl /tmp/gh-aw/agent_output.json - /tmp/gh-aw/awf-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 conclusion: @@ -1065,7 +981,6 @@ jobs: GH_AW_SETUP_WORKFLOW_NAME: "Issue 自动分类与回复" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }} GH_AW_INFO_VERSION: "0.137.0" - GH_AW_INFO_AWF_VERSION: "v0.27.2" GH_AW_INFO_ENGINE_ID: "codex" - name: Download agent output artifact id: download-agent-output @@ -1228,7 +1143,6 @@ jobs: GH_AW_SETUP_WORKFLOW_NAME: "Issue 自动分类与回复" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }} GH_AW_INFO_VERSION: "0.137.0" - GH_AW_INFO_AWF_VERSION: "v0.27.2" GH_AW_INFO_ENGINE_ID: "codex" - name: Check team membership for workflow id: check_membership @@ -1288,7 +1202,6 @@ jobs: GH_AW_SETUP_WORKFLOW_NAME: "Issue 自动分类与回复" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }} GH_AW_INFO_VERSION: "0.137.0" - GH_AW_INFO_AWF_VERSION: "v0.27.2" GH_AW_INFO_ENGINE_ID: "codex" - name: Download agent output artifact id: download-agent-output diff --git a/.github/workflows/issue-triage.md b/.github/workflows/issue-triage.md index 48a54a26..3a875d80 100644 --- a/.github/workflows/issue-triage.md +++ b/.github/workflows/issue-triage.md @@ -6,7 +6,7 @@ on: engine: id: codex env: - OPENAI_BASE_URL: "https://ark.cn-beijing.volces.com/api/v3" + OPENAI_BASE_URL: "https://ark.cn-beijing.volces.com/api/v3/responses" OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} CODEX_MODEL: doubao-seed-2-0-code-preview-260215 model: doubao-seed-2-0-code-preview-260215 @@ -16,6 +16,12 @@ engine: max-ai-credits: -1 +features: + dangerously-disable-sandbox-agent: "controlled environment for issue triage automation" +sandbox: + agent: false +strict: false + network: allowed: - defaults From 56594bdc39fdde4bcab64b05bf77920018bf2708 Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Tue, 23 Jun 2026 11:34:53 +0800 Subject: [PATCH 39/59] feat: add agentic workflows for issue triage and auto fix --- .github/workflows/issue-triage.lock.yml | 6 ++---- .github/workflows/issue-triage.md | 8 +------- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/.github/workflows/issue-triage.lock.yml b/.github/workflows/issue-triage.lock.yml index 4169d09f..ed0cb62c 100644 --- a/.github/workflows/issue-triage.lock.yml +++ b/.github/workflows/issue-triage.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"4eba86fa909777f0a6038b0e48c6c9be43657266fd1eef63de8afb40e77b0023","body_hash":"bf4f8784cdac578e246f253a70aa7f7acce80a6fcf1c9116a0f5867b9ece3260","compiler_version":"v0.79.6","agent_id":"codex","agent_model":"doubao-seed-2-0-code-preview-260215","engine_versions":{"codex":"0.137.0"}} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"9823cd4e17938360ba666b3b4a31631c421f6c95e04140e19485e3fba2720f81","body_hash":"bf4f8784cdac578e246f253a70aa7f7acce80a6fcf1c9116a0f5867b9ece3260","compiler_version":"v0.79.6","agent_id":"codex","agent_model":"doubao-seed-2-0-code-preview-260215","engine_versions":{"codex":"0.137.0"}} # gh-aw-manifest: {"version":1,"secrets":["CODEX_API_KEY","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"5c2fe865bb4dc46e1450f6ee0d0541d759aea73a","version":"v0.79.6"}],"containers":[{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]} # ___ _ _ # / _ \ | | (_) @@ -116,7 +116,6 @@ jobs: GH_AW_INFO_AWMG_VERSION: "" GH_AW_INFO_FIREWALL_TYPE: "" GH_AW_COMPILED_STRICT: "false" - GH_AW_INFO_TOKEN_WEIGHTS: '{"multipliers":{"doubao":1}}' uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | @@ -815,7 +814,6 @@ jobs: env: CODEX_API_KEY: ${{ secrets.CODEX_API_KEY || secrets.OPENAI_API_KEY }} CODEX_HOME: /tmp/gh-aw/mcp-config - CODEX_MODEL: doubao-seed-2-0-code-preview-260215 GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }} GH_AW_MCP_CONFIG: ${{ runner.temp }}/gh-aw/mcp-config/config.toml GH_AW_MODEL_AGENT_CODEX: doubao-seed-2-0-code-preview-260215 @@ -1100,7 +1098,7 @@ jobs: 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_MAX_AI_CREDITS: "-1" + GH_AW_MAX_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_MAX_AI_CREDITS || '1000' }} 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 }} diff --git a/.github/workflows/issue-triage.md b/.github/workflows/issue-triage.md index 3a875d80..c91ecb93 100644 --- a/.github/workflows/issue-triage.md +++ b/.github/workflows/issue-triage.md @@ -5,16 +5,10 @@ on: engine: id: codex + model: doubao-seed-2-0-code-preview-260215 env: OPENAI_BASE_URL: "https://ark.cn-beijing.volces.com/api/v3/responses" OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - CODEX_MODEL: doubao-seed-2-0-code-preview-260215 - model: doubao-seed-2-0-code-preview-260215 - token-weights: - multipliers: - doubao: 1.0 - -max-ai-credits: -1 features: dangerously-disable-sandbox-agent: "controlled environment for issue triage automation" From fd3dc63d47bc94b3632b1c1a84e957879f626094 Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Tue, 23 Jun 2026 13:56:37 +0800 Subject: [PATCH 40/59] feat: add agentic workflows for issue triage and auto fix --- .github/workflows/issue-triage.lock.yml | 197 ++++++++++-------------- .github/workflows/issue-triage.md | 12 +- 2 files changed, 89 insertions(+), 120 deletions(-) diff --git a/.github/workflows/issue-triage.lock.yml b/.github/workflows/issue-triage.lock.yml index ed0cb62c..40be73b8 100644 --- a/.github/workflows/issue-triage.lock.yml +++ b/.github/workflows/issue-triage.lock.yml @@ -1,5 +1,5 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"9823cd4e17938360ba666b3b4a31631c421f6c95e04140e19485e3fba2720f81","body_hash":"bf4f8784cdac578e246f253a70aa7f7acce80a6fcf1c9116a0f5867b9ece3260","compiler_version":"v0.79.6","agent_id":"codex","agent_model":"doubao-seed-2-0-code-preview-260215","engine_versions":{"codex":"0.137.0"}} -# gh-aw-manifest: {"version":1,"secrets":["CODEX_API_KEY","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"5c2fe865bb4dc46e1450f6ee0d0541d759aea73a","version":"v0.79.6"}],"containers":[{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"7a4b62c54aa180ebdcccd6d911f4d76467a76f4d68bae604e79ae6c640eb1905","body_hash":"bf4f8784cdac578e246f253a70aa7f7acce80a6fcf1c9116a0f5867b9ece3260","compiler_version":"v0.79.6","agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}} +# gh-aw-manifest: {"version":1,"secrets":["GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"5c2fe865bb4dc46e1450f6ee0d0541d759aea73a","version":"v0.79.6"}],"containers":[{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]} # ___ _ _ # / _ \ | | (_) # | |_| | __ _ ___ _ __ | |_ _ ___ @@ -24,7 +24,6 @@ # # # Secrets used: -# - CODEX_API_KEY # - GH_AW_GITHUB_MCP_SERVER_TOKEN # - GH_AW_GITHUB_TOKEN # - GITHUB_TOKEN @@ -34,7 +33,6 @@ # - actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 # - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 # - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 -# - actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 # - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 # - github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 # @@ -75,7 +73,6 @@ jobs: engine_id: ${{ steps.generate_aw_info.outputs.engine_id }} lockdown_check_failed: ${{ steps.generate_aw_info.outputs.lockdown_check_failed == 'true' }} model: ${{ steps.generate_aw_info.outputs.model }} - secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} 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 }} @@ -95,22 +92,22 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "Issue 自动分类与回复" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "0.137.0" - GH_AW_INFO_ENGINE_ID: "codex" + GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_ENGINE_ID: "copilot" - 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: "doubao-seed-2-0-code-preview-260215" - GH_AW_INFO_VERSION: "0.137.0" - GH_AW_INFO_AGENT_VERSION: "0.137.0" + GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_INFO_ENGINE_NAME: "GitHub Copilot CLI" + GH_AW_INFO_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || vars.GH_AW_DEFAULT_MODEL_COPILOT || 'claude-sonnet-4.6' }} + GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_AGENT_VERSION: "1.0.60" GH_AW_INFO_CLI_VERSION: "v0.79.6" GH_AW_INFO_WORKFLOW_NAME: "Issue 自动分类与回复" GH_AW_INFO_EXPERIMENTAL: "false" GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true" GH_AW_INFO_STAGED: "false" - GH_AW_INFO_ALLOWED_DOMAINS: '["defaults","ark.cn-beijing.volces.com","github.com","api.github.com"]' + GH_AW_INFO_ALLOWED_DOMAINS: '["defaults","ark.cn-beijing.volces.com"]' GH_AW_INFO_FIREWALL_ENABLED: "false" GH_AW_INFO_AWF_VERSION: "" GH_AW_INFO_AWMG_VERSION: "" @@ -141,12 +138,6 @@ jobs: setupGlobals(core, github, context, exec, io, getOctokit); const { main } = require('${{ runner.temp }}/gh-aw/actions/check_daily_aic_workflow_guardrail.cjs'); await main(); - - name: Validate CODEX_API_KEY or OPENAI_API_KEY secret - id: validate-secret - run: bash "${RUNNER_TEMP}/gh-aw/actions/validate_multi_secret.sh" CODEX_API_KEY OPENAI_API_KEY Codex https://github.github.com/gh-aw/reference/engines/#openai-codex - env: - CODEX_API_KEY: ${{ secrets.CODEX_API_KEY }} - OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - name: Checkout .github and .agents folders uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: @@ -195,7 +186,7 @@ jobs: id: sanitized uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: - GH_AW_ALLOWED_DOMAINS: "172.30.0.1,api.github.com,api.openai.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,chatgpt.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,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,openai.com,packagecloud.io,packages.cloud.google.com,packages.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" + GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,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,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); @@ -271,7 +262,7 @@ jobs: uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GH_AW_ENGINE_ID: "codex" + GH_AW_ENGINE_ID: "copilot" GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} with: script: | @@ -341,8 +332,8 @@ jobs: /tmp/gh-aw/aw-prompts/prompt-import-tree.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/.github/agents + /tmp/gh-aw/.github/skills if-no-files-found: ignore retention-days: 1 @@ -392,8 +383,8 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "Issue 自动分类与回复" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "0.137.0" - GH_AW_INFO_ENGINE_ID: "codex" + GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_ENGINE_ID: "copilot" - name: Set runtime paths id: set-runtime-paths run: | @@ -439,13 +430,10 @@ jobs: setupGlobals(core, github, context, exec, io, getOctokit); const { main } = require('${{ runner.temp }}/gh-aw/actions/checkout_pr_branch.cjs'); await main(); - - name: Setup Node.js - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 - with: - node-version: '24' - package-manager-cache: false - - name: Install Codex CLI - run: npm install --ignore-scripts -g @openai/codex@0.137.0 + - name: Install GitHub Copilot CLI + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.60 + env: + GH_HOST: github.com - name: Parse integrity filter lists id: parse-guard-vars env: @@ -466,12 +454,12 @@ jobs: 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" + GH_AW_SUB_AGENT_DIR: ".github/agents" + GH_AW_SUB_AGENT_EXT: ".agent.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" + GH_AW_SKILL_DIR: ".github/skills" run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_inline_skills.sh" - name: Download container images run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c @@ -661,7 +649,6 @@ jobs: - name: Start MCP Gateway id: start-mcp-gateway env: - CODEX_HOME: /tmp/gh-aw/mcp-config GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-start.outputs.api_key }} GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-start.outputs.port }} @@ -682,7 +669,7 @@ jobs: export MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD="524288" export DEBUG="*" - export GH_AW_ENGINE="codex" + export GH_AW_ENGINE="copilot" MCP_GATEWAY_UID=$(id -u 2>/dev/null || echo '0') MCP_GATEWAY_GID=$(id -g 2>/dev/null || echo '0') case "${DOCKER_HOST:-}" in @@ -691,47 +678,19 @@ jobs: * ) DOCKER_SOCK_PATH=/var/run/docker.sock ;; esac DOCKER_SOCK_GID=$(stat -c '%g' "$DOCKER_SOCK_PATH" 2>/dev/null || echo '0') - export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --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_API_KEY -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_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -e CODEX_HOME -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.3.25' - - cat > "${RUNNER_TEMP}/gh-aw/mcp-config/config.toml" << GH_AW_MCP_CONFIG_7602cb776b25e54a_EOF - [history] - persistence = "none" - - [shell_environment_policy] - inherit = "core" - include_only = ["^CODEX_API_KEY$", "^GH_AW_ASSETS_ALLOWED_EXTS$", "^GH_AW_ASSETS_BRANCH$", "^GH_AW_ASSETS_MAX_SIZE_KB$", "^GH_AW_SAFE_OUTPUTS$", "^GITHUB_PERSONAL_ACCESS_TOKEN$", "^GITHUB_REPOSITORY$", "^GITHUB_SERVER_URL$", "^HOME$", "^OPENAI_API_KEY$", "^PATH$"] - - [mcp_servers.github] - user_agent = "issue" - startup_timeout_sec = 120 - tool_timeout_sec = 60 - container = "ghcr.io/github/github-mcp-server:v1.1.2" - env = { "GITHUB_HOST" = "$GITHUB_SERVER_URL", "GITHUB_PERSONAL_ACCESS_TOKEN" = "$GH_AW_GITHUB_TOKEN", "GITHUB_READ_ONLY" = "1", "GITHUB_TOOLSETS" = "context,repos,issues,pull_requests" } - env_vars = ["GITHUB_HOST", "GITHUB_PERSONAL_ACCESS_TOKEN", "GITHUB_READ_ONLY", "GITHUB_TOOLSETS"] - - [mcp_servers.safeoutputs] - type = "http" - url = "http://localhost:$GH_AW_SAFE_OUTPUTS_PORT" - - [mcp_servers.safeoutputs.headers] - Authorization = "$GH_AW_SAFE_OUTPUTS_API_KEY" - - [mcp_servers.safeoutputs."guard-policies"] + export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --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_API_KEY -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_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.3.25' - [mcp_servers.safeoutputs."guard-policies".write-sink] - accept = ["*"] - GH_AW_MCP_CONFIG_7602cb776b25e54a_EOF - - # Generate JSON config for MCP gateway + mkdir -p /home/runner/.copilot GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_bb2cc39de9e76341_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_f41962abaffbda74_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "github": { + "type": "stdio", "container": "ghcr.io/github/github-mcp-server:v1.1.2", "env": { - "GITHUB_HOST": "$GITHUB_SERVER_URL", - "GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_MCP_SERVER_TOKEN", + "GITHUB_HOST": "\${GITHUB_SERVER_URL}", + "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}", "GITHUB_READ_ONLY": "1", "GITHUB_TOOLSETS": "context,repos,issues,pull_requests" }, @@ -749,7 +708,7 @@ jobs: "type": "http", "url": "http://localhost:$GH_AW_SAFE_OUTPUTS_PORT", "headers": { - "Authorization": "$GH_AW_SAFE_OUTPUTS_API_KEY" + "Authorization": "\${GH_AW_SAFE_OUTPUTS_API_KEY}" }, "guard-policies": { "write-sink": { @@ -767,20 +726,7 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_bb2cc39de9e76341_EOF - - # Sync converter output to writable CODEX_HOME for Codex - mkdir -p /tmp/gh-aw/mcp-config - cat > "/tmp/gh-aw/mcp-config/config.toml" << GH_AW_CODEX_SHELL_POLICY_eead21463895a36c_EOF - [shell_environment_policy] - inherit = "core" - include_only = ["^CODEX_API_KEY$", "^GH_AW_ASSETS_ALLOWED_EXTS$", "^GH_AW_ASSETS_BRANCH$", "^GH_AW_ASSETS_MAX_SIZE_KB$", "^GH_AW_SAFE_OUTPUTS$", "^GITHUB_PERSONAL_ACCESS_TOKEN$", "^GITHUB_REPOSITORY$", "^GITHUB_SERVER_URL$", "^HOME$", "^OPENAI_API_KEY$", "^PATH$"] - GH_AW_CODEX_SHELL_POLICY_eead21463895a36c_EOF - cat "${RUNNER_TEMP}/gh-aw/mcp-config/config.toml" >> "/tmp/gh-aw/mcp-config/config.toml" - chmod 600 "/tmp/gh-aw/mcp-config/config.toml" - mkdir -p "${CODEX_HOME}" - if [ "/tmp/gh-aw/mcp-config/config.toml" != "${CODEX_HOME}/config.toml" ]; then cp "/tmp/gh-aw/mcp-config/config.toml" "${CODEX_HOME}/config.toml"; fi - chmod 600 "${CODEX_HOME}/config.toml" + GH_AW_MCP_CONFIG_f41962abaffbda74_EOF - name: Mount MCP servers as CLIs id: mount-mcp-clis continue-on-error: true @@ -802,31 +748,51 @@ jobs: id: pre_agent_audit continue-on-error: true run: bash "${RUNNER_TEMP}/gh-aw/actions/audit_pre_agent_workspace.sh" - - name: Execute Codex CLI + - name: Execute GitHub Copilot CLI id: agentic_execution + # Copilot CLI tool arguments (sorted): + # --allow-tool github + # --allow-tool safeoutputs + timeout-minutes: 20 run: | set -o pipefail printf '%s' "$(date +%s%3N)" > /tmp/gh-aw/agent_cli_start_ms.txt touch /tmp/gh-aw/agent-step-summary.md (umask 177 && touch /tmp/gh-aw/agent-stdio.log) - mkdir -p "$CODEX_HOME/logs" - 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" -c fetch="disabled" --sandbox workspace-write --skip-git-repo-check -c approval_policy="never" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt 2>&1 | tee /tmp/gh-aw/agent-stdio.log + trap 'rm -f /home/runner/.copilot/settings.json' EXIT + mkdir -p /home/runner/.copilot + printf '%s' '{"builtInAgents":{"rubberDuck":false}}' > /home/runner/.copilot/settings.json + mkdir -p /tmp/ + mkdir -p /tmp/gh-aw/ + mkdir -p /tmp/gh-aw/agent/ + mkdir -p /tmp/gh-aw/sandbox/agent/logs/ + 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/copilot_harness.cjs copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-tool github --allow-tool safeoutputs --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt 2>&1 | tee /tmp/gh-aw/agent-stdio.log env: - CODEX_API_KEY: ${{ secrets.CODEX_API_KEY || secrets.OPENAI_API_KEY }} - CODEX_HOME: /tmp/gh-aw/mcp-config + COPILOT_AGENT_RUNNER_TYPE: STANDALONE + COPILOT_MODEL: doubao-seed-2-0-code-preview-260215 + COPILOT_PROVIDER_API_KEY: ${{ secrets.OPENAI_API_KEY }} + COPILOT_PROVIDER_BASE_URL: https://ark.cn-beijing.volces.com/api/v3/responses + COPILOT_PROVIDER_TYPE: openai + COPILOT_PROVIDER_WIRE_API: responses GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }} - GH_AW_MCP_CONFIG: ${{ runner.temp }}/gh-aw/mcp-config/config.toml - GH_AW_MODEL_AGENT_CODEX: doubao-seed-2-0-code-preview-260215 + GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json 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_TIMEOUT_MINUTES: 20 GH_AW_VERSION: v0.79.6 + GITHUB_API_URL: ${{ github.api_url }} GITHUB_AW: true + GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows + GITHUB_HEAD_REF: ${{ github.head_ref }} + GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + GITHUB_REF_NAME: ${{ github.ref_name }} + GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md - OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - OPENAI_BASE_URL: https://ark.cn-beijing.volces.com/api/v3/responses + GITHUB_WORKSPACE: ${{ github.workspace }} 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,ocodex_exec=debug' || 'warn' }} + S2STOKENS: true + XDG_CONFIG_HOME: /home/runner - name: Detect agent errors if: always() id: detect-agent-errors @@ -845,6 +811,10 @@ jobs: SERVER_URL_STRIPPED="${SERVER_URL#https://}" git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" echo "Git configured with standard GitHub Actions identity" + - name: Copy Copilot session state files to logs + if: always() + continue-on-error: true + run: bash "${RUNNER_TEMP}/gh-aw/actions/copy_copilot_session_state.sh" - name: Stop MCP Gateway if: always() continue-on-error: true @@ -864,8 +834,7 @@ jobs: const { main } = require('${{ runner.temp }}/gh-aw/actions/redact_secrets.cjs'); await main(); env: - GH_AW_SECRET_NAMES: 'CODEX_API_KEY,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN,OPENAI_API_KEY' - SECRET_CODEX_API_KEY: ${{ secrets.CODEX_API_KEY }} + GH_AW_SECRET_NAMES: 'GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN,OPENAI_API_KEY' SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -886,7 +855,7 @@ jobs: 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: "172.30.0.1,api.github.com,api.openai.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,chatgpt.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,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,openai.com,packagecloud.io,packages.cloud.google.com,packages.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" + GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,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,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} with: @@ -899,12 +868,12 @@ jobs: if: always() uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: - GH_AW_AGENT_OUTPUT: /tmp/gh-aw/agent-stdio.log + GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/ with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_codex_log.cjs'); + const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_copilot_log.cjs'); await main(); - name: Parse MCP Gateway logs for step summary if: always() @@ -930,7 +899,7 @@ jobs: name: agent path: | /tmp/gh-aw/aw-prompts/prompt.txt - /tmp/gh-aw/mcp-config/logs/ + /tmp/gh-aw/sandbox/agent/logs/ /tmp/gh-aw/redacted-urls.log /tmp/gh-aw/mcp-logs/ /tmp/gh-aw/proxy-logs/ @@ -978,8 +947,8 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "Issue 自动分类与回复" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "0.137.0" - GH_AW_INFO_ENGINE_ID: "codex" + GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_ENGINE_ID: "copilot" - name: Download agent output artifact id: download-agent-output continue-on-error: true @@ -1091,8 +1060,7 @@ jobs: GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} GH_AW_WORKFLOW_ID: "issue-triage" GH_AW_ACTION_FAILURE_ISSUE_EXPIRES_HOURS: "168" - GH_AW_ENGINE_ID: "codex" - GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.activation.outputs.secret_verification_result }} + GH_AW_ENGINE_ID: "copilot" GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens || '' }} GH_AW_AI_CREDITS_RATE_LIMIT_ERROR: ${{ needs.agent.outputs.ai_credits_rate_limit_error || 'false' }} @@ -1103,7 +1071,7 @@ jobs: 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_ENGINE_API_HOSTS: "api.openai.com" + GH_AW_ENGINE_API_HOSTS: "api.enterprise.githubcopilot.com,api.githubcopilot.com,api.business.githubcopilot.com,api.individual.githubcopilot.com" GH_AW_LOCKDOWN_CHECK_FAILED: ${{ needs.activation.outputs.lockdown_check_failed }} GH_AW_STALE_LOCK_FILE_FAILED: ${{ needs.activation.outputs.stale_lock_file_failed }} GH_AW_DAILY_EFFECTIVE_WORKFLOW_EXCEEDED: ${{ needs.activation.outputs.daily_effective_workflow_exceeded }} @@ -1140,8 +1108,8 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "Issue 自动分类与回复" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "0.137.0" - GH_AW_INFO_ENGINE_ID: "codex" + GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_ENGINE_ID: "copilot" - name: Check team membership for workflow id: check_membership uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -1173,8 +1141,9 @@ jobs: GH_AW_AMBIENT_CONTEXT: ${{ needs.agent.outputs.ambient_context }} GH_AW_CALLER_WORKFLOW_ID: "${{ github.repository }}/issue-triage" GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens }} - GH_AW_ENGINE_ID: "codex" - GH_AW_ENGINE_MODEL: "doubao-seed-2-0-code-preview-260215" + GH_AW_ENGINE_ID: "copilot" + GH_AW_ENGINE_MODEL: ${{ needs.agent.outputs.model }} + GH_AW_ENGINE_VERSION: "1.0.60" GH_AW_WORKFLOW_ID: "issue-triage" GH_AW_WORKFLOW_NAME: "Issue 自动分类与回复" GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-triage.md" @@ -1199,8 +1168,8 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "Issue 自动分类与回复" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "0.137.0" - GH_AW_INFO_ENGINE_ID: "codex" + GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_ENGINE_ID: "copilot" - name: Download agent output artifact id: download-agent-output continue-on-error: true @@ -1231,7 +1200,7 @@ jobs: 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_ALLOWED_DOMAINS: "172.30.0.1,api.github.com,api.openai.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,chatgpt.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,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,openai.com,packagecloud.io,packages.cloud.google.com,packages.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" + GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,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,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.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},\"add_labels\":{\"allowed\":[\"bug\",\"feature\",\"enhancement\",\"documentation\",\"question\",\"duplicate\",\"invalid\"]},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"report_incomplete\":{}}" diff --git a/.github/workflows/issue-triage.md b/.github/workflows/issue-triage.md index c91ecb93..65255cfa 100644 --- a/.github/workflows/issue-triage.md +++ b/.github/workflows/issue-triage.md @@ -4,11 +4,13 @@ on: types: [opened, reopened] engine: - id: codex - model: doubao-seed-2-0-code-preview-260215 + id: copilot env: - OPENAI_BASE_URL: "https://ark.cn-beijing.volces.com/api/v3/responses" - OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + COPILOT_PROVIDER_BASE_URL: "https://ark.cn-beijing.volces.com/api/v3/responses" + COPILOT_PROVIDER_API_KEY: ${{ secrets.OPENAI_API_KEY }} + COPILOT_MODEL: doubao-seed-2-0-code-preview-260215 + COPILOT_PROVIDER_TYPE: openai + COPILOT_PROVIDER_WIRE_API: responses features: dangerously-disable-sandbox-agent: "controlled environment for issue triage automation" @@ -20,8 +22,6 @@ network: allowed: - defaults - ark.cn-beijing.volces.com - - github.com - - api.github.com tools: github: From c8098c00dfb14f321517c9944262352971ec9f0c Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Tue, 23 Jun 2026 14:15:34 +0800 Subject: [PATCH 41/59] feat: add agentic workflows for issue triage and auto fix --- .github/workflows/issue-triage.lock.yml | 4 ++-- .github/workflows/issue-triage.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/issue-triage.lock.yml b/.github/workflows/issue-triage.lock.yml index 40be73b8..93b70878 100644 --- a/.github/workflows/issue-triage.lock.yml +++ b/.github/workflows/issue-triage.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"7a4b62c54aa180ebdcccd6d911f4d76467a76f4d68bae604e79ae6c640eb1905","body_hash":"bf4f8784cdac578e246f253a70aa7f7acce80a6fcf1c9116a0f5867b9ece3260","compiler_version":"v0.79.6","agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"39f23d88a92aca3024c2d52d770c8bf621563823691394ae53ad3082b6b136ff","body_hash":"bf4f8784cdac578e246f253a70aa7f7acce80a6fcf1c9116a0f5867b9ece3260","compiler_version":"v0.79.6","agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}} # gh-aw-manifest: {"version":1,"secrets":["GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"5c2fe865bb4dc46e1450f6ee0d0541d759aea73a","version":"v0.79.6"}],"containers":[{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]} # ___ _ _ # / _ \ | | (_) @@ -770,8 +770,8 @@ jobs: env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_MODEL: doubao-seed-2-0-code-preview-260215 - COPILOT_PROVIDER_API_KEY: ${{ secrets.OPENAI_API_KEY }} COPILOT_PROVIDER_BASE_URL: https://ark.cn-beijing.volces.com/api/v3/responses + COPILOT_PROVIDER_BEARER_TOKEN: ${{ secrets.OPENAI_API_KEY }} COPILOT_PROVIDER_TYPE: openai COPILOT_PROVIDER_WIRE_API: responses GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }} diff --git a/.github/workflows/issue-triage.md b/.github/workflows/issue-triage.md index 65255cfa..a5a1dbaf 100644 --- a/.github/workflows/issue-triage.md +++ b/.github/workflows/issue-triage.md @@ -7,7 +7,7 @@ engine: id: copilot env: COPILOT_PROVIDER_BASE_URL: "https://ark.cn-beijing.volces.com/api/v3/responses" - COPILOT_PROVIDER_API_KEY: ${{ secrets.OPENAI_API_KEY }} + COPILOT_PROVIDER_BEARER_TOKEN: ${{ secrets.OPENAI_API_KEY }} COPILOT_MODEL: doubao-seed-2-0-code-preview-260215 COPILOT_PROVIDER_TYPE: openai COPILOT_PROVIDER_WIRE_API: responses From 6fee8e6424ad1fe151dbd3a4f8033fb768a1fb5f Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Tue, 23 Jun 2026 14:23:45 +0800 Subject: [PATCH 42/59] feat: add agentic workflows for issue triage and auto fix --- .github/workflows/issue-triage.lock.yml | 4 ++-- .github/workflows/issue-triage.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/issue-triage.lock.yml b/.github/workflows/issue-triage.lock.yml index 93b70878..1214c52b 100644 --- a/.github/workflows/issue-triage.lock.yml +++ b/.github/workflows/issue-triage.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"39f23d88a92aca3024c2d52d770c8bf621563823691394ae53ad3082b6b136ff","body_hash":"bf4f8784cdac578e246f253a70aa7f7acce80a6fcf1c9116a0f5867b9ece3260","compiler_version":"v0.79.6","agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"6755cb1b3db280f418be9daf8f20588c0332414b28bf418786db7dc30de58d26","body_hash":"bf4f8784cdac578e246f253a70aa7f7acce80a6fcf1c9116a0f5867b9ece3260","compiler_version":"v0.79.6","agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}} # gh-aw-manifest: {"version":1,"secrets":["GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"5c2fe865bb4dc46e1450f6ee0d0541d759aea73a","version":"v0.79.6"}],"containers":[{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]} # ___ _ _ # / _ \ | | (_) @@ -770,7 +770,7 @@ jobs: env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_MODEL: doubao-seed-2-0-code-preview-260215 - COPILOT_PROVIDER_BASE_URL: https://ark.cn-beijing.volces.com/api/v3/responses + COPILOT_PROVIDER_BASE_URL: https://ark.cn-beijing.volces.com/api/v3 COPILOT_PROVIDER_BEARER_TOKEN: ${{ secrets.OPENAI_API_KEY }} COPILOT_PROVIDER_TYPE: openai COPILOT_PROVIDER_WIRE_API: responses diff --git a/.github/workflows/issue-triage.md b/.github/workflows/issue-triage.md index a5a1dbaf..49f4115b 100644 --- a/.github/workflows/issue-triage.md +++ b/.github/workflows/issue-triage.md @@ -6,7 +6,7 @@ on: engine: id: copilot env: - COPILOT_PROVIDER_BASE_URL: "https://ark.cn-beijing.volces.com/api/v3/responses" + COPILOT_PROVIDER_BASE_URL: "https://ark.cn-beijing.volces.com/api/v3" COPILOT_PROVIDER_BEARER_TOKEN: ${{ secrets.OPENAI_API_KEY }} COPILOT_MODEL: doubao-seed-2-0-code-preview-260215 COPILOT_PROVIDER_TYPE: openai From b36549b754317338be016329fc0962152b852cae Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Tue, 23 Jun 2026 14:32:19 +0800 Subject: [PATCH 43/59] feat: add agentic workflows for issue triage and auto fix --- .github/workflows/auto-code.lock.yml | 323 ++++++++++----------------- .github/workflows/auto-code.md | 20 +- 2 files changed, 124 insertions(+), 219 deletions(-) diff --git a/.github/workflows/auto-code.lock.yml b/.github/workflows/auto-code.lock.yml index c41cf285..0c3a48bf 100644 --- a/.github/workflows/auto-code.lock.yml +++ b/.github/workflows/auto-code.lock.yml @@ -1,5 +1,5 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"1883cf08233ac6269970aae96ec73b20118a2b2d94bd30c6cb60395e375fd7ee","body_hash":"9959a757362d73cb28768bc2f9a90afc30a49f61e3226f922c791d0cbf387678","compiler_version":"v0.79.6","strict":true,"agent_id":"codex","agent_model":"doubao-seed-2-0-code-preview-260215","engine_versions":{"codex":"0.137.0"}} -# gh-aw-manifest: {"version":1,"secrets":["CODEX_API_KEY","GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"5c2fe865bb4dc46e1450f6ee0d0541d759aea73a","version":"v0.79.6"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2","digest":"sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2","digest":"sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2@sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2","digest":"sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2@sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.25","digest":"sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.25@sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa"},{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"31e704abf0cc67a7873ed877b1f39e07f391c21da86512dc05e99f3d5e2df28a","body_hash":"9959a757362d73cb28768bc2f9a90afc30a49f61e3226f922c791d0cbf387678","compiler_version":"v0.79.6","agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}} +# gh-aw-manifest: {"version":1,"secrets":["GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"5c2fe865bb4dc46e1450f6ee0d0541d759aea73a","version":"v0.79.6"}],"containers":[{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]} # ___ _ _ # / _ \ | | (_) # | |_| | __ _ ___ _ __ | |_ _ ___ @@ -24,7 +24,6 @@ # # # Secrets used: -# - CODEX_API_KEY # - GH_AW_CI_TRIGGER_TOKEN # - GH_AW_GITHUB_MCP_SERVER_TOKEN # - GH_AW_GITHUB_TOKEN @@ -35,15 +34,10 @@ # - actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 # - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 # - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 -# - actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 # - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 # - github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 # # Container images used: -# - ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6 -# - ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2@sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4 -# - ghcr.io/github/gh-aw-firewall/squid:0.27.2@sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591 -# - ghcr.io/github/gh-aw-mcpg:v0.3.25@sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa # - ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c name: "自动处理 Issue" @@ -79,7 +73,6 @@ jobs: engine_id: ${{ steps.generate_aw_info.outputs.engine_id }} lockdown_check_failed: ${{ steps.generate_aw_info.outputs.lockdown_check_failed == 'true' }} model: ${{ steps.generate_aw_info.outputs.model }} - secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} 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 }} @@ -99,29 +92,27 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "自动处理 Issue" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/auto-code.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "0.137.0" - GH_AW_INFO_AWF_VERSION: "v0.27.2" - GH_AW_INFO_ENGINE_ID: "codex" + GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_ENGINE_ID: "copilot" - 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: "doubao-seed-2-0-code-preview-260215" - GH_AW_INFO_VERSION: "0.137.0" - GH_AW_INFO_AGENT_VERSION: "0.137.0" + GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_INFO_ENGINE_NAME: "GitHub Copilot CLI" + GH_AW_INFO_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || vars.GH_AW_DEFAULT_MODEL_COPILOT || 'claude-sonnet-4.6' }} + GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_AGENT_VERSION: "1.0.60" GH_AW_INFO_CLI_VERSION: "v0.79.6" GH_AW_INFO_WORKFLOW_NAME: "自动处理 Issue" GH_AW_INFO_EXPERIMENTAL: "false" GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true" GH_AW_INFO_STAGED: "false" GH_AW_INFO_ALLOWED_DOMAINS: '["defaults","ark.cn-beijing.volces.com","github.com","api.github.com"]' - GH_AW_INFO_FIREWALL_ENABLED: "true" - GH_AW_INFO_AWF_VERSION: "v0.27.2" + GH_AW_INFO_FIREWALL_ENABLED: "false" + GH_AW_INFO_AWF_VERSION: "" GH_AW_INFO_AWMG_VERSION: "" - GH_AW_INFO_FIREWALL_TYPE: "squid" - GH_AW_COMPILED_STRICT: "true" - GH_AW_INFO_TOKEN_WEIGHTS: '{"multipliers":{"doubao":0.5}}' + GH_AW_INFO_FIREWALL_TYPE: "" + GH_AW_COMPILED_STRICT: "false" uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | @@ -147,12 +138,6 @@ jobs: setupGlobals(core, github, context, exec, io, getOctokit); const { main } = require('${{ runner.temp }}/gh-aw/actions/check_daily_aic_workflow_guardrail.cjs'); await main(); - - name: Validate CODEX_API_KEY or OPENAI_API_KEY secret - id: validate-secret - run: bash "${RUNNER_TEMP}/gh-aw/actions/validate_multi_secret.sh" CODEX_API_KEY OPENAI_API_KEY Codex https://github.github.com/gh-aw/reference/engines/#openai-codex - env: - CODEX_API_KEY: ${{ secrets.CODEX_API_KEY }} - OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - name: Checkout .github and .agents folders uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: @@ -201,7 +186,7 @@ jobs: id: sanitized uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: - GH_AW_ALLOWED_DOMAINS: "172.30.0.1,api.github.com,api.openai.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,chatgpt.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,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,openai.com,packagecloud.io,packages.cloud.google.com,packages.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" + GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,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,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); @@ -281,7 +266,7 @@ jobs: uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GH_AW_ENGINE_ID: "codex" + GH_AW_ENGINE_ID: "copilot" GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} with: script: | @@ -353,8 +338,8 @@ jobs: /tmp/gh-aw/aw-prompts/prompt-import-tree.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/.github/agents + /tmp/gh-aw/.github/skills if-no-files-found: ignore retention-days: 1 @@ -403,9 +388,8 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "自动处理 Issue" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/auto-code.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "0.137.0" - GH_AW_INFO_AWF_VERSION: "v0.27.2" - GH_AW_INFO_ENGINE_ID: "codex" + GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_ENGINE_ID: "copilot" - name: Set runtime paths id: set-runtime-paths run: | @@ -451,15 +435,10 @@ jobs: setupGlobals(core, github, context, exec, io, getOctokit); const { main } = require('${{ runner.temp }}/gh-aw/actions/checkout_pr_branch.cjs'); await main(); - - name: Setup Node.js - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 - with: - node-version: '24' - package-manager-cache: false - - name: Install Codex CLI - run: npm install --ignore-scripts -g @openai/codex@0.137.0 - - name: Install AWF binary - run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.27.2 + - name: Install GitHub Copilot CLI + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.60 + env: + GH_HOST: github.com - name: Parse integrity filter lists id: parse-guard-vars env: @@ -480,15 +459,15 @@ jobs: 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" + GH_AW_SUB_AGENT_DIR: ".github/agents" + GH_AW_SUB_AGENT_EXT: ".agent.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" + GH_AW_SKILL_DIR: ".github/skills" run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_inline_skills.sh" - name: Download container images - run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6 ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2@sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4 ghcr.io/github/gh-aw-firewall/squid:0.27.2@sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591 ghcr.io/github/gh-aw-mcpg:v0.3.25@sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c + run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c - name: Generate Safe Outputs Config run: | mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" @@ -697,7 +676,6 @@ jobs: - name: Start MCP Gateway id: start-mcp-gateway env: - CODEX_HOME: /tmp/gh-aw/mcp-config GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-start.outputs.api_key }} GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-start.outputs.port }} @@ -708,7 +686,7 @@ jobs: # Export gateway environment variables for MCP config and gateway script export MCP_GATEWAY_PORT="8080" - export MCP_GATEWAY_DOMAIN="host.docker.internal" + export MCP_GATEWAY_DOMAIN="localhost" export MCP_GATEWAY_HOST_DOMAIN="localhost" MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=') echo "::add-mask::${MCP_GATEWAY_API_KEY}" @@ -718,7 +696,7 @@ jobs: export MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD="524288" export DEBUG="*" - export GH_AW_ENGINE="codex" + export GH_AW_ENGINE="copilot" MCP_GATEWAY_UID=$(id -u 2>/dev/null || echo '0') MCP_GATEWAY_GID=$(id -g 2>/dev/null || echo '0') case "${DOCKER_HOST:-}" in @@ -727,47 +705,19 @@ jobs: * ) DOCKER_SOCK_PATH=/var/run/docker.sock ;; esac DOCKER_SOCK_GID=$(stat -c '%g' "$DOCKER_SOCK_PATH" 2>/dev/null || echo '0') - export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --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_API_KEY -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_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -e CODEX_HOME -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.3.25' - - cat > "${RUNNER_TEMP}/gh-aw/mcp-config/config.toml" << GH_AW_MCP_CONFIG_d9dc58ce079498af_EOF - [history] - persistence = "none" - - [shell_environment_policy] - inherit = "core" - include_only = ["^CODEX_API_KEY$", "^GH_AW_ASSETS_ALLOWED_EXTS$", "^GH_AW_ASSETS_BRANCH$", "^GH_AW_ASSETS_MAX_SIZE_KB$", "^GH_AW_SAFE_OUTPUTS$", "^GITHUB_PERSONAL_ACCESS_TOKEN$", "^GITHUB_REPOSITORY$", "^GITHUB_SERVER_URL$", "^HOME$", "^OPENAI_API_KEY$", "^PATH$"] - - [mcp_servers.github] - user_agent = "issue" - startup_timeout_sec = 120 - tool_timeout_sec = 60 - container = "ghcr.io/github/github-mcp-server:v1.1.2" - env = { "GITHUB_HOST" = "$GITHUB_SERVER_URL", "GITHUB_PERSONAL_ACCESS_TOKEN" = "$GH_AW_GITHUB_TOKEN", "GITHUB_READ_ONLY" = "1", "GITHUB_TOOLSETS" = "context,repos,issues,pull_requests" } - env_vars = ["GITHUB_HOST", "GITHUB_PERSONAL_ACCESS_TOKEN", "GITHUB_READ_ONLY", "GITHUB_TOOLSETS"] + export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --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_API_KEY -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_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.3.25' - [mcp_servers.safeoutputs] - type = "http" - url = "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT" - - [mcp_servers.safeoutputs.headers] - Authorization = "$GH_AW_SAFE_OUTPUTS_API_KEY" - - [mcp_servers.safeoutputs."guard-policies"] - - [mcp_servers.safeoutputs."guard-policies".write-sink] - accept = ["*"] - GH_AW_MCP_CONFIG_d9dc58ce079498af_EOF - - # Generate JSON config for MCP gateway + mkdir -p /home/runner/.copilot GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_ca772287f17ffc28_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_f41962abaffbda74_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "github": { + "type": "stdio", "container": "ghcr.io/github/github-mcp-server:v1.1.2", "env": { - "GITHUB_HOST": "$GITHUB_SERVER_URL", - "GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_MCP_SERVER_TOKEN", + "GITHUB_HOST": "\${GITHUB_SERVER_URL}", + "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}", "GITHUB_READ_ONLY": "1", "GITHUB_TOOLSETS": "context,repos,issues,pull_requests" }, @@ -783,9 +733,9 @@ jobs: }, "safeoutputs": { "type": "http", - "url": "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT", + "url": "http://localhost:$GH_AW_SAFE_OUTPUTS_PORT", "headers": { - "Authorization": "$GH_AW_SAFE_OUTPUTS_API_KEY" + "Authorization": "\${GH_AW_SAFE_OUTPUTS_API_KEY}" }, "guard-policies": { "write-sink": { @@ -803,34 +753,7 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_ca772287f17ffc28_EOF - - # Sync converter output to writable CODEX_HOME for Codex - mkdir -p /tmp/gh-aw/mcp-config - cat > "/tmp/gh-aw/mcp-config/config.toml" << GH_AW_CODEX_SHELL_POLICY_929fca99db4cd5ec_EOF - - model_provider = "openai-proxy" - - [model_providers.openai-proxy] - name = "OpenAI AWF proxy" - base_url = "http://172.30.0.30:10000" - env_key = "OPENAI_API_KEY" - supports_websockets = false - [shell_environment_policy] - inherit = "core" - include_only = ["^CODEX_API_KEY$", "^GH_AW_ASSETS_ALLOWED_EXTS$", "^GH_AW_ASSETS_BRANCH$", "^GH_AW_ASSETS_MAX_SIZE_KB$", "^GH_AW_SAFE_OUTPUTS$", "^GITHUB_PERSONAL_ACCESS_TOKEN$", "^GITHUB_REPOSITORY$", "^GITHUB_SERVER_URL$", "^HOME$", "^OPENAI_API_KEY$", "^PATH$"] - GH_AW_CODEX_SHELL_POLICY_929fca99db4cd5ec_EOF - awk ' - BEGIN { skip_openai_proxy = 0 } - /^[[:space:]]*model_provider[[:space:]]*=/ { next } - /^\[model_providers\.openai-proxy\][[:space:]]*$/ { skip_openai_proxy = 1; next } - /^\[/ { skip_openai_proxy = 0 } - !skip_openai_proxy { print } - ' "${RUNNER_TEMP}/gh-aw/mcp-config/config.toml" >> "/tmp/gh-aw/mcp-config/config.toml" - chmod 600 "/tmp/gh-aw/mcp-config/config.toml" - mkdir -p "${CODEX_HOME}" - if [ "/tmp/gh-aw/mcp-config/config.toml" != "${CODEX_HOME}/config.toml" ]; then cp "/tmp/gh-aw/mcp-config/config.toml" "${CODEX_HOME}/config.toml"; fi - chmod 600 "${CODEX_HOME}/config.toml" + GH_AW_MCP_CONFIG_f41962abaffbda74_EOF - name: Mount MCP servers as CLIs id: mount-mcp-clis continue-on-error: true @@ -852,55 +775,73 @@ jobs: id: pre_agent_audit continue-on-error: true run: bash "${RUNNER_TEMP}/gh-aw/actions/audit_pre_agent_workspace.sh" - - name: Execute Codex CLI + - name: Execute GitHub Copilot CLI id: agentic_execution + # Copilot CLI tool arguments (sorted): + # --allow-tool github + # --allow-tool safeoutputs + # --allow-tool shell(cat) + # --allow-tool shell(date) + # --allow-tool shell(echo) + # --allow-tool shell(git add:*) + # --allow-tool shell(git branch:*) + # --allow-tool shell(git checkout:*) + # --allow-tool shell(git commit:*) + # --allow-tool shell(git merge:*) + # --allow-tool shell(git rm:*) + # --allow-tool shell(git status) + # --allow-tool shell(git switch:*) + # --allow-tool shell(grep) + # --allow-tool shell(head) + # --allow-tool shell(ls) + # --allow-tool shell(printf) + # --allow-tool shell(pwd) + # --allow-tool shell(safeoutputs:*) + # --allow-tool shell(sort) + # --allow-tool shell(tail) + # --allow-tool shell(uniq) + # --allow-tool shell(wc) + # --allow-tool shell(yq) + # --allow-tool write + timeout-minutes: 20 run: | set -o pipefail 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 + touch /tmp/gh-aw/agent-step-summary.md (umask 177 && touch /tmp/gh-aw/agent-stdio.log) - GH_AW_MAX_AI_CREDITS="${{ vars.GH_AW_DEFAULT_MAX_AI_CREDITS || '1000' }}" - printf '%s\n' "{\"\$schema\":\"https://github.com/github/gh-aw-firewall/releases/download/v0.27.2/awf-config.schema.json\",\"network\":{\"allowDomains\":[\"172.30.0.1\",\"api.github.com\",\"api.openai.com\",\"api.snapcraft.io\",\"archive.ubuntu.com\",\"ark.cn-beijing.volces.com\",\"azure.archive.ubuntu.com\",\"chatgpt.com\",\"crl.geotrust.com\",\"crl.globalsign.com\",\"crl.identrust.com\",\"crl.sectigo.com\",\"crl.thawte.com\",\"crl.usertrust.com\",\"crl.verisign.com\",\"crl3.digicert.com\",\"crl4.digicert.com\",\"crls.ssl.com\",\"github.com\",\"host.docker.internal\",\"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\",\"openai.com\",\"packagecloud.io\",\"packages.cloud.google.com\",\"packages.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\"]},\"apiProxy\":{\"enabled\":true,\"enableTokenSteering\":true,\"maxRuns\":500,\"maxAiCredits\":${GH_AW_MAX_AI_CREDITS},\"targets\":{\"openai\":{\"host\":\"ark.cn-beijing.volces.com\"}},\"models\":{\"agent\":[\"sonnet-6x\",\"gpt-5.4\",\"gpt-5.3\",\"gemini-pro\",\"any\"],\"antigravity\":[\"copilot/antigravity*\",\"google/antigravity*\",\"gemini/antigravity*\"],\"any\":[\"copilot/*\",\"anthropic/*\",\"openai/*\",\"google/*\",\"gemini/*\"],\"claude\":[\"agent\"],\"codex\":[\"agent\"],\"coding\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\",\"gpt-5-codex\"],\"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*\"],\"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-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-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.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*\"],\"haiku\":[\"copilot/*haiku*\",\"anthropic/*haiku*\"],\"large\":[\"sonnet\",\"gpt-5-pro\",\"gpt-5\",\"gemini-pro\"],\"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\"],\"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-4-5-*\",\"anthropic/*sonnet-4-5-*\",\"copilot/*sonnet-4-6*\",\"anthropic/*sonnet-4-6*\"],\"summarization\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash-lite\",\"mini\"],\"vision\":[\"copilot/gemini-*image*\",\"gemini/gemini-*image*\",\"copilot/gemini-*flash*\",\"gemini/gemini-*flash*\"]}},\"container\":{\"imageTag\":\"0.27.2,squid=sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591,agent=sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6,api-proxy=sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4,cli-proxy=sha256:02f3ec08f32dc26c5427920c6a2e2f3036238fce44802f2f11ef49ed8621b5d0\"}}" > "${RUNNER_TEMP}/gh-aw/awf-config.json" - GH_AW_MODEL_MULTIPLIERS_PATH="/tmp/gh-aw/model_multipliers.json" node "${RUNNER_TEMP}/gh-aw/actions/merge_awf_model_multipliers.cjs" - 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_PATH_PREFIX_ARGS="" - if [[ "${DOCKER_HOST:-}" =~ ^tcp:// ]]; then - GH_AW_DOCKER_HOST_PATH_PREFIX_ARGS="--docker-host-path-prefix /tmp/gh-aw" - fi - GH_AW_TOOL_CACHE_MOUNT="" - GH_AW_TOOL_CACHE="${RUNNER_TOOL_CACHE:-/opt/hostedtoolcache}" - 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 - elif [ -d "/home/runner/work/_tool" ]; then - GH_AW_TOOL_CACHE_MOUNT="/home/runner/work/_tool:/home/runner/work/_tool:ro" - fi - # shellcheck disable=SC1003 - sudo -E 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_PATH_PREFIX_ARGS} --env-all --exclude-env CODEX_API_KEY --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --exclude-env OPENAI_API_KEY --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull --openai-api-base-path /api/v3 \ - -- /bin/bash -c 'set +o histexpand; export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && GH_AW_TOOL_CACHE="${RUNNER_TOOL_CACHE:-/opt/hostedtoolcache}"; export PATH="$(find "$GH_AW_TOOL_CACHE" /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 5 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/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" -c fetch="disabled" --dangerously-bypass-approvals-and-sandbox --skip-git-repo-check --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + trap 'rm -f /home/runner/.copilot/settings.json' EXIT + mkdir -p /home/runner/.copilot + printf '%s' '{"builtInAgents":{"rubberDuck":false}}' > /home/runner/.copilot/settings.json + mkdir -p /tmp/ + mkdir -p /tmp/gh-aw/ + mkdir -p /tmp/gh-aw/agent/ + mkdir -p /tmp/gh-aw/sandbox/agent/logs/ + 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/copilot_harness.cjs copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-tool github --allow-tool safeoutputs --allow-tool 'shell(cat)' --allow-tool 'shell(date)' --allow-tool 'shell(echo)' --allow-tool 'shell(git add:*)' --allow-tool 'shell(git branch:*)' --allow-tool 'shell(git checkout:*)' --allow-tool 'shell(git commit:*)' --allow-tool 'shell(git merge:*)' --allow-tool 'shell(git rm:*)' --allow-tool 'shell(git status)' --allow-tool 'shell(git switch:*)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(ls)' --allow-tool 'shell(printf)' --allow-tool 'shell(pwd)' --allow-tool 'shell(safeoutputs:*)' --allow-tool 'shell(sort)' --allow-tool 'shell(tail)' --allow-tool 'shell(uniq)' --allow-tool 'shell(wc)' --allow-tool 'shell(yq)' --allow-tool write --allow-all-paths --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt 2>&1 | tee /tmp/gh-aw/agent-stdio.log env: - CODEX_API_KEY: ${{ secrets.CODEX_API_KEY || secrets.OPENAI_API_KEY }} - CODEX_HOME: /tmp/gh-aw/mcp-config - CODEX_MODEL: doubao-seed-2-0-code-preview-260215 + COPILOT_AGENT_RUNNER_TYPE: STANDALONE + COPILOT_MODEL: doubao-seed-2-0-code-preview-260215 + COPILOT_PROVIDER_BASE_URL: https://ark.cn-beijing.volces.com/api/v3 + COPILOT_PROVIDER_BEARER_TOKEN: ${{ secrets.OPENAI_API_KEY }} + COPILOT_PROVIDER_TYPE: openai + COPILOT_PROVIDER_WIRE_API: responses GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }} - GH_AW_MCP_CONFIG: ${{ runner.temp }}/gh-aw/mcp-config/config.toml - GH_AW_MODEL_AGENT_CODEX: doubao-seed-2-0-code-preview-260215 + GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json 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_TIMEOUT_MINUTES: 20 GH_AW_VERSION: v0.79.6 + GITHUB_API_URL: ${{ github.api_url }} GITHUB_AW: true + GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows + GITHUB_HEAD_REF: ${{ github.head_ref }} + GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + GITHUB_REF_NAME: ${{ github.ref_name }} + GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md - GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com - GIT_AUTHOR_NAME: github-actions[bot] - GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com - GIT_COMMITTER_NAME: github-actions[bot] - OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - OPENAI_BASE_URL: https://ark.cn-beijing.volces.com/api/v3 + GITHUB_WORKSPACE: ${{ github.workspace }} 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,ocodex_exec=debug' || 'warn' }} + XDG_CONFIG_HOME: /home/runner - name: Detect agent errors if: always() id: detect-agent-errors @@ -919,6 +860,10 @@ jobs: SERVER_URL_STRIPPED="${SERVER_URL#https://}" git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" echo "Git configured with standard GitHub Actions identity" + - name: Copy Copilot session state files to logs + if: always() + continue-on-error: true + run: bash "${RUNNER_TEMP}/gh-aw/actions/copy_copilot_session_state.sh" - name: Stop MCP Gateway if: always() continue-on-error: true @@ -938,8 +883,7 @@ jobs: const { main } = require('${{ runner.temp }}/gh-aw/actions/redact_secrets.cjs'); await main(); env: - GH_AW_SECRET_NAMES: 'CODEX_API_KEY,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN,OPENAI_API_KEY' - SECRET_CODEX_API_KEY: ${{ secrets.CODEX_API_KEY }} + GH_AW_SECRET_NAMES: 'GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN,OPENAI_API_KEY' SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -960,7 +904,7 @@ jobs: 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: "172.30.0.1,api.github.com,api.openai.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,chatgpt.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,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,openai.com,packagecloud.io,packages.cloud.google.com,packages.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" + GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,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,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} with: @@ -973,12 +917,12 @@ jobs: if: always() uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: - GH_AW_AGENT_OUTPUT: /tmp/gh-aw/agent-stdio.log + GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/ with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_codex_log.cjs'); + const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_copilot_log.cjs'); await main(); - name: Parse MCP Gateway logs for step summary if: always() @@ -990,41 +934,6 @@ jobs: setupGlobals(core, github, context, exec, io, getOctokit); const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_mcp_gateway_log.cjs'); await main(); - - name: Print firewall logs - if: always() - continue-on-error: true - env: - AWF_LOGS_DIR: /tmp/gh-aw/sandbox/firewall/logs - run: | - # Fix permissions on firewall logs/audit dirs so they can be uploaded as artifacts - # AWF runs with sudo, creating files owned by root - sudo chmod -R a+rX /tmp/gh-aw/sandbox/firewall 2>/dev/null || true - # Only run awf logs summary if awf command exists (it may not be installed if workflow failed before install step) - if command -v awf &> /dev/null; then - awf logs summary | tee -a "$GITHUB_STEP_SUMMARY" - else - echo 'AWF binary not installed, skipping firewall log summary' - fi - - name: Parse token usage for step summary - if: always() - continue-on-error: true - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 - with: - script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/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 { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/awf_reflect_summary.cjs'); - await main(); - name: Write agent output placeholder if missing if: always() run: | @@ -1039,12 +948,11 @@ jobs: name: agent path: | /tmp/gh-aw/aw-prompts/prompt.txt - /tmp/gh-aw/mcp-config/logs/ + /tmp/gh-aw/sandbox/agent/logs/ /tmp/gh-aw/redacted-urls.log /tmp/gh-aw/mcp-logs/ /tmp/gh-aw/proxy-logs/ !/tmp/gh-aw/proxy-logs/proxy-tls/ - /tmp/gh-aw/agent_usage.json /tmp/gh-aw/agent-stdio.log /tmp/gh-aw/pre-agent-audit.txt /tmp/gh-aw/agent/ @@ -1053,10 +961,6 @@ jobs: /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/sandbox/firewall/logs/ - /tmp/gh-aw/sandbox/firewall/audit/ - /tmp/gh-aw/sandbox/firewall/awf-reflect.json if-no-files-found: ignore conclusion: @@ -1094,9 +998,8 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "自动处理 Issue" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/auto-code.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "0.137.0" - GH_AW_INFO_AWF_VERSION: "v0.27.2" - GH_AW_INFO_ENGINE_ID: "codex" + GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_ENGINE_ID: "copilot" - name: Download agent output artifact id: download-agent-output continue-on-error: true @@ -1208,8 +1111,7 @@ jobs: GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} GH_AW_WORKFLOW_ID: "auto-code" GH_AW_ACTION_FAILURE_ISSUE_EXPIRES_HOURS: "168" - GH_AW_ENGINE_ID: "codex" - GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.activation.outputs.secret_verification_result }} + GH_AW_ENGINE_ID: "copilot" GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens || '' }} GH_AW_AI_CREDITS_RATE_LIMIT_ERROR: ${{ needs.agent.outputs.ai_credits_rate_limit_error || 'false' }} @@ -1220,7 +1122,7 @@ jobs: 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_ENGINE_API_HOSTS: "api.openai.com" + GH_AW_ENGINE_API_HOSTS: "api.enterprise.githubcopilot.com,api.githubcopilot.com,api.business.githubcopilot.com,api.individual.githubcopilot.com" 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 }} @@ -1259,9 +1161,8 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "自动处理 Issue" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/auto-code.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "0.137.0" - GH_AW_INFO_AWF_VERSION: "v0.27.2" - GH_AW_INFO_ENGINE_ID: "codex" + GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_ENGINE_ID: "copilot" - name: Check team membership for workflow id: check_membership uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -1293,8 +1194,9 @@ jobs: GH_AW_AMBIENT_CONTEXT: ${{ needs.agent.outputs.ambient_context }} GH_AW_CALLER_WORKFLOW_ID: "${{ github.repository }}/auto-code" GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens }} - GH_AW_ENGINE_ID: "codex" - GH_AW_ENGINE_MODEL: "doubao-seed-2-0-code-preview-260215" + GH_AW_ENGINE_ID: "copilot" + GH_AW_ENGINE_MODEL: ${{ needs.agent.outputs.model }} + GH_AW_ENGINE_VERSION: "1.0.60" GH_AW_WORKFLOW_ID: "auto-code" GH_AW_WORKFLOW_NAME: "自动处理 Issue" GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/auto-code.md" @@ -1321,9 +1223,8 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "自动处理 Issue" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/auto-code.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "0.137.0" - GH_AW_INFO_AWF_VERSION: "v0.27.2" - GH_AW_INFO_ENGINE_ID: "codex" + GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_ENGINE_ID: "copilot" - name: Download agent output artifact id: download-agent-output continue-on-error: true @@ -1400,7 +1301,7 @@ jobs: 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_ALLOWED_DOMAINS: "172.30.0.1,api.github.com,api.openai.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,chatgpt.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,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,openai.com,packagecloud.io,packages.cloud.google.com,packages.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" + GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,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,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.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},\"create_pull_request\":{\"base_branch\":\"develop\",\"max\":1,\"max_patch_files\":100,\"max_patch_size\":1024,\"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\",\"CHANGELOG.md\",\"SECURITY.md\",\"CODE_OF_CONDUCT.md\",\"AGENTS.md\",\"CLAUDE.md\",\"GEMINI.md\"],\"protected_files_policy\":\"request_review\"},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"report_incomplete\":{}}" diff --git a/.github/workflows/auto-code.md b/.github/workflows/auto-code.md index 13ac6436..4dc2bc88 100644 --- a/.github/workflows/auto-code.md +++ b/.github/workflows/auto-code.md @@ -4,15 +4,19 @@ on: types: [labeled] engine: - id: codex + id: copilot env: - OPENAI_BASE_URL: "https://ark.cn-beijing.volces.com/api/v3" - OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - CODEX_MODEL: doubao-seed-2-0-code-preview-260215 - model: doubao-seed-2-0-code-preview-260215 - token-weights: - multipliers: - doubao: 0.5 + COPILOT_PROVIDER_BASE_URL: "https://ark.cn-beijing.volces.com/api/v3" + COPILOT_PROVIDER_BEARER_TOKEN: ${{ secrets.OPENAI_API_KEY }} + COPILOT_MODEL: doubao-seed-2-0-code-preview-260215 + COPILOT_PROVIDER_TYPE: openai + COPILOT_PROVIDER_WIRE_API: responses + +features: + dangerously-disable-sandbox-agent: "controlled environment for issue triage automation" +sandbox: + agent: false +strict: false network: allowed: From 0577fa9941e5e4e13d0bce94531ee1f69104c56c Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Tue, 23 Jun 2026 14:48:35 +0800 Subject: [PATCH 44/59] feat: add agentic workflows for issue triage and auto fix --- .github/workflows/auto-code.lock.yml | 6 ++-- .github/workflows/auto-code.md | 37 ++++++++++++++++++++----- .github/workflows/issue-triage.lock.yml | 2 +- .github/workflows/issue-triage.md | 2 +- 4 files changed, 36 insertions(+), 11 deletions(-) diff --git a/.github/workflows/auto-code.lock.yml b/.github/workflows/auto-code.lock.yml index 0c3a48bf..3a16e64d 100644 --- a/.github/workflows/auto-code.lock.yml +++ b/.github/workflows/auto-code.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"31e704abf0cc67a7873ed877b1f39e07f391c21da86512dc05e99f3d5e2df28a","body_hash":"9959a757362d73cb28768bc2f9a90afc30a49f61e3226f922c791d0cbf387678","compiler_version":"v0.79.6","agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"340de800e9f76e963530448880c49d6aa4fd6733ba59da73714733fc7b3e515b","body_hash":"933be462fe387f4bb4315169afec95edcf1360efbf55af7259bf54b9d96f7974","compiler_version":"v0.79.6","agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}} # gh-aw-manifest: {"version":1,"secrets":["GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"5c2fe865bb4dc46e1450f6ee0d0541d759aea73a","version":"v0.79.6"}],"containers":[{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]} # ___ _ _ # / _ \ | | (_) @@ -107,7 +107,7 @@ jobs: GH_AW_INFO_EXPERIMENTAL: "false" GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true" GH_AW_INFO_STAGED: "false" - GH_AW_INFO_ALLOWED_DOMAINS: '["defaults","ark.cn-beijing.volces.com","github.com","api.github.com"]' + GH_AW_INFO_ALLOWED_DOMAINS: '["defaults","ark.cn-beijing.volces.com"]' GH_AW_INFO_FIREWALL_ENABLED: "false" GH_AW_INFO_AWF_VERSION: "" GH_AW_INFO_AWMG_VERSION: "" @@ -349,6 +349,7 @@ jobs: runs-on: ubuntu-latest permissions: contents: read + copilot-requests: write issues: read pull-requests: read env: @@ -841,6 +842,7 @@ jobs: GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md GITHUB_WORKSPACE: ${{ github.workspace }} RUNNER_TEMP: ${{ runner.temp }} + S2STOKENS: true XDG_CONFIG_HOME: /home/runner - name: Detect agent errors if: always() diff --git a/.github/workflows/auto-code.md b/.github/workflows/auto-code.md index 4dc2bc88..9c49c474 100644 --- a/.github/workflows/auto-code.md +++ b/.github/workflows/auto-code.md @@ -22,8 +22,6 @@ network: allowed: - defaults - ark.cn-beijing.volces.com - - github.com - - api.github.com tools: github: @@ -33,6 +31,7 @@ permissions: contents: read issues: read pull-requests: read + copilot-requests: write safe-outputs: threat-detection: false @@ -44,13 +43,14 @@ safe-outputs: # 自动处理 Issue -当 Issue 被打上 `bug` 或 `enhancement` 标签时触发。其他标签直接退出,不做任何操作。 +当 Issue 被打上 `bug` 或 `enhancement` 或 `feature` 标签时触发。其他标签直接退出,不做任何操作。 ## 判断任务类型 读取 Issue #${{ github.event.issue.number }} 当前的标签: - 如果包含 `bug` 标签 → 执行【Bug 修复流程】 -- 如果包含 `enhancement` 标签 → 执行【新功能开发流程】 +- 如果包含 `feature` 标签 → 执行【新功能开发流程】 +- 如果包含 `enhancement` 标签 → 执行【功能改进开发流程】 - 其他情况 → 直接退出 --- @@ -67,7 +67,7 @@ safe-outputs: - 问题根因 - 修复方式 - 如何验证 -6. 在原 Issue 下用中文回复,说明已提交 PR 及修复思路 +6. 在原 Issue 下使用用户提问的语言进行回复,说明已提交 PR 及修复思路 如果问题过于复杂或信息不足,在 Issue 下用中文说明原因,不创建 PR。 @@ -88,6 +88,29 @@ safe-outputs: - 实现了哪些功能 - 涉及哪些文件改动 - 如何验证/测试 -6. 在原 Issue 下用中文回复,说明已提交 PR、实现思路和测试建议 +6. 在原 Issue 下使用用户提问的语言进行回复,说明已提交 PR、实现思路和测试建议 -如果需求描述不清晰或实现风险过大,在 Issue 下用中文说明原因,不创建 PR。 \ No newline at end of file +如果需求描述不清晰或实现风险过大,在 Issue 下用中文说明原因,不创建 PR。 + +--- + +## 功能改进开发流程 + +1. 阅读 Issue 的完整标题和正文,明确功能改进与优化的具体目标(如性能提升、代码结构重构、用户体验优化等)。 +2. 浏览仓库现有代码,评估受影响的范围,定位需要进行优化或重构的核心文件及函数。 +3. 制定改进方案,需特别注意: + - **向下兼容性**:确保本次改进不会破坏现有的公开接口(API)和已有功能。 + - **防御性编程**:优化逻辑的同时,不能降低代码的健壮性。 +4. 按照方案实施代码改动,注意: + - 保持与现有代码风格高度一致。 + - 仅针对性能、可读性或结构进行局部优化,严禁引入未经需求的无关大范围改动。 +5. 创建 Pull Request,根据改进的核心侧重点选择标题格式: + - 侧重于代码重构/可读性优化:`refactor: ` + - 侧重于运行运行效率/性能优化:`perf: ` + 在 PR 描述中说明: + - 优化的动机与改进点 + - 改进前后的对比或预期收益 + - 验证优化是否生效的测试方法 +6. 在原 Issue 下使用用户提问的语言进行回复,说明已提交 PR、优化思路及预期的提升效果。 + +如果功能改进可能带来重大的破坏性变更(Breaking Changes)或者现有代码结构不支持盲目优化,在 Issue 下用中文说明原因,保持维持原状,不创建 PR。 \ No newline at end of file diff --git a/.github/workflows/issue-triage.lock.yml b/.github/workflows/issue-triage.lock.yml index 1214c52b..9f5f7654 100644 --- a/.github/workflows/issue-triage.lock.yml +++ b/.github/workflows/issue-triage.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"6755cb1b3db280f418be9daf8f20588c0332414b28bf418786db7dc30de58d26","body_hash":"bf4f8784cdac578e246f253a70aa7f7acce80a6fcf1c9116a0f5867b9ece3260","compiler_version":"v0.79.6","agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"6755cb1b3db280f418be9daf8f20588c0332414b28bf418786db7dc30de58d26","body_hash":"b17fdb8754e311cfac38664fbaa575804386c0027689ce0def213670917f77f0","compiler_version":"v0.79.6","agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}} # gh-aw-manifest: {"version":1,"secrets":["GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"5c2fe865bb4dc46e1450f6ee0d0541d759aea73a","version":"v0.79.6"}],"containers":[{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]} # ___ _ _ # / _ \ | | (_) diff --git a/.github/workflows/issue-triage.md b/.github/workflows/issue-triage.md index 49f4115b..adb7c7d1 100644 --- a/.github/workflows/issue-triage.md +++ b/.github/workflows/issue-triage.md @@ -64,7 +64,7 @@ safe-outputs: - `duplicate`:与已有 Issue 重复 - `invalid`:信息不完整或无效 -3. 用中文回复一条友好的评论,包含: +3. 使用用户提问的语言回复一条友好的评论,包含: - 感谢用户提交 Issue - 说明你打的标签和原因 - 如果是 bug,请用户补充:复现步骤、环境信息、错误日志 From 75af77f9a7670b8e4ae67d248e1f9b7c58017b4b Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Tue, 23 Jun 2026 15:35:54 +0800 Subject: [PATCH 45/59] feat: add agentic workflows for issue triage and auto fix --- .github/workflows/auto-code.lock.yml | 4 ++-- .github/workflows/auto-code.md | 2 +- .github/workflows/issue-triage.lock.yml | 4 ++-- .github/workflows/issue-triage.md | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/auto-code.lock.yml b/.github/workflows/auto-code.lock.yml index 3a16e64d..48760890 100644 --- a/.github/workflows/auto-code.lock.yml +++ b/.github/workflows/auto-code.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"340de800e9f76e963530448880c49d6aa4fd6733ba59da73714733fc7b3e515b","body_hash":"933be462fe387f4bb4315169afec95edcf1360efbf55af7259bf54b9d96f7974","compiler_version":"v0.79.6","agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"f0999b12a45a5ac3e9a50546fe3505d0a5b37b56a980c568cde64532b837f6a7","body_hash":"933be462fe387f4bb4315169afec95edcf1360efbf55af7259bf54b9d96f7974","compiler_version":"v0.79.6","agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}} # gh-aw-manifest: {"version":1,"secrets":["GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"5c2fe865bb4dc46e1450f6ee0d0541d759aea73a","version":"v0.79.6"}],"containers":[{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]} # ___ _ _ # / _ \ | | (_) @@ -820,7 +820,7 @@ jobs: 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/copilot_harness.cjs copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-tool github --allow-tool safeoutputs --allow-tool 'shell(cat)' --allow-tool 'shell(date)' --allow-tool 'shell(echo)' --allow-tool 'shell(git add:*)' --allow-tool 'shell(git branch:*)' --allow-tool 'shell(git checkout:*)' --allow-tool 'shell(git commit:*)' --allow-tool 'shell(git merge:*)' --allow-tool 'shell(git rm:*)' --allow-tool 'shell(git status)' --allow-tool 'shell(git switch:*)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(ls)' --allow-tool 'shell(printf)' --allow-tool 'shell(pwd)' --allow-tool 'shell(safeoutputs:*)' --allow-tool 'shell(sort)' --allow-tool 'shell(tail)' --allow-tool 'shell(uniq)' --allow-tool 'shell(wc)' --allow-tool 'shell(yq)' --allow-tool write --allow-all-paths --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt 2>&1 | tee /tmp/gh-aw/agent-stdio.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE - COPILOT_MODEL: doubao-seed-2-0-code-preview-260215 + COPILOT_MODEL: doubao-seed-2-1-pro-260628 COPILOT_PROVIDER_BASE_URL: https://ark.cn-beijing.volces.com/api/v3 COPILOT_PROVIDER_BEARER_TOKEN: ${{ secrets.OPENAI_API_KEY }} COPILOT_PROVIDER_TYPE: openai diff --git a/.github/workflows/auto-code.md b/.github/workflows/auto-code.md index 9c49c474..aa873e1c 100644 --- a/.github/workflows/auto-code.md +++ b/.github/workflows/auto-code.md @@ -8,7 +8,7 @@ engine: env: COPILOT_PROVIDER_BASE_URL: "https://ark.cn-beijing.volces.com/api/v3" COPILOT_PROVIDER_BEARER_TOKEN: ${{ secrets.OPENAI_API_KEY }} - COPILOT_MODEL: doubao-seed-2-0-code-preview-260215 + COPILOT_MODEL: doubao-seed-2-1-pro-260628 COPILOT_PROVIDER_TYPE: openai COPILOT_PROVIDER_WIRE_API: responses diff --git a/.github/workflows/issue-triage.lock.yml b/.github/workflows/issue-triage.lock.yml index 9f5f7654..6a0c51e9 100644 --- a/.github/workflows/issue-triage.lock.yml +++ b/.github/workflows/issue-triage.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"6755cb1b3db280f418be9daf8f20588c0332414b28bf418786db7dc30de58d26","body_hash":"b17fdb8754e311cfac38664fbaa575804386c0027689ce0def213670917f77f0","compiler_version":"v0.79.6","agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"45a6b32f52be59e7cbe5d4e41a9f38422a8185821ed5ea13517219ed44d54a83","body_hash":"b17fdb8754e311cfac38664fbaa575804386c0027689ce0def213670917f77f0","compiler_version":"v0.79.6","agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}} # gh-aw-manifest: {"version":1,"secrets":["GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"5c2fe865bb4dc46e1450f6ee0d0541d759aea73a","version":"v0.79.6"}],"containers":[{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]} # ___ _ _ # / _ \ | | (_) @@ -769,7 +769,7 @@ jobs: 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/copilot_harness.cjs copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-tool github --allow-tool safeoutputs --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt 2>&1 | tee /tmp/gh-aw/agent-stdio.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE - COPILOT_MODEL: doubao-seed-2-0-code-preview-260215 + COPILOT_MODEL: doubao-seed-2-1-pro-260628 COPILOT_PROVIDER_BASE_URL: https://ark.cn-beijing.volces.com/api/v3 COPILOT_PROVIDER_BEARER_TOKEN: ${{ secrets.OPENAI_API_KEY }} COPILOT_PROVIDER_TYPE: openai diff --git a/.github/workflows/issue-triage.md b/.github/workflows/issue-triage.md index adb7c7d1..2c8e3ce3 100644 --- a/.github/workflows/issue-triage.md +++ b/.github/workflows/issue-triage.md @@ -8,7 +8,7 @@ engine: env: COPILOT_PROVIDER_BASE_URL: "https://ark.cn-beijing.volces.com/api/v3" COPILOT_PROVIDER_BEARER_TOKEN: ${{ secrets.OPENAI_API_KEY }} - COPILOT_MODEL: doubao-seed-2-0-code-preview-260215 + COPILOT_MODEL: doubao-seed-2-1-pro-260628 COPILOT_PROVIDER_TYPE: openai COPILOT_PROVIDER_WIRE_API: responses From 63454669d528717341c8504d5b98d8f0228c77ba Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Tue, 23 Jun 2026 17:35:44 +0800 Subject: [PATCH 46/59] feat: add agentic workflows for issue triage and auto fix --- .github/workflows/auto-code.lock.yml | 10 +++++----- .github/workflows/auto-code.md | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/auto-code.lock.yml b/.github/workflows/auto-code.lock.yml index 48760890..8855619e 100644 --- a/.github/workflows/auto-code.lock.yml +++ b/.github/workflows/auto-code.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"f0999b12a45a5ac3e9a50546fe3505d0a5b37b56a980c568cde64532b837f6a7","body_hash":"933be462fe387f4bb4315169afec95edcf1360efbf55af7259bf54b9d96f7974","compiler_version":"v0.79.6","agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"0faca3af8f2e7e23b043a560be1ba892295a7d795fa66b456110bb64b212c1e3","body_hash":"933be462fe387f4bb4315169afec95edcf1360efbf55af7259bf54b9d96f7974","compiler_version":"v0.79.6","agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}} # gh-aw-manifest: {"version":1,"secrets":["GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"5c2fe865bb4dc46e1450f6ee0d0541d759aea73a","version":"v0.79.6"}],"containers":[{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]} # ___ _ _ # / _ \ | | (_) @@ -474,9 +474,9 @@ jobs: mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs - cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_8796a8c61fc66972_EOF' - {"add_comment":{"max":1},"create_pull_request":{"base_branch":"develop","max":1,"max_patch_files":100,"max_patch_size":1024,"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","CHANGELOG.md","SECURITY.md","CODE_OF_CONDUCT.md","AGENTS.md","CLAUDE.md","GEMINI.md"],"protected_files_policy":"request_review"},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} - GH_AW_SAFE_OUTPUTS_CONFIG_8796a8c61fc66972_EOF + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_b5dafa3335f30723_EOF' + {"add_comment":{"max":1},"create_pull_request":{"base_branch":"develop","max":1,"max_patch_files":100,"max_patch_size":1024,"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","CHANGELOG.md","SECURITY.md","CODE_OF_CONDUCT.md","AGENTS.md","CLAUDE.md","GEMINI.md"],"protected_files_policy":"allowed"},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} + GH_AW_SAFE_OUTPUTS_CONFIG_b5dafa3335f30723_EOF - name: Generate Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -1306,7 +1306,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,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,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.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},\"create_pull_request\":{\"base_branch\":\"develop\",\"max\":1,\"max_patch_files\":100,\"max_patch_size\":1024,\"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\",\"CHANGELOG.md\",\"SECURITY.md\",\"CODE_OF_CONDUCT.md\",\"AGENTS.md\",\"CLAUDE.md\",\"GEMINI.md\"],\"protected_files_policy\":\"request_review\"},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"report_incomplete\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":1},\"create_pull_request\":{\"base_branch\":\"develop\",\"max\":1,\"max_patch_files\":100,\"max_patch_size\":1024,\"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\",\"CHANGELOG.md\",\"SECURITY.md\",\"CODE_OF_CONDUCT.md\",\"AGENTS.md\",\"CLAUDE.md\",\"GEMINI.md\"],\"protected_files_policy\":\"allowed\"},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"report_incomplete\":{}}" GH_AW_CI_TRIGGER_TOKEN: ${{ secrets.GH_AW_CI_TRIGGER_TOKEN }} with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/auto-code.md b/.github/workflows/auto-code.md index aa873e1c..a1a48955 100644 --- a/.github/workflows/auto-code.md +++ b/.github/workflows/auto-code.md @@ -37,6 +37,7 @@ safe-outputs: threat-detection: false create-pull-request: base-branch: develop + protected-files: allowed add-comment: max: 1 --- From 00185b65891ca5c2f20606832389c703b32eeb5b Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Wed, 24 Jun 2026 10:09:02 +0800 Subject: [PATCH 47/59] feat: add agentic workflows for issue triage and auto fix --- .github/workflows/auto-code.lock.yml | 4 ++-- .github/workflows/auto-code.md | 2 +- .github/workflows/issue-triage.lock.yml | 4 ++-- .github/workflows/issue-triage.md | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/auto-code.lock.yml b/.github/workflows/auto-code.lock.yml index 8855619e..dc2937be 100644 --- a/.github/workflows/auto-code.lock.yml +++ b/.github/workflows/auto-code.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"0faca3af8f2e7e23b043a560be1ba892295a7d795fa66b456110bb64b212c1e3","body_hash":"933be462fe387f4bb4315169afec95edcf1360efbf55af7259bf54b9d96f7974","compiler_version":"v0.79.6","agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"2db2d71c8e339e852eac5725e4d115b95a5f802b476179caca5c78d07e99d221","body_hash":"933be462fe387f4bb4315169afec95edcf1360efbf55af7259bf54b9d96f7974","compiler_version":"v0.79.6","agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}} # gh-aw-manifest: {"version":1,"secrets":["GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"5c2fe865bb4dc46e1450f6ee0d0541d759aea73a","version":"v0.79.6"}],"containers":[{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]} # ___ _ _ # / _ \ | | (_) @@ -820,7 +820,7 @@ jobs: 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/copilot_harness.cjs copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-tool github --allow-tool safeoutputs --allow-tool 'shell(cat)' --allow-tool 'shell(date)' --allow-tool 'shell(echo)' --allow-tool 'shell(git add:*)' --allow-tool 'shell(git branch:*)' --allow-tool 'shell(git checkout:*)' --allow-tool 'shell(git commit:*)' --allow-tool 'shell(git merge:*)' --allow-tool 'shell(git rm:*)' --allow-tool 'shell(git status)' --allow-tool 'shell(git switch:*)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(ls)' --allow-tool 'shell(printf)' --allow-tool 'shell(pwd)' --allow-tool 'shell(safeoutputs:*)' --allow-tool 'shell(sort)' --allow-tool 'shell(tail)' --allow-tool 'shell(uniq)' --allow-tool 'shell(wc)' --allow-tool 'shell(yq)' --allow-tool write --allow-all-paths --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt 2>&1 | tee /tmp/gh-aw/agent-stdio.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE - COPILOT_MODEL: doubao-seed-2-1-pro-260628 + COPILOT_MODEL: doubao-seed-evolving COPILOT_PROVIDER_BASE_URL: https://ark.cn-beijing.volces.com/api/v3 COPILOT_PROVIDER_BEARER_TOKEN: ${{ secrets.OPENAI_API_KEY }} COPILOT_PROVIDER_TYPE: openai diff --git a/.github/workflows/auto-code.md b/.github/workflows/auto-code.md index a1a48955..d90ad258 100644 --- a/.github/workflows/auto-code.md +++ b/.github/workflows/auto-code.md @@ -8,7 +8,7 @@ engine: env: COPILOT_PROVIDER_BASE_URL: "https://ark.cn-beijing.volces.com/api/v3" COPILOT_PROVIDER_BEARER_TOKEN: ${{ secrets.OPENAI_API_KEY }} - COPILOT_MODEL: doubao-seed-2-1-pro-260628 + COPILOT_MODEL: doubao-seed-evolving COPILOT_PROVIDER_TYPE: openai COPILOT_PROVIDER_WIRE_API: responses diff --git a/.github/workflows/issue-triage.lock.yml b/.github/workflows/issue-triage.lock.yml index 6a0c51e9..c4c7adb3 100644 --- a/.github/workflows/issue-triage.lock.yml +++ b/.github/workflows/issue-triage.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"45a6b32f52be59e7cbe5d4e41a9f38422a8185821ed5ea13517219ed44d54a83","body_hash":"b17fdb8754e311cfac38664fbaa575804386c0027689ce0def213670917f77f0","compiler_version":"v0.79.6","agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"01651461ea771a40a1d9a25bbf950f25e913d6b556796467343b77b45eabdd15","body_hash":"b17fdb8754e311cfac38664fbaa575804386c0027689ce0def213670917f77f0","compiler_version":"v0.79.6","agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}} # gh-aw-manifest: {"version":1,"secrets":["GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"5c2fe865bb4dc46e1450f6ee0d0541d759aea73a","version":"v0.79.6"}],"containers":[{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]} # ___ _ _ # / _ \ | | (_) @@ -769,7 +769,7 @@ jobs: 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/copilot_harness.cjs copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-tool github --allow-tool safeoutputs --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt 2>&1 | tee /tmp/gh-aw/agent-stdio.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE - COPILOT_MODEL: doubao-seed-2-1-pro-260628 + COPILOT_MODEL: doubao-seed-evolving COPILOT_PROVIDER_BASE_URL: https://ark.cn-beijing.volces.com/api/v3 COPILOT_PROVIDER_BEARER_TOKEN: ${{ secrets.OPENAI_API_KEY }} COPILOT_PROVIDER_TYPE: openai diff --git a/.github/workflows/issue-triage.md b/.github/workflows/issue-triage.md index 2c8e3ce3..ae117408 100644 --- a/.github/workflows/issue-triage.md +++ b/.github/workflows/issue-triage.md @@ -8,7 +8,7 @@ engine: env: COPILOT_PROVIDER_BASE_URL: "https://ark.cn-beijing.volces.com/api/v3" COPILOT_PROVIDER_BEARER_TOKEN: ${{ secrets.OPENAI_API_KEY }} - COPILOT_MODEL: doubao-seed-2-1-pro-260628 + COPILOT_MODEL: doubao-seed-evolving COPILOT_PROVIDER_TYPE: openai COPILOT_PROVIDER_WIRE_API: responses From cf70570a4dd898a22b5662fbe7776c53477645fb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 24 Jun 2026 02:52:58 +0000 Subject: [PATCH 48/59] =?UTF-8?q?feat:=20=E5=AE=9E=E7=8E=B0web=E9=AA=8C?= =?UTF-8?q?=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 添加 Web 客户端示例 (Authorize_APPWebClient.html): - WebSocket 长连接登录(端口5301) - 心跳保活(2秒间隔) - 接收服务端过期通知 AUTH_EXPIRED(0x1006) 并自动断开 - 可选MD5密码加密、动态验证码 - HTTP API辅助功能(注册、充值、查询时间、公告、Token续期) - 断线重连、实时日志界面 - 更新XEngine_Apps/README.md添加Web客户端说明 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- XEngine_Apps/Authorize_APPWebClient.html | 614 +++++++++++++++++++++++ XEngine_Apps/README.md | 16 +- 2 files changed, 629 insertions(+), 1 deletion(-) create mode 100644 XEngine_Apps/Authorize_APPWebClient.html diff --git a/XEngine_Apps/Authorize_APPWebClient.html b/XEngine_Apps/Authorize_APPWebClient.html new file mode 100644 index 00000000..2cba92da --- /dev/null +++ b/XEngine_Apps/Authorize_APPWebClient.html @@ -0,0 +1,614 @@ + + + + + +XEngine Authorize - Web 客户端示例 + + + +

+ + + + diff --git a/XEngine_Apps/README.md b/XEngine_Apps/README.md index 11e0c290..e0f5e41c 100644 --- a/XEngine_Apps/README.md +++ b/XEngine_Apps/README.md @@ -1 +1,15 @@ -appclient just only x86 and x64 debug compile on windows \ No newline at end of file +appclient just only x86 and x64 debug compile on windows + +## Authorize_APPWebClient +Web client example (`Authorize_APPWebClient.html`): A browser-based client that demonstrates WebSocket authentication with the XEngine Authorize server. Features include: +- WebSocket long connection to port 5301 with configurable server address +- User login with optional MD5 password encryption +- Heartbeat keep-alive (every 2 seconds) +- Session expiration/timeout notification (AUTH_EXPIRED) with automatic disconnection +- HTTP API support (register, recharge, query time, get announcements, token renewal) +- Dynamic verification code flow +- Auto-reconnect on unexpected disconnect +- Real-time log display + +Open the HTML file directly in any modern browser (Chrome/Firefox/Edge/Safari). No build required. +Default credentials: admin / 123123aa \ No newline at end of file From 9df3941e0cc923912083fd505ad9f7265b1a0511 Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Wed, 24 Jun 2026 14:05:48 +0800 Subject: [PATCH 49/59] feat: add agentic workflows for issue triage and auto fix --- .github/workflows/auto-code.lock.yml | 2 +- .github/workflows/auto-code.md | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/.github/workflows/auto-code.lock.yml b/.github/workflows/auto-code.lock.yml index dc2937be..b04ed548 100644 --- a/.github/workflows/auto-code.lock.yml +++ b/.github/workflows/auto-code.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"2db2d71c8e339e852eac5725e4d115b95a5f802b476179caca5c78d07e99d221","body_hash":"933be462fe387f4bb4315169afec95edcf1360efbf55af7259bf54b9d96f7974","compiler_version":"v0.79.6","agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"2db2d71c8e339e852eac5725e4d115b95a5f802b476179caca5c78d07e99d221","body_hash":"dc0f8e434922db7d88d542941296221fb03c65d33aa32c7190fd92b6ca05e13a","compiler_version":"v0.79.6","agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}} # gh-aw-manifest: {"version":1,"secrets":["GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"5c2fe865bb4dc46e1450f6ee0d0541d759aea73a","version":"v0.79.6"}],"containers":[{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]} # ___ _ _ # / _ \ | | (_) diff --git a/.github/workflows/auto-code.md b/.github/workflows/auto-code.md index d90ad258..f3f2f91b 100644 --- a/.github/workflows/auto-code.md +++ b/.github/workflows/auto-code.md @@ -54,12 +54,17 @@ safe-outputs: - 如果包含 `enhancement` 标签 → 执行【功能改进开发流程】 - 其他情况 → 直接退出 +## 任务执行限制 +- 尽量只读取相关代码文件和文档,不去操作无关代码和文件 +- 尽量减少操作时间和步骤,减少TOKEN和时间消耗 + --- + ## Bug 修复流程 1. 阅读 Issue 的完整标题和正文,理解问题现象 -2. 浏览仓库代码和文档,定位问题所在的文件和函数 +2. 浏览仓库相关代码和文档,定位问题所在的文件和函数 3. 分析根本原因 4. 实现修复方案,注意: - 保持与现有代码风格一致 @@ -77,7 +82,7 @@ safe-outputs: ## 新功能开发流程 1. 阅读 Issue 的完整标题和正文,理解需求目标 -2. 浏览仓库现有代码结构和文档,找到最相关的模块和文件 +2. 浏览仓库相关代码结构和文档,找到最相关的模块和文件 3. 制定实现方案: - 需要新增哪些文件或函数 - 需要修改哪些现有文件 @@ -98,7 +103,7 @@ safe-outputs: ## 功能改进开发流程 1. 阅读 Issue 的完整标题和正文,明确功能改进与优化的具体目标(如性能提升、代码结构重构、用户体验优化等)。 -2. 浏览仓库现有代码,评估受影响的范围,定位需要进行优化或重构的核心文件及函数。 +2. 浏览仓库相关代码,评估受影响的范围,定位需要进行优化或重构的核心文件及函数。 3. 制定改进方案,需特别注意: - **向下兼容性**:确保本次改进不会破坏现有的公开接口(API)和已有功能。 - **防御性编程**:优化逻辑的同时,不能降低代码的健壮性。 From 7dc2e98e256ce500be8ebc908e7c42c57a533616 Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Wed, 24 Jun 2026 15:20:29 +0800 Subject: [PATCH 50/59] feat: add agentic workflows for issue triage and auto fix --- .github/workflows/auto-code.lock.yml | 2 +- .github/workflows/auto-code.md | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/auto-code.lock.yml b/.github/workflows/auto-code.lock.yml index b04ed548..2a10a786 100644 --- a/.github/workflows/auto-code.lock.yml +++ b/.github/workflows/auto-code.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"2db2d71c8e339e852eac5725e4d115b95a5f802b476179caca5c78d07e99d221","body_hash":"dc0f8e434922db7d88d542941296221fb03c65d33aa32c7190fd92b6ca05e13a","compiler_version":"v0.79.6","agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"2db2d71c8e339e852eac5725e4d115b95a5f802b476179caca5c78d07e99d221","body_hash":"f4631eca0387739bc44c8ad08d5c0670c98c72198743c2ea9240d97915dca04e","compiler_version":"v0.79.6","agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}} # gh-aw-manifest: {"version":1,"secrets":["GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"5c2fe865bb4dc46e1450f6ee0d0541d759aea73a","version":"v0.79.6"}],"containers":[{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]} # ___ _ _ # / _ \ | | (_) diff --git a/.github/workflows/auto-code.md b/.github/workflows/auto-code.md index f3f2f91b..f73bb475 100644 --- a/.github/workflows/auto-code.md +++ b/.github/workflows/auto-code.md @@ -55,6 +55,7 @@ safe-outputs: - 其他情况 → 直接退出 ## 任务执行限制 +- 根据需求查找相对应的可能关联的代码文件 - 尽量只读取相关代码文件和文档,不去操作无关代码和文件 - 尽量减少操作时间和步骤,减少TOKEN和时间消耗 From bf428d30d39068655ab5e4ae0b76b347d0f57960 Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Wed, 24 Jun 2026 15:21:10 +0800 Subject: [PATCH 51/59] added:user online time of count --- .../AuthorizeModule_Database.def | 2 + .../DBModule_MySQL/DBModule_MySQL.cpp | 57 +++++++++++++++++-- .../DBModule_MySQL/DBModule_MySQL.h | 1 + .../DBModule_SQLite/DBModule_SQLite.cpp | 48 +++++++++++++++- .../DBModule_SQLite/DBModule_SQLite.h | 1 + .../Database_Define.h | 38 +++++++++++++ .../AuthorizeModule_Database/pch.cpp | 8 +++ XEngine_Source/XAuth_Protocol.h | 3 +- .../Authorize_Net.cpp | 9 +++ 9 files changed, 159 insertions(+), 8 deletions(-) diff --git a/XEngine_Source/AuthorizeModule_Database/AuthorizeModule_Database.def b/XEngine_Source/AuthorizeModule_Database/AuthorizeModule_Database.def index 07a2227f..e6c50ca0 100644 --- a/XEngine_Source/AuthorizeModule_Database/AuthorizeModule_Database.def +++ b/XEngine_Source/AuthorizeModule_Database/AuthorizeModule_Database.def @@ -14,6 +14,7 @@ EXPORTS DBModule_SQLite_UserSet DBModule_SQLite_UserList DBModule_SQLite_UserLogin + DBModule_SQLite_UserTime DBModule_SQLite_QueryLogin DBModule_SQLite_SerialInsert @@ -49,6 +50,7 @@ EXPORTS DBModule_MySQL_UserSet DBModule_MySQL_UserList DBModule_MySQL_UserLogin + DBModule_MySQL_UserTime DBModule_MySQL_QueryLogin DBModule_MySQL_SerialInsert diff --git a/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.cpp b/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.cpp index 7f427e80..9318806f 100644 --- a/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.cpp +++ b/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.cpp @@ -123,7 +123,7 @@ bool CDBModule_MySQL::DBModule_MySQL_UserRegister(AUTHREG_USERTABLE* pSt_UserInf SQLPacket_dwErrorCode = ERROR_AUTHORIZE_MODULE_DATABASE_EXIST; return false; } - _xstprintf(tszSQLStatement, _X("INSERT INTO `Authorize_User`(UserName, Password, LeftTime, EmailAddr, HardCode, CardSerialType, PhoneNumber, IDCard, nUserLevel, CreateTime) values('%s','%s','%s','%s','%s','%d',%lld,%lld,%d,NOW())"), pSt_UserInfo->st_UserInfo.tszUserName, pSt_UserInfo->st_UserInfo.tszUserPass, pSt_UserInfo->tszLeftTime, pSt_UserInfo->st_UserInfo.tszEMailAddr, pSt_UserInfo->tszHardCode, pSt_UserInfo->enSerialType, pSt_UserInfo->st_UserInfo.nPhoneNumber, pSt_UserInfo->st_UserInfo.nIDNumber, pSt_UserInfo->st_UserInfo.nUserLevel); + _xstprintf(tszSQLStatement, _X("INSERT INTO `Authorize_User`(UserName, Password, LeftTime, EmailAddr, HardCode, CardSerialType, PhoneNumber, IDCard, nUserLevel, CountTime, CreateTime) values('%s','%s','%s','%s','%s','%d',%lld,%lld,%d,0,NOW())"), pSt_UserInfo->st_UserInfo.tszUserName, pSt_UserInfo->st_UserInfo.tszUserPass, pSt_UserInfo->tszLeftTime, pSt_UserInfo->st_UserInfo.tszEMailAddr, pSt_UserInfo->tszHardCode, pSt_UserInfo->enSerialType, pSt_UserInfo->st_UserInfo.nPhoneNumber, pSt_UserInfo->st_UserInfo.nIDNumber, pSt_UserInfo->st_UserInfo.nUserLevel); if (!DataBase_MySQL_Execute(xhData, tszSQLStatement)) { SQLPacket_IsErrorOccur = true; @@ -202,14 +202,18 @@ bool CDBModule_MySQL::DBModule_MySQL_UserQuery(LPCXSTR lpszUserName, AUTHREG_USE { _tcsxcpy(pSt_UserInfo->st_UserInfo.tszUserName, pptszResult[nFliedValue]); } - //密码 nFliedValue++; if (NULL != pptszResult[nFliedValue]) { _tcsxcpy(pSt_UserInfo->st_UserInfo.tszUserPass, pptszResult[nFliedValue]); } - + //TOKEN + nFliedValue++; + if (NULL != pptszResult[nFliedValue]) + { + pSt_UserInfo->st_UserInfo.xhToken = _ttxoll(pptszResult[nFliedValue]); + } //过期时间 nFliedValue++; if (NULL != pptszResult[nFliedValue]) @@ -258,7 +262,12 @@ bool CDBModule_MySQL::DBModule_MySQL_UserQuery(LPCXSTR lpszUserName, AUTHREG_USE { pSt_UserInfo->st_UserInfo.nUserLevel = _ttxoi(pptszResult[nFliedValue]); } - + //总时间 + nFliedValue++; + if (NULL != pptszResult[nFliedValue]) + { + pSt_UserInfo->nTimeCount = _ttxoll(pptszResult[nFliedValue]); + } //登录日期 nFliedValue++; if (NULL != pptszResult[nFliedValue] && _tcsxlen(pptszResult[nFliedValue]) > 0) @@ -468,7 +477,7 @@ bool CDBModule_MySQL::DBModule_MySQL_UserSet(AUTHREG_USERTABLE* pSt_UserTable) XCHAR tszSQLStatement[1024]; //SQL语句 memset(tszSQLStatement, '\0', 1024); - _xstprintf(tszSQLStatement, _X("UPDATE `Authorize_User` SET Password = '%s',LeftTime = '%s',EmailAddr = '%s',HardCode = '%s',CardSerialType = '%d',PhoneNumber = '%lld',IDCard = '%lld',nUserLevel = '%d',UPTime = NOW(),CreateTime = '%s' WHERE UserName = '%s'"), pSt_UserTable->st_UserInfo.tszUserPass, pSt_UserTable->tszLeftTime, pSt_UserTable->st_UserInfo.tszEMailAddr, pSt_UserTable->tszHardCode, pSt_UserTable->enSerialType, pSt_UserTable->st_UserInfo.nPhoneNumber, pSt_UserTable->st_UserInfo.nIDNumber, pSt_UserTable->st_UserInfo.nUserLevel/*, pSt_UserTable->st_UserInfo.tszLoginTime*/, pSt_UserTable->st_UserInfo.tszCreateTime, pSt_UserTable->st_UserInfo.tszUserName); + _xstprintf(tszSQLStatement, _X("UPDATE `Authorize_User` SET Password = '%s',Token = '%lld',LeftTime = '%s',EmailAddr = '%s',HardCode = '%s',CardSerialType = '%d',PhoneNumber = '%lld',IDCard = '%lld',nUserLevel = '%d',CountTime = '%lld',CreateTime = '%s' WHERE UserName = '%s'"), pSt_UserTable->st_UserInfo.tszUserPass, pSt_UserTable->st_UserInfo.xhToken, pSt_UserTable->tszLeftTime, pSt_UserTable->st_UserInfo.tszEMailAddr, pSt_UserTable->tszHardCode, pSt_UserTable->enSerialType, pSt_UserTable->st_UserInfo.nPhoneNumber, pSt_UserTable->st_UserInfo.nIDNumber, pSt_UserTable->st_UserInfo.nUserLevel, pSt_UserTable->nTimeCount, pSt_UserTable->st_UserInfo.tszCreateTime, pSt_UserTable->st_UserInfo.tszUserName); //更新用户剩余时间 if (!DataBase_MySQL_Execute(xhData, tszSQLStatement)) @@ -548,6 +557,9 @@ bool CDBModule_MySQL::DBModule_MySQL_UserList(AUTHREG_USERTABLE*** pppSt_UserInf //密码 nFliedValue++; _tcsxcpy((*pppSt_UserInfo)[i]->st_UserInfo.tszUserPass, ppszResult[nFliedValue]); + //TOKEN + nFliedValue++; + (*pppSt_UserInfo)[i]->st_UserInfo.xhToken = _ttxoll(ppszResult[nFliedValue]); //过期时间 nFliedValue++; _tcsxcpy((*pppSt_UserInfo)[i]->tszLeftTime, ppszResult[nFliedValue]); @@ -569,6 +581,9 @@ bool CDBModule_MySQL::DBModule_MySQL_UserList(AUTHREG_USERTABLE*** pppSt_UserInf //用户级别 -1表示封禁 nFliedValue++; (*pppSt_UserInfo)[i]->st_UserInfo.nUserLevel = _ttxoi(ppszResult[nFliedValue]); + //总时间 + nFliedValue++; + (*pppSt_UserInfo)[i]->nTimeCount = _ttxoll(ppszResult[nFliedValue]); //登录日期 nFliedValue++; if (NULL != ppszResult[nFliedValue] && _tcsxlen(ppszResult[nFliedValue]) > 0) @@ -620,6 +635,38 @@ bool CDBModule_MySQL::DBModule_MySQL_UserLogin(LPCXSTR lpszUserName, LPCXSTR lps return true; } /******************************************************************** +函数名称:DBModule_MySQL_UserTime +函数功能:增加用户在线时间 + 参数.一:lpszUserName + In/Out:In + 类型:常量字符指针 + 可空:N + 意思:用户名 + 参数.二:nTime + In/Out:In + 类型:整数型 + 可空:N + 意思:增加的时间 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +bool CDBModule_MySQL::DBModule_MySQL_UserTime(LPCXSTR lpszUserName, __int64x nTime) +{ + SQLPacket_IsErrorOccur = false; + XCHAR tszSQLStatement[1024] = {}; + _xstprintf(tszSQLStatement, _X("UPDATE Authorize_Login SET CountTime = CountTime + %lld WHERE UserName = '%s'"), nTime, lpszUserName); + + if (!DataBase_MySQL_Execute(xhData, tszSQLStatement)) + { + SQLPacket_IsErrorOccur = true; + SQLPacket_dwErrorCode = ERROR_AUTHORIZE_MODULE_DATABASE_ISFAILED; + return false; + } + return true; +} +/******************************************************************** 函数名称:DBModule_MySQL_QueryLogin 函数功能:用户登录记录查询 参数.一:lpszUserName diff --git a/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.h b/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.h index 71f85531..9945666c 100644 --- a/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.h +++ b/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.h @@ -31,6 +31,7 @@ class CDBModule_MySQL bool DBModule_MySQL_UserSet(AUTHREG_USERTABLE* pSt_UserTable); //设置用户信息 bool DBModule_MySQL_UserList(AUTHREG_USERTABLE*** pppSt_UserInfo, int* pInt_ListCount, int nPosStart, int nPosEnd); //获取用户列表 bool DBModule_MySQL_UserLogin(LPCXSTR lpszUserName, LPCXSTR lpszUserAddr); + bool DBModule_MySQL_UserTime(LPCXSTR lpszUserName, __int64x nTime); bool DBModule_MySQL_QueryLogin(LPCXSTR lpszUserName, LPCXSTR lpszUserAddr); public: bool DBModule_MySQL_SerialInsert(AUTHREG_SERIALTABLE* pSt_SerialTable); //插入序列卡 diff --git a/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.cpp b/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.cpp index 56ff3dc7..845b3e95 100644 --- a/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.cpp +++ b/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.cpp @@ -126,7 +126,7 @@ bool CDBModule_SQLite::DBModule_SQLite_UserRegister(AUTHREG_USERTABLE* pSt_UserI SQLPacket_dwErrorCode = ERROR_AUTHORIZE_MODULE_DATABASE_EXIST; return false; } - _xstprintf(tszSQLStatement, _X("INSERT INTO Authorize_User(UserName, Password, LeftTime, EmailAddr, HardCode, CardSerialType, PhoneNumber, IDCard, nUserLevel, CreateTime) values('%s','%s','%s','%s','%s','%d',%lld,%lld,%d,datetime('now', 'localtime'))"), pSt_UserInfo->st_UserInfo.tszUserName, pSt_UserInfo->st_UserInfo.tszUserPass, pSt_UserInfo->tszLeftTime, pSt_UserInfo->st_UserInfo.tszEMailAddr, pSt_UserInfo->tszHardCode, pSt_UserInfo->enSerialType, pSt_UserInfo->st_UserInfo.nPhoneNumber, pSt_UserInfo->st_UserInfo.nIDNumber, pSt_UserInfo->st_UserInfo.nUserLevel); + _xstprintf(tszSQLStatement, _X("INSERT INTO Authorize_User(UserName, Password, LeftTime, EmailAddr, HardCode, CardSerialType, PhoneNumber, IDCard, nUserLevel, CountTime, CreateTime) values('%s','%s','%s','%s','%s','%d',%lld,%lld,%d,0,datetime('now', 'localtime'))"), pSt_UserInfo->st_UserInfo.tszUserName, pSt_UserInfo->st_UserInfo.tszUserPass, pSt_UserInfo->tszLeftTime, pSt_UserInfo->st_UserInfo.tszEMailAddr, pSt_UserInfo->tszHardCode, pSt_UserInfo->enSerialType, pSt_UserInfo->st_UserInfo.nPhoneNumber, pSt_UserInfo->st_UserInfo.nIDNumber, pSt_UserInfo->st_UserInfo.nUserLevel); if (!DataBase_SQLite_Exec(xhData, tszSQLStatement)) { SQLPacket_IsErrorOccur = true; @@ -201,6 +201,9 @@ bool CDBModule_SQLite::DBModule_SQLite_UserQuery(LPCXSTR lpszUserName, AUTHREG_U //密码 nFliedValue++; _tcsxcpy(pSt_UserInfo->st_UserInfo.tszUserPass, ppszResult[nFliedValue]); + //TOKEN + nFliedValue++; + pSt_UserInfo->st_UserInfo.xhToken = _ttxoll(ppszResult[nFliedValue]); //过期时间 nFliedValue++; _tcsxcpy(pSt_UserInfo->tszLeftTime, ppszResult[nFliedValue]); @@ -222,6 +225,9 @@ bool CDBModule_SQLite::DBModule_SQLite_UserQuery(LPCXSTR lpszUserName, AUTHREG_U //用户级别 -1表示封禁 nFliedValue++; pSt_UserInfo->st_UserInfo.nUserLevel = _ttxoi(ppszResult[nFliedValue]); + //总共时间 + nFliedValue++; + pSt_UserInfo->nTimeCount = _ttxoll(ppszResult[nFliedValue]); //登录日期 nFliedValue++; if (NULL != ppszResult[nFliedValue] && _tcsxlen(ppszResult[nFliedValue]) > 0) @@ -427,7 +433,7 @@ bool CDBModule_SQLite::DBModule_SQLite_UserSet(AUTHREG_USERTABLE* pSt_UserTable) XCHAR tszSQLStatement[1024]; //SQL语句 memset(tszSQLStatement, '\0', 1024); - _xstprintf(tszSQLStatement, _X("UPDATE Authorize_User SET Password = '%s',LeftTime = '%s',EmailAddr = '%s',HardCode = '%s',CardSerialType = '%d',PhoneNumber = '%lld',IDCard = '%lld',nUserLevel = '%d',UPTime = '%s',CreateTime = '%s' WHERE UserName = '%s'"), pSt_UserTable->st_UserInfo.tszUserPass, pSt_UserTable->tszLeftTime, pSt_UserTable->st_UserInfo.tszEMailAddr, pSt_UserTable->tszHardCode, pSt_UserTable->enSerialType, pSt_UserTable->st_UserInfo.nPhoneNumber, pSt_UserTable->st_UserInfo.nIDNumber, pSt_UserTable->st_UserInfo.nUserLevel, pSt_UserTable->st_UserInfo.tszLoginTime, pSt_UserTable->st_UserInfo.tszCreateTime, pSt_UserTable->st_UserInfo.tszUserName); + _xstprintf(tszSQLStatement, _X("UPDATE Authorize_User SET Password = '%s',Token = '%lld',LeftTime = '%s',EmailAddr = '%s',HardCode = '%s',CardSerialType = '%d',PhoneNumber = '%lld',IDCard = '%lld',nUserLevel = '%d',CountTime = '%lld',CreateTime = '%s' WHERE UserName = '%s'"), pSt_UserTable->st_UserInfo.tszUserPass, pSt_UserTable->st_UserInfo.xhToken, pSt_UserTable->tszLeftTime, pSt_UserTable->st_UserInfo.tszEMailAddr, pSt_UserTable->tszHardCode, pSt_UserTable->enSerialType, pSt_UserTable->st_UserInfo.nPhoneNumber, pSt_UserTable->st_UserInfo.nIDNumber, pSt_UserTable->st_UserInfo.nUserLevel, pSt_UserTable->nTimeCount, pSt_UserTable->st_UserInfo.tszCreateTime, pSt_UserTable->st_UserInfo.tszUserName); //更新用户剩余时间 if (!DataBase_SQLite_Exec(xhData, tszSQLStatement)) { @@ -500,6 +506,9 @@ bool CDBModule_SQLite::DBModule_SQLite_UserList(AUTHREG_USERTABLE*** pppSt_UserI //密码 nFliedValue++; _tcsxcpy((*pppSt_UserInfo)[i]->st_UserInfo.tszUserPass, ppszResult[nFliedValue]); + //TOKEN + nFliedValue++; + (*pppSt_UserInfo)[i]->st_UserInfo.xhToken = _ttxoll(ppszResult[nFliedValue]); //过期时间 nFliedValue++; _tcsxcpy((*pppSt_UserInfo)[i]->tszLeftTime, ppszResult[nFliedValue]); @@ -521,6 +530,9 @@ bool CDBModule_SQLite::DBModule_SQLite_UserList(AUTHREG_USERTABLE*** pppSt_UserI //用户级别 -1表示封禁 nFliedValue++; (*pppSt_UserInfo)[i]->st_UserInfo.nUserLevel = _ttxoi(ppszResult[nFliedValue]); + //总共时间 + nFliedValue++; + (*pppSt_UserInfo)[i]->nTimeCount = _ttxoll(ppszResult[nFliedValue]); //登录日期 nFliedValue++; if (NULL != ppszResult[nFliedValue] && _tcsxlen(ppszResult[nFliedValue]) > 0) @@ -571,6 +583,38 @@ bool CDBModule_SQLite::DBModule_SQLite_UserLogin(LPCXSTR lpszUserName, LPCXSTR l return true; } /******************************************************************** +函数名称:DBModule_SQLite_UserTime +函数功能:增加用户在线时间 + 参数.一:lpszUserName + In/Out:In + 类型:常量字符指针 + 可空:N + 意思:用户名 + 参数.二:nTime + In/Out:In + 类型:整数型 + 可空:N + 意思:增加的时间 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +bool CDBModule_SQLite::DBModule_SQLite_UserTime(LPCXSTR lpszUserName, __int64x nTime) +{ + SQLPacket_IsErrorOccur = false; + + XCHAR tszSQLStatement[1024] = {}; + _xstprintf(tszSQLStatement, _X("UPDATE Authorize_Login SET CountTime = CountTime + %lld WHERE UserName = '%s'"), nTime, lpszUserName); + if (!DataBase_SQLite_Exec(xhData, tszSQLStatement)) + { + SQLPacket_IsErrorOccur = true; + SQLPacket_dwErrorCode = ERROR_AUTHORIZE_MODULE_DATABASE_INSERT; + return false; + } + return true; +} +/******************************************************************** 函数名称:DBModule_SQLite_QueryLogin 函数功能:用户登录记录查询 参数.一:lpszUserName diff --git a/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.h b/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.h index 7ce8482d..065d0979 100644 --- a/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.h +++ b/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.h @@ -31,6 +31,7 @@ class CDBModule_SQLite bool DBModule_SQLite_UserSet(AUTHREG_USERTABLE* pSt_UserTable); bool DBModule_SQLite_UserList(AUTHREG_USERTABLE*** pppSt_UserInfo, int* pInt_ListCount, int nPosStart, int nPosEnd); bool DBModule_SQLite_UserLogin(LPCXSTR lpszUserName, LPCXSTR lpszUserAddr); + bool DBModule_SQLite_UserTime(LPCXSTR lpszUserName, __int64x nTime); bool DBModule_SQLite_QueryLogin(LPCXSTR lpszUserName, LPCXSTR lpszUserAddr); public: bool DBModule_SQLite_SerialInsert(AUTHREG_SERIALTABLE* pSt_SerialTable); //插入序列卡 diff --git a/XEngine_Source/AuthorizeModule_Database/Database_Define.h b/XEngine_Source/AuthorizeModule_Database/Database_Define.h index 4b3aa74d..e024ac4b 100644 --- a/XEngine_Source/AuthorizeModule_Database/Database_Define.h +++ b/XEngine_Source/AuthorizeModule_Database/Database_Define.h @@ -193,6 +193,25 @@ extern "C" bool DBModule_SQLite_UserList(AUTHREG_USERTABLE*** pppSt_UserInfo, in *********************************************************************/ extern "C" bool DBModule_SQLite_UserLogin(LPCXSTR lpszUserName, LPCXSTR lpszUserAddr); /******************************************************************** +函数名称:DBModule_SQLite_UserTime +函数功能:增加用户在线时间 + 参数.一:lpszUserName + In/Out:In + 类型:常量字符指针 + 可空:N + 意思:用户名 + 参数.二:nTime + In/Out:In + 类型:整数型 + 可空:N + 意思:增加的时间 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +extern "C" bool DBModule_SQLite_UserTime(LPCXSTR lpszUserName, __int64x nTime); +/******************************************************************** 函数名称:DBModule_SQLite_QueryLogin 函数功能:用户登录记录查询 参数.一:lpszUserName @@ -1032,6 +1051,25 @@ extern "C" bool DBModule_MySQL_AnnouncementList(AUTHREG_ANNOUNCEMENT*** ppppSt_A *********************************************************************/ extern "C" bool DBModule_MySQL_UserLogin(LPCXSTR lpszUserName, LPCXSTR lpszUserAddr); /******************************************************************** +函数名称:DBModule_MySQL_UserTime +函数功能:增加用户在线时间 + 参数.一:lpszUserName + In/Out:In + 类型:常量字符指针 + 可空:N + 意思:用户名 + 参数.二:nTime + In/Out:In + 类型:整数型 + 可空:N + 意思:增加的时间 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +extern "C" bool DBModule_MySQL_UserTime(LPCXSTR lpszUserName, __int64x nTime); +/******************************************************************** 函数名称:DBModule_MySQL_QueryLogin 函数功能:用户登录记录查询 参数.一:lpszUserName diff --git a/XEngine_Source/AuthorizeModule_Database/pch.cpp b/XEngine_Source/AuthorizeModule_Database/pch.cpp index 4260df94..fab208bb 100644 --- a/XEngine_Source/AuthorizeModule_Database/pch.cpp +++ b/XEngine_Source/AuthorizeModule_Database/pch.cpp @@ -71,6 +71,10 @@ extern "C" bool DBModule_SQLite_UserLogin(LPCXSTR lpszUserName, LPCXSTR lpszUser { return m_DBSQLite.DBModule_SQLite_UserLogin(lpszUserName, lpszUserAddr); } +extern "C" bool DBModule_SQLite_UserTime(LPCXSTR lpszUserName, __int64x nTime) +{ + return m_DBSQLite.DBModule_SQLite_UserTime(lpszUserName, nTime); +} extern "C" bool DBModule_SQLite_QueryLogin(LPCXSTR lpszUserName, LPCXSTR lpszUserAddr) { return m_DBSQLite.DBModule_SQLite_QueryLogin(lpszUserName, lpszUserAddr); @@ -262,6 +266,10 @@ extern "C" bool DBModule_MySQL_UserLogin(LPCXSTR lpszUserName, LPCXSTR lpszUserA { return m_DBMySQL.DBModule_MySQL_UserLogin(lpszUserName, lpszUserAddr); } +extern "C" bool DBModule_MySQL_UserTime(LPCXSTR lpszUserName, __int64x nTime) +{ + return m_DBMySQL.DBModule_MySQL_UserTime(lpszUserName, nTime); +} extern "C" bool DBModule_MySQL_QueryLogin(LPCXSTR lpszUserName, LPCXSTR lpszUserAddr) { return m_DBMySQL.DBModule_MySQL_QueryLogin(lpszUserName, lpszUserAddr); diff --git a/XEngine_Source/XAuth_Protocol.h b/XEngine_Source/XAuth_Protocol.h index 22c1d4d2..2cbbe2f1 100644 --- a/XEngine_Source/XAuth_Protocol.h +++ b/XEngine_Source/XAuth_Protocol.h @@ -81,7 +81,8 @@ typedef struct tag_AuthReg_UserTable XCHAR tszADDInfo[2048]; //附加信息 XCHAR tszLeftTime[64]; //剩余日期 XCHAR tszHardCode[32]; //硬件码 - ENUM_VERIFICATION_MODULE_SERIAL_TYPE enSerialType; //充值卡类型 + __int64u nTimeCount; //在线时间 + ENUM_VERIFICATION_MODULE_SERIAL_TYPE enSerialType; //充值卡类型 ENUM_PROTOCOLDEVICE_TYPE enDeviceType; //设备类型 }AUTHREG_USERTABLE, * LPAUTHREG_USERTABLE; //注册序列号表 diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Net.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Net.cpp index 204ecb90..3386eeda 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Net.cpp +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Net.cpp @@ -161,6 +161,15 @@ bool XEngine_CloseClient(LPCXSTR lpszClientAddr, int nLeaveType) _tcsxcpy(st_AuthTime.tszLeftTime, st_NETClient.tszLeftTime); _tcsxcpy(st_AuthTime.tszUserAddr, st_NETClient.tszClientAddr); + if (0 == st_AuthConfig.st_XSql.nDBType) + { + DBModule_SQLite_UserTime(st_NETClient.st_UserTable.st_UserInfo.tszUserName, st_NETClient.nOnlineTime); + } + else + { + DBModule_MySQL_UserTime(st_NETClient.st_UserTable.st_UserInfo.tszUserName, st_NETClient.nOnlineTime); + } + if (st_AuthConfig.st_XLogin.bPassAuth) { int nSDLen = 0; From 76954dffb59f19afe51882090c8691a625251d38 Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Mon, 29 Jun 2026 15:32:03 +0800 Subject: [PATCH 52/59] update:vs to 2026 for example --- .../Authorize_APPClient/Authorize_APPClient.vcxproj | 8 ++++---- .../Authorize_APPLocal/Authorize_APPLocal.vcxproj | 8 ++++---- .../Authorize_CDKeyNetVer/Authorize_CDKeyNetVer.vcxproj | 8 ++++---- .../Authorize_ClientModule/Authorize_ClientModule.vcxproj | 8 ++++---- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/XEngine_Apps/Authorize_APPClient/Authorize_APPClient.vcxproj b/XEngine_Apps/Authorize_APPClient/Authorize_APPClient.vcxproj index a1404cd6..4f71e6bc 100644 --- a/XEngine_Apps/Authorize_APPClient/Authorize_APPClient.vcxproj +++ b/XEngine_Apps/Authorize_APPClient/Authorize_APPClient.vcxproj @@ -29,26 +29,26 @@ Application true - v143 + v145 Unicode Application false - v143 + v145 true Unicode Application true - v143 + v145 Unicode Application false - v143 + v145 true Unicode diff --git a/XEngine_Apps/Authorize_APPLocal/Authorize_APPLocal.vcxproj b/XEngine_Apps/Authorize_APPLocal/Authorize_APPLocal.vcxproj index e9a4b822..df6bf489 100644 --- a/XEngine_Apps/Authorize_APPLocal/Authorize_APPLocal.vcxproj +++ b/XEngine_Apps/Authorize_APPLocal/Authorize_APPLocal.vcxproj @@ -29,26 +29,26 @@ Application true - v143 + v145 Unicode Application false - v143 + v145 true Unicode Application true - v143 + v145 Unicode Application false - v143 + v145 true Unicode diff --git a/XEngine_Apps/Authorize_CDKeyNetVer/Authorize_CDKeyNetVer.vcxproj b/XEngine_Apps/Authorize_CDKeyNetVer/Authorize_CDKeyNetVer.vcxproj index fd661dbc..a26a0645 100644 --- a/XEngine_Apps/Authorize_CDKeyNetVer/Authorize_CDKeyNetVer.vcxproj +++ b/XEngine_Apps/Authorize_CDKeyNetVer/Authorize_CDKeyNetVer.vcxproj @@ -29,26 +29,26 @@ Application true - v143 + v145 Unicode Application false - v143 + v145 true Unicode Application true - v143 + v145 Unicode Application false - v143 + v145 true Unicode diff --git a/XEngine_Apps/Authorize_ClientModule/Authorize_ClientModule.vcxproj b/XEngine_Apps/Authorize_ClientModule/Authorize_ClientModule.vcxproj index 2ce2a8f9..f1638110 100644 --- a/XEngine_Apps/Authorize_ClientModule/Authorize_ClientModule.vcxproj +++ b/XEngine_Apps/Authorize_ClientModule/Authorize_ClientModule.vcxproj @@ -29,26 +29,26 @@ Application true - v143 + v145 Unicode Application false - v143 + v145 true Unicode Application true - v143 + v145 Unicode Application false - v143 + v145 true Unicode From 684114fab8d9a56ca832e5c14253c3eb94e1991f Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Mon, 29 Jun 2026 15:51:36 +0800 Subject: [PATCH 53/59] fixed:app example build failure --- .../Authorize_APPClient.cpp | 37 +++++++++---------- .../Authorize_ClientModule.cpp | 1 + 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/XEngine_Apps/Authorize_APPClient/Authorize_APPClient.cpp b/XEngine_Apps/Authorize_APPClient/Authorize_APPClient.cpp index 8834b959..6f0b7651 100644 --- a/XEngine_Apps/Authorize_APPClient/Authorize_APPClient.cpp +++ b/XEngine_Apps/Authorize_APPClient/Authorize_APPClient.cpp @@ -40,14 +40,14 @@ using namespace std; bool bRun = true; bool bLogin = true; bool bTimeOut = true; -bool bEncrypto = false; +bool bEncrypto = true; bool bHeart = true; XNETHANDLE xhToken = 0; int nDYCode = 0; XSOCKET m_Socket = 0; LPCXSTR lpszUser = _X("123123aa"); -LPCXSTR lpszPass = _X("123123"); +LPCXSTR lpszPass = _X("123123aa"); LPCXSTR lpszHWCode = _X("2FDWAD02JD2091"); LPCXSTR lpszSerial = _X("Y5V0Y-03O2L-E7G8Y-NX1DR-3EGVO-UDIRQ-GBBKO-FGX0C"); LPCXSTR lpszEmail = _X("486179@qq.com"); @@ -66,13 +66,11 @@ XHTHREAD AuthClient_Thread() memset(&st_ProtocolHdr, '\0', sizeof(XENGINE_PROTOCOLHDR)); if (XClient_TCPSelect_RecvPkt(m_Socket, &ptszMsgBuffer, &nMsgLen, &st_ProtocolHdr)) { - XCHAR tszMsgBuffer[4096]; - memset(tszMsgBuffer, '\0', sizeof(tszMsgBuffer)); - + XCHAR tszMsgBuffer[4096] = {}; if (nMsgLen > 0 && bEncrypto) { //只有有后续数据的情况才需要解密 - Cryption_XCrypto_Decoder(ptszMsgBuffer, &nMsgLen, tszMsgBuffer, lpszPass); + Cryption_Api_CryptDecodec((LPCXBTR)ptszMsgBuffer, (XBYTE*)tszMsgBuffer, &nMsgLen, lpszPass, ENUM_XENGINE_CRYPTION_SYMMETRIC_AES128); } else { @@ -161,10 +159,10 @@ int AuthClient_Register() XCHAR tszDEBuffer[2048] = {}; nMsgLen = st_JsonRoot.toStyledString().length(); - Cryption_XCrypto_Encoder(st_JsonRoot.toStyledString().c_str(), &nMsgLen, (XBYTE*)tszENBuffer, lpszPass); + Cryption_Api_CryptEncodec((LPCXBTR)st_JsonRoot.toStyledString().c_str(), (XBYTE*)tszENBuffer, &nMsgLen, lpszPass); APIClient_Http_Request(_X("POST"), lpszUrl, tszENBuffer, NULL, &ptszMsgBuffer, &nMsgLen); - Cryption_XCrypto_Decoder(ptszMsgBuffer, &nMsgLen, tszDEBuffer, lpszPass); + Cryption_Api_CryptDecodec((LPCXBTR)ptszMsgBuffer, (XBYTE*)tszDEBuffer, &nMsgLen, lpszPass); printf("AuthClient_Register:\n%s\n", tszDEBuffer); BaseLib_Memory_FreeCStyle((XPPMEM)&ptszMsgBuffer); } @@ -197,10 +195,10 @@ int AuthClient_Pay() XCHAR tszDEBuffer[2048] = {}; nMsgLen = st_JsonRoot.toStyledString().length(); - Cryption_XCrypto_Encoder(st_JsonRoot.toStyledString().c_str(), &nMsgLen, (XBYTE*)tszENBuffer, lpszPass); + Cryption_Api_CryptEncodec((LPCXBTR)st_JsonRoot.toStyledString().c_str(), (XBYTE*)tszENBuffer, &nMsgLen, lpszPass); APIClient_Http_Request(_X("POST"), lpszUrl, tszENBuffer, NULL, &ptszMsgBuffer, &nMsgLen); - Cryption_XCrypto_Decoder(ptszMsgBuffer, &nMsgLen, tszDEBuffer, lpszPass); + Cryption_Api_CryptDecodec((LPCXBTR)ptszMsgBuffer, (XBYTE*)tszDEBuffer, &nMsgLen, lpszPass); printf("AuthClient_Pay:\n%s\n", tszDEBuffer); BaseLib_Memory_FreeCStyle((XPPMEM)&ptszMsgBuffer); } @@ -228,7 +226,7 @@ int AuthClient_DynamicCode() { XCHAR tszDEBuffer[2048] = {}; - Cryption_XCrypto_Decoder(ptszMsgBuffer, &nMsgLen, tszDEBuffer, lpszPass); + Cryption_Api_CryptDecodec((LPCXBTR)ptszMsgBuffer, (XBYTE*)tszDEBuffer, &nMsgLen, lpszPass); if (!pSt_JsonReader->parse(tszDEBuffer, tszDEBuffer + nMsgLen, &st_JsonRoot, &st_JsonError)) { return 0; @@ -297,8 +295,7 @@ int AuthClient_Login() memset(tszCodecBuffer, '\0', sizeof(tszCodecBuffer)); st_ProtocolHdr.wCrypto = ENUM_XENGINE_PROTOCOLHDR_CRYPTO_TYPE_XCRYPT; - Cryption_XCrypto_Encoder((LPCXSTR)&st_AuthUser, (int*)&st_ProtocolHdr.unPacketSize, (XBYTE*)tszCodecBuffer, lpszPass); - + Cryption_Api_CryptEncodec((LPCXBTR)&st_AuthUser, (XBYTE*)tszCodecBuffer, (int*)&st_ProtocolHdr.unPacketSize, lpszPass); memcpy(tszMsgBuffer, &st_ProtocolHdr, sizeof(XENGINE_PROTOCOLHDR)); memcpy(tszMsgBuffer + sizeof(XENGINE_PROTOCOLHDR), tszCodecBuffer, st_ProtocolHdr.unPacketSize); @@ -341,7 +338,7 @@ int AuthClient_Notice() { XCHAR tszDEBuffer[2048] = {}; - Cryption_XCrypto_Decoder(ptszMsgBuffer, &nMsgLen, tszDEBuffer, lpszPass); + Cryption_Api_CryptDecodec((LPCXBTR)ptszMsgBuffer, (XBYTE*)tszDEBuffer, &nMsgLen, lpszPass); if (!pSt_JsonReader->parse(tszDEBuffer, tszDEBuffer + nMsgLen, &st_JsonRoot, &st_JsonError)) { return 0; @@ -406,10 +403,10 @@ int AuthClient_GetPass() XCHAR tszDEBuffer[2048] = {}; nMsgLen = st_JsonRoot.toStyledString().length(); - Cryption_XCrypto_Encoder(st_JsonRoot.toStyledString().c_str(), &nMsgLen, (XBYTE*)tszENBuffer, lpszPass); + Cryption_Api_CryptEncodec((LPCXBTR)st_JsonRoot.toStyledString().c_str(), (XBYTE*)tszENBuffer, &nMsgLen, lpszPass); APIClient_Http_Request(_X("POST"), lpszUrl, tszENBuffer, NULL, &ptszMsgBuffer, &nMsgLen); - Cryption_XCrypto_Decoder(ptszMsgBuffer, &nMsgLen, tszDEBuffer, lpszPass); + Cryption_Api_CryptDecodec((LPCXBTR)ptszMsgBuffer, (XBYTE*)tszDEBuffer, &nMsgLen, lpszPass); printf("AuthClient_GetPass:\n%s\n", tszDEBuffer); BaseLib_Memory_FreeCStyle((XPPMEM)&ptszMsgBuffer); } @@ -453,10 +450,10 @@ int AuthClient_GetTime() XCHAR tszDEBuffer[2048] = {}; nMsgLen = st_JsonRoot.toStyledString().length(); - Cryption_XCrypto_Encoder(st_JsonRoot.toStyledString().c_str(), &nMsgLen, (XBYTE*)tszENBuffer, lpszPass); + Cryption_Api_CryptEncodec((LPCXBTR)st_JsonRoot.toStyledString().c_str(), (XBYTE*)tszENBuffer, &nMsgLen, lpszPass); APIClient_Http_Request(_X("GET"), tszURLStr, tszENBuffer, NULL, &ptszMsgBuffer, &nMsgLen); - Cryption_XCrypto_Decoder(ptszMsgBuffer, &nMsgLen, tszDEBuffer, lpszPass); + Cryption_Api_CryptDecodec((LPCXBTR)ptszMsgBuffer, (XBYTE*)tszDEBuffer, &nMsgLen, lpszPass); printf("AuthClient_GetTime:\n%s\n", tszDEBuffer); BaseLib_Memory_FreeCStyle((XPPMEM)&ptszMsgBuffer); } @@ -502,10 +499,10 @@ int AuthClient_Delete() XCHAR tszDEBuffer[2048] = {}; nMsgLen = st_JsonRoot.toStyledString().length(); - Cryption_XCrypto_Encoder(st_JsonRoot.toStyledString().c_str(), &nMsgLen, (XBYTE*)tszENBuffer, lpszPass); + Cryption_Api_CryptEncodec((LPCXBTR)st_JsonRoot.toStyledString().c_str(), (XBYTE*)tszENBuffer, &nMsgLen, lpszPass); APIClient_Http_Request(_X("POST"), lpszUrl, tszENBuffer, NULL, &ptszMsgBuffer, &nMsgLen); - Cryption_XCrypto_Decoder(ptszMsgBuffer, &nMsgLen, tszDEBuffer, lpszPass); + Cryption_Api_CryptDecodec((LPCXBTR)ptszMsgBuffer, (XBYTE*)tszDEBuffer, &nMsgLen, lpszPass); printf("AuthClient_Delete:\n%s\n", tszDEBuffer); BaseLib_Memory_FreeCStyle((XPPMEM)&ptszMsgBuffer); } diff --git a/XEngine_Apps/Authorize_ClientModule/Authorize_ClientModule.cpp b/XEngine_Apps/Authorize_ClientModule/Authorize_ClientModule.cpp index 6131e491..b703f600 100644 --- a/XEngine_Apps/Authorize_ClientModule/Authorize_ClientModule.cpp +++ b/XEngine_Apps/Authorize_ClientModule/Authorize_ClientModule.cpp @@ -14,6 +14,7 @@ #include using namespace std; #include +#include #include "../../XEngine_Source/XEngine_DependLibrary/XEngine_Module/XEngine_Verification/Verification_Define.h" #include "../../XEngine_Source/XEngine_DependLibrary/XEngine_Module/XEngine_Verification/Verification_Error.h" From 31c222915536f4703dc05227de5ad25db5fba083 Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Mon, 29 Jun 2026 16:17:08 +0800 Subject: [PATCH 54/59] added:insert create user name for serial created --- .../DBModule_MySQL/DBModule_MySQL.cpp | 12 +++++++++--- .../DBModule_SQLite/DBModule_SQLite.cpp | 12 +++++++++--- XEngine_Source/XAuth_Protocol.h | 1 + .../AuthorizeHTTP_Post/AuthorizeHTTP_User.cpp | 4 ++-- 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.cpp b/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.cpp index 9318806f..41413411 100644 --- a/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.cpp +++ b/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.cpp @@ -123,7 +123,7 @@ bool CDBModule_MySQL::DBModule_MySQL_UserRegister(AUTHREG_USERTABLE* pSt_UserInf SQLPacket_dwErrorCode = ERROR_AUTHORIZE_MODULE_DATABASE_EXIST; return false; } - _xstprintf(tszSQLStatement, _X("INSERT INTO `Authorize_User`(UserName, Password, LeftTime, EmailAddr, HardCode, CardSerialType, PhoneNumber, IDCard, nUserLevel, CountTime, CreateTime) values('%s','%s','%s','%s','%s','%d',%lld,%lld,%d,0,NOW())"), pSt_UserInfo->st_UserInfo.tszUserName, pSt_UserInfo->st_UserInfo.tszUserPass, pSt_UserInfo->tszLeftTime, pSt_UserInfo->st_UserInfo.tszEMailAddr, pSt_UserInfo->tszHardCode, pSt_UserInfo->enSerialType, pSt_UserInfo->st_UserInfo.nPhoneNumber, pSt_UserInfo->st_UserInfo.nIDNumber, pSt_UserInfo->st_UserInfo.nUserLevel); + _xstprintf(tszSQLStatement, _X("INSERT INTO `Authorize_User`(UserName, Password, Token, LeftTime, EmailAddr, HardCode, CardSerialType, PhoneNumber, IDCard, nUserLevel, CountTime, CreateTime) values('%s','%s','0','%s','%s','%s','%d',%lld,%lld,%d,0,NOW())"), pSt_UserInfo->st_UserInfo.tszUserName, pSt_UserInfo->st_UserInfo.tszUserPass, pSt_UserInfo->tszLeftTime, pSt_UserInfo->st_UserInfo.tszEMailAddr, pSt_UserInfo->tszHardCode, pSt_UserInfo->enSerialType, pSt_UserInfo->st_UserInfo.nPhoneNumber, pSt_UserInfo->st_UserInfo.nIDNumber, pSt_UserInfo->st_UserInfo.nUserLevel); if (!DataBase_MySQL_Execute(xhData, tszSQLStatement)) { SQLPacket_IsErrorOccur = true; @@ -739,7 +739,7 @@ bool CDBModule_MySQL::DBModule_MySQL_SerialInsert(AUTHREG_SERIALTABLE* pSt_Seria SQLPacket_dwErrorCode = ERROR_AUTHORIZE_MODULE_DATABASE_EXIST; return false; } - _xstprintf(tszSQLStatement, _X("INSERT INTO `Authorize_Serial` values(NULL,'%s','%s','%s',%d,%d,'%s','%s')"), pSt_SerialTable->tszUserName, pSt_SerialTable->tszSerialNumber, pSt_SerialTable->tszMaxTime, pSt_SerialTable->enSerialType, pSt_SerialTable->bIsUsed, pSt_SerialTable->tszCreateTime, pSt_SerialTable->tszExpiredTime); + _xstprintf(tszSQLStatement, _X("INSERT INTO `Authorize_Serial` values(NULL,'NOT','%s','%s',%d,%d,'%s','%s','%s')"), pSt_SerialTable->tszSerialNumber, pSt_SerialTable->tszMaxTime, pSt_SerialTable->enSerialType, pSt_SerialTable->bIsUsed, pSt_SerialTable->tszCreateTime, pSt_SerialTable->tszUserName, pSt_SerialTable->tszExpiredTime); if (!DataBase_MySQL_Execute(xhData, tszSQLStatement)) { @@ -843,9 +843,12 @@ bool CDBModule_MySQL::DBModule_MySQL_SerialQuery(LPCXSTR lpszSerialNumber, LPAUT //是否已经使用 nFliedValue++; pSt_SerialTable->bIsUsed = _ttxoi(ppszResult[nFliedValue]); - //超时时间 + //创建时间 nFliedValue++; _tcsxcpy(pSt_SerialTable->tszCreateTime, ppszResult[nFliedValue]); + //创建用户 + nFliedValue++; + _tcsxcpy(pSt_SerialTable->tszCreateUser, ppszResult[nFliedValue]); //过期时间 nFliedValue++; if (NULL != ppszResult[nFliedValue]) @@ -941,6 +944,9 @@ bool CDBModule_MySQL::DBModule_MySQL_SerialQueryAll(AUTHREG_SERIALTABLE*** pppSt //创建时间 _tcsxcpy((*pppSt_SerialTable)[i]->tszCreateTime, ppszResult[nFliedValue]); nFliedValue++; + //创建用户 + _tcsxcpy((*pppSt_SerialTable)[i]->tszCreateUser, ppszResult[nFliedValue]); + nFliedValue++; //过期时间 if (NULL != ppszResult[nFliedValue]) { diff --git a/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.cpp b/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.cpp index 845b3e95..e5dee934 100644 --- a/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.cpp +++ b/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.cpp @@ -126,7 +126,7 @@ bool CDBModule_SQLite::DBModule_SQLite_UserRegister(AUTHREG_USERTABLE* pSt_UserI SQLPacket_dwErrorCode = ERROR_AUTHORIZE_MODULE_DATABASE_EXIST; return false; } - _xstprintf(tszSQLStatement, _X("INSERT INTO Authorize_User(UserName, Password, LeftTime, EmailAddr, HardCode, CardSerialType, PhoneNumber, IDCard, nUserLevel, CountTime, CreateTime) values('%s','%s','%s','%s','%s','%d',%lld,%lld,%d,0,datetime('now', 'localtime'))"), pSt_UserInfo->st_UserInfo.tszUserName, pSt_UserInfo->st_UserInfo.tszUserPass, pSt_UserInfo->tszLeftTime, pSt_UserInfo->st_UserInfo.tszEMailAddr, pSt_UserInfo->tszHardCode, pSt_UserInfo->enSerialType, pSt_UserInfo->st_UserInfo.nPhoneNumber, pSt_UserInfo->st_UserInfo.nIDNumber, pSt_UserInfo->st_UserInfo.nUserLevel); + _xstprintf(tszSQLStatement, _X("INSERT INTO Authorize_User(UserName, Password, Token, LeftTime, EmailAddr, HardCode, CardSerialType, PhoneNumber, IDCard, nUserLevel, CountTime, CreateTime) values('%s','%s','0','%s','%s','%s','%d',%lld,%lld,%d,0,datetime('now', 'localtime'))"), pSt_UserInfo->st_UserInfo.tszUserName, pSt_UserInfo->st_UserInfo.tszUserPass, pSt_UserInfo->tszLeftTime, pSt_UserInfo->st_UserInfo.tszEMailAddr, pSt_UserInfo->tszHardCode, pSt_UserInfo->enSerialType, pSt_UserInfo->st_UserInfo.nPhoneNumber, pSt_UserInfo->st_UserInfo.nIDNumber, pSt_UserInfo->st_UserInfo.nUserLevel); if (!DataBase_SQLite_Exec(xhData, tszSQLStatement)) { SQLPacket_IsErrorOccur = true; @@ -687,7 +687,7 @@ bool CDBModule_SQLite::DBModule_SQLite_SerialInsert(AUTHREG_SERIALTABLE *pSt_Ser SQLPacket_dwErrorCode = ERROR_AUTHORIZE_MODULE_DATABASE_EXIST; return false; } - _xstprintf(tszSQLStatement, _X("INSERT INTO Authorize_Serial values(NULL,'%s','%s','%s',%d,%d,'%s','%s')"), pSt_SerialTable->tszUserName, pSt_SerialTable->tszSerialNumber, pSt_SerialTable->tszMaxTime, pSt_SerialTable->enSerialType, pSt_SerialTable->bIsUsed, pSt_SerialTable->tszCreateTime, pSt_SerialTable->tszExpiredTime); + _xstprintf(tszSQLStatement, _X("INSERT INTO Authorize_Serial values(NULL,'NOT','%s','%s',%d,%d,'%s','%s','%s')"), pSt_SerialTable->tszSerialNumber, pSt_SerialTable->tszMaxTime, pSt_SerialTable->enSerialType, pSt_SerialTable->bIsUsed, pSt_SerialTable->tszCreateTime, pSt_SerialTable->tszUserName, pSt_SerialTable->tszExpiredTime); if (!DataBase_SQLite_Exec(xhData, tszSQLStatement)) { @@ -786,9 +786,12 @@ bool CDBModule_SQLite::DBModule_SQLite_SerialQuery(LPCXSTR lpszSerialNumber, LPA //是否已经使用 nFliedValue++; pSt_SerialTable->bIsUsed = _ttxoi(ppszResult[nFliedValue]); - //超时时间 + //创建时间 nFliedValue++; _tcsxcpy(pSt_SerialTable->tszCreateTime, ppszResult[nFliedValue]); + //创建用户 + nFliedValue++; + _tcsxcpy(pSt_SerialTable->tszCreateUser, ppszResult[nFliedValue]); //过期时间 nFliedValue++; if (NULL != ppszResult[nFliedValue]) @@ -877,6 +880,9 @@ bool CDBModule_SQLite::DBModule_SQLite_SerialQueryAll(AUTHREG_SERIALTABLE*** ppp nFliedValue++; //创建时间 _tcsxcpy((*pppSt_SerialTable)[i]->tszCreateTime, ppszResult[nFliedValue]); + nFliedValue++; + //创建用户 + _tcsxcpy((*pppSt_SerialTable)[i]->tszCreateUser, ppszResult[nFliedValue]); nFliedValue++; //过期时间 if (NULL != ppszResult[nFliedValue]) diff --git a/XEngine_Source/XAuth_Protocol.h b/XEngine_Source/XAuth_Protocol.h index 2cbbe2f1..f72e3109 100644 --- a/XEngine_Source/XAuth_Protocol.h +++ b/XEngine_Source/XAuth_Protocol.h @@ -94,6 +94,7 @@ typedef struct tag_AuthReg_SerialTable ENUM_VERIFICATION_MODULE_SERIAL_TYPE enSerialType; //充值卡类型 int bIsUsed; //是否已经使用 XCHAR tszCreateTime[64]; //创建时间 + XCHAR tszCreateUser[64]; //创建用户 XCHAR tszExpiredTime[64]; //过期时间 }AUTHREG_SERIALTABLE, * LPAUTHREG_SERIALTABLE; //网络临时验证表 diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_User.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_User.cpp index fa438c96..88f20abf 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_User.cpp +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_User.cpp @@ -173,7 +173,7 @@ bool XEngine_AuthorizeHTTP_User(XNETHANDLE xhToken, LPCXSTR lpszClientAddr, LPCX { Protocol_Packet_HttpComm(tszSDBuffer, &nSDLen, ERROR_AUTHORIZE_PROTOCOL_NOTFOUND, "serial number not found"); XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP); - XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("HTTP客户端:%s,充值失败,充值序列卡:%s 不存在!"), lpszClientAddr, st_SerialTable.tszSerialNumber); + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("HTTP客户端:%s,充值失败,充值序列卡:%s 不存在!"), lpszClientAddr, st_UserPay.tszSerialNumber); return false; } if (_tcsxlen(st_SerialTable.tszExpiredTime) > 1) @@ -186,7 +186,7 @@ bool XEngine_AuthorizeHTTP_User(XNETHANDLE xhToken, LPCXSTR lpszClientAddr, LPCX { Protocol_Packet_HttpComm(tszSDBuffer, &nSDLen, ERROR_AUTHORIZE_PROTOCOL_EXPIRED, "serial was expired"); XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP); - XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("HTTP客户端:%s,充值失败,序列卡:%s 已经过期!"), lpszClientAddr, st_SerialTable.tszSerialNumber); + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("HTTP客户端:%s,充值失败,序列卡:%s 已经过期!"), lpszClientAddr, st_UserPay.tszSerialNumber); return false; } } From 952eddf21f5ba8ac649fe62bcf7d4e9b9d984a5a Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Mon, 29 Jun 2026 16:55:46 +0800 Subject: [PATCH 55/59] added:serial create user and user token and time count management app support --- .../DBModule_MySQL/DBModule_MySQL.cpp | 2 +- .../DBModule_SQLite/DBModule_SQLite.cpp | 2 +- .../Protocol_Packet/Protocol_Packet.cpp | 7 +++++++ .../Protocol_Parse/Protocol_Parse.cpp | 8 ++++++++ .../Authorize_Dialog/Dialog_Modify.cpp | 13 +++++++++++++ .../Authorize_Dialog/Dialog_Modify.h | 2 ++ .../Authorize_Dialog/Dialog_Serial.cpp | 14 ++++++++------ .../Authorize_Dialog/Dialog_User.cpp | 2 ++ .../XEngineAuthorizeApp.rc | Bin 49846 -> 50300 bytes .../AuthorizeHTTP_Serial.cpp | 3 ++- .../AuthorizeHTTP_Post/AuthorizeHTTP_Serial.h | 2 +- .../Authorize_HttpTask.cpp | 2 +- 12 files changed, 46 insertions(+), 11 deletions(-) diff --git a/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.cpp b/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.cpp index 41413411..27fe7003 100644 --- a/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.cpp +++ b/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.cpp @@ -739,7 +739,7 @@ bool CDBModule_MySQL::DBModule_MySQL_SerialInsert(AUTHREG_SERIALTABLE* pSt_Seria SQLPacket_dwErrorCode = ERROR_AUTHORIZE_MODULE_DATABASE_EXIST; return false; } - _xstprintf(tszSQLStatement, _X("INSERT INTO `Authorize_Serial` values(NULL,'NOT','%s','%s',%d,%d,'%s','%s','%s')"), pSt_SerialTable->tszSerialNumber, pSt_SerialTable->tszMaxTime, pSt_SerialTable->enSerialType, pSt_SerialTable->bIsUsed, pSt_SerialTable->tszCreateTime, pSt_SerialTable->tszUserName, pSt_SerialTable->tszExpiredTime); + _xstprintf(tszSQLStatement, _X("INSERT INTO `Authorize_Serial` values(NULL,'NOT','%s','%s',%d,%d,'%s','%s','%s')"), pSt_SerialTable->tszSerialNumber, pSt_SerialTable->tszMaxTime, pSt_SerialTable->enSerialType, pSt_SerialTable->bIsUsed, pSt_SerialTable->tszCreateTime, pSt_SerialTable->tszCreateUser, pSt_SerialTable->tszExpiredTime); if (!DataBase_MySQL_Execute(xhData, tszSQLStatement)) { diff --git a/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.cpp b/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.cpp index e5dee934..30c43e64 100644 --- a/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.cpp +++ b/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.cpp @@ -687,7 +687,7 @@ bool CDBModule_SQLite::DBModule_SQLite_SerialInsert(AUTHREG_SERIALTABLE *pSt_Ser SQLPacket_dwErrorCode = ERROR_AUTHORIZE_MODULE_DATABASE_EXIST; return false; } - _xstprintf(tszSQLStatement, _X("INSERT INTO Authorize_Serial values(NULL,'NOT','%s','%s',%d,%d,'%s','%s','%s')"), pSt_SerialTable->tszSerialNumber, pSt_SerialTable->tszMaxTime, pSt_SerialTable->enSerialType, pSt_SerialTable->bIsUsed, pSt_SerialTable->tszCreateTime, pSt_SerialTable->tszUserName, pSt_SerialTable->tszExpiredTime); + _xstprintf(tszSQLStatement, _X("INSERT INTO Authorize_Serial values(NULL,'NOT','%s','%s',%d,%d,'%s','%s','%s')"), pSt_SerialTable->tszSerialNumber, pSt_SerialTable->tszMaxTime, pSt_SerialTable->enSerialType, pSt_SerialTable->bIsUsed, pSt_SerialTable->tszCreateTime, pSt_SerialTable->tszCreateUser, pSt_SerialTable->tszExpiredTime); if (!DataBase_SQLite_Exec(xhData, tszSQLStatement)) { diff --git a/XEngine_Source/AuthorizeModule_Protocol/Protocol_Packet/Protocol_Packet.cpp b/XEngine_Source/AuthorizeModule_Protocol/Protocol_Packet/Protocol_Packet.cpp index 310dfb85..b78d1789 100644 --- a/XEngine_Source/AuthorizeModule_Protocol/Protocol_Packet/Protocol_Packet.cpp +++ b/XEngine_Source/AuthorizeModule_Protocol/Protocol_Packet/Protocol_Packet.cpp @@ -405,12 +405,14 @@ bool CProtocol_Packet::Protocol_Packet_HttpClientInfo(XCHAR* ptszMsgBuffer, int* st_JsonUser["tszUserName"] = pSt_UserTable->st_UserInfo.tszUserName; st_JsonUser["tszUserPass"] = pSt_UserTable->st_UserInfo.tszUserPass; + st_JsonUser["xhToken"] = pSt_UserTable->st_UserInfo.xhToken; st_JsonUser["tszEMailAddr"] = pSt_UserTable->st_UserInfo.tszEMailAddr; st_JsonUser["tszLoginTime"] = pSt_UserTable->st_UserInfo.tszLoginTime; st_JsonUser["tszCreateTime"] = pSt_UserTable->st_UserInfo.tszCreateTime; st_JsonUser["nPhoneNumber"] = (Json::Value::UInt64)pSt_UserTable->st_UserInfo.nPhoneNumber; st_JsonUser["nIDNumber"] = (Json::Value::UInt64)pSt_UserTable->st_UserInfo.nIDNumber; st_JsonUser["nUserLevel"] = pSt_UserTable->st_UserInfo.nUserLevel; + st_JsonUser["nTimeCount"] = pSt_UserTable->nTimeCount; st_JsonUser["nUserState"] = 0; st_JsonObject["tszLeftTime"] = pSt_UserTable->tszLeftTime; @@ -485,12 +487,14 @@ bool CProtocol_Packet::Protocol_Packet_HttpClientList(XCHAR* ptszMsgBuffer, int* st_JsonUser["tszUserName"] = (*pppSt_OnClient)[i]->st_UserTable.st_UserInfo.tszUserName; st_JsonUser["tszUserPass"] = (*pppSt_OnClient)[i]->st_UserTable.st_UserInfo.tszUserPass; + st_JsonUser["xhToken"] = (*pppSt_OnClient)[i]->st_UserTable.st_UserInfo.xhToken; st_JsonUser["tszEMailAddr"] = (*pppSt_OnClient)[i]->st_UserTable.st_UserInfo.tszEMailAddr; st_JsonUser["tszLoginTime"] = (*pppSt_OnClient)[i]->st_UserTable.st_UserInfo.tszLoginTime; st_JsonUser["tszCreateTime"] = (*pppSt_OnClient)[i]->st_UserTable.st_UserInfo.tszCreateTime; st_JsonUser["nPhoneNumber"] = (Json::Value::UInt64)(*pppSt_OnClient)[i]->st_UserTable.st_UserInfo.nPhoneNumber; st_JsonUser["nIDNumber"] = (Json::Value::UInt64)(*pppSt_OnClient)[i]->st_UserTable.st_UserInfo.nIDNumber; st_JsonUser["nUserLevel"] = (*pppSt_OnClient)[i]->st_UserTable.st_UserInfo.nUserLevel; + st_JsonUser["nTimeCount"] = (*pppSt_OnClient)[i]->st_UserTable.nTimeCount; st_JsonUser["nUserState"] = 1; st_JsonObject["tszClientAddr"] = (*pppSt_OnClient)[i]->tszClientAddr; @@ -525,12 +529,14 @@ bool CProtocol_Packet::Protocol_Packet_HttpClientList(XCHAR* ptszMsgBuffer, int* st_JsonUser["tszUserName"] = (*pppSt_OffClient)[i]->st_UserInfo.tszUserName; st_JsonUser["tszUserPass"] = (*pppSt_OffClient)[i]->st_UserInfo.tszUserPass; + st_JsonUser["xhToken"] = (*pppSt_OffClient)[i]->st_UserInfo.xhToken; st_JsonUser["tszEMailAddr"] = (*pppSt_OffClient)[i]->st_UserInfo.tszEMailAddr; st_JsonUser["tszLoginTime"] = (*pppSt_OffClient)[i]->st_UserInfo.tszLoginTime; st_JsonUser["tszCreateTime"] = (*pppSt_OffClient)[i]->st_UserInfo.tszCreateTime; st_JsonUser["nPhoneNumber"] = (Json::Value::UInt64)(*pppSt_OffClient)[i]->st_UserInfo.nPhoneNumber; st_JsonUser["nIDNumber"] = (Json::Value::UInt64)(*pppSt_OffClient)[i]->st_UserInfo.nIDNumber; st_JsonUser["nUserLevel"] = (*pppSt_OffClient)[i]->st_UserInfo.nUserLevel; + st_JsonUser["nTimeCount"] = (*pppSt_OffClient)[i]->nTimeCount; st_JsonUser["nUserState"] = 0; st_JsonObject["tszLeftTime"] = (*pppSt_OffClient)[i]->tszLeftTime; @@ -599,6 +605,7 @@ bool CProtocol_Packet::Protocol_Packet_HttpSerialList(XCHAR* ptszMsgBuffer, int* st_JsonObject["enSerialType"] = (*pppSt_SerialList)[i]->enSerialType; st_JsonObject["bIsUsed"] = (*pppSt_SerialList)[i]->bIsUsed; st_JsonObject["tszCreateTime"] = (*pppSt_SerialList)[i]->tszCreateTime; + st_JsonObject["tszCreateUser"] = (*pppSt_SerialList)[i]->tszCreateUser; st_JsonObject["tszExpiredTime"] = (*pppSt_SerialList)[i]->tszExpiredTime; st_JsonArray.append(st_JsonObject); } diff --git a/XEngine_Source/AuthorizeModule_Protocol/Protocol_Parse/Protocol_Parse.cpp b/XEngine_Source/AuthorizeModule_Protocol/Protocol_Parse/Protocol_Parse.cpp index 8211cec2..90567b43 100644 --- a/XEngine_Source/AuthorizeModule_Protocol/Protocol_Parse/Protocol_Parse.cpp +++ b/XEngine_Source/AuthorizeModule_Protocol/Protocol_Parse/Protocol_Parse.cpp @@ -487,6 +487,10 @@ bool CProtocol_Parse::Protocol_Parse_HttpParseTable(LPCXSTR lpszMsgBuffer, int n { _tcsxcpy(pSt_UserTable->st_UserInfo.tszUserPass, st_UserInfo["tszUserPass"].asCString()); } + if (!st_UserInfo["xhToken"].isNull()) + { + pSt_UserTable->st_UserInfo.xhToken = st_UserInfo["xhToken"].asInt64(); + } if (!st_UserInfo["tszEMailAddr"].isNull()) { _tcsxcpy(pSt_UserTable->st_UserInfo.tszEMailAddr, st_UserInfo["tszEMailAddr"].asCString()); @@ -515,6 +519,10 @@ bool CProtocol_Parse::Protocol_Parse_HttpParseTable(LPCXSTR lpszMsgBuffer, int n { pSt_UserTable->st_UserInfo.nUserState = st_UserInfo["nUserState"].asInt(); } + if (!st_UserInfo["nTimeCount"].isNull()) + { + pSt_UserTable->nTimeCount = st_UserInfo["nTimeCount"].asInt(); + } return true; } /******************************************************************** diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_Modify.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_Modify.cpp index d59ee7f9..8805e863 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_Modify.cpp +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_Modify.cpp @@ -35,6 +35,8 @@ void CDialog_Modify::DoDataExchange(CDataExchange* pDX) DDX_Control(pDX, IDC_EDIT7, m_EditHardCode); DDX_Control(pDX, IDC_BUTTON2, m_BtnModify); DDX_Control(pDX, IDC_DATETIMEPICKER1, m_DateTimeRegister); + DDX_Control(pDX, IDC_EDIT9, m_EditUserToken); + DDX_Control(pDX, IDC_EDIT11, m_EditCountTime); } @@ -139,6 +141,8 @@ BOOL CDialog_Modify::OnInitDialog() m_EditUser.SetWindowText(A2W(st_JsonObject["st_UserInfo"]["tszUserName"].asCString())); m_EditPass.SetWindowText(A2W(st_JsonObject["st_UserInfo"]["tszUserPass"].asCString())); m_EditEMail.SetWindowText(A2W(st_JsonObject["st_UserInfo"]["tszEMailAddr"].asCString())); + m_EditUserToken.SetWindowText(std::to_wstring(st_JsonObject["st_UserInfo"]["xhToken"].asInt64()).c_str()); + m_EditCountTime.SetWindowText(std::to_wstring(st_JsonObject["st_UserInfo"]["nTimeCount"].asInt64()).c_str()); COleDateTime m_OleDTime; if (m_OleDTime.ParseDateTime(A2W(st_JsonObject["st_UserInfo"]["tszCreateTime"].asCString()))) { @@ -183,6 +187,12 @@ void CDialog_Modify::OnBnClickedButton2() m_EditPass.GetWindowText(m_StrUserInfo); strcpy(st_UserTable.st_UserInfo.tszUserPass, W2A(m_StrUserInfo.GetBuffer())); m_StrUserInfo.ReleaseBuffer(); + m_EditUserToken.GetWindowText(m_StrUserInfo); + st_UserTable.st_UserInfo.xhToken = _ttxoll(W2A(m_StrUserInfo.GetBuffer())); + m_StrUserInfo.ReleaseBuffer(); + m_EditCountTime.GetWindowText(m_StrUserInfo); + st_UserTable.nTimeCount = _ttxoll(W2A(m_StrUserInfo.GetBuffer())); + m_StrUserInfo.ReleaseBuffer(); m_EditEMail.GetWindowText(m_StrUserInfo); strcpy(st_UserTable.st_UserInfo.tszEMailAddr, W2A(m_StrUserInfo.GetBuffer())); m_StrUserInfo.ReleaseBuffer(); @@ -234,11 +244,14 @@ void CDialog_Modify::OnBnClickedButton2() st_JsonUser["tszUserName"] = st_UserTable.st_UserInfo.tszUserName; st_JsonUser["tszUserPass"] = st_UserTable.st_UserInfo.tszUserPass; + st_JsonUser["xhToken"] = st_UserTable.st_UserInfo.xhToken; st_JsonUser["tszEMailAddr"] = st_UserTable.st_UserInfo.tszEMailAddr; st_JsonUser["tszCreateTime"] = st_UserTable.st_UserInfo.tszCreateTime; st_JsonUser["nPhoneNumber"] = st_UserTable.st_UserInfo.nPhoneNumber; st_JsonUser["nIDNumber"] = st_UserTable.st_UserInfo.nIDNumber; st_JsonUser["nUserLevel"] = st_UserTable.st_UserInfo.nUserLevel; + + st_JsonTable["xhToken"] = st_UserTable.nTimeCount; st_JsonTable["tszLeftTime"] = st_UserTable.tszLeftTime; st_JsonTable["tszHardCode"] = st_UserTable.tszHardCode; st_JsonTable["enSerialType"] = st_UserTable.enSerialType; diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_Modify.h b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_Modify.h index c4546bd7..4da3954c 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_Modify.h +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_Modify.h @@ -36,4 +36,6 @@ class CDialog_Modify : public CDialogEx CButton m_BtnModify; afx_msg void OnBnClickedButton3(); CDateTimeCtrl m_DateTimeRegister; + CEdit m_EditUserToken; + CEdit m_EditCountTime; }; diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_Serial.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_Serial.cpp index db6a8329..8b3b58d6 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_Serial.cpp +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_Serial.cpp @@ -53,13 +53,14 @@ BOOL CDialog_Serial::OnInitDialog() CDialogEx::OnInitDialog(); // TODO: 在此添加额外的初始化 - m_ListSerial.InsertColumn(0, _T("使用者"), LVCFMT_LEFT, 100); - m_ListSerial.InsertColumn(1, _T("序列号"), LVCFMT_LEFT, 450); + m_ListSerial.InsertColumn(0, _T("使用者"), LVCFMT_LEFT, 60); + m_ListSerial.InsertColumn(1, _T("序列号"), LVCFMT_LEFT, 350); m_ListSerial.InsertColumn(2, _T("时间/次数"), LVCFMT_LEFT, 90); m_ListSerial.InsertColumn(3, _T("卡类型"), LVCFMT_LEFT, 80); m_ListSerial.InsertColumn(4, _T("是否使用"), LVCFMT_LEFT, 80); - m_ListSerial.InsertColumn(5, _T("创建日期"), LVCFMT_LEFT, 120); - m_ListSerial.InsertColumn(6, _T("过期日期"), LVCFMT_LEFT, 120); + m_ListSerial.InsertColumn(5, _T("创建用户"), LVCFMT_LEFT, 60); + m_ListSerial.InsertColumn(6, _T("创建日期"), LVCFMT_LEFT, 120); + m_ListSerial.InsertColumn(7, _T("过期日期"), LVCFMT_LEFT, 120); m_ListSerial.SetExtendedStyle(LVS_EX_FULLROWSELECT); for (int i = 0; i < 5; i++) @@ -165,8 +166,9 @@ void CDialog_Serial::OnBnClickedButton1() { m_ListSerial.SetItemText(i, 4, _T("未使用")); } - m_ListSerial.SetItemText(i, 5, A2W(st_JsonArray["tszCreateTime"].asCString())); - m_ListSerial.SetItemText(i, 6, A2W(st_JsonArray["tszExpiredTime"].asCString())); + m_ListSerial.SetItemText(i, 5, A2W(st_JsonArray["tszCreateUser"].asCString())); + m_ListSerial.SetItemText(i, 6, A2W(st_JsonArray["tszCreateTime"].asCString())); + m_ListSerial.SetItemText(i, 7, A2W(st_JsonArray["tszExpiredTime"].asCString())); } BaseLib_Memory_FreeCStyle((XPPMEM)&ptszMsgBuffer); } diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_User.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_User.cpp index faa5e5b7..13bbfffe 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_User.cpp +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_User.cpp @@ -62,6 +62,7 @@ BOOL CDialog_User::OnInitDialog() m_ListCtrlClient.InsertColumn(6, _T("充值类型"), LVCFMT_LEFT, 80); m_ListCtrlClient.InsertColumn(7, _T("设备类型"), LVCFMT_LEFT, 80); m_ListCtrlClient.InsertColumn(8, _T("是否在线"), LVCFMT_LEFT, 80); + m_ListCtrlClient.InsertColumn(9, _T("总在线时长"), LVCFMT_LEFT, 80); m_ListCtrlClient.SetExtendedStyle(LVS_EX_FULLROWSELECT); m_EditFlushTime.SetWindowText(_T("10")); @@ -174,6 +175,7 @@ void CDialog_User::OnBnClickedButton1() m_ListCtrlClient.SetItemText(i, 6, A2W(lpszXSerialType[st_JsonArray["enSerialType"].asInt()])); m_ListCtrlClient.SetItemText(i, 7, A2W(lpszXDevType[st_JsonArray["enDeviceType"].asInt()])); m_ListCtrlClient.SetItemText(i, 8, lpszStuType[st_JsonObject["nUserState"].asInt()]); + m_ListCtrlClient.SetItemText(i, 9, std::to_wstring(st_JsonArray["nTimeCount"].asInt64()).c_str()); } BaseLib_Memory_FreeCStyle((XPPMEM)&ptszMsgBuffer); UpdateWindow(); diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/XEngineAuthorizeApp.rc b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/XEngineAuthorizeApp.rc index fbb7a2ad64107cf6d554bd551bd0b68781e33606..23a539acda5fdfad7b18237b0ae12b469d06f45f 100644 GIT binary patch delta 364 zcmYjLO-sT67=FhzGAn0+LZLy3jF8%#(=9czF*5?|5Jb=+gP;(ie-IKDs}c;JHh5>C~Zji=fNH`@B3~&mHmmTI|b3(Ig#D(xv-Y91{cs&5nw0FW|nH zjsk*-7psDECxC7>9aKpr1hiaBolP02>G?9-{hs8Wtp&bz{Nk`rth4S5ZB_L7(<69apXeG2Al9p4`<$I)=o z7}aEdiRmZqwC-_m6T@(0Jp8xH@Z7ih#4c^q7TMGwNUdbp8(iSZ3}w-@W-*#mrc7o$ zj?t_9sO$%ehhN7R5ZVhNjSSzRAzI#ysC=ue@_vl0UBTOG%9ZN%6Vc$ur)xs0Pr48N G*vt>|-eCy< delta 291 zcmeyy0I}udUYGXCcDe?W3lv!iBTqaa*Z3rBtcv8$$4T*lk56axQ&1| xnu6^$g4)0`*}#1hKg5L=P;*QtKis7~Ic5{r=0~138I0zWKW?zz9JNVF2mnJ!Q6&HX diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_Serial.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_Serial.cpp index 704898c3..17dff3ab 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_Serial.cpp +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_Serial.cpp @@ -9,7 +9,7 @@ // - Database backend is selected by st_AuthConfig.st_XSql.nDBType. // - Response data is sent back through XEngine_Client_TaskSend. // - Dynamically allocated parse/query buffers must be released after use. -bool XEngine_AuthorizeHTTP_Serial(LPCXSTR lpszClientAddr, LPCXSTR lpszAPIName, LPCXSTR lpszMsgBuffer, int nMsgLen) +bool XEngine_AuthorizeHTTP_Serial(LPCXSTR lpszClientAddr, LPCXSTR lpszClientUser, LPCXSTR lpszAPIName, LPCXSTR lpszMsgBuffer, int nMsgLen) { int nSDLen = 0; LPCXSTR lpszAPIList = _X("list"); @@ -104,6 +104,7 @@ bool XEngine_AuthorizeHTTP_Serial(LPCXSTR lpszClientAddr, LPCXSTR lpszAPIName, L _tcsxcpy(st_SerialTable.tszCreateTime, tszCreateTime); _tcsxcpy(st_SerialTable.tszExpiredTime, tszExpiredTime); _tcsxcpy(st_SerialTable.tszMaxTime, tszMaxTime); + _tcsxcpy(st_SerialTable.tszCreateUser, lpszClientUser); Verification_XAuthKey_KeySerial(st_SerialTable.tszSerialNumber, nFieldCount, 0); if (0 == st_AuthConfig.st_XSql.nDBType) diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_Serial.h b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_Serial.h index c8aca15f..95af13a7 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_Serial.h +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_Serial.h @@ -1,3 +1,3 @@ #pragma once -bool XEngine_AuthorizeHTTP_Serial(LPCXSTR lpszClientAddr, LPCXSTR lpszAPIName, LPCXSTR lpszMsgBuffer, int nMsgLen); \ No newline at end of file +bool XEngine_AuthorizeHTTP_Serial(LPCXSTR lpszClientAddr, LPCXSTR lpszClientUser, LPCXSTR lpszAPIName, LPCXSTR lpszMsgBuffer, int nMsgLen); \ No newline at end of file diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_HttpTask.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_HttpTask.cpp index d8c7a7a6..79228126 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_HttpTask.cpp +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_HttpTask.cpp @@ -238,7 +238,7 @@ bool XEngine_Client_HttpTask(LPCXSTR lpszClientAddr, LPCXSTR lpszMsgBuffer, int XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("HTTP客户端:%s,请求的API:%s 失败,因为TOKEN权限不足"), lpszClientAddr, pSt_HTTPParament->tszHttpUri); return false; } - XEngine_AuthorizeHTTP_Serial(lpszClientAddr, tszAPIName, lpszMsgBuffer, nMsgLen); + XEngine_AuthorizeHTTP_Serial(lpszClientAddr, st_UserTable.st_UserInfo.tszUserName, tszAPIName, lpszMsgBuffer, nMsgLen); } else if (0 == _tcsxncmp(lpszAPIVerSwitch, tszAPIVer, _tcsxlen(lpszAPIVerSwitch))) { From b85a294e3a6e3008d7dd673d288f30b4178a492a Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Mon, 29 Jun 2026 17:10:28 +0800 Subject: [PATCH 56/59] fixed:user token and time count process failure --- .../Protocol_Packet/Protocol_Packet.cpp | 4 +-- .../Protocol_Parse/Protocol_Parse.cpp | 9 ++--- .../Authorize_Dialog/Dialog_Modify.cpp | 2 +- .../Authorize_Dialog/Dialog_User.cpp | 34 ++++++++++--------- 4 files changed, 26 insertions(+), 23 deletions(-) diff --git a/XEngine_Source/AuthorizeModule_Protocol/Protocol_Packet/Protocol_Packet.cpp b/XEngine_Source/AuthorizeModule_Protocol/Protocol_Packet/Protocol_Packet.cpp index b78d1789..06356263 100644 --- a/XEngine_Source/AuthorizeModule_Protocol/Protocol_Packet/Protocol_Packet.cpp +++ b/XEngine_Source/AuthorizeModule_Protocol/Protocol_Packet/Protocol_Packet.cpp @@ -412,8 +412,8 @@ bool CProtocol_Packet::Protocol_Packet_HttpClientInfo(XCHAR* ptszMsgBuffer, int* st_JsonUser["nPhoneNumber"] = (Json::Value::UInt64)pSt_UserTable->st_UserInfo.nPhoneNumber; st_JsonUser["nIDNumber"] = (Json::Value::UInt64)pSt_UserTable->st_UserInfo.nIDNumber; st_JsonUser["nUserLevel"] = pSt_UserTable->st_UserInfo.nUserLevel; - st_JsonUser["nTimeCount"] = pSt_UserTable->nTimeCount; st_JsonUser["nUserState"] = 0; + st_JsonUser["nTimeCount"] = pSt_UserTable->nTimeCount; st_JsonObject["tszLeftTime"] = pSt_UserTable->tszLeftTime; st_JsonObject["tszHardCode"] = pSt_UserTable->tszHardCode; @@ -494,8 +494,8 @@ bool CProtocol_Packet::Protocol_Packet_HttpClientList(XCHAR* ptszMsgBuffer, int* st_JsonUser["nPhoneNumber"] = (Json::Value::UInt64)(*pppSt_OnClient)[i]->st_UserTable.st_UserInfo.nPhoneNumber; st_JsonUser["nIDNumber"] = (Json::Value::UInt64)(*pppSt_OnClient)[i]->st_UserTable.st_UserInfo.nIDNumber; st_JsonUser["nUserLevel"] = (*pppSt_OnClient)[i]->st_UserTable.st_UserInfo.nUserLevel; - st_JsonUser["nTimeCount"] = (*pppSt_OnClient)[i]->st_UserTable.nTimeCount; st_JsonUser["nUserState"] = 1; + st_JsonUser["nTimeCount"] = (*pppSt_OnClient)[i]->st_UserTable.nTimeCount; st_JsonObject["tszClientAddr"] = (*pppSt_OnClient)[i]->tszClientAddr; st_JsonObject["tszLeftTime"] = (*pppSt_OnClient)[i]->tszLeftTime; diff --git a/XEngine_Source/AuthorizeModule_Protocol/Protocol_Parse/Protocol_Parse.cpp b/XEngine_Source/AuthorizeModule_Protocol/Protocol_Parse/Protocol_Parse.cpp index 90567b43..40a5ed70 100644 --- a/XEngine_Source/AuthorizeModule_Protocol/Protocol_Parse/Protocol_Parse.cpp +++ b/XEngine_Source/AuthorizeModule_Protocol/Protocol_Parse/Protocol_Parse.cpp @@ -491,6 +491,10 @@ bool CProtocol_Parse::Protocol_Parse_HttpParseTable(LPCXSTR lpszMsgBuffer, int n { pSt_UserTable->st_UserInfo.xhToken = st_UserInfo["xhToken"].asInt64(); } + if (!st_UserInfo["nTimeCount"].isNull()) + { + pSt_UserTable->nTimeCount = st_UserInfo["nTimeCount"].asInt(); + } if (!st_UserInfo["tszEMailAddr"].isNull()) { _tcsxcpy(pSt_UserTable->st_UserInfo.tszEMailAddr, st_UserInfo["tszEMailAddr"].asCString()); @@ -519,10 +523,7 @@ bool CProtocol_Parse::Protocol_Parse_HttpParseTable(LPCXSTR lpszMsgBuffer, int n { pSt_UserTable->st_UserInfo.nUserState = st_UserInfo["nUserState"].asInt(); } - if (!st_UserInfo["nTimeCount"].isNull()) - { - pSt_UserTable->nTimeCount = st_UserInfo["nTimeCount"].asInt(); - } + return true; } /******************************************************************** diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_Modify.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_Modify.cpp index 8805e863..9110928e 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_Modify.cpp +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_Modify.cpp @@ -250,8 +250,8 @@ void CDialog_Modify::OnBnClickedButton2() st_JsonUser["nPhoneNumber"] = st_UserTable.st_UserInfo.nPhoneNumber; st_JsonUser["nIDNumber"] = st_UserTable.st_UserInfo.nIDNumber; st_JsonUser["nUserLevel"] = st_UserTable.st_UserInfo.nUserLevel; + st_JsonUser["nTimeCount"] = st_UserTable.nTimeCount; - st_JsonTable["xhToken"] = st_UserTable.nTimeCount; st_JsonTable["tszLeftTime"] = st_UserTable.tszLeftTime; st_JsonTable["tszHardCode"] = st_UserTable.tszHardCode; st_JsonTable["enSerialType"] = st_UserTable.enSerialType; diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_User.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_User.cpp index 13bbfffe..fa596672 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_User.cpp +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_User.cpp @@ -55,14 +55,15 @@ BOOL CDialog_User::OnInitDialog() // TODO: 在此添加额外的初始化 m_ListCtrlClient.InsertColumn(0, _T("序号"), LVCFMT_LEFT, 40); m_ListCtrlClient.InsertColumn(1, _T("用户名"), LVCFMT_LEFT, 120); - m_ListCtrlClient.InsertColumn(2, _T("IP地址"), LVCFMT_LEFT, 100); - m_ListCtrlClient.InsertColumn(3, _T("级别"), LVCFMT_LEFT, 80); - m_ListCtrlClient.InsertColumn(4, _T("在线时间(秒钟)"), LVCFMT_LEFT, 150); - m_ListCtrlClient.InsertColumn(5, _T("剩余时间/过期时间"), LVCFMT_LEFT, 150); - m_ListCtrlClient.InsertColumn(6, _T("充值类型"), LVCFMT_LEFT, 80); - m_ListCtrlClient.InsertColumn(7, _T("设备类型"), LVCFMT_LEFT, 80); - m_ListCtrlClient.InsertColumn(8, _T("是否在线"), LVCFMT_LEFT, 80); - m_ListCtrlClient.InsertColumn(9, _T("总在线时长"), LVCFMT_LEFT, 80); + m_ListCtrlClient.InsertColumn(2, _T("TOKEN"), LVCFMT_LEFT, 60); + m_ListCtrlClient.InsertColumn(3, _T("IP地址"), LVCFMT_LEFT, 100); + m_ListCtrlClient.InsertColumn(4, _T("级别"), LVCFMT_LEFT, 80); + m_ListCtrlClient.InsertColumn(5, _T("在线时间(秒钟)"), LVCFMT_LEFT, 150); + m_ListCtrlClient.InsertColumn(6, _T("剩余时间/过期时间"), LVCFMT_LEFT, 150); + m_ListCtrlClient.InsertColumn(7, _T("充值类型"), LVCFMT_LEFT, 80); + m_ListCtrlClient.InsertColumn(8, _T("设备类型"), LVCFMT_LEFT, 80); + m_ListCtrlClient.InsertColumn(9, _T("是否在线"), LVCFMT_LEFT, 80); + m_ListCtrlClient.InsertColumn(10, _T("总在线时长"), LVCFMT_LEFT, 80); m_ListCtrlClient.SetExtendedStyle(LVS_EX_FULLROWSELECT); m_EditFlushTime.SetWindowText(_T("10")); @@ -156,11 +157,12 @@ void CDialog_User::OnBnClickedButton1() m_ListCtrlClient.InsertItem(i, _T("")); m_ListCtrlClient.SetItemText(i, 0, tszIndex); m_ListCtrlClient.SetItemText(i, 1, A2W(st_JsonObject["tszUserName"].asCString())); + m_ListCtrlClient.SetItemText(i, 2, std::to_wstring(st_JsonObject["xhToken"].asInt64()).c_str()); if (!st_JsonArray["tszClientAddr"].isNull()) { - m_ListCtrlClient.SetItemText(i, 2, A2W(st_JsonArray["tszClientAddr"].asCString())); + m_ListCtrlClient.SetItemText(i, 3, A2W(st_JsonArray["tszClientAddr"].asCString())); } - m_ListCtrlClient.SetItemText(i, 3, A2W(lpszXLevelType[st_JsonObject["nUserLevel"].asInt() + 1])); + m_ListCtrlClient.SetItemText(i, 4, A2W(lpszXLevelType[st_JsonObject["nUserLevel"].asInt() + 1])); if (1 == st_JsonObject["nUserState"].asInt()) { @@ -169,13 +171,13 @@ void CDialog_User::OnBnClickedButton1() __int64x nTime = st_JsonArray["nOnlineTime"].asUInt64(); _stprintf(tszTimeStr, _T("%lld"), nTime); - m_ListCtrlClient.SetItemText(i, 4, tszTimeStr); + m_ListCtrlClient.SetItemText(i, 5, tszTimeStr); } - m_ListCtrlClient.SetItemText(i, 5, A2W(st_JsonArray["tszLeftTime"].asCString())); - m_ListCtrlClient.SetItemText(i, 6, A2W(lpszXSerialType[st_JsonArray["enSerialType"].asInt()])); - m_ListCtrlClient.SetItemText(i, 7, A2W(lpszXDevType[st_JsonArray["enDeviceType"].asInt()])); - m_ListCtrlClient.SetItemText(i, 8, lpszStuType[st_JsonObject["nUserState"].asInt()]); - m_ListCtrlClient.SetItemText(i, 9, std::to_wstring(st_JsonArray["nTimeCount"].asInt64()).c_str()); + m_ListCtrlClient.SetItemText(i, 6, A2W(st_JsonArray["tszLeftTime"].asCString())); + m_ListCtrlClient.SetItemText(i, 7, A2W(lpszXSerialType[st_JsonArray["enSerialType"].asInt()])); + m_ListCtrlClient.SetItemText(i, 8, A2W(lpszXDevType[st_JsonArray["enDeviceType"].asInt()])); + m_ListCtrlClient.SetItemText(i, 9, lpszStuType[st_JsonObject["nUserState"].asInt()]); + m_ListCtrlClient.SetItemText(i, 10, std::to_wstring(st_JsonObject["nTimeCount"].asInt64()).c_str()); } BaseLib_Memory_FreeCStyle((XPPMEM)&ptszMsgBuffer); UpdateWindow(); From 519c33bdf80a1fcd53e36e00cb8af4bb5d7229c7 Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Tue, 30 Jun 2026 09:59:07 +0800 Subject: [PATCH 57/59] fixed:verification example not process time --- .../XEngine_AuthorizeService/XEngine_AuthorizeService.cpp | 1 + XEngine_Source/XEngine_DependLibrary | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/XEngine_AuthorizeService.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/XEngine_AuthorizeService.cpp index 421bb356..c4010b5a 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/XEngine_AuthorizeService.cpp +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/XEngine_AuthorizeService.cpp @@ -469,6 +469,7 @@ int main(int argc, char** argv) //一个简单的示例,没有验证硬件码 if (Verification_XAuthKey_FileRead(&st_AuthLocal, st_AuthConfig.st_XVerification.st_XCDKey.tszKeyFile, st_AuthConfig.st_XVerification.st_XCDKey.tszKeyPass)) { + Verification_XAuthKey_KeyParse(&st_AuthLocal); Verification_XAuthKey_FileWrite(&st_AuthLocal, st_AuthConfig.st_XVerification.st_XCDKey.tszKeyFile, st_AuthConfig.st_XVerification.st_XCDKey.tszKeyPass); XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("启动服务中,授权文件验证成功,总可运行次数:%s,剩余可运行次数:%lld"), st_AuthLocal.st_AuthRegInfo.tszLeftTime, st_AuthLocal.st_AuthRegInfo.nHasTime); } diff --git a/XEngine_Source/XEngine_DependLibrary b/XEngine_Source/XEngine_DependLibrary index 8b6a9413..237be589 160000 --- a/XEngine_Source/XEngine_DependLibrary +++ b/XEngine_Source/XEngine_DependLibrary @@ -1 +1 @@ -Subproject commit 8b6a9413ad3407b06abea611a7b89a0e968e36c0 +Subproject commit 237be589ec33bba0bf3405c095db470c1d3766b3 From 1771ba1fa8506b99f5aededdd9d4c1057e84c35a Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Tue, 30 Jun 2026 10:07:32 +0800 Subject: [PATCH 58/59] update:sql db file --- XEngine_SQL/mysql.sql | 27 +++++++++++++++------------ XEngine_SQL/sqlite.sql | 33 ++++++++++++++++++--------------- 2 files changed, 33 insertions(+), 27 deletions(-) diff --git a/XEngine_SQL/mysql.sql b/XEngine_SQL/mysql.sql index 4944cb66..d0c64199 100644 --- a/XEngine_SQL/mysql.sql +++ b/XEngine_SQL/mysql.sql @@ -3,15 +3,15 @@ Source Server : QQCloud Source Server Type : MySQL - Source Server Version : 80043 (8.0.43-0ubuntu0.24.04.1) + Source Server Version : 80046 (8.0.46-0ubuntu0.24.04.2) Source Host : 118.25.14.242:3306 Source Schema : authorize Target Server Type : MySQL - Target Server Version : 80043 (8.0.43-0ubuntu0.24.04.1) + Target Server Version : 80046 (8.0.46-0ubuntu0.24.04.2) File Encoding : 65001 - Date: 20/08/2025 11:17:20 + Date: 30/06/2026 10:05:45 */ SET NAMES utf8mb4; @@ -86,13 +86,14 @@ CREATE TABLE `Authorize_Login` ( DROP TABLE IF EXISTS `Authorize_Serial`; CREATE TABLE `Authorize_Serial` ( `ID` int NOT NULL AUTO_INCREMENT, - `UserName` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL, - `SerialNumber` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL, - `MaxTime` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL, - `CardSerialType` int NULL DEFAULT NULL, - `bIsUsed` tinyint(1) NULL DEFAULT NULL, - `CreateTime` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, - `ExpiredTime` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL, + `UserName` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '使用者', + `SerialNumber` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '序列号', + `MaxTime` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '最大时间', + `CardSerialType` int NOT NULL COMMENT '卡类型', + `bIsUsed` tinyint(1) NOT NULL COMMENT '是否使用', + `CreateTime` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, + `CreateUser` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '创建用户', + `ExpiredTime` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '过期时间', PRIMARY KEY (`ID`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = DYNAMIC; @@ -126,6 +127,7 @@ CREATE TABLE `Authorize_User` ( `ID` int NOT NULL AUTO_INCREMENT, `UserName` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '用户名', `Password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '密码', + `Token` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'Token', `LeftTime` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '剩余时间', `EmailAddr` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '电子邮件', `HardCode` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '设备SN', @@ -133,14 +135,15 @@ CREATE TABLE `Authorize_User` ( `PhoneNumber` bigint NOT NULL COMMENT '电话号码', `IDCard` bigint NOT NULL COMMENT '身份证', `nUserLevel` int NOT NULL COMMENT '用户等级,数字越小越高', + `CountTime` bigint NOT NULL COMMENT '时间统计', `UPTime` datetime NULL DEFAULT NULL COMMENT '登录时间', `CreateTime` datetime NOT NULL COMMENT '注册时间', PRIMARY KEY (`ID`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = DYNAMIC; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = DYNAMIC; -- ---------------------------- -- Records of Authorize_User -- ---------------------------- -INSERT INTO `Authorize_User` VALUES (1, 'admin', '123123aa', '0', '486179@qq.com', 'DAFD2A2DAD', 1, 13699430000, 511025198881118888, 0, '2022-09-21 15:06:45', '2022-09-21 15:06:45'); +INSERT INTO `Authorize_User` VALUES (1, 'admin', '123123aa', '0', '0', '486179@qq.com', 'DAFD2A2DAD', 1, 13699430000, 511025198881118888, 0, 0, '2022-09-21 15:06:45', '2022-09-21 15:06:45'); SET FOREIGN_KEY_CHECKS = 1; diff --git a/XEngine_SQL/sqlite.sql b/XEngine_SQL/sqlite.sql index 79cc011b..7d868a4f 100644 --- a/XEngine_SQL/sqlite.sql +++ b/XEngine_SQL/sqlite.sql @@ -10,7 +10,7 @@ Target Server Version : 3045000 (3.45.0) File Encoding : 65001 - Date: 22/12/2025 11:12:05 + Date: 30/06/2026 10:05:03 */ PRAGMA foreign_keys = false; @@ -83,12 +83,13 @@ DROP TABLE IF EXISTS "Authorize_Serial"; CREATE TABLE "Authorize_Serial" ( "ID" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "UserName" TEXT, - "SerialNumber" TEXT, - "MaxTime" TEXT, - "CardSerialType" integer, - "bIsUsed" boolean, + "SerialNumber" TEXT NOT NULL, + "MaxTime" TEXT NOT NULL, + "CardSerialType" integer NOT NULL, + "bIsUsed" boolean NOT NULL, "CreateTime" TEXT NOT NULL, - "ExpiredTime" DATE + "CreateUser" TEXT NOT NULL, + "ExpiredTime" text ); -- ---------------------------- @@ -120,6 +121,7 @@ CREATE TABLE "Authorize_User" ( "ID" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "UserName" TEXT NOT NULL, "Password" TEXT NOT NULL, + "Token" TEXT NOT NULL, "LeftTime" TEXT NOT NULL, "EmailAddr" TEXT NOT NULL, "HardCode" TEXT, @@ -127,6 +129,7 @@ CREATE TABLE "Authorize_User" ( "PhoneNumber" integer NOT NULL, "IDCard" integer NOT NULL, "nUserLevel" integer NOT NULL, + "CountTime" integer NOT NULL, "UPTime" DATE, "CreateTime" DATE NOT NULL ); @@ -134,7 +137,7 @@ CREATE TABLE "Authorize_User" ( -- ---------------------------- -- Records of Authorize_User -- ---------------------------- -INSERT INTO "Authorize_User" VALUES (1, 'admin', '123123aa', '5', '486179@qq.com', 'DAFD2A2DAD', 1, 13699430000, 511025198881118888, 0, '2022-09-21 15:06:45', '2022-09-21 15:06:45'); +INSERT INTO "Authorize_User" VALUES (1, 'admin', '123123aa', '0', '5', '486179@qq.com', 'DAFD2A2DAD', 1, 13699430000, 511025198881118888, 0, 0, '2022-09-21 15:06:45', '2022-09-21 15:06:45'); -- ---------------------------- -- Table structure for sqlite_sequence @@ -148,31 +151,31 @@ CREATE TABLE "sqlite_sequence" ( -- ---------------------------- -- Records of sqlite_sequence -- ---------------------------- -INSERT INTO "sqlite_sequence" VALUES ('Authorize_BannedUser', 0); -INSERT INTO "sqlite_sequence" VALUES ('Authorize_BannedAddr', 0); -INSERT INTO "sqlite_sequence" VALUES ('Authorize_TempVer', 0); +INSERT INTO "sqlite_sequence" VALUES ('Authorize_BannedUser', 1); +INSERT INTO "sqlite_sequence" VALUES ('Authorize_BannedAddr', 1); +INSERT INTO "sqlite_sequence" VALUES ('Authorize_TempVer', 1); +INSERT INTO "sqlite_sequence" VALUES ('Authorize_Serial', 1); INSERT INTO "sqlite_sequence" VALUES ('Authorize_User', 1); -INSERT INTO "sqlite_sequence" VALUES ('Authorize_Serial', 0); -- ---------------------------- -- Auto increment value for Authorize_BannedAddr -- ---------------------------- -UPDATE "sqlite_sequence" SET seq = 0 WHERE name = 'Authorize_BannedAddr'; +UPDATE "sqlite_sequence" SET seq = 1 WHERE name = 'Authorize_BannedAddr'; -- ---------------------------- -- Auto increment value for Authorize_BannedUser -- ---------------------------- -UPDATE "sqlite_sequence" SET seq = 0 WHERE name = 'Authorize_BannedUser'; +UPDATE "sqlite_sequence" SET seq = 1 WHERE name = 'Authorize_BannedUser'; -- ---------------------------- -- Auto increment value for Authorize_Serial -- ---------------------------- -UPDATE "sqlite_sequence" SET seq = 0 WHERE name = 'Authorize_Serial'; +UPDATE "sqlite_sequence" SET seq = 1 WHERE name = 'Authorize_Serial'; -- ---------------------------- -- Auto increment value for Authorize_TempVer -- ---------------------------- -UPDATE "sqlite_sequence" SET seq = 0 WHERE name = 'Authorize_TempVer'; +UPDATE "sqlite_sequence" SET seq = 41 WHERE name = 'Authorize_TempVer'; -- ---------------------------- -- Auto increment value for Authorize_User From 210ec0b4331db9cc3b0efc828df2a345434353ac Mon Sep 17 00:00:00 2001 From: qyt <486179@qq.com> Date: Tue, 30 Jun 2026 14:34:35 +0800 Subject: [PATCH 59/59] update:app key and fixed build --- CHANGELOG | 26 ++++++++++++++++++ XEngine_Docment/Docment_en.docx | Bin 155965 -> 152537 bytes XEngine_Docment/Docment_zh.docx | Bin 160793 -> 158974 bytes XEngine_Release/APPVer.key | Bin 767 -> 736 bytes .../Protocol_Packet/Protocol_Packet.cpp | 12 ++++---- 5 files changed, 32 insertions(+), 6 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index b9b36782..c2b92b7f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,29 @@ +XEngine_Authorize V3.23.0.1001 + +ci:add agentic workflows for issue triage and auto fix +ci:delete cppcheck.yml and issue-translator.yml +added:email notify after user pay +added:user online time of count +added:insert create user name for serial created +added:serial create user and user token and time count management app support +update:vs to 2026 +modify:pay user auto adjust level +modify:warning and scan code problem +modify:token of session module instead depend session module +delete:get notice of task code and modify notice permission + +ci:增加了新的issue问题分类和处理工作流 +ci:删除了多余的工作流 +增加:用户充值邮件通知 +增加:用户在线时间统计 +增加:序列号增加用户创建字段 +增加:用户列表用户时间字段和TOKEN字段 +更新:VS编译器支持2026 +修改:用户注册后自动调整等级 +修改:通过scan扫描的代码问题 +修改:使用依赖库的会话模块替代自身的TOKEN模块 +删除:多余的通知消息 +================================================================ XEngine_Authorize V3.22.0.1001 ci:更新库依赖环境 diff --git a/XEngine_Docment/Docment_en.docx b/XEngine_Docment/Docment_en.docx index 575294e856c991ae8c0bcf6179a4a89c0fa19697..9a988725ba74f68eceb023667bb528677daf6326 100644 GIT binary patch delta 92051 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 MfB07mdneBS0CCe;lmGw# delta 95454 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

2mrpj_7M9e= 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 diff --git a/XEngine_Release/APPVer.key b/XEngine_Release/APPVer.key index 25fbd01949d8d8b770d51ace80cb30525d459594..d9af837de1a9b6f3eae308d39d49d7aa475bf71c 100644 GIT binary patch literal 736 zcmV<60w4X)A9r8Py`lJeCBkHclmd}8t(;7o!t84&mWTDU4fj(8d>XoLDAx{JW6E>3 zluRa{ACe=)Ju1jkJm|R&Srng=o{(vAXf6N?3h?5)B!d{LGfWieb3mtW z;6cs!n=2AnWN9PsuwrR!o7Ys};itGpBqnbNNem*N|02 z0&r9$f$eFSCIIEvgdzPt zNs+SKi=TrqP63p!rsNGD9~G((&MpZ{*{*1F6;>&33)hTEK!%S0aOtW}TNRyOWN( literal 767 zcmYLHOHUe67-i9P@82mRth%r6VPGDB(2-Q7Qfw?J!_WeW4CBn@G0gi859y-SHl{H~ zqO{til_12Lw9z0bCZF+Mz-{YR|oO8dK8Qb6EGVa@Y%MXH+@Se@}-e${26;T40 zgR(5=osRKkVTIq(BHsqO@)+^5w>?jDS8aK3`oQTBHJ$$Eh|^Z)8Juag8cf0 zuwr5oe|#-*fNH5j!35X!;z38{nv4e8q#eRSR3CP9o-T`^UG(8WHyRd-zIogi#u{bZ z=Q3M*Z@E%cgJ868Hj$Pu8-R!O^%rglwfI=N(<_|KnhUz@YQEKkV1ac*w$m4W+8K ztamPZZsH3COse0fzD@GeSa`XTq2frrPORnJ8_7c>>InuzemS2a;+X()^d?GY-Ttrw zaPuG1)gRqexh}$p>C2R_&OkQB>(?D&DZ5P52YHm(NQRK(dh8YDUL-U?cxWt}+skim z#^`kfvH^lHCEOiHiv}~nBXJB1ATn@c#3L-&WER6gb5vj1;VgXxOK;|=T^6f41xDvg zEn-qWZMYMO=TunO+geLL@!$V_mn#%E=H!Mx+H1{Zi) j-|m>Wl2+|?=VtR%MH;rtx?%3|WN(sC+!^-Chrj;->E5Ee diff --git a/XEngine_Source/AuthorizeModule_Protocol/Protocol_Packet/Protocol_Packet.cpp b/XEngine_Source/AuthorizeModule_Protocol/Protocol_Packet/Protocol_Packet.cpp index 06356263..b41367b1 100644 --- a/XEngine_Source/AuthorizeModule_Protocol/Protocol_Packet/Protocol_Packet.cpp +++ b/XEngine_Source/AuthorizeModule_Protocol/Protocol_Packet/Protocol_Packet.cpp @@ -405,7 +405,7 @@ bool CProtocol_Packet::Protocol_Packet_HttpClientInfo(XCHAR* ptszMsgBuffer, int* st_JsonUser["tszUserName"] = pSt_UserTable->st_UserInfo.tszUserName; st_JsonUser["tszUserPass"] = pSt_UserTable->st_UserInfo.tszUserPass; - st_JsonUser["xhToken"] = pSt_UserTable->st_UserInfo.xhToken; + st_JsonUser["xhToken"] = (Json::Value::Int64)pSt_UserTable->st_UserInfo.xhToken; st_JsonUser["tszEMailAddr"] = pSt_UserTable->st_UserInfo.tszEMailAddr; st_JsonUser["tszLoginTime"] = pSt_UserTable->st_UserInfo.tszLoginTime; st_JsonUser["tszCreateTime"] = pSt_UserTable->st_UserInfo.tszCreateTime; @@ -413,7 +413,7 @@ bool CProtocol_Packet::Protocol_Packet_HttpClientInfo(XCHAR* ptszMsgBuffer, int* st_JsonUser["nIDNumber"] = (Json::Value::UInt64)pSt_UserTable->st_UserInfo.nIDNumber; st_JsonUser["nUserLevel"] = pSt_UserTable->st_UserInfo.nUserLevel; st_JsonUser["nUserState"] = 0; - st_JsonUser["nTimeCount"] = pSt_UserTable->nTimeCount; + st_JsonUser["nTimeCount"] = (Json::Value::Int64)pSt_UserTable->nTimeCount; st_JsonObject["tszLeftTime"] = pSt_UserTable->tszLeftTime; st_JsonObject["tszHardCode"] = pSt_UserTable->tszHardCode; @@ -487,7 +487,7 @@ bool CProtocol_Packet::Protocol_Packet_HttpClientList(XCHAR* ptszMsgBuffer, int* st_JsonUser["tszUserName"] = (*pppSt_OnClient)[i]->st_UserTable.st_UserInfo.tszUserName; st_JsonUser["tszUserPass"] = (*pppSt_OnClient)[i]->st_UserTable.st_UserInfo.tszUserPass; - st_JsonUser["xhToken"] = (*pppSt_OnClient)[i]->st_UserTable.st_UserInfo.xhToken; + st_JsonUser["xhToken"] = (Json::Value::Int64)(*pppSt_OnClient)[i]->st_UserTable.st_UserInfo.xhToken; st_JsonUser["tszEMailAddr"] = (*pppSt_OnClient)[i]->st_UserTable.st_UserInfo.tszEMailAddr; st_JsonUser["tszLoginTime"] = (*pppSt_OnClient)[i]->st_UserTable.st_UserInfo.tszLoginTime; st_JsonUser["tszCreateTime"] = (*pppSt_OnClient)[i]->st_UserTable.st_UserInfo.tszCreateTime; @@ -495,7 +495,7 @@ bool CProtocol_Packet::Protocol_Packet_HttpClientList(XCHAR* ptszMsgBuffer, int* st_JsonUser["nIDNumber"] = (Json::Value::UInt64)(*pppSt_OnClient)[i]->st_UserTable.st_UserInfo.nIDNumber; st_JsonUser["nUserLevel"] = (*pppSt_OnClient)[i]->st_UserTable.st_UserInfo.nUserLevel; st_JsonUser["nUserState"] = 1; - st_JsonUser["nTimeCount"] = (*pppSt_OnClient)[i]->st_UserTable.nTimeCount; + st_JsonUser["nTimeCount"] = (Json::Value::Int64)(*pppSt_OnClient)[i]->st_UserTable.nTimeCount; st_JsonObject["tszClientAddr"] = (*pppSt_OnClient)[i]->tszClientAddr; st_JsonObject["tszLeftTime"] = (*pppSt_OnClient)[i]->tszLeftTime; @@ -529,14 +529,14 @@ bool CProtocol_Packet::Protocol_Packet_HttpClientList(XCHAR* ptszMsgBuffer, int* st_JsonUser["tszUserName"] = (*pppSt_OffClient)[i]->st_UserInfo.tszUserName; st_JsonUser["tszUserPass"] = (*pppSt_OffClient)[i]->st_UserInfo.tszUserPass; - st_JsonUser["xhToken"] = (*pppSt_OffClient)[i]->st_UserInfo.xhToken; + st_JsonUser["xhToken"] = (Json::Value::Int64)(*pppSt_OffClient)[i]->st_UserInfo.xhToken; st_JsonUser["tszEMailAddr"] = (*pppSt_OffClient)[i]->st_UserInfo.tszEMailAddr; st_JsonUser["tszLoginTime"] = (*pppSt_OffClient)[i]->st_UserInfo.tszLoginTime; st_JsonUser["tszCreateTime"] = (*pppSt_OffClient)[i]->st_UserInfo.tszCreateTime; st_JsonUser["nPhoneNumber"] = (Json::Value::UInt64)(*pppSt_OffClient)[i]->st_UserInfo.nPhoneNumber; st_JsonUser["nIDNumber"] = (Json::Value::UInt64)(*pppSt_OffClient)[i]->st_UserInfo.nIDNumber; st_JsonUser["nUserLevel"] = (*pppSt_OffClient)[i]->st_UserInfo.nUserLevel; - st_JsonUser["nTimeCount"] = (*pppSt_OffClient)[i]->nTimeCount; + st_JsonUser["nTimeCount"] = (Json::Value::Int64)(*pppSt_OffClient)[i]->nTimeCount; st_JsonUser["nUserState"] = 0; st_JsonObject["tszLeftTime"] = (*pppSt_OffClient)[i]->tszLeftTime;

^Y_0kYgL85 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 Af&c&j diff --git a/XEngine_Docment/Docment_zh.docx b/XEngine_Docment/Docment_zh.docx index 4553a3fdf4623849494c0f47f4efd67507a1f4ce..420c88cc9c722f47cc70ca8e1cd2da3d945af490 100644 GIT binary patch delta 88541 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%0DOiUXRtZh}xr% zgumyklrY%A&BUWZ(+YpC-?R8sfN2M?B(&$xqGGH|1|m&%TTaq5tt!rCRV*iI0_*pz zfgi=R0AV%=F`ZR9?9IBjSUNOeJPcQ@5wgD6;27&VX)eU5XCbJF^A_>4!BRo$dS;n) zSkM+V@XT6kC=Xvt)SpUZvY{nkqdhkzJGZB&0jx6N+eJu!P0W8wj3rcZMuO)97Ye_n zpa{~}fedtt6|gOAWP2;R^i#&ey>n6s?5Ft$x%CNp;DN#a;f7sj+!H|gKlu%R%6`{H3 zd*w_jL8#WS-!tY%tlbJnPQz%C!UZ^6;1ZDpD??8$!ygR^&^_ApLGuY9c*42gM=eI9 zR>-RAftHg%psGg-rjf2Z+-e$W-Y2c6krsW@W*Vt?oLK*W3rRUF#zHY{;IBF$hSf(d zX8@Mir0;2#f0{Eey;Y6DDgT(D2)r5sTSTJ?Ys5rEvqe->#MaFf4=ev!<8P&h7ys(g zc+hOvwy@njq9>DSQ~RnRvAekM1<4uZri>a=G=n$_u9H+Y-GNP|!D3QFj<*7EWLbS* zA^m}+_OI5qzoelB4v}Bwj%63+w~4+tAe$D^cnp#7fA^lX5(X!@-FQ-HI>Ge^HlG?W z?*UeX4t!bEj7`Nrq^)ktNe7ly&ADX7a?&=i{=gpiSxg5I<)aYuMXkeLtb2#0BNHX# zaCMH5^~DA!ST{v;A;tq6K}}qCh?fJF3DWd4%cSFi7Bs*!>*P=#zE-F|l*naEOTR{Y zZCiF>e?Oi^u&RRZHX;2rF>eW$(8(DIUk_X;{GNd#C|?IE&?z%uM>xp#QcmfqwA=Gj zP2$W>qTI19(cQHlfld*cvjm`~5-V(ka=~QFY37&rNpM_-cI_36-qTC)6ud0l(h9Fw zW3B7zXIV$-js1@| zmq$Z?-!m4A7-v$@vA?FqKbyRKak`AsSbLx?Ote&F?5EbM2q8mK%CR}-jA&_OVvmXB zNG1s*6fLEWQ6~t4%}i-Ys4-yb4HgS*`~pW-&1kX4OHg*e9wI5$maevpaBoN-jnJ?T z>a+mC4m)8T)!iF4K+dZgsMiVvUe!qbcBDstHaBQT>eNXm?MU4^Y1ocbODA4WaH*(( zkBQVATllGGh+};_S4RL=*s>|hm|X)i7?c>y#BB?YK&v9~ZoD_)1aTSDtQ(gUIrisT zM1}rQrSDvia{XecG-%e$ESMW1y0V$ErLJxgyIlQTk~ycsZlZ=X%^;3an3SoiJMgxD zH29d7ki}C0Sn#Y|w^U)nQu|+PJI{|{3vA+kadte*J%5@Q1`STrAu5d~E0IyJz6(1w2&C1Y4H5ZP9@!aW z&QQ$`E7Z4I&efL24x?RdTlUi3oAzK81;5*b%wf)4r&vKJ=OntC390ck1COA5J*Yr$ za{}%SiR^~Wl&&^%mp{cM$=oEKd#)w=6S)5=5cDF2HNJw{3A#ZL3`cNXbW-?#>$FaK zQam7y;Eox8fQ7-u>;7f`q7t3c1kW?;zT{6%f2TLYwOwc6UbMiFcX;3emxl)@TVn=%0gC^q($VYpBz7FieO$S6!8DoRsB^@947PZwgw1ofVK9LeUq zcIGF)zkUC6cX$8e>;2DP2h$!F-^{bS@TTkN{pXtp=3PuTZ@B4C{sNakK>`%B=fN8l z3Z%q6y)J4201G#h4A&WdU2|Z?k>&eF?0+D5x2dek`XY=c>XTu{*s}wkiS?UksogSa zsY6nO@vq-gQa8qMa>6*)Jb=*Ay|-@Ntjv=imG!HC`Sa_W55Bp&f4IK8{p3UWrTg%M ztJ@cMm)Ey{{N%&mf4P5AKK$U}@#6OK;^yx5>XQ$@yL$NWUw-|6zyH^-zWw;&>hTeO z_V592ar^M`>ldGV`0DZT&Bq^o^zh=<)$5CgU*5gBx&`?1?*8?~BmVdPj~~6hxc~a? zn_s-Rd;R9(@%pRlo9oB#KJw0`58vJ9?voGS-rs)w?iRmzef{G8?&0p`lQw|AIJI6x%>zBdboVNeD(8g_x>AwbgsR4ym)o-@V!Jn-|^+m&%2}k z;EvA%c60aQ>mT0p>gP>b{QidDz5eSreE8|Gh*UpAzq$VE{^I^wXS@^X*DpT)?2os1 z_ZMH?U^oze?GGTGA3Tlj{2L$n{O9S%t3N;e{><&WA70*^A29X5hD!U(-QDXCzWw;k z)%^>sYv@DgKK$qaUt!cxlJoAjcaLAZy}!SEdwcn>R~Pu53GchR$9M4M)ys>wH;-Rl zeD%fS-5WgMn+v?L`gb?KyubJs>-5w6>&ySTx_`WXesOX0#hZ&4_|^MAm6)FY^!DyQ z-rl}=eEX!g{{8Cy7Ju{vym)nSfAInje0SxzyM4UByLo?uqi^q_4t{X;^9^5J-hc7x z;?3239^%8Ve|7iq!}-O#F+Y6p&Bs@N##CHgUO&PVyt%%7eSu}`U3?n-N9-2ge*6+I ze~b5j|Bw40{vSqjmg+C$`Po1E_51t%?X_38mp}QRAKm9~fBXJ6e{^Zey5ZZ2+LTz!ElySeJ$JwmC!{p$Ir|GvI_eD(Z+&UgLI)x|eg{o=*f4>wp> z?U=(S@a@f)_ZQbsU+no8Pk+7s{02tzi&xiwFCYK&>Jcjb3A(ua)7yu~-(25b{p;2B zA74FwcKhWK+UNT`TLkoKK`IPkOBzg)zbjKc>L}LlXm;~#r0pV+U@1P;VrIl$7ezM$4Br#4dCj3 z_B{D_&;wt7_vUI}U0@bLKK?lmd-`Vk=K9U&*I2#xpWR+!{r}S*cK!0@)jb|?eernp zIhM@z{oS`u^Zcw*{#nn3g#9=E7-~2`WM6#U?;aoTUjOTNZ(d=p|37@mkAAq$F7ICa z*TwylGI;*+ha&v??)Dg{?=Qdl?%(cz{_yF|*Ps3A?)tZ%e)gB&{;B=t|N1}N{Pxq| zfBX4t?ss4Q_Uq68a(VNIPe1?mcVB+y&hLNs>F=*!{+~}idH3WWJP%~{^7|kD6WZkc zW1N%ho6paabkM&d=bu&#B!q4tDOpH$#@$5n=15p|a3lux97#DF&q>pIPG0?gouK>( z5my7hn|KZH%+*hj;sZxQh|55_YaEHm@i~x`gYlf~vr@#1AN)Dqm(1_xH7cJsAcN0= zPr)14q&b$A}g~b~J6{n`(}o zBhkh8%;v|4cw@~0+5Brq$;OO-Mw#1qj@NCBEow7H5LYsulj7ueORiSFf|KkpITAwP z>nA}|RE}tK9LcV3{yy1tV|KC|hPKRZ1>-qb_Ixd5(Z$~<2S^V`v?eZZS(h_LooeCV zr$AZpYl?))S4j!gkb@Gdv3^RN%eY%EkxNK*mh99s+ZGb}2&$`MTq8Aqae1pTPUCJ+ z%3LGiUYS3qxvqS!o9y+Dd;S>lJ#(pQFxUq3(=AKQqn@~=Ho>-=kv9F?!Ekz3%JV&rYC;0e9V zM=)h7UkfvAgKYpYR`BwFFk2Qf`MfQdQ~ni}pNWrcL8uHQ7v*odB^VZP`&s!a*%9(% zAU*Lp*f~e~rUGKs=$i`YMxNg;RONdA;oL2#<+&YVoFlYu+xWo%+)udk=$mXmQ)^zZ-fEQJNZqX&=EPMnizEOQG z8a&rKqOq%iq|RBiXjbk?0LhUf(K}y)pb?91SCV0ya(#oLs`A-^ z-4_0)@MMhjvsAcu2xMjBnz#&0yF~}rqg$ru+GTq&R@M%G!I0~%ON_ha%2(q_ibbjq zpp&IjIq)vUL^U6f$vq=4u5kb>>O+tB}D)})I8|S0`M1Bk;559tZaD}f057Vf8 z1VQuS@1wqZKBKC=@)^}!JfAmEKJJ?V8Jyh$S)A4Q2p!LnlqUDhd_GRUfz(bV-e(VY zmm?u?PT{kE#$q5*I12!>x!&>FVgbI0;ko*vp;GMvWMu=%)sSoW=#9@#g3q{ zC;FOG<6ohdyZfU^RW$GoL6~&JjEFGjGaf!{LF9%?>m3f4T(2K5DZVx@7%f16r3wO z{ubc7PO4piL>^NOa{N#OQAgh=hnlwC>-T;Hj*;DWyo;^pRaCr+psc}t^ zwfHrEA+<%nLQo%h>?vp%o612@U0m-3jXCiVL@;bV2arQ!)G-vUEklG`P4yd)$URCR zg-dUU(KRk1Ao$$M1bD92H7Z<-g#^cu&nWCR_fJE?82Idz+y{S76(i3C#Phf^kY&hq zO^xf(&>-@B4w{!i^#PEhr$_G z=x}x|ByqM8dTa(V{NS7~46VkOI|zT%0cywPZ64R&K)kU|=ZW-jBp6wQ0J~)9s^ufk zy@#cNXP3jq%HmSBb6%8jDf}$%&*_N<(DzYz8J*4nkixTl>NN0d1(3$QY83~HVj!D; zvl@jp%f{VgH2$Wdna2Wvl)^_XadGXUk{!sZlrR6&S&O zNFdulV1pOG+l-D^+yGfTH>EQV;a_{^W!RDxqoEU5%)DOgL~3|;84|jAg^F&UcrHgb zG@Nmb`Q>&L?q>n1+!NOgxuz>CI?2372FTzt8l87ME*4$J5GW#2I6nZ=coZ~>_RU8i zu`L6!Ry~l-SACS+Ijf1@36E%h0#P2@0J3=QJ^IwSClQ02osR%+HTNVU96By<2kHE4 zD~vP0n`-B);Oufs3uN&X9CN6gk7Cfu<6<$xo8n&~r@<{oEH3e=2av^oy@FU|a8ECm zFnPWNQjj?71k!lkIaZKMezz9frdAWk;JMx7Y4ZB22z$!8OYGnwTn;*PBA3K2n=?po z&dB2jKo(~xxS$&A6rLu}A^_>!dylYx+-d@;Jn9jL7elT`@SMZO5x23nr?0%W2*@GuH= z7JpNplzUS^!2T%`T;Q4f6vUdH;FonxSlkbW3ux39r4W-fw%E9TZ9E9KSqaRNd&o&8 zY~z|-xOPeLEG~}t$m`!y)Xp_h0`WE^K6%e=BaqJXrzss)!I9*+?oBy+9!COVWF8J; ztnHi|kG7@)CdB8U z`IqZC@;adej>au|8s7SHu$k}o9sdMrh3lQ+4Njg$2%Ph!p~^jRAdyGi(@4v@CTGs8 z(iG3@mDBWM*sSS2&yoUBTIxAh2BMs$r4=`4-f1P_Im)!MQK6Df+=Z{;Ek?c`h*8^`wmR-- z0hv6uk#-K8sRC&{Mhu6t@hY9{G;z(B&-N&~g0uL{vtwDb@px4ROXKS_3m6X{8xS6) z1`>H4R|Z#q=M@n7#8CKi{Fxw*gv#X_NasFn_PTj}Zw9a95|Y8+c(xDU+VQw$R(K!$ zYpW=aoWjE}R#pac;Z>D6o+1nbiChwaB(7m|^n=$|<(QjrBst;QKPOpyS6K#s<108P z2qK@i6f>{+0W!Jf%b<3~jAm(u9At0gc5?JcA3Q48BT6^p$H%*gsxv4`dp;YO0a3 z$uo6-9>K^fL>{xtD>rU6^LE<#m)k0XOYhdqeZah9;~rRXCt1LeAe+7qklpB9m#3__ zfn**%E)E}o&S-H-c-*C&0D?e$zZFDR7Ld)gSP?gQRdNwuxdkkunaAIX#LOe7K#aZE zKo+ktD?WJcQ35f%w&Gzj_>B5Ixuz(mM3Rp!;4@IYe^Y`uo=qyjJI;}SRKDs<2!Y$v z0v5n47Yl4XUvov1@|_Juv*%d^AkmPw=mux_CCZ5WeWGuiL6&sFX&mv+7@V zMi#q(DDs`^#oT#ciVR~l7C(7rs8r|q{`yj-ajjgc_gp8I8u#S0)6(W0OiG8#WFRqc zu3UQlf4(=^Pmp5hgCRzh0ZdHemZ?mq+?oL~^7Unc;`6T!-`N=T3`Q@5GEZHYiSYNC z+4J~lS+Y1wE6XSDiI){N&m9)95JN^+n!KA&S=sYy`?BE!^1E%fIPWd{?CCWSqrR$a zpAG5VYS{X+qmln9I~%bYAc^mEs;4}HzA2E&f3-_>I(SB{x)^wz@3gewl6Z=axTOV> zc}%DtmPDnuo(VxnO3_uEJ(Lg%a*VhPi_Wuf ze^pg@?S9o{bOopiXVNuahJ?arba>bJ*iKf&xF$J6Cr+y`L7l$v zUGzXE_v`EO!eibQ9EtBptV=idcI!G@hdGiwkC@f%2CrPKTLSNSRkto4hi#`3e-fPo zAe&cow6nvWKBu{$oOJ?;JRc0i=<3u!?6}=-5*=sJCosojw^-Unl{JvYbBE1a+2sc2 z!lP2ntMcl=7NlhQO@X8YL1*mw(+eaw!SqDyr)uY$*6Z}f87=vf7Bj_;Lf3kALlvx-mOb8n@1E`p9DrKn&iC zPwjZrz0KVD-en+@SLnB;I{0&7oq0sFZLNm%?pSzTK-Dpmco7@%VVlK33-C*sMG zP`D=V4wjZmJP@Nsvtt0U8qSQ-{d;*o{!t;lKj za02O?>*kI`AdSa+yFZ2N6oHN5^*cSp#{19$F<560sc?(YRTk&*{WM$Ra-cqQj?`5x z8P(MJF6|!0=%v%o<`=pafGDq6>qqTS9Rg(YTy;N~G}Hfdj;AG|E zQ|%)OkG}ya#>yIb@_1sOU}=2b<_T1Dieif1wAM5TBiK`qEJCGES!j zR={B=Oy!BY2~C#t5Ns zyFEg*<{%`;*XaPK;IWMXmxfu;r?X#|pt zYmx>YdxE=Pf4SWrVDUWaG4g4XXduR!03#>iIf;>T^6?Wr#Avel5*Awq#H9j zvKabcWTRKuz<1+WUm%(9I2bbpW7N~KjX*4mvEV%Od0Rg4J~Cs4$)iPMMddyqkj3}< z0@=pOOWdVs>Na#@}>0uUsbrF}lUfLy@Q)oF-MqbHrCJy+9VP zcAR3Jf0F_v^153fjcals27jC22R!pIy<~1_r-xU-pW`+1RX=?+a(WZGg-aC>gW*pY zChnKaAV$ac8T{tPaT#MvVpOBf zq@L$OffT-iflOZCJ5$=mo2DFiY;Yc$$mJl*f8zFM=GeK9K65r|L4g=&UCiP<-x)NE zcpkq7QVqE-Si#0Miq&l(#;Gf_q{VgoELnIi2T0-ZgIWFN^;NUR%_D#loPzWC*}#PO zsGE<gjyg5?h+;UD=c=T(o5IO6dD>q(!Hn(5KD%qiOwy~TPUbVMe5bn>d z6ZfZcy<8HW%UR&5ywebn%`*>6oadDzOT_5$xg=CB@eAsjb3P!M?}!KCay+uVd=l;< zuiz)o5Uv20M%U>IX&UbX<{f(t#^oU9$}@K>d1D2y6a!z43lqvU z-^#jqjBDj+bdy{8Kolu3seG>CpYmwlD!%ay)G8tJ*wZRjm)=!k;8q4m<17Hk;(PxW z?71-q)d|;@t9qmEX;od^+g&voCuc0!60VU}6JzhoYTn2L0*S^7ZlM@+&`e#`e^j~E z1kyNzTrD?4uDeS-Cjq4M%+TuAxfQDi;|y4Q>Se5w9y71Z22u?<=x`+XTIk>*9D$F{ za}sL=BO(K2@+jLH$>@x|MmA331)|(K1Btw9VohzlrhXlQ&EIDx&nwNb5FC%Xuk9Sq zGXe32&DvsgwFQ!S#oF4T@&3JQe{1Dz14D~kTW+VuX~Y}WnfJ5Xu+H2^-y)9Z__u_> z*W8w5k`8DYmA_&%)Z8e-pQWKo-x+ z?|6<8=3+KZSlbCc247hzR<1`kylO)dQ_ej5 zzfT(q0||-mItS8uY-49Nx@qs?JPqwgnhlP$ zPwhUR>*l*5y$#f#f4QcEe{&=_CC2GUyXC_BrR^S!(@-`nI`=@t3A9LD{F+nqj^9I=ZQe7AqOK?UQr0dI3;+GWc2vlBX^#C+0z+S zdwY82HK%)OH&)}+!DDHA#=_%oKq~Je1H{-(v}aNtd)mt>uhHB~e=^Ta0ol9@#acr1IR#G@-4hMUJ!fh1$zwx66U!(b_osqURU-y;BI(b_z5B89HTbJlI4 zC&tM+8i-b-3fSAEo{_ke`FUXC;4@KsD&RDeM)$$qyrZmBXM)XNdfO`>(Ta?VJk_D8$~ z-o-_{_mQqs@gW-X=3#%Rr9B7i@LjX#D4|SOqkvEhy5mjY%_*0v5Hs(wCZV4>rO5V< z*0zd<%y;X{DZ!v|OVM%;MCOPVdP<{cJ*NUtq=iDO=_ESOe|M%z1V;UzgA5v>l^9&6 zCuab`%u(r$8u^Z1iBSgEJ8<(dm+M%S?>m&(eWZJNR)Gs&u%T0qH|Q7*kXXV0}*uBtS9Df#e3 z`b{$|I^Az3e=H_#%<#Po*5{Lf69S{6b^VP|As)cPOPge&*KM zs$Xd&SW5GmM$DviW7ppkLOn_t;KVE1f#juhZ1wb#reC4L22$QDHD#p?U+|i|LSJf+ z{FH5}BMw?4BXyr*LymZUj;A!yO*_L0raIAm)yJIje;(k{lJGr*(z5e3f&nD(^NgfH z;Apf}+K!d-YXKqmw2PRWT^F?1xSZO3%Ht0`;JtXI!_w0z0TAOX61c4@T#LbE@@T7^ zs${yKRywpBt)@GrXMCR#bQ=^OebWK`Ph$=;d~{sLkKlPPHyLMp2_3;GKG1C6F<6sU z&&X(zf7g`AIA@U4RX?Vyv|?JuN|8nuWNhK5QvmUv#%=}6s`0zc5O`b+NaW|>%2er` zIV?$)W)2N=jiDNfBu|mOLvfa7qCj0TziLaN-GzkkMf{< zD^8!)P5lz@O5$|^-YwXAHalQqp;Mjc;W$pZf<0WY!AEd(EgO~_;9*V@N0H1wCdHXi~Mv;ucvhreU2W{p>v=q6uy2m#X{?^ zJwDr{J2k+&gQNbOKj*b^Ifx=k<6;Nlf3Xc8LmafrwU2;k5RgcDO?hPELxr6TM2nVJ1!O^IpfA3uz^}zfgH8h&%;TdhNdq>ELM)&1>>$ zNDkW=8@wsb`QT0Qx+gz|>vZoW5aoF@KV}&Gn~s@ayD?}1CkSs0Qw27Ln~p! zzd~HJm(D3b=dpFaVhD7H3+O2P4>~*R%mE+4^t=}I5Y<5IZvC!#(~O!wS!{06_mIRn z(jH;c+9E7P7pV7skjN!u&(yfS-aAy&W?AkP$kKw!)DRzE>o8$({DJ0HeSx&^hoqI|C{3 zYU$X(IWw(W5AaI@wPxW|C(^C}FuNa9#bH^?^n>R&l z`$7HFki{1oOAF`Ze<7;p0Fuov^?*P$2qmw}Lp!@(-!}F@wb7YaH zRV^X6z<2nE0>_%h{ec*}NZ>0NXAb}g%5_Ll<@>ioiOzAYToRmGs>w?V{2T!wadS;^ zI?Hq02*u0y*o2xi(;ehc{!(dG7?50OCO_07i!xOpX;Zcye`=LUBMag5Fs8BS(8LX{ zuFE@wL3^Uy{}3cc>ybh)InbKZ&|BPemnjga3i{=G%e;?F=tCnt zCk04uw7*Lje=aN(atFy&b7W8Y?Z@X*Ha_1at>qID7Ir6Pi9IZZ)T#HXRg+k)QV-W`hN!(mQ*~v^zM| zI4n0GHNF9jWF2Hs?;S|uHT7Yhj+Fd4D>hoU5$48%f24O?k_@W}&vnt5U0CHD(@T+d zax)Ye5Cu91Yir|ju$@NQNexIWG+Q3v2NxQ}2^$2CX0hSW2E*3x<#^xL0RME+XdV#w zA8f7_o@=8kSRLFpnxE4XtEYKDg@;;bJ(4;QY+BKwE;)XBmAaaE4U@VBy~8A4#YIQ+ z!78eOf6leS+vVrrsx%|w3?%a1`YK(7T0oTnSAxlb%8r%BLlj;$KP5}?c?Qi^s0Wj$ zbx-QmHL4F34p^i;m4KX9o)kHq9_W|z@D6F^A`GyR-_~#%IMO!_$@3Em6?8q)=!$~G z7TTX&p?nLU19-bW(HR99ty~VY2Jv*%T2FZsO+}iIv>pjaWXf)VsH40J{N5GXn;WVU^pZX&o&rVsrm;ERr59XBHti0su=Knah{9&_ z9@CQ@{23Q_YG|s)d9Iqk2B}}7sSEF^1SER8Gf0z7{24+WLQl&$uK9BCiSAy*JbPZP zbIe5MX-LkEos#Snl0DX z13$e=8~lB47rKjlhnV(goYMs)HqOO*l}yk1);?v?-Jd!Fv>1KU5klPLWm zf6tczBAmwq(N4X0n8uLk?kJt-94I>K+5MusVsy^TPm2b%O@^hN8_I&p+uX*ftp`~& zTcIn$)X{lc8Kjer`W!>ZrFU0&40LR}`AMr8bkFE$Rz&wwo^On2uLflf(KYz!Osb;m zl4N7fT=gd~>%K(u=`A*beoWmYf&*m+TU=h=Asyz$svmK#)d5=#ZvC_PA)D;}%%5XlQ zWa%{#YnWXE}J9QHv?YMJp{LrZZ4a{2W}^Xq8S(BNUng zizhoqbK(&yzVJ7N-#%EDhVhXgqlc> z=2&8eEup!oSR^*ummn5@4vC^jI2#KnqIvUqD~FQPQI{GPpV4ymNzgecpeQtl9IKNu z=p0m!B}b*VhLh_0e{`Kmk|ik&M6VP~5-b_-f249{ZQpOR-jrM9CkT*Se={OFrN~Eh z6@OScP2As+@3bLX7k#&FY>{$a+ZGeT9Ua%XzNAe(!V-4QFQb(s#5hC0&E*f{fK94- zVpX#ctE{)@`4V<$5|STwDsJRSNA)zbtpos@%c8oh>ns-&6$h@y)s(E=5FUUg+~~cO|wP z1G#)c?y5Y=K!}7Null(0j@~F=!yUaZVl#}CftAqheUf6h>K7jze^1pDy)|6HdooMt z%h}h1^&zqQqGP! zjV43SQOj7Gjjd`S&K)T&y^kxmgvdA~ zkWBJ*A&0dZbNfj4T7<{Y3u?7w?s6R&Sp|J*R%I7pHMmtP-1S7HO4pm889(ND3K8kT zTQ8f5yYz}`=!Y0NX2>Z_Dl;SBvHIFVpOCeb*#a|>+ll(ee?*qKBbezXbd2$vc`e9@ z&AJ=QDqA7~xN19PqE!AvkVVH}JdWU+-Sn_N*gSm?CpVdUNthuiq#E)aU3q)xLy;!? z95bTKZ=TqT%KSyr93kDJ1t}t4ew_H;tD%iyUG^Mnvp!SB+Djq1VpPON94uVHu#fwk z+Hm6-vW?Yve^#>)U+9B0(ff=U12#`-tey1z-pky;;mN^G}C z=tCr!2;NhvX14Tf`^Qscgw)L1c`xU>Hr=XH_?eRne@~DU(tezsQ^c=v4^GY8B~gec z%pkJUQei!JT3hJb5FfAHO+ko%=!V9O)&jjuL3`5Q%p^)I@1^Y3i23V!CajGiBR zVb}8tf39;^8vnBR4xL_)3U0ioQT%f;Vk4w-hNORF>GbhEY->^}~Eik7;12 zojpevOI}+~3wel;l91VXo{cjX#Vk|8oO&TYdVG2j_r|J=7|z6bTwcOMi{G?tTNrzn z=+Xl4Qf0eT^u@brG{6Jmg|fpu0;@17Upq9Be#Ygz(Ba~m)DpL zf5E@Ae|Q$WMQa>Tozv%M`O9AJnv{~@o8O&E}83?ouS_pxr2>{WxzT zu{;q*NapF+LTY1qEizWIhTSE`9^YUIf2+lN;3aRq3(@c$>wnyLY8l_hPdUg#-0#Qv zF5V;E16R7_384Z1#C!Rk-%W*mDL;tzSE%c|xIW$)WFT1MVa z+Bl2EM+{iQJs46YI8VYyWW3<5A7W3KyW(R?{^Q!lbe>o3Iq{MxfQ_Y(El%ZHg)fh5+!bEY46dunm$L-Bbk zSL^$V@y@tALMCQRyN>&q_&c)rC$shSqG1dnJ3@iDJ3H5gmaFfcH+qEA^{Hs&Ms@P}iJr3Z_} z=yLyb-f%~Sh(M7X?ca&!FNo;Nq21WS4~*7_kUEgVcG38Wl_y<>-a)z3f78_3_?h+b zw85xC{xFYNh#l~d$c@?wi^xYyKhmn#oRvrE4 zI>v*0bV)?7dmt07wq9~RXoZSWe1?3d7mK5fh)2>5BHcI_w3j78#=mpZMV~{DssfCP z^cv07@a)vDaF?B4v%V1Se}O)mq3zsjvw_xOkMaSmCevamW)ZFCzh?EZbg>wZ!D}1oqV>^j#SLPle?E+K32BbC*xkRn zP-k_Shdh@@h#&00(0$4Lz#A-qz}+QvazD2Cg`|P~*1ML?)zd=s46k6N4`c5_azTG@ z7o`|zH})aB4Q-4*Bz=*;^|A9sUz(7*_`K;V7W6CkDGBle8F`|`-{;JWb;;abkwNzP zYR9}mAwJN@)t3|#e|l(RC;?YbOJjZm^IiH9KS57PUv8Vvn_lz$_?;EwdlA{jxl(F;62jgZD&Q%5?fk4UG(Y=)tmU@VdB)rwgl!&9l~0UVx7MQeAsPCTz#?AEZ>YQ(%a zKJos3^t&BhbQGtq3=!-fr&pA?U=(49-E!{A=whAddm2NAD@&JAzKJ>8V~n&>JC89N z*M$!8e_q4r{}}hjgy}J!b(a3qOTs9ekkm!!nqz85`Az4E-fV=(0DCO2SCu)3 zGV!lg1m9OE7i}HpE-9BM^tH-pK~epcuQfi9CMn@nh6?^*(iAKQ1Bmg9YsCjTfzfjP zYjv!_9p^=x0YYwSoRK?j&c?d_c5m3PGZ150b%*_6HCHwhR?UukrL&MdT~YiWYm>aj zKBwd5bg;^2JgDXJMxHIr5O1dUOe7#5r;|({34KyMa{n!%nei=5I4SaeQ1`{_J2RW#*bVdq#+{ zbvSc(j@-=>u>xFMsmU;3Oo+@J{0c>k3;m;#dWmnatkZh%*3TLZR`7SKcnC&PW-T#} zgc18NQ+C!GxoM2p#m-~1w(moR9|-pnf1T0R34M06dL-T=(#yj-{#nPbb1mjyu@BSK zP8Y0SnDy0!9t?efda!z6w(RWhoh@3*;vO_B4qNi*?2%J~U#_pZ(Z?k# zLY5AGxqfw1@qI@0FlNNQi_!lX#u;W}&f&gLZ_gpFj$VQ}#DuU1#2hPsI7vr{aembl zfvYUvMANtmScoJkJ~LApEPEvse+TBRM}kVjPV7QFq3s;VM4M^O-HbKhj47x5J2y?N zsG71qej&1|F}q1f8E8AtWijxUk*MlIWJcu$Be|m&XRe(tGp=>?Kb{aFTsbTxKg>&; z;lsx%C39UJ1YWhY>5sKtkqtaMOO`9&k}!iY^Gb*x^leNDu^)TAqbCcVf1NEkiV@to zcc~a56jD2D+I=lyucLW(<*p4nqK!KdPSNg+dACBEqYr=H`lF_6-f4rG&=tGo`*Tms zu|(t+&Z!q-++Ba(C#j5g?tO{pbj=q%9PxKv`z0-(=Y+n1`Gy;_v?mse{zM_N+VE7p ze0O5q$%+c2~>>LeIkbYUPXpF|o3d^R2J9fpNeUo@G3V z>)YwW+OhSW(lO?`zUziD*OgLk=q*|@>l3#+CHe%Z0 z!mqt@&KIMkE7!)c(3N|hnAIZt!XNf~T6z6?(|pRtYKWC@arD`(fBZzf@oSeTt;Y8$ zF>#mfLKK-E^r@~ADMa`_e_a6>X?dXseU+Ub#%WiLk(_vT>hOj6RpO70`v3~DhZ!nD zoI8`Q`ecpc_h~t0>@*}KbCw7Z*_v24wc^gBCBE9t9qY4} z<@zv3W?3l}dtQmBe|o~|>1CEL=B+O~)-j(vDis@_czcQU&x&cP7}FEdHfEL$p++!aYDSI)?Bhzen@iHiN_fS z%THbyV-XSqg%Ek^pkI0QlqTjDt=`-)mwIUnn56~Mk=?F7e?$-Pefq42&s*QpB`A0L zj$~#;M8+`BPKae>Ttd9ErX8R0jNUb}BoaToU|4eW5ii-NA8YjS?4k9s zWH&m-^kn3O9ATt#UBQ|~+L8ZSDG3?znmuz>^O_^_sR>yy3 z>qQ?|AdVg;nY6iJK1Cory?34ZW9HU6qZseo8M2H}o1Gn=az^UI$k4hmkPF}Ew)`>U zl0kXUZ@F&IJg;rt=njG3N5`-oT(yvaKH~MdtXI6-e{YnGUMV5|F^hiUH7qUP3GXQ) z*Lgg1*v z@i%_sd3YUmOX4FhO$HXiA3ep!m;WIK6-XQLQ*Xjea9e1@f(Ob0ZkQvG=IFb~&f9fU@fZBPtIM#R)WzH3hT5VY+3$4T5 zu5ky)ZC`eNA1QRh>~tw~=N^*V#1k=NZJVXVr`KebARpb`L%_4C|hiu`-kiZ*z^6F)qZI7X^A_e3vr%# zvgfqRx?TpxK!(5PGsF1yUNJ-xzxK+dA%om9L+{7WjP&@tt>K$B?ON^eSCCb3(KZv( z7W#ztj&fgI^-kW<3fMlHiF-`>eWI9-L(bZS;Lk&X@%+q;Y=yzF*jmjFiFh;C}X@ zb-1G)KJU&oX>|OZ_sJ+=B*jQDMDmwdFZ^Y>A*XmX{zs(M&AL&x3}?^mH}gcVf8l=O zLg;lDB8Gsc>WK%Sw{^dpH};F(Py8M`oSiQf?g}7dxAH8K6Z2ir|8_oE?^qEpqz%kM zJkgT{`+1+JA;&JTCn{!;4W3|07)d$N`wSyP=eu4oBljfzhjycoobd(+;+TJZQgo;# z2^+(Ed5X+QwLU!YC-v&c-%gr2e_>2qNd2&S`lQt+W-cBbwuchwq*D*(5ucoD!uum6 zIu{|5(?uR~^7uN&+Jxkaz4ihbXrG=u^FG|Tk|$1K5~6F5 zs}|Dvp0>}p5ABg5{?MOzTCNkBYK(^H$RLGy!z_c-M7VfITQtGrXGXec*9$2Rx!7s% z$MpDP;{L3EqALLQDLK~ie?d=)kg_qy?3mYunWe`@Wxw*VQyb=J9uESEEBKo+ihs>x zf)@X^C9TQN2*YfXSnR;=aH+6bVmCsIZGEDGp3*n5l(`8Vi6?!7phL-E;TEgHJ zoET}ri0l%6Q=Jj4*f~QCiB}yaI{LWI@HEjkD5OsGMV}EpKk)mEf9o9?WFV7y)%<>R zus>6511)hO?wC(;WIG@9dYmcQi+RY7xmgqquJ?*Na?PNc+K1 zR{gkh-&rk+q!F=Vm>YgpmnDvRF6N)2PxUOxe(djmB&c|L{Mk`WgwO2qqncGn=K997 zdzqN?b7bxwwBFBtf91y+)dLkh=qI{^qjh+s?77$8k%)DSQ3lf4VmY2J>-w;rSu@FY zuFRgaaRYt$M=!+vDTLIF@%nS#_b}oq#4q;eJ7HC0uI{<1HuOE6TUy~Ay%Mo(Gu`fk zPw$l+W!vmUWC-u+o8{wudr|s`Ym-gO+3DvUpP2V_UgY!9e;#PtETgw55S~(hzmyin z(XVXxft*4};hwTWYR4S2aC%(ySKV(#P9GxoM+StBfoybqpCqFA0}+4Z-ASWxNB$f6 zcWBez{E7IIq_{a1!PFD|3OZoSVB1w9RgwrC|rHn{SzD8QqdHXS81t zii3UKZz(>If8pygCZ5|D`H=+~u~wFO%C->Q5=K_$$tJh#vav(PEjo+n6S@-PoWpdh z3{=!VH#`oQnJpwOted*Emw`RWZjE`>xN6yE4KuH9%i=ruOcTS$4s^HK_s~atoBPHY z6t|7s(YGPV;)Y%8Zrk-?C4i7NFsgWE5|kgvvyO~df0k5Be0ojt05cb_#U9|=f_S5C zcJ-Pc=A2%eRxws^W2{HUy$;I=YixwLV_)iPuNc;!3aOd(f<61Nj{mx}HrCT#Z+T!% zinNayWo7iybm}!2;$Q-@A$GN=;FeEZFxqkfBH^wA*|H6^Huiz2(g7e;=4q5&=-BR zw8D38l^=bnh1kSw6CpnMO;_{A-&6?CvAN5`1ICCojDg+Nqd*vuQy%8xT&Z*Jfp@oO z?m~X|tRJsnZ*fTcogMx!+_!yG!YrzLl6Ag6vO>A$?#5JIUco8fhdCwpME7<)Z)bj$ zf2GS=ZJ~{RPfSeUXHMoxqC)JU2jj{J?C2M}64o1i8}}x^m>qa;`3mzy5nrCkDMatX z&seFL5q0nQ5_8KN9V+lmC6aiC%e}`IX58F(p&#!fK8SPs?tOlEN8jg(<-to|VVxxb zJ2AWVKG_)P`OyNz-*B&mY}WN}=8N8lfA{H+VRn-=Ou6VSda`L3@;7|}=UCf|30lZD z-q%I2Y1J>fcwsE`ebcyR^+m-Q-uf4{Cm0KjF6bX>=O?CEk?*|krNqy~ln1oHgw%t+ zXi3q+bA4YrVI?CHxnKA@S&|BC5nk3wM4Rd5oS0t=X&af{lNjw-j~;2>9N~Cbe?$>` zj=Vg+iX8%9-qDa45#3<)#|x%l8ul!GMVo`% zKP;Jr`Fuhu=k5z>Y%{$w0z*Xi2Yb1_a%5}b_bIm>^g%x9^M!WstEn!us$Z1KV@AiT z(U6if;H%9NO3N2hhA@NZ#YA=b0WtZ?@8+oAr?Nu>lS~F8THo;ch<9b?>o4`Snt`Mp}q1j2XRNB@ggTd;QUk{&oK`G2!*` zaV3qA9~H_kI`goMk9=ij4kLXZ`W)WK+EM&#viK|JV7$?^0({dUR>K@=obVtsk~jJs z-iZFND3NB%mCw%lyraece^ySN&%w&h*_&@wdn}QbwTjm6TQPJP-)CL>(0YGMT$T4a zdSd=SN_#ka;O&|?lJd4$W^K0n&%gG{#+>bUKKn3={US+*dE(I#WjT68mC<|rWRxsE zy*Gb`SyV!zw=W{2J@PVkk&4BEJzVFdlYjGq!sd@3%LpVk0vcz zhB)lCkSx8$&#a2mhy!VrtljkGnvLpd12LnxrVy7cfp40pSBebDTuFvfSx62S1|lU@ zVgZ4)LmJ}`d6dyEf28Um(C9*1!pspNyDajY3b_>{t3qCAG)8!OViHFTsf0+%&c9Rh zhjm~=O6t@bNJvXgJ;?&ehh$YCF;@x^tB>O7fwYf2B|^GSstgh`*ykWb7C+y{x@}PY zfsj+2>KlbfhVUN599*)dgd}UkgoKQg$qSmI=c7@UwUCvte^aCoS?I(Z0uim^RfkU% zPgRpPqilvGUG`yg`42gi-4uu)ilhjUNTTdOAsQ0VIva%-U)&lDq6K8jZSZ9rn3HJYvi-nqX44EQ@@-q^iR$P9}Y zks~&UXJE~F?shIjs-CP+A)Yt+ zl~cG0e{hbpknN4~LsF2~LRAVvsuzkB3u$(!KSc`Vh#BB1#DBt@^(U|?dYR&)Zt}+q z*=1AYA?n@iQD+_jMXZmJ8r5}-_(5r@pNU=zh{&Qu-kWmCn4uD#9VPkb{zx6MQcMIl1l$BWfTe-ZK5@m%K9*KB#^RDe=|i(4V;D&h+{RY5KGt*EMn+}(=DS@ z%ZDEHKx|WwPa!e*1D#FzPF0l!Eq8@|B%3 ze{zNFW|TXbB46MkBaRA=w{b^%%9CPKF&QZ}>ft4%WbEfH#QY*hN-=(vavFtb2Uk6_;WT0) ztr}|DG_7v5Y12GkMz)cr^f~&g()x_;f086)7bD+7WMRghi7NCJa`Y5 zED2;NDRQ!Cvb_-d64h`B8Fr9)rzILq@r9IR)>o?G5R#-z7#ZzRq&N`APOC!J=X_81 zDnB&SjyMyq;8mw?a#Gu0z7%~C(mu@E6XK$9c&bh>m7=7g-8%H>drCJKW5y-kf7^N0 zx8{t@JKYfwe{U*^GSH^YQm7B5WzJa!2x*y|i(@B&6m98S@QMuVV7$m+ZIcT z=rN7fdlpxAv{)qH9rNFWe-sgRJO`snz~S0P%;ETf$a2J0#|$Kl|Ku@ir3wlmE8}E) zAv-h!BDz0l>E&_1Le)1yo=7LZ&uf*RnO`fEnGohzEvUDJxKXX55Nm__j|$mVS&j-h z7}u1#FzgN;M(h=>D!(`DtNe;q8u8v0bF0Bs`o z&mt~3?=X;-(K-}jg_*;e<@@nFE271S93RL!^G-a2TuA;ApUb=2U`f7bar9*6y_;bK zO5Y~2cT$MBGXJ&b4_H?=UJo9Nh#l~4Z^Q*N5#pt zLZ)@T!Lk=F`XKYme~}Z5NONa-{VZLUy)W9|@G~x{jPLW-w=jyG-}yQ-)px&!oI;c@ zqR5PRMvY!%nH|b464LBLUyaC4m}iWL^6=V58km0&SMfszSt3gZd16T+Lhyakvx9M& zA_J)NzU5$Jbb3pqexYqvL|!I(ega_*Tk@4uCf5?%|f=JP>A-@*lj`yd; z{2$C&DAD^2W0a*t8$jIa5=lpNMukKb2O}k6M7l(;80wuaM4W<8Vv*#f4)#f}(=JWF z4#cp6B1M)e$4g4J@~HA8kb0=DKuB*`FB5}vrMGcMqv{>yb!nge$G_HeOVKl@59f{% zjv}2|&^sxOf0;JFkC4Y-yY-k^jmYrLcU!V$B3m!ASO&%yib?-aEsqeTd83r zMTks$(oDso>pY%B6OTuGyU5Bp=#MWEt-uVG;-zk6swK1!`c#FqOSSSbz@<&hDJedZ zvwRCqgH~H~=wN%h__Tulo#HDSdMAtT7^;ED`LIGPe~^Nm2m|pSnn}pR?55H`AILgO zm*7F0w)EDVdO!&2Iy!huB7X;Mz(6?nOA_qE*-@#C6jkwz)J}D-Lh{$Bwjw5imQ9)F zLTZ`lhb_Y$`>w>G*~}cajOm;UTEvA%2C5kor;AlduVGGJ%GI(g`6Mp(;^x& zSiiYHKnBgUcWCMKxH9DqY6uU+(G*#9GQZmMwB0YXl ze@|H(kiby>pJlFk##t! zUM9LXX1)tT>`*O_5R>A@?~}bI^tRSK+NQctA(OlCrCPr9p^UFG3ns=6brEDX;tC{u zAKHyV>O{|+EVhO-$R$}KY=k>1h;^f+e~}D$JRx<-1j7}`&f@GdX&A$~Nzo&|K4io~ z8g}AHwPl$mxI4{qMQgV<*|ex>Yr8U?ac%9@!Lq7_HxEyug)YIrX0>GGZ`Fn+^hH;j z38xYW5#d1{EW{J)tm?U9N4-G&qTa6F4C{l1n9N$-YgsI;nQGL-^R4e+o9Ii^e?fGt z{r^KIdcSJd>X5rs(W-*JXwiG!Zaj%yG8rRkwMUUBu6lgmLLYvWar#(ej2L!{D-be% z{Epkk=$MXf?O0<|$26`$3elpw#fZ)Ue(f2l__#Z>RLA^~I_sBNzKJ$e^!wKt`SExc zrgSsfCH2q7z!N{WVJ{sahi5hjf4LdEYNWcp59gN%Nzo@Bk?@S+@2n8m_&%#vwzGuD z-p0LNt$fVImi?0CLKb!1`a>??({)53@$~NGoY_-%&N!t}$P&HA-;u>~dDSQVsD_9J zH`s$nNb|xgI5GDHS0FR1|M+Xpo&SY&ch=5lq=z{__2>d&C0Z3BuV|mve{&)l$;c0H zcs@hZ7Vt7pLQzt)fMs*TjGCSOFmVW(m-x0L{=dGwQ%qN z-#{S0;2v0b`cUq~gkC;7rtg3r+GbuFa{m@Rz^ON?5b1N8g(YOPi8-1=oNL&dEeRM# zwxm3s5ZjLPHHC=qVAgB%@L%IO@Z>nzQAqu8TC@;L2d%^Ay&ak}6n}_Mmaq}M#As~u zt;>a9+uzrbTMEgGdcj92oMDG_A<}1P@waYuV-{8Go+fhTe{`KmmLwqzL$5?I*sx^0 z|B*_r_0L|mUS&oSU?h*NN1X(J&&d17_ss9153=>>rH1cxgl`b{+lZt}d_Q_LoB$yt ze}-PeHmV=2@@Zq1OMf%Bge>2f)zZe!2NklAaxs^n$$)HBZB4}PGP9fiK0rk5!#>-A zGg$=mGhF?-UMs^~Ej70iPz()waz8X|h9eE+PHCUry>(sHMH z$U-cA7@HE}8}n4#>S>_Yy{!{{=MmA_#@w&AqZu&%(ybc_cj0$l4TMc^}cBZz>v=B;_6Z=+o?U*_c3ZSfwx;ke`{5VORr zqjtA(c7_a9`hUTM?r9HmO4@xkn7`fUKa|l+-{fa|x)(4iFGMN_-}d{;!03N_{uQiN z5yH~~g!FG=AG7vG%&0|V{^(fH-Y%T=DoYgt6_F}?P3tDaIaY0{=Zkv5()PmB!50Z)VE`1b|4R}QJ zYtd-;TJ*udES>1yn^0reH&VwQh4yWmyw>0OE_Kfp@)~EFOGX6gLPQrGDm~e$+)*=$ zaz>FQA^(k1aNQz5A5VQCkM~_7cz7f_|t}0^r2Xtjq9q#@1uwUkr#6k8OeO3TZ=RdeCigB8u@QZ zS(pi9t!3=UFQj|N`UNpto78t-$c~)1TryY}m_9oHIN66Gf^r z*O!>T_MulQ5YA7up6p^p)jxu|#Cnws#$DB0Xh%dWIeOiNxMNkO#ROxlpR;~jNA6-W z$(!#IsojcdH-=JYwl1TU#P`C8Dj&3?W9X@Itw#hL(T0rMD%MTeh=yGJX-`)@uG@^R z0Dow&XKNd~0@!rt+!dQMb4NWPZDA#v&1F9<#oQA8X!&N$xx*D*Ia1&lX&=_@TGT3{ zGP0QIgnm9-5&p;Dv!>s zHdg%!5q+Vz?J3d?X>~lwilIgFWIj;OdC~?!&w?ju4D_IjgqUO8%+sw6qrUp2d{Aq; z)M3SS^DkVAwARx5xnbB#1B@PirAHf6$hTn55?lS^4w)1 z;$mn=g*2QTC}ilOp6t$(~w9eO^Mqw=0_>6nKS%?5G8P2}7<*NICO8P0Ty zin7Kri7-b4t+Kdn8CbXLO?+FJsW^{PFrJ$-7 zQaNiP=0|ehFWJgG(RV9Wmo9dxa*uKAXes>jiS>;!2)Loo&OM6Z@b~!01%Exku1%1U zt$SojA+yt^T^wUmLPY)XdwR-T6X`wIj=3u?;{PFA_pW=6<{1ew$2na>JXNff_dY&H zhA$+)AJ3*65P6l5FiMEbGEo(H7e_+RocG-(Y8fGRG4|p8{LuA6N<$Bmk0?XNU#hM1 zVZ1TMGcByn^_cjJ{$3y5xqt4%hb$tW#vy)yHIY7xj53~|S^dLW`PlFua(^ATIxFnllg{7~n^Mfn8UhT-% zqtq8C+z8PXggyrebT^Cx`fmB4{_)7WMZcJ&NBc1Q*^fC+F%!~L#eWEt%tRW@gl>s> zWr*naunoEXqo&Jm&)gl{@9~1(W2vI{Fvj9y(UpJceWjpA7s3;W0&(s@r{&BA{RcwI zV+;FSvJKbmc@SSjx-ZO5_cyCC7kelFV0JHN+R_Q`siceCMf;;%yidDMoTJ|E$z&;L zS4mNqjCCwM?UYb~^?wxoylHj1>^Rq`_0R>FCnO|lB^aqV2TI6r!<`riPD>Lq%fN0I z{adwRwWJW^SqlBT`JfHyaWnEe%{4b((QIwweJaETR@U|0qa*{7VHN#IT`c}!&QH&g z)xyY$If;z;KtED1y0WleO)t$a_A=|4nqrz}2a~xU1}a3zeSeb^FkRF2pnX z?7By5HvSvk^?&>X9<7D>Z~R;6=M(4rQ6tbr6c=*7?z?2HmG6GOgK?(rPwyL_I!rm{ zarNlnJ-#w60%B3 zd~dJlMup$Aq-pt_E>B!FE97HeT9+!|*|R!mVYp-MJ$VtQ_ul=ZtYP zA$4OuQh(V7`jxwcQODY`{$dC%e$O*o=(p@K+!!@rAPYNn^*413^WW@>(|d)Sda-^% zza=G%V|0nehcTle{nPMd2`LNxA^%}?taFuaPJcX`btLIYb@GjfU1fr!+`)vP18aB3p5#ISL#^EK{) zC#Bgqk1GZTCS+Vfaz{%(B=>pVl#uda?~D<3U>M045>;=AtdFZ^M|pbLxCS*B#~j*G zEq@hc-hnu(wo!ZG+VWBL4Cr+qbv5o>LW6&vmru{DSYNjk5XtwAmW^Er)J}%Ijt= zE(Sy_u{SUJ3~gi%!*=Fux?xwA0{4!+JWvA;PnjoG3Xu`PU#c@wF(YcY)(z`VhtC++ zf=HY!x-q1+&Ct&`{N{uc1_CKK4J8oHwtpY}D+#%akXDf+4XFa25hBDk?|6xHXFDq4 z_+wv-Mst5Rdeh*GC z)&b6$d18cR(6=F^9jrJQuSTI9BAyz?^u}8@Fq=+@a}V(Gq8$mX&P+w-k`d1h)!~eI z8v6Z(7|+3-NzxT>z?rUX)TeA@QdM7f5kZ~Y(}>|WUBMKm3PRDX@65Vg*K3d zI!lOg&i2fyvIk>ki462x>h8(TZ!Xv9Q^-g(WMsr2zn|R7`|&-}hv?@MQYLn?nObS? zD>d^ioNYggd&gLt6m{XslUa6tXf0=XKl*t`tFVRM$r;@Xkr9Ura$xjj)~IB`XRB_G z%5_$07OY~Nb)}5C1c6k{+kcq#Nj2dwZC~RE?u?Fy=#dHJAwQTcrZC|?Xgy{04bJE_ z!RNHybUW_RCUuC6Yg&$8w1`ygQalS*#Z>VLgiOr0oYrh%2J4j0;*NSVhT}D$DTga8C^jyQr$7#CFFt27xwN=aun4VI@4s=4KgYnb+e}6nUBI10=xTaTI zd>W&c6}iiF(O&ej&8QAW);Yaro})H>)(`!bvS8BAxDR9uCZ9%sIU#?WJu=$yF6q(i z0{3;Fk@?DqK8!zYJI|4xBPX8SE+j9^=ANU-y5Jf}<}Hl5PKmRQ)oWAKf&INxSK!6! zfhlvjQPWPDF|P5PbAQJOa72!Os6M8S6?+NhisU%_wAG69zFtk2Gwv#>oWlEUt-`sW zb8Tr(0H=q{$nfI7+1ds;eMdsCaV&K1h{EBz?e^<#+(GPc-S+x6<~hux9g6)R zqhzRJCRw~vj^qboyhl&Zoo|e@Wc$z}om(!ypL6SDMtoyrH-E0^t%EmuT; z@OECUM}-t3;CF7ptz#um1k}(>)Fs7zHHWxp1GKOY{p7|sQ$LksluKIX@I5#F+dd-FOU14Y zONxbOLJKJwqXYBCkgn>XF+nw23 z!7e*OtYI&z^)LDP)3meEgR$mmTv4^=3%@QQD_5@jkYs8Tb+ByPchPsd*7(t(R!BCC zeF$kh2WsgB9h_IN^l*lep(Q<6`JP)xJCVO9`oHn&Tzw7x(*2c-YF9{ej0mh<%Ex!s zHh)j(Q(e0o=Yp;+je-8&wQrP_F;cjD;W|3NST(y&#PsmlPWYnnWJ$GghW@&xT#S|r zX&3Wdg!sl>k9DI}KR(-SHZb0}ZcM-CXB*+XMPz;xBTzz`Ggp4O6^ux)r#H$s`YV-t zXRP->=LeCSxQ0VWS*R$5_(i6=Q}&7;K!35(oG_BIQ>_`b^G?fj>JYi*!+e*m>y#@F zcJx8Qn`wU|a!47;hU+Fo2Akf({$^@FoYv*namH5uX9!Au5 zK9whu?W|*h9`s$jJhVu=%*>rUcabi@D8eq$2as&YuBjzF!Mn!jaz=7CWRSZS?|+!3 zBgXf2yfJoNWuP6^4fAmi*6?R;>~gSMZyhr_gm}f+hwM}+L`0<9P|NIglA$^b9+rjK15EcSYIL}PkwV2iW1k_v~w^TE9A$N?Hw&T&|kHs^Cntyso<|+ zZg?P%PnP%0c{M`Jk#%lg*^wV?@qdPicggN0FMiwIYC~1MqhmGddLc2?0+Ew4dOd_# z#%!%UzHeYOX^-3tqda@GaxsRyN3YDu_ZanJ@8>;c`f=v|89tt$5f#_`)VfPBe!6G2 zhkX|Itm$Ij`kvA<7-8RY$olf9?Z!%P&sPg7iM`T~`OYGCwV^j}uLv&_r+?Twa1(v_ zTO#8_{wA&M6TR+xy=0hwuy@g?;S=nZ9P=smp0+Utw)IB~HQ?SSmpOr?Ex=J?z`uVu`865^Rp)=lkT zU5-RS_*)sN4gE;_#-vxYVt=>R%eMEnS}`gj^!yy@l7hF)`EFtjc)l0;lZ<4pS~@vd z!yEl%S$NE%I-+RYXHH1n*tJ`?xpnl+3Gu~yC-=(PwPK@*yP}=EQbU_4B%Xngk}}t| z9f@6@I;jgoS0Mk*Fn`W>Ic3*@5rI>FG5jNXKhd{widZ!A>myNO=!X?z9V?+vM0xPm zjI?M&kMpU~k(j?{J|P=hXFeem`}!$!lG=Pd=yheVOe}OJBh_ z#);;icrTpR+QVqlX|nMc?K`cfi#)_)bbL>S%+%cM@_vsb$VNaJW$GSuDz3-rRUr3p#&CW>v!}bm_a?BVw zV_LyFy)$;&*nbs3NdAy<3HdRJ>O`3WR!1G_Ij&JVvsvXEaEc9LHqe>(`%oPUDUZ*> zd^S-3oTZ(EnV2WsiP$+w+&b~3aUqt_!z3Y5A8Np}dgIxWXN@Q>XCy|lAhJH5`XwYP z^$^*S?T5&13G30%dOp~?L}~;xyWKvna1l}(-z8fV7Juu+&(S=<J@kAIGoQpaCKRwE=QWRQXUcnjIv#rl$) zU(2Wgg~af7LW({Pt1_>oSwqi{c!O7rJKqu|F8I{NoI6fMkKTc*O^8+0&Q}_6^4=-3 z2B?2-iK10}KP86A;XWw0WxUaEtsnQiy0tq`AH8){t^|nM+=Tolh_)|( znm8x3nwa#8zKy%D4UE&?BM!@F`+QRT_!dqn+;R7wmbrW3Jr`JnC9J>rJ^AP}x=dnu=hXYQqzJ9a`$qcp_EY>-D82_C%}ml8z&KG+&CS z5xwpA<(iQnysxB=nTt<4t744ueNm6j$cRCJh^%rkze>tbmV!=wApA~WaDQ*i-h5y9 zL+C6#5oO1IPeMw=PTwzvU!y&El3DD7e0fQV^Y<)?THGN;ijtqLMB+M~Mj<&Pe|tqX zk=L!fQcx8HGOB&4k$Pq2SX z;(hft?l|>Y%L94uYo~Fx<9}N7-C_QYkg_l) zA;cg0(%x8&dp8L&j-$V^KdvTv913<(-uV z)&mN$iMsxsV~<(%xl%0nd(Nwly=%4Gr5Etb$tZKbjd%UyDSw*pY9BJ+xxGxjW$yaL z#Uy|_#($m!1IKoS6s|XWB9{ka1@HaJ$rAGM>`x({QO^ak(YGPp>_6DXv;5Ex`*d+X zjH5pp`42q{`lOHh5(u%xJ6?x7GpBglKFo|0;+JLtM=PIiQ|@FSrBmb~ka{S4Cg$^2 zoH-mw!;X|fVt)t|>_j0o8U3C>%BCC)A-d3MMTNv98-9XOCPkox#57{Cqe65}sryZq zKu(2huaGa}tXUx?cVeA^)Q@g6A+>xolT(OGzr!gJGAc%fgv^MgAQH7(u-_tSqhK$c z98KblqRT>Z{wOb6NKKRci9*~if{C^wmP$O@Ikog_*N(otYk)_BH z*=@X{k)J{=K$MwhsF;7HtQH|NCCW4xva3;yKM<=_5ijKA%=S(1&3JWUBr~y2Au*_)ev!F6Dxg5`D7xsc#$P!N_T(sCz)<`*2RAkYbhcLxgz2+J7Nh9^MCI=SDu&Ktw8Vb;gUf z8iYg%F0b3vWx^I|=2D1t24XmkI2^a0_y(M_RDYVSB4k^6`~+8f9@lN@+>=Kp5Xbr- zAz%F{b5TgM#J_ZT{wVV*5RM`U=@~n0M!!YBY!B9~AE^Q%r+jRc_y71@L~`AfeI}&T zO1>H)#`*C=M%~QCq>L8ZgOhX=@NZ7i7Qr<*o)h&-js_}RlM=&eQ{`tnBPL-mQVOrZ z`F}BmHV`kQs`bRR{y5v$b#dbFxg%$`y)S*2IiGY%r(6#qT2GomAw)MiDI+1vozL8p zbsY+kFxCpF zgOIH!;J?}5k9CVWAIe6RUPt48>_<{(pER z68}IN@0}_^N%@IF+~>tzRaazBB64ddznGBMumez*L~o6EZ!4T(97sD9rxj9bLKdKJ z@kX80gp98uTbJDb7F)6QqAxTd(oC2Q6iChFOA{gjMR`v`#5VXX*vn3Ns{cr5J1UBF z@HUIs7}f^|Vwm$Iq|{BGQz6=uk0ReW20Y`$ksPB@EANB8@KP%y}XE!`^g(SfUKCK-|!4_(?M@K3U^cXMdX*ZQ_yp zf3p|tQYB?tec)P>&3xMm+^r-%2ib^bIFRh+*d#9F7CNFn{hu4p-0zf9`V zo1-1cpy*{F_E7)C$ghvO0e=fQqJ#KL&&SauA*~kPZ^vZc@co=#FbgCQ$N6SLMw^cB zN1AD(H&4u|ZORQ7qT3V|i)0a3jOIw5%&0yhm8_s2Nr)MB1;~-;z#h#&HbxP?xVF&) z7|3I8`Fh=a<|0&#wo2zs9G~7o1O!+e<`ltLMr!CLL|R&u85c;wdVlmB4iTeTD4H!PkK^Nl5P_YE5z-fbl7@w@58x8$$K?88E zRSvVIiQ3QwfI-5ej)xp zPxK>YaZX3yt&n1rZGR%NO(4+~nGrjb z0g+=wZ>OAXAtL{j*%J#brN__aw)mIU5#0k3nYvK%&DCRu>M%Fm=afGxL?V#tnS_jd z`KjB9`WHsBp?1#FS%dAHxnvXm9vgPiubfRcJ+ciUjl9 zL~1qa+bTpNgDL_35zH+TG8)#s3puHwde2>K13e45>)H7J>E@Rz>mswZ>K`J#BxDgf5&F`}36l3B~7dYM4%qfQ(`TE;n0fs~6; z`8>^Va%~`vol=CXhW(X=oHVJgl#rVedYE$bD5U(voR^3Q-&xDbMAeo>t1fzV^IC22 zEwf^ZCL%lXGjK(P;FPRDN~KO+ftVpD&)Xxu%SbI4<$w7{`1kBlEAO5CKI~VMbwrBs zJ~+BjF$*N0lCcX#Ach@ggjinaSI%dK1VUujjb4v@j`TKv&n*@Gqd5wzF`FUlDtpYU z?h#=}YpKoF(YK!O^Gy|EB3#J|#`yF5IHz8SWzM{cu|Uo&;B~{ErIG*VhuQj@JUcf> zaxcyd3V)<-{5>TSuc))4kn&Z$7fM8vsD?wx{>NTqJ8 zs3i35mqtqg(0_k3OLNR&(mBXDU0F!4SeqndICdQtvP$8dI8R;30wgffVmm6si~Ssg zTX0W?W@|bx>`&5OG0%3tQZQPu4CW#t{*7;oZC2cd4== zkUTNI5Xi;YN7+*R$kxm5BE|gFI~RmJ z)8<#$?wrX}7KE&H*!G^tk-@Vq?tiI2pO6=$YYDlZu3Frq(SeTl^_AV>HMq56KUE=C z9b-l%I*RkzzFKLveD~Fc`4r{V81I5eFYJF4Vjp@Mr6$vdH4j4Sp!y#n=R0U!YTQ_u zX;D)Zxg({!QHXvH-DXwRI#H(wA#RRd0wL}gqpWF^g1+^drgS5J&zCn%0b@jOdR~~J zUv)9CpHGNkFKZ#Ea@Ke)&u}7hu6o^t=DiCM@8x$|B~6e8R9Ux$Svs|L-NF0>=i{uS zT4l!2iq-n0-0*vs-c12se}9oOMr>+yY(sXdi}9G+<>r zy1vq|a!ZKegmxh%8OExs{=j(MR%<_O)r#5ncuH1GJLhLxZDPE>u2Y+WSxe~-dIwA}c9_Vms6Z9lOWT%D7?k9SoJWy3rnUFe3>#e|ga#~Pe! zoW-jfGgan0r~Bi#eNNN>A#z*AjNE!t`*9j?Zkun-oBhM+n5at{Y~!!lKrcZIf_IFc z*4t}E4^zFCrwdCzkKNKOWbn2IuTQqIJ*hl+%8|Xc5->4HkjqN+qM*KHNr-b%F`>!*i)oJ-F z>~n|!2lfIHekS&SMh?Fb(h=sI})+aLeU z$P*QEi<%*1HA3_~xNf#m`SH|CD~I3X>En99<`McvD;8c@ehV%ojPc;8+e*B5+^wVS zZ9Y@SytL-4aAkM%6a7pPk@-hn)w;wU^_df5U;FVl_D#GSbq;iC@u&F@UqI_pIjHo6 zFmqw7qPEC*pAdL=-NOUC;jsZzhT&(XWi_+=Y} zP-^5;?@SMK<|KuwvWyNN+Ks1vl#nnY?bp)44l`v8?@WV;>>Z4#39*Znb!D8|F~_XT zk=RNrbBh1)ZgIl8~1+`Zmf6QrY;We@lD;vkc0LX<>$nh^BY_{XlRsog=C8 zT`!~NA=C45*#W(IWex74EJS=8GvkW58P2>HvVF24BI3?i_ffVCZ~o1Wi7nOQ9mTOu z+*|l#pKT#I;G}UOo-W33Fw4U%-m+Kdd}C}`8_2-QezBuZsGRJBD;OyoYki9+#vwN= zf2Y?;6MGzKk1f?BHivwn+)z9EP|A&sE8<1wDn}kmFLyNhl+GzXN7|KLHMU62XyfJF@@*DnZ zCeFlvO*bIsK}xr|lZg=T*@in;Q}V`!h~#|GJ6Sz0LUZAS)XH9hnr2KG6BkmsYeV(4 zWb9K?)6Eg%fHl4F@MJl6KbSc$q;XxfMwhQWAOzst+HrJ$FfO5hUu@MVX!j-JL^f2VOBn2?syTCa7riIrPEyQ-n5(bK=};|*?VtV3FC z9QCbDpNb4wAL_NXjI_dM+mkcU>a6083;owZd{P%8vg6TfSlfw)dFw)~qZQ!D#r%-k zJS!P@q20_;IFHxhgm!Oe;f@?cvX3o7q!zBVs^Xd%vl(h1b)d~B>Yllye?;v*83EsI z#K@USLNdpoIvYgb*Khi;_5JoM^|_xkE$`V4bqk z(CaRwa;H@xt)UHDmrt)k+0jcUUTcr2VKz`*K2i1q$?U7CtGnuBq~dIFAtNl7-Zf)k z*;y+*tc9z~=cDr)Tzlwgf2>O!lx-x@eU8iMRGA?YuRABsxT(9;j1?|*S7Tp|BL{tU zb@ysCuRzEw5xr7%pSY0+*Zo99(Ly<)Jeou$#9Kb`ZxVN6ccdk@o=*01yboltjz1+2 zzUxnqAM$o~j+oKm&FpZZpOD9Mc~bq2bi&n<3M*_QUFjX(xjXIff4kisxl3>LpaJdG_Le|sps&F9r%JyY|}6?n_&2U0!w*F4&XcZrZTQ6n{vh9V1XZsViR zp`}(1+R82MR?)-MEM%NyAS9MGQR0Oh)K$&8&JTX6Y{8B`q2@&bc($7zZ~Vwe<&H+p zZg?1{h;t03XY#-0@>URFp9l1}VBOP4@}f-q zn=Yk@>n4O_e=JS(V_?=^lR3ya7*2K#qnAS3V~x~2GaApS4#T49%0foCSgY8Yv_Zay8>B}nH6#7#U8CdJr5`Ss;Y0>zck<&zL-P`*I z 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 N(o#{;dQdt|^&dyT7ytkO delta 90434 zcmZU)V|bli^FAEgO&Z&7Y&3Rbr?GA4ip?D~Xl$#ot%i-+*tY+<@B8_EdEYPlIQBl) ztZS|{Gv~}Xv-aB(eA)qg4K*wv)Va5IRRsp7EQ!g>M{G$% z!@f_(i?#v=K