Search code examples
githubcontinuous-integrationgithub-actions

GitHub Action to periodically update toolchain versions?


I have a GitHub project that pins Rust toolchain versions for use in CI. So far, I've been periodically updating these versions manually.

It's a rote task that, from a scripting perspective, is trivial to automate. As in, it's literally be this simple:

# After updating Cargo.toml
VERSION=$(cargo metadata --format-version 1 |\
    jq -r ".packages[] | select(.name == \"zerocopy\").metadata.ci.pinned-stable)

TRYBUILD=overwrite cargo +$VERSION test --all
git commit -am '[CI] Update pinned stable toolchain version'

However, is there a way that I can configure a GitHub action to periodically run this script and submit a PR automatically? I'd still manually review the PRs, of course.


Solution

  • I ended up figuring it out. Here's the GitHub Actions config file:

    name: Roll pinned toolchain versions
    on:
      schedule:
        - cron: '29 15 * * *'
    
    # TODO: Once we confirm this works, try changing this to `read-all` to see if
    # the job still works.
    permissions: write-all
    
    jobs:
      roll:
        name: Roll pinned toolchain versions
        runs-on: ubuntu-latest
        steps:
          - name: "Checkout code"
            uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
            with:
              ref: main
          - name: "Calculate target version"
            # Use yesterday's date (`-d '-1 day'`) so we're sure the nightly for that
            # date has actually been published yet. This allows us to not worry
            # about what time of day this job runs.
            run: echo "ZC_TARGET_NIGHTLY=nightly-$(date -d '-1 day' +%Y-%m-%d)" >> $GITHUB_ENV
          - name: Install Rust with ${{ env.ZC_TARGET_NIGHTLY }} toolchain
            uses: dtolnay/rust-toolchain@00b49be78f40fba4e87296b2ead62868750bdd83 # stable
            with:
                toolchain: ${{ env.ZC_TARGET_NIGHTLY }}
          - name: "Update files"
            run: |
              set -eox pipefail
              # Confirm that `Cargo.toml` lists the pinned nightly version in the
              # expected format. This is a prerequisite for the subsequent `sed`
              # command. If this fails, the preceding `set -eo pipefail` will cause
              # the script to exit with an error.
              REGEX='^pinned-nightly = "[a-z0-9-]*"$'
              grep "$REGEX" Cargo.toml >/dev/null
              sed -i -e "s/$REGEX/pinned-nightly = \"$ZC_TARGET_NIGHTLY\"/" Cargo.toml
              # Confirm that the update didn't bork `Cargo.toml`.
              grep "$REGEX" Cargo.toml >/dev/null
              # Update `.stderr` files as needed for the new nightly version.
              TRYBUILD=overwrite ./cargo.sh +nightly test --all-features --package zerocopy
              TRYBUILD=overwrite ./cargo.sh +nightly test --all-features --package zerocopy-derive
          
          - name: "Submit PR"
            uses: peter-evans/create-pull-request@153407881ec5c347639a548ade7d8ad1d6740e38 # v5.0.2
            with:
              commit-message: "[ci] Roll pinned nightly toolchain"
              branch: roll-pinned-toolchain-to-${{ env.ZC_TARGET_NIGHTLY }}