Skip to content

Commit 0b0f91e

Browse files
sbryngelsonmre
authored andcommitted
Split comment posting from check logic for fork PR support
1 parent 4ef3d02 commit 0b0f91e

File tree

1 file changed

+30
-7
lines changed

1 file changed

+30
-7
lines changed

ci/pr-check/src/main.rs

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,22 @@
99
//! - More than one contributor
1010
//! - Repository is at least 3 months old
1111
//!
12-
//! The results are posted as a single comment on the PR (updating an existing
13-
//! bot comment if one already exists). The process exits with a non-zero status
14-
//! code when any hard criterion is not met, causing CI to fail.
12+
//! The results are either posted as a single comment on the PR (updating an
13+
//! existing bot comment if one already exists) or written to a file when the
14+
//! `COMMENT_OUTPUT_FILE` environment variable is set. The latter mode is used
15+
//! in CI to work around the GitHub Actions restriction that prevents fork PRs
16+
//! from writing to the base repository. A separate `pr-comment` workflow then
17+
//! picks up the file and posts the comment with the necessary permissions.
18+
//!
19+
//! The process exits with a non-zero status code when any hard criterion is
20+
//! not met, causing CI to fail.
1521
//!
1622
//! Expected environment variables:
17-
//! GITHUB_TOKEN - a token with `pull-requests: write` permission
18-
//! GITHUB_REPOSITORY - owner/repo, e.g. "analysis-tools-dev/static-analysis"
19-
//! PR_NUMBER - the pull request number
23+
//! GITHUB_TOKEN - a token with `pull-requests: write` permission
24+
//! GITHUB_REPOSITORY - owner/repo, e.g. "analysis-tools-dev/static-analysis"
25+
//! PR_NUMBER - the pull request number
26+
//! COMMENT_OUTPUT_FILE - (optional) path to write the rendered comment body
27+
//! to instead of posting it directly via the API.
2028
2129
use anyhow::{Context, Result, bail};
2230
use askama::Template;
@@ -470,7 +478,22 @@ async fn main() -> Result<()> {
470478

471479
let comment_body = render_comment(&reports)?;
472480

473-
upsert_comment(&client, &gh_repo, pr_number, &comment_body).await?;
481+
// If COMMENT_OUTPUT_FILE is set, write the comment to that file instead of
482+
// posting it via the API. This is used by the `pull_request` CI workflow to
483+
// avoid the 403 that GitHub returns when a fork PR tries to write comments.
484+
// A separate `pr-comment` workflow picks up the file and posts the comment
485+
// with the write permissions it has as a `workflow_run` job.
486+
if let Ok(output_file) = env::var("COMMENT_OUTPUT_FILE") {
487+
if let Some(parent) = std::path::Path::new(&output_file).parent() {
488+
std::fs::create_dir_all(parent)
489+
.with_context(|| format!("Failed to create directory for {output_file}"))?;
490+
}
491+
std::fs::write(&output_file, &comment_body)
492+
.with_context(|| format!("Failed to write comment to {output_file}"))?;
493+
eprintln!("Comment written to {output_file}");
494+
} else {
495+
upsert_comment(&client, &gh_repo, pr_number, &comment_body).await?;
496+
}
474497

475498
let any_failures = reports.iter().any(|r| r.any_fail());
476499
if any_failures {

0 commit comments

Comments
 (0)