Skip to content

Commit 8596967

Browse files
authored
ci: "fix: exempt team members from compliance cleanup" (anomalyco#28865)
1 parent 0003802 commit 8596967

6 files changed

Lines changed: 31 additions & 56 deletions

File tree

.github/workflows/compliance-close.yml

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -34,25 +34,11 @@ jobs:
3434
3535
const now = Date.now();
3636
const twoHours = 2 * 60 * 60 * 1000;
37-
const teamAssociations = ['OWNER', 'MEMBER', 'COLLABORATOR'];
3837
3938
for (const item of items) {
4039
const isPR = !!item.pull_request;
4140
const kind = isPR ? 'PR' : 'issue';
4241
43-
if (teamAssociations.includes(item.author_association)) {
44-
core.info(`Skipping ${kind} #${item.number}: author association is ${item.author_association}`);
45-
try {
46-
await github.rest.issues.removeLabel({
47-
owner: context.repo.owner,
48-
repo: context.repo.repo,
49-
issue_number: item.number,
50-
name: 'needs:compliance',
51-
});
52-
} catch (e) {}
53-
continue;
54-
}
55-
5642
const { data: comments } = await github.rest.issues.listComments({
5743
owner: context.repo.owner,
5844
repo: context.repo.repo,

.github/workflows/duplicate-issues.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ on:
66

77
jobs:
88
check-duplicates:
9-
if: github.event.action == 'opened' && !contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.issue.author_association)
9+
if: github.event.action == 'opened'
1010
runs-on: blacksmith-4vcpu-ubuntu-2404
1111
permissions:
1212
contents: read
@@ -118,7 +118,7 @@ jobs:
118118
Remember: post at most ONE comment combining all findings. If everything is fine, post nothing."
119119
120120
recheck-compliance:
121-
if: github.event.action == 'edited' && contains(github.event.issue.labels.*.name, 'needs:compliance') && !contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.issue.author_association)
121+
if: github.event.action == 'edited' && contains(github.event.issue.labels.*.name, 'needs:compliance')
122122
runs-on: blacksmith-4vcpu-ubuntu-2404
123123
permissions:
124124
contents: read

.github/workflows/pr-management.yml

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,25 +11,22 @@ jobs:
1111
contents: read
1212
pull-requests: write
1313
steps:
14+
- name: Checkout repository
15+
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
16+
with:
17+
fetch-depth: 1
18+
1419
- name: Check team membership
1520
id: team-check
1621
run: |
1722
LOGIN="${{ github.event.pull_request.user.login }}"
18-
ASSOCIATION="${{ github.event.pull_request.author_association }}"
19-
if [ "$LOGIN" = "opencode-agent[bot]" ] || [ "$ASSOCIATION" = "OWNER" ] || [ "$ASSOCIATION" = "MEMBER" ] || [ "$ASSOCIATION" = "COLLABORATOR" ]; then
23+
if [ "$LOGIN" = "opencode-agent[bot]" ] || grep -qxF "$LOGIN" .github/TEAM_MEMBERS; then
2024
echo "is_team=true" >> "$GITHUB_OUTPUT"
2125
echo "Skipping: $LOGIN is a team member or bot"
2226
else
2327
echo "is_team=false" >> "$GITHUB_OUTPUT"
2428
fi
2529
26-
- name: Checkout repository
27-
if: steps.team-check.outputs.is_team != 'true'
28-
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
29-
with:
30-
fetch-depth: 1
31-
ref: ${{ github.event.pull_request.base.sha }}
32-
3330
- name: Setup Bun
3431
if: steps.team-check.outputs.is_team != 'true'
3532
uses: ./.github/actions/setup-bun

.github/workflows/pr-standards.yml

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,15 @@ jobs:
2828
2929
// Check if author is a team member or bot
3030
if (login === 'opencode-agent[bot]') return;
31-
const teamAssociations = ['OWNER', 'MEMBER', 'COLLABORATOR'];
32-
if (teamAssociations.includes(pr.author_association)) {
33-
console.log(`Skipping: ${login} has author association ${pr.author_association}`);
31+
const { data: file } = await github.rest.repos.getContent({
32+
owner: context.repo.owner,
33+
repo: context.repo.repo,
34+
path: '.github/TEAM_MEMBERS',
35+
ref: 'dev'
36+
});
37+
const members = Buffer.from(file.content, 'base64').toString().split('\n').map(l => l.trim()).filter(Boolean);
38+
if (members.includes(login)) {
39+
console.log(`Skipping: ${login} is a team member`);
3440
return;
3541
}
3642
@@ -169,9 +175,15 @@ jobs:
169175
170176
// Check if author is a team member or bot
171177
if (login === 'opencode-agent[bot]') return;
172-
const teamAssociations = ['OWNER', 'MEMBER', 'COLLABORATOR'];
173-
if (teamAssociations.includes(pr.author_association)) {
174-
console.log(`Skipping: ${login} has author association ${pr.author_association}`);
178+
const { data: file } = await github.rest.repos.getContent({
179+
owner: context.repo.owner,
180+
repo: context.repo.repo,
181+
path: '.github/TEAM_MEMBERS',
182+
ref: 'dev'
183+
});
184+
const members = Buffer.from(file.content, 'base64').toString().split('\n').map(l => l.trim()).filter(Boolean);
185+
if (members.includes(login)) {
186+
console.log(`Skipping: ${login} is a team member`);
175187
return;
176188
}
177189

script/github/close-issues.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,8 @@ const cutoff = new Date(Date.now() - days * 24 * 60 * 60 * 1000)
1515
type Issue = {
1616
number: number
1717
updated_at: string
18-
author_association: string
1918
}
2019

21-
const teamAssociations = new Set(["OWNER", "MEMBER", "COLLABORATOR"])
22-
2320
const headers = {
2421
Authorization: `Bearer ${token}`,
2522
"Content-Type": "application/json",
@@ -66,10 +63,6 @@ async function main() {
6663
for (const i of all) {
6764
const updated = new Date(i.updated_at)
6865
if (updated < cutoff) {
69-
if (teamAssociations.has(i.author_association)) {
70-
console.log(`Skipping #${i.number}: author association is ${i.author_association}`)
71-
continue
72-
}
7366
stale.push(i.number)
7467
} else {
7568
console.log(`\nFound fresh issue #${i.number}, stopping`)

script/github/close-prs.ts

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ const maxClose =
6969
const sleepMs = requireNonNegativeInteger("sleep-ms", values["sleep-ms"])
7070
const printLimit = requireNonNegativeInteger("print-limit", values["print-limit"])
7171
const cutoff = subtractMonths(new Date(), ageMonths)
72-
const teamAssociations = new Set(["OWNER", "MEMBER", "COLLABORATOR"])
7372

7473
const headers = {
7574
Authorization: `Bearer ${token}`,
@@ -83,7 +82,6 @@ type PullRequest = {
8382
title: string
8483
url: string
8584
createdAt: string
86-
authorAssociation: string
8785
reactionGroups: Array<{
8886
content: string
8987
users: {
@@ -147,25 +145,19 @@ async function main() {
147145
console.log(`Threshold: fewer than ${threshold} positive reactions`)
148146

149147
const prs = await fetchOpenPullRequests()
150-
const scored = prs.map((pr) => ({ ...pr, positiveReactions: positiveReactionCount(pr) }))
151-
const recentCount = scored.filter((pr) => new Date(pr.createdAt) >= cutoff).length
152-
const teamCount = scored.filter((pr) => isTeamMember(pr)).length
153-
const matching = scored.filter(
154-
(pr) => !isTeamMember(pr) && new Date(pr.createdAt) < cutoff && pr.positiveReactions < threshold,
155-
)
148+
const recentCount = prs.filter((pr) => new Date(pr.createdAt) >= cutoff).length
149+
const matching = prs
150+
.map((pr) => ({ ...pr, positiveReactions: positiveReactionCount(pr) }))
151+
.filter((pr) => new Date(pr.createdAt) < cutoff && pr.positiveReactions < threshold)
156152
const candidates = matching.filter((pr) => !hasPriorCleanup(pr))
157153
const selected = maxClose === undefined ? candidates : candidates.slice(0, maxClose)
158154

159155
console.log(`Fetched ${prs.length} open PRs`)
160156
console.log(`Matching cleanup criteria: ${matching.length}`)
161157
console.log(`Skipped previously cleaned PRs: ${matching.length - candidates.length}`)
162-
console.log(`Team member PRs untouched: ${teamCount}`)
163158
console.log(`Recent PRs untouched: ${recentCount}`)
164159
console.log(
165-
`Older PRs with at least ${threshold} positive reactions untouched: ${
166-
scored.filter((pr) => !isTeamMember(pr) && new Date(pr.createdAt) < cutoff && pr.positiveReactions >= threshold)
167-
.length
168-
}`,
160+
`Older PRs with at least ${threshold} positive reactions untouched: ${prs.length - matching.length - recentCount}`,
169161
)
170162

171163
if (selected.length === 0) return
@@ -213,7 +205,6 @@ async function fetchOpenPullRequests() {
213205
title
214206
url
215207
createdAt
216-
authorAssociation
217208
reactionGroups {
218209
content
219210
users {
@@ -344,10 +335,6 @@ function hasPriorCleanup(pr: PullRequest) {
344335
return pr.labels.nodes.some((label) => label.name === cleanupLabel)
345336
}
346337

347-
function isTeamMember(pr: PullRequest) {
348-
return teamAssociations.has(pr.authorAssociation)
349-
}
350-
351338
function requireRepo(value: string | undefined) {
352339
if (!value) throw new Error("repo is required")
353340
const [owner, name] = value.split("/")

0 commit comments

Comments
 (0)