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