diff --git a/.github/workflows/api-consumption-report.md b/.github/workflows/api-consumption-report.md index b9b6263cfc5..5e237147b87 100644 --- a/.github/workflows/api-consumption-report.md +++ b/.github/workflows/api-consumption-report.md @@ -152,6 +152,18 @@ Example structure: ## Step 3 — Update Cache-Memory Trending History +**Cache validation**: Before appending, check whether the cache was restored from a previous run: + +```bash +history_file="/tmp/gh-aw/cache-memory/trending/api-consumption/history.jsonl" +if [ -f "$history_file" ] && [ -s "$history_file" ]; then + entry_count=$(wc -l < "$history_file") + echo "Cache restored from previous run: yes ($entry_count existing entries)" +else + echo "Cache restored from previous run: no (first run or empty cache)" +fi +``` + Append today's summary to the rolling history file: ``` @@ -405,6 +417,7 @@ Create a discussion with the following structure. Replace placeholders with real 📦 Cache Memory Status - **Location**: `/tmp/gh-aw/cache-memory/trending/api-consumption/history.jsonl` +- **Cache restored from previous run**: {yes (N entries) / no (first run)} - **Data points stored**: {data_points} - **Earliest entry**: {earliest_date} - **Retention policy**: 90 days diff --git a/.github/workflows/cloclo.lock.yml b/.github/workflows/cloclo.lock.yml index 93d68184ceb..83b583eb54d 100644 --- a/.github/workflows/cloclo.lock.yml +++ b/.github/workflows/cloclo.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"05880052889e3bbb55a9ba4a46ba2573d79401b4fbb53fab9552a56848ce8893","strict":true,"agent_id":"claude"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"8b86dda695c9490ee6bf58d37aaa2214a88f42af04a109262ac07f3889ad59e6","strict":true,"agent_id":"claude"} # gh-aw-manifest: {"version":1,"secrets":["ANTHROPIC_API_KEY","GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"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-go","sha":"4a3601121dd01d1626a1e23e37211e3254c1c06c","version":"v6.4.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"docker/build-push-action","sha":"bcafcacb16a39f128d818304e6c9c0c18556b85f","version":"v7.1.0"},{"repo":"docker/setup-buildx-action","sha":"4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd","version":"v4"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.28","digest":"sha256:a8834e285807654bf680154faa710d43fe4365a0868142f5c20e48c85e137a7a","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.28@sha256:a8834e285807654bf680154faa710d43fe4365a0868142f5c20e48c85e137a7a"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.28","digest":"sha256:93290f2393752252911bd7c39a047f776c0b53063575e7bde4e304962a9a61cb","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.28@sha256:93290f2393752252911bd7c39a047f776c0b53063575e7bde4e304962a9a61cb"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.28","digest":"sha256:844c18280f82cd1b06345eb2f4e91966b34185bfc51c9f237c3e022e848fb474","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.28@sha256:844c18280f82cd1b06345eb2f4e91966b34185bfc51c9f237c3e022e848fb474"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.0"},{"image":"ghcr.io/github/github-mcp-server:v1.0.2"},{"image":"ghcr.io/github/serena-mcp-server:latest","digest":"sha256:bf343399e3725c45528f531a230f3a04521d4cdef29f9a5af6282ff0d3c393c5","pinned_image":"ghcr.io/github/serena-mcp-server:latest@sha256:bf343399e3725c45528f531a230f3a04521d4cdef29f9a5af6282ff0d3c393c5"},{"image":"mcr.microsoft.com/playwright/mcp","digest":"sha256:7b82f29c6ef83480a97f612d53ac3fd5f30a32df3fea1e06923d4204d3532bb2","pinned_image":"mcr.microsoft.com/playwright/mcp@sha256:7b82f29c6ef83480a97f612d53ac3fd5f30a32df3fea1e06923d4204d3532bb2"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} # ___ _ _ # / _ \ | | (_) @@ -275,9 +275,9 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_b5ce1be05f56810c_EOF' + cat << 'GH_AW_PROMPT_c0a594c3f146f6fd_EOF' - GH_AW_PROMPT_b5ce1be05f56810c_EOF + GH_AW_PROMPT_c0a594c3f146f6fd_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" @@ -285,16 +285,16 @@ jobs: cat "${RUNNER_TEMP}/gh-aw/prompts/agentic_workflows_guide.md" cat "${RUNNER_TEMP}/gh-aw/prompts/cache_memory_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_b5ce1be05f56810c_EOF' + cat << 'GH_AW_PROMPT_c0a594c3f146f6fd_EOF' Tools: add_comment, create_pull_request, missing_tool, missing_data, noop - GH_AW_PROMPT_b5ce1be05f56810c_EOF + GH_AW_PROMPT_c0a594c3f146f6fd_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_create_pull_request.md" - cat << 'GH_AW_PROMPT_b5ce1be05f56810c_EOF' + cat << 'GH_AW_PROMPT_c0a594c3f146f6fd_EOF' - GH_AW_PROMPT_b5ce1be05f56810c_EOF + GH_AW_PROMPT_c0a594c3f146f6fd_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_b5ce1be05f56810c_EOF' + cat << 'GH_AW_PROMPT_c0a594c3f146f6fd_EOF' The following GitHub context information is available for this workflow: {{#if __GH_AW_GITHUB_ACTOR__ }} @@ -323,12 +323,12 @@ jobs: {{/if}} - GH_AW_PROMPT_b5ce1be05f56810c_EOF + GH_AW_PROMPT_c0a594c3f146f6fd_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" if [ "$GITHUB_EVENT_NAME" = "issue_comment" ] && [ -n "$GH_AW_IS_PR_COMMENT" ] || [ "$GITHUB_EVENT_NAME" = "pull_request_review_comment" ] || [ "$GITHUB_EVENT_NAME" = "pull_request_review" ]; then cat "${RUNNER_TEMP}/gh-aw/prompts/pr_context_prompt.md" fi - cat << 'GH_AW_PROMPT_b5ce1be05f56810c_EOF' + cat << 'GH_AW_PROMPT_c0a594c3f146f6fd_EOF' ## Serena Code Analysis @@ -365,7 +365,7 @@ jobs: {{#runtime-import .github/workflows/shared/mcp/serena-go.md}} {{#runtime-import .github/workflows/shared/reporting.md}} {{#runtime-import .github/workflows/cloclo.md}} - GH_AW_PROMPT_b5ce1be05f56810c_EOF + GH_AW_PROMPT_c0a594c3f146f6fd_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 @@ -665,9 +665,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_98581509f913d5aa_EOF' + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_9af7e074921cf918_EOF' {"add_comment":{"max":1},"create_pull_request":{"excluded_files":[".github/workflows/*.lock.yml"],"expires":48,"labels":["automation","cloclo"],"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","DESIGN.md","CLAUDE.md","AGENTS.md"],"protected_files_policy":"fallback-to-issue","protected_path_prefixes":[".github/",".agents/",".githooks/",".husky/",".claude/"],"title_prefix":"[cloclo] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} - GH_AW_SAFE_OUTPUTS_CONFIG_98581509f913d5aa_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_9af7e074921cf918_EOF - name: Write Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -901,7 +901,7 @@ jobs: 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 /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.3.0' GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_9a4d8800d86c517c_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_39c90f8439173991_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "agenticworkflows": { @@ -1009,7 +1009,7 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_9a4d8800d86c517c_EOF + GH_AW_MCP_CONFIG_39c90f8439173991_EOF - name: Mount MCP servers as CLIs id: mount-mcp-clis continue-on-error: true diff --git a/.github/workflows/cloclo.md b/.github/workflows/cloclo.md index 172e33e904b..110b74681c5 100644 --- a/.github/workflows/cloclo.md +++ b/.github/workflows/cloclo.md @@ -27,7 +27,7 @@ tools: playwright: bash: true cache-memory: - key: cloclo-memory-${{ github.workflow }}-${{ github.run_id }} + key: cloclo-memory-${{ github.workflow }} safe-outputs: create-pull-request: expires: 2d diff --git a/.github/workflows/poem-bot.lock.yml b/.github/workflows/poem-bot.lock.yml index 4c4f55d8d66..b04cc0e04b2 100644 --- a/.github/workflows/poem-bot.lock.yml +++ b/.github/workflows/poem-bot.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"f13f798d1656df3e6936f8f8655271763099d96a1a3b64fcd639879a51790f9a","strict":true,"agent_id":"copilot","agent_model":"gpt-5"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"223e31aa7ed4ac26a21e61cb71d52be240886fc68ef8cebcbda9e2f2f18d2f7a","strict":true,"agent_id":"copilot","agent_model":"gpt-5"} # gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_AGENT_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"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":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.28","digest":"sha256:a8834e285807654bf680154faa710d43fe4365a0868142f5c20e48c85e137a7a","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.28@sha256:a8834e285807654bf680154faa710d43fe4365a0868142f5c20e48c85e137a7a"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.28","digest":"sha256:93290f2393752252911bd7c39a047f776c0b53063575e7bde4e304962a9a61cb","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.28@sha256:93290f2393752252911bd7c39a047f776c0b53063575e7bde4e304962a9a61cb"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.28","digest":"sha256:844c18280f82cd1b06345eb2f4e91966b34185bfc51c9f237c3e022e848fb474","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.28@sha256:844c18280f82cd1b06345eb2f4e91966b34185bfc51c9f237c3e022e848fb474"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.0"},{"image":"ghcr.io/github/github-mcp-server:v1.0.2"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} # ___ _ _ # / _ \ | | (_) @@ -240,25 +240,25 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_b408d9dacab7d48a_EOF' + cat << 'GH_AW_PROMPT_6e1306852ad83aaf_EOF' - GH_AW_PROMPT_b408d9dacab7d48a_EOF + GH_AW_PROMPT_6e1306852ad83aaf_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/cache_memory_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_b408d9dacab7d48a_EOF' + cat << 'GH_AW_PROMPT_6e1306852ad83aaf_EOF' Tools: add_comment(max:3), create_issue(max:2), update_issue(max:2), create_discussion(max:2), create_agent_session, create_pull_request, close_pull_request(max:2), create_pull_request_review_comment(max:2), add_labels(max:5), push_to_pull_request_branch, link_sub_issue(max:3), missing_tool, missing_data, noop - GH_AW_PROMPT_b408d9dacab7d48a_EOF + GH_AW_PROMPT_6e1306852ad83aaf_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_create_pull_request.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_push_to_pr_branch.md" - cat << 'GH_AW_PROMPT_b408d9dacab7d48a_EOF' + cat << 'GH_AW_PROMPT_6e1306852ad83aaf_EOF' - GH_AW_PROMPT_b408d9dacab7d48a_EOF + GH_AW_PROMPT_6e1306852ad83aaf_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_b408d9dacab7d48a_EOF' + cat << 'GH_AW_PROMPT_6e1306852ad83aaf_EOF' The following GitHub context information is available for this workflow: {{#if __GH_AW_GITHUB_ACTOR__ }} @@ -287,7 +287,7 @@ jobs: {{/if}} - GH_AW_PROMPT_b408d9dacab7d48a_EOF + GH_AW_PROMPT_6e1306852ad83aaf_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" if [ "$GITHUB_EVENT_NAME" = "issue_comment" ] && [ -n "$GH_AW_IS_PR_COMMENT" ] || [ "$GITHUB_EVENT_NAME" = "pull_request_review_comment" ] || [ "$GITHUB_EVENT_NAME" = "pull_request_review" ]; then cat "${RUNNER_TEMP}/gh-aw/prompts/pr_context_prompt.md" @@ -295,11 +295,11 @@ jobs: if [ "$GITHUB_EVENT_NAME" = "issue_comment" ] && [ -n "$GH_AW_IS_PR_COMMENT" ] || [ "$GITHUB_EVENT_NAME" = "pull_request_review_comment" ] || [ "$GITHUB_EVENT_NAME" = "pull_request_review" ]; then cat "${RUNNER_TEMP}/gh-aw/prompts/pr_context_push_to_pr_branch_guidance.md" fi - cat << 'GH_AW_PROMPT_b408d9dacab7d48a_EOF' + cat << 'GH_AW_PROMPT_6e1306852ad83aaf_EOF' {{#runtime-import .github/workflows/shared/reporting.md}} {{#runtime-import .github/workflows/poem-bot.md}} - GH_AW_PROMPT_b408d9dacab7d48a_EOF + GH_AW_PROMPT_6e1306852ad83aaf_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 @@ -525,9 +525,9 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs/upload-artifacts" - cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_0ea35372bf399405_EOF' + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_94256f3d3f1c6097_EOF' {"add_comment":{"max":3,"target":"*"},"add_labels":{"allowed":["poetry","creative","automation","ai-generated","epic","haiku","sonnet","limerick"],"max":5},"close_pull_request":{"max":2,"required_labels":["poetry","automation"],"required_title_prefix":"[🎨 POETRY]","target":"*"},"create_agent_session":{"base":"main","max":1},"create_discussion":{"category":"audits","close_older_discussions":true,"expires":24,"fallback_to_issue":true,"labels":["poetry","automation","ai-generated"],"max":2,"title_prefix":"[📜 POETRY] "},"create_issue":{"expires":48,"group":true,"labels":["poetry","automation","ai-generated"],"max":2,"title_prefix":"[🎭 POEM-BOT] "},"create_pull_request":{"draft":false,"expires":48,"labels":["poetry","automation","creative-writing"],"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","DESIGN.md","AGENTS.md","CLAUDE.md","GEMINI.md"],"protected_path_prefixes":[".github/",".agents/",".githooks/",".husky/"],"reviewers":["copilot"],"title_prefix":"[🎨 POETRY] "},"create_pull_request_review_comment":{"max":2,"side":"RIGHT"},"create_report_incomplete_issue":{},"link_sub_issue":{"max":3,"parent_required_labels":["poetry","epic"],"parent_title_prefix":"[🎭 POEM-BOT]","sub_required_labels":["poetry"],"sub_title_prefix":"[🎭 POEM-BOT]"},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"push_to_pull_request_branch":{"if_no_changes":"warn","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","DESIGN.md","AGENTS.md","CLAUDE.md","GEMINI.md"],"protected_path_prefixes":[".github/",".agents/",".githooks/",".husky/"]},"report_incomplete":{},"update_issue":{"allow_body":true,"allow_status":true,"allow_title":true,"max":2,"target":"*"},"upload_artifact":{"max-size-bytes":104857600,"max-uploads":1,"retention-days":30}} - GH_AW_SAFE_OUTPUTS_CONFIG_0ea35372bf399405_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_94256f3d3f1c6097_EOF - name: Write Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -1005,7 +1005,7 @@ jobs: 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_4ca7187fa45e194b_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_b7df822785374805_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "github": { @@ -1046,7 +1046,7 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_4ca7187fa45e194b_EOF + GH_AW_MCP_CONFIG_b7df822785374805_EOF - name: Mount MCP servers as CLIs id: mount-mcp-clis continue-on-error: true diff --git a/.github/workflows/poem-bot.md b/.github/workflows/poem-bot.md index 479757729cc..486eb163b03 100644 --- a/.github/workflows/poem-bot.md +++ b/.github/workflows/poem-bot.md @@ -49,7 +49,7 @@ tools: - "git" # Memory cache for persistent AI memory across runs cache-memory: - key: poem-memory-${{ github.workflow }}-${{ github.run_id }} + key: poem-memory-${{ github.workflow }} retention-days: 30 # Comprehensive safe-outputs configuration - ALL types with staged mode diff --git a/.github/workflows/python-data-charts.lock.yml b/.github/workflows/python-data-charts.lock.yml index 5be1c5616e5..826bff2c4ef 100644 --- a/.github/workflows/python-data-charts.lock.yml +++ b/.github/workflows/python-data-charts.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"76235d12ff53ff9dc2cc14b00712702c925e4a54b32c3a39f6f4e571d787eb5c","strict":true,"agent_id":"copilot"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"a9f5127311ce3720bc28d3d4b61584a0e898c0641792d63ddfa31284043e4963","strict":true,"agent_id":"copilot"} # gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"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-go","sha":"4a3601121dd01d1626a1e23e37211e3254c1c06c","version":"v6.4.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/setup-python","sha":"a309ff8b426b58ec0e2a45f0f869d46889d02405","version":"v6.2.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"docker/build-push-action","sha":"bcafcacb16a39f128d818304e6c9c0c18556b85f","version":"v7.1.0"},{"repo":"docker/setup-buildx-action","sha":"4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd","version":"v4"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.28","digest":"sha256:a8834e285807654bf680154faa710d43fe4365a0868142f5c20e48c85e137a7a","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.28@sha256:a8834e285807654bf680154faa710d43fe4365a0868142f5c20e48c85e137a7a"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.28","digest":"sha256:93290f2393752252911bd7c39a047f776c0b53063575e7bde4e304962a9a61cb","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.28@sha256:93290f2393752252911bd7c39a047f776c0b53063575e7bde4e304962a9a61cb"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.28","digest":"sha256:844c18280f82cd1b06345eb2f4e91966b34185bfc51c9f237c3e022e848fb474","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.28@sha256:844c18280f82cd1b06345eb2f4e91966b34185bfc51c9f237c3e022e848fb474"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.0"},{"image":"ghcr.io/github/github-mcp-server:v1.0.2"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} # ___ _ _ # / _ \ | | (_) @@ -184,24 +184,24 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_81a8e50872c6de0c_EOF' + cat << 'GH_AW_PROMPT_add4675a8ec09a44_EOF' - GH_AW_PROMPT_81a8e50872c6de0c_EOF + GH_AW_PROMPT_add4675a8ec09a44_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/agentic_workflows_guide.md" cat "${RUNNER_TEMP}/gh-aw/prompts/cache_memory_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_81a8e50872c6de0c_EOF' + cat << 'GH_AW_PROMPT_add4675a8ec09a44_EOF' Tools: create_discussion, upload_asset(max:5), missing_tool, missing_data, noop upload_asset: provide a file path; returns a URL; assets are published after the workflow completes (safeoutputs). - GH_AW_PROMPT_81a8e50872c6de0c_EOF + GH_AW_PROMPT_add4675a8ec09a44_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_81a8e50872c6de0c_EOF' + cat << 'GH_AW_PROMPT_add4675a8ec09a44_EOF' The following GitHub context information is available for this workflow: {{#if __GH_AW_GITHUB_ACTOR__ }} @@ -230,15 +230,15 @@ jobs: {{/if}} - GH_AW_PROMPT_81a8e50872c6de0c_EOF + GH_AW_PROMPT_add4675a8ec09a44_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_81a8e50872c6de0c_EOF' + cat << 'GH_AW_PROMPT_add4675a8ec09a44_EOF' {{#runtime-import .github/workflows/shared/charts-with-trending.md}} {{#runtime-import .github/workflows/shared/python-dataviz.md}} {{#runtime-import .github/workflows/shared/trends.md}} {{#runtime-import .github/workflows/python-data-charts.md}} - GH_AW_PROMPT_81a8e50872c6de0c_EOF + GH_AW_PROMPT_add4675a8ec09a44_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 @@ -532,9 +532,9 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs/upload-artifacts" - cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << GH_AW_SAFE_OUTPUTS_CONFIG_a50c8e475bad7c13_EOF + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << GH_AW_SAFE_OUTPUTS_CONFIG_215e8b901c87e9d1_EOF {"create_discussion":{"category":"artifacts","expires":24,"fallback_to_issue":true,"max":1},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{},"upload_artifact":{"max-size-bytes":104857600,"max-uploads":3,"retention-days":30,"skip-archive":true},"upload_asset":{"allowed-exts":[".png",".jpg",".jpeg",".svg"],"branch":"assets/${GITHUB_WORKFLOW}","max":5,"max-size":10240}} - GH_AW_SAFE_OUTPUTS_CONFIG_a50c8e475bad7c13_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_215e8b901c87e9d1_EOF - name: Write Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -742,7 +742,7 @@ jobs: 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_44d0cdc5bdbd6d85_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_cbc1ab9ee7a4183a_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "agenticworkflows": { @@ -802,7 +802,7 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_44d0cdc5bdbd6d85_EOF + GH_AW_MCP_CONFIG_cbc1ab9ee7a4183a_EOF - name: Mount MCP servers as CLIs id: mount-mcp-clis continue-on-error: true diff --git a/.github/workflows/shared/charts-with-trending.md b/.github/workflows/shared/charts-with-trending.md index af895d9d519..a81f7b09a05 100644 --- a/.github/workflows/shared/charts-with-trending.md +++ b/.github/workflows/shared/charts-with-trending.md @@ -27,7 +27,7 @@ imports: tools: cache-memory: - key: charts-trending-${{ env.GH_AW_WORKFLOW_ID_SANITIZED }}-${{ github.run_id }} + key: charts-trending-${{ env.GH_AW_WORKFLOW_ID_SANITIZED }} --- # Charts with Trending - Complete Guide diff --git a/.github/workflows/shared/trending-charts-simple.md b/.github/workflows/shared/trending-charts-simple.md index e3b559b862e..1e543de8241 100644 --- a/.github/workflows/shared/trending-charts-simple.md +++ b/.github/workflows/shared/trending-charts-simple.md @@ -4,7 +4,7 @@ tools: cache-memory: - key: trending-data-${{ env.GH_AW_WORKFLOW_ID_SANITIZED }}-${{ github.run_id }} + key: trending-data-${{ env.GH_AW_WORKFLOW_ID_SANITIZED }} bash: - "*" diff --git a/.github/workflows/stale-repo-identifier.lock.yml b/.github/workflows/stale-repo-identifier.lock.yml index fd1fba554dd..f6541fa2046 100644 --- a/.github/workflows/stale-repo-identifier.lock.yml +++ b/.github/workflows/stale-repo-identifier.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"c9d04cc37c7b87b23c32c61d51aff8bd9c650f40ada0ba452ceaa53244a48a5d","strict":true,"agent_id":"copilot"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"d244c78cced3a9fe34f29779b857ad7488c36f36c7c24a62b34a83e8f1859244","strict":true,"agent_id":"copilot"} # gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_ENDPOINT","GH_AW_OTEL_HEADERS","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"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":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/setup-python","sha":"a309ff8b426b58ec0e2a45f0f869d46889d02405","version":"v6.2.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/stale-repos","sha":"5f2e18fc5432823f96c1feb69327f665c2acab59","version":"v9.0.8"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.28","digest":"sha256:a8834e285807654bf680154faa710d43fe4365a0868142f5c20e48c85e137a7a","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.28@sha256:a8834e285807654bf680154faa710d43fe4365a0868142f5c20e48c85e137a7a"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.28","digest":"sha256:93290f2393752252911bd7c39a047f776c0b53063575e7bde4e304962a9a61cb","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.28@sha256:93290f2393752252911bd7c39a047f776c0b53063575e7bde4e304962a9a61cb"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.28","digest":"sha256:844c18280f82cd1b06345eb2f4e91966b34185bfc51c9f237c3e022e848fb474","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.28@sha256:844c18280f82cd1b06345eb2f4e91966b34185bfc51c9f237c3e022e848fb474"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.0"},{"image":"ghcr.io/github/github-mcp-server:v1.0.2"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} # ___ _ _ # / _ \ | | (_) @@ -208,15 +208,15 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_e60571291c112fc7_EOF' + cat << 'GH_AW_PROMPT_5d9a37b4d9bf19c5_EOF' - GH_AW_PROMPT_e60571291c112fc7_EOF + GH_AW_PROMPT_5d9a37b4d9bf19c5_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/cache_memory_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_e60571291c112fc7_EOF' + cat << 'GH_AW_PROMPT_5d9a37b4d9bf19c5_EOF' Tools: create_issue(max:10), create_discussion, upload_asset(max:5), missing_tool, missing_data, noop @@ -250,9 +250,9 @@ jobs: {{/if}} - GH_AW_PROMPT_e60571291c112fc7_EOF + GH_AW_PROMPT_5d9a37b4d9bf19c5_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_e60571291c112fc7_EOF' + cat << 'GH_AW_PROMPT_5d9a37b4d9bf19c5_EOF' {{#runtime-import .github/workflows/shared/github-guard-policy.md}} {{#runtime-import .github/workflows/shared/jqschema.md}} @@ -260,7 +260,7 @@ jobs: {{#runtime-import .github/workflows/shared/reporting.md}} {{#runtime-import .github/workflows/shared/observability-otlp.md}} {{#runtime-import .github/workflows/stale-repo-identifier.md}} - GH_AW_PROMPT_e60571291c112fc7_EOF + GH_AW_PROMPT_5d9a37b4d9bf19c5_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 @@ -580,9 +580,9 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs/upload-artifacts" - cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << GH_AW_SAFE_OUTPUTS_CONFIG_555d5b0a3d5f58b1_EOF + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << GH_AW_SAFE_OUTPUTS_CONFIG_a74e2253525531da_EOF {"create_discussion":{"category":"audits","close_older_discussions":true,"expires":72,"fallback_to_issue":true,"max":1,"title_prefix":"[stale-repo-identifier] "},"create_issue":{"expires":48,"group":true,"labels":["stale-repository","automated-analysis","cookie"],"max":10,"title_prefix":"[Stale Repository] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{},"upload_artifact":{"allowed-paths":["**/*.png","**/*.jpg","**/*.svg"],"max-size-bytes":104857600,"max-uploads":5,"retention-days":30,"skip-archive":true},"upload_asset":{"allowed-exts":[".png",".jpg",".jpeg",".svg"],"branch":"assets/${GITHUB_WORKFLOW}","max":5,"max-size":10240}} - GH_AW_SAFE_OUTPUTS_CONFIG_555d5b0a3d5f58b1_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_a74e2253525531da_EOF - name: Write Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -819,7 +819,7 @@ jobs: 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_2052547cc855def1_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_ff4c587e437ae9d8_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "github": { @@ -869,7 +869,7 @@ jobs: } } } - GH_AW_MCP_CONFIG_2052547cc855def1_EOF + GH_AW_MCP_CONFIG_ff4c587e437ae9d8_EOF - name: Clean git credentials continue-on-error: true run: bash "${RUNNER_TEMP}/gh-aw/actions/clean_git_credentials.sh" diff --git a/.github/workflows/stale-repo-identifier.md b/.github/workflows/stale-repo-identifier.md index 4b45b720a2b..a11c77fe457 100644 --- a/.github/workflows/stale-repo-identifier.md +++ b/.github/workflows/stale-repo-identifier.md @@ -66,7 +66,7 @@ tools: - issues - pull_requests cache-memory: - key: stale-repos-analysis-${{ github.workflow }}-${{ github.run_id }} + key: stale-repos-analysis-${{ github.workflow }} bash: - "*" edit: diff --git a/pkg/workflow/cache.go b/pkg/workflow/cache.go index 5f8b7498756..6e8469bcede 100644 --- a/pkg/workflow/cache.go +++ b/pkg/workflow/cache.go @@ -85,6 +85,9 @@ func parseCacheMemoryEntry(cacheMap map[string]any, defaultID string) (CacheMemo // Parse custom key if key, exists := cacheMap["key"]; exists { if keyStr, ok := key.(string); ok { + if err := validateNoCacheKeyRunID(keyStr); err != nil { + return entry, err + } entry.Key = keyStr // Automatically append -${{ github.run_id }} if the key doesn't already end with it runIdSuffix := "-${{ github.run_id }}" diff --git a/pkg/workflow/cache_key_validation_test.go b/pkg/workflow/cache_key_validation_test.go new file mode 100644 index 00000000000..b6aacdd7378 --- /dev/null +++ b/pkg/workflow/cache_key_validation_test.go @@ -0,0 +1,126 @@ +//go:build !integration + +package workflow + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// TestCacheKeyRunIDValidationObject tests that github.run_id in a cache key raises +// a compilation error (object notation). +func TestCacheKeyRunIDValidationObject(t *testing.T) { + tests := []struct { + name string + key string + wantError bool + errorText string + }{ + { + name: "key without run_id is accepted", + key: "trending-data-${{ env.GH_AW_WORKFLOW_ID_SANITIZED }}", + wantError: false, + }, + { + name: "key with run_id is rejected", + key: "trending-data-${{ env.GH_AW_WORKFLOW_ID_SANITIZED }}-${{ github.run_id }}", + wantError: true, + errorText: "cache key must not reference github.run_id", + }, + { + name: "key with only run_id is rejected", + key: "${{ github.run_id }}", + wantError: true, + errorText: "cache key must not reference github.run_id", + }, + { + name: "plain key without expressions is accepted", + key: "my-stable-cache-key", + wantError: false, + }, + { + name: "key with github.run_identifier is not a false positive", + key: "my-cache-${{ github.run_identifier }}", + wantError: false, + }, + { + name: "key with github.run_id_backup suffix is not a false positive", + key: "my-cache-github.run_id_backup", + wantError: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + toolsMap := map[string]any{ + "cache-memory": map[string]any{ + "key": tt.key, + }, + } + + toolsConfig, err := ParseToolsConfig(toolsMap) + require.NoError(t, err, "Should parse tools config") + + compiler := NewCompiler() + _, err = compiler.extractCacheMemoryConfig(toolsConfig) + + if tt.wantError { + require.Error(t, err, "Should return error for key containing run_id") + assert.ErrorContains(t, err, tt.errorText, "Error should contain expected message") + } else { + assert.NoError(t, err, "Should not return error for valid key") + } + }) + } +} + +// TestCacheKeyRunIDValidationArray tests that github.run_id in a cache key raises +// a compilation error (array notation). +func TestCacheKeyRunIDValidationArray(t *testing.T) { + tests := []struct { + name string + key string + wantError bool + errorText string + }{ + { + name: "array entry key without run_id is accepted", + key: "my-data-${{ env.GH_AW_WORKFLOW_ID_SANITIZED }}", + wantError: false, + }, + { + name: "array entry key with run_id is rejected", + key: "my-data-${{ env.GH_AW_WORKFLOW_ID_SANITIZED }}-${{ github.run_id }}", + wantError: true, + errorText: "cache key must not reference github.run_id", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + toolsMap := map[string]any{ + "cache-memory": []any{ + map[string]any{ + "id": "test-cache", + "key": tt.key, + }, + }, + } + + toolsConfig, err := ParseToolsConfig(toolsMap) + require.NoError(t, err, "Should parse tools config") + + compiler := NewCompiler() + _, err = compiler.extractCacheMemoryConfig(toolsConfig) + + if tt.wantError { + require.Error(t, err, "Should return error for key containing run_id") + assert.ErrorContains(t, err, tt.errorText, "Error should contain expected message") + } else { + assert.NoError(t, err, "Should not return error for valid key") + } + }) + } +} diff --git a/pkg/workflow/cache_validation.go b/pkg/workflow/cache_validation.go index 82a5efdd5d3..63c104e9541 100644 --- a/pkg/workflow/cache_validation.go +++ b/pkg/workflow/cache_validation.go @@ -9,6 +9,7 @@ // # Validation Functions // // - validateNoDuplicateCacheIDs() - Ensures each cache entry has a unique ID +// - validateNoCacheKeyRunID() - Rejects cache keys that reference github.run_id // // # When to Add Validation Here // @@ -18,6 +19,34 @@ package workflow +import "regexp" + +// cacheKeyRunIDPattern matches github.run_id as a complete token — not as a +// prefix of a longer identifier like "github.run_identifier". +// It matches "github.run_id" that is either: +// - not followed by an underscore or word character (letter/digit/underscore) +// - at the end of the string +var cacheKeyRunIDPattern = regexp.MustCompile(`github\.run_id(?:[^_\w]|$)`) + +// validateNoCacheKeyRunID returns an error when a user-supplied cache key +// contains the ${{ github.run_id }} expression. +// +// Including run_id in the key means every run writes to a unique cache slot and +// the cache can never be restored from a previous run. The compiler already +// appends run_id automatically to the save key while generating a stable +// restore-keys prefix — users must not add it themselves. +func validateNoCacheKeyRunID(key string) error { + if cacheKeyRunIDPattern.MatchString(key) { + return NewValidationError( + "tools.cache-memory.key", + key, + "cache key must not reference github.run_id — every run would write to a unique cache slot, preventing cross-run cache restoration", + "Remove github.run_id from the key. The compiler appends it automatically to the save key and generates a stable restore-keys prefix.\n\nExample:\n\ntools:\n cache-memory:\n key: my-data-${{ env.GH_AW_WORKFLOW_ID_SANITIZED }}\n # ✓ compiler adds run_id to the save key; restore-keys prefix enables cross-run restoration", + ) + } + return nil +} + // validateNoDuplicateCacheIDs checks for duplicate cache IDs and returns an error if found. // Uses the generic validateNoDuplicateIDs helper for consistent duplicate detection. func validateNoDuplicateCacheIDs(caches []CacheMemoryEntry) error {