| name: CI | |
| on: | |
| merge_group: | |
| pull_request: | |
| branches: | |
| - 'master' | |
| schedule: | |
| - cron: '44 4 * * *' # At 4:44 UTC every day. | |
| defaults: | |
| run: | |
| shell: bash | |
| jobs: | |
| test: | |
| name: test (${{ matrix.host_target }}) | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - host_target: x86_64-unknown-linux-gnu | |
| os: ubuntu-latest | |
| - host_target: i686-unknown-linux-gnu | |
| os: ubuntu-latest | |
| multiarch: i386 | |
| gcc_cross: i686-linux-gnu | |
| - host_target: aarch64-unknown-linux-gnu | |
| os: ubuntu-24.04-arm | |
| - host_target: armv7-unknown-linux-gnueabihf | |
| os: ubuntu-24.04-arm | |
| multiarch: armhf | |
| gcc_cross: arm-linux-gnueabihf | |
| # Ubuntu mirrors are not reliable enough for these architectures | |
| # (see <https://bugs.launchpad.net/ubuntu/+bug/2130309>). | |
| # - host_target: riscv64gc-unknown-linux-gnu | |
| # os: ubuntu-latest | |
| # multiarch: riscv64 | |
| # gcc_cross: riscv64-linux-gnu | |
| # qemu: true | |
| # - host_target: s390x-unknown-linux-gnu | |
| # os: ubuntu-latest | |
| # multiarch: s390x | |
| # gcc_cross: s390x-linux-gnu | |
| # qemu: true | |
| # - host_target: powerpc64le-unknown-linux-gnu | |
| # os: ubuntu-latest | |
| # multiarch: ppc64el | |
| # gcc_cross: powerpc64le-linux-gnu | |
| # qemu: true | |
| - host_target: aarch64-apple-darwin | |
| os: macos-latest | |
| - host_target: i686-pc-windows-msvc | |
| os: windows-latest | |
| - host_target: aarch64-pc-windows-msvc | |
| os: windows-11-arm | |
| runs-on: ${{ matrix.os }} | |
| env: | |
| HOST_TARGET: ${{ matrix.host_target }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: install multiarch | |
| if: ${{ matrix.multiarch != '' }} | |
| run: | | |
| # armhf, s390x, ppc64el, riscv64 need Ubuntu Ports to be in the mirror list | |
| sudo bash -c "echo 'https://ports.ubuntu.com/ priority:4' >> /etc/apt/apt-mirrors.txt" | |
| # Add architecture | |
| sudo dpkg --add-architecture ${{ matrix.multiarch }} | |
| # Ubuntu Ports often has outdated mirrors so try a few times to get the apt repo | |
| for TRY in $(seq 3); do | |
| { sudo apt update && break; } || sleep 60 | |
| done | |
| # Install needed packages | |
| sudo apt install $(echo "libatomic1: zlib1g-dev:" | sed 's/:/:${{ matrix.multiarch }}/g') | |
| - name: install qemu | |
| if: ${{ matrix.qemu }} | |
| run: sudo apt install qemu-user qemu-user-binfmt | |
| - uses: ./.github/workflows/setup | |
| with: | |
| toolchain_flags: "--host ${{ matrix.host_target }}" | |
| # We set up the cross-compiler *after* the basic setup as setting CC would otherwise | |
| # cause confusion. | |
| - name: install gcc-cross | |
| if: ${{ matrix.gcc_cross != '' }} | |
| run: | | |
| sudo apt install gcc-${{ matrix.gcc_cross }} | |
| echo "Setting environment variables:" | |
| echo "CC_${{ matrix.host_target }}=${{ matrix.gcc_cross }}-gcc" | tee -a $GITHUB_ENV | |
| TARGET_UPPERCASE=$(echo ${{ matrix.host_target }} | tr '[:lower:]-' '[:upper:]_') | |
| echo "CARGO_TARGET_${TARGET_UPPERCASE}_LINKER=${{ matrix.gcc_cross }}-gcc" | tee -a $GITHUB_ENV | |
| # The main test job! We don't run this in qemu as that is quite slow, | |
| # so those targets only get the clippy check below. | |
| - name: test Miri | |
| if: ${{ !matrix.qemu }} | |
| run: ./ci/ci.sh | |
| # The `style` job only runs on Linux; this makes sure the host-specific | |
| # code is also covered by clippy. | |
| - name: clippy | |
| run: ./miri clippy -- -D warnings | |
| style: | |
| name: style checks | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: ./.github/workflows/setup | |
| - name: rustfmt | |
| run: ./miri fmt --check | |
| - name: clippy (no features) | |
| run: ./miri clippy --no-default-features -- -D warnings | |
| - name: clippy (all features) | |
| run: ./miri clippy --all-features -- -D warnings | |
| - name: rustdoc | |
| run: RUSTDOCFLAGS="-Dwarnings" ./miri doc --document-private-items | |
| bootstrap: | |
| name: bootstrap build | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| # Deliberately skipping `./.github/workflows/setup` as we do our own setup | |
| - name: Add cache for cargo | |
| id: cache | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| # Taken from <https://doc.rust-lang.org/nightly/cargo/guide/cargo-home.html#caching-the-cargo-home-in-ci>. | |
| # Cache package/registry information | |
| ~/.cargo/registry/index | |
| ~/.cargo/registry/cache | |
| ~/.cargo/git/db | |
| # Cache bootstrap downloads | |
| ../rust/build/cache | |
| key: cargo-bootstrap-${{ hashFiles('rust-version') }} | |
| restore-keys: cargo-bootstrap | |
| - name: prepare build environment | |
| run: | | |
| MIRIDIR=$(pwd) | |
| cd .. | |
| # Bootstrap needs at least depth 2 to function. | |
| git clone https://github.com/rust-lang/rust/ rust --depth 2 --revision $(cat "$MIRIDIR/rust-version") | |
| cd rust | |
| # Replace the in-tree Miri with the current version. | |
| rm src/tools/miri -rf | |
| ln -s "$MIRIDIR" src/tools/miri | |
| - name: check build | |
| run: | | |
| cd ../rust # ./x does not seem to like being invoked from elsewhere | |
| ./x check miri | |
| coverage: | |
| name: coverage report | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: ./.github/workflows/setup | |
| - name: coverage | |
| run: ./miri test --coverage | |
| # Summary job for the merge queue. | |
| # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB! | |
| # And they should be added below in `cron-fail-notify` as well. | |
| conclusion: | |
| needs: [test, style, bootstrap, coverage] | |
| # We need to ensure this job does *not* get skipped if its dependencies fail, | |
| # because a skipped job is considered a success by GitHub. So we have to | |
| # overwrite `if:`. We use `!cancelled()` to ensure the job does still not get run | |
| # when the workflow is canceled manually. | |
| if: ${{ !cancelled() }} | |
| runs-on: ubuntu-latest | |
| steps: | |
| # Manually check the status of all dependencies. `if: failure()` does not work. | |
| - name: Conclusion | |
| run: | | |
| # Print the dependent jobs to see them in the CI log | |
| jq -C <<< '${{ toJson(needs) }}' | |
| # Check if all jobs that we depend on (in the needs array) were successful. | |
| jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}' | |
| cron-rustc-pull: | |
| name: automatic pull from rustc | |
| runs-on: ubuntu-latest | |
| permissions: | |
| # The cronjob needs to be able to push to the repo... | |
| contents: write | |
| # ... and create a PR. | |
| pull-requests: write | |
| if: ${{ github.event_name == 'schedule' }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 256 # get a bit more of the history | |
| - name: install josh-sync | |
| run: cargo +stable install --locked --git https://github.com/rust-lang/josh-sync | |
| - name: setup bot git name and email | |
| run: | | |
| git config --global user.name 'The Miri Cronjob Bot' | |
| git config --global user.email 'miri@cron.bot' | |
| - name: Install nightly toolchain | |
| run: rustup toolchain install nightly --profile minimal | |
| - name: Install rustup-toolchain-install-master | |
| run: cargo install -f rustup-toolchain-install-master | |
| # Create a token for the next step so it can create a PR that actually runs CI. | |
| - uses: actions/create-github-app-token@v2 | |
| id: app-token | |
| with: | |
| app-id: ${{ vars.APP_CLIENT_ID }} | |
| private-key: ${{ secrets.APP_PRIVATE_KEY }} | |
| - name: pull changes from rustc and create PR | |
| run: | | |
| # Make it easier to see what happens. | |
| set -x | |
| # Temporarily disable early exit to examine the status code of rustc-josh-sync | |
| set +e | |
| rustc-josh-sync pull | |
| exitcode=$? | |
| set -e | |
| # If there were no changes to pull, rustc-josh-sync returns status code 2. | |
| # In that case, skip the rest of the job. | |
| if [ $exitcode -eq 2 ]; then | |
| echo "Nothing changed in rustc, skipping PR" | |
| exit 0 | |
| elif [ $exitcode -ne 0 ]; then | |
| # If return code was not 0 or 2, rustc-josh-sync actually failed | |
| echo "error: rustc-josh-sync failed" | |
| exit ${exitcode} | |
| fi | |
| # Store merge commit message | |
| git log -1 --pretty=%B > message.txt | |
| # Format changes | |
| ./miri toolchain | |
| ./miri fmt --check || (./miri fmt && git commit -am "fmt") | |
| # Create a PR | |
| BRANCH="rustup-$(date -u +%Y-%m-%d)" | |
| git switch -c $BRANCH | |
| git push -u origin $BRANCH | |
| gh pr create -B master --title 'Automatic Rustup' --body-file message.txt | |
| env: | |
| GITHUB_TOKEN: ${{ steps.app-token.outputs.token }} | |
| cron-fail-notify: | |
| name: cronjob failure notification | |
| runs-on: ubuntu-latest | |
| needs: [test, style, bootstrap, coverage] | |
| if: ${{ github.event_name == 'schedule' && failure() }} | |
| steps: | |
| # Send a Zulip notification | |
| - name: Install zulip-send | |
| run: pip3 install zulip | |
| - name: Send Zulip notification | |
| env: | |
| ZULIP_BOT_EMAIL: ${{ secrets.ZULIP_BOT_EMAIL }} | |
| ZULIP_API_TOKEN: ${{ secrets.ZULIP_API_TOKEN }} | |
| run: | | |
| ~/.local/bin/zulip-send --user $ZULIP_BOT_EMAIL --api-key $ZULIP_API_TOKEN --site https://rust-lang.zulipchat.com \ | |
| --stream miri --subject "Miri Build Failure ($(date -u +%Y-%m))" \ | |
| --message 'Dear @*T-miri*, | |
| It would appear that the [Miri cron job build]('"https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID"') failed. | |
| This likely means that rustc changed the miri directory and | |
| we now need to do a [`rustc-josh-sync pull`](https://github.com/rust-lang/miri/blob/master/CONTRIBUTING.md#importing-changes-from-the-rustc-repo). | |
| Would you mind investigating this issue? | |
| Thanks in advance! | |
| Sincerely, | |
| The Miri Cronjobs Bot' |