1
- name : CLA Signature Recorder
1
+ name : CLA Approval Handler
2
2
3
3
on :
4
- pull_request_target :
5
- types : [labeled ]
4
+ issue_comment :
5
+ types : [created ]
6
6
7
7
permissions : write-all
8
8
9
9
jobs :
10
- record -cla-signature :
10
+ process -cla-comment :
11
11
runs-on : ubuntu-latest
12
- if : github.event.label.name == 'cla-signed ' && github.actor != 'workflow-authentication-public[bot]'
12
+ if : github.event_name == 'issue_comment ' && github.actor != 'workflow-authentication-public[bot]'
13
13
14
14
steps :
15
-
16
15
- name : Generate Token
17
16
id : generate-token
18
17
continue-on-error : true
@@ -21,48 +20,173 @@ jobs:
21
20
app-id : " ${{ secrets.WORKFLOW_AUTH_PUBLIC_APP_ID }}"
22
21
private-key : " ${{ secrets.WORKFLOW_AUTH_PUBLIC_PRIVATE_KEY }}"
23
22
24
- - name : Check out code
25
- uses : actions/checkout@v4
26
- with :
27
- fetch-depth : 0
28
- token : ${{ steps.generate-token.outputs.token || secrets.GITHUB_TOKEN }}
29
-
30
- - name : Extract PR Information
31
- id : pr-info
23
+ - name : Process CLA Agreement Comment
24
+ id : process-comment
32
25
uses : actions/github-script@v7
33
26
with :
34
27
github-token : ${{ steps.generate-token.outputs.token || secrets.GITHUB_TOKEN }}
35
28
script : |
36
- // Extract PR details from the event
37
- const prNumber = context.payload.pull_request.number;
38
- const prAuthor = context.payload.pull_request.user.login;
39
- const approvedBy = context.actor;
29
+ // Only process comments on pull requests
30
+ if (!context.payload.issue.pull_request) {
31
+ console.log('Comment is not on a pull request, skipping...');
32
+ return;
33
+ }
34
+
35
+ const prNumber = context.payload.issue.number;
36
+ const commentBody = context.payload.comment.body;
37
+ const commenter = context.payload.comment.user.login;
38
+
39
+ console.log(`Processing comment on PR #${prNumber} from ${commenter}`);
40
+
41
+ // Check if this is a CLA agreement comment
42
+ const isClaAgreement = commentBody.includes('I agree to the Trademark License Addendum') &&
43
+ commentBody.includes('CLA-SIGNATURE:');
44
+
45
+ if (!isClaAgreement) {
46
+ console.log('Comment is not a CLA agreement, skipping...');
47
+ return;
48
+ }
49
+
50
+ console.log('Found CLA agreement comment, validating...');
51
+
52
+ // Extract the signature from the comment
53
+ const signatureMatch = commentBody.match(/CLA-SIGNATURE:\s*(\S+)/);
54
+ if (!signatureMatch) {
55
+ console.log('CLA signature format is invalid');
56
+ return;
57
+ }
58
+
59
+ const signatureUser = signatureMatch[1];
60
+
61
+ // Get PR details to verify the commenter is the PR author
62
+ const { data: pr } = await github.rest.pulls.get({
63
+ owner: context.repo.owner,
64
+ repo: context.repo.repo,
65
+ pull_number: prNumber
66
+ });
67
+
68
+ const prAuthor = pr.user.login;
69
+ console.log(`PR author: ${prAuthor}, commenter: ${commenter}, signature: ${signatureUser}`);
70
+
71
+ // If someone other than PR author is trying to sign, silently ignore
72
+ if (commenter !== prAuthor) {
73
+ console.log(`Comment with CLA text from ${commenter} (not PR author ${prAuthor}), ignoring silently`);
74
+ return;
75
+ }
76
+
77
+ // If PR author is signing but signature doesn't match their username, silently ignore
78
+ if (signatureUser !== commenter) {
79
+ console.log(`PR author ${commenter} used incorrect signature '${signatureUser}', ignoring silently`);
80
+ return;
81
+ }
40
82
41
- console.log(`Recording CLA signature for PR #${prNumber}`);
42
- console.log(`PR Author: ${prAuthor}`);
43
- console.log(`Approved by: ${approvedBy}`);
83
+ // Check if PR has trademark-addendum-required label
84
+ const { data: labels } = await github.rest.issues.listLabelsOnIssue({
85
+ owner: context.repo.owner,
86
+ repo: context.repo.repo,
87
+ issue_number: prNumber
88
+ });
44
89
45
- // Store the information for the signature recording step
90
+ const hasTrademarkRequired = labels.some(label => label.name === 'trademark-addendum-required');
91
+ const hasTrademarkSigned = labels.some(label => label.name === 'trademark-addendum-signed');
92
+
93
+ if (!hasTrademarkRequired) {
94
+ console.log('PR does not have trademark-addendum-required label, skipping...');
95
+ return;
96
+ }
97
+
98
+ if (hasTrademarkSigned) {
99
+ console.log('PR already has trademark-addendum-signed label, skipping...');
100
+ return;
101
+ }
102
+
103
+ console.log('Valid CLA agreement from PR author, processing...');
104
+
105
+ // Remove blocking labels
106
+ try {
107
+ await github.rest.issues.removeLabel({
108
+ owner: context.repo.owner,
109
+ repo: context.repo.repo,
110
+ issue_number: prNumber,
111
+ name: 'trademark-addendum-required'
112
+ });
113
+ console.log('Removed trademark-addendum-required label');
114
+ } catch (e) {
115
+ console.log('trademark-addendum-required label not found or already removed');
116
+ }
117
+
118
+ try {
119
+ await github.rest.issues.removeLabel({
120
+ owner: context.repo.owner,
121
+ repo: context.repo.repo,
122
+ issue_number: prNumber,
123
+ name: 'integrations-with-image-change'
124
+ });
125
+ console.log('Removed integrations-with-image-change label');
126
+ } catch (e) {
127
+ console.log('integrations-with-image-change label not found or already removed');
128
+ }
129
+
130
+ // Add trademark-addendum-signed label
131
+ await github.rest.issues.addLabels({
132
+ owner: context.repo.owner,
133
+ repo: context.repo.repo,
134
+ issue_number: prNumber,
135
+ labels: ['trademark-addendum-signed']
136
+ });
137
+
138
+ console.log('Added trademark-addendum-signed label successfully');
139
+
140
+ // Store the signature information for the next step
46
141
core.setOutput('pr_number', prNumber);
47
142
core.setOutput('pr_author', prAuthor);
48
- core.setOutput('approved_by', approvedBy);
143
+ core.setOutput('approved_by', prAuthor); // Self-signed agreement
144
+
145
+ // Add confirmation comment
146
+ const confirmationBody = [
147
+ '## Trademark license agreement confirmed ✅',
148
+ '',
149
+ `The trademark license agreement has been confirmed for @${prAuthor}.`,
150
+ '',
151
+ '**Status:** Confirmed',
152
+ `**Date:** ${new Date().toISOString()}`,
153
+ '**Method:** Self-signed agreement via comment',
154
+ '',
155
+ 'This PR is now unblocked and can proceed with normal review.'
156
+ ].join('\n');
157
+
158
+ await github.rest.issues.createComment({
159
+ owner: context.repo.owner,
160
+ repo: context.repo.repo,
161
+ issue_number: prNumber,
162
+ body: confirmationBody
163
+ });
164
+
165
+ console.log(`✅ CLA agreement processed successfully for ${prAuthor} - proceeding to record signature`);
166
+
167
+ - name : Check out code
168
+ if : success() && steps.process-comment.outputs.pr_number != ''
169
+ uses : actions/checkout@v4
170
+ with :
171
+ fetch-depth : 0
172
+ token : ${{ steps.generate-token.outputs.token || secrets.GITHUB_TOKEN }}
49
173
50
174
- name : Record CLA Signature
51
- if : success() && steps.pr-info .outputs.pr_number != ''
175
+ if : success() && steps.process-comment .outputs.pr_number != ''
52
176
run : |
53
177
set -e # Exit on any error
54
178
55
179
echo "=== Recording CLA signature ==="
56
180
echo "Available outputs:"
57
- echo " pr_number: '${{ steps.pr-info .outputs.pr_number }}'"
58
- echo " pr_author: '${{ steps.pr-info .outputs.pr_author }}'"
59
- echo " approved_by: '${{ steps.pr-info .outputs.approved_by }}'"
181
+ echo " pr_number: '${{ steps.process-comment .outputs.pr_number }}'"
182
+ echo " pr_author: '${{ steps.process-comment .outputs.pr_author }}'"
183
+ echo " approved_by: '${{ steps.process-comment .outputs.approved_by }}'"
60
184
61
185
# Extract signature details
62
- USERNAME="${{ steps.pr-info .outputs.pr_author }}"
186
+ USERNAME="${{ steps.process-comment .outputs.pr_author }}"
63
187
DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
64
- PR_NUMBER="${{ steps.pr-info .outputs.pr_number }}"
65
- APPROVED_BY="${{ steps.pr-info .outputs.approved_by }}"
188
+ PR_NUMBER="${{ steps.process-comment .outputs.pr_number }}"
189
+ APPROVED_BY="${{ steps.process-comment .outputs.approved_by }}"
66
190
67
191
# Validate required fields
68
192
if [ -z "$USERNAME" ] || [ -z "$PR_NUMBER" ] || [ -z "$APPROVED_BY" ]; then
73
197
exit 1
74
198
fi
75
199
76
- echo "Recording manual trademark addendum approval :"
200
+ echo "Recording CLA signature :"
77
201
echo " Username: $USERNAME"
78
202
echo " PR Number: $PR_NUMBER"
79
203
echo " Approved by: $APPROVED_BY"
@@ -202,4 +326,4 @@ jobs:
202
326
fi
203
327
fi
204
328
205
- echo "✅ Manual trademark addendum approval recorded successfully"
329
+ echo "✅ CLA signature recorded successfully for ${prAuthor} "
0 commit comments