|
9 | 9 | //! - More than one contributor |
10 | 10 | //! - Repository is at least 3 months old |
11 | 11 | //! |
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. |
15 | 21 | //! |
16 | 22 | //! 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. |
20 | 28 |
|
21 | 29 | use anyhow::{Context, Result, bail}; |
22 | 30 | use askama::Template; |
@@ -470,7 +478,22 @@ async fn main() -> Result<()> { |
470 | 478 |
|
471 | 479 | let comment_body = render_comment(&reports)?; |
472 | 480 |
|
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 | + } |
474 | 497 |
|
475 | 498 | let any_failures = reports.iter().any(|r| r.any_fail()); |
476 | 499 | if any_failures { |
|
0 commit comments