1name: CI
2on:
3  # Run CI for PRs to `main` and to release branches.
4  #
5  # Note that PRs to `main` will run a subset of tests and PRs to the
6  # `release-*` branches will run full CI.
7  pull_request:
8    branches:
9    - main
10    - 'release-*'
11
12  # This is the CI that runs for PRs-to-merge.
13  merge_group:
14
15  push:
16    branches:
17    # Right now merge queues can't be used with wildcards in branch protections
18    # so full CI runs both on PRs to release branches as well as merges to
19    # release branches. Note that the merge to a release branch may produce a
20    # tag at the end of CI if successful and the tag will trigger the artifact
21    # uploads as well as publication to crates.io.
22    - 'release-*'
23
24  # Allow manually triggering this request via a button or another workflow.
25  workflow_dispatch:
26
27defaults:
28  run:
29    shell: bash
30
31# Cancel any in-flight jobs for the same PR/branch so there's only one active
32# at a time
33concurrency:
34  group: ${{ github.workflow }}-${{ github.ref }}
35  cancel-in-progress: true
36
37jobs:
38  # Check Code style quickly by running `rustfmt` over all code
39  rustfmt:
40    name: Rustfmt
41    runs-on: ubuntu-latest
42    steps:
43    - uses: actions/checkout@v4
44      with:
45        submodules: true
46    - uses: ./.github/actions/install-rust
47    - run: rustup component add rustfmt
48    - run: cargo fmt --all -- --check
49
50    # common logic to cancel the entire run if this job fails
51    - uses: ./.github/actions/cancel-on-failure
52      if: failure()
53
54  # Quick JS formatting/linting checks for the little bits of JS we have for the
55  # `wasmtime explore` UI.
56  check_js:
57    name: Check JS
58    runs-on: ubuntu-latest
59    steps:
60    - uses: actions/checkout@v4
61    - run: npm install
62      working-directory: ./crates/explorer
63    - run: npm run lint
64      working-directory: ./crates/explorer
65    - run: npm run fmt-check
66      working-directory: ./crates/explorer
67
68    # common logic to cancel the entire run if this job fails
69    - uses: ./.github/actions/cancel-on-failure
70      if: failure()
71
72  # Check Code style quickly by running `clang-format` over all the C/C++ code
73  #
74  # Note that `wasmtime-platform.h` is excluded here as it's auto-generated.
75  clangformat:
76    name: Clang format
77    runs-on: ubuntu-24.04
78    steps:
79    - uses: actions/checkout@v4
80      with:
81        submodules: true
82    - run: |
83        git ls-files '*.h' '*.c' '*.cpp' '*.hh' '*.cc' | \
84          grep -v wasmtime-platform.h | \
85          grep -v wasm.h | \
86          xargs clang-format-18 --dry-run --Werror --verbose
87
88    # common logic to cancel the entire run if this job fails
89    - uses: ./.github/actions/cancel-on-failure
90      if: failure()
91
92  # Lint dependency graph for security advisories, duplicate versions, and
93  # incompatible licences
94  cargo_deny:
95    name: Cargo deny
96    needs: determine
97    if: needs.determine.outputs.audit
98    runs-on: ubuntu-latest
99    steps:
100    - uses: actions/checkout@v4
101      with:
102        submodules: true
103    - uses: ./.github/actions/install-rust
104    - run: |
105        set -e
106        curl -L https://github.com/EmbarkStudios/cargo-deny/releases/download/0.18.2/cargo-deny-0.18.2-x86_64-unknown-linux-musl.tar.gz | tar xzf -
107        mv cargo-deny-*-x86_64-unknown-linux-musl/cargo-deny cargo-deny
108        echo `pwd` >> $GITHUB_PATH
109    - run: cargo deny check bans licenses
110
111    # common logic to cancel the entire run if this job fails
112    - uses: ./.github/actions/cancel-on-failure
113      if: failure()
114
115  # Ensure dependencies are vetted. See https://mozilla.github.io/cargo-vet/
116  #
117  # Note that this step, on PRs only, is allowed to fail. This is then followed
118  # up with the `cargo_vet_failure_for_prs` step below. The intention is to
119  # avoid causing this check to fail PRs while still enabling it to fail the
120  # merge queue checks. That way PRs can enter the merge queue when this step is
121  # failing if `main` has picked up `cargo vet` entries in the meantime for the
122  # failures.
123  cargo_vet:
124    name: Cargo vet
125    needs: determine
126    if: github.repository == 'bytecodealliance/wasmtime' && needs.determine.outputs.audit
127    runs-on: ubuntu-latest
128    outputs:
129      outcome: ${{ steps.vet.outcome }}
130    steps:
131    - uses: actions/checkout@v4
132      with:
133        submodules: true
134    - uses: ./.github/actions/install-rust
135    - uses: ./.github/actions/install-cargo-vet
136    - id: vet
137      run: cargo vet --locked
138      continue-on-error: ${{ github.event_name == 'pull_request' }}
139
140    # Double-check that if versions are bumped that `cargo vet` still works.
141    # This is intended to weed out mistakes such as #9115 from happening again.
142    - run: rustc scripts/publish.rs && ./publish bump-patch && cargo vet
143      name: Ensure `cargo vet` works if versions are bumped
144
145    # common logic to cancel the entire run if this job fails
146    - uses: ./.github/actions/cancel-on-failure
147      if: failure()
148
149  cargo_vet_failure_for_prs:
150    name: Cargo vet failed on a Pull Request
151    needs:
152    - determine
153    - cargo_vet
154    if: |
155      needs.determine.outputs.audit
156      && github.event_name == 'pull_request'
157      && needs.cargo_vet.outputs.outcome == 'failure'
158    runs-on: ubuntu-latest
159    steps:
160    # NB: this message ideally would link back to the previous step, but I'm not
161    # sure how to easily do that.
162    - run: |
163        echo 'failed to run "cargo vet", see previous `Cargo vet` step'
164        echo 'exiting with a nonzero status now to alert PR authors'
165        echo 'note, though, that this PR can still enter the merge queue'
166        echo ''
167        echo 'See https://docs.wasmtime.dev/contributing-coding-guidelines.html#cargo-vet-for-contributors'
168        echo 'for more information about the vetting process for Wasmtime'
169        exit 1
170
171  # This job is a dependency of many of the jobs below. This calculates what's
172  # actually being run for this workflow. For example:
173  #
174  # * Pushes to branches, which is currently both pushes to merge queue branches
175  #   as well as release branches, perform full CI.
176  # * PRs to release branches (not `main`) run full CI.
177  # * PRs to `main` will only run a few smoke tests above plus some elements of
178  #   the test matrix. The test matrix here is determined dynamically by the
179  #   `./ci/build-test-matrix.js` script given the commits that happened and
180  #   the files modified.
181  determine:
182    name: Determine CI jobs to run
183    runs-on: ubuntu-latest
184    outputs:
185      run-full: ${{ steps.calculate.outputs.run-full }}
186      test-matrix: ${{ steps.calculate.outputs.test-matrix }}
187      build-matrix: ${{ steps.calculate.outputs.build-matrix }}
188      test-capi: ${{ steps.calculate.outputs.test-capi }}
189      test-nightly: ${{ steps.calculate.outputs.test-nightly }}
190      test-miri: ${{ steps.calculate.outputs.test-miri }}
191      audit: ${{ steps.calculate.outputs.audit }}
192      preview1-adapter: ${{ steps.calculate.outputs.preview1-adapter }}
193      run-dwarf: ${{ steps.calculate.outputs.run-dwarf }}
194      platform-checks: ${{ steps.calculate.outputs.platform-checks }}
195    steps:
196    - uses: actions/checkout@v4
197    - id: calculate
198      env:
199        GH_TOKEN: ${{ github.token }}
200      run: |
201        touch commits.log names.log
202        # Note that CI doesn't run on pushes to `main`, only pushes to merge
203        # queue branches and release branches, so this only runs full CI in
204        # those locations.
205        if [ "${{ github.event_name }}" != "pull_request" ]; then
206          run_full=true
207        else
208          pr=${{ github.event.number }}
209          gh pr view $pr --json commits | tee commits.log
210          gh pr diff $pr --name-only | tee names.log || echo "failed to get files"
211          if [ "${{ github.base_ref }}" != "main" ]; then
212            run_full=true
213          elif grep -q 'prtest:full' commits.log; then
214            run_full=true
215          elif grep -q 'prtest:debug' commits.log; then
216            echo run-dwarf=true >> $GITHUB_OUTPUT
217          elif grep -q 'prtest:platform-checks' commits.log; then
218            echo platform-checks=true >> $GITHUB_OUTPUT
219          elif grep -q 'prtest:miri' commits.log; then
220            echo test-miri=true >> $GITHUB_OUTPUT
221          fi
222          if grep -q crates.c-api names.log; then
223            echo test-capi=true >> $GITHUB_OUTPUT
224          fi
225          if grep -q fuzz names.log; then
226            echo test-nightly=true >> $GITHUB_OUTPUT
227          fi
228          if grep -q sys.custom names.log; then
229            echo test-nightly=true >> $GITHUB_OUTPUT
230          fi
231          if grep -q Cargo.lock names.log; then
232            echo audit=true >> $GITHUB_OUTPUT
233          fi
234          if grep -q supply-chain names.log; then
235            echo audit=true >> $GITHUB_OUTPUT
236          fi
237          if grep -q component-adapter names.log; then
238            echo preview1-adapter=true >> $GITHUB_OUTPUT
239          fi
240          if grep -q debug names.log; then
241            echo run-dwarf=true >> $GITHUB_OUTPUT
242          fi
243          if grep -q pulley names.log; then
244            echo test-nightly=true >> $GITHUB_OUTPUT
245          fi
246        fi
247        matrix="$(node ./ci/build-test-matrix.js ./commits.log ./names.log $run_full)"
248        echo "test-matrix={\"include\":$(echo $matrix)}" >> $GITHUB_OUTPUT
249        echo "$matrix"
250
251        matrix="$(node ./ci/build-build-matrix.js)"
252        echo "build-matrix={\"include\":$(echo $matrix)}" >> $GITHUB_OUTPUT
253
254        if [ "$run_full" = "true" ]; then
255            echo run-full=true >> $GITHUB_OUTPUT
256            echo test-capi=true >> $GITHUB_OUTPUT
257            echo test-nightly=true >> $GITHUB_OUTPUT
258            echo test-miri=true >> $GITHUB_OUTPUT
259            echo audit=true >> $GITHUB_OUTPUT
260            echo preview1-adapter=true >> $GITHUB_OUTPUT
261            echo run-dwarf=true >> $GITHUB_OUTPUT
262            echo platform-checks=true >> $GITHUB_OUTPUT
263        fi
264
265  # Build all documentation of Wasmtime, including the C API documentation,
266  # mdbook documentation, etc. This produces a `gh-pages` artifact which is what
267  # gets uploaded to the `gh-pages` branch later on.
268  doc:
269    needs: determine
270    if: needs.determine.outputs.run-full
271    name: Doc build
272    runs-on: ubuntu-latest
273    env:
274      CARGO_MDBOOK_VERSION: 0.4.37
275      RUSTDOCFLAGS: -Dbroken_intra_doc_links --cfg docsrs
276      OPENVINO_SKIP_LINKING: 1
277    steps:
278    - uses: actions/checkout@v4
279      with:
280        submodules: true
281    - uses: ./.github/actions/install-rust
282      with:
283        toolchain: wasmtime-ci-pinned-nightly
284
285    # Build C API documentation
286    - run: curl -L https://github.com/doxygen/doxygen/releases/download/Release_1_9_3/doxygen-1.9.3.linux.bin.tar.gz | tar xzf -
287    - run: echo "`pwd`/doxygen-1.9.3/bin" >> $GITHUB_PATH
288    - run: cmake -S crates/c-api -B target/c-api
289    - run: cmake --build target/c-api --target doc
290
291    # install mdbook, build the docs, and test the docs
292    - uses: actions/cache@v4
293      with:
294        path: ${{ runner.tool_cache }}/mdbook
295        key: cargo-mdbook-bin-${{ env.CARGO_MDBOOK_VERSION }}
296    - run: |
297        echo "${{ runner.tool_cache }}/mdbook/bin" >> $GITHUB_PATH
298        cargo install --root ${{ runner.tool_cache }}/mdbook --version ${{ env.CARGO_MDBOOK_VERSION }} mdbook --locked
299    - run: (cd docs && mdbook build)
300    - run: cargo build -p wasi-common --features wasmtime/wat,wasmtime/cranelift
301    - run: (cd docs && mdbook test -L ../target/debug/deps)
302
303    # Build Rust API documentation.
304    #
305    # Enable extra features in crates as well to ensure they're documented
306    - run: |
307        cargo doc --no-deps --workspace \
308          --exclude wasmtime-cli \
309          --exclude test-programs \
310          --exclude cranelift-codegen-meta \
311          --features call-hook
312      env:
313        RUSTDOCFLAGS: --cfg=docsrs
314    - run: cargo doc --package cranelift-codegen-meta --document-private-items
315      env:
316        RUSTDOCFLAGS: --cfg=docsrs
317
318    # Assemble the documentation, and always upload it as an artifact for
319    # inspection on PRs and such.
320    - run: |
321        mv docs/book gh-pages
322        mv crates/c-api/html gh-pages/c-api
323        mv target/doc gh-pages/api
324        tar czf gh-pages.tar.gz gh-pages
325    - uses: actions/upload-artifact@v4
326      with:
327        name: gh-pages
328        path: gh-pages.tar.gz
329
330    # common logic to cancel the entire run if this job fails
331    - uses: ./.github/actions/cancel-on-failure
332      if: failure()
333
334  # Checks of various feature combinations and whether things compile. The goal
335  # here isn't to run tests, mostly just serve as a double-check that Rust code
336  # compiles and is likely to work everywhere else.
337  micro_checks:
338    name: Check ${{matrix.name}}
339    strategy:
340      fail-fast: true
341      matrix:
342        include:
343          - name: wasmtime
344            checks: |
345              -p wasmtime --no-default-features
346              -p wasmtime --no-default-features --features wat
347              -p wasmtime --no-default-features --features profiling
348              -p wasmtime --no-default-features --features cache
349              -p wasmtime --no-default-features --features async
350              -p wasmtime --no-default-features --features std
351              -p wasmtime --no-default-features --features pooling-allocator
352              -p wasmtime --no-default-features --features cranelift
353              -p wasmtime --no-default-features --features component-model
354              -p wasmtime --no-default-features --features runtime,component-model
355              -p wasmtime --no-default-features --features cranelift,wat,async,std,cache
356              -p wasmtime --no-default-features --features winch
357              -p wasmtime --no-default-features --features wmemcheck
358              -p wasmtime --no-default-features --features wmemcheck,cranelift,runtime
359              -p wasmtime --no-default-features --features demangle
360              -p wasmtime --no-default-features --features addr2line
361              -p wasmtime --no-default-features --features gc
362              -p wasmtime --no-default-features --features runtime,gc
363              -p wasmtime --no-default-features --features cranelift,gc
364              -p wasmtime --no-default-features --features gc-drc
365              -p wasmtime --no-default-features --features runtime,gc-drc
366              -p wasmtime --no-default-features --features cranelift,gc-drc
367              -p wasmtime --no-default-features --features gc-null
368              -p wasmtime --no-default-features --features runtime,gc-null
369              -p wasmtime --no-default-features --features cranelift,gc-null
370              -p wasmtime --no-default-features --features runtime
371              -p wasmtime --no-default-features --features threads
372              -p wasmtime --no-default-features --features runtime,threads
373              -p wasmtime --no-default-features --features cranelift,threads
374              -p wasmtime --no-default-features --features stack-switching
375              -p wasmtime --no-default-features --features cranelift,stack-switching
376              -p wasmtime --no-default-features --features runtime,stack-switching
377              -p wasmtime --features incremental-cache
378              -p wasmtime --features profile-pulley
379              -p wasmtime --all-features
380
381          - name: wasmtime-fiber
382            checks: |
383              -p wasmtime-internal-fiber --no-default-features
384              -p wasmtime-internal-fiber --no-default-features --features std
385              -p wasmtime-internal-fiber --all-features
386
387          - name: wasmtime-cli
388            checks: |
389              -p wasmtime-cli --no-default-features
390              -p wasmtime-cli --no-default-features --features pooling-allocator
391              -p wasmtime-cli --no-default-features --features run
392              -p wasmtime-cli --no-default-features --features run,component-model
393              -p wasmtime-cli --no-default-features --features run,pooling-allocator
394              -p wasmtime-cli --no-default-features --features compile
395              -p wasmtime-cli --no-default-features --features compile,cranelift
396              -p wasmtime-cli --no-default-features --features compile,cranelift,component-model
397              -p wasmtime-cli --no-default-features --features objdump
398              -p wasmtime-cli --all-features
399              -p wasmtime-cli --features component-model
400
401          - name: cranelift-codegen
402            checks: |
403              -p cranelift-codegen --benches
404              -p cranelift-codegen --no-default-features --features std,unwind,pulley
405
406          - name: cranelift-entity
407            checks: |
408              -p cranelift-entity --no-default-features
409              -p cranelift-entity --no-default-features --features enable-serde
410
411          - name: wasmtime-bench-api
412            checks: |
413              -p wasmtime-bench-api
414
415          - name: wasmtime-c-api
416            checks: |
417              -p wasmtime-c-api --no-default-features
418              -p wasmtime-c-api --no-default-features --features wat
419              -p wasmtime-c-api --no-default-features --features wasi
420    runs-on: ubuntu-latest
421    steps:
422    - uses: actions/checkout@v4
423      with:
424        submodules: true
425    - uses: ./.github/actions/install-rust
426
427    # Run the check.
428    - run: |
429        checks=$(cat <<END
430        ${{ matrix.checks }}
431        END
432        )
433        echo "$checks" | xargs -I CHECK sh -c 'echo "=== cargo check CHECK ==="; cargo check CHECK'
434
435    # common logic to cancel the entire run if this job fails
436    - uses: ./.github/actions/cancel-on-failure
437      if: failure()
438
439  special_tests:
440    name: One-off special tests
441    runs-on: ubuntu-latest
442    needs: determine
443    if: needs.determine.outputs.run-full
444    steps:
445    - uses: actions/checkout@v4
446      with:
447        submodules: true
448    - uses: ./.github/actions/install-rust
449    - run: cargo test -p wasmtime-internal-fiber --no-default-features
450    - run: cargo test -p cranelift-tools --test logged-filetests
451
452    # common logic to cancel the entire run if this job fails
453    - uses: ./.github/actions/cancel-on-failure
454      if: failure()
455
456  # Check that Clippy lints are passing.
457  clippy:
458    name: Clippy
459    runs-on: ubuntu-latest
460    env:
461      CARGO_NDK_VERSION: 2.12.2
462    steps:
463    - uses: actions/checkout@v4
464      with:
465        submodules: true
466    - uses: ./.github/actions/install-rust
467
468    - run: rustup component add clippy
469    - run: cargo clippy --workspace --all-targets
470
471    # common logic to cancel the entire run if this job fails
472    - uses: ./.github/actions/cancel-on-failure
473      if: failure()
474
475  # Similar to `micro_checks` but where we need to install some more state
476  # (e.g. Android NDK) and we haven't factored support for those things out into
477  # a parallel jobs yet.
478  monolith_checks:
479    name: Monolith Checks
480    runs-on: ubuntu-latest
481    env:
482      CARGO_NDK_VERSION: 2.12.2
483    steps:
484    - uses: actions/checkout@v4
485      with:
486        submodules: true
487    - uses: ./.github/actions/install-rust
488
489    # Check that wasmtime compiles with panic=abort since there's some `#[cfg]`
490    # for specifically panic=abort there.
491    - run: cargo check -p wasmtime
492      env:
493        RUSTFLAGS: -Cpanic=abort
494
495    # Check a few builds of the cranelift backend
496    # - only x86 backend support,
497    # - only arm64 backend support,
498    # - no debug_assertions.
499    - run: cargo check --manifest-path=./cranelift/Cargo.toml --bin clif-util --no-default-features --features=cranelift-codegen/arm64
500    - run: cargo check --manifest-path=./cranelift/Cargo.toml --bin clif-util --no-default-features --features=cranelift-codegen/x86
501    - run: cargo check --manifest-path=./cranelift/Cargo.toml --bin clif-util
502      env:
503        CARGO_PROFILE_DEV_DEBUG_ASSERTIONS: false
504
505    # Re-vendor all WIT files and ensure that they're all up-to-date by ensuring
506    # that there's no git changes.
507    - name: Re-vendor WIT
508      run: ./ci/vendor-wit.sh
509    - run: git diff --exit-code
510
511    # Re-vendor the C API and make sure it's up-to-date.
512    - name: Re-vendor C API
513      run: ./ci/vendor-c-api-headers.sh
514    - run: git diff --exit-code
515
516    # common logic to cancel the entire run if this job fails
517    - uses: ./.github/actions/cancel-on-failure
518      if: failure()
519
520  # Various checks that Wasmtime builds for a variety of platforms. Each
521  # platform may not include the entire dependency tree and maybe just a few
522  # features here and there, see the `include` matrix for more details.
523  platform_checks:
524    needs: determine
525    if: needs.determine.outputs.platform-checks
526    name: "Platform: ${{ matrix.target }}"
527    runs-on: ${{ matrix.os }}
528    strategy:
529      fail-fast: true
530      matrix:
531        include:
532        - target: x86_64-unknown-freebsd
533          os: ubuntu-latest
534          test: cargo check
535        - target: aarch64-pc-windows-msvc
536          os: windows-latest
537          test: cargo check
538        # While we're here testing a windows target also test a feature'd build
539        # on Windows. Note that this isn't covered by `micro_checks` above since
540        # that's for unix platforms, not Windows, so include a small check here
541        # which isn't the full `micro_checks` matrix but hopefully enough bang
542        # for our buck.
543        - target: i686-pc-windows-msvc
544          os: windows-latest
545          test: cargo check && cargo build -p wasmtime --no-default-features --features runtime
546        # This is used for general compatibility with `#![no_std]` targets and a
547        # variety of crates are tested here.
548        - target: x86_64-unknown-none
549          os: ubuntu-latest
550          test: >
551            cargo check -p wasmtime --no-default-features --features runtime,component-model &&
552            cargo check -p wasmtime --no-default-features --features runtime,gc,component-model,async &&
553            cargo check -p cranelift-control --no-default-features &&
554            cargo check -p pulley-interpreter --features encode,decode,disas,interp &&
555            cargo check -p wasmtime-wasi-io --no-default-features
556        # Use `cross` for illumos to have a C compiler/linker available.
557        - target: x86_64-unknown-illumos
558          os: ubuntu-latest
559          cross: true
560          test: cross build
561        - target: wasm32-wasip1
562          os: ubuntu-latest
563          test: cargo build --no-default-features --features compile,cranelift,all-arch
564        - target: aarch64-apple-ios
565          os: macos-latest
566          test: cargo build
567          env:
568            IPHONEOS_DEPLOYMENT_TARGET: 13.0
569        # Test that when Cranelift has no support for an architecture, even a
570        # 64-bit one, that Wasmtime still compiles. Note that this is also
571        # intended to test various fallbacks in the codebase where we have no
572        # support at all for a particular architecture. In theory if someone
573        # adds powerpc64 support to Wasmtime this should get switched to some
574        # other architecture.
575        - target: powerpc64le-unknown-linux-gnu
576          os: ubuntu-latest
577          test: cargo build
578          apt_packages: gcc-powerpc64le-linux-gnu
579          env:
580            CARGO_TARGET_POWERPC64LE_UNKNOWN_LINUX_GNU_LINKER: powerpc64le-linux-gnu-gcc
581        # A no_std target without 64-bit atomics
582        - target: riscv32imac-unknown-none-elf
583          os: ubuntu-latest
584          test: cargo check -p wasmtime --no-default-features --features runtime,gc,component-model,async
585    env: ${{ matrix.env || fromJSON('{}') }}
586    steps:
587    - uses: actions/checkout@v4
588      with:
589        submodules: true
590    - uses: ./.github/actions/install-rust
591    - run: rustup target add ${{ matrix.target }}
592    - name: Install cross
593      run: |
594        curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash
595        cargo binstall --no-confirm cross
596      if: ${{ matrix.cross }}
597    - name: Install apt packages
598      if: ${{ matrix.apt_packages }}
599      run: sudo apt-get update && sudo apt-get install -y ${{ matrix.apt_packages }}
600    - run: ${{ matrix.test }}
601      env:
602        CARGO_BUILD_TARGET: ${{ matrix.target }}
603
604    # common logic to cancel the entire run if this job fails
605    - uses: ./.github/actions/cancel-on-failure
606      if: failure()
607
608  # Run tests that require a nightly compiler, such as building fuzz targets.
609  test_nightly:
610    needs: determine
611    if: needs.determine.outputs.test-nightly
612    name: Nightly tests
613    runs-on: ubuntu-latest
614    steps:
615    - uses: actions/checkout@v4
616      with:
617        submodules: true
618    # Note that nightly is pinned here to insulate us from breakage that might
619    # happen upstream. This is periodically updated through a PR.
620    - uses: ./.github/actions/install-rust
621      with:
622        toolchain: wasmtime-ci-pinned-nightly
623
624    # Check that `pulley-interpreter` compiles with tail calls enabled.  Don't
625    # actually run the tests with tail calls enabled, because they are not yet
626    # implemented in rustc and cause an ICE.
627    - run: cargo check -p pulley-interpreter --all-features
628      env:
629        RUSTFLAGS: "--cfg pulley_tail_calls"
630    - run: cargo check -p pulley-interpreter --all-features
631      env:
632        RUSTFLAGS: "--cfg pulley_disable_interp_simd"
633    - run: cargo test -p pulley-interpreter --all-features --release
634      env:
635        RUSTFLAGS: "--cfg pulley_assume_llvm_makes_tail_calls"
636
637    # Ensure that fuzzers still build.
638    #
639    # Install the OCaml packages necessary for fuzz targets that use the
640    # `wasm-spec-interpreter`.
641    - run: cargo install cargo-fuzz --vers "^0.11" --locked
642    - run: sudo apt-get update && sudo apt install -y ocaml-nox ocamlbuild ocaml-findlib libzarith-ocaml-dev
643    - run: cargo fetch
644      working-directory: ./fuzz
645    - run: cargo fuzz build --dev
646    - run: cargo fuzz build --dev --fuzz-dir ./cranelift/isle/fuzz
647    - run: cargo fuzz build --dev --fuzz-dir ./crates/environ/fuzz --features component-model
648    - run: cargo fuzz build --dev --fuzz-dir ./cranelift/assembler-x64/fuzz
649
650    # common logic to cancel the entire run if this job fails
651    - uses: ./.github/actions/cancel-on-failure
652      if: failure()
653
654  # Perform all tests of the c-api
655  test_capi:
656    needs: determine
657    name: Test C-API ${{ matrix.os }}
658    runs-on: ${{ matrix.os }}
659    if: needs.determine.outputs.test-capi
660
661    strategy:
662      fail-fast: true
663      matrix:
664        os: [ubuntu-24.04, macos-14, windows-2025]
665
666    steps:
667    - uses: actions/checkout@v4
668      with:
669        submodules: true
670    - uses: ./.github/actions/install-rust
671
672    # Build and test the C API with example C programs along with the example
673    # Rust programs. Note that this only executes if the `determine` step told
674    # us to test the capi which is off-by-default for PRs.
675    - run: rustup target add wasm32-wasip2 # wasip2 target needed by example programs
676    - run: cmake -Sexamples -Bexamples/build -DBUILD_SHARED_LIBS=OFF -DBUILD_TESTS=ON
677    - run: cmake --build examples/build --config Debug
678    - run: cmake -E env CTEST_OUTPUT_ON_FAILURE=1 cmake --build examples/build --config Debug --target RUN_TESTS
679      if: runner.os == 'Windows'
680    - run: cmake -E env CTEST_OUTPUT_ON_FAILURE=1 cmake --build examples/build --config Debug --target test
681      if: runner.os != 'Windows'
682
683    # common logic to cancel the entire run if this job fails
684    - uses: ./.github/actions/cancel-on-failure
685      if: failure()
686
687  # Perform all tests (debug mode) for `wasmtime`.
688  #
689  # Note that the full matrix for what may run here is defined within
690  # `./ci/build-test-matrix.js` and the execution of the `determine` step will
691  # calculate whether the tests are actually run as part of PRs and such.
692  test:
693    needs: determine
694    name: ${{ matrix.name }}
695    runs-on: ${{ matrix.os }}
696    env:
697      QEMU_BUILD_VERSION: 9.1.2
698    strategy:
699      fail-fast: ${{ github.event_name != 'pull_request' }}
700      matrix: ${{ fromJson(needs.determine.outputs.test-matrix) }}
701    steps:
702    - uses: actions/checkout@v4
703      with:
704        submodules: true
705    - uses: ./.github/actions/install-rust
706      with:
707        toolchain: ${{ matrix.rust }}
708
709    # Install targets in order to build various tests throughout the repo
710    - run: rustup target add wasm32-wasip1 wasm32-unknown-unknown ${{ matrix.target }}
711    - run: echo CARGO_BUILD_TARGET=${{ matrix.target }} >> $GITHUB_ENV
712      if: matrix.target != ''
713
714    # Fix an ICE for now in gcc when compiling zstd with debuginfo (??)
715    - run: echo CFLAGS=-g0 >> $GITHUB_ENV
716      if: matrix.target == 'x86_64-pc-windows-gnu'
717
718    # Update binutils if MinGW due to https://github.com/rust-lang/rust/issues/112368
719    - run: C:/msys64/usr/bin/pacman.exe -S --needed mingw-w64-x86_64-gcc --noconfirm
720      if: matrix.target == 'x86_64-pc-windows-gnu'
721    - shell: pwsh
722      run: echo "C:\msys64\mingw64\bin" >> $Env:GITHUB_PATH
723      if: matrix.target == 'x86_64-pc-windows-gnu'
724
725    - run: cargo fetch --locked
726
727    - name: Install cross-compilation tools
728      run: |
729        set -ex
730
731        sudo apt-get update
732        sudo apt-get install -y ${{ matrix.gcc_package }}
733
734        # Configure Cargo for cross compilation and tell it how it can run
735        # cross executables
736        upcase=$(echo ${{ matrix.target }} | awk '{ print toupper($0) }' | sed 's/-/_/g')
737        echo CARGO_TARGET_${upcase}_LINKER=${{ matrix.gcc }} >> $GITHUB_ENV
738      if: matrix.gcc != ''
739
740    - uses: actions/cache@v4
741      with:
742        path: ${{ runner.tool_cache }}/qemu
743        key: qemu-${{ matrix.target }}-${{ env.QEMU_BUILD_VERSION }}-patchcpuinfo
744      if: matrix.qemu != ''
745    - name: Install qemu
746      run: |
747        set -ex
748
749        upcase=$(echo ${{ matrix.target }} | awk '{ print toupper($0) }' | sed 's/-/_/g')
750        echo CARGO_TARGET_${upcase}_RUNNER=${{ runner.tool_cache }}/qemu/bin/${{ matrix.qemu }} >> $GITHUB_ENV
751
752        # QEMU emulation is not always the speediest, so total testing time
753        # goes down if we build the libs in release mode when running tests.
754        echo CARGO_PROFILE_DEV_OPT_LEVEL=2 >> $GITHUB_ENV
755
756        # See comments in the source for why we enable this during QEMU
757        # emulation.
758        echo WASMTIME_TEST_NO_HOG_MEMORY=1 >> $GITHUB_ENV
759
760        # See if qemu is already in the cache
761        if [ -f ${{ runner.tool_cache }}/qemu/built ]; then
762          exit 0
763        fi
764
765        # Install build dependencies of QEMU itself.
766        sudo apt-get install -y libglib2.0-dev ninja-build
767
768        # Download and build qemu from source since the most recent release is
769        # way faster at arm emulation than the current version github actions'
770        # ubuntu image uses. Disable as much as we can to get it to build
771        # quickly.
772        curl https://download.qemu.org/qemu-$QEMU_BUILD_VERSION.tar.xz | tar xJf -
773        cd qemu-$QEMU_BUILD_VERSION
774        ./configure --target-list=${{ matrix.qemu_target }} --prefix=${{ runner.tool_cache}}/qemu --disable-tools --disable-slirp --disable-fdt --disable-capstone --disable-docs
775        ninja -C build install
776        touch ${{ runner.tool_cache }}/qemu/built
777      if: matrix.qemu != ''
778
779    - name: Configure ASAN
780      run: |
781        echo CARGO_PROFILE_DEV_OPT_LEVEL=2 >> $GITHUB_ENV
782        echo CARGO_PROFILE_TEST_OPT_LEVEL=2 >> $GITHUB_ENV
783        echo RUSTFLAGS=-Zsanitizer=address >> $GITHUB_ENV
784        echo RUSTDOCFLAGS="-Zsanitizer=address -Copt-level=2 -Ccodegen-units=16" >> $GITHUB_ENV
785      if: ${{ contains(matrix.name, 'ASAN') }}
786
787    # Record some CPU details; this is helpful information if tests fail due
788    # to CPU-specific features.
789    - name: CPU information
790      run: lscpu
791      if: runner.os == 'Linux'
792    - name: CPU information
793      run: sysctl hw
794      if: runner.os == 'macOS'
795    - name: CPU information
796      run: Get-WmiObject Win32_Processor
797      shell: pwsh
798      if: runner.os == 'Windows'
799
800    # Since MPK (PKU) is not present on some GitHub runners, we check if it is
801    # available before force-enabling it. This occasional testing is better than
802    # none at all; ideally we would test in a system-mode QEMU VM.
803    - name: Force-run with MPK enabled, if available
804      if: ${{ contains(matrix.name, 'MPK') }}
805      run: |
806        if cargo run --example mpk-available; then
807          echo "::notice::This CI run will force-enable MPK; this ensures tests conditioned with the \`WASMTIME_TEST_FORCE_MPK\` environment variable will run with MPK-protected memory pool stripes."
808          echo WASMTIME_TEST_FORCE_MPK=1 >> $GITHUB_ENV
809        else
810          echo "::warning::This CI run will not test MPK; it has been detected as not available on this machine (\`cargo run --example mpk-available\`)."
811        fi
812
813    # Install VTune, see `cli_tests::profile_with_vtune`.
814    - name: Install VTune
815      if: matrix.filter == 'linux-x64' && contains(matrix.bucket, 'wasmtime-cli')
816      uses: abrown/install-vtune-action@v1
817
818    # Build and test all features.
819    #
820    # Note that this uses a different shell, notably not `bash` on Windows. In
821    # the past `bash` would add more items to `PATH` on Windows which would
822    # interfere and cause the `gcc.exe` executable to fail and exit with 1 and
823    # no output. It's believed that `bash` adds things like `/usr/bin` to PATH
824    # which is the wrong DLL or something like that.
825    - run: python3 ./ci/run-tests.py --locked ${{ matrix.bucket }}
826      shell: pwsh
827
828    # common logic to cancel the entire run if this job fails
829    - uses: ./.github/actions/cancel-on-failure
830      if: failure()
831
832  # Test `wasmtime-wasi-nn` in its own job, as not all of its backends are
833  # compatible with all targets, and each must be tested separately anyways.
834  test_wasi_nn:
835    strategy:
836      matrix:
837        feature: ["openvino"]
838        os: ["ubuntu-24.04", "windows-2025"]
839        include:
840          - os: windows-2025
841            feature: winml
842    name: Test wasi-nn (${{ matrix.feature }}, ${{ matrix.os }})
843    runs-on: ${{ matrix.os }}
844    needs: determine
845    if: needs.determine.outputs.run-full
846    steps:
847    - uses: actions/checkout@v4
848      with:
849        submodules: true
850    - uses: ./.github/actions/install-rust
851
852    # Install OpenVINO
853    - uses: abrown/install-openvino-action@v9
854      if: runner.arch == 'X64'
855
856    # Install WinML for testing wasi-nn WinML backend. WinML is only available
857    # on Windows clients and Windows Server with desktop experience enabled.
858    # GitHub Actions Window Server image doesn't have desktop experience
859    # enabled, so we download the standalone library from ONNX Runtime project.
860    - uses: nuget/setup-nuget@v2
861      if: (runner.os == 'Windows') && (matrix.feature == 'winml')
862    - run: nuget install Microsoft.AI.MachineLearning
863      if: (runner.os == 'Windows') && (matrix.feature == 'winml')
864
865    # Install Rust targets.
866    - run: rustup target add wasm32-wasip1
867
868    # Run the tests!
869    - run: cargo test -p wasmtime-wasi-nn --features ${{ matrix.feature }}
870
871    # common logic to cancel the entire run if this job fails
872    - uses: ./.github/actions/cancel-on-failure
873      if: failure()
874
875  # Test the `wasmtime-fuzzing` crate. Split out from the main tests because
876  # `--all-features` brings in OCaml, which is a pain to get setup for all
877  # targets.
878  test_fuzzing:
879    needs: determine
880    if: needs.determine.outputs.run-full
881    name: Test wasmtime-fuzzing
882    runs-on: 'ubuntu-latest'
883    steps:
884    - uses: actions/checkout@v4
885      with:
886        submodules: true
887    - uses: ./.github/actions/install-rust
888
889    # Run the tests
890    - run: |
891        cargo test -p wasmtime-fuzzing -p wasm-spec-interpreter
892
893    # common logic to cancel the entire run if this job fails
894    - uses: ./.github/actions/cancel-on-failure
895      if: failure()
896
897  # Test debug (DWARF) related functionality.
898  test_debug_dwarf:
899    needs: determine
900    if: needs.determine.outputs.run-dwarf
901    name: Test DWARF debugging
902    runs-on: ubuntu-22.04 # FIXME: fails on `ubuntu-24.04` right now
903    steps:
904    - uses: actions/checkout@v4
905      with:
906        submodules: true
907    - uses: ./.github/actions/install-rust
908    - run: |
909        rustup target add wasm32-wasip1 wasm32-unknown-unknown
910        cd /tmp
911        curl -OL https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-25/wasi-sdk-25.0-x86_64-linux.tar.gz
912        tar -xzf wasi-sdk-25.0-x86_64-linux.tar.gz
913        mv wasi-sdk-25.0-x86_64-linux wasi-sdk
914    - run: |
915        sudo apt-get update && sudo apt-get install -y gdb lldb-15 llvm
916        # workaround for https://bugs.launchpad.net/ubuntu/+source/llvm-defaults/+bug/1972855
917        sudo mkdir -p /usr/lib/local/lib/python3.10/dist-packages/lldb
918        sudo ln -s /usr/lib/llvm-15/lib/python3.10/dist-packages/lldb/* /usr/lib/python3/dist-packages/lldb/
919        # Only testing release since it is more likely to expose issues with our low-level symbol handling.
920        cargo test --release --test all -- --ignored --test-threads 1 debug::
921      env:
922        LLDB: lldb-15 # override default version, 14
923        WASI_SDK_PATH: /tmp/wasi-sdk
924
925    # common logic to cancel the entire run if this job fails
926    - uses: ./.github/actions/cancel-on-failure
927      if: failure()
928
929  build-preview1-component-adapter:
930    name: Build wasi-preview1-component-adapter
931    needs: determine
932    if: needs.determine.outputs.preview1-adapter
933    runs-on: ubuntu-latest
934    permissions:
935      deployments: write
936      contents: write
937    steps:
938    - uses: actions/checkout@v4
939      with:
940        submodules: true
941    - uses: ./.github/actions/install-rust
942    - run: rustup target add wasm32-wasip1 wasm32-unknown-unknown
943
944    - name: Install wasm-tools
945      run: |
946        curl -L https://github.com/bytecodealliance/wasm-tools/releases/download/wasm-tools-1.0.27/wasm-tools-1.0.27-x86_64-linux.tar.gz | tar xfz -
947        echo `pwd`/wasm-tools-1.0.27-x86_64-linux >> $GITHUB_PATH
948
949    - run: ./ci/build-wasi-preview1-component-adapter.sh
950      env:
951        VERSION: ${{ github.sha }}
952
953    - uses: actions/upload-artifact@v4
954      with:
955        name: bins-wasi-preview1-component-adapter
956        path: target/wasm32-unknown-unknown/release/wasi_snapshot_preview1.*.wasm
957
958
959    # common logic to cancel the entire run if this job fails
960    - uses: ./.github/actions/cancel-on-failure
961      if: failure()
962
963  build-preview1-component-adapter-provider:
964    name: Build wasi-preview1-component-adapter-provider
965    needs: build-preview1-component-adapter
966    runs-on: ubuntu-latest
967    steps:
968    - uses: actions/checkout@v4
969      with:
970        submodules: true
971    - uses: ./.github/actions/install-rust
972    - uses: ./.github/actions/build-adapter-provider
973      with:
974        run-id: ${{ github.run_id }}
975
976    # common logic to cancel the entire run if this job fails
977    - uses: ./.github/actions/cancel-on-failure
978      if: failure()
979
980  # Verify the "min platform" example still works.
981  test-min-platform-example:
982    name: Test the min-platform example
983    needs: determine
984    if: needs.determine.outputs.run-full
985    runs-on: ubuntu-latest
986    steps:
987    - uses: actions/checkout@v4
988      with:
989        submodules: true
990    - uses: ./.github/actions/install-rust
991    - run: cargo install cbindgen --vers "^0.28" --locked
992    - run: rustup target add x86_64-unknown-none
993    - run: rustup target add wasm32-wasip2
994    - run: ./build.sh x86_64-unknown-none
995      working-directory: ./examples/min-platform
996
997    # Afterwards make sure the generated header file is up to date by ensuring
998    # that the regeneration process didn't change anything in-tree.
999    - run: git diff --exit-code
1000
1001    # Test some other feature combinations
1002    - run: ./build.sh x86_64-unknown-none
1003      working-directory: ./examples/min-platform
1004      env:
1005        WASMTIME_SIGNALS_BASED_TRAPS: 1
1006
1007    - run: ./build.sh x86_64-unknown-none
1008      working-directory: ./examples/min-platform
1009      env:
1010        WASMTIME_SIGNALS_BASED_TRAPS: 1
1011        MIN_PLATFORM_TEST_DISABLE_WASI: 1
1012
1013    # Add the `wasmtime-platform.h` file as a release artifact
1014    - uses: actions/upload-artifact@v4
1015      with:
1016        name: wasmtime-platform-header
1017        path: examples/min-platform/embedding/wasmtime-platform.h
1018
1019    # common logic to cancel the entire run if this job fails
1020    - uses: ./.github/actions/cancel-on-failure
1021      if: failure()
1022
1023  bench:
1024    needs: determine
1025    if: needs.determine.outputs.run-full
1026    name: Run benchmarks
1027    runs-on: ubuntu-latest
1028    steps:
1029    - uses: actions/checkout@v4
1030      with:
1031        submodules: true
1032    - uses: ./.github/actions/install-rust
1033    - run: rustup target add wasm32-wasip1
1034    - run: cargo test --benches --release
1035
1036    # common logic to cancel the entire run if this job fails
1037    - uses: ./.github/actions/cancel-on-failure
1038      if: failure()
1039
1040  # Verify that cranelift's code generation is deterministic
1041  meta_deterministic_check:
1042    needs: determine
1043    if: needs.determine.outputs.run-full
1044    name: Meta deterministic check
1045    runs-on: ubuntu-latest
1046    steps:
1047    - uses: actions/checkout@v4
1048      with:
1049        submodules: true
1050    - uses: ./.github/actions/install-rust
1051    - run: cd cranelift/codegen && cargo build --features all-arch
1052    - run: ci/ensure_deterministic_build.sh
1053
1054    # common logic to cancel the entire run if this job fails
1055    - uses: ./.github/actions/cancel-on-failure
1056      if: failure()
1057
1058  verify-publish:
1059    needs: determine
1060    if: github.repository == 'bytecodealliance/wasmtime' && needs.determine.outputs.run-full
1061    runs-on: ubuntu-latest
1062    steps:
1063    - uses: actions/checkout@v4
1064      with:
1065        submodules: true
1066    - uses: ./.github/actions/install-rust
1067    - run: |
1068        cd ${{ runner.tool_cache }}
1069        curl -L https://github.com/mozilla/sccache/releases/download/0.2.13/sccache-0.2.13-x86_64-unknown-linux-musl.tar.gz | tar xzf -
1070        echo "`pwd`/sccache-0.2.13-x86_64-unknown-linux-musl" >> $GITHUB_PATH
1071        echo RUSTC_WRAPPER=sccache >> $GITHUB_ENV
1072    - run: rustc scripts/publish.rs
1073    # Make sure the tree is publish-able as-is
1074    - run: ./publish verify
1075    # Make sure we can bump version numbers for the next release
1076    - run: ./publish bump
1077
1078    # common logic to cancel the entire run if this job fails
1079    - uses: ./.github/actions/cancel-on-failure
1080      if: failure()
1081
1082  # Run a subset of tests under MIRI on CI to help check the `unsafe` code in
1083  # Wasmtime to make sure it's at least not obviously incorrect for basic usage.
1084  # Note that this doesn't run the full test suite since MIRI can't actually run
1085  # WebAssembly itself at this time (aka it doesn't support a JIT). There are a
1086  # number of annotations throughout the code which gates some tests on MIRI not
1087  # being run.
1088  #
1089  # Note that `cargo nextest` is used here additionally to get parallel test
1090  # execution by default to help cut down on the time in CI.
1091  miri:
1092    strategy:
1093      matrix:
1094        include:
1095          - crate: "wasmtime --features pulley"
1096          - crate: "wasmtime-cli"
1097          - crate: "wasmtime-environ --all-features"
1098          - crate: "pulley-interpreter --all-features"
1099          - script: ./ci/miri-provenance-test.sh
1100    needs: determine
1101    if: needs.determine.outputs.test-miri && github.repository == 'bytecodealliance/wasmtime'
1102    name: Miri
1103    runs-on: ubuntu-latest
1104    env:
1105      CARGO_NEXTEST_VERSION: 0.9.88
1106      MIRIFLAGS: -Zmiri-permissive-provenance
1107    steps:
1108    - uses: actions/checkout@v4
1109      with:
1110        submodules: true
1111    - uses: ./.github/actions/install-rust
1112      with:
1113        toolchain: wasmtime-ci-pinned-nightly
1114    - run: rustup component add rust-src miri
1115    - uses: actions/cache@v4
1116      with:
1117        path: ${{ runner.tool_cache }}/cargo-nextest
1118        key: cargo-nextest-bin-${{ env.CARGO_NEXTEST_VERSION }}
1119    - run: echo "${{ runner.tool_cache }}/cargo-nextest/bin" >> $GITHUB_PATH
1120    - run: cargo install --root ${{ runner.tool_cache }}/cargo-nextest --version ${{ env.CARGO_NEXTEST_VERSION }} cargo-nextest --locked
1121    - run: |
1122        cargo miri nextest run -j4 --no-fail-fast -p ${{ matrix.crate }}
1123      if: ${{ matrix.crate }}
1124    - run: ${{ matrix.script }}
1125      if: ${{ matrix.script }}
1126
1127    # common logic to cancel the entire run if this job fails
1128    - uses: ./.github/actions/cancel-on-failure
1129      if: failure()
1130
1131  # Perform release builds of `wasmtime` and `libwasmtime.so`. Builds a variety
1132  # of platforms and architectures and then uploads the release artifacts to
1133  # this workflow run's list of artifacts.
1134  #
1135  # Note that the full matrix is computed by `ci/build-build-matrix.js`.
1136  build:
1137    needs: determine
1138    if: needs.determine.outputs.run-full
1139    name: Release build for ${{ matrix.build }}
1140    runs-on: ${{ matrix.os }}
1141    strategy:
1142      fail-fast: ${{ github.event_name != 'pull_request' }}
1143      matrix: ${{ fromJson(needs.determine.outputs.build-matrix) }}
1144    env: ${{ matrix.env || fromJSON('{}') }}
1145    steps:
1146    - uses: actions/checkout@v4
1147      with:
1148        submodules: true
1149
1150    - uses: ./.github/actions/install-ninja
1151    - uses: ./.github/actions/install-rust
1152      with:
1153        toolchain: ${{ matrix.rust }}
1154    - run: |
1155        rustup component add rust-src
1156        rustup target add ${{ matrix.target }}
1157
1158    # On one builder produce the source tarball since there's no need to produce
1159    # it everywhere
1160    - run: ./ci/build-src-tarball.sh
1161      if: matrix.build == 'x86_64-linux'
1162
1163    - uses: ./.github/actions/android-ndk
1164      if: contains(matrix.target, 'android')
1165      with:
1166        target: ${{ matrix.target }}
1167
1168    - run: ./ci/build-release-artifacts.sh "${{ matrix.build }}" "${{ matrix.target }}"
1169
1170    # Assemble release artifacts appropriate for this platform, then upload them
1171    # unconditionally to this workflow's files so we have a copy of them.
1172    - run: ./ci/build-tarballs.sh "${{ matrix.build }}" "${{ matrix.target }}"
1173
1174    - uses: actions/upload-artifact@v4
1175      with:
1176        name: bins-${{ matrix.build }}
1177        path: dist
1178
1179    # common logic to cancel the entire run if this job fails
1180    - uses: ./.github/actions/cancel-on-failure
1181      if: failure()
1182
1183  # This is a "join node" which depends on all prior workflows. The merge queue,
1184  # for example, gates on this to ensure that everything has executed
1185  # successfully.
1186  #
1187  # Note that this is required currently for odd reasons with github. Notably
1188  # the set of checks to enter the merge queue and leave the merge queue must
1189  # be the same which means that the "build" step for example shows as skipped
1190  # for PRs but expands to many different steps for merge-queue-based PRs. That
1191  # means that for that step there's no single name to gate on, so it's required
1192  # to have a "join" node here which joins everything.
1193  #
1194  # Note that this currently always runs to always report a status, even on
1195  # cancellation and even if dependency steps fail. Each dependency tries to
1196  # cancel the whole run if it fails, so if a test matrix entry fails, for
1197  # example, it cancels the build matrix entries too. This step then tries to
1198  # fail on cancellation to ensure that the dependency failures are propagated
1199  # correctly.
1200  ci-status:
1201    name: Record the result of testing and building steps
1202    runs-on: ubuntu-latest
1203    needs:
1204      - test
1205      - test_capi
1206      - test_debug_dwarf
1207      - test_fuzzing
1208      - test_wasi_nn
1209      - test_nightly
1210      - build
1211      - rustfmt
1212      - clangformat
1213      - cargo_deny
1214      - cargo_vet
1215      - doc
1216      - micro_checks
1217      - special_tests
1218      - clippy
1219      - monolith_checks
1220      - platform_checks
1221      - bench
1222      - meta_deterministic_check
1223      - verify-publish
1224      - determine
1225      - miri
1226      - build-preview1-component-adapter
1227      - build-preview1-component-adapter-provider
1228      - test-min-platform-example
1229      - check_js
1230    if: always()
1231    steps:
1232    - name: Successful test and build
1233      if: ${{ !(contains(needs.*.result, 'failure')) }}
1234      run: exit 0
1235    - name: Failing test and build
1236      if: ${{ contains(needs.*.result, 'failure') }}
1237      run: exit 1
1238    - name: Report failure on cancellation
1239      if: ${{ contains(needs.*.result, 'cancelled') || cancelled() }}
1240      run: exit 1
1241
1242  # The purpose of this jobs is to watch for changes on the `release-*`
1243  # branches of this repository and look for the term
1244  # "automatically-tag-and-release-this-commit" within merged PRs/commits. Once
1245  # that term is found the current version of `Cargo.toml`, the `wasmtime-cli`
1246  # Cargo.toml, is created as a tag and the tag is pushed to the repo.
1247  # Currently the tag is created through the GitHub API with an access token to
1248  # ensure that CI is further triggered for the tag itself which performs the
1249  # full release process.
1250  #
1251  # Note that this depends on the `ci-status` step above which is the "join"
1252  # point of this workflow for when everything succeeds. the purpose of that is
1253  # so that the tag is only created after the aftifacts have been uploaded for
1254  # this workflow as the `publish-artifacts.yml` workflow will download these
1255  # artifacts and then publish them to the tag.
1256  push-tag:
1257    runs-on: ubuntu-latest
1258    needs: ci-status
1259    if: |
1260      always()
1261      && needs.ci-status.result == 'success'
1262      && github.event_name == 'push'
1263      && startsWith(github.ref, 'refs/heads/release-')
1264      && github.repository == 'bytecodealliance/wasmtime'
1265    steps:
1266    - uses: actions/checkout@v4
1267      with:
1268        submodules: true
1269        fetch-depth: 0
1270    - name: Test if tag is needed
1271      run: |
1272        git log ${{ github.event.before }}...${{ github.event.after }} | tee main.log
1273        version=$(grep '^version =' Cargo.toml | head -n 1 | sed 's/.*"\(.*\)"/\1/')
1274        echo "version: $version"
1275        echo "version=$version" >> $GITHUB_OUTPUT
1276        echo "sha=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
1277        if grep -q "automatically-tag-and-release-this-commit" main.log; then
1278          echo push-tag
1279          echo "push_tag=yes" >> $GITHUB_OUTPUT
1280        else
1281          echo no-push-tag
1282          echo "push_tag=no" >> $GITHUB_OUTPUT
1283        fi
1284      id: tag
1285    - name: Push the tag
1286      run: |
1287        git_refs_url=$(jq .repository.git_refs_url $GITHUB_EVENT_PATH | tr -d '"' | sed 's/{\/sha}//g')
1288        curl -iX POST $git_refs_url \
1289          -H "Authorization: token ${{ secrets.PERSONAL_ACCESS_TOKEN }}" \
1290          -d @- << EOF
1291        {
1292          "ref": "refs/tags/v${{ steps.tag.outputs.version }}",
1293          "sha": "${{ steps.tag.outputs.sha }}"
1294        }
1295        EOF
1296      if: steps.tag.outputs.push_tag == 'yes'
1297
1298  # File an issue on the repo if this run failed and was triggered via
1299  # `workflow_dispatch`, which mostly means that
1300  # `.github/workflows/trigger-release-branch-ci.yml` will file issues on
1301  # failure so we get to see a notification when a build fails for a historical
1302  # release branch.
1303  file-issue-on-error:
1304    name: File an issue if this build failed and was cron-triggered
1305    runs-on: ubuntu-latest
1306    needs: ci-status
1307    if: |
1308      always()
1309      && needs.ci-status.result != 'success'
1310      && github.event_name == 'workflow_dispatch'
1311    permissions:
1312      issues: write
1313    steps:
1314    - uses: actions/github-script@v7
1315      with:
1316        script: |
1317          github.rest.issues.create({
1318            owner: context.repo.owner,
1319            repo: context.repo.repo,
1320            title: `Failed CI build for ${context.ref}`,
1321            body: `See https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`,
1322          })
1323