-
Notifications
You must be signed in to change notification settings - Fork 154
Expand file tree
/
Copy pathcontributor-agreement-check.yml
More file actions
139 lines (115 loc) · 5.46 KB
/
contributor-agreement-check.yml
File metadata and controls
139 lines (115 loc) · 5.46 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
name: Check Contributor Agreement
on:
pull_request:
types: [opened, synchronize, reopened]
permissions:
contents: read
pull-requests: write # Needed to comment on PRs
jobs:
check-contributor-agreement:
runs-on: ubuntu-latest
steps:
- name: Check if user is a maintainer
id: check-maintainer
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const { owner, repo } = context.repo;
const username = context.payload.pull_request.user.login;
try {
const { data: permission } = await github.rest.repos.getCollaboratorPermissionLevel({
owner,
repo,
username,
});
// Skip check for users with admin or write permissions
if (['admin', 'write'].includes(permission.permission)) {
console.log(`User ${username} is a maintainer with ${permission.permission} permissions. Skipping check.`);
return true;
}
console.log(`User ${username} has ${permission.permission} permissions. Continuing with check.`);
return false;
} catch (error) {
console.log(`Error checking permissions: ${error}`);
return false;
}
- name: Checkout code
if: steps.check-maintainer.outputs.result != 'true'
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0
- name: Check for contributor agreement
if: steps.check-maintainer.outputs.result != 'true'
id: check-agreement
run: |
# Get the PR author's username
PR_AUTHOR="${{ github.event.pull_request.user.login }}"
echo "PR author: $PR_AUTHOR"
# Check if contributor agreement file exists
AGREEMENT_FILE=".github/contributors/${PR_AUTHOR}.md"
if [ -f "$AGREEMENT_FILE" ]; then
echo "✅ Contributor agreement file found: $AGREEMENT_FILE"
# Check if file is not empty and contains the username
if [ ! -s "$AGREEMENT_FILE" ]; then
echo "❌ Contributor agreement file is empty"
exit 1
fi
if ! grep -q "$PR_AUTHOR" "$AGREEMENT_FILE"; then
echo "❌ Contributor agreement file does not contain the contributor's username"
exit 1
fi
echo "✅ Contributor agreement file is valid"
else
echo "❌ No contributor agreement file found for $PR_AUTHOR"
echo "Please create a file at .github/contributors/${PR_AUTHOR}.md with the filled-in contributor agreement."
echo "See .github/CONTRIBUTOR_AGREEMENT.md for the template."
exit 1
fi
- name: Check for deleted contributor agreements
if: steps.check-maintainer.outputs.result != 'true'
id: check-deleted
run: |
# Set proper base ref
git fetch origin ${{ github.base_ref }}
# Get the list of deleted files in this PR
DELETED_FILES=$(git diff --name-only --diff-filter=D origin/${{ github.base_ref }} HEAD | grep -E "^.github/contributors/.*\.md$" || true)
if [ -n "$DELETED_FILES" ]; then
echo "❌ The following contributor agreement files are being deleted in this PR:"
echo "$DELETED_FILES"
echo "Deletion of contributor agreement files is not allowed."
exit 1
else
echo "✅ No contributor agreement files are being deleted."
fi
- name: Comment on PR if checks fail
if: ${{ failure() && steps.check-maintainer.outputs.result != 'true' }}
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const author = context.payload.pull_request.user.login;
let message = '';
if ('${{ steps.check-agreement.outcome }}' === 'failure') {
message = `Hi @${author}! 👋
Thank you for your contribution! We require all contributors to sign our Contributor Agreement.
Please:
1. Read the [Contributor Agreement](.github/CONTRIBUTOR_AGREEMENT.md)
2. Fill in the required information (make sure to include your GitHub username: ${author})
3. Add the filled-in version as \`.github/contributors/${author}.md\` to this PR
This helps ensure all contributions are properly licensed. Thanks for your understanding!`;
}
if ('${{ steps.check-deleted.outcome }}' === 'failure') {
message = `Hi @${author}! 👋
Your PR is attempting to delete one or more contributor agreement files. This is not allowed.
Please restore the deleted files and update your PR. If you believe this is in error, please contact a maintainer.`;
}
if (message) {
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: message
});
}