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  # Run full CI on the `main` branch once a day to prime the GitHub Actions
13  # caches used by PRs and the merge queue.
14  schedule:
15  - cron: '13 4 * * *'
16
17  # This is the CI that runs for PRs-to-merge.
18  merge_group:
19
20  push:
21    branches:
22    # Right now merge queues can't be used with wildcards in branch protections
23    # so full CI runs both on PRs to release branches as well as merges to
24    # release branches. Note that the merge to a release branch may produce a
25    # tag at the end of CI if successful and the tag will trigger the artifact
26    # uploads as well as publication to crates.io.
27    - 'release-*'
28
29defaults:
30  run:
31    shell: bash
32
33# Cancel any in-flight jobs for the same PR/branch so there's only one active
34# at a time
35concurrency:
36  group: ${{ github.workflow }}-${{ github.ref }}
37  cancel-in-progress: true
38
39jobs:
40  # Check Code style quickly by running `rustfmt` over all code
41  rustfmt:
42    name: Rustfmt
43    runs-on: ubuntu-latest
44    steps:
45    - uses: actions/checkout@v3
46      with:
47        submodules: true
48    - uses: ./.github/actions/install-rust
49    - run: rustup component add rustfmt
50    - run: cargo fmt --all -- --check
51
52    # common logic to cancel the entire run if this job fails
53    - run: gh run cancel ${{ github.run_id }}
54      if: failure() && github.event_name != 'pull_request'
55      env:
56        GH_TOKEN: ${{ github.token }}
57
58  # Check Code style quickly by running `clang-format` over all the C/C++ code
59  clangformat:
60    name: Clang format
61    runs-on: ubuntu-latest
62    steps:
63    - uses: actions/checkout@v3
64      with:
65        submodules: true
66    - run: git ls-files '*.h' '*.c' '*.cpp' | xargs clang-format-15 --dry-run --Werror --verbose
67
68    # common logic to cancel the entire run if this job fails
69    - run: gh run cancel ${{ github.run_id }}
70      if: failure() && github.event_name != 'pull_request'
71      env:
72        GH_TOKEN: ${{ github.token }}
73
74  # Lint dependency graph for security advisories, duplicate versions, and
75  # incompatible licences
76  cargo_deny:
77    name: Cargo deny
78    needs: determine
79    if: needs.determine.outputs.audit
80    runs-on: ubuntu-latest
81    steps:
82    - uses: actions/checkout@v3
83      with:
84        submodules: true
85    - uses: ./.github/actions/install-rust
86    - run: |
87        set -e
88        curl -L https://github.com/EmbarkStudios/cargo-deny/releases/download/0.8.5/cargo-deny-0.8.5-x86_64-unknown-linux-musl.tar.gz | tar xzf -
89        mv cargo-deny-*-x86_64-unknown-linux-musl/cargo-deny cargo-deny
90        echo `pwd` >> $GITHUB_PATH
91    - run: cargo deny check bans licenses
92
93    # common logic to cancel the entire run if this job fails
94    - run: gh run cancel ${{ github.run_id }}
95      if: failure() && github.event_name != 'pull_request'
96      env:
97        GH_TOKEN: ${{ github.token }}
98
99  # Ensure dependencies are vetted. See https://mozilla.github.io/cargo-vet/
100  cargo_vet:
101    name: Cargo vet
102    needs: determine
103    if: needs.determine.outputs.audit
104    runs-on: ubuntu-latest
105    steps:
106    - uses: actions/checkout@v3
107      with:
108        submodules: true
109    - uses: ./.github/actions/install-rust
110    - uses: ./.github/actions/install-cargo-vet
111    - run: cargo vet --locked
112
113    # common logic to cancel the entire run if this job fails
114    - run: gh run cancel ${{ github.run_id }}
115      if: failure() && github.event_name != 'pull_request'
116      env:
117        GH_TOKEN: ${{ github.token }}
118
119  # This job is a dependency of many of the jobs below. This calculates what's
120  # actually being run for this workflow. For example:
121  #
122  # * Pushes to branches, which is currently both pushes to merge queue branches
123  #   as well as release branches, perform full CI.
124  # * PRs to release branches (not `main`) run full CI.
125  # * PRs to `main` will only run a few smoke tests above plus some elements of
126  #   the test matrix. The test matrix here is determined dynamically by the
127  #   `./ci/build-test-matrix.js` script given the commits that happened and
128  #   the files modified.
129  determine:
130    name: Determine CI jobs to run
131    runs-on: ubuntu-latest
132    outputs:
133      run-full: ${{ steps.calculate.outputs.run-full }}
134      test-matrix: ${{ steps.calculate.outputs.test-matrix }}
135      build-matrix: ${{ steps.calculate.outputs.build-matrix }}
136      test-capi: ${{ steps.calculate.outputs.test-capi }}
137      build-fuzz: ${{ steps.calculate.outputs.build-fuzz }}
138      audit: ${{ steps.calculate.outputs.audit }}
139      preview1-adapter: ${{ steps.calculate.outputs.preview1-adapter }}
140    steps:
141    - uses: actions/checkout@v3
142    - id: calculate
143      env:
144        GH_TOKEN: ${{ github.token }}
145      run: |
146        touch commits.log names.log
147        # Note that CI doesn't run on pushes to `main`, only pushes to merge
148        # queue branches and release branches, so this only runs full CI in
149        # those locations.
150        if [ "${{ github.event_name }}" != "pull_request" ]; then
151          run_full=true
152        else
153          pr=${{ github.event.number }}
154          gh pr view $pr --json commits | tee commits.log
155          gh pr diff $pr --name-only | tee names.log
156          if [ "${{ github.base_ref }}" != "main" ]; then
157            run_full=true
158          elif grep -q 'prtest:full' commits.log; then
159            run_full=true
160          fi
161          if grep -q crates.c-api names.log; then
162            echo test-capi=true >> $GITHUB_OUTPUT
163          fi
164          if grep -q fuzz names.log; then
165            echo build-fuzz=true >> $GITHUB_OUTPUT
166          fi
167          if grep -q Cargo.lock names.log; then
168            echo audit=true >> $GITHUB_OUTPUT
169          fi
170          if grep -q supply-chain names.log; then
171            echo audit=true >> $GITHUB_OUTPUT
172          fi
173          if grep -q component-adapter names.log; then
174            echo preview1-adapter=true >> $GITHUB_OUTPUT
175          fi
176        fi
177        matrix="$(node ./ci/build-test-matrix.js ./commits.log ./names.log $run_full)"
178        echo "test-matrix={\"include\":$(echo $matrix)}" >> $GITHUB_OUTPUT
179        echo "$matrix"
180
181        matrix="$(node ./ci/build-build-matrix.js)"
182        echo "build-matrix={\"include\":$(echo $matrix)}" >> $GITHUB_OUTPUT
183
184        if [ "$run_full" = "true" ]; then
185            echo run-full=true >> $GITHUB_OUTPUT
186            echo test-capi=true >> $GITHUB_OUTPUT
187            echo build-fuzz=true >> $GITHUB_OUTPUT
188            echo audit=true >> $GITHUB_OUTPUT
189            echo preview1-adapter=true >> $GITHUB_OUTPUT
190        fi
191
192  # Build all documentation of Wasmtime, including the C API documentation,
193  # mdbook documentation, etc. This produces a `gh-pages` artifact which is what
194  # gets uploaded to the `gh-pages` branch later on.
195  doc:
196    needs: determine
197    if: needs.determine.outputs.run-full
198    name: Doc build
199    runs-on: ubuntu-latest
200    env:
201      CARGO_MDBOOK_VERSION: 0.4.21
202      RUSTDOCFLAGS: -Dbroken_intra_doc_links --cfg nightlydoc
203      OPENVINO_SKIP_LINKING: 1
204    steps:
205    - uses: actions/checkout@v3
206      with:
207        submodules: true
208    - uses: ./.github/actions/install-rust
209      with:
210        toolchain: nightly-2023-10-10
211
212    # Build C API documentation
213    - run: curl -L https://sourceforge.net/projects/doxygen/files/rel-1.9.3/doxygen-1.9.3.linux.bin.tar.gz/download | tar xzf -
214    - run: echo "`pwd`/doxygen-1.9.3/bin" >> $GITHUB_PATH
215    - run: cd crates/c-api && doxygen doxygen.conf
216
217    # install mdbook, build the docs, and test the docs
218    - uses: actions/cache@v3
219      with:
220        path: ${{ runner.tool_cache }}/mdbook
221        key: cargo-mdbook-bin-${{ env.CARGO_MDBOOK_VERSION }}
222    - run: |
223        echo "${{ runner.tool_cache }}/mdbook/bin" >> $GITHUB_PATH
224        cargo install --root ${{ runner.tool_cache }}/mdbook --version ${{ env.CARGO_MDBOOK_VERSION }} mdbook
225    - run: (cd docs && mdbook build)
226    - run: cargo build -p wasmtime-wasi --features wasmtime/wat,wasmtime/cranelift
227    - run: (cd docs/rust_wasi_markdown_parser && cargo build)
228    - run: (cd docs && mdbook test -L ../target/debug/deps)
229
230    # Build Rust API documentation.
231    # We pass in the `component-model` feature
232    # to match the docs.rs metadata in
233    # crates/wasmtime/Cargo.toml.
234    - run: |
235        cargo doc --no-deps --workspace \
236          --exclude wasmtime-cli \
237          --exclude test-programs \
238          --exclude wasi-http-tests \
239          --exclude cranelift-codegen-meta \
240          --features component-model
241    - run: cargo doc --package cranelift-codegen-meta --document-private-items
242
243    # Assemble the documentation, and always upload it as an artifact for
244    # inspection on PRs and such.
245    - run: |
246        mv docs/book gh-pages
247        mv crates/c-api/html gh-pages/c-api
248        mv target/doc gh-pages/api
249        tar czf gh-pages.tar.gz gh-pages
250    - uses: actions/upload-artifact@v3
251      with:
252        name: gh-pages
253        path: gh-pages.tar.gz
254
255    # common logic to cancel the entire run if this job fails
256    - run: gh run cancel ${{ github.run_id }}
257      if: failure() && github.event_name != 'pull_request'
258      env:
259        GH_TOKEN: ${{ github.token }}
260
261  # Checks of various feature combinations and whether things
262  # compile. The goal here isn't to run tests, mostly just serve as a
263  # double-check that Rust code compiles and is likely to work everywhere else.
264  checks:
265    needs: determine
266    if: needs.determine.outputs.run-full
267    name: Check
268    runs-on: ubuntu-latest
269    env:
270      CARGO_NDK_VERSION: 2.12.2
271    steps:
272    - uses: actions/checkout@v3
273      with:
274        submodules: true
275    - uses: ./.github/actions/install-rust
276
277    # Check some feature combinations of the `wasmtime` crate
278    - run: cargo check -p wasmtime --no-default-features
279    - run: cargo check -p wasmtime --no-default-features --features wat
280    - run: cargo check -p wasmtime --no-default-features --features profiling
281    - run: cargo check -p wasmtime --no-default-features --features cache
282    - run: cargo check -p wasmtime --no-default-features --features async
283    - run: cargo check -p wasmtime --no-default-features --features pooling-allocator
284    - run: cargo check -p wasmtime --no-default-features --features cranelift
285    - run: cargo check -p wasmtime --no-default-features --features component-model
286    - run: cargo check -p wasmtime --no-default-features --features cranelift,wat,async,cache
287    - run: cargo check -p wasmtime --no-default-features --features winch
288    - run: cargo check -p wasmtime --no-default-features --features wmemcheck
289    - run: cargo check -p wasmtime --no-default-features --features demangle
290    - run: cargo check -p wasmtime --no-default-features --features addr2line
291    - run: cargo check --features component-model
292    - run: cargo check -p wasmtime --features incremental-cache
293
294    # Feature combinations of the `wasmtime-cli`
295    - run: cargo check -p wasmtime-cli --no-default-features
296
297    # Check that benchmarks of the cranelift project build
298    - run: cargo check --benches -p cranelift-codegen
299
300    # Check that the bench-api compiles
301    - run: cargo check -p wasmtime-bench-api
302
303    # Check some feature combinations of the `wasmtime-c-api` crate
304    - run: cargo check -p wasmtime-c-api --no-default-features
305    - run: cargo check -p wasmtime-c-api --no-default-features --features wat
306    - run: cargo check -p wasmtime-c-api --no-default-features --features wasi
307
308    # Check a few builds of the cranelift backend
309    # - only x86 backend support,
310    # - only arm64 backend support,
311    # - no debug_assertions.
312    - run: cargo check --manifest-path=./cranelift/Cargo.toml --bin clif-util --no-default-features --features=cranelift-codegen/arm64
313    - run: cargo check --manifest-path=./cranelift/Cargo.toml --bin clif-util --no-default-features --features=cranelift-codegen/x86
314    - run: cargo check --manifest-path=./cranelift/Cargo.toml --bin clif-util
315      env:
316        CARGO_PROFILE_DEV_DEBUG_ASSERTIONS: false
317
318    # Check whether `wasmtime` cross-compiles to x86_64-unknown-freebsd
319    # TODO: We aren't building with default features since the `ittapi` crate fails to compile on freebsd.
320    - run: rustup target add x86_64-unknown-freebsd
321    - run: cargo check -p wasmtime --no-default-features --features cranelift,wat,async,cache --target x86_64-unknown-freebsd
322
323    # Check whether `wasmtime` cross-compiles to aarch64-linux-android
324    - run: rustup target add aarch64-linux-android
325    - name: Setup Android SDK
326      uses: android-actions/setup-android@v2
327    - uses: actions/cache@v3
328      with:
329        path: ${{ runner.tool_cache }}/cargo-ndk
330        key: cargo-ndk-bin-${{ env.CARGO_NDK_VERSION }}
331    - run: echo "${{ runner.tool_cache }}/cargo-ndk/bin" >> $GITHUB_PATH
332    - run: cargo install --root ${{ runner.tool_cache }}/cargo-ndk --version ${{ env.CARGO_NDK_VERSION }} cargo-ndk
333    - run: cargo ndk -t arm64-v8a check -p wasmtime
334
335    # Run clippy configuration
336    - run: rustup component add clippy
337    - run: cargo clippy --workspace
338
339    # common logic to cancel the entire run if this job fails
340    - run: gh run cancel ${{ github.run_id }}
341      if: failure() && github.event_name != 'pull_request'
342      env:
343        GH_TOKEN: ${{ github.token }}
344
345  # Check whether `wasmtime` cross-compiles to aarch64-pc-windows-msvc
346  # We don't build nor test it because it lacks trap handling.
347  # Tracking issue: https://github.com/bytecodealliance/wasmtime/issues/4992
348  checks_winarm64:
349    needs: determine
350    if: needs.determine.outputs.run-full
351    name: Check Windows ARM64
352    runs-on: windows-latest
353    steps:
354    - uses: actions/checkout@v3
355      with:
356        submodules: true
357    - uses: ./.github/actions/install-rust
358    - run: rustup target add aarch64-pc-windows-msvc
359    - run: cargo check -p wasmtime --target aarch64-pc-windows-msvc
360
361    # common logic to cancel the entire run if this job fails
362    - run: gh run cancel ${{ github.run_id }}
363      if: failure() && github.event_name != 'pull_request'
364      env:
365        GH_TOKEN: ${{ github.token }}
366
367  # Verify all fuzz targets compile successfully
368  fuzz_targets:
369    needs: determine
370    if: needs.determine.outputs.build-fuzz
371    name: Fuzz Targets
372    runs-on: ubuntu-latest
373    steps:
374    - uses: actions/checkout@v3
375      with:
376        submodules: true
377    # Note that building with fuzzers requires nightly since it uses unstable
378    # flags to rustc.
379    - uses: ./.github/actions/install-rust
380      with:
381        toolchain: nightly-2023-10-10
382    - run: cargo install cargo-fuzz --vers "^0.11"
383    # Install the OCaml packages necessary for fuzz targets that use the
384    # `wasm-spec-interpreter`.
385    - run: sudo apt-get update && sudo apt install -y ocaml-nox ocamlbuild ocaml-findlib libzarith-ocaml-dev
386    - run: cargo fetch
387      working-directory: ./fuzz
388    - run: cargo fuzz build --dev -s none
389    # Check that the ISLE fuzz targets build too.
390    - run: cargo fuzz build --dev -s none --fuzz-dir ./cranelift/isle/fuzz
391
392    # common logic to cancel the entire run if this job fails
393    - run: gh run cancel ${{ github.run_id }}
394      if: failure() && github.event_name != 'pull_request'
395      env:
396        GH_TOKEN: ${{ github.token }}
397
398  # Perform all tests (debug mode) for `wasmtime`.
399  #
400  # Note that the full matrix for what may run here is defined within
401  # `./ci/build-test-matrix.js` and the execution of the `determine` step will
402  # calculate whether the tests are actually run as part of PRs and such.
403  test:
404    needs: determine
405    name: ${{ matrix.name }}
406    runs-on: ${{ matrix.os }}
407    env:
408      QEMU_BUILD_VERSION: 8.1.1
409    strategy:
410      fail-fast: ${{ github.event_name != 'pull_request' }}
411      matrix: ${{ fromJson(needs.determine.outputs.test-matrix) }}
412    steps:
413    - uses: actions/checkout@v3
414      with:
415        submodules: true
416    - uses: ./.github/actions/install-rust
417      with:
418        toolchain: ${{ matrix.rust }}
419
420    # Install targets in order to build various tests throughout the repo
421    - run: rustup target add wasm32-wasi wasm32-unknown-unknown ${{ matrix.target }}
422    - run: echo CARGO_BUILD_TARGET=${{ matrix.target }} >> $GITHUB_ENV
423      if: matrix.target != ''
424
425    # Fix an ICE for now in gcc when compiling zstd with debuginfo (??)
426    - run: echo CFLAGS=-g0 >> $GITHUB_ENV
427      if: matrix.target == 'x86_64-pc-windows-gnu'
428
429    - run: cargo fetch --locked
430
431    - uses: actions/cache@v3
432      with:
433        path: ${{ runner.tool_cache }}/qemu
434        key: qemu-${{ matrix.target }}-${{ env.QEMU_BUILD_VERSION }}-patchcpuinfo
435      if: matrix.target != '' && matrix.os == 'ubuntu-latest'
436    - name: Install cross-compilation tools
437      run: |
438        set -ex
439        sudo apt-get update
440        sudo apt-get install -y ${{ matrix.gcc_package }} ninja-build
441
442        # Configure Cargo for cross compilation and tell it how it can run
443        # cross executables
444        upcase=$(echo ${{ matrix.target }} | awk '{ print toupper($0) }' | sed 's/-/_/g')
445        echo CARGO_TARGET_${upcase}_RUNNER=${{ runner.tool_cache }}/qemu/bin/${{ matrix.qemu }} >> $GITHUB_ENV
446        echo CARGO_TARGET_${upcase}_LINKER=${{ matrix.gcc }} >> $GITHUB_ENV
447
448        # QEMU emulation is not always the speediest, so total testing time
449        # goes down if we build the libs in release mode when running tests.
450        echo CARGO_PROFILE_DEV_OPT_LEVEL=2 >> $GITHUB_ENV
451
452        # See comments in the source for why we enable this during QEMU
453        # emulation.
454        echo WASMTIME_TEST_NO_HOG_MEMORY=1 >> $GITHUB_ENV
455
456        # See if qemu is already in the cache
457        if [ -f ${{ runner.tool_cache }}/qemu/built ]; then
458          exit 0
459        fi
460
461        # Download and build qemu from source since the most recent release is
462        # way faster at arm emulation than the current version github actions'
463        # ubuntu image uses. Disable as much as we can to get it to build
464        # quickly.
465        curl https://download.qemu.org/qemu-$QEMU_BUILD_VERSION.tar.xz | tar xJf -
466        cd qemu-$QEMU_BUILD_VERSION
467        ./configure --target-list=${{ matrix.qemu_target }} --prefix=${{ runner.tool_cache}}/qemu --disable-tools --disable-slirp --disable-fdt --disable-capstone --disable-docs
468        ninja -C build install
469        touch ${{ runner.tool_cache }}/qemu/built
470      if: matrix.gcc != ''
471
472    # Build and test the C API with example C programs along with the example
473    # Rust programs. Note that this only executes if the `determine` step told
474    # us to test the capi which is off-by-default for PRs.
475    - run: cmake -Sexamples -Bexamples/build -DBUILD_SHARED_LIBS=OFF
476      if: matrix.target == '' && needs.determine.outputs.test-capi
477    - run: cmake --build examples/build --config Debug
478      if: matrix.target == '' && needs.determine.outputs.test-capi
479    - run: cmake -E env CTEST_OUTPUT_ON_FAILURE=1 cmake --build examples/build --config Debug --target RUN_TESTS
480      env:
481        RUST_BACKTRACE: 1
482      if: matrix.target == '' && matrix.os == 'windows-latest' && needs.determine.outputs.test-capi
483    - run: cmake -E env CTEST_OUTPUT_ON_FAILURE=1 cmake --build examples/build --config Debug --target test
484      env:
485        RUST_BACKTRACE: 1
486      if: matrix.target == '' && matrix.os != 'windows-latest' && needs.determine.outputs.test-capi
487
488    # Ensure wit definitions are in sync: both wasmtime-wasi and wasmtime-wasi-http need their own
489    # copy of the wit definitions so publishing works, but we need to ensure they are identical copies.
490    - name: Check that the wasi and wasi-http wit directories agree
491      run: |
492        diff -ru crates/wasi/wit crates/wasi-http/wit
493
494    # Record some CPU details; this is helpful information if tests fail due
495    # to CPU-specific features.
496    - name: CPU information
497      run: lscpu
498      if: matrix.os == 'ubuntu-latest'
499    - name: CPU information
500      run: sysctl hw
501      if: matrix.os == 'macos-latest'
502    - name: CPU information
503      run: wmic cpu list /format:list
504      shell: pwsh
505      if: matrix.os == 'windows-latest'
506
507    # Build and test all features
508    - run: ./ci/run-tests.sh --locked
509      env:
510        RUST_BACKTRACE: 1
511
512    # Test debug (DWARF) related functionality.
513    - run: |
514        sudo apt-get update && sudo apt-get install -y gdb lldb llvm
515        cargo test test_debug_dwarf -- --ignored --test-threads 1
516      if: matrix.os == 'ubuntu-latest' && matrix.target == ''&& needs.determine.outputs.run-full
517      env:
518        RUST_BACKTRACE: 1
519
520    # NB: the test job here is explicitly lacking in cancellation of this run if
521    # something goes wrong. These take the longest anyway and otherwise if
522    # Windows fails GitHub Actions will confusingly mark the failed Windows job
523    # as cancelled instead of failed.
524
525  # Build and test the wasi-nn module.
526  test_wasi_nn:
527    needs: determine
528    if: needs.determine.outputs.run-full
529    name: Test wasi-nn module
530    runs-on: ubuntu-latest
531    steps:
532      - uses: actions/checkout@v3
533        with:
534          submodules: true
535      - uses: ./.github/actions/install-rust
536      - run: rustup target add wasm32-wasi
537      - uses: abrown/install-openvino-action@v7
538        with:
539          version: 2022.3.0
540          apt: true
541      - run: ./ci/run-wasi-nn-example.sh
542        env:
543          RUST_BACKTRACE: 1
544
545      # common logic to cancel the entire run if this job fails
546      - run: gh run cancel ${{ github.run_id }}
547        if: failure() && github.event_name != 'pull_request'
548        env:
549          GH_TOKEN: ${{ github.token }}
550
551  build-preview1-component-adapter:
552    name: Build wasi-preview1-component-adapter
553    needs: determine
554    if: needs.determine.outputs.preview1-adapter
555    runs-on: ubuntu-latest
556    permissions:
557      deployments: write
558      contents: write
559    steps:
560    - uses: actions/checkout@v3
561      with:
562        submodules: true
563    - run: rustup update stable && rustup default stable
564    - run: rustup target add wasm32-wasi wasm32-unknown-unknown
565
566    - name: Install wasm-tools
567      run: |
568        curl -L https://github.com/bytecodealliance/wasm-tools/releases/download/wasm-tools-1.0.27/wasm-tools-1.0.27-x86_64-linux.tar.gz | tar xfz -
569        echo `pwd`/wasm-tools-1.0.27-x86_64-linux >> $GITHUB_PATH
570
571    - run: ./ci/build-wasi-preview1-component-adapter.sh
572      env:
573        VERSION: ${{ github.sha }}
574
575    - uses: actions/upload-artifact@v3
576      with:
577        name: bins-wasi-preview1-component-adapter
578        path: target/wasm32-unknown-unknown/release/wasi_snapshot_preview1.*.wasm
579
580
581    # common logic to cancel the entire run if this job fails
582    - run: gh run cancel ${{ github.run_id }}
583      if: failure() && github.event_name != 'pull_request'
584      env:
585        GH_TOKEN: ${{ github.token }}
586
587
588  bench:
589    needs: determine
590    if: needs.determine.outputs.run-full
591    name: Run benchmarks
592    runs-on: ubuntu-latest
593    steps:
594    - uses: actions/checkout@v3
595      with:
596        submodules: true
597    - uses: ./.github/actions/install-rust
598    - run: rustup target add wasm32-wasi
599    - run: cargo test --benches --release
600
601    # common logic to cancel the entire run if this job fails
602    - run: gh run cancel ${{ github.run_id }}
603      if: failure() && github.event_name != 'pull_request'
604      env:
605        GH_TOKEN: ${{ github.token }}
606
607  # Verify that cranelift's code generation is deterministic
608  meta_deterministic_check:
609    needs: determine
610    if: needs.determine.outputs.run-full
611    name: Meta deterministic check
612    runs-on: ubuntu-latest
613    steps:
614    - uses: actions/checkout@v3
615      with:
616        submodules: true
617    - uses: ./.github/actions/install-rust
618    - run: cd cranelift/codegen && cargo build --features all-arch
619    - run: ci/ensure_deterministic_build.sh
620
621    # common logic to cancel the entire run if this job fails
622    - run: gh run cancel ${{ github.run_id }}
623      if: failure() && github.event_name != 'pull_request'
624      env:
625        GH_TOKEN: ${{ github.token }}
626
627  verify-publish:
628    needs: determine
629    if: github.repository == 'bytecodealliance/wasmtime' && needs.determine.outputs.run-full
630    runs-on: ubuntu-latest
631    steps:
632    - uses: actions/checkout@v3
633      with:
634        submodules: true
635    - run: rustup update stable && rustup default stable
636    - run: |
637        cd ${{ runner.tool_cache }}
638        curl -L https://github.com/mozilla/sccache/releases/download/0.2.13/sccache-0.2.13-x86_64-unknown-linux-musl.tar.gz | tar xzf -
639        echo "`pwd`/sccache-0.2.13-x86_64-unknown-linux-musl" >> $GITHUB_PATH
640        echo RUSTC_WRAPPER=sccache >> $GITHUB_ENV
641    - run: rustc scripts/publish.rs
642    # Make sure the tree is publish-able as-is
643    - run: ./publish verify
644    # Make sure we can bump version numbers for the next release
645    - run: ./publish bump
646
647    # common logic to cancel the entire run if this job fails
648    - run: gh run cancel ${{ github.run_id }}
649      if: failure() && github.event_name != 'pull_request'
650      env:
651        GH_TOKEN: ${{ github.token }}
652
653  # Run a subset of tests under MIRI on CI to help check the `unsafe` code in
654  # Wasmtime to make sure it's at least not obviously incorrect for basic usage.
655  # Note that this doesn't run the full test suite since MIRI can't actually run
656  # WebAssembly itself at this time (aka it doesn't support a JIT). There are a
657  # number of annotations throughout the code which gates some tests on MIRI not
658  # being run.
659  #
660  # Note that `cargo nextest` is used here additionally to get parallel test
661  # execution by default to help cut down on the time in CI.
662  miri:
663    needs: determine
664    if: needs.determine.outputs.run-full && github.repository == 'bytecodealliance/wasmtime'
665    name: Miri
666    runs-on: ubuntu-latest
667    env:
668      CARGO_NEXTEST_VERSION: 0.9.51
669    steps:
670    - uses: actions/checkout@v3
671      with:
672        submodules: true
673    - uses: ./.github/actions/install-rust
674      with:
675        toolchain: nightly-2023-10-10
676    - run: rustup component add rust-src miri
677    - uses: actions/cache@v3
678      with:
679        path: ${{ runner.tool_cache }}/cargo-nextest
680        key: cargo-nextest-bin-${{ env.CARGO_NEXTEST_VERSION }}
681    - run: echo "${{ runner.tool_cache }}/cargo-nextest/bin" >> $GITHUB_PATH
682    - run: cargo install --root ${{ runner.tool_cache }}/cargo-nextest --version ${{ env.CARGO_NEXTEST_VERSION }} cargo-nextest
683    - run: |
684        cargo miri nextest run -j4 --no-fail-fast \
685          -p wasmtime \
686          -p wasmtime-cli \
687          -p wasmtime-runtime \
688          -p wasmtime-environ
689      env:
690        MIRIFLAGS: -Zmiri-strict-provenance
691
692    # common logic to cancel the entire run if this job fails
693    - run: gh run cancel ${{ github.run_id }}
694      if: failure() && github.event_name != 'pull_request'
695      env:
696        GH_TOKEN: ${{ github.token }}
697
698  # Perform release builds of `wasmtime` and `libwasmtime.so`. Builds a variety
699  # of platforms and architectures and then uploads the release artifacts to
700  # this workflow run's list of artifacts.
701  #
702  # Note that the full matrix is computed by `ci/build-build-matrix.js`.
703  build:
704    needs: determine
705    if: needs.determine.outputs.run-full
706    name: Release build for ${{ matrix.build }}
707    runs-on: ${{ matrix.os }}
708    strategy:
709      fail-fast: ${{ github.event_name != 'pull_request' }}
710      matrix: ${{ fromJson(needs.determine.outputs.build-matrix) }}
711    steps:
712    - uses: actions/checkout@v3
713      with:
714        submodules: true
715
716    - uses: ./.github/actions/install-rust
717      with:
718        toolchain: ${{ matrix.rust }}
719    - run: |
720        rustup component add rust-src
721        rustup target add ${{ matrix.target }}
722
723    # On one builder produce the source tarball since there's no need to produce
724    # it everywhere
725    - run: ./ci/build-src-tarball.sh
726      if: matrix.build == 'x86_64-linux'
727    - uses: ./.github/actions/binary-compatible-builds
728      with:
729        name: ${{ matrix.build }}
730
731    - run: $CENTOS ./ci/build-release-artifacts.sh "${{ matrix.build }}" "${{ matrix.target }}"
732
733    # Assemble release artifacts appropriate for this platform, then upload them
734    # unconditionally to this workflow's files so we have a copy of them.
735    - run: ./ci/build-tarballs.sh "${{ matrix.build }}" "${{ matrix.target }}"
736
737    - uses: actions/upload-artifact@v3
738      with:
739        name: bins-${{ matrix.build }}
740        path: dist
741
742    # common logic to cancel the entire run if this job fails
743    - run: gh run cancel ${{ github.run_id }}
744      if: failure() && github.event_name != 'pull_request'
745      env:
746        GH_TOKEN: ${{ github.token }}
747
748  # This is a "join node" which depends on all prior workflows. The merge queue,
749  # for example, gates on this to ensure that everything has executed
750  # successfully.
751  #
752  # Note that this is required currently for odd reasons with github. Notably
753  # the set of checks to enter the merge queue and leave the merge queue must
754  # be the same which means that the "build" step for example shows as skipped
755  # for PRs but expands to many different steps for merge-queue-based PRs. That
756  # means that for that step there's no single name to gate on, so it's required
757  # to have a "join" node here which joins everything.
758  #
759  # Note that this currently always runs to always report a status, even on
760  # cancellation and even if dependency steps fail. Each dependency tries to
761  # cancel the whole run if it fails, so if a test matrix entry fails, for
762  # example, it cancels the build matrix entries too. This step then tries to
763  # fail on cancellation to ensure that the dependency failures are propagated
764  # correctly.
765  ci-status:
766    name: Record the result of testing and building steps
767    runs-on: ubuntu-latest
768    needs:
769      - test
770      - build
771      - rustfmt
772      - cargo_deny
773      - cargo_vet
774      - doc
775      - checks
776      - checks_winarm64
777      - fuzz_targets
778      - test_wasi_nn
779      - bench
780      - meta_deterministic_check
781      - verify-publish
782      - determine
783      - miri
784      - build-preview1-component-adapter
785    if: always()
786    steps:
787    - name: Dump needs context
788      env:
789        CONTEXT: ${{ toJson(needs) }}
790      run: |
791        echo -e "\033[33;1;4mDump context\033[0m"
792        echo -e "$CONTEXT\n"
793    - name: Successful test and build
794      if: ${{ !(contains(needs.*.result, 'failure')) }}
795      run: exit 0
796    - name: Failing test and build
797      if: ${{ contains(needs.*.result, 'failure') }}
798      run: exit 1
799    - name: Report failure on cancellation
800      if: ${{ contains(needs.*.result, 'cancelled') || cancelled() }}
801      run: exit 1
802
803  # The purpose of this jobs is to watch for changes on the `release-*`
804  # branches of this repository and look for the term
805  # "automatically-tag-and-release-this-commit" within merged PRs/commits. Once
806  # that term is found the current version of `Cargo.toml`, the `wasmtime-cli`
807  # Cargo.toml, is created as a tag and the tag is pushed to the repo.
808  # Currently the tag is created through the GitHub API with an access token to
809  # ensure that CI is further triggered for the tag itself which performs the
810  # full release process.
811  #
812  # Note that this depends on the `ci-status` step above which is the "join"
813  # point of this workflow for when everything succeeds. the purpose of that is
814  # so that the tag is only created after the aftifacts have been uploaded for
815  # this workflow as the `publish-artifacts.yml` workflow will download these
816  # artifacts and then publish them to the tag.
817  push-tag:
818    runs-on: ubuntu-latest
819    needs: ci-status
820    if: |
821      always()
822      && needs.ci-status.result == 'success'
823      && github.event_name == 'push'
824      && startsWith(github.ref, 'refs/heads/release-')
825      && github.repository == 'bytecodealliance/wasmtime'
826    steps:
827    - uses: actions/checkout@v3
828      with:
829        submodules: true
830        fetch-depth: 0
831    - name: Test if tag is needed
832      run: |
833        git log ${{ github.event.before }}...${{ github.event.after }} | tee main.log
834        version=$(grep '^version =' Cargo.toml | head -n 1 | sed 's/.*"\(.*\)"/\1/')
835        echo "version: $version"
836        echo "version=$version" >> $GITHUB_OUTPUT
837        echo "sha=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
838        if grep -q "automatically-tag-and-release-this-commit" main.log; then
839          echo push-tag
840          echo "push_tag=yes" >> $GITHUB_OUTPUT
841        else
842          echo no-push-tag
843          echo "push_tag=no" >> $GITHUB_OUTPUT
844        fi
845      id: tag
846    - name: Push the tag
847      run: |
848        git_refs_url=$(jq .repository.git_refs_url $GITHUB_EVENT_PATH | tr -d '"' | sed 's/{\/sha}//g')
849        curl -iX POST $git_refs_url \
850          -H "Authorization: token ${{ secrets.PERSONAL_ACCESS_TOKEN }}" \
851          -d @- << EOF
852        {
853          "ref": "refs/tags/v${{ steps.tag.outputs.version }}",
854          "sha": "${{ steps.tag.outputs.sha }}"
855        }
856        EOF
857      if: steps.tag.outputs.push_tag == 'yes'
858