| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 39e7ff9 commit 1268f86
6 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -34,11 +34,25 @@ jobs: | |||
| 34 | 34 | ||
| 35 | 35 | const now = Date.now(); | |
| 36 | 36 | const twoHours = 2 * 60 * 60 * 1000; | |
| 37 | + const teamAssociations = ['OWNER', 'MEMBER', 'COLLABORATOR']; | ||
| 37 | 38 | ||
| 38 | 39 | for (const item of items) { | |
| 39 | 40 | const isPR = !!item.pull_request; | |
| 40 | 41 | const kind = isPR ? 'PR' : 'issue'; | |
| 41 | 42 | ||
| 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 | + | ||
| 42 | 56 | const { data: comments } = await github.rest.issues.listComments({ | |
| 43 | 57 | owner: context.repo.owner, | |
| 44 | 58 | repo: context.repo.repo, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -6,7 +6,7 @@ on: | |||
| 6 | 6 | ||
| 7 | 7 | jobs: | |
| 8 | 8 | check-duplicates: | |
| 9 | - if: github.event.action == 'opened' | ||
| 9 | + if: github.event.action == 'opened' && !contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.issue.author_association) | ||
| 10 | 10 | runs-on: blacksmith-4vcpu-ubuntu-2404 | |
| 11 | 11 | permissions: | |
| 12 | 12 | contents: read | |
@@ -118,7 +118,7 @@ jobs: | |||
| 118 | 118 | Remember: post at most ONE comment combining all findings. If everything is fine, post nothing." | |
| 119 | 119 | ||
| 120 | 120 | recheck-compliance: | |
| 121 | - if: github.event.action == 'edited' && contains(github.event.issue.labels.*.name, 'needs: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) | ||
| 122 | 122 | runs-on: blacksmith-4vcpu-ubuntu-2404 | |
| 123 | 123 | permissions: | |
| 124 | 124 | contents: read | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -11,22 +11,25 @@ jobs: | |||
| 11 | 11 | contents: read | |
| 12 | 12 | pull-requests: write | |
| 13 | 13 | steps: | |
| 14 | - - name: Checkout repository | ||
| 15 | - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 | ||
| 16 | - with: | ||
| 17 | - fetch-depth: 1 | ||
| 18 | - | ||
| 19 | 14 | - name: Check team membership | |
| 20 | 15 | id: team-check | |
| 21 | 16 | run: | | |
| 22 | 17 | LOGIN="${{ github.event.pull_request.user.login }}" | |
| 23 | - if [ "$LOGIN" = "opencode-agent[bot]" ] || grep -qxF "$LOGIN" .github/TEAM_MEMBERS; then | ||
| 18 | + ASSOCIATION="${{ github.event.pull_request.author_association }}" | ||
| 19 | + if [ "$LOGIN" = "opencode-agent[bot]" ] || [ "$ASSOCIATION" = "OWNER" ] || [ "$ASSOCIATION" = "MEMBER" ] || [ "$ASSOCIATION" = "COLLABORATOR" ]; then | ||
| 24 | 20 | echo "is_team=true" >> "$GITHUB_OUTPUT" | |
| 25 | 21 | echo "Skipping: $LOGIN is a team member or bot" | |
| 26 | 22 | else | |
| 27 | 23 | echo "is_team=false" >> "$GITHUB_OUTPUT" | |
| 28 | 24 | fi | |
| 29 | 25 | ||
| 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 | + | ||
| 30 | 33 | - name: Setup Bun | |
| 31 | 34 | if: steps.team-check.outputs.is_team != 'true' | |
| 32 | 35 | uses: ./.github/actions/setup-bun | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -28,15 +28,9 @@ jobs: | |||
| 28 | 28 | ||
| 29 | 29 | // Check if author is a team member or bot | |
| 30 | 30 | if (login === 'opencode-agent[bot]') return; | |
| 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`); | ||
| 31 | + const teamAssociations = ['OWNER', 'MEMBER', 'COLLABORATOR']; | ||
| 32 | + if (teamAssociations.includes(pr.author_association)) { | ||
| 33 | + console.log(`Skipping: ${login} has author association ${pr.author_association}`); | ||
| 40 | 34 | return; | |
| 41 | 35 | } | |
| 42 | 36 | ||
@@ -175,15 +169,9 @@ jobs: | |||
| 175 | 169 | ||
| 176 | 170 | // Check if author is a team member or bot | |
| 177 | 171 | if (login === 'opencode-agent[bot]') return; | |
| 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`); | ||
| 172 | + const teamAssociations = ['OWNER', 'MEMBER', 'COLLABORATOR']; | ||
| 173 | + if (teamAssociations.includes(pr.author_association)) { | ||
| 174 | + console.log(`Skipping: ${login} has author association ${pr.author_association}`); | ||
| 187 | 175 | return; | |
| 188 | 176 | } | |
| 189 | 177 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -15,8 +15,11 @@ const cutoff = new Date(Date.now() - days * 24 * 60 * 60 * 1000) | |||
| 15 | 15 | type Issue = { | |
| 16 | 16 | number: number | |
| 17 | 17 | updated_at: string | |
| 18 | + author_association: string | ||
| 18 | 19 | } | |
| 19 | 20 | ||
| 21 | + const teamAssociations = new Set(["OWNER", "MEMBER", "COLLABORATOR"]) | ||
| 22 | + | ||
| 20 | 23 | const headers = { | |
| 21 | 24 | Authorization: `Bearer ${token}`, | |
| 22 | 25 | "Content-Type": "application/json", | |
@@ -63,6 +66,10 @@ async function main() { | |||
| 63 | 66 | for (const i of all) { | |
| 64 | 67 | const updated = new Date(i.updated_at) | |
| 65 | 68 | 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 | + } | ||
| 66 | 73 | stale.push(i.number) | |
| 67 | 74 | } else { | |
| 68 | 75 | console.log(`\nFound fresh issue #${i.number}, stopping`) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -69,6 +69,7 @@ const maxClose = | |||
| 69 | 69 | const sleepMs = requireNonNegativeInteger("sleep-ms", values["sleep-ms"]) | |
| 70 | 70 | const printLimit = requireNonNegativeInteger("print-limit", values["print-limit"]) | |
| 71 | 71 | const cutoff = subtractMonths(new Date(), ageMonths) | |
| 72 | + const teamAssociations = new Set(["OWNER", "MEMBER", "COLLABORATOR"]) | ||
| 72 | 73 | ||
| 73 | 74 | const headers = { | |
| 74 | 75 | Authorization: `Bearer ${token}`, | |
@@ -82,6 +83,7 @@ type PullRequest = { | |||
| 82 | 83 | title: string | |
| 83 | 84 | url: string | |
| 84 | 85 | createdAt: string | |
| 86 | + authorAssociation: string | ||
| 85 | 87 | reactionGroups: Array<{ | |
| 86 | 88 | content: string | |
| 87 | 89 | users: { | |
@@ -145,19 +147,25 @@ async function main() { | |||
| 145 | 147 | console.log(`Threshold: fewer than ${threshold} positive reactions`) | |
| 146 | 148 | ||
| 147 | 149 | const prs = await fetchOpenPullRequests() | |
| 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) | ||
| 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 | + ) | ||
| 152 | 156 | const candidates = matching.filter((pr) => !hasPriorCleanup(pr)) | |
| 153 | 157 | const selected = maxClose === undefined ? candidates : candidates.slice(0, maxClose) | |
| 154 | 158 | ||
| 155 | 159 | console.log(`Fetched ${prs.length} open PRs`) | |
| 156 | 160 | console.log(`Matching cleanup criteria: ${matching.length}`) | |
| 157 | 161 | console.log(`Skipped previously cleaned PRs: ${matching.length - candidates.length}`) | |
| 162 | + console.log(`Team member PRs untouched: ${teamCount}`) | ||
| 158 | 163 | console.log(`Recent PRs untouched: ${recentCount}`) | |
| 159 | 164 | console.log( | |
| 160 | - `Older PRs with at least ${threshold} positive reactions untouched: ${prs.length - matching.length - recentCount}`, | ||
| 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 | + }`, | ||
| 161 | 169 | ) | |
| 162 | 170 | ||
| 163 | 171 | if (selected.length === 0) return | |
@@ -205,6 +213,7 @@ async function fetchOpenPullRequests() { | |||
| 205 | 213 | title | |
| 206 | 214 | url | |
| 207 | 215 | createdAt | |
| 216 | + authorAssociation | ||
| 208 | 217 | reactionGroups { | |
| 209 | 218 | content | |
| 210 | 219 | users { | |
@@ -335,6 +344,10 @@ function hasPriorCleanup(pr: PullRequest) { | |||
| 335 | 344 | return pr.labels.nodes.some((label) => label.name === cleanupLabel) | |
| 336 | 345 | } | |
| 337 | 346 | ||
| 347 | + function isTeamMember(pr: PullRequest) { | ||
| 348 | + return teamAssociations.has(pr.authorAssociation) | ||
| 349 | + } | ||
| 350 | + | ||
| 338 | 351 | function requireRepo(value: string | undefined) { | |
| 339 | 352 | if (!value) throw new Error("repo is required") | |
| 340 | 353 | const [owner, name] = value.split("/") | |
| Back | FazBrowse Home | New Git URL |
0 commit comments