Repository navigation
Expand file tree
/
Copy pathaction.yml
More file actions
167 lines (146 loc) · 5.8 KB
/
Copy pathaction.yml
File metadata and controls
167 lines (146 loc) · 5.8 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
166
167
name: "AgentConfigScore Regression Gate"
description: "Block pull requests that make AGENTS.md, CLAUDE.md, Cursor, Copilot, Gemini, or other coding-agent instructions worse."
author: "Zhibo Lin"
branding:
icon: "shield"
color: "green"
inputs:
base-sha:
description: "Baseline commit SHA. Defaults to the pull request base SHA."
required: false
default: ""
max-drop:
description: "Optional override for policy.max_drop. Empty uses the baseline repository policy or 0."
required: false
default: ""
fail-on-new-errors:
description: "Optional override for policy.fail_on_new_errors. Empty uses the baseline policy, or true when no policy file exists."
required: false
default: ""
python-version:
description: "Python version used to run AgentConfigScore."
required: false
default: "3.12"
outputs:
base-score:
description: "AgentConfigScore for the baseline revision."
value: ${{ steps.regression.outputs.base-score }}
head-score:
description: "AgentConfigScore for the candidate revision."
value: ${{ steps.regression.outputs.head-score }}
delta:
description: "Candidate score minus baseline score."
value: ${{ steps.regression.outputs.delta }}
new-findings:
description: "Number of newly introduced findings."
value: ${{ steps.regression.outputs.new-findings }}
new-errors:
description: "Number of newly introduced error-severity findings."
value: ${{ steps.regression.outputs.new-errors }}
resolved-findings:
description: "Number of findings resolved by the candidate revision."
value: ${{ steps.regression.outputs.resolved-findings }}
runs:
using: "composite"
steps:
- name: Set up Python
uses: actions/setup-python@v7
with:
python-version: ${{ inputs.python-version }}
- name: Install AgentConfigScore
shell: bash
run: python -m pip install --disable-pip-version-check "${{ github.action_path }}"
- name: Check agent-config regression
id: regression
shell: bash
env:
ACS_BASE_SHA: ${{ inputs.base-sha }}
ACS_EVENT_BASE_SHA: ${{ github.event.pull_request.base.sha }}
ACS_MAX_DROP: ${{ inputs.max-drop }}
ACS_FAIL_ON_NEW_ERRORS: ${{ inputs.fail-on-new-errors }}
run: |
set -euo pipefail
base_sha="${ACS_BASE_SHA:-$ACS_EVENT_BASE_SHA}"
if [[ -z "$base_sha" ]]; then
echo "::error::AgentConfigScore needs a base SHA. Use this action on pull_request or set 'base-sha'."
exit 2
fi
if ! [[ "$base_sha" =~ ^[0-9a-fA-F]{7,40}$ ]]; then
echo "::error::Invalid base SHA: $base_sha"
exit 2
fi
if [[ -n "$ACS_MAX_DROP" ]] && ! [[ "$ACS_MAX_DROP" =~ ^[0-9]+$ ]]; then
echo "::error::max-drop must be a non-negative integer"
exit 2
fi
if [[ -n "$ACS_FAIL_ON_NEW_ERRORS" && "$ACS_FAIL_ON_NEW_ERRORS" != "true" && "$ACS_FAIL_ON_NEW_ERRORS" != "false" ]]; then
echo "::error::fail-on-new-errors must be 'true' or 'false'"
exit 2
fi
if ! git cat-file -e "${base_sha}^{commit}" 2>/dev/null; then
git fetch --no-tags --depth=1 origin "$base_sha"
fi
base_dir="$RUNNER_TEMP/agent-config-score-base-${GITHUB_RUN_ID:-run}"
summary="$RUNNER_TEMP/agent-config-score-summary-${GITHUB_RUN_ID:-run}.md"
result_json="$RUNNER_TEMP/agent-config-score-result-${GITHUB_RUN_ID:-run}.json"
git worktree remove --force "$base_dir" >/dev/null 2>&1 || true
git worktree prune
git worktree add --detach "$base_dir" "$base_sha"
cleanup() {
git worktree remove --force "$base_dir" >/dev/null 2>&1 || true
git worktree prune >/dev/null 2>&1 || true
}
trap cleanup EXIT
if [[ -f "$base_dir/.agentconfigscore.json" ]]; then
echo "AgentConfigScore policy: baseline .agentconfigscore.json"
else
echo "AgentConfigScore policy: compatibility defaults (no baseline .agentconfigscore.json)"
fi
args=(
compare "$base_dir" "$GITHUB_WORKSPACE"
--markdown "$summary"
--explain
--json
)
if [[ -n "$ACS_MAX_DROP" ]]; then
args+=(--max-drop "$ACS_MAX_DROP")
fi
if [[ -n "$ACS_FAIL_ON_NEW_ERRORS" ]]; then
if [[ "$ACS_FAIL_ON_NEW_ERRORS" == "true" ]]; then
args+=(--fail-on-new-errors)
else
args+=(--no-fail-on-new-errors)
fi
elif [[ ! -f "$base_dir/.agentconfigscore.json" ]]; then
# Preserve the Action's historical default when a repository has not
# opted into an explicit policy file yet.
args+=(--fail-on-new-errors)
fi
set +e
agent-config-score "${args[@]}" > "$result_json"
status=$?
set -e
if [[ -f "$summary" && -n "${GITHUB_STEP_SUMMARY:-}" ]]; then
cat "$summary" >> "$GITHUB_STEP_SUMMARY"
fi
if [[ -s "$result_json" ]]; then
python - "$result_json" "$GITHUB_OUTPUT" <<'PY'
import json
import sys
result_path, output_path = sys.argv[1:]
with open(result_path, encoding="utf-8") as handle:
data = json.load(handle)
outputs = {
"base-score": data["base"]["score"],
"head-score": data["head"]["score"],
"delta": data["delta"],
"new-findings": len(data["new_findings"]),
"new-errors": sum(1 for finding in data["new_findings"] if finding["severity"] == "error"),
"resolved-findings": len(data["resolved_findings"]),
}
with open(output_path, "a", encoding="utf-8") as handle:
for key, value in outputs.items():
print(f"{key}={value}", file=handle)
PY
fi
exit "$status"