-
Notifications
You must be signed in to change notification settings - Fork 158
138 lines (128 loc) · 6.16 KB
/
Copy pathmodule-scorecard-check.yaml
File metadata and controls
138 lines (128 loc) · 6.16 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
# Scores modules changed in a pull request against
# .github/scorecard/SCORECARD.md and posts a sticky comment comparing the
# PR's score to the module's current scorecard discussion. Flags
# regressions, celebrates improvements, and confirms unchanged scores.
#
# Never creates or updates discussions; the comparison is read-only against
# GitHub and only writes the PR comment.
#
# Two triggers:
# - pull_request: runs automatically for same-repo PRs. Fork PRs are
# skipped because secrets are unavailable to them.
# - issue_comment: a maintainer comments "/scorecard" on any PR
# (including fork PRs) to run the check on demand. Restricted to
# OWNER/MEMBER/COLLABORATOR, so every fork-PR scoring is an explicit
# maintainer decision.
#
# Modules in every namespace (registry/<namespace>/modules/<name>) are
# scored. Only registry/coder modules have discussion baselines; community
# modules always report a fresh advisory score.
#
# Both paths execute only trusted code: the checkout is the base
# repository, and PR content is fetched separately and materialized ONLY
# under registry/, where the scoring script reads it as
# inert text for the LLM prompt. Nothing from the PR head is executed.
#
# Required repository secrets:
# SCORECARD_ANTHROPIC_API_KEY Anthropic API key used for scoring
#
# The baseline lookup reads discussions with the built-in GITHUB_TOKEN
# (discussions: read below); no PAT is needed.
name: Module Scorecard Check
on:
pull_request:
paths:
- "registry/*/modules/**"
issue_comment:
types: [created]
permissions:
contents: read
discussions: read
pull-requests: write
concurrency:
group: module-scorecard-check-${{ github.event.pull_request.number || github.event.issue.number }}
cancel-in-progress: true
jobs:
check:
name: Compare module scores against main
if: >-
(github.event_name == 'pull_request' &&
github.event.pull_request.head.repo.full_name == github.repository) ||
(github.event_name == 'issue_comment' &&
github.event.issue.pull_request &&
startsWith(github.event.comment.body, '/scorecard') &&
contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.comment.author_association))
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout trusted base
# For issue_comment this is the default branch; for pull_request it
# is the test merge commit of a same-repo PR. Either way the
# .github/scorecard scripts executed below come from the base
# repository, never from a fork.
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
with:
bun-version: latest
- name: Determine changed modules
id: changed
env:
PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }}
# Fetch GitHub's test merge commit (PR head merged into current
# main) so FETCH_HEAD^1 is the exact main tip this PR is applied
# to and the diff is precisely what the PR changes. Diffing against
# github.event.pull_request.base.sha is wrong: that SHA is the base
# tip from when the PR was opened, so on stale PRs it picks up every
# module merged to main since the PR branched and scores unrelated
# modules (REG-74).
run: |
git fetch --depth=2 origin "refs/pull/${PR_NUMBER}/merge"
# Module specs are namespace/name (for example coder/git-clone or
# droopy4096/mise-install) so community-namespace modules are
# scored too, not just registry/coder.
MODULES=$(git diff --name-only FETCH_HEAD^1 FETCH_HEAD | { grep -oP '^registry/\K[^/]+/modules/[^/]+' || true; } | sed 's#/modules/#/#' | sort -u | paste -sd, -)
echo "modules=${MODULES}" >> "${GITHUB_OUTPUT}"
echo "pr=${PR_NUMBER}" >> "${GITHUB_OUTPUT}"
echo "Changed modules: ${MODULES:-none}"
- name: Materialize PR module content (data only)
if: steps.changed.outputs.modules != ''
# Overlay the registry/ tree from the PR merge commit onto the
# trusted checkout. The scoring script reads these files as plain
# text for the LLM prompt; it never executes them. Everything under
# .github/ stays at the trusted base. A literal pathspec is used
# because wildcard pathspecs (registry/*/modules) do not
# directory-prefix match and fail to match any files.
run: |
git rm -rq --ignore-unmatch registry
git checkout FETCH_HEAD -- registry
- name: Score changed modules
if: steps.changed.outputs.modules != ''
env:
ANTHROPIC_API_KEY: ${{ secrets.SCORECARD_ANTHROPIC_API_KEY }}
GITHUB_DISCUSSIONS_TOKEN: ${{ github.token }}
MODULES: ${{ steps.changed.outputs.modules }}
run: bun run .github/scorecard/score-modules.ts --modules "${MODULES}" --pr-report /tmp/scorecard-report.md
- name: Upsert PR comment
if: steps.changed.outputs.modules != ''
env:
GH_TOKEN: ${{ github.token }}
PR_NUMBER: ${{ steps.changed.outputs.pr }}
run: |
# No report means every changed module was skipped (for example,
# internal building blocks); leave no comment in that case.
if [[ ! -s /tmp/scorecard-report.md ]]; then
echo "No scorecard report generated; skipping comment."
exit 0
fi
MARKER="<!-- module-scorecard-pr -->"
COMMENT_ID=$(gh api "repos/${GITHUB_REPOSITORY}/issues/${PR_NUMBER}/comments" --paginate --jq ".[] | select(.body | contains(\"${MARKER}\")) | .id" | head -1)
if [[ -n "${COMMENT_ID}" ]]; then
gh api --method PATCH "repos/${GITHUB_REPOSITORY}/issues/comments/${COMMENT_ID}" -F body=@/tmp/scorecard-report.md > /dev/null
echo "Updated comment ${COMMENT_ID}"
else
gh api "repos/${GITHUB_REPOSITORY}/issues/${PR_NUMBER}/comments" -F body=@/tmp/scorecard-report.md > /dev/null
echo "Created comment"
fi