From f7bfc8aac00db4d1f55a65c97b52b5112e1219f9 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 14 Feb 2024 12:41:09 -0800 Subject: [PATCH] new release process --- .github/workflows/main.yml | 125 ++++++++++- .github/workflows/publish-to-cratesio.yml | 25 +++ .github/workflows/release-process.yml | 106 +++++++++ Cargo.lock | 116 +++++----- Cargo.toml | 29 +-- ci/print-current-version.sh | 2 + ci/publish.rs | 250 ++++++++-------------- crates/c-api/Cargo.toml | 1 - crates/fuzz-stats/Cargo.toml | 1 - crates/wasm-compose/Cargo.toml | 2 +- crates/wasm-encoder/Cargo.toml | 2 +- crates/wasm-metadata/Cargo.toml | 2 +- crates/wasm-mutate-stats/Cargo.toml | 1 - crates/wasm-mutate/Cargo.toml | 2 +- crates/wasm-shrink/Cargo.toml | 2 +- crates/wasm-smith/Cargo.toml | 2 +- crates/wasmparser/Cargo.toml | 2 +- crates/wasmprinter/Cargo.toml | 2 +- crates/wast/Cargo.toml | 2 +- crates/wat/Cargo.toml | 2 +- crates/wit-component/Cargo.toml | 2 +- crates/wit-parser/Cargo.toml | 2 +- crates/wit-parser/fuzz/Cargo.toml | 1 - crates/wit-smith/Cargo.toml | 2 +- fuzz/Cargo.toml | 1 - 25 files changed, 424 insertions(+), 260 deletions(-) create mode 100644 .github/workflows/publish-to-cratesio.yml create mode 100644 .github/workflows/release-process.yml create mode 100755 ci/print-current-version.sh diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c4b061d282..3953429123 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,9 +1,7 @@ name: CI on: - push: - branches: [main] pull_request: - branches: [main] + merge_group: # Cancel any in-flight jobs for the same PR/branch so there's only one active # at a time @@ -12,6 +10,48 @@ concurrency: cancel-in-progress: true jobs: + build: + name: Build wasm-tools + runs-on: ${{ matrix.os }} + strategy: + matrix: + include: + - build: x86_64-linux + os: ubuntu-latest + - build: x86_64-macos + os: macos-latest + - build: aarch64-macos + os: macos-latest + target: aarch64-apple-darwin + - build: x86_64-windows + os: windows-latest + - build: aarch64-linux + os: ubuntu-latest + target: aarch64-unknown-linux-gnu + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - run: rustup update stable --no-self-update && rustup default stable + - uses: bytecodealliance/wasmtime/.github/actions/binary-compatible-builds@v17.0.1 + with: + name: ${{ matrix.build }} + - run: | + echo CARGO_BUILD_TARGET=${{ matrix.target }} >> $GITHUB_ENV + rustup target add ${{ matrix.target }} + if: matrix.target != '' + - run: $CENTOS cargo build --release + - run: ./ci/build-tarballs.sh "${{ matrix.build }}" "${{ matrix.target }}" + - uses: actions/upload-artifact@v3 + with: + name: bins-${{ matrix.build }} + path: dist + + # - uses: softprops/action-gh-release@v1 + # if: startsWith(github.ref, 'refs/tags/') && github.repository == 'bytecodealliance/wasm-tools' + # with: + # files: "dist/*" + test: name: Test runs-on: ${{ matrix.os }} @@ -35,7 +75,7 @@ jobs: os: windows-latest rust: stable steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - name: Install Rust (rustup) @@ -54,7 +94,7 @@ jobs: name: Test on WebAssembly runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - name: Install Rust @@ -77,7 +117,7 @@ jobs: name: Rustfmt runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Rust run: rustup update stable && rustup default stable && rustup component add rustfmt # Note that this doesn't use `cargo fmt` because that doesn't format @@ -89,7 +129,7 @@ jobs: name: Fuzz runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - name: Install Rust @@ -101,7 +141,7 @@ jobs: check: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - run: cargo check --benches -p wasm-smith - run: cargo check --no-default-features - run: cargo check --no-default-features --features print @@ -133,5 +173,72 @@ jobs: doc: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - run: cargo doc --all + + # "Join node" which the merge queue waits on. + ci-status: + name: Record the result of testing and building steps + runs-on: ubuntu-latest + needs: + - test + - wasm + - rustfmt + - fuzz + - check + - doc + - build + if: always() + steps: + - name: Successful test and build + if: ${{ !(contains(needs.*.result, 'failure')) }} + run: exit 0 + - name: Failing test and build + if: ${{ contains(needs.*.result, 'failure') }} + run: exit 1 + - name: Report failure on cancellation + if: ${{ contains(needs.*.result, 'cancelled') || cancelled() }} + run: exit 1 + + # Look for the term "automatically-tag-and-release-this-commit" within merged + # PRs/commits. + push-tag: + runs-on: ubuntu-latest + needs: ci-status + if: | + always() + && needs.ci-status.result == 'success' + && github.event_name == 'push' + && github.ref == 'refs/heads/main' + && github.repository_owner == 'bytecodealliance' + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - name: Test if tag is needed + run: | + git log ${{ github.event.before }}...${{ github.event.after }} | tee main.log + version=$(./ci/print-current-version.sh) + echo "version: $version" + echo "version=$version" >> $GITHUB_OUTPUT + echo "sha=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT + if grep -q "automatically-tag-and-release-this-commit" main.log; then + echo push-tag + echo "push_tag=yes" >> $GITHUB_OUTPUT + else + echo no-push-tag + echo "push_tag=no" >> $GITHUB_OUTPUT + fi + id: tag + - name: Push the tag + run: | + git_refs_url=$(jq .repository.git_refs_url $GITHUB_EVENT_PATH | tr -d '"' | sed 's/{\/sha}//g') + curl -iX POST $git_refs_url \ + -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ + -d @- << EOF + { + "ref": "refs/tags/v${{ steps.tag.outputs.version }}", + "sha": "${{ steps.tag.outputs.sha }}" + } + EOF + if: steps.tag.outputs.push_tag == 'yes' diff --git a/.github/workflows/publish-to-cratesio.yml b/.github/workflows/publish-to-cratesio.yml new file mode 100644 index 0000000000..7dd07bd859 --- /dev/null +++ b/.github/workflows/publish-to-cratesio.yml @@ -0,0 +1,25 @@ +# The purpose of this workflow is to publish the workspace of crates whenever a +# tag is created. This baiscally boils down to running `ci/publish.rs` at the +# right time. + +name: "Publish to crates.io" + +on: + push: + tags: + - 'v*' + +jobs: + publish: + if: github.repository_owner == 'bytecodealliance' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - run: rustup update stable && rustup default stable + - run: | + rustc ci/publish.rs + ./publish publish + env: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} diff --git a/.github/workflows/release-process.yml b/.github/workflows/release-process.yml new file mode 100644 index 0000000000..09c4e025e5 --- /dev/null +++ b/.github/workflows/release-process.yml @@ -0,0 +1,106 @@ +# The purpose of this workflow is to orchestrate Wasmtime's release process as +# much as possible. This specific workflow is responsible for a few timed parts +# of the process: +# +# * On the 5th of every month a new release branch is automatically created and +# the version number of the `main` branch is increased +# * On the 20th of every month the previous release branch is published. +# +# This automation is all done through PRs except for the creation of the release +# branch itself which is an write-action performed by this script. Otherwise +# humans are ideally reviewing and rubber-stamping the output of the script all +# other steps of the way. +# +# Note that this script also helps manage patch releases by sending a PR to the +# release branch with a bumped version number for all crates with a patch-bump. + +name: "Automated Release Process" +on: + # Allow manually triggering this request via the button on the action + # workflow page. + workflow_dispatch: + inputs: + action: + description: 'Publish script argument: "release-major", or "release-patch"' + required: false + default: 'release-major' + +jobs: + release_process: + name: Run the release process + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - name: Setup + run: | + rustc ci/publish.rs + git config user.name 'Auto Release Process' + git config user.email 'auto-release-process@users.noreply.github.com' + git remote set-url origin https://git:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }} + + - run: rustup update stable && rustup default stable + + - run: rustc ci/publish.rs + + - name: Bump major version number + run: ./publish bump + if: github.event.inputs.action == 'release-major' + + - name: Bump minor version number + run: ./publish bump-patch + if: github.event.inputs.action == 'release-minor' + + - name: Prep PR metadata + run: | + set -ex + git fetch origin + + cur=$(./ci/print-current-version.sh) + + git commit --allow-empty -a -F-<> $GITHUB_ENV + echo "PR_TITLE=Release ${{ github.event.repository.name }} $cur" >> $GITHUB_ENV + echo "PR_BASE=release-$cur" >> $GITHUB_ENV + cat > pr-body <<-EOF + This is an automated pull request from CI to release + ${{ github.event.repository.name }} $cur when merged. The commit + message for this PR has a marker that is detected by CI to create + tags and publish crate artifacts. + + [RELEASES.md]: https://github.com/${{ github.repository }}/blob/main/RELEASES.md + [process]: https://docs.wasmtime.dev/contributing-release-process.html + [branch]: https://github.com/${{ github.repository }}/tree/release-$cur + EOF + + - name: Make a PR + # Note that the syntax here is kinda funky, and the general gist is that + # I couldn't figure out a good way to have a multiline string-literal + # become a json-encoded string literal to send to GitHub. This + # represents my best attempt. + run: | + set -ex + body=$(jq -sR < ./pr-body) + + curl --include --request POST \ + https://api.github.com/repos/${{ github.repository }}/pulls \ + --header "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ + --data @- << EOF + { + "head": "$PR_HEAD", + "base": "$PR_BASE", + "title": "$PR_TITLE", + "body": $body, + "maintainer_can_modify": true + + } + EOF diff --git a/Cargo.lock b/Cargo.lock index e30ae2d617..f55d5bba12 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -660,7 +660,7 @@ dependencies = [ [[package]] name = "fuzz-stats" -version = "0.1.0" +version = "0.0.0" dependencies = [ "anyhow", "arbitrary", @@ -1688,7 +1688,7 @@ checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" [[package]] name = "wasm-compose" -version = "0.5.5" +version = "0.200.0" dependencies = [ "anyhow", "glob", @@ -1702,9 +1702,9 @@ dependencies = [ "serde_derive", "serde_yaml", "smallvec", - "wasm-encoder 0.41.2", - "wasmparser 0.121.2", - "wasmprinter 0.2.80", + "wasm-encoder 0.200.0", + "wasmparser 0.200.0", + "wasmprinter 0.200.0", "wat", "wit-component", ] @@ -1720,17 +1720,17 @@ dependencies = [ [[package]] name = "wasm-encoder" -version = "0.41.2" +version = "0.200.0" dependencies = [ "anyhow", "leb128", "tempfile", - "wasmparser 0.121.2", + "wasmparser 0.200.0", ] [[package]] name = "wasm-metadata" -version = "0.10.20" +version = "0.200.0" dependencies = [ "anyhow", "clap 4.4.18", @@ -1739,14 +1739,14 @@ dependencies = [ "serde_derive", "serde_json", "spdx", - "wasm-encoder 0.41.2", - "wasmparser 0.121.2", + "wasm-encoder 0.200.0", + "wasmparser 0.200.0", "wat", ] [[package]] name = "wasm-mutate" -version = "0.2.48" +version = "0.200.0" dependencies = [ "anyhow", "clap 4.4.18", @@ -1755,15 +1755,15 @@ dependencies = [ "log", "rand", "thiserror", - "wasm-encoder 0.41.2", - "wasmparser 0.121.2", - "wasmprinter 0.2.80", + "wasm-encoder 0.200.0", + "wasmparser 0.200.0", + "wasmprinter 0.200.0", "wat", ] [[package]] name = "wasm-mutate-stats" -version = "0.1.0" +version = "0.0.0" dependencies = [ "anyhow", "arbitrary", @@ -1774,14 +1774,14 @@ dependencies = [ "num_cpus", "rand", "wasm-mutate", - "wasmparser 0.121.2", - "wasmprinter 0.2.80", + "wasmparser 0.200.0", + "wasmprinter 0.200.0", "wasmtime", ] [[package]] name = "wasm-shrink" -version = "0.1.49" +version = "0.200.0" dependencies = [ "anyhow", "blake3", @@ -1790,14 +1790,14 @@ dependencies = [ "log", "rand", "wasm-mutate", - "wasmparser 0.121.2", - "wasmprinter 0.2.80", + "wasmparser 0.200.0", + "wasmprinter 0.200.0", "wat", ] [[package]] name = "wasm-smith" -version = "0.16.1" +version = "0.200.0" dependencies = [ "anyhow", "arbitrary", @@ -1810,15 +1810,15 @@ dependencies = [ "rand", "serde", "serde_derive", - "wasm-encoder 0.41.2", - "wasmparser 0.121.2", - "wasmprinter 0.2.80", + "wasm-encoder 0.200.0", + "wasmparser 0.200.0", + "wasmprinter 0.200.0", "wat", ] [[package]] name = "wasm-tools" -version = "1.0.60" +version = "1.0.200" dependencies = [ "addr2line 0.21.0", "anyhow", @@ -1841,37 +1841,37 @@ dependencies = [ "tempfile", "termcolor", "wasm-compose", - "wasm-encoder 0.41.2", + "wasm-encoder 0.200.0", "wasm-metadata", "wasm-mutate", "wasm-shrink", "wasm-smith", - "wasmparser 0.121.2", - "wasmprinter 0.2.80", + "wasmparser 0.200.0", + "wasmprinter 0.200.0", "wast", "wat", "wit-component", - "wit-parser 0.14.0", + "wit-parser 0.200.0", "wit-smith", ] [[package]] name = "wasm-tools-c-api" -version = "0.1.1" +version = "0.0.0" dependencies = [ "arbitrary", "wasm-mutate", "wasm-shrink", "wasm-smith", - "wasmparser 0.121.2", - "wasmprinter 0.2.80", + "wasmparser 0.200.0", + "wasmprinter 0.200.0", "wast", "wat", ] [[package]] name = "wasm-tools-fuzz" -version = "0.0.1" +version = "0.0.0" dependencies = [ "anyhow", "arbitrary", @@ -1879,16 +1879,16 @@ dependencies = [ "libfuzzer-sys", "log", "tempfile", - "wasm-encoder 0.41.2", + "wasm-encoder 0.200.0", "wasm-mutate", "wasm-smith", - "wasmparser 0.121.2", - "wasmprinter 0.2.80", + "wasmparser 0.200.0", + "wasmprinter 0.200.0", "wasmtime", "wast", "wat", "wit-component", - "wit-parser 0.14.0", + "wit-parser 0.200.0", "wit-smith", ] @@ -1915,7 +1915,7 @@ dependencies = [ [[package]] name = "wasmparser" -version = "0.121.2" +version = "0.200.0" dependencies = [ "anyhow", "bitflags 2.4.2", @@ -1926,7 +1926,7 @@ dependencies = [ "once_cell", "rayon", "semver", - "wasm-encoder 0.41.2", + "wasm-encoder 0.200.0", "wast", "wat", ] @@ -1943,13 +1943,13 @@ dependencies = [ [[package]] name = "wasmprinter" -version = "0.2.80" +version = "0.200.0" dependencies = [ "anyhow", "diff", "rayon", "tempfile", - "wasmparser 0.121.2", + "wasmparser 0.200.0", "wast", "wat", ] @@ -2207,7 +2207,7 @@ dependencies = [ [[package]] name = "wast" -version = "71.0.1" +version = "200.0.0" dependencies = [ "anyhow", "bumpalo", @@ -2215,14 +2215,14 @@ dependencies = [ "memchr", "rayon", "unicode-width", - "wasm-encoder 0.41.2", - "wasmparser 0.121.2", + "wasm-encoder 0.200.0", + "wasmparser 0.200.0", "wat", ] [[package]] name = "wat" -version = "1.0.88" +version = "1.0.200" dependencies = [ "wast", ] @@ -2418,7 +2418,7 @@ checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" [[package]] name = "wit-component" -version = "0.21.0" +version = "0.200.0" dependencies = [ "anyhow", "bitflags 2.4.2", @@ -2430,14 +2430,14 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "wasm-encoder 0.41.2", + "wasm-encoder 0.200.0", "wasm-metadata", - "wasmparser 0.121.2", - "wasmprinter 0.2.80", + "wasmparser 0.200.0", + "wasmprinter 0.200.0", "wasmtime", "wast", "wat", - "wit-parser 0.14.0", + "wit-parser 0.200.0", ] [[package]] @@ -2458,7 +2458,7 @@ dependencies = [ [[package]] name = "wit-parser" -version = "0.14.0" +version = "0.200.0" dependencies = [ "anyhow", "env_logger", @@ -2472,26 +2472,26 @@ dependencies = [ "serde_derive", "serde_json", "unicode-xid", - "wasmparser 0.121.2", + "wasmparser 0.200.0", "wat", - "wit-parser 0.14.0", + "wit-parser 0.200.0", ] [[package]] name = "wit-parser-fuzz" -version = "0.0.1" +version = "0.0.0" dependencies = [ "arbitrary", "env_logger", "libfuzzer-sys", "log", - "wasmprinter 0.2.80", - "wit-parser 0.14.0", + "wasmprinter 0.200.0", + "wit-parser 0.200.0", ] [[package]] name = "wit-smith" -version = "0.1.30" +version = "0.200.0" dependencies = [ "arbitrary", "clap 4.4.18", @@ -2499,7 +2499,7 @@ dependencies = [ "log", "semver", "wit-component", - "wit-parser 0.14.0", + "wit-parser 0.200.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 921c2fa6a2..3c1f00053a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasm-tools" -version = "1.0.60" +version = "1.0.200" authors = ["The Wasmtime Project Developers"] edition.workspace = true description = "CLI tools for interoperating with WebAssembly files" @@ -32,6 +32,7 @@ all = "allow" [workspace.package] edition = '2021' +version = "0.200.0" [workspace.dependencies] anyhow = "1.0.58" @@ -56,19 +57,19 @@ pretty_assertions = "1.3.0" semver = "1.0.0" smallvec = "1.11.1" -wasm-compose = { version = "0.5.5", path = "crates/wasm-compose" } -wasm-encoder = { version = "0.41.2", path = "crates/wasm-encoder" } -wasm-metadata = { version = "0.10.20", path = "crates/wasm-metadata" } -wasm-mutate = { version = "0.2.48", path = "crates/wasm-mutate" } -wasm-shrink = { version = "0.1.49", path = "crates/wasm-shrink" } -wasm-smith = { version = "0.16.1", path = "crates/wasm-smith" } -wasmparser = { version = "0.121.2", path = "crates/wasmparser" } -wasmprinter = { version = "0.2.80", path = "crates/wasmprinter" } -wast = { version = "71.0.1", path = "crates/wast" } -wat = { version = "1.0.88", path = "crates/wat" } -wit-component = { version = "0.21.0", path = "crates/wit-component" } -wit-parser = { version = "0.14.0", path = "crates/wit-parser" } -wit-smith = { version = "0.1.30", path = "crates/wit-smith" } +wasm-compose = { version = "0.200.0", path = "crates/wasm-compose" } +wasm-encoder = { version = "0.200.0", path = "crates/wasm-encoder" } +wasm-metadata = { version = "0.200.0", path = "crates/wasm-metadata" } +wasm-mutate = { version = "0.200.0", path = "crates/wasm-mutate" } +wasm-shrink = { version = "0.200.0", path = "crates/wasm-shrink" } +wasm-smith = { version = "0.200.0", path = "crates/wasm-smith" } +wasmparser = { version = "0.200.0", path = "crates/wasmparser" } +wasmprinter = { version = "0.200.0", path = "crates/wasmprinter" } +wast = { version = "200.0.0", path = "crates/wast" } +wat = { version = "1.0.200", path = "crates/wat" } +wit-component = { version = "0.200.0", path = "crates/wit-component" } +wit-parser = { version = "0.200.0", path = "crates/wit-parser" } +wit-smith = { version = "0.200.0", path = "crates/wit-smith" } [dependencies] anyhow = { workspace = true } diff --git a/ci/print-current-version.sh b/ci/print-current-version.sh new file mode 100755 index 0000000000..348b8ce580 --- /dev/null +++ b/ci/print-current-version.sh @@ -0,0 +1,2 @@ +#!/bin/sh +grep '^version =' Cargo.toml | head -n 1 | sed 's/.*"\(.*\)"/\1/' diff --git a/ci/publish.rs b/ci/publish.rs index a55c21bd33..70fcd5a7f6 100644 --- a/ci/publish.rs +++ b/ci/publish.rs @@ -1,30 +1,20 @@ -//! Helper script to manage versions in this repository for various crates. +//! Helper script to publish the wasmtime and cranelift suites of crates //! -//! Three subcommands: +//! See documentation in `docs/contributing-release-process.md` for more +//! information, but in a nutshell: //! -//! * `./publish diff wasmparser` - shows a git diff for the wasmparser -//! crate from the last tagged version to now. Useful for figuring out if a -//! major version bump is needed or not. -//! -//! * `./publish bump crate1:major crate2:minor ...` - performs a major or minor -//! version bump of the crates specified. All crates not mentioned here -//! which transitively depend on these crates are minor-bumped. -//! -//! * `./publish publish` - attempts to publish all crates. Only publishes if -//! their current version isn't already published. Will add wasmtime -//! publication group automatically. A git tag is created for all published -//! crates. +//! * `./publish bump` - bump crate versions in-tree +//! * `./publish publish` - actually publish crates to crates.io use std::collections::HashMap; use std::env; use std::fs; -use std::os::unix::prelude::*; use std::path::{Path, PathBuf}; use std::process::Command; use std::thread; use std::time::Duration; -// Crates we care about publishing sorted topologically. +// note that this list must be topologically sorted by dependencies const CRATES_TO_PUBLISH: &[&str] = &[ "wasm-encoder", "wasmparser", @@ -43,39 +33,28 @@ const CRATES_TO_PUBLISH: &[&str] = &[ "wasm-tools", ]; -const NO_VERIFY: &[&str] = &[ - // Circular dev dependencies between `wasmparser` and `wasm-encoder`. - "wasm-encoder", - "wasmparser", -]; +const API_STABLE_CRATES: &[&str] = &["wasm-tools", "wat"]; -/// A mapping from a crate to those crates which have a public dependency on -/// that crate. -/// -/// This is used so that when a major version bump of the left-hand-side is done -/// then it must also force major version bumps of everything on the -/// right-hand-side. -const PUBLIC_DEPS: &[(&str, &[&str])] = &[ - ("wasmparser", &["wasm-encoder"]), - ("wit-parser", &["wit-component"]), - ("wasm-metadata", &["wit-component"]), -]; +struct Workspace { + version: String, +} -#[derive(Clone)] struct Crate { manifest: PathBuf, name: String, version: String, - // Only set by `bump_version` if the crate was actually updated to get a new - // version. - new_version: Option, publish: bool, + workspace_version: Option, } fn main() { let mut crates = Vec::new(); - crates.push(read_crate("./Cargo.toml".as_ref())); - find_crates("crates".as_ref(), &mut crates); + let root = read_crate(None, "./Cargo.toml".as_ref()); + let ws = Workspace { + version: root.workspace_version.clone().unwrap(), + }; + crates.push(root); + find_crates("crates".as_ref(), &ws, &mut crates); let pos = CRATES_TO_PUBLISH .iter() @@ -85,37 +64,9 @@ fn main() { crates.sort_by_key(|krate| pos.get(&krate.name[..])); match &env::args().nth(1).expect("must have one argument")[..] { - "bump" => { - let mut bumps = env::args() - .skip(2) - .map(|s| { - if let Some(s) = s.strip_suffix(":major") { - (s.to_string(), true) - } else if let Some(s) = s.strip_suffix(":minor") { - (s.to_string(), false) - } else { - panic!("unknown: {}", s); - } - }) - .collect::>(); - - // For all major version bumps automatically do a major version - // bump those crates which have a public dependency on it. - let mut extra = Vec::new(); - for (name, _) in bumps.iter().filter(|(_, major)| *major) { - if let Some((_, public_deps)) = PUBLIC_DEPS.iter().find(|(n, _)| name == n) { - extra.extend(public_deps.iter().map(|name| (name.to_string(), true))); - } - } - bumps.extend(extra); - - // Move all major bumps first in the case of duplicate keys to - // ensure that major bumps are seen first. - bumps.sort_by_key(|(_, major)| if *major { 0 } else { 1 }); - - for (i, mut krate) in crates.clone().into_iter().enumerate() { - bump_version(&mut krate, &mut crates, &bumps); - crates[i] = krate; + name @ "bump" | name @ "bump-patch" => { + for krate in crates.iter() { + bump_version(&krate, &crates, name == "bump-patch"); } // update the lock file assert!(Command::new("cargo") @@ -133,7 +84,7 @@ fn main() { // publish in a loop and we remove crates once they're successfully // published. Failed-to-publish crates get enqueued for another try // later on. - for _ in 0..5 { + for _ in 0..10 { crates.retain(|krate| !publish(krate)); if crates.is_empty() { @@ -144,38 +95,19 @@ fn main() { "{} crates failed to publish, waiting for a bit to retry", crates.len(), ); - thread::sleep(Duration::from_secs(20)); + thread::sleep(Duration::from_secs(40)); } assert!(crates.is_empty(), "failed to publish all crates"); - - println!(""); - println!("==================================================================="); - println!(""); - println!("Don't forget to push tags for this release!"); - println!(""); - println!(" $ git push --tags"); - } - - "diff" => { - let krate = env::args().nth(2).unwrap(); - let krate = crates.iter().find(|c| c.name == krate).unwrap(); - Command::new("git") - .arg("diff") - .arg(format!("{}-{}..HEAD", krate.name, krate.version)) - .arg("--") - .arg(krate.manifest.parent().unwrap()) - .exec(); } s => panic!("unknown command: {}", s), } } -// Recursively looks for `Cargo.toml` in `dir` -fn find_crates(dir: &Path, dst: &mut Vec) { +fn find_crates(dir: &Path, ws: &Workspace, dst: &mut Vec) { if dir.join("Cargo.toml").exists() { - let krate = read_crate(&dir.join("Cargo.toml")); + let krate = read_crate(Some(ws), &dir.join("Cargo.toml")); if !krate.publish || CRATES_TO_PUBLISH.iter().any(|c| krate.name == *c) { dst.push(krate); } else { @@ -186,16 +118,23 @@ fn find_crates(dir: &Path, dst: &mut Vec) { for entry in dir.read_dir().unwrap() { let entry = entry.unwrap(); if entry.file_type().unwrap().is_dir() { - find_crates(&entry.path(), dst); + find_crates(&entry.path(), ws, dst); } } } -fn read_crate(manifest: &Path) -> Crate { +fn read_crate(ws: Option<&Workspace>, manifest: &Path) -> Crate { let mut name = None; let mut version = None; + let mut workspace_version = None; let mut publish = true; + let mut in_workspace = false; for line in fs::read_to_string(manifest).unwrap().lines() { + if line.starts_with("[") { + in_workspace = line.starts_with("[workspace"); + continue; + } + if name.is_none() && line.starts_with("name = \"") { name = Some( line.replace("name = \"", "") @@ -204,72 +143,86 @@ fn read_crate(manifest: &Path) -> Crate { .to_string(), ); } - if version.is_none() && line.starts_with("version = \"") { - version = Some( + if line.starts_with("version = \"") { + let dst = if in_workspace { + &mut workspace_version + } else { + &mut version + }; + assert!(dst.is_none()); + *dst = Some( line.replace("version = \"", "") .replace("\"", "") .trim() .to_string(), ); } + if let Some(ws) = ws { + if version.is_none() && line.starts_with("version.workspace = true") { + version = Some(ws.version.clone()); + } + } if line.starts_with("publish = false") { publish = false; } } let name = name.unwrap(); - let version = version.unwrap(); + let version = if !publish { + "0.0.0".to_string() + } else { + version.unwrap() + }; Crate { manifest: manifest.to_path_buf(), name, version, + workspace_version, publish, - new_version: None, } } -fn bump_version(krate: &mut Crate, crates: &mut [Crate], bumps: &[(String, bool)]) { +fn bump_version(krate: &Crate, crates: &[Crate], patch: bool) { let contents = fs::read_to_string(&krate.manifest).unwrap(); - - let next_version = |target: &Crate| -> String { - // If this crate is publishable then if it's explicitly requested on the - // command line we bump the version. Otherwise we also force a version - // bump if it's the same as this `krate` requested originally for this - // function. This forced bump will be thrown away if no other - // dependencies get updated. - if CRATES_TO_PUBLISH.contains(&&target.name[..]) { - if let Some((_, major)) = bumps.iter().find(|(s, _)| *s == target.name) { - return bump(&target.version, !*major); - } - if target.name == krate.name { - return bump(&target.version, true); - } + let next_version = |krate: &Crate| -> String { + if CRATES_TO_PUBLISH.contains(&&krate.name[..]) { + let patch = patch || API_STABLE_CRATES.contains(&&krate.name[..]); + bump(&krate.version, patch) + } else { + krate.version.clone() } - - // Prefer the `new_version`, if set, over the old version. The new - // version will be updated by this point since crates are sorted - // topologically. - target.new_version.clone().unwrap_or(target.version.clone()) }; let mut new_manifest = String::new(); let mut is_deps = false; - let mut updated_deps = false; + let mut is_workspace = false; for line in contents.lines() { let mut rewritten = false; if !is_deps && line.starts_with("version =") { if CRATES_TO_PUBLISH.contains(&&krate.name[..]) { - new_manifest.push_str(&line.replace(&krate.version, &next_version(krate))); + println!( + "bump `{}` {} => {}", + krate.name, + krate.version, + next_version(krate), + ); + let new_line = if is_workspace { + let ws_version = krate.workspace_version.as_ref().unwrap(); + let next_version = bump(ws_version, patch); + line.replace(ws_version, &next_version) + } else { + line.replace(&krate.version, &next_version(krate)) + }; + new_manifest.push_str(&new_line); rewritten = true; } } - is_deps = if line.starts_with("[") { - line.contains("dependencies") - } else { - is_deps - }; + if line.starts_with("[") { + is_deps = line.contains("dependencies"); + is_workspace = line.contains("workspace"); + } - for other in crates.iter() { + for other in crates { // If `other` isn't a published crate then it's not going to get a // bumped version so we don't need to update anything in the // manifest. @@ -279,7 +232,7 @@ fn bump_version(krate: &mut Crate, crates: &mut [Crate], bumps: &[(String, bool) if !is_deps || !line.starts_with(&format!("{} ", other.name)) { continue; } - if !line.contains(&other.version) && !line.contains("workspace = true") { + if !line.contains(&other.version) { if !line.contains("version =") || !krate.publish { continue; } @@ -288,12 +241,8 @@ fn bump_version(krate: &mut Crate, crates: &mut [Crate], bumps: &[(String, bool) krate.manifest, other.name, other.version ); } - let next = next_version(other); - if next != other.version { - rewritten = true; - updated_deps = true; - new_manifest.push_str(&line.replace(&other.version, &next)); - } + rewritten = true; + new_manifest.push_str(&line.replace(&other.version, &next_version(other))); break; } if !rewritten { @@ -301,16 +250,7 @@ fn bump_version(krate: &mut Crate, crates: &mut [Crate], bumps: &[(String, bool) } new_manifest.push_str("\n"); } - - // Only actually rewrite the manifest if this crate was explicitly requested - // to get bumped or one of its dependencies changed, otherwise nothing - // changed about it. - if updated_deps || bumps.iter().any(|(s, _)| *s == krate.name) { - let new = next_version(krate); - println!("bump `{}` {} => {}", krate.name, krate.version, new,); - fs::write(&krate.manifest, new_manifest).unwrap(); - krate.new_version = Some(new); - } + fs::write(&krate.manifest, new_manifest).unwrap(); } /// Performs a major version bump increment on the semver version `version`. @@ -360,29 +300,17 @@ fn publish(krate: &Crate) -> bool { return true; } - let mut cmd = Command::new("cargo"); - cmd.arg("publish"); - cmd.current_dir(krate.manifest.parent().unwrap()); - - if NO_VERIFY.iter().any(|s| *s == krate.name) { - cmd.arg("--no-verify"); - } - - let status = cmd.status().expect("failed to run cargo"); + let status = Command::new("cargo") + .arg("publish") + .current_dir(krate.manifest.parent().unwrap()) + .arg("--no-verify") + .status() + .expect("failed to run cargo"); if !status.success() { println!("FAIL: failed to publish `{}`: {}", krate.name, status); return false; } - let status = Command::new("git") - .arg("tag") - .arg(format!("{}-{}", krate.name, krate.version)) - .status() - .expect("failed to run git"); - if !status.success() { - panic!("FAIL: failed to tag: {}", status); - } - // After we've published then make sure that the `wasmtime-publish` group is // added to this crate for future publications. If it's already present // though we can skip the `cargo owner` modification. diff --git a/crates/c-api/Cargo.toml b/crates/c-api/Cargo.toml index 594bd92985..c993d4a052 100644 --- a/crates/c-api/Cargo.toml +++ b/crates/c-api/Cargo.toml @@ -7,7 +7,6 @@ edition.workspace = true license = "Apache-2.0 WITH LLVM-exception" readme = "./README.md" repository = "https://github.com/bytecodealliance/wasm-tools/tree/main/crates/c-api" -version = "0.1.1" publish = false [lib] diff --git a/crates/fuzz-stats/Cargo.toml b/crates/fuzz-stats/Cargo.toml index c5c1a6ee09..78048b53a4 100644 --- a/crates/fuzz-stats/Cargo.toml +++ b/crates/fuzz-stats/Cargo.toml @@ -1,6 +1,5 @@ [package] name = "fuzz-stats" -version = "0.1.0" edition.workspace = true publish = false diff --git a/crates/wasm-compose/Cargo.toml b/crates/wasm-compose/Cargo.toml index 66978dd232..fa25c2b2e7 100644 --- a/crates/wasm-compose/Cargo.toml +++ b/crates/wasm-compose/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasm-compose" -version = "0.5.5" +version.workspace = true edition.workspace = true authors = ["Peter Huene "] license = "Apache-2.0 WITH LLVM-exception" diff --git a/crates/wasm-encoder/Cargo.toml b/crates/wasm-encoder/Cargo.toml index 430c6e07fb..b936e01ba9 100644 --- a/crates/wasm-encoder/Cargo.toml +++ b/crates/wasm-encoder/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasm-encoder" -version = "0.41.2" +version.workspace = true authors = ["Nick Fitzgerald "] edition.workspace = true license = "Apache-2.0 WITH LLVM-exception" diff --git a/crates/wasm-metadata/Cargo.toml b/crates/wasm-metadata/Cargo.toml index 8a9c80d23c..0bccc0b1a5 100644 --- a/crates/wasm-metadata/Cargo.toml +++ b/crates/wasm-metadata/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasm-metadata" -version = "0.10.20" +version.workspace = true edition.workspace = true license = "Apache-2.0 WITH LLVM-exception" repository = "https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wasm-metadata" diff --git a/crates/wasm-mutate-stats/Cargo.toml b/crates/wasm-mutate-stats/Cargo.toml index eb04025043..d5d9edf5f8 100644 --- a/crates/wasm-mutate-stats/Cargo.toml +++ b/crates/wasm-mutate-stats/Cargo.toml @@ -1,6 +1,5 @@ [package] name = "wasm-mutate-stats" -version = "0.1.0" edition.workspace = true publish = false diff --git a/crates/wasm-mutate/Cargo.toml b/crates/wasm-mutate/Cargo.toml index 83b39734f7..c7f1541854 100644 --- a/crates/wasm-mutate/Cargo.toml +++ b/crates/wasm-mutate/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasm-mutate" -version = "0.2.48" +version.workspace = true edition.workspace = true license = "Apache-2.0 WITH LLVM-exception" repository = "https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wasm-mutate" diff --git a/crates/wasm-shrink/Cargo.toml b/crates/wasm-shrink/Cargo.toml index a082353f43..84f3ee0c14 100644 --- a/crates/wasm-shrink/Cargo.toml +++ b/crates/wasm-shrink/Cargo.toml @@ -8,7 +8,7 @@ license = "Apache-2.0 WITH LLVM-exception" readme = "./README.md" repository = "https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wasm-shrink" name = "wasm-shrink" -version = "0.1.49" +version.workspace = true [lints] workspace = true diff --git a/crates/wasm-smith/Cargo.toml b/crates/wasm-smith/Cargo.toml index 0403c9ef71..093b95fa09 100644 --- a/crates/wasm-smith/Cargo.toml +++ b/crates/wasm-smith/Cargo.toml @@ -8,7 +8,7 @@ license = "Apache-2.0 WITH LLVM-exception" name = "wasm-smith" readme = "./README.md" repository = "https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wasm-smith" -version = "0.16.1" +version.workspace = true exclude = ["/benches/corpus"] [[bench]] diff --git a/crates/wasmparser/Cargo.toml b/crates/wasmparser/Cargo.toml index 1d7e6dd112..64a86b3f45 100644 --- a/crates/wasmparser/Cargo.toml +++ b/crates/wasmparser/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmparser" -version = "0.121.2" +version.workspace = true authors = ["Yury Delendik "] license = "Apache-2.0 WITH LLVM-exception" repository = "https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wasmparser" diff --git a/crates/wasmprinter/Cargo.toml b/crates/wasmprinter/Cargo.toml index 42d248c2c2..3cb1c4dd6f 100644 --- a/crates/wasmprinter/Cargo.toml +++ b/crates/wasmprinter/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmprinter" -version = "0.2.80" +version.workspace = true authors = ["Alex Crichton "] edition.workspace = true license = "Apache-2.0 WITH LLVM-exception" diff --git a/crates/wast/Cargo.toml b/crates/wast/Cargo.toml index 28e3881675..f0ba9997e8 100644 --- a/crates/wast/Cargo.toml +++ b/crates/wast/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wast" -version = "71.0.1" +version = "200.0.0" authors = ["Alex Crichton "] edition.workspace = true license = "Apache-2.0 WITH LLVM-exception" diff --git a/crates/wat/Cargo.toml b/crates/wat/Cargo.toml index 415d64b11e..4f560fbe48 100644 --- a/crates/wat/Cargo.toml +++ b/crates/wat/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wat" -version = "1.0.88" +version = "1.0.200" authors = ["Alex Crichton "] edition.workspace = true license = "Apache-2.0 WITH LLVM-exception" diff --git a/crates/wit-component/Cargo.toml b/crates/wit-component/Cargo.toml index 709d730dff..19eb573f0b 100644 --- a/crates/wit-component/Cargo.toml +++ b/crates/wit-component/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "wit-component" authors = ["Peter Huene "] -version = "0.21.0" +version.workspace = true edition.workspace = true license = "Apache-2.0 WITH LLVM-exception" readme = "README.md" diff --git a/crates/wit-parser/Cargo.toml b/crates/wit-parser/Cargo.toml index a7259921be..b0ad5eaad8 100644 --- a/crates/wit-parser/Cargo.toml +++ b/crates/wit-parser/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "wit-parser" authors = ["Alex Crichton "] -version = "0.14.0" +version.workspace = true edition.workspace = true license = "Apache-2.0 WITH LLVM-exception" readme = "README.md" diff --git a/crates/wit-parser/fuzz/Cargo.toml b/crates/wit-parser/fuzz/Cargo.toml index 6be0c5262c..734cdb4887 100644 --- a/crates/wit-parser/fuzz/Cargo.toml +++ b/crates/wit-parser/fuzz/Cargo.toml @@ -1,6 +1,5 @@ [package] name = "wit-parser-fuzz" -version = "0.0.1" publish = false edition.workspace = true diff --git a/crates/wit-smith/Cargo.toml b/crates/wit-smith/Cargo.toml index cf96e038ac..16c2c15c3d 100644 --- a/crates/wit-smith/Cargo.toml +++ b/crates/wit-smith/Cargo.toml @@ -5,7 +5,7 @@ edition.workspace = true license = "Apache-2.0 WITH LLVM-exception" name = "wit-smith" repository = "https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wit-smith" -version = "0.1.30" +version.workspace = true [lints] workspace = true diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index b163b513ea..9175f95731 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -1,6 +1,5 @@ [package] name = "wasm-tools-fuzz" -version = "0.0.1" publish = false edition.workspace = true