-
-
Notifications
You must be signed in to change notification settings - Fork 206
198 lines (194 loc) · 10.7 KB
/
Copy pathcla.yml
File metadata and controls
198 lines (194 loc) · 10.7 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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# .github/workflows/cla.yml -- goes in EACH library repo.
# Blocks a PR from merging until every human commit-author has signed the
# Contributor Assignment Agreement (CAA). Signatures are recorded per GitHub
# user in one central file, so a person signs once and it counts everywhere.
#
# Contributors sign by posting this exact comment ON THEIR PULL REQUEST:
# I have read the CAA and I hereby sign it, assigning copyright in my
# contributions to Más Bandwidth LLC.
#
# REQUIRES a repo or org secret named CLA_SIGNATURES_TOKEN (a fine-grained or
# classic PAT with contents + pull-requests write on the library repos and on
# mas-bandwidth/.github). The built-in GITHUB_TOKEN is read-only for pull
# requests from forks, which is exactly the case we need to gate, so the PAT is
# required. Do not commit the token, add it in repo/org Settings -> Secrets.
#
# ---------------------------------------------------------------------------
# SCOPE AND LIMITS OF THIS AUTOMATION -- read before changing this file.
#
# contributor-assistant/github-action is PULL-REQUEST-ONLY BY DESIGN. The first
# thing it does is a GraphQL query for `repository.pullRequest(number: N)` in
# order to list that PR's commit authors; its whole data model is "which commit
# authors on this PR have signed". A plain issue has no pull request and no
# commits, so the query fails with
#
# graphql call to get the committers details failed: GraphqlError:
# Could not resolve to a PullRequest with the number of N
#
# and the run dies there, before it ever looks at the comments. That is not a
# misconfiguration on our side and it cannot be fixed from this file. It will
# not be fixed upstream either: the action's repository is ARCHIVED and v2.6.1
# (2024-09-26) is the last release it will ever have.
#
# LIMIT 1 -- A SIGNATURE POSTED ON AN ISSUE IS NEVER RECORDED AUTOMATICALLY.
# The check below is therefore gated to pull requests, so issue threads stop
# showing a spurious failed run. A signature posted on an issue is still a valid
# signature; it just has to be entered by hand (see RECORDING BY HAND).
#
# LIMIT 2 -- THE SIGNATURE TEST IS EXACT STRING EQUALITY.
# Because `custom-pr-sign-comment` is set, the action matches signatures with
# getCustomPrSignComment().toLowerCase() === comment.trim().toLowerCase()
# (src/pullrequest/signatureComment.ts). Anything extra -- a footnote, a version
# pin, a trailing remark -- is not a match. The action does have a permissive
# "contains" mode, but it is reachable only when `custom-pr-sign-comment` is
# left empty, and its pattern is hardcoded to CLA Assistant's own default
# wording ("I have read the CLA Document and I hereby sign the CLA"). Custom
# wording and substring matching are mutually exclusive; we need our own
# wording, so we are on the exact-equality branch and cannot leave it.
# A signature carrying extra text is still valid under Más Bandwidth policy
# (version-pinned signatures were expressly ruled acceptable on 2026-07-24), so
# it too must be recorded by hand.
# One narrow variant does recover on its own: the action trims and lowercases
# both sides before comparing, while the gate below is exact, so a signature
# differing only in capitalisation or surrounding whitespace satisfies the
# action but never reaches it. Commenting `recheck` re-runs the action, which
# then finds that comment and records it normally.
#
# The second step below exists only to make both of those cases LOUD instead of
# silent. It records nothing and writes nowhere; it raises a warning so that a
# maintainer notices and records the signature manually.
#
# RECORDING A SIGNATURE BY HAND
# Append one object to signatures/caa.json on the `cla-signatures` branch of
# mas-bandwidth/.github, in the same shape the action writes:
#
# {"name": "<github login>", "id": <numeric user id>,
# "comment_id": <id of the signing comment>,
# "created_at": "<comment created_at, ISO 8601>",
# "repoId": <numeric repo id>, "pullRequestNo": <issue or PR number>}
#
# The ids come from the comment itself, e.g.
# gh api repos/mas-bandwidth/<repo>/issues/<n>/comments \
# --jq '.[] | {comment_id: .id, name: .user.login, id: .user.id,
# created_at}'
# gh api repos/mas-bandwidth/<repo> --jq .id
# Commit it with a message naming the signer and the thread, so the ledger's
# history stays auditable.
#
# Then, if a pull request is sitting red waiting on that signature, comment
# `recheck` on it. That re-runs the check against the updated ledger and turns
# it green. Nothing else re-evaluates an already-open pull request short of
# pushing another commit to it, and that is true of every route into the
# ledger, not just manual ones: the ledger is org-wide, so a contributor who
# signs on one pull request leaves any other open pull request of theirs red
# until it is rechecked.
# ---------------------------------------------------------------------------
name: Contributor Assignment Agreement
on:
issue_comment:
types: [created]
pull_request_target:
types: [opened, synchronize]
permissions:
actions: write
contents: read
pull-requests: write
statuses: write
jobs:
caa:
runs-on: ubuntu-latest
steps:
# Pull requests only. `github.event.issue.pull_request` is present only
# when an issue_comment was posted on a PR; on a plain issue it is null
# and the action would abort (see LIMIT 1 above).
#
# `recheck` re-runs the check; it records nothing by itself, it just makes
# the action re-read this PR's commit authors and the ledger and restate
# the verdict. It has to be accepted here because the action advertises it
# unprompted -- `suggest-recheck` defaults to true, so every "please sign"
# comment it posts ends with "You can retrigger this bot by commenting
# recheck in this Pull Request". Without this clause that instruction is
# dead: the comment arrives, no `if` matches, the job never starts, and
# the contributor gets no run, no log and no error. It is also the only
# way to clear a red check after a signature is recorded by hand.
- name: CAA check
if: >-
github.event_name == 'pull_request_target' ||
(github.event.issue.pull_request != null &&
(github.event.comment.body == 'I have read the CAA and I hereby sign it, assigning copyright in my contributions to Más Bandwidth LLC.' ||
github.event.comment.body == 'recheck'))
uses: contributor-assistant/github-action@v2.6.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PERSONAL_ACCESS_TOKEN: ${{ secrets.CLA_SIGNATURES_TOKEN }}
with:
# one central signature store for the whole org -> per-user tracking
remote-organization-name: mas-bandwidth
remote-repository-name: .github
branch: cla-signatures
path-to-signatures: signatures/caa.json
path-to-document: https://github.com/mas-bandwidth/.github/blob/main/CAA.md
# our own accounts and bots never need to sign
allowlist: gafferongames,rowan-claude,*[bot]
custom-notsigned-prcomment: 'Thanks for the contribution. Before it can be merged, please read the [Contributor Assignment Agreement](https://github.com/mas-bandwidth/.github/blob/main/CAA.md) and sign it by posting the exact sentence below as a comment on this PR.'
custom-pr-sign-comment: 'I have read the CAA and I hereby sign it, assigning copyright in my contributions to Más Bandwidth LLC.'
custom-allsigned-prcomment: 'All contributors have signed the CAA. Thank you.'
lock-pullrequest-aftermerge: false
# Fires when a comment reads like a CAA signature but will not be picked
# up by the step above -- either it is on an issue rather than a pull
# request (LIMIT 1), or it carries extra text and so fails the action's
# exact-equality test (LIMIT 2). This step records nothing anywhere. It
# only raises a warning, so that a signature is never lost silently.
# Bots are skipped because the action's own "please sign" comment quotes
# the signature sentence verbatim; the two accounts below are skipped for
# the same reason as in `allowlist` above -- they are ours, and they quote
# signatures back when replying by email.
- name: Flag a signature the automation cannot record
if: >-
github.event_name == 'issue_comment' &&
github.event.comment.user.type != 'Bot' &&
github.event.comment.user.login != 'gafferongames' &&
github.event.comment.user.login != 'rowan-claude' &&
contains(github.event.comment.body, 'I hereby sign it, assigning copyright') &&
!(github.event.issue.pull_request != null &&
github.event.comment.body == 'I have read the CAA and I hereby sign it, assigning copyright in my contributions to Más Bandwidth LLC.')
env:
# via env, never inlined into the script: comment bodies are untrusted
SIGNER: ${{ github.event.comment.user.login }}
SIGNER_ID: ${{ github.event.comment.user.id }}
COMMENT_ID: ${{ github.event.comment.id }}
COMMENT_AT: ${{ github.event.comment.created_at }}
COMMENT_URL: ${{ github.event.comment.html_url }}
REPO_ID: ${{ github.event.repository.id }}
THREAD_NO: ${{ github.event.issue.number }}
IS_PR: ${{ github.event.issue.pull_request != null }}
run: |
set -euo pipefail
if [ "$IS_PR" = "true" ]; then
why="it carries text beyond the exact signature sentence"
else
why="it was posted on an issue rather than a pull request"
fi
printf '::warning title=CAA signature needs manual recording::%s appears to have signed the CAA, but it was NOT recorded automatically because %s. See %s\n' \
"$SIGNER" "$why" "$COMMENT_URL"
{
echo "### CAA signature needs manual recording"
echo
echo "\`$SIGNER\` appears to have signed the CAA, but the signature was **not** recorded automatically because $why."
echo
echo "Comment: $COMMENT_URL"
echo
echo "Review the comment. If it is a genuine signature, append this to"
echo "\`signatures/caa.json\` on the \`cla-signatures\` branch of \`mas-bandwidth/.github\`:"
echo
echo '```json'
echo "{"
echo " \"name\": \"$SIGNER\","
echo " \"id\": $SIGNER_ID,"
echo " \"comment_id\": $COMMENT_ID,"
echo " \"created_at\": \"$COMMENT_AT\","
echo " \"repoId\": $REPO_ID,"
echo " \"pullRequestNo\": $THREAD_NO"
echo "}"
echo '```'
} >> "$GITHUB_STEP_SUMMARY"