Skip to content

Commit 12247f7

Browse files
Simplify CLA gate workflow
1 parent d93b381 commit 12247f7

1 file changed

Lines changed: 62 additions & 83 deletions

File tree

.github/workflows/cla-gate.yml

Lines changed: 62 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,106 +1,85 @@
11
name: CLA Gate
22

3-
# This workflow publishes a repository-owned commit status named `CLA Gate`.
4-
# Make `CLA Gate` required instead of requiring CLA Assistant's raw `license/cla`
5-
# status directly. That lets merge queue entries pass without waiting for CLA
6-
# Assistant to report on the synthetic merge-group SHA, while pull requests still
7-
# mirror the real CLA Assistant result.
3+
# Make this Actions check required instead of requiring CLA Assistant's raw
4+
# `license/cla` status directly. Merge queue entries pass without waiting for
5+
# CLA Assistant on the synthetic merge-group SHA, while pull requests use
6+
# `cargo ci cla-assistant status` to follow the real CLA Assistant result.
87
#
9-
# SECURITY: This workflow uses pull_request_target so it can publish commit
10-
# statuses on external PRs. It must never check out, build, or execute PR code.
8+
# SECURITY: This workflow uses pull_request_target so it can read statuses on
9+
# external PRs. It must never check out, build, or execute PR code.
1110

1211
on:
1312
pull_request_target:
14-
types: [opened, reopened]
15-
status:
13+
types: [opened, reopened, synchronize, ready_for_review]
1614
merge_group:
1715

1816
permissions:
1917
contents: read
20-
pull-requests: read
21-
statuses: write
18+
statuses: read
19+
20+
concurrency:
21+
group: cla-gate-${{ github.event.pull_request.number || github.sha }}
22+
cancel-in-progress: true
2223

2324
jobs:
24-
publish-cla-gate-status:
25-
name: CLA status
25+
cla-gate:
26+
name: CLA Gate
2627
runs-on: ubuntu-latest
27-
if: github.event_name != 'status' || github.event.context == 'license/cla'
2828

2929
steps:
30+
- name: Skip CLA check for merge queue
31+
if: ${{ github.event_name == 'merge_group' }}
32+
run: echo "Merge group entry; CLA was checked before entering the queue."
33+
3034
- name: Check out trusted base code
35+
if: ${{ github.event_name == 'pull_request_target' }}
3136
uses: actions/checkout@v4
3237
with:
3338
ref: ${{ github.event.repository.default_branch }}
3439

35-
- uses: dsherret/rust-toolchain-file@v1
40+
- name: Set up Rust
41+
if: ${{ github.event_name == 'pull_request_target' }}
42+
uses: dsherret/rust-toolchain-file@v1
3643

37-
- name: Publish CLA Gate status
38-
uses: actions/github-script@v7
44+
- name: Follow CLA Assistant status
45+
if: ${{ github.event_name == 'pull_request_target' }}
3946
env:
4047
GITHUB_TOKEN: ${{ github.token }}
41-
with:
42-
script: |
43-
const { execFileSync } = require("child_process");
44-
45-
function claStatus(args) {
46-
const output = execFileSync("cargo", ["ci", "cla-assistant", "status", ...args], {
47-
encoding: "utf8",
48-
env: process.env,
49-
});
50-
return JSON.parse(output);
51-
}
52-
53-
async function postStatus({ sha, state, description, targetUrl }) {
54-
const statusContext = "CLA Gate";
55-
core.info(
56-
`Publishing ${statusContext}=${state} for ${sha}: ${description}`
57-
);
58-
59-
await github.rest.repos.createCommitStatus({
60-
owner: context.repo.owner,
61-
repo: context.repo.repo,
62-
sha,
63-
state,
64-
description,
65-
context: statusContext,
66-
target_url: targetUrl,
67-
});
68-
}
69-
70-
let targetSha;
71-
let claStatusArgs;
72-
73-
if (context.eventName === "merge_group") {
74-
await postStatus({
75-
sha: process.env.GITHUB_SHA,
76-
state: "success",
77-
description: "Merge group entry; CLA already checked before queue",
78-
});
79-
return;
80-
}
81-
82-
if (context.eventName === "status") {
83-
targetSha = context.payload.sha;
84-
claStatusArgs = ["--sha", targetSha];
85-
} else if (context.eventName === "pull_request_target") {
86-
const pr = context.payload.pull_request;
87-
targetSha = pr.head.sha;
88-
claStatusArgs = ["--pr", String(pr.number)];
89-
} else {
90-
core.setFailed(`Unsupported event type: ${context.eventName}`);
91-
return;
92-
}
93-
94-
const status = claStatus(claStatusArgs);
95-
96-
if (!status.state) {
97-
core.info(`No CLA Gate status to publish for ${targetSha}`);
98-
return;
99-
}
100-
101-
await postStatus({
102-
sha: targetSha,
103-
state: status.state,
104-
description: status.description || undefined,
105-
targetUrl: status.target_url || undefined,
106-
});
48+
PR_NUMBER: ${{ github.event.pull_request.number }}
49+
run: |
50+
set -euo pipefail
51+
52+
for attempt in $(seq 1 30); do
53+
status_json="$(cargo ci cla-assistant status --pr "${PR_NUMBER}")"
54+
state="$(jq -r '.state // "missing"' <<<"${status_json}")"
55+
description="$(jq -r '.description // ""' <<<"${status_json}")"
56+
target_url="$(jq -r '.target_url // ""' <<<"${status_json}")"
57+
58+
echo "license/cla is ${state}: ${description}"
59+
case "${state}" in
60+
success)
61+
exit 0
62+
;;
63+
pending|missing)
64+
;;
65+
failure|error)
66+
if [ -n "${target_url}" ]; then
67+
echo "::error title=license/cla ${state}::${description} (${target_url})"
68+
else
69+
echo "::error title=license/cla ${state}::${description}"
70+
fi
71+
exit 1
72+
;;
73+
*)
74+
echo "::error::Unexpected license/cla state: ${state}"
75+
exit 1
76+
;;
77+
esac
78+
79+
if [ "${attempt}" -lt 30 ]; then
80+
sleep 10
81+
fi
82+
done
83+
84+
echo "::error::Timed out waiting for license/cla to succeed."
85+
exit 1

0 commit comments

Comments
 (0)