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