ci: skip cla for signed contributors
This commit is contained in:
+117
-3
@@ -4,7 +4,7 @@ on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
pull_request_target:
|
||||
types: [opened, closed, synchronize]
|
||||
types: [opened, synchronize]
|
||||
|
||||
permissions:
|
||||
actions: write
|
||||
@@ -16,14 +16,128 @@ jobs:
|
||||
cla:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check stored CLA signatures
|
||||
id: cla_state
|
||||
if: github.event_name == 'pull_request_target'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const signaturePath = "signatures/cla.json";
|
||||
const signatureBranch = "dev";
|
||||
const allowlist = [
|
||||
"code-yeongyu",
|
||||
"bot*",
|
||||
"dependabot*",
|
||||
"github-actions*",
|
||||
"*[bot]",
|
||||
"sisyphus-dev-ai",
|
||||
"web-flow",
|
||||
];
|
||||
|
||||
const matchesAllowlist = (login) => {
|
||||
const normalizedLogin = login.toLowerCase();
|
||||
|
||||
return allowlist.some((entry) => {
|
||||
const pattern = entry.toLowerCase();
|
||||
|
||||
if (pattern.startsWith("*")) {
|
||||
return normalizedLogin.endsWith(pattern.slice(1));
|
||||
}
|
||||
|
||||
if (pattern.endsWith("*")) {
|
||||
return normalizedLogin.startsWith(pattern.slice(0, -1));
|
||||
}
|
||||
|
||||
return normalizedLogin === pattern;
|
||||
});
|
||||
};
|
||||
|
||||
const { owner, repo } = context.repo;
|
||||
const pullNumber = context.payload.pull_request.number;
|
||||
|
||||
const [signatureFile, commits] = await Promise.all([
|
||||
github.rest.repos.getContent({
|
||||
owner,
|
||||
repo,
|
||||
path: signaturePath,
|
||||
ref: signatureBranch,
|
||||
}),
|
||||
github.paginate(github.rest.pulls.listCommits, {
|
||||
owner,
|
||||
repo,
|
||||
pull_number: pullNumber,
|
||||
per_page: 100,
|
||||
}),
|
||||
]);
|
||||
|
||||
if (Array.isArray(signatureFile.data) || signatureFile.data.type !== "file") {
|
||||
core.setFailed(`${signaturePath} is not a file on ${signatureBranch}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const signatureContent = Buffer.from(
|
||||
signatureFile.data.content,
|
||||
signatureFile.data.encoding,
|
||||
).toString("utf8");
|
||||
const signatures = JSON.parse(signatureContent);
|
||||
const signedContributors = Array.isArray(signatures.signedContributors)
|
||||
? signatures.signedContributors
|
||||
: [];
|
||||
const signedIds = new Set(
|
||||
signedContributors
|
||||
.map((contributor) => Number(contributor.id))
|
||||
.filter((id) => Number.isFinite(id)),
|
||||
);
|
||||
const signedNames = new Set(
|
||||
signedContributors
|
||||
.map((contributor) => String(contributor.name || "").toLowerCase())
|
||||
.filter(Boolean),
|
||||
);
|
||||
const contributors = new Map();
|
||||
|
||||
for (const commit of commits) {
|
||||
if (commit.author?.login && commit.author?.id) {
|
||||
contributors.set(commit.author.login, {
|
||||
id: commit.author.id,
|
||||
login: commit.author.login,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const unsigned = [...contributors.values()].filter((contributor) => {
|
||||
const login = contributor.login.toLowerCase();
|
||||
|
||||
return (
|
||||
!matchesAllowlist(contributor.login) &&
|
||||
!signedIds.has(contributor.id) &&
|
||||
!signedNames.has(login)
|
||||
);
|
||||
});
|
||||
|
||||
core.setOutput("needs_cla_action", unsigned.length > 0 ? "true" : "false");
|
||||
|
||||
if (unsigned.length > 0) {
|
||||
core.info(
|
||||
`CLA Assistant needed for unsigned contributors: ${unsigned
|
||||
.map((contributor) => contributor.login)
|
||||
.join(", ")}`,
|
||||
);
|
||||
} else {
|
||||
core.info("All linked commit authors already signed the CLA or are allowlisted.");
|
||||
}
|
||||
|
||||
- name: CLA Assistant
|
||||
if: (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'
|
||||
if: >-
|
||||
(github.event_name == 'issue_comment' &&
|
||||
(github.event.comment.body == 'recheck' ||
|
||||
github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA')) ||
|
||||
steps.cla_state.outputs.needs_cla_action == 'true'
|
||||
uses: contributor-assistant/github-action@v2.6.1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
path-to-signatures: 'signatures/cla.json'
|
||||
path-to-document: 'https://github.com/code-yeongyu/oh-my-opencode/blob/master/CLA.md'
|
||||
path-to-document: 'https://github.com/code-yeongyu/oh-my-openagent/blob/dev/CLA.md'
|
||||
branch: 'dev'
|
||||
allowlist: code-yeongyu,bot*,dependabot*,github-actions*,*[bot],sisyphus-dev-ai,web-flow
|
||||
custom-notsigned-prcomment: |
|
||||
|
||||
Reference in New Issue
Block a user