From b8741db5aa233c8e32be52426a76cf189f65eee4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 1 May 2026 10:49:44 +0000 Subject: [PATCH 1/5] Initial plan From c84b225109957384ce769dd7b8c62de75ba29257 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 1 May 2026 11:08:48 +0000 Subject: [PATCH 2/5] fix: sanitize repo-memory filenames before artifact upload to prevent NTFS char failures Agent-Logs-Url: https://github.com/github/gh-aw/sessions/3a5dc581-4953-4eaa-a437-d4481a5da2e9 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .../agent-performance-analyzer.lock.yml | 13 +++++++++ .github/workflows/audit-workflows.lock.yml | 13 +++++++++ .../workflows/code-scanning-fixer.lock.yml | 13 +++++++++ .../workflows/copilot-agent-analysis.lock.yml | 13 +++++++++ .../copilot-cli-deep-research.lock.yml | 13 +++++++++ .../copilot-pr-nlp-analysis.lock.yml | 13 +++++++++ .../copilot-pr-prompt-analysis.lock.yml | 13 +++++++++ .../copilot-session-insights.lock.yml | 13 +++++++++ .../workflows/copilot-token-audit.lock.yml | 13 +++++++++ .../copilot-token-optimizer.lock.yml | 13 +++++++++ .../workflows/daily-cli-performance.lock.yml | 13 +++++++++ .github/workflows/daily-code-metrics.lock.yml | 13 +++++++++ .../daily-community-attribution.lock.yml | 13 +++++++++ .github/workflows/daily-news.lock.yml | 13 +++++++++ .../workflows/daily-sentrux-report.lock.yml | 13 +++++++++ .../daily-testify-uber-super-expert.lock.yml | 13 +++++++++ .github/workflows/deep-report.lock.yml | 13 +++++++++ .github/workflows/delight.lock.yml | 13 +++++++++ .../developer-docs-consolidator.lock.yml | 13 +++++++++ .../workflows/discussion-task-miner.lock.yml | 13 +++++++++ .github/workflows/firewall-escape.lock.yml | 13 +++++++++ .../workflows/glossary-maintainer.lock.yml | 13 +++++++++ .github/workflows/metrics-collector.lock.yml | 13 +++++++++ .github/workflows/pr-triage-agent.lock.yml | 13 +++++++++ .../workflows/security-compliance.lock.yml | 13 +++++++++ .github/workflows/smoke-ci.lock.yml | 13 +++++++++ .../workflows/technical-doc-writer.lock.yml | 13 +++++++++ .../weekly-blog-post-writer.lock.yml | 13 +++++++++ .../workflow-health-manager.lock.yml | 13 +++++++++ pkg/workflow/repo_memory.go | 29 ++++++++++++++++--- 30 files changed, 402 insertions(+), 4 deletions(-) diff --git a/.github/workflows/agent-performance-analyzer.lock.yml b/.github/workflows/agent-performance-analyzer.lock.yml index aa559ceb2f2..895b161c9c7 100644 --- a/.github/workflows/agent-performance-analyzer.lock.yml +++ b/.github/workflows/agent-performance-analyzer.lock.yml @@ -1000,6 +1000,19 @@ jobs: echo '{"items":[]}' > /tmp/gh-aw/agent_output.json fi # Upload repo memory as artifacts for push job + - name: Sanitize repo-memory filenames (default) + if: always() + shell: bash + run: | + find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do + dir=$(dirname "$f") + base=$(basename "$f") + safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') + if [ "$base" != "$safe" ]; then + mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" + fi + done + true - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/audit-workflows.lock.yml b/.github/workflows/audit-workflows.lock.yml index 651a68ec917..f065273c865 100644 --- a/.github/workflows/audit-workflows.lock.yml +++ b/.github/workflows/audit-workflows.lock.yml @@ -1111,6 +1111,19 @@ jobs: echo '{"items":[]}' > /tmp/gh-aw/agent_output.json fi # Upload repo memory as artifacts for push job + - name: Sanitize repo-memory filenames (default) + if: always() + shell: bash + run: | + find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do + dir=$(dirname "$f") + base=$(basename "$f") + safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') + if [ "$base" != "$safe" ]; then + mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" + fi + done + true - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/code-scanning-fixer.lock.yml b/.github/workflows/code-scanning-fixer.lock.yml index 4cbe36f4dba..6a4cf0ac9bc 100644 --- a/.github/workflows/code-scanning-fixer.lock.yml +++ b/.github/workflows/code-scanning-fixer.lock.yml @@ -919,6 +919,19 @@ jobs: echo '{"items":[]}' > /tmp/gh-aw/agent_output.json fi # Upload repo memory as artifacts for push job + - name: Sanitize repo-memory filenames (campaigns) + if: always() + shell: bash + run: | + find /tmp/gh-aw/repo-memory/campaigns -depth -type f 2>/dev/null | while IFS= read -r f; do + dir=$(dirname "$f") + base=$(basename "$f") + safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') + if [ "$base" != "$safe" ]; then + mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" + fi + done + true - name: Upload repo-memory artifact (campaigns) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/copilot-agent-analysis.lock.yml b/.github/workflows/copilot-agent-analysis.lock.yml index a859fbcf9a7..337af48fb97 100644 --- a/.github/workflows/copilot-agent-analysis.lock.yml +++ b/.github/workflows/copilot-agent-analysis.lock.yml @@ -1000,6 +1000,19 @@ jobs: echo '{"items":[]}' > /tmp/gh-aw/agent_output.json fi # Upload repo memory as artifacts for push job + - name: Sanitize repo-memory filenames (default) + if: always() + shell: bash + run: | + find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do + dir=$(dirname "$f") + base=$(basename "$f") + safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') + if [ "$base" != "$safe" ]; then + mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" + fi + done + true - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/copilot-cli-deep-research.lock.yml b/.github/workflows/copilot-cli-deep-research.lock.yml index ca937007aba..eeccfe8b5c7 100644 --- a/.github/workflows/copilot-cli-deep-research.lock.yml +++ b/.github/workflows/copilot-cli-deep-research.lock.yml @@ -887,6 +887,19 @@ jobs: echo '{"items":[]}' > /tmp/gh-aw/agent_output.json fi # Upload repo memory as artifacts for push job + - name: Sanitize repo-memory filenames (default) + if: always() + shell: bash + run: | + find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do + dir=$(dirname "$f") + base=$(basename "$f") + safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') + if [ "$base" != "$safe" ]; then + mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" + fi + done + true - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/copilot-pr-nlp-analysis.lock.yml b/.github/workflows/copilot-pr-nlp-analysis.lock.yml index bb0189c1799..00a586ffed4 100644 --- a/.github/workflows/copilot-pr-nlp-analysis.lock.yml +++ b/.github/workflows/copilot-pr-nlp-analysis.lock.yml @@ -989,6 +989,19 @@ jobs: echo '{"items":[]}' > /tmp/gh-aw/agent_output.json fi # Upload repo memory as artifacts for push job + - name: Sanitize repo-memory filenames (default) + if: always() + shell: bash + run: | + find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do + dir=$(dirname "$f") + base=$(basename "$f") + safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') + if [ "$base" != "$safe" ]; then + mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" + fi + done + true - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/copilot-pr-prompt-analysis.lock.yml b/.github/workflows/copilot-pr-prompt-analysis.lock.yml index 0b6638bb56f..8902f0e4eef 100644 --- a/.github/workflows/copilot-pr-prompt-analysis.lock.yml +++ b/.github/workflows/copilot-pr-prompt-analysis.lock.yml @@ -939,6 +939,19 @@ jobs: echo '{"items":[]}' > /tmp/gh-aw/agent_output.json fi # Upload repo memory as artifacts for push job + - name: Sanitize repo-memory filenames (default) + if: always() + shell: bash + run: | + find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do + dir=$(dirname "$f") + base=$(basename "$f") + safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') + if [ "$base" != "$safe" ]; then + mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" + fi + done + true - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/copilot-session-insights.lock.yml b/.github/workflows/copilot-session-insights.lock.yml index e98e184f318..ec481b6a9cb 100644 --- a/.github/workflows/copilot-session-insights.lock.yml +++ b/.github/workflows/copilot-session-insights.lock.yml @@ -1045,6 +1045,19 @@ jobs: echo '{"items":[]}' > /tmp/gh-aw/agent_output.json fi # Upload repo memory as artifacts for push job + - name: Sanitize repo-memory filenames (default) + if: always() + shell: bash + run: | + find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do + dir=$(dirname "$f") + base=$(basename "$f") + safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') + if [ "$base" != "$safe" ]; then + mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" + fi + done + true - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/copilot-token-audit.lock.yml b/.github/workflows/copilot-token-audit.lock.yml index de0cca62c16..944088ad72d 100644 --- a/.github/workflows/copilot-token-audit.lock.yml +++ b/.github/workflows/copilot-token-audit.lock.yml @@ -1059,6 +1059,19 @@ jobs: echo '{"items":[]}' > /tmp/gh-aw/agent_output.json fi # Upload repo memory as artifacts for push job + - name: Sanitize repo-memory filenames (default) + if: always() + shell: bash + run: | + find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do + dir=$(dirname "$f") + base=$(basename "$f") + safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') + if [ "$base" != "$safe" ]; then + mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" + fi + done + true - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/copilot-token-optimizer.lock.yml b/.github/workflows/copilot-token-optimizer.lock.yml index 739480349f7..41fc43d72d7 100644 --- a/.github/workflows/copilot-token-optimizer.lock.yml +++ b/.github/workflows/copilot-token-optimizer.lock.yml @@ -918,6 +918,19 @@ jobs: echo '{"items":[]}' > /tmp/gh-aw/agent_output.json fi # Upload repo memory as artifacts for push job + - name: Sanitize repo-memory filenames (default) + if: always() + shell: bash + run: | + find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do + dir=$(dirname "$f") + base=$(basename "$f") + safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') + if [ "$base" != "$safe" ]; then + mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" + fi + done + true - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/daily-cli-performance.lock.yml b/.github/workflows/daily-cli-performance.lock.yml index e44604d77f6..ef6549b6582 100644 --- a/.github/workflows/daily-cli-performance.lock.yml +++ b/.github/workflows/daily-cli-performance.lock.yml @@ -1135,6 +1135,19 @@ jobs: echo '{"items":[]}' > /tmp/gh-aw/agent_output.json fi # Upload repo memory as artifacts for push job + - name: Sanitize repo-memory filenames (default) + if: always() + shell: bash + run: | + find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do + dir=$(dirname "$f") + base=$(basename "$f") + safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') + if [ "$base" != "$safe" ]; then + mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" + fi + done + true - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/daily-code-metrics.lock.yml b/.github/workflows/daily-code-metrics.lock.yml index e671f52fc25..8d8079e2f53 100644 --- a/.github/workflows/daily-code-metrics.lock.yml +++ b/.github/workflows/daily-code-metrics.lock.yml @@ -1024,6 +1024,19 @@ jobs: echo '{"items":[]}' > /tmp/gh-aw/agent_output.json fi # Upload repo memory as artifacts for push job + - name: Sanitize repo-memory filenames (default) + if: always() + shell: bash + run: | + find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do + dir=$(dirname "$f") + base=$(basename "$f") + safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') + if [ "$base" != "$safe" ]; then + mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" + fi + done + true - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/daily-community-attribution.lock.yml b/.github/workflows/daily-community-attribution.lock.yml index 74dab38eb11..ea5a08fd52f 100644 --- a/.github/workflows/daily-community-attribution.lock.yml +++ b/.github/workflows/daily-community-attribution.lock.yml @@ -999,6 +999,19 @@ jobs: echo '{"items":[]}' > /tmp/gh-aw/agent_output.json fi # Upload repo memory as artifacts for push job + - name: Sanitize wiki-memory filenames (default) + if: always() + shell: bash + run: | + find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do + dir=$(dirname "$f") + base=$(basename "$f") + safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') + if [ "$base" != "$safe" ]; then + mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" + fi + done + true - name: Upload wiki-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/daily-news.lock.yml b/.github/workflows/daily-news.lock.yml index 2a2a57fb32c..ca585e4fb44 100644 --- a/.github/workflows/daily-news.lock.yml +++ b/.github/workflows/daily-news.lock.yml @@ -1071,6 +1071,19 @@ jobs: echo '{"items":[]}' > /tmp/gh-aw/agent_output.json fi # Upload repo memory as artifacts for push job + - name: Sanitize repo-memory filenames (default) + if: always() + shell: bash + run: | + find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do + dir=$(dirname "$f") + base=$(basename "$f") + safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') + if [ "$base" != "$safe" ]; then + mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" + fi + done + true - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/daily-sentrux-report.lock.yml b/.github/workflows/daily-sentrux-report.lock.yml index cf8cfc9826c..41b7cf92646 100644 --- a/.github/workflows/daily-sentrux-report.lock.yml +++ b/.github/workflows/daily-sentrux-report.lock.yml @@ -909,6 +909,19 @@ jobs: echo '{"items":[]}' > /tmp/gh-aw/agent_output.json fi # Upload repo memory as artifacts for push job + - name: Sanitize repo-memory filenames (default) + if: always() + shell: bash + run: | + find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do + dir=$(dirname "$f") + base=$(basename "$f") + safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') + if [ "$base" != "$safe" ]; then + mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" + fi + done + true - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/daily-testify-uber-super-expert.lock.yml b/.github/workflows/daily-testify-uber-super-expert.lock.yml index fd50314f5d0..8664d36e676 100644 --- a/.github/workflows/daily-testify-uber-super-expert.lock.yml +++ b/.github/workflows/daily-testify-uber-super-expert.lock.yml @@ -1004,6 +1004,19 @@ jobs: echo '{"items":[]}' > /tmp/gh-aw/agent_output.json fi # Upload repo memory as artifacts for push job + - name: Sanitize repo-memory filenames (default) + if: always() + shell: bash + run: | + find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do + dir=$(dirname "$f") + base=$(basename "$f") + safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') + if [ "$base" != "$safe" ]; then + mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" + fi + done + true - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/deep-report.lock.yml b/.github/workflows/deep-report.lock.yml index 11ce8672252..3f73775c25b 100644 --- a/.github/workflows/deep-report.lock.yml +++ b/.github/workflows/deep-report.lock.yml @@ -1093,6 +1093,19 @@ jobs: echo '{"items":[]}' > /tmp/gh-aw/agent_output.json fi # Upload repo memory as artifacts for push job + - name: Sanitize repo-memory filenames (default) + if: always() + shell: bash + run: | + find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do + dir=$(dirname "$f") + base=$(basename "$f") + safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') + if [ "$base" != "$safe" ]; then + mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" + fi + done + true - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/delight.lock.yml b/.github/workflows/delight.lock.yml index 3be9ba05dba..cbb32ca73b6 100644 --- a/.github/workflows/delight.lock.yml +++ b/.github/workflows/delight.lock.yml @@ -955,6 +955,19 @@ jobs: echo '{"items":[]}' > /tmp/gh-aw/agent_output.json fi # Upload repo memory as artifacts for push job + - name: Sanitize repo-memory filenames (default) + if: always() + shell: bash + run: | + find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do + dir=$(dirname "$f") + base=$(basename "$f") + safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') + if [ "$base" != "$safe" ]; then + mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" + fi + done + true - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/developer-docs-consolidator.lock.yml b/.github/workflows/developer-docs-consolidator.lock.yml index 6d12003d413..20a58a00bbd 100644 --- a/.github/workflows/developer-docs-consolidator.lock.yml +++ b/.github/workflows/developer-docs-consolidator.lock.yml @@ -1117,6 +1117,19 @@ jobs: echo '{"items":[]}' > /tmp/gh-aw/agent_output.json fi # Upload repo memory as artifacts for push job + - name: Sanitize wiki-memory filenames (default) + if: always() + shell: bash + run: | + find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do + dir=$(dirname "$f") + base=$(basename "$f") + safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') + if [ "$base" != "$safe" ]; then + mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" + fi + done + true - name: Upload wiki-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/discussion-task-miner.lock.yml b/.github/workflows/discussion-task-miner.lock.yml index 5b3ef9dd4be..2f20a2d4e15 100644 --- a/.github/workflows/discussion-task-miner.lock.yml +++ b/.github/workflows/discussion-task-miner.lock.yml @@ -918,6 +918,19 @@ jobs: echo '{"items":[]}' > /tmp/gh-aw/agent_output.json fi # Upload repo memory as artifacts for push job + - name: Sanitize repo-memory filenames (default) + if: always() + shell: bash + run: | + find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do + dir=$(dirname "$f") + base=$(basename "$f") + safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') + if [ "$base" != "$safe" ]; then + mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" + fi + done + true - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/firewall-escape.lock.yml b/.github/workflows/firewall-escape.lock.yml index 89f5de375ec..10734b0d134 100644 --- a/.github/workflows/firewall-escape.lock.yml +++ b/.github/workflows/firewall-escape.lock.yml @@ -906,6 +906,19 @@ jobs: echo '{"items":[]}' > /tmp/gh-aw/agent_output.json fi # Upload repo memory as artifacts for push job + - name: Sanitize repo-memory filenames (default) + if: always() + shell: bash + run: | + find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do + dir=$(dirname "$f") + base=$(basename "$f") + safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') + if [ "$base" != "$safe" ]; then + mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" + fi + done + true - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/glossary-maintainer.lock.yml b/.github/workflows/glossary-maintainer.lock.yml index 73ee5bbf688..11b2a5abd13 100644 --- a/.github/workflows/glossary-maintainer.lock.yml +++ b/.github/workflows/glossary-maintainer.lock.yml @@ -992,6 +992,19 @@ jobs: echo '{"items":[]}' > /tmp/gh-aw/agent_output.json fi # Upload repo memory as artifacts for push job + - name: Sanitize wiki-memory filenames (default) + if: always() + shell: bash + run: | + find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do + dir=$(dirname "$f") + base=$(basename "$f") + safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') + if [ "$base" != "$safe" ]; then + mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" + fi + done + true - name: Upload wiki-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/metrics-collector.lock.yml b/.github/workflows/metrics-collector.lock.yml index bdb7ee35892..691b820cf1d 100644 --- a/.github/workflows/metrics-collector.lock.yml +++ b/.github/workflows/metrics-collector.lock.yml @@ -880,6 +880,19 @@ jobs: echo '{"items":[]}' > /tmp/gh-aw/agent_output.json fi # Upload repo memory as artifacts for push job + - name: Sanitize repo-memory filenames (default) + if: always() + shell: bash + run: | + find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do + dir=$(dirname "$f") + base=$(basename "$f") + safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') + if [ "$base" != "$safe" ]; then + mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" + fi + done + true - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/pr-triage-agent.lock.yml b/.github/workflows/pr-triage-agent.lock.yml index dcd0fac261a..cfef9e4cda6 100644 --- a/.github/workflows/pr-triage-agent.lock.yml +++ b/.github/workflows/pr-triage-agent.lock.yml @@ -999,6 +999,19 @@ jobs: echo '{"items":[]}' > /tmp/gh-aw/agent_output.json fi # Upload repo memory as artifacts for push job + - name: Sanitize repo-memory filenames (default) + if: always() + shell: bash + run: | + find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do + dir=$(dirname "$f") + base=$(basename "$f") + safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') + if [ "$base" != "$safe" ]; then + mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" + fi + done + true - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/security-compliance.lock.yml b/.github/workflows/security-compliance.lock.yml index ab3d7b205c1..f07008f137c 100644 --- a/.github/workflows/security-compliance.lock.yml +++ b/.github/workflows/security-compliance.lock.yml @@ -885,6 +885,19 @@ jobs: echo '{"items":[]}' > /tmp/gh-aw/agent_output.json fi # Upload repo memory as artifacts for push job + - name: Sanitize repo-memory filenames (default) + if: always() + shell: bash + run: | + find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do + dir=$(dirname "$f") + base=$(basename "$f") + safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') + if [ "$base" != "$safe" ]; then + mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" + fi + done + true - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/smoke-ci.lock.yml b/.github/workflows/smoke-ci.lock.yml index ea278a05528..3b4cc47f80e 100644 --- a/.github/workflows/smoke-ci.lock.yml +++ b/.github/workflows/smoke-ci.lock.yml @@ -1117,6 +1117,19 @@ jobs: echo '{"items":[]}' > /tmp/gh-aw/agent_output.json fi # Upload repo memory as artifacts for push job + - name: Sanitize repo-memory filenames (default) + if: always() + shell: bash + run: | + find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do + dir=$(dirname "$f") + base=$(basename "$f") + safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') + if [ "$base" != "$safe" ]; then + mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" + fi + done + true - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/technical-doc-writer.lock.yml b/.github/workflows/technical-doc-writer.lock.yml index e07a6e1c579..4fa0af9aa61 100644 --- a/.github/workflows/technical-doc-writer.lock.yml +++ b/.github/workflows/technical-doc-writer.lock.yml @@ -964,6 +964,19 @@ jobs: echo '{"items":[]}' > /tmp/gh-aw/agent_output.json fi # Upload repo memory as artifacts for push job + - name: Sanitize wiki-memory filenames (default) + if: always() + shell: bash + run: | + find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do + dir=$(dirname "$f") + base=$(basename "$f") + safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') + if [ "$base" != "$safe" ]; then + mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" + fi + done + true - name: Upload wiki-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/weekly-blog-post-writer.lock.yml b/.github/workflows/weekly-blog-post-writer.lock.yml index 46ab43eb0e1..e577d81eb24 100644 --- a/.github/workflows/weekly-blog-post-writer.lock.yml +++ b/.github/workflows/weekly-blog-post-writer.lock.yml @@ -968,6 +968,19 @@ jobs: echo '{"items":[]}' > /tmp/gh-aw/agent_output.json fi # Upload repo memory as artifacts for push job + - name: Sanitize wiki-memory filenames (default) + if: always() + shell: bash + run: | + find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do + dir=$(dirname "$f") + base=$(basename "$f") + safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') + if [ "$base" != "$safe" ]; then + mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" + fi + done + true - name: Upload wiki-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/workflow-health-manager.lock.yml b/.github/workflows/workflow-health-manager.lock.yml index eed9d5e8a99..6aa2c5f9f8b 100644 --- a/.github/workflows/workflow-health-manager.lock.yml +++ b/.github/workflows/workflow-health-manager.lock.yml @@ -959,6 +959,19 @@ jobs: echo '{"items":[]}' > /tmp/gh-aw/agent_output.json fi # Upload repo memory as artifacts for push job + - name: Sanitize repo-memory filenames (default) + if: always() + shell: bash + run: | + find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do + dir=$(dirname "$f") + base=$(basename "$f") + safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') + if [ "$base" != "$safe" ]; then + mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" + fi + done + true - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/pkg/workflow/repo_memory.go b/pkg/workflow/repo_memory.go index c6bf99ed0ff..18b8b7456da 100644 --- a/pkg/workflow/repo_memory.go +++ b/pkg/workflow/repo_memory.go @@ -491,12 +491,33 @@ func generateRepoMemoryArtifactUpload(builder *strings.Builder, data *WorkflowDa // Sanitize memory ID for artifact naming (remove hyphens, lowercase) sanitizedID := SanitizeWorkflowIDForCacheKey(memory.ID) - // Step: Upload repo-memory directory as artifact + // Determine the label for step names + memoryLabel := "repo-memory" if memory.Wiki { - fmt.Fprintf(builder, " - name: Upload wiki-memory artifact (%s)\n", memory.ID) - } else { - fmt.Fprintf(builder, " - name: Upload repo-memory artifact (%s)\n", memory.ID) + memoryLabel = "wiki-memory" } + + // Step: Sanitize filenames before upload to prevent artifact upload failures. + // GitHub Actions artifacts are stored on NTFS-compatible filesystems, so filenames + // must not contain: ? : * | < > " (among other characters). + // The agent may create files with these characters (e.g. "Can-we-have-a-PR?.md"), + // which causes the upload-artifact action to fail with a hard error. + fmt.Fprintf(builder, " - name: Sanitize %s filenames (%s)\n", memoryLabel, memory.ID) + builder.WriteString(" if: always()\n") + builder.WriteString(" shell: bash\n") + builder.WriteString(" run: |\n") + fmt.Fprintf(builder, " find %s -depth -type f 2>/dev/null | while IFS= read -r f; do\n", memoryDir) + builder.WriteString(" dir=$(dirname \"$f\")\n") + builder.WriteString(" base=$(basename \"$f\")\n") + builder.WriteString(" safe=$(printf '%s' \"$base\" | sed 's/[?:*|<>\"]/-/g')\n") + builder.WriteString(" if [ \"$base\" != \"$safe\" ]; then\n") + builder.WriteString(" mv -- \"$f\" \"$dir/$safe\" && echo \"Renamed: $base -> $safe\"\n") + builder.WriteString(" fi\n") + builder.WriteString(" done\n") + builder.WriteString(" true\n") + + // Step: Upload repo-memory directory as artifact + fmt.Fprintf(builder, " - name: Upload %s artifact (%s)\n", memoryLabel, memory.ID) builder.WriteString(" if: always()\n") fmt.Fprintf(builder, " uses: %s\n", getActionPin("actions/upload-artifact")) builder.WriteString(" with:\n") From b6e006eb347305123e2fd09c7acbd5985c9f478b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 1 May 2026 11:13:44 +0000 Subject: [PATCH 3/5] fix: add clarifying comment for true sentinel in sanitize step Agent-Logs-Url: https://github.com/github/gh-aw/sessions/3a5dc581-4953-4eaa-a437-d4481a5da2e9 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- pkg/workflow/repo_memory.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkg/workflow/repo_memory.go b/pkg/workflow/repo_memory.go index 18b8b7456da..0f70fb5f3b7 100644 --- a/pkg/workflow/repo_memory.go +++ b/pkg/workflow/repo_memory.go @@ -514,6 +514,10 @@ func generateRepoMemoryArtifactUpload(builder *strings.Builder, data *WorkflowDa builder.WriteString(" mv -- \"$f\" \"$dir/$safe\" && echo \"Renamed: $base -> $safe\"\n") builder.WriteString(" fi\n") builder.WriteString(" done\n") + // Ensure the step always exits 0: the while loop exits cleanly when + // find produces no output, but the `true` guards against edge cases + // (e.g. find returning non-zero for a missing directory) that could + // fail the step and block artifact upload. builder.WriteString(" true\n") // Step: Upload repo-memory directory as artifact From 57c4de8717b42b881b308f251303877d3ad8cd5b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 1 May 2026 11:28:01 +0000 Subject: [PATCH 4/5] refactor: move filename sanitization to sanitize_repo_memory_filenames.sh using git commands Agent-Logs-Url: https://github.com/github/gh-aw/sessions/9aa6d1b9-1ab1-40c6-9621-41ec2a0e2827 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .../agent-performance-analyzer.lock.yml | 14 +--- .github/workflows/audit-workflows.lock.yml | 14 +--- .../workflows/code-scanning-fixer.lock.yml | 14 +--- .../workflows/copilot-agent-analysis.lock.yml | 14 +--- .../copilot-cli-deep-research.lock.yml | 14 +--- .../copilot-pr-nlp-analysis.lock.yml | 14 +--- .../copilot-pr-prompt-analysis.lock.yml | 14 +--- .../copilot-session-insights.lock.yml | 14 +--- .../workflows/copilot-token-audit.lock.yml | 14 +--- .../copilot-token-optimizer.lock.yml | 14 +--- .../workflows/daily-cli-performance.lock.yml | 14 +--- .github/workflows/daily-code-metrics.lock.yml | 14 +--- .../daily-community-attribution.lock.yml | 14 +--- .github/workflows/daily-news.lock.yml | 14 +--- .../workflows/daily-sentrux-report.lock.yml | 14 +--- .../daily-testify-uber-super-expert.lock.yml | 14 +--- .github/workflows/deep-report.lock.yml | 14 +--- .github/workflows/delight.lock.yml | 14 +--- .../developer-docs-consolidator.lock.yml | 14 +--- .../workflows/discussion-task-miner.lock.yml | 14 +--- .github/workflows/firewall-escape.lock.yml | 14 +--- .../workflows/glossary-maintainer.lock.yml | 14 +--- .github/workflows/metrics-collector.lock.yml | 14 +--- .github/workflows/pr-triage-agent.lock.yml | 14 +--- .../workflows/security-compliance.lock.yml | 14 +--- .github/workflows/smoke-ci.lock.yml | 14 +--- .../workflows/technical-doc-writer.lock.yml | 14 +--- .../weekly-blog-post-writer.lock.yml | 14 +--- .../workflow-health-manager.lock.yml | 14 +--- .../sh/sanitize_repo_memory_filenames.sh | 66 +++++++++++++++++++ pkg/workflow/repo_memory.go | 20 ++---- 31 files changed, 158 insertions(+), 334 deletions(-) create mode 100644 actions/setup/sh/sanitize_repo_memory_filenames.sh diff --git a/.github/workflows/agent-performance-analyzer.lock.yml b/.github/workflows/agent-performance-analyzer.lock.yml index 895b161c9c7..73f7ea8c2ab 100644 --- a/.github/workflows/agent-performance-analyzer.lock.yml +++ b/.github/workflows/agent-performance-analyzer.lock.yml @@ -1002,17 +1002,9 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() - shell: bash - run: | - find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do - dir=$(dirname "$f") - base=$(basename "$f") - safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') - if [ "$base" != "$safe" ]; then - mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" - fi - done - true + env: + MEMORY_DIR: /tmp/gh-aw/repo-memory/default + run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/audit-workflows.lock.yml b/.github/workflows/audit-workflows.lock.yml index f065273c865..a7d0560df81 100644 --- a/.github/workflows/audit-workflows.lock.yml +++ b/.github/workflows/audit-workflows.lock.yml @@ -1113,17 +1113,9 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() - shell: bash - run: | - find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do - dir=$(dirname "$f") - base=$(basename "$f") - safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') - if [ "$base" != "$safe" ]; then - mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" - fi - done - true + env: + MEMORY_DIR: /tmp/gh-aw/repo-memory/default + run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/code-scanning-fixer.lock.yml b/.github/workflows/code-scanning-fixer.lock.yml index 6a4cf0ac9bc..7b0e859002c 100644 --- a/.github/workflows/code-scanning-fixer.lock.yml +++ b/.github/workflows/code-scanning-fixer.lock.yml @@ -921,17 +921,9 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (campaigns) if: always() - shell: bash - run: | - find /tmp/gh-aw/repo-memory/campaigns -depth -type f 2>/dev/null | while IFS= read -r f; do - dir=$(dirname "$f") - base=$(basename "$f") - safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') - if [ "$base" != "$safe" ]; then - mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" - fi - done - true + env: + MEMORY_DIR: /tmp/gh-aw/repo-memory/campaigns + run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" - name: Upload repo-memory artifact (campaigns) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/copilot-agent-analysis.lock.yml b/.github/workflows/copilot-agent-analysis.lock.yml index 337af48fb97..44674cb2d44 100644 --- a/.github/workflows/copilot-agent-analysis.lock.yml +++ b/.github/workflows/copilot-agent-analysis.lock.yml @@ -1002,17 +1002,9 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() - shell: bash - run: | - find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do - dir=$(dirname "$f") - base=$(basename "$f") - safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') - if [ "$base" != "$safe" ]; then - mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" - fi - done - true + env: + MEMORY_DIR: /tmp/gh-aw/repo-memory/default + run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/copilot-cli-deep-research.lock.yml b/.github/workflows/copilot-cli-deep-research.lock.yml index eeccfe8b5c7..bfecdc4e3ff 100644 --- a/.github/workflows/copilot-cli-deep-research.lock.yml +++ b/.github/workflows/copilot-cli-deep-research.lock.yml @@ -889,17 +889,9 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() - shell: bash - run: | - find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do - dir=$(dirname "$f") - base=$(basename "$f") - safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') - if [ "$base" != "$safe" ]; then - mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" - fi - done - true + env: + MEMORY_DIR: /tmp/gh-aw/repo-memory/default + run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/copilot-pr-nlp-analysis.lock.yml b/.github/workflows/copilot-pr-nlp-analysis.lock.yml index 00a586ffed4..2e45f30df1b 100644 --- a/.github/workflows/copilot-pr-nlp-analysis.lock.yml +++ b/.github/workflows/copilot-pr-nlp-analysis.lock.yml @@ -991,17 +991,9 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() - shell: bash - run: | - find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do - dir=$(dirname "$f") - base=$(basename "$f") - safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') - if [ "$base" != "$safe" ]; then - mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" - fi - done - true + env: + MEMORY_DIR: /tmp/gh-aw/repo-memory/default + run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/copilot-pr-prompt-analysis.lock.yml b/.github/workflows/copilot-pr-prompt-analysis.lock.yml index 8902f0e4eef..d4d498c7604 100644 --- a/.github/workflows/copilot-pr-prompt-analysis.lock.yml +++ b/.github/workflows/copilot-pr-prompt-analysis.lock.yml @@ -941,17 +941,9 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() - shell: bash - run: | - find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do - dir=$(dirname "$f") - base=$(basename "$f") - safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') - if [ "$base" != "$safe" ]; then - mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" - fi - done - true + env: + MEMORY_DIR: /tmp/gh-aw/repo-memory/default + run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/copilot-session-insights.lock.yml b/.github/workflows/copilot-session-insights.lock.yml index ec481b6a9cb..39dc5e3a43d 100644 --- a/.github/workflows/copilot-session-insights.lock.yml +++ b/.github/workflows/copilot-session-insights.lock.yml @@ -1047,17 +1047,9 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() - shell: bash - run: | - find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do - dir=$(dirname "$f") - base=$(basename "$f") - safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') - if [ "$base" != "$safe" ]; then - mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" - fi - done - true + env: + MEMORY_DIR: /tmp/gh-aw/repo-memory/default + run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/copilot-token-audit.lock.yml b/.github/workflows/copilot-token-audit.lock.yml index 944088ad72d..b34e66fbf4f 100644 --- a/.github/workflows/copilot-token-audit.lock.yml +++ b/.github/workflows/copilot-token-audit.lock.yml @@ -1061,17 +1061,9 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() - shell: bash - run: | - find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do - dir=$(dirname "$f") - base=$(basename "$f") - safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') - if [ "$base" != "$safe" ]; then - mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" - fi - done - true + env: + MEMORY_DIR: /tmp/gh-aw/repo-memory/default + run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/copilot-token-optimizer.lock.yml b/.github/workflows/copilot-token-optimizer.lock.yml index 41fc43d72d7..4fca95ef69c 100644 --- a/.github/workflows/copilot-token-optimizer.lock.yml +++ b/.github/workflows/copilot-token-optimizer.lock.yml @@ -920,17 +920,9 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() - shell: bash - run: | - find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do - dir=$(dirname "$f") - base=$(basename "$f") - safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') - if [ "$base" != "$safe" ]; then - mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" - fi - done - true + env: + MEMORY_DIR: /tmp/gh-aw/repo-memory/default + run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/daily-cli-performance.lock.yml b/.github/workflows/daily-cli-performance.lock.yml index ef6549b6582..3c06382669b 100644 --- a/.github/workflows/daily-cli-performance.lock.yml +++ b/.github/workflows/daily-cli-performance.lock.yml @@ -1137,17 +1137,9 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() - shell: bash - run: | - find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do - dir=$(dirname "$f") - base=$(basename "$f") - safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') - if [ "$base" != "$safe" ]; then - mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" - fi - done - true + env: + MEMORY_DIR: /tmp/gh-aw/repo-memory/default + run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/daily-code-metrics.lock.yml b/.github/workflows/daily-code-metrics.lock.yml index 8d8079e2f53..6f53e8fba70 100644 --- a/.github/workflows/daily-code-metrics.lock.yml +++ b/.github/workflows/daily-code-metrics.lock.yml @@ -1026,17 +1026,9 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() - shell: bash - run: | - find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do - dir=$(dirname "$f") - base=$(basename "$f") - safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') - if [ "$base" != "$safe" ]; then - mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" - fi - done - true + env: + MEMORY_DIR: /tmp/gh-aw/repo-memory/default + run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/daily-community-attribution.lock.yml b/.github/workflows/daily-community-attribution.lock.yml index ea5a08fd52f..c7250f8bb9f 100644 --- a/.github/workflows/daily-community-attribution.lock.yml +++ b/.github/workflows/daily-community-attribution.lock.yml @@ -1001,17 +1001,9 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize wiki-memory filenames (default) if: always() - shell: bash - run: | - find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do - dir=$(dirname "$f") - base=$(basename "$f") - safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') - if [ "$base" != "$safe" ]; then - mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" - fi - done - true + env: + MEMORY_DIR: /tmp/gh-aw/repo-memory/default + run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" - name: Upload wiki-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/daily-news.lock.yml b/.github/workflows/daily-news.lock.yml index ca585e4fb44..3228fb8587a 100644 --- a/.github/workflows/daily-news.lock.yml +++ b/.github/workflows/daily-news.lock.yml @@ -1073,17 +1073,9 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() - shell: bash - run: | - find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do - dir=$(dirname "$f") - base=$(basename "$f") - safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') - if [ "$base" != "$safe" ]; then - mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" - fi - done - true + env: + MEMORY_DIR: /tmp/gh-aw/repo-memory/default + run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/daily-sentrux-report.lock.yml b/.github/workflows/daily-sentrux-report.lock.yml index 41b7cf92646..61b9bd938e2 100644 --- a/.github/workflows/daily-sentrux-report.lock.yml +++ b/.github/workflows/daily-sentrux-report.lock.yml @@ -911,17 +911,9 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() - shell: bash - run: | - find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do - dir=$(dirname "$f") - base=$(basename "$f") - safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') - if [ "$base" != "$safe" ]; then - mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" - fi - done - true + env: + MEMORY_DIR: /tmp/gh-aw/repo-memory/default + run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/daily-testify-uber-super-expert.lock.yml b/.github/workflows/daily-testify-uber-super-expert.lock.yml index 8664d36e676..16e88064c97 100644 --- a/.github/workflows/daily-testify-uber-super-expert.lock.yml +++ b/.github/workflows/daily-testify-uber-super-expert.lock.yml @@ -1006,17 +1006,9 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() - shell: bash - run: | - find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do - dir=$(dirname "$f") - base=$(basename "$f") - safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') - if [ "$base" != "$safe" ]; then - mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" - fi - done - true + env: + MEMORY_DIR: /tmp/gh-aw/repo-memory/default + run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/deep-report.lock.yml b/.github/workflows/deep-report.lock.yml index 3f73775c25b..14ae0d2239f 100644 --- a/.github/workflows/deep-report.lock.yml +++ b/.github/workflows/deep-report.lock.yml @@ -1095,17 +1095,9 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() - shell: bash - run: | - find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do - dir=$(dirname "$f") - base=$(basename "$f") - safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') - if [ "$base" != "$safe" ]; then - mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" - fi - done - true + env: + MEMORY_DIR: /tmp/gh-aw/repo-memory/default + run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/delight.lock.yml b/.github/workflows/delight.lock.yml index cbb32ca73b6..71c1fcd61ac 100644 --- a/.github/workflows/delight.lock.yml +++ b/.github/workflows/delight.lock.yml @@ -957,17 +957,9 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() - shell: bash - run: | - find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do - dir=$(dirname "$f") - base=$(basename "$f") - safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') - if [ "$base" != "$safe" ]; then - mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" - fi - done - true + env: + MEMORY_DIR: /tmp/gh-aw/repo-memory/default + run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/developer-docs-consolidator.lock.yml b/.github/workflows/developer-docs-consolidator.lock.yml index 20a58a00bbd..384c250f493 100644 --- a/.github/workflows/developer-docs-consolidator.lock.yml +++ b/.github/workflows/developer-docs-consolidator.lock.yml @@ -1119,17 +1119,9 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize wiki-memory filenames (default) if: always() - shell: bash - run: | - find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do - dir=$(dirname "$f") - base=$(basename "$f") - safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') - if [ "$base" != "$safe" ]; then - mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" - fi - done - true + env: + MEMORY_DIR: /tmp/gh-aw/repo-memory/default + run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" - name: Upload wiki-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/discussion-task-miner.lock.yml b/.github/workflows/discussion-task-miner.lock.yml index 2f20a2d4e15..857ae58de92 100644 --- a/.github/workflows/discussion-task-miner.lock.yml +++ b/.github/workflows/discussion-task-miner.lock.yml @@ -920,17 +920,9 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() - shell: bash - run: | - find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do - dir=$(dirname "$f") - base=$(basename "$f") - safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') - if [ "$base" != "$safe" ]; then - mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" - fi - done - true + env: + MEMORY_DIR: /tmp/gh-aw/repo-memory/default + run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/firewall-escape.lock.yml b/.github/workflows/firewall-escape.lock.yml index 10734b0d134..955422f39df 100644 --- a/.github/workflows/firewall-escape.lock.yml +++ b/.github/workflows/firewall-escape.lock.yml @@ -908,17 +908,9 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() - shell: bash - run: | - find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do - dir=$(dirname "$f") - base=$(basename "$f") - safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') - if [ "$base" != "$safe" ]; then - mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" - fi - done - true + env: + MEMORY_DIR: /tmp/gh-aw/repo-memory/default + run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/glossary-maintainer.lock.yml b/.github/workflows/glossary-maintainer.lock.yml index 11b2a5abd13..c03dc724f0f 100644 --- a/.github/workflows/glossary-maintainer.lock.yml +++ b/.github/workflows/glossary-maintainer.lock.yml @@ -994,17 +994,9 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize wiki-memory filenames (default) if: always() - shell: bash - run: | - find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do - dir=$(dirname "$f") - base=$(basename "$f") - safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') - if [ "$base" != "$safe" ]; then - mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" - fi - done - true + env: + MEMORY_DIR: /tmp/gh-aw/repo-memory/default + run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" - name: Upload wiki-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/metrics-collector.lock.yml b/.github/workflows/metrics-collector.lock.yml index 691b820cf1d..340150da26f 100644 --- a/.github/workflows/metrics-collector.lock.yml +++ b/.github/workflows/metrics-collector.lock.yml @@ -882,17 +882,9 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() - shell: bash - run: | - find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do - dir=$(dirname "$f") - base=$(basename "$f") - safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') - if [ "$base" != "$safe" ]; then - mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" - fi - done - true + env: + MEMORY_DIR: /tmp/gh-aw/repo-memory/default + run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/pr-triage-agent.lock.yml b/.github/workflows/pr-triage-agent.lock.yml index cfef9e4cda6..18069b074f5 100644 --- a/.github/workflows/pr-triage-agent.lock.yml +++ b/.github/workflows/pr-triage-agent.lock.yml @@ -1001,17 +1001,9 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() - shell: bash - run: | - find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do - dir=$(dirname "$f") - base=$(basename "$f") - safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') - if [ "$base" != "$safe" ]; then - mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" - fi - done - true + env: + MEMORY_DIR: /tmp/gh-aw/repo-memory/default + run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/security-compliance.lock.yml b/.github/workflows/security-compliance.lock.yml index f07008f137c..f2be9036442 100644 --- a/.github/workflows/security-compliance.lock.yml +++ b/.github/workflows/security-compliance.lock.yml @@ -887,17 +887,9 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() - shell: bash - run: | - find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do - dir=$(dirname "$f") - base=$(basename "$f") - safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') - if [ "$base" != "$safe" ]; then - mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" - fi - done - true + env: + MEMORY_DIR: /tmp/gh-aw/repo-memory/default + run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/smoke-ci.lock.yml b/.github/workflows/smoke-ci.lock.yml index 3b4cc47f80e..27f123ac897 100644 --- a/.github/workflows/smoke-ci.lock.yml +++ b/.github/workflows/smoke-ci.lock.yml @@ -1119,17 +1119,9 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() - shell: bash - run: | - find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do - dir=$(dirname "$f") - base=$(basename "$f") - safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') - if [ "$base" != "$safe" ]; then - mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" - fi - done - true + env: + MEMORY_DIR: /tmp/gh-aw/repo-memory/default + run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/technical-doc-writer.lock.yml b/.github/workflows/technical-doc-writer.lock.yml index 4fa0af9aa61..3ecfe7ef12f 100644 --- a/.github/workflows/technical-doc-writer.lock.yml +++ b/.github/workflows/technical-doc-writer.lock.yml @@ -966,17 +966,9 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize wiki-memory filenames (default) if: always() - shell: bash - run: | - find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do - dir=$(dirname "$f") - base=$(basename "$f") - safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') - if [ "$base" != "$safe" ]; then - mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" - fi - done - true + env: + MEMORY_DIR: /tmp/gh-aw/repo-memory/default + run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" - name: Upload wiki-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/weekly-blog-post-writer.lock.yml b/.github/workflows/weekly-blog-post-writer.lock.yml index e577d81eb24..b418c678145 100644 --- a/.github/workflows/weekly-blog-post-writer.lock.yml +++ b/.github/workflows/weekly-blog-post-writer.lock.yml @@ -970,17 +970,9 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize wiki-memory filenames (default) if: always() - shell: bash - run: | - find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do - dir=$(dirname "$f") - base=$(basename "$f") - safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') - if [ "$base" != "$safe" ]; then - mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" - fi - done - true + env: + MEMORY_DIR: /tmp/gh-aw/repo-memory/default + run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" - name: Upload wiki-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/workflow-health-manager.lock.yml b/.github/workflows/workflow-health-manager.lock.yml index 6aa2c5f9f8b..ddc66f8de6c 100644 --- a/.github/workflows/workflow-health-manager.lock.yml +++ b/.github/workflows/workflow-health-manager.lock.yml @@ -961,17 +961,9 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() - shell: bash - run: | - find /tmp/gh-aw/repo-memory/default -depth -type f 2>/dev/null | while IFS= read -r f; do - dir=$(dirname "$f") - base=$(basename "$f") - safe=$(printf '%s' "$base" | sed 's/[?:*|<>"]/-/g') - if [ "$base" != "$safe" ]; then - mv -- "$f" "$dir/$safe" && echo "Renamed: $base -> $safe" - fi - done - true + env: + MEMORY_DIR: /tmp/gh-aw/repo-memory/default + run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" - name: Upload repo-memory artifact (default) if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/actions/setup/sh/sanitize_repo_memory_filenames.sh b/actions/setup/sh/sanitize_repo_memory_filenames.sh new file mode 100644 index 00000000000..4253a0c0842 --- /dev/null +++ b/actions/setup/sh/sanitize_repo_memory_filenames.sh @@ -0,0 +1,66 @@ +#!/usr/bin/env bash +set -euo pipefail + +# sanitize_repo_memory_filenames.sh +# Renames files in the repo-memory git working tree whose names contain +# characters forbidden by GitHub Actions artifact upload (NTFS: ? : * | < > "). +# Tracked files are renamed with `git mv` so the rename is reflected in git +# history. New (untracked) files written by the agent are renamed with `mv`. +# +# Required environment variables: +# MEMORY_DIR: Path to the repo-memory git working tree + +MEMORY_DIR="${MEMORY_DIR:?MEMORY_DIR is required}" + +if [ ! -d "$MEMORY_DIR" ]; then + echo "Memory directory not found: $MEMORY_DIR — skipping sanitization" + exit 0 +fi + +cd "$MEMORY_DIR" + +if [ ! -d ".git" ]; then + echo "Not a git repository: $MEMORY_DIR — skipping sanitization" + exit 0 +fi + +# sanitize_name: replace NTFS-forbidden characters in a filename with hyphen +sanitize_name() { + printf '%s' "$1" | sed 's/[?:*|<>"]/-/g' +} + +# Rename tracked files (in git index) that contain forbidden characters. +# git mv handles both the working-tree rename and the index update atomically. +while IFS= read -r -d '' filepath; do + base=$(basename "$filepath") + safe=$(sanitize_name "$base") + if [ "$base" != "$safe" ]; then + dir=$(dirname "$filepath") + if [ "$dir" = "." ]; then + newpath="$safe" + else + newpath="$dir/$safe" + fi + git mv -- "$filepath" "$newpath" + echo "Renamed tracked: $filepath -> $newpath" + fi +done < <(git ls-files --cached -z 2>/dev/null) + +# Rename untracked (new) files written by the agent that contain forbidden characters. +# These are not yet in the git index so plain mv is used. +while IFS= read -r -d '' filepath; do + base=$(basename "$filepath") + safe=$(sanitize_name "$base") + if [ "$base" != "$safe" ]; then + dir=$(dirname "$filepath") + if [ "$dir" = "." ]; then + newpath="$safe" + else + newpath="$dir/$safe" + fi + mv -- "$filepath" "$newpath" + echo "Renamed untracked: $filepath -> $newpath" + fi +done < <(git ls-files --others -z 2>/dev/null) + +echo "Sanitization complete" diff --git a/pkg/workflow/repo_memory.go b/pkg/workflow/repo_memory.go index 0f70fb5f3b7..75e1fdf306a 100644 --- a/pkg/workflow/repo_memory.go +++ b/pkg/workflow/repo_memory.go @@ -502,23 +502,13 @@ func generateRepoMemoryArtifactUpload(builder *strings.Builder, data *WorkflowDa // must not contain: ? : * | < > " (among other characters). // The agent may create files with these characters (e.g. "Can-we-have-a-PR?.md"), // which causes the upload-artifact action to fail with a hard error. + // The script uses git commands (git mv for tracked files, mv for untracked) since + // repo-memory is backed by a git working tree. fmt.Fprintf(builder, " - name: Sanitize %s filenames (%s)\n", memoryLabel, memory.ID) builder.WriteString(" if: always()\n") - builder.WriteString(" shell: bash\n") - builder.WriteString(" run: |\n") - fmt.Fprintf(builder, " find %s -depth -type f 2>/dev/null | while IFS= read -r f; do\n", memoryDir) - builder.WriteString(" dir=$(dirname \"$f\")\n") - builder.WriteString(" base=$(basename \"$f\")\n") - builder.WriteString(" safe=$(printf '%s' \"$base\" | sed 's/[?:*|<>\"]/-/g')\n") - builder.WriteString(" if [ \"$base\" != \"$safe\" ]; then\n") - builder.WriteString(" mv -- \"$f\" \"$dir/$safe\" && echo \"Renamed: $base -> $safe\"\n") - builder.WriteString(" fi\n") - builder.WriteString(" done\n") - // Ensure the step always exits 0: the while loop exits cleanly when - // find produces no output, but the `true` guards against edge cases - // (e.g. find returning non-zero for a missing directory) that could - // fail the step and block artifact upload. - builder.WriteString(" true\n") + builder.WriteString(" env:\n") + fmt.Fprintf(builder, " MEMORY_DIR: %s\n", memoryDir) + builder.WriteString(" run: bash \"${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh\"\n") // Step: Upload repo-memory directory as artifact fmt.Fprintf(builder, " - name: Upload %s artifact (%s)\n", memoryLabel, memory.ID) From 33ff510fe76654c5fb8244c39555928132546df6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 1 May 2026 14:53:39 +0000 Subject: [PATCH 5/5] fix: address reviewer feedback on sanitize_repo_memory_filenames.sh and tests Agent-Logs-Url: https://github.com/github/gh-aw/sessions/a6f0672f-efe2-4ca4-a223-74e6af700fa7 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .../agent-performance-analyzer.lock.yml | 1 + .github/workflows/audit-workflows.lock.yml | 1 + .../workflows/code-scanning-fixer.lock.yml | 1 + .../workflows/copilot-agent-analysis.lock.yml | 1 + .../copilot-cli-deep-research.lock.yml | 1 + .../copilot-pr-nlp-analysis.lock.yml | 1 + .../copilot-pr-prompt-analysis.lock.yml | 1 + .../copilot-session-insights.lock.yml | 1 + .../workflows/copilot-token-audit.lock.yml | 1 + .../copilot-token-optimizer.lock.yml | 1 + .../workflows/daily-cli-performance.lock.yml | 1 + .github/workflows/daily-code-metrics.lock.yml | 1 + .../daily-community-attribution.lock.yml | 1 + .github/workflows/daily-news.lock.yml | 1 + .../workflows/daily-sentrux-report.lock.yml | 1 + .../daily-testify-uber-super-expert.lock.yml | 1 + .github/workflows/deep-report.lock.yml | 1 + .github/workflows/delight.lock.yml | 1 + .../developer-docs-consolidator.lock.yml | 1 + .../workflows/discussion-task-miner.lock.yml | 1 + .github/workflows/firewall-escape.lock.yml | 1 + .../workflows/glossary-maintainer.lock.yml | 1 + .github/workflows/metrics-collector.lock.yml | 1 + .github/workflows/pr-triage-agent.lock.yml | 1 + .../workflows/security-compliance.lock.yml | 1 + .github/workflows/smoke-ci.lock.yml | 1 + .../workflows/technical-doc-writer.lock.yml | 1 + .../weekly-blog-post-writer.lock.yml | 1 + .../workflow-health-manager.lock.yml | 1 + .../sh/sanitize_repo_memory_filenames.sh | 134 +++++++++++++----- pkg/workflow/repo_memory.go | 1 + pkg/workflow/repo_memory_test.go | 76 ++++++++++ 32 files changed, 202 insertions(+), 38 deletions(-) diff --git a/.github/workflows/agent-performance-analyzer.lock.yml b/.github/workflows/agent-performance-analyzer.lock.yml index 73f7ea8c2ab..843f8cd86f4 100644 --- a/.github/workflows/agent-performance-analyzer.lock.yml +++ b/.github/workflows/agent-performance-analyzer.lock.yml @@ -1002,6 +1002,7 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() + continue-on-error: true env: MEMORY_DIR: /tmp/gh-aw/repo-memory/default run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" diff --git a/.github/workflows/audit-workflows.lock.yml b/.github/workflows/audit-workflows.lock.yml index a7d0560df81..354133042c9 100644 --- a/.github/workflows/audit-workflows.lock.yml +++ b/.github/workflows/audit-workflows.lock.yml @@ -1113,6 +1113,7 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() + continue-on-error: true env: MEMORY_DIR: /tmp/gh-aw/repo-memory/default run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" diff --git a/.github/workflows/code-scanning-fixer.lock.yml b/.github/workflows/code-scanning-fixer.lock.yml index 7b0e859002c..4dcc24e2195 100644 --- a/.github/workflows/code-scanning-fixer.lock.yml +++ b/.github/workflows/code-scanning-fixer.lock.yml @@ -921,6 +921,7 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (campaigns) if: always() + continue-on-error: true env: MEMORY_DIR: /tmp/gh-aw/repo-memory/campaigns run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" diff --git a/.github/workflows/copilot-agent-analysis.lock.yml b/.github/workflows/copilot-agent-analysis.lock.yml index 44674cb2d44..c52e14453c7 100644 --- a/.github/workflows/copilot-agent-analysis.lock.yml +++ b/.github/workflows/copilot-agent-analysis.lock.yml @@ -1002,6 +1002,7 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() + continue-on-error: true env: MEMORY_DIR: /tmp/gh-aw/repo-memory/default run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" diff --git a/.github/workflows/copilot-cli-deep-research.lock.yml b/.github/workflows/copilot-cli-deep-research.lock.yml index bfecdc4e3ff..202df0b8fc7 100644 --- a/.github/workflows/copilot-cli-deep-research.lock.yml +++ b/.github/workflows/copilot-cli-deep-research.lock.yml @@ -889,6 +889,7 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() + continue-on-error: true env: MEMORY_DIR: /tmp/gh-aw/repo-memory/default run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" diff --git a/.github/workflows/copilot-pr-nlp-analysis.lock.yml b/.github/workflows/copilot-pr-nlp-analysis.lock.yml index 2e45f30df1b..18d3522dacb 100644 --- a/.github/workflows/copilot-pr-nlp-analysis.lock.yml +++ b/.github/workflows/copilot-pr-nlp-analysis.lock.yml @@ -991,6 +991,7 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() + continue-on-error: true env: MEMORY_DIR: /tmp/gh-aw/repo-memory/default run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" diff --git a/.github/workflows/copilot-pr-prompt-analysis.lock.yml b/.github/workflows/copilot-pr-prompt-analysis.lock.yml index d4d498c7604..8d08d0de2bd 100644 --- a/.github/workflows/copilot-pr-prompt-analysis.lock.yml +++ b/.github/workflows/copilot-pr-prompt-analysis.lock.yml @@ -941,6 +941,7 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() + continue-on-error: true env: MEMORY_DIR: /tmp/gh-aw/repo-memory/default run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" diff --git a/.github/workflows/copilot-session-insights.lock.yml b/.github/workflows/copilot-session-insights.lock.yml index 39dc5e3a43d..18f02879b36 100644 --- a/.github/workflows/copilot-session-insights.lock.yml +++ b/.github/workflows/copilot-session-insights.lock.yml @@ -1047,6 +1047,7 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() + continue-on-error: true env: MEMORY_DIR: /tmp/gh-aw/repo-memory/default run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" diff --git a/.github/workflows/copilot-token-audit.lock.yml b/.github/workflows/copilot-token-audit.lock.yml index b34e66fbf4f..48d980b7f9c 100644 --- a/.github/workflows/copilot-token-audit.lock.yml +++ b/.github/workflows/copilot-token-audit.lock.yml @@ -1061,6 +1061,7 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() + continue-on-error: true env: MEMORY_DIR: /tmp/gh-aw/repo-memory/default run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" diff --git a/.github/workflows/copilot-token-optimizer.lock.yml b/.github/workflows/copilot-token-optimizer.lock.yml index 4fca95ef69c..a20be430c54 100644 --- a/.github/workflows/copilot-token-optimizer.lock.yml +++ b/.github/workflows/copilot-token-optimizer.lock.yml @@ -920,6 +920,7 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() + continue-on-error: true env: MEMORY_DIR: /tmp/gh-aw/repo-memory/default run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" diff --git a/.github/workflows/daily-cli-performance.lock.yml b/.github/workflows/daily-cli-performance.lock.yml index 3c06382669b..40eab683de7 100644 --- a/.github/workflows/daily-cli-performance.lock.yml +++ b/.github/workflows/daily-cli-performance.lock.yml @@ -1137,6 +1137,7 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() + continue-on-error: true env: MEMORY_DIR: /tmp/gh-aw/repo-memory/default run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" diff --git a/.github/workflows/daily-code-metrics.lock.yml b/.github/workflows/daily-code-metrics.lock.yml index 6f53e8fba70..a2031997bec 100644 --- a/.github/workflows/daily-code-metrics.lock.yml +++ b/.github/workflows/daily-code-metrics.lock.yml @@ -1026,6 +1026,7 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() + continue-on-error: true env: MEMORY_DIR: /tmp/gh-aw/repo-memory/default run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" diff --git a/.github/workflows/daily-community-attribution.lock.yml b/.github/workflows/daily-community-attribution.lock.yml index c7250f8bb9f..f23d23c6140 100644 --- a/.github/workflows/daily-community-attribution.lock.yml +++ b/.github/workflows/daily-community-attribution.lock.yml @@ -1001,6 +1001,7 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize wiki-memory filenames (default) if: always() + continue-on-error: true env: MEMORY_DIR: /tmp/gh-aw/repo-memory/default run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" diff --git a/.github/workflows/daily-news.lock.yml b/.github/workflows/daily-news.lock.yml index 3228fb8587a..cc9a09f70fe 100644 --- a/.github/workflows/daily-news.lock.yml +++ b/.github/workflows/daily-news.lock.yml @@ -1073,6 +1073,7 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() + continue-on-error: true env: MEMORY_DIR: /tmp/gh-aw/repo-memory/default run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" diff --git a/.github/workflows/daily-sentrux-report.lock.yml b/.github/workflows/daily-sentrux-report.lock.yml index 61b9bd938e2..856b3e324c1 100644 --- a/.github/workflows/daily-sentrux-report.lock.yml +++ b/.github/workflows/daily-sentrux-report.lock.yml @@ -911,6 +911,7 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() + continue-on-error: true env: MEMORY_DIR: /tmp/gh-aw/repo-memory/default run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" diff --git a/.github/workflows/daily-testify-uber-super-expert.lock.yml b/.github/workflows/daily-testify-uber-super-expert.lock.yml index 16e88064c97..17617c79296 100644 --- a/.github/workflows/daily-testify-uber-super-expert.lock.yml +++ b/.github/workflows/daily-testify-uber-super-expert.lock.yml @@ -1006,6 +1006,7 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() + continue-on-error: true env: MEMORY_DIR: /tmp/gh-aw/repo-memory/default run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" diff --git a/.github/workflows/deep-report.lock.yml b/.github/workflows/deep-report.lock.yml index 14ae0d2239f..e7899da210b 100644 --- a/.github/workflows/deep-report.lock.yml +++ b/.github/workflows/deep-report.lock.yml @@ -1095,6 +1095,7 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() + continue-on-error: true env: MEMORY_DIR: /tmp/gh-aw/repo-memory/default run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" diff --git a/.github/workflows/delight.lock.yml b/.github/workflows/delight.lock.yml index 71c1fcd61ac..0a8a280db40 100644 --- a/.github/workflows/delight.lock.yml +++ b/.github/workflows/delight.lock.yml @@ -957,6 +957,7 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() + continue-on-error: true env: MEMORY_DIR: /tmp/gh-aw/repo-memory/default run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" diff --git a/.github/workflows/developer-docs-consolidator.lock.yml b/.github/workflows/developer-docs-consolidator.lock.yml index 384c250f493..2708918b4e1 100644 --- a/.github/workflows/developer-docs-consolidator.lock.yml +++ b/.github/workflows/developer-docs-consolidator.lock.yml @@ -1119,6 +1119,7 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize wiki-memory filenames (default) if: always() + continue-on-error: true env: MEMORY_DIR: /tmp/gh-aw/repo-memory/default run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" diff --git a/.github/workflows/discussion-task-miner.lock.yml b/.github/workflows/discussion-task-miner.lock.yml index 857ae58de92..59dfe98e5b3 100644 --- a/.github/workflows/discussion-task-miner.lock.yml +++ b/.github/workflows/discussion-task-miner.lock.yml @@ -920,6 +920,7 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() + continue-on-error: true env: MEMORY_DIR: /tmp/gh-aw/repo-memory/default run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" diff --git a/.github/workflows/firewall-escape.lock.yml b/.github/workflows/firewall-escape.lock.yml index 955422f39df..09e4e1221e7 100644 --- a/.github/workflows/firewall-escape.lock.yml +++ b/.github/workflows/firewall-escape.lock.yml @@ -908,6 +908,7 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() + continue-on-error: true env: MEMORY_DIR: /tmp/gh-aw/repo-memory/default run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" diff --git a/.github/workflows/glossary-maintainer.lock.yml b/.github/workflows/glossary-maintainer.lock.yml index c03dc724f0f..33233e311eb 100644 --- a/.github/workflows/glossary-maintainer.lock.yml +++ b/.github/workflows/glossary-maintainer.lock.yml @@ -994,6 +994,7 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize wiki-memory filenames (default) if: always() + continue-on-error: true env: MEMORY_DIR: /tmp/gh-aw/repo-memory/default run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" diff --git a/.github/workflows/metrics-collector.lock.yml b/.github/workflows/metrics-collector.lock.yml index 340150da26f..85f0ef66a7f 100644 --- a/.github/workflows/metrics-collector.lock.yml +++ b/.github/workflows/metrics-collector.lock.yml @@ -882,6 +882,7 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() + continue-on-error: true env: MEMORY_DIR: /tmp/gh-aw/repo-memory/default run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" diff --git a/.github/workflows/pr-triage-agent.lock.yml b/.github/workflows/pr-triage-agent.lock.yml index 18069b074f5..f27918dbee2 100644 --- a/.github/workflows/pr-triage-agent.lock.yml +++ b/.github/workflows/pr-triage-agent.lock.yml @@ -1001,6 +1001,7 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() + continue-on-error: true env: MEMORY_DIR: /tmp/gh-aw/repo-memory/default run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" diff --git a/.github/workflows/security-compliance.lock.yml b/.github/workflows/security-compliance.lock.yml index f2be9036442..03902e38a0a 100644 --- a/.github/workflows/security-compliance.lock.yml +++ b/.github/workflows/security-compliance.lock.yml @@ -887,6 +887,7 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() + continue-on-error: true env: MEMORY_DIR: /tmp/gh-aw/repo-memory/default run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" diff --git a/.github/workflows/smoke-ci.lock.yml b/.github/workflows/smoke-ci.lock.yml index 27f123ac897..796905ad887 100644 --- a/.github/workflows/smoke-ci.lock.yml +++ b/.github/workflows/smoke-ci.lock.yml @@ -1119,6 +1119,7 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() + continue-on-error: true env: MEMORY_DIR: /tmp/gh-aw/repo-memory/default run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" diff --git a/.github/workflows/technical-doc-writer.lock.yml b/.github/workflows/technical-doc-writer.lock.yml index 3ecfe7ef12f..735ce31b68a 100644 --- a/.github/workflows/technical-doc-writer.lock.yml +++ b/.github/workflows/technical-doc-writer.lock.yml @@ -966,6 +966,7 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize wiki-memory filenames (default) if: always() + continue-on-error: true env: MEMORY_DIR: /tmp/gh-aw/repo-memory/default run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" diff --git a/.github/workflows/weekly-blog-post-writer.lock.yml b/.github/workflows/weekly-blog-post-writer.lock.yml index b418c678145..072f0c09fa7 100644 --- a/.github/workflows/weekly-blog-post-writer.lock.yml +++ b/.github/workflows/weekly-blog-post-writer.lock.yml @@ -970,6 +970,7 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize wiki-memory filenames (default) if: always() + continue-on-error: true env: MEMORY_DIR: /tmp/gh-aw/repo-memory/default run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" diff --git a/.github/workflows/workflow-health-manager.lock.yml b/.github/workflows/workflow-health-manager.lock.yml index ddc66f8de6c..ee23fb417a2 100644 --- a/.github/workflows/workflow-health-manager.lock.yml +++ b/.github/workflows/workflow-health-manager.lock.yml @@ -961,6 +961,7 @@ jobs: # Upload repo memory as artifacts for push job - name: Sanitize repo-memory filenames (default) if: always() + continue-on-error: true env: MEMORY_DIR: /tmp/gh-aw/repo-memory/default run: bash "${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh" diff --git a/actions/setup/sh/sanitize_repo_memory_filenames.sh b/actions/setup/sh/sanitize_repo_memory_filenames.sh index 4253a0c0842..1f48a03f594 100644 --- a/actions/setup/sh/sanitize_repo_memory_filenames.sh +++ b/actions/setup/sh/sanitize_repo_memory_filenames.sh @@ -2,13 +2,17 @@ set -euo pipefail # sanitize_repo_memory_filenames.sh -# Renames files in the repo-memory git working tree whose names contain -# characters forbidden by GitHub Actions artifact upload (NTFS: ? : * | < > "). -# Tracked files are renamed with `git mv` so the rename is reflected in git -# history. New (untracked) files written by the agent are renamed with `mv`. +# Renames files in the repo-memory directory whose names contain characters +# forbidden by GitHub Actions artifact upload (NTFS: ? : * | < > "). +# When the directory is a git working tree, tracked files are renamed with +# `git mv` so the rename is reflected in git history. Untracked files and +# files in plain (non-git) directories are renamed with `mv`. +# +# Collision handling: if the sanitized destination already exists, a numeric +# suffix is appended (e.g. "a-.md" -> "a--1.md") to avoid overwriting. # # Required environment variables: -# MEMORY_DIR: Path to the repo-memory git working tree +# MEMORY_DIR: Path to the repo-memory directory (git working tree or plain dir) MEMORY_DIR="${MEMORY_DIR:?MEMORY_DIR is required}" @@ -19,9 +23,9 @@ fi cd "$MEMORY_DIR" -if [ ! -d ".git" ]; then - echo "Not a git repository: $MEMORY_DIR — skipping sanitization" - exit 0 +IS_GIT=false +if [ -d ".git" ]; then + IS_GIT=true fi # sanitize_name: replace NTFS-forbidden characters in a filename with hyphen @@ -29,38 +33,92 @@ sanitize_name() { printf '%s' "$1" | sed 's/[?:*|<>"]/-/g' } -# Rename tracked files (in git index) that contain forbidden characters. -# git mv handles both the working-tree rename and the index update atomically. -while IFS= read -r -d '' filepath; do - base=$(basename "$filepath") - safe=$(sanitize_name "$base") - if [ "$base" != "$safe" ]; then - dir=$(dirname "$filepath") - if [ "$dir" = "." ]; then - newpath="$safe" - else - newpath="$dir/$safe" - fi - git mv -- "$filepath" "$newpath" - echo "Renamed tracked: $filepath -> $newpath" +# unique_path: given a path, append a numeric suffix until it does not exist. +# Note: extension splitting uses the last dot only (e.g. "file.tar.gz" splits +# into base="file.tar" and ext=".gz"), which is intentional — we only need a +# unique name, not perfect extension preservation. +unique_path() { + local candidate="$1" + # Use both -e and -L to also detect broken symlinks + if [ ! -e "$candidate" ] && [ ! -L "$candidate" ]; then + printf '%s' "$candidate" + return + fi + local base ext n + # Split candidate into base and extension (last dot only) + base="${candidate%.*}" + if [ "$base" = "$candidate" ]; then + ext="" + else + ext=".${candidate##*.}" fi -done < <(git ls-files --cached -z 2>/dev/null) + n=1 + while [ -e "${base}-${n}${ext}" ] || [ -L "${base}-${n}${ext}" ]; do + n=$((n + 1)) + done + printf '%s' "${base}-${n}${ext}" +} -# Rename untracked (new) files written by the agent that contain forbidden characters. -# These are not yet in the git index so plain mv is used. -while IFS= read -r -d '' filepath; do - base=$(basename "$filepath") - safe=$(sanitize_name "$base") - if [ "$base" != "$safe" ]; then - dir=$(dirname "$filepath") - if [ "$dir" = "." ]; then - newpath="$safe" - else - newpath="$dir/$safe" - fi - mv -- "$filepath" "$newpath" - echo "Renamed untracked: $filepath -> $newpath" +# do_rename: rename $1 to $2 using git mv (tracked) or mv (untracked/plain) +do_rename() { + local src="$1" dst="$2" is_tracked="$3" + dst=$(unique_path "$dst") + if [ "$is_tracked" = "true" ]; then + git mv -- "$src" "$dst" + echo "Renamed tracked: $src -> $dst" + else + mv -- "$src" "$dst" + echo "Renamed untracked: $src -> $dst" fi -done < <(git ls-files --others -z 2>/dev/null) +} + +if [ "$IS_GIT" = "true" ]; then + # Rename tracked files (in git index) that contain forbidden characters. + # git mv handles both the working-tree rename and the index update atomically. + while IFS= read -r -d '' filepath; do + base=$(basename "$filepath") + safe=$(sanitize_name "$base") + if [ "$base" != "$safe" ]; then + dir=$(dirname "$filepath") + if [ "$dir" = "." ]; then + newpath="$safe" + else + newpath="$dir/$safe" + fi + do_rename "$filepath" "$newpath" true + fi + done < <(git ls-files --cached -z 2>/dev/null) + + # Rename untracked (new) files written by the agent that contain forbidden characters. + while IFS= read -r -d '' filepath; do + base=$(basename "$filepath") + safe=$(sanitize_name "$base") + if [ "$base" != "$safe" ]; then + dir=$(dirname "$filepath") + if [ "$dir" = "." ]; then + newpath="$safe" + else + newpath="$dir/$safe" + fi + do_rename "$filepath" "$newpath" false + fi + done < <(git ls-files --others -z 2>/dev/null) +else + # Plain directory (no git): best-effort rename all files with forbidden characters. + echo "Not a git repository — using plain mv for filename sanitization" + while IFS= read -r -d '' filepath; do + base=$(basename "$filepath") + safe=$(sanitize_name "$base") + if [ "$base" != "$safe" ]; then + dir=$(dirname "$filepath") + if [ "$dir" = "." ]; then + newpath="$safe" + else + newpath="$dir/$safe" + fi + do_rename "$filepath" "$newpath" false + fi + done < <(find . -depth -type f -print0 2>/dev/null) +fi echo "Sanitization complete" diff --git a/pkg/workflow/repo_memory.go b/pkg/workflow/repo_memory.go index 75e1fdf306a..39945169c9a 100644 --- a/pkg/workflow/repo_memory.go +++ b/pkg/workflow/repo_memory.go @@ -506,6 +506,7 @@ func generateRepoMemoryArtifactUpload(builder *strings.Builder, data *WorkflowDa // repo-memory is backed by a git working tree. fmt.Fprintf(builder, " - name: Sanitize %s filenames (%s)\n", memoryLabel, memory.ID) builder.WriteString(" if: always()\n") + builder.WriteString(" continue-on-error: true\n") builder.WriteString(" env:\n") fmt.Fprintf(builder, " MEMORY_DIR: %s\n", memoryDir) builder.WriteString(" run: bash \"${RUNNER_TEMP}/gh-aw/actions/sanitize_repo_memory_filenames.sh\"\n") diff --git a/pkg/workflow/repo_memory_test.go b/pkg/workflow/repo_memory_test.go index d8952899e7e..62f3ddc568f 100644 --- a/pkg/workflow/repo_memory_test.go +++ b/pkg/workflow/repo_memory_test.go @@ -245,6 +245,82 @@ func TestRepoMemoryStepsGeneration(t *testing.T) { } } +// TestGenerateRepoMemoryArtifactUpload tests that the artifact upload steps are generated correctly, +// including the sanitize step that appears before each upload step. +func TestGenerateRepoMemoryArtifactUpload(t *testing.T) { + tests := []struct { + name string + memory RepoMemoryEntry + wantSanitizeLabel string + }{ + { + name: "non-wiki memory", + memory: RepoMemoryEntry{ + ID: "default", + BranchName: "memory/default", + Wiki: false, + }, + wantSanitizeLabel: "repo-memory", + }, + { + name: "wiki memory", + memory: RepoMemoryEntry{ + ID: "notes", + BranchName: "memory/notes", + Wiki: true, + }, + wantSanitizeLabel: "wiki-memory", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + config := &RepoMemoryConfig{ + Memories: []RepoMemoryEntry{tt.memory}, + } + data := &WorkflowData{ + RepoMemoryConfig: config, + } + + var builder strings.Builder + generateRepoMemoryArtifactUpload(&builder, data) + output := builder.String() + + sanitizeName := "Sanitize " + tt.wantSanitizeLabel + " filenames (" + tt.memory.ID + ")" + uploadName := "Upload " + tt.wantSanitizeLabel + " artifact (" + tt.memory.ID + ")" + + // Both steps must be present + assert.Contains(t, output, sanitizeName, "Should contain sanitize step") + assert.Contains(t, output, uploadName, "Should contain upload step") + + // Sanitize step must appear before the upload step + sanitizePos := strings.Index(output, sanitizeName) + uploadPos := strings.Index(output, uploadName) + assert.Less(t, sanitizePos, uploadPos, "Sanitize step should appear before upload step") + + // Sanitize step must have continue-on-error: true so a rename failure + // does not block the artifact upload. Verify it appears between + // "if: always()" and "env:" (correct position in YAML step structure). + sanitizeSection := output[sanitizePos:uploadPos] + ifPos := strings.Index(sanitizeSection, "if: always()") + continuePos := strings.Index(sanitizeSection, "continue-on-error: true") + envPos := strings.Index(sanitizeSection, "env:") + require.Greater(t, continuePos, -1, "Sanitize step should have continue-on-error: true") + assert.Greater(t, continuePos, ifPos, + "continue-on-error should appear after if: always()") + assert.Less(t, continuePos, envPos, + "continue-on-error should appear before env:") + + // Sanitize step must set MEMORY_DIR and call the script + expectedDir := "/tmp/gh-aw/repo-memory/" + tt.memory.ID + assert.Contains(t, sanitizeSection, "MEMORY_DIR: "+expectedDir, + "Sanitize step should set MEMORY_DIR env var") + assert.Contains(t, sanitizeSection, "sanitize_repo_memory_filenames.sh", + "Sanitize step should call sanitize_repo_memory_filenames.sh") + }) + } +} + // TestRepoMemoryPromptGeneration tests that prompt section is generated correctly func TestRepoMemoryPromptGeneration(t *testing.T) { config := &RepoMemoryConfig{