Skip to content

Commit 56a41dd

Browse files
aconite33claude
andcommitted
Add CLA Assistant workflow
Port cla.yml from blacklanternsecurity/bbot so PRs against main can satisfy the org-level "Require CLA" ruleset, which gates merges on a CLAAssistant status check. Without this workflow nothing posts that status, so PRs are permanently blocked. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 4a4fd9e commit 56a41dd

1 file changed

Lines changed: 97 additions & 0 deletions

File tree

.github/workflows/cla.yml

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
name: "CLA Assistant"
2+
on:
3+
issue_comment:
4+
types: [created]
5+
pull_request_target:
6+
types: [opened, closed, synchronize]
7+
8+
permissions:
9+
pull-requests: write
10+
statuses: write
11+
12+
jobs:
13+
CLAAssistant:
14+
runs-on: ubuntu-latest
15+
steps:
16+
- name: Generate token from GitHub App
17+
id: app-token
18+
uses: actions/create-github-app-token@v1
19+
with:
20+
app-id: ${{ secrets.APP_ID }}
21+
private-key: ${{ secrets.APP_PRIVATE_KEY }}
22+
owner: blacklanternsecurity
23+
24+
- name: Check all committers against org and allowlist
25+
id: cla-check
26+
env:
27+
GH_TOKEN: ${{ steps.app-token.outputs.token }}
28+
run: |
29+
if [ "${{ github.event_name }}" = "pull_request_target" ]; then
30+
PR_NUM="${{ github.event.pull_request.number }}"
31+
else
32+
PR_NUM="${{ github.event.issue.number }}"
33+
fi
34+
35+
COMMITTERS=$(gh api "repos/${{ github.repository }}/pulls/$PR_NUM/commits" --paginate --jq '.[].author.login' | sort -u)
36+
ALL_EXEMPT=true
37+
38+
for LOGIN in $COMMITTERS; do
39+
# treat commits with no associated GitHub login as non-exempt
40+
if [ -z "$LOGIN" ] || [ "$LOGIN" = "null" ]; then
41+
echo "Unknown committer (no GitHub login) — not exempt"
42+
ALL_EXEMPT=false
43+
break
44+
fi
45+
46+
EXEMPT=false
47+
48+
# check if account type is Bot (GitHub App accounts)
49+
AUTHOR_TYPE=$(gh api "users/${LOGIN}" --jq '.type' 2>/dev/null || echo "Unknown")
50+
if [ "$AUTHOR_TYPE" = "Bot" ]; then
51+
echo "$LOGIN is a Bot account — exempt"
52+
EXEMPT=true
53+
fi
54+
55+
# check org membership
56+
if [ "$EXEMPT" = "false" ]; then
57+
if gh api "orgs/blacklanternsecurity/members/$LOGIN" > /dev/null 2>&1; then
58+
echo "$LOGIN is an org member — exempt"
59+
EXEMPT=true
60+
fi
61+
fi
62+
63+
if [ "$EXEMPT" = "false" ]; then
64+
echo "$LOGIN is not exempt — CLA required"
65+
ALL_EXEMPT=false
66+
break
67+
fi
68+
done
69+
70+
echo "all_exempt=$ALL_EXEMPT" >> "$GITHUB_OUTPUT"
71+
72+
- name: Skip CLA when all committers are exempt
73+
if: steps.cla-check.outputs.all_exempt == 'true' && github.event_name == 'pull_request_target'
74+
env:
75+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
76+
run: |
77+
gh api --method POST "repos/${{ github.repository }}/statuses/${{ github.event.pull_request.head.sha }}" \
78+
-f state=success \
79+
-f context="CLAAssistant" \
80+
-f description="CLA check skipped — all committers are org members or bots"
81+
82+
- name: "CLA Assistant"
83+
if: |
84+
(steps.cla-check.outputs.all_exempt != 'true') &&
85+
((github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target')
86+
uses: contributor-assistant/github-action@v2.6.1
87+
env:
88+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
89+
PERSONAL_ACCESS_TOKEN: ${{ steps.app-token.outputs.token }}
90+
with:
91+
path-to-signatures: "signatures/version1/cla.json"
92+
path-to-document: "https://github.com/blacklanternsecurity/CLA/blob/main/ICLA.md"
93+
branch: "main"
94+
allowlist: "dependabot[bot],github-actions[bot],renovate[bot]"
95+
remote-organization-name: "blacklanternsecurity"
96+
remote-repository-name: "CLA"
97+
lock-pullrequest-aftermerge: "false"

0 commit comments

Comments
 (0)