Repository navigation
Expand file tree
/
Copy pathaction.yml
More file actions
165 lines (145 loc) · 7.81 KB
/
Copy pathaction.yml
File metadata and controls
165 lines (145 loc) · 7.81 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
name: Commit summary
description: Summarises a GameTracking commit with Claude Code and posts it as a commit comment. Reads the token from the CLAUDE_CODE_OAUTH_TOKEN environment variable (made with claude setup-token).
inputs:
sha:
description: 'Commit to summarise'
required: true
model:
description: 'Claude model'
required: false
default: 'opus'
worker-model:
description: 'Claude model for the workers that read the diff'
required: false
default: 'sonnet'
runs:
using: composite
steps:
# Older builds are needed for revert checks and "is this new" lookups, history searches in the prompt are limited to the same six months
- name: Fetch older builds
shell: bash
working-directory: tracked_game
run: git fetch --quiet --shallow-since="6 months ago" origin
# Other Source 2 games with recent history, to spot shared engine changes and when they first appeared
- name: Clone GameTracking-CS2
if: github.repository != 'SteamTracking/GameTracking-CS2'
shell: bash
run: git clone --quiet --shallow-since="2 months ago" https://github.com/SteamTracking/GameTracking-CS2.git "$GITHUB_WORKSPACE/siblings/GameTracking-CS2"
- name: Clone GameTracking-Dota2
if: github.repository != 'SteamTracking/GameTracking-Dota2'
shell: bash
run: git clone --quiet --shallow-since="2 months ago" https://github.com/SteamTracking/GameTracking-Dota2.git "$GITHUB_WORKSPACE/siblings/GameTracking-Dota2"
- name: Clone GameTracking-Deadlock
if: github.repository != 'SteamTracking/GameTracking-Deadlock'
shell: bash
run: git clone --quiet --shallow-since="2 months ago" https://github.com/SteamTracking/GameTracking-Deadlock.git "$GITHUB_WORKSPACE/siblings/GameTracking-Deadlock"
# The main session orchestrates, worker agents read the diff and a writer agent turns their notes into the comment
- name: Prepare prompts
shell: bash
run: |
# Forward slashes on Windows, so the paths survive unquoted in shell commands
norm() { if command -v cygpath > /dev/null 2>&1; then cygpath -m "$1"; else printf '%s' "$1"; fi; }
workspace=$(norm "$GITHUB_WORKSPACE")
tools=$workspace/tools/exe
notes=$(norm "$RUNNER_TEMP")/commit_summary_notes
out=$workspace/commit_summary.md
run=$(
echo '## This run'
echo "- The game repository is checked out at \`$workspace/tracked_game\` with its last six months of history; run git as \`git -C <that path> …\`."
echo '- The commit to summarise is `<sha>` = `${{ inputs.sha }}`.'
echo "- Repos of the other games are checked out at their latest commit under \`$workspace/siblings/\`, with their last two months of history."
echo "- \`<tools>\` is \`$tools\`."
echo "- \`<notes>\` is \`$notes\`."
echo "- The comment body (or \`NO_COMMENT\`) goes to \`$out\`, this exact absolute path, and only the writer writes it. Apart from that file, notes and temp files from \`mktemp\`, nobody writes anything. Only that file is posted, not the final reply."
)
mkdir -p "$RUNNER_TEMP/commit_summary_notes"
printf '%s\n\n%s\n\n%s\n' "$(cat "$GITHUB_ACTION_PATH/common.md")" "$(cat "$GITHUB_ACTION_PATH/orchestrator.md")" "$run" > "$RUNNER_TEMP/commit_summary_prompt.md"
role() { printf '%s\n\n%s\n\n%s\n' "$(cat "$GITHUB_ACTION_PATH/common.md")" "$(cat "$GITHUB_ACTION_PATH/$1.md")" "$run"; }
jq -n \
--arg worker "$(role worker)" \
--arg writer "$(role writer)" \
--arg worker_model "${{ inputs.worker-model }}" \
'{
worker: {description: "Reads one area of a GameTracking commit diff completely and writes notes with findings and evidence", prompt: $worker, model: $worker_model},
writer: {description: "Writes the commit comment from the workers notes and checks it against the rules", prompt: $writer}
}' \
> "$RUNNER_TEMP/commit_summary_agents.json"
# The installers are per platform, both install to ~/.local/bin. Retried as downloads can be rate limited.
- name: Install Claude Code (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
for ($attempt = 1; $true; $attempt++) {
try {
& ([scriptblock]::Create((Invoke-RestMethod https://claude.ai/install.ps1)))
if (Test-Path "$env:USERPROFILE\.local\bin\claude.exe") { break }
throw "claude.exe was not installed"
} catch {
if ($attempt -ge 3) { throw }
Write-Host "Install attempt $attempt failed: $_"
Start-Sleep -Seconds (10 * $attempt)
}
}
"$env:USERPROFILE\.local\bin" | Out-File -FilePath $env:GITHUB_PATH -Append -Encoding utf8
- name: Install Claude Code (Linux)
if: runner.os != 'Windows'
shell: bash
run: |
set -o pipefail
for attempt in 1 2 3; do
if curl -fsSL https://claude.ai/install.sh | bash; then
break
fi
if [[ $attempt == 3 ]]; then
exit 1
fi
echo "Install attempt $attempt failed"
sleep $((10 * attempt))
done
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
# The transcript and the workers' notes are kept as an artifact, so skipped steps can be audited
- name: Run Claude Code
shell: bash
run: |
set -o pipefail
claude -p "$(cat "$RUNNER_TEMP/commit_summary_prompt.md")" \
--model "${{ inputs.model }}" \
--agents "$RUNNER_TEMP/commit_summary_agents.json" \
--permission-mode auto \
--output-format stream-json \
--verbose < /dev/null > "$RUNNER_TEMP/commit_summary_transcript.jsonl"
jq -r 'select(.type == "result") | .result' "$RUNNER_TEMP/commit_summary_transcript.jsonl" | tee -a "$GITHUB_STEP_SUMMARY"
# Set-diffing big string dumps can take minutes, so commands get longer than the default 2 minute timeout
env:
BASH_DEFAULT_TIMEOUT_MS: '600000'
BASH_MAX_TIMEOUT_MS: '1800000'
- name: Upload transcript
if: always()
uses: actions/upload-artifact@v7
with:
name: commit-summary-transcript
path: |
${{ runner.temp }}/commit_summary_transcript.jsonl
${{ runner.temp }}/commit_summary_notes/
if-no-files-found: ignore
retention-days: 7
- name: Post comment
shell: bash
run: |
if [[ ! -s commit_summary.md ]]; then
echo "::error::Claude Code did not write commit_summary.md"
find . -name commit_summary.md -not -path '*/.git/*'
exit 1
fi
if [[ "$(tr -d '[:space:]`' < commit_summary.md)" == "NO_COMMENT" ]]; then
echo "Nothing worth commenting"
exit 0
fi
if grep -nE '\ba value\b|(^|[^A-Za-z])I (did|have|read|checked|could|was)\b|\b(leak|unreleased|upcoming)\b' commit_summary.md; then
echo "::warning::The comment matched a banned phrase (see above)"
fi
printf '\n\n---\n<sub>This summary was generated by AI and may contain mistakes.</sub>\n' >> commit_summary.md
gh api "repos/$GITHUB_REPOSITORY/commits/${{ inputs.sha }}/comments" \
-F body=@commit_summary.md
env:
GH_TOKEN: ${{ github.token }}