Skip to content

Commit d180319

Browse files
Pass CLA retry PR numbers from workflow
1 parent e458f91 commit d180319

2 files changed

Lines changed: 43 additions & 95 deletions

File tree

.github/workflows/retry-cla-assistant.yml

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,45 @@ jobs:
4343

4444
- uses: dsherret/rust-toolchain-file@v1
4545

46+
- name: Collect pull requests to check
47+
id: prs
48+
env:
49+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
50+
run: |
51+
pr_numbers="${RUNNER_TEMP}/cla-pr-numbers"
52+
53+
case "${GITHUB_EVENT_NAME}" in
54+
pull_request_target)
55+
jq -r '.pull_request.number' "${GITHUB_EVENT_PATH}" > "${pr_numbers}"
56+
;;
57+
workflow_run)
58+
if jq -e '.workflow_run.name == "Retry CLA Assistant"' "${GITHUB_EVENT_PATH}" > /dev/null; then
59+
: > "${pr_numbers}"
60+
else
61+
jq -r '.workflow_run.pull_requests[].number' "${GITHUB_EVENT_PATH}" > "${pr_numbers}"
62+
fi
63+
;;
64+
schedule)
65+
gh api --paginate "repos/${GITHUB_REPOSITORY}/pulls?state=open&base=master&per_page=100" --jq '.[].number' > "${pr_numbers}"
66+
;;
67+
workflow_dispatch)
68+
jq -r '.inputs.pr_number' "${GITHUB_EVENT_PATH}" > "${pr_numbers}"
69+
;;
70+
*)
71+
echo "unsupported event ${GITHUB_EVENT_NAME}" >&2
72+
exit 1
73+
;;
74+
esac
75+
76+
sort -n -u "${pr_numbers}" -o "${pr_numbers}"
77+
echo "path=${pr_numbers}" >> "${GITHUB_OUTPUT}"
78+
4679
- name: Recheck CLA Assistant
4780
env:
4881
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
49-
INPUT_PR_NUMBER: ${{ inputs.pr_number }}
50-
run: cargo ci retry-cla-assistant
82+
run: |
83+
while read -r pr_number; do
84+
if [ -n "${pr_number}" ]; then
85+
cargo ci retry-cla-assistant --pr-number "${pr_number}"
86+
fi
87+
done < "${{ steps.prs.outputs.path }}"

tools/ci/src/retry_cla_assistant.rs

Lines changed: 4 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
use std::collections::{BTreeMap, BTreeSet};
1+
use std::collections::BTreeMap;
22
use std::env;
3-
use std::fs;
43
use std::time::Duration;
54

65
use anyhow::{anyhow, bail, Context, Result};
@@ -10,7 +9,6 @@ use reqwest::blocking::Client;
109
use reqwest::header::{HeaderMap, HeaderValue, ACCEPT, AUTHORIZATION, USER_AGENT};
1110
use serde::de::DeserializeOwned;
1211
use serde::Deserialize;
13-
use serde_json::Value;
1412

1513
const CLA_CONTEXT: &str = "license/cla";
1614
const MIN_HEAD_AGE: Duration = Duration::from_secs(10 * 60);
@@ -19,9 +17,9 @@ const POLL_DELAY: Duration = Duration::from_secs(30);
1917

