From 88197e4182d16a711a2b78051a20ab9e6951451d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Thu, 30 Jan 2025 16:24:39 +0100 Subject: [PATCH 1/2] Distinguish between "nothing to pull" and "pull error" in josh-sync --- josh-sync/src/main.rs | 15 +++++++++++++-- josh-sync/src/sync.rs | 24 +++++++++++++++++++----- 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/josh-sync/src/main.rs b/josh-sync/src/main.rs index 84613ad86..175f016f7 100644 --- a/josh-sync/src/main.rs +++ b/josh-sync/src/main.rs @@ -1,5 +1,5 @@ use clap::Parser; -use crate::sync::GitSync; +use crate::sync::{GitSync, RustcPullError}; mod sync; @@ -22,7 +22,18 @@ fn main() -> anyhow::Result<()> { let sync = GitSync::from_current_dir()?; match args { Args::RustcPull => { - sync.rustc_pull(None)?; + if let Err(error) = sync.rustc_pull(None) { + match error { + RustcPullError::NothingToPull => { + eprintln!("Nothing to pull"); + std::process::exit(2); + } + RustcPullError::PullFailed(error) => { + eprintln!("Pull failure: {error:?}"); + std::process::exit(1); + } + } + } } Args::RustcPush { github_username, branch } => { sync.rustc_push(github_username, branch)?; diff --git a/josh-sync/src/sync.rs b/josh-sync/src/sync.rs index eff80b109..cd64be636 100644 --- a/josh-sync/src/sync.rs +++ b/josh-sync/src/sync.rs @@ -11,6 +11,19 @@ const JOSH_FILTER: &str = ":/src/doc/rustc-dev-guide"; const JOSH_PORT: u16 = 42042; const UPSTREAM_REPO: &str = "rust-lang/rust"; +pub enum RustcPullError { + /// No changes are available to be pulled. + NothingToPull, + /// A rustc-pull has failed, probably a git operation error has occurred. + PullFailed(anyhow::Error) +} + +impl From for RustcPullError where E: Into { + fn from(error: E) -> Self { + Self::PullFailed(error.into()) + } +} + pub struct GitSync { dir: PathBuf, } @@ -24,7 +37,7 @@ impl GitSync { }) } - pub fn rustc_pull(&self, commit: Option) -> anyhow::Result<()> { + pub fn rustc_pull(&self, commit: Option) -> Result<(), RustcPullError> { let sh = Shell::new()?; sh.change_dir(&self.dir); let commit = commit.map(Ok).unwrap_or_else(|| { @@ -38,7 +51,7 @@ impl GitSync { })?; // Make sure the repo is clean. if cmd!(sh, "git status --untracked-files=no --porcelain").read()?.is_empty().not() { - bail!("working directory must be clean before performing rustc pull"); + return Err(anyhow::anyhow!("working directory must be clean before performing rustc pull").into()); } // Make sure josh is running. let josh = Self::start_josh()?; @@ -47,7 +60,7 @@ impl GitSync { let previous_base_commit = sh.read_file("rust-version")?.trim().to_string(); if previous_base_commit == commit { - return Err(anyhow::anyhow!("No changes since last pull")); + return Err(RustcPullError::NothingToPull); } // Update rust-version file. As a separate commit, since making it part of @@ -94,12 +107,13 @@ impl GitSync { cmd!(sh, "git reset --hard HEAD^") .run() .expect("FAILED to clean up after creating the preparation commit"); - return Err(anyhow::anyhow!("No merge was performed, nothing to pull. Rolled back the preparation commit.")); + eprintln!("No merge was performed, no changes to pull were found. Rolled back the preparation commit."); + return Err(RustcPullError::NothingToPull); } // Check that the number of roots did not increase. if num_roots()? != num_roots_before { - bail!("Josh created a new root commit. This is probably not the history you want."); + return Err(anyhow::anyhow!("Josh created a new root commit. This is probably not the history you want.").into()); } drop(josh); From c45e1e9a0e7874db1b530641462621d28184d3f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Thu, 30 Jan 2025 17:29:01 +0100 Subject: [PATCH 2/2] Run rustc-pull CI every day, don't notify when there is nothing to update --- .github/workflows/rustc-pull.yml | 40 ++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/.github/workflows/rustc-pull.yml b/.github/workflows/rustc-pull.yml index 615927d55..5d5b145c9 100644 --- a/.github/workflows/rustc-pull.yml +++ b/.github/workflows/rustc-pull.yml @@ -3,8 +3,8 @@ name: rustc-pull on: workflow_dispatch: schedule: - # Run at 04:00 UTC every Monday - - cron: '0 4 * * 1' + # Run at 04:00 UTC every day + - cron: '0 4 * * *' jobs: pull: @@ -34,8 +34,25 @@ jobs: git config --global user.name 'The rustc-dev-guide Cronjob Bot' git config --global user.email 'github-actions@github.com' - name: Perform rustc-pull - run: cargo run --manifest-path josh-sync/Cargo.toml -- rustc-pull + id: rustc-pull + # Turn off -e to disable early exit + shell: bash {0} + run: | + cargo run --manifest-path josh-sync/Cargo.toml -- rustc-pull + exitcode=$? + + # If no pull was performed, we want to mark this job as successful, + # but we do not want to perform the follow-up steps. + if [ $exitcode -eq 0 ]; then + echo "pull_result=pull-finished" >> $GITHUB_OUTPUT + elif [ $exitcode -eq 2 ]; then + echo "pull_result=skipped" >> $GITHUB_OUTPUT + exitcode=0 + fi + + exit ${exitcode} - name: Push changes to a branch + if: ${{ steps.rustc-pull.outputs.pull_result == 'pull-finished' }} run: | # Update a sticky branch that is used only for rustc pulls BRANCH="rustc-pull" @@ -43,6 +60,7 @@ jobs: git push -u origin $BRANCH --force - name: Create pull request id: update-pr + if: ${{ steps.rustc-pull.outputs.pull_result == 'pull-finished' }} run: | # Check if an open pull request for an rustc pull update already exists # If it does, the previous push has just updated it @@ -54,6 +72,7 @@ jobs: echo "pr_url=$PR_URL" >> $GITHUB_OUTPUT else PR_URL=`gh pr list --author github-actions[bot] --state open -q 'map(select(.title=="Rustc pull update")) | .[0].url' --json url,title` + echo "Updating pull request ${PR_URL}" echo "pr_url=$PR_URL" >> $GITHUB_OUTPUT fi env: @@ -64,16 +83,23 @@ jobs: runs-on: ubuntu-latest steps: - name: Compute message - id: message + id: create-message run: | - if [ "${{ needs.pull.result }}" == "failure" ]; - then + if [ "${{ needs.pull.result }}" == "failure" ]; then WORKFLOW_URL="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" echo "message=Rustc pull sync failed. Check out the [workflow URL]($WORKFLOW_URL)." >> $GITHUB_OUTPUT else - echo "message=Rustc pull sync succeeded. Check out the [PR](${{ needs.pull.outputs.pr_url }})." >> $GITHUB_OUTPUT + CREATED_AT=`gh pr list --author github-actions[bot] --state open -q 'map(select(.title=="Rustc pull update")) | .[0].createdAt' --json createdAt,title` + PR_URL=`gh pr list --author github-actions[bot] --state open -q 'map(select(.title=="Rustc pull update")) | .[0].url' --json url,title` + week_ago=$(date +%F -d '7 days ago') + + # If there is an open PR that is at least a week old, post a message about it + if [[ -n $DATE_GH && $DATE_GH < $week_ago ]]; then + echo "message=A PR with a Rustc pull has been opened for more a week. Check out the [PR](${PR_URL})." >> $GITHUB_OUTPUT + fi fi - name: Send a Zulip message about updated PR + if: ${{ steps.create-message.outputs.message != '' }} uses: zulip/github-actions-zulip/send-message@e4c8f27c732ba9bd98ac6be0583096dea82feea5 with: api-key: ${{ secrets.ZULIP_API_TOKEN }}