2018
#[derive(Args)]
2119
pub(crate) struct RetryClaAssistantArgs {
22-
/// Pull request number. If omitted, GitHub Actions event payloads are used.
20+
/// Pull request number to check.
2321
#[arg(long)]
24-
pub(crate) pr_number: Option<u64>,
22+
pub(crate) pr_number: u64,
2523

2624
/// Repository in `owner/name` form. Defaults to GITHUB_REPOSITORY.
2725
#[arg(long)]
@@ -39,71 +37,7 @@ pub(crate) fn run(args: RetryClaAssistantArgs) -> Result<()> {
3937
let token = env::var("GITHUB_TOKEN").context("GITHUB_TOKEN is required")?;
4038
let client = GithubClient::new(token)?;
4139

42-
let pr_numbers = candidate_pull_requests(&client, owner, repo_name, args.pr_number)?;
43-
if pr_numbers.is_empty() {
44-
println!("No pull request associated with this event; skipping.");
45-
return Ok(());
46-
}
47-
48-
for pr_number in pr_numbers {
49-
retry_for_pr(&client, owner, repo_name, pr_number)?;
50-
}
51-
52-
Ok(())
53-
}
54-
55-
fn candidate_pull_requests(client: &GithubClient, owner: &str, repo: &str, pr_number: Option<u64>) -> Result<Vec<u64>> {
56-
if let Some(pr_number) = pr_number {
57-
return Ok(vec![pr_number]);
58-
}
59-
60-
if let Ok(input_pr_number) = env::var("INPUT_PR_NUMBER") {
61-
if !input_pr_number.trim().is_empty() {
62-
return Ok(vec![input_pr_number.parse().with_context(|| {
63-
format!("INPUT_PR_NUMBER must be numeric, got {input_pr_number:?}")
64-
})?]);
65-
}
66-
}
67-
68-
let event_name = env::var("GITHUB_EVENT_NAME").unwrap_or_default();
69-
if event_name == "schedule" {
70-
return client.list_open_pull_requests(owner, repo);
71-
}
72-
73-
let event_path = match env::var("GITHUB_EVENT_PATH") {
74-
Ok(path) => path,
75-
Err(_) => return Ok(Vec::new()),
76-
};
77-
let event: Value = serde_json::from_str(
78-
&fs::read_to_string(&event_path)
79-
.with_context(|| format!("failed to read GitHub event payload {event_path}"))?,
80-
)?;
81-
82-
let mut pr_numbers = BTreeSet::new();
83-
match event_name.as_str() {
84-
"pull_request" | "pull_request_target" => {
85-
if let Some(number) = event.pointer("/pull_request/number").and_then(Value::as_u64) {
86-
pr_numbers.insert(number);
87-
}
88-
}
89-
"workflow_run" => {
90-
if event.pointer("/workflow_run/name").and_then(Value::as_str) == Some("Retry CLA Assistant") {
91-
println!("Ignoring completion of this workflow.");
92-
return Ok(Vec::new());
93-
}
94-
if let Some(prs) = event.pointer("/workflow_run/pull_requests").and_then(Value::as_array) {
95-
for pr in prs {
96-
if let Some(number) = pr.get("number").and_then(Value::as_u64) {
97-
pr_numbers.insert(number);
98-
}
99-
}
100-
}
101-
}
102-
"workflow_dispatch" => {}
103-
other => println!("Unsupported event {other}; skipping."),
104-
}
105-
106-
Ok(pr_numbers.into_iter().collect())
40+
retry_for_pr(&client, owner, repo_name, args.pr_number)
10741
}
10842

10943
fn retry_for_pr(client: &GithubClient, owner: &str, repo: &str, pr_number: u64) -> Result<()> {
@@ -274,24 +208,6 @@ impl GithubClient {
274208
Ok(response.statuses)
275209
}
276210

277-
fn list_open_pull_requests(&self, owner: &str, repo: &str) -> Result<Vec<u64>> {
278-
let mut page = 1;
279-
let mut pr_numbers = Vec::new();
280-
281-
loop {
282-
let path = format!("/repos/{owner}/{repo}/pulls?state=open&base=master&per_page=100&page={page}");
283-
let prs: Vec<PullRequestSummary> = self.github_get(&path)?;
284-
let is_last_page = prs.len() < 100;
285-
pr_numbers.extend(prs.into_iter().map(|pr| pr.number));
286-
if is_last_page {
287-
break;
288-
}
289-
page += 1;
290-
}
291-
292-
Ok(pr_numbers)
293-
}
294-
295211
fn recheck_cla(&self, owner: &str, repo: &str, pr_number: u64) -> Result<()> {
296212
let url = format!("https://cla-assistant.io/check/{owner}/{repo}?pullRequest={pr_number}");
297213
let response = self
@@ -315,11 +231,6 @@ struct PullRequest {
315231
base: PullRequestRef,
316232
}
317233

318-
#[derive(Deserialize)]
319-
struct PullRequestSummary {
320-
number: u64,
321-
}
322-
323234
#[derive(Deserialize)]
324235
struct PullRequestRef {
325236
sha: String,

0 commit comments

Comments
 (0)