From 6d5bebd860e7844d4ca633918a9f8a48f697c48f Mon Sep 17 00:00:00 2001 From: Meet Mangukiya Date: Sat, 14 May 2022 01:40:05 +0530 Subject: [PATCH] Release process and CI (#1240) * Fix the crate versions * release.toml: add cargo-release config * CONTRIBUTING.md: Update Releasing section * feat: add release github workflow * feat: generate CHANGELOGs and create github releases in CI --- .github/workflows/release-tag-from.js | 37 +++++++ .github/workflows/releases.yml | 99 +++++++++++++++++++ CONTRIBUTING.md | 64 ++++-------- Cargo.lock | 20 ++-- Cargo.toml | 4 +- ethers-addressbook/Cargo.toml | 2 +- ethers-contract/Cargo.toml | 2 +- .../ethers-contract-abigen/Cargo.toml | 4 +- .../ethers-contract-derive/Cargo.toml | 2 +- ethers-core/Cargo.toml | 2 +- ethers-core/ethers-derive-eip712/Cargo.toml | 2 +- ethers-etherscan/Cargo.toml | 2 +- ethers-middleware/Cargo.toml | 2 +- ethers-providers/Cargo.toml | 2 +- ethers-signers/Cargo.toml | 4 +- ethers-solc/Cargo.toml | 4 +- examples/ethers-wasm/Cargo.toml | 2 +- release.toml | 2 + 18 files changed, 182 insertions(+), 74 deletions(-) create mode 100644 .github/workflows/release-tag-from.js create mode 100644 .github/workflows/releases.yml create mode 100644 release.toml diff --git a/.github/workflows/release-tag-from.js b/.github/workflows/release-tag-from.js new file mode 100644 index 00000000..b796824e --- /dev/null +++ b/.github/workflows/release-tag-from.js @@ -0,0 +1,37 @@ +const semver = require("semver"); + +const previousVersion = (currentVersion, releaseType) => { + const parsedVersion = semver.parse(currentVersion); + + switch (releaseType) { + case "major": { + return `v${parsedVersion.major - 1}.0.0`; + } + case "minor": { + return `v${parsedVersion.major}.${parsedVersion.minor - 1}.0`; + } + case "patch": { + return `v${parsedVersion.major}.${parsedVersion.minor}.${ + parsedVersion.patch - 1 + }`; + } + case "alpha": { + return `v${parsedVersion.major}.${parsedVersion.minor}.${ + parsedVersion.patch + }-alpha.${parsedVersion.prerelease[1] - 1}`; + } + case "beta": { + return `v${parsedVersion.major}.${parsedVersion.minor}.${ + parsedVersion.patch + }-beta.${parsedVersion.prerelease[1] - 1}`; + } + case "rc": { + return `v${parsedVersion.major}.${parsedVersion.minor}.${ + parsedVersion.patch + }-rc.${parsedVersion.prerelease[1] - 1}`; + } + } +}; + +const [currentVersion, releaseType] = process.argv.slice(-2); +console.log(previousVersion(currentVersion, releaseType)); diff --git a/.github/workflows/releases.yml b/.github/workflows/releases.yml new file mode 100644 index 00000000..6dc4ad0a --- /dev/null +++ b/.github/workflows/releases.yml @@ -0,0 +1,99 @@ +name: Release + +on: + schedule: + - cron: "0 0 * * 0" + + workflow_dispatch: + inputs: + release_type: + type: choice + description: Release type + options: + - major + - minor + - patch + - rc + - beta + - alpha + +permissions: + contents: write + +jobs: + release: + runs-on: ubuntu-latest + env: + CARGO_TOKEN: ${{ secrets.CARGO_TOKEN }} + RELEASE_TYPE: ${{ github.event.inputs.release_type }} + steps: + - name: Checkout sources + uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Configure git + run: | + git config user.name github-actions + git config user.email github-actions@github.com + - name: Rust stable + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + - uses: Swatinem/rust-cache@v1 + with: + cache-on-failure: true + - name: Install cargo-release + uses: actions-rs/install@v0.1 + with: + crate: cargo-release + version: latest + - name: Cargo login + run: | + cargo login $CARGO_TOKEN + - name: Dry-run cargo release + run: | + cargo release --workspace ${RELEASE_TYPE:-alpha} --exclude ethers-wasm + - name: Publish release + run: | + cargo release --workspace ${RELEASE_TYPE:-alpha} --exclude ethers-wasm --execute --no-confirm + - name: Setup node + uses: actions/setup-node@v3 + with: + node-version: 14 + - run: | + npm i semver + - name: Install git-cliff + uses: actions-rs/install@v0.1 + with: + crate: git-cliff + version: latest + - name: Publish changelog + id: changelog + run: | + current_version=$(git tag --contains HEAD -l "v*" | head -1) + from_version=$(node .github/workflows/release-tag-from.js $current_version $RELEASE_TYPE) + echo from $from_version to $current_version + + echo "::set-output name=release_version::$(echo $current_version)" + + if git rev-parse "$from_version" >/dev/null 2>&1; then + echo "tag exists, can generate changelog"; + else + echo "tag does not exist, cannot generate changelog, publish github release manually" + exit 0 + fi + + git cliff $from_version..$current_version > GENERATED_CHANGELOG.md + cat GENERATED_CHANGELOG.md + - name: Create GitHub release + id: release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + RELEASE_VERSION: ${{ steps.changelog.outputs.release_version }} + with: + tag_name: ${{ env.RELEASE_VERSION }} + release_name: ${{ env.RELEASE_VERSION }} + body_path: GENERATED_CHANGELOG.md + prerelease: ${{ env.RELEASE_TYPE == 'alpha' }} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 42525537..233aa78e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -189,7 +189,7 @@ of `ethers-rs` will create an instance of `Provider` is by using `Provider::::try_from`, this is how the documentation test is structured. Lines that start with `/// #` are removed when the documentation is generated. -They are only there to get the test to run. +They are only there to get the test to run. ### Commits @@ -370,58 +370,28 @@ _Adapted from the [Tokio contributing guide](https://github.com/tokio-rs/tokio/b Since the ethers-rs project consists of a number of crates, many of which depend on each other, releasing new versions to crates.io can involve some complexities. -When releasing a new version of a crate, follow these steps: +We use [`cargo-release`](https://github.com/crate-ci/cargo-release) to manage these +complexities and the whole release process. -1. **Ensure that the release crate has no path dependencies.** When the HEAD - version of a ethers-rs crate requires unreleased changes in another ethers-rs crate, - the crates.io dependency on the second crate will be replaced with a path - dependency. Crates with path dependencies cannot be published, so before - publishing the dependent crate, any path dependencies must also be published. - This should be done through a form of depth-first tree traversal: +When releasing the workspace: - 1. Starting with the first path dependency in the crate to be released, - inspect the `Cargo.toml` for the dependency. If the dependency has any - path dependencies of its own, repeat this step with the first such - dependency. - 2. Begin the release process for the path dependency. - 3. Once the path dependency has been published to crates.io, update the - dependent crate to depend on the crates.io version. - 4. When all path dependencies have been published, the dependent crate may - be published. - - To verify that a crate is ready to publish, run: - - ```bash - bin/publish --dry-run - ``` - -2. **Update Cargo metadata.** After releasing any path dependencies, update the - `version` field in `Cargo.toml` to the new version, and the `documentation` - field to the docs.rs URL of the new version. -3. **Update other documentation links.** Update the `#![doc(html_root_url)]` - attribute in the crate's `lib.rs` and the "Documentation" link in the crate's - `README.md` to point to the docs.rs URL of the new version. -4. **Update the changelog for the crate.** Each crate in the ethers-rs repository - has its own `CHANGELOG.md` in that crate's subdirectory. Any changes to that - crate since the last release should be added to the changelog. Change - descriptions may be taken from the Git history, but should be edited to - ensure a consistent format, based on [Keep A Changelog][keep-a-changelog]. - Other entries in that crate's changelog may also be used for reference. -5. **Perform a final audit for breaking changes.** Compare the HEAD version of +1. **Perform a final audit for breaking changes.** Compare the HEAD version of crate with the Git tag for the most recent release version. If there are any breaking API changes, determine if those changes can be made without breaking - existing APIs. If so, resolve those issues. Otherwise, if it is necessary to - make a breaking release, update the version numbers to reflect this. -6. **Open a pull request with your changes.** Once that pull request has been - approved by a maintainer and the pull request has been merged, continue to - the next step. -7. **Release the crate.** Run the following command: + existing APIs. If so, resolve those issues and make a `minor` change + release. Otherwise, if it is necessary to make a breaking release, make a + `major` change release. +2. **Dry run the release** by running `cargo release --workspace ` +3. **Update the changelog for the crate.** Changelog for all crates go in + [`CHANGELOG.md`](./CHANGELOG.md). Any unreleased changes changelogs should + be moved to respective crates released changelogs. Change descriptions + may be taken from the Git history, but should be edited to ensure a consistent + format, based on [Keep A Changelog][keep-a-changelog]. Other entries in that + crate's changelog may also be used for reference. +4. **Release the crate.** Run the following command: ```bash - bin/publish + cargo release --workspace --execute ``` - Your editor and prompt you to edit a message for the tag. Copy the changelog - entry for that release version into your editor and close the window. - [keep-a-changelog]: https://github.com/olivierlacan/keep-a-changelog/blob/master/CHANGELOG.md diff --git a/Cargo.lock b/Cargo.lock index 93feaa97..8fdbc201 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1150,7 +1150,7 @@ dependencies = [ [[package]] name = "ethers" -version = "0.6.0" +version = "0.6.2" dependencies = [ "bytes", "ethers-addressbook", @@ -1181,7 +1181,7 @@ dependencies = [ [[package]] name = "ethers-contract" -version = "0.6.0" +version = "0.6.2" dependencies = [ "ethers-contract-abigen", "ethers-contract-derive", @@ -1203,7 +1203,7 @@ dependencies = [ [[package]] name = "ethers-contract-abigen" -version = "0.6.0" +version = "0.6.3" dependencies = [ "Inflector", "cfg-if 1.0.0", @@ -1226,7 +1226,7 @@ dependencies = [ [[package]] name = "ethers-contract-derive" -version = "0.6.0" +version = "0.6.3" dependencies = [ "ethers-contract-abigen", "ethers-core", @@ -1239,7 +1239,7 @@ dependencies = [ [[package]] name = "ethers-core" -version = "0.6.0" +version = "0.6.3" dependencies = [ "arrayvec 0.7.2", "bincode", @@ -1268,7 +1268,7 @@ dependencies = [ [[package]] name = "ethers-derive-eip712" -version = "0.2.0" +version = "0.2.2" dependencies = [ "ethers-contract", "ethers-contract-derive", @@ -1282,7 +1282,7 @@ dependencies = [ [[package]] name = "ethers-etherscan" -version = "0.2.0" +version = "0.2.2" dependencies = [ "ethers-core", "ethers-solc", @@ -1301,7 +1301,7 @@ dependencies = [ [[package]] name = "ethers-middleware" -version = "0.6.0" +version = "0.6.2" dependencies = [ "async-trait", "ethers-contract", @@ -1329,7 +1329,7 @@ dependencies = [ [[package]] name = "ethers-providers" -version = "0.6.0" +version = "0.6.2" dependencies = [ "async-trait", "auto_impl", @@ -1366,7 +1366,7 @@ dependencies = [ [[package]] name = "ethers-signers" -version = "0.6.0" +version = "0.6.2" dependencies = [ "async-trait", "coins-bip32", diff --git a/Cargo.toml b/Cargo.toml index d63af71e..de7a3807 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ethers" -version = "0.6.0" +version = "0.6.2" authors = ["Georgios Konstantopoulos "] license = "MIT OR Apache-2.0" edition = "2021" @@ -150,4 +150,4 @@ required-features = ["trezor"] [[example]] name = "yubi" path = "examples/yubi.rs" -required-features = ["yubi"] \ No newline at end of file +required-features = ["yubi"] diff --git a/ethers-addressbook/Cargo.toml b/ethers-addressbook/Cargo.toml index 73a8d47a..792df280 100644 --- a/ethers-addressbook/Cargo.toml +++ b/ethers-addressbook/Cargo.toml @@ -8,4 +8,4 @@ once_cell = "1.10.0" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -ethers-core = { path = "../ethers-core" } +ethers-core = { path = "../ethers-core", version = "^0.6.0" } diff --git a/ethers-contract/Cargo.toml b/ethers-contract/Cargo.toml index 554e2971..1f0cd464 100644 --- a/ethers-contract/Cargo.toml +++ b/ethers-contract/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "ethers-contract" license = "MIT OR Apache-2.0" -version = "0.6.0" +version = "0.6.2" authors = ["Georgios Konstantopoulos "] edition = "2018" description = "Smart contract bindings for the ethers-rs crate" diff --git a/ethers-contract/ethers-contract-abigen/Cargo.toml b/ethers-contract/ethers-contract-abigen/Cargo.toml index dbe63ad5..759a535a 100644 --- a/ethers-contract/ethers-contract-abigen/Cargo.toml +++ b/ethers-contract/ethers-contract-abigen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ethers-contract-abigen" -version = "0.6.0" +version = "0.6.3" authors = ["Nicholas Rodrigues Lordello ", "Georgios Konstantopoulos "] edition = "2018" license = "MIT OR Apache-2.0" @@ -41,4 +41,4 @@ rustls = ["reqwest/rustls-tls"] [dev-dependencies] tempfile = "3.2.0" -ethers-solc = { path = "../../ethers-solc", default-features = false, features = ["project-util"] } +ethers-solc = { version = "^0.3.0", path = "../../ethers-solc", default-features = false, features = ["project-util"] } diff --git a/ethers-contract/ethers-contract-derive/Cargo.toml b/ethers-contract/ethers-contract-derive/Cargo.toml index a4311090..251e98f5 100644 --- a/ethers-contract/ethers-contract-derive/Cargo.toml +++ b/ethers-contract/ethers-contract-derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ethers-contract-derive" -version = "0.6.0" +version = "0.6.3" authors = ["Nicholas Rodrigues Lordello ", "Georgios Konstantopoulos "] edition = "2018" license = "MIT OR Apache-2.0" diff --git a/ethers-core/Cargo.toml b/ethers-core/Cargo.toml index 2d3d61af..1cc5ac7a 100644 --- a/ethers-core/Cargo.toml +++ b/ethers-core/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "ethers-core" license = "MIT OR Apache-2.0" -version = "0.6.0" +version = "0.6.3" authors = ["Georgios Konstantopoulos "] edition = "2018" description = "Core structures for the ethers-rs crate" diff --git a/ethers-core/ethers-derive-eip712/Cargo.toml b/ethers-core/ethers-derive-eip712/Cargo.toml index 82155397..3194fc6a 100644 --- a/ethers-core/ethers-derive-eip712/Cargo.toml +++ b/ethers-core/ethers-derive-eip712/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ethers-derive-eip712" -version = "0.2.0" +version = "0.2.2" edition = "2018" description = "Custom derive macro for EIP-712 typed data" license = "MIT OR Apache-2.0" diff --git a/ethers-etherscan/Cargo.toml b/ethers-etherscan/Cargo.toml index 0687567d..e5ee05d0 100644 --- a/ethers-etherscan/Cargo.toml +++ b/ethers-etherscan/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ethers-etherscan" -version = "0.2.0" +version = "0.2.2" authors = ["Matthias Seitz ", "Georgios Konstantopoulos "] license = "MIT OR Apache-2.0" edition = "2018" diff --git a/ethers-middleware/Cargo.toml b/ethers-middleware/Cargo.toml index e16d26ff..8da735d7 100644 --- a/ethers-middleware/Cargo.toml +++ b/ethers-middleware/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "ethers-middleware" license = "MIT OR Apache-2.0" -version = "0.6.0" +version = "0.6.2" authors = ["Georgios Konstantopoulos "] edition = "2018" description = "Middleware implementations for the ethers-rs crate" diff --git a/ethers-providers/Cargo.toml b/ethers-providers/Cargo.toml index 90f0069b..4d2c6adc 100644 --- a/ethers-providers/Cargo.toml +++ b/ethers-providers/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "ethers-providers" license = "MIT OR Apache-2.0" -version = "0.6.0" +version = "0.6.2" authors = ["Georgios Konstantopoulos "] edition = "2018" description = "Provider implementations for the ethers-rs crate" diff --git a/ethers-signers/Cargo.toml b/ethers-signers/Cargo.toml index 25ec3bf3..cbe24383 100644 --- a/ethers-signers/Cargo.toml +++ b/ethers-signers/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "ethers-signers" license = "MIT OR Apache-2.0" -version = "0.6.0" +version = "0.6.2" authors = ["Georgios Konstantopoulos "] edition = "2018" description = "Signer implementations for the ethers-rs crate" @@ -42,7 +42,7 @@ home = { version = "0.5.3", optional = true } [dev-dependencies] ethers-contract = { version = "^0.6.0", path = "../ethers-contract", features = ["eip712", "abigen"]} -ethers-derive-eip712 = { version = "0.2.0", path = "../ethers-core/ethers-derive-eip712" } +ethers-derive-eip712 = { version = "^0.2.0", path = "../ethers-core/ethers-derive-eip712" } serde_json = { version = "1.0.64" } tracing-subscriber = "0.3.11" yubihsm = { version = "0.40.0", features = ["secp256k1", "usb", "mockhsm"] } diff --git a/ethers-solc/Cargo.toml b/ethers-solc/Cargo.toml index 8427ede4..a184ea32 100644 --- a/ethers-solc/Cargo.toml +++ b/ethers-solc/Cargo.toml @@ -44,8 +44,8 @@ path-slash = "0.1.4" home = "0.5.3" # SVM is not WASM compatible yet. # svm = { package = "svm-rs", default-features = false, version = "0.2.7", optional = true } -svm = { package = "svm-rs", default-features = false, git = "https://github.com/roynalnaruto/svm-rs", optional = true, features = ["blocking"] } -svm-builds = { package = "svm-rs-builds", git = "https://github.com/roynalnaruto/svm-rs", optional = true} +svm = { package = "svm-rs", version = "0.2.9", default-features = false, git = "https://github.com/roynalnaruto/svm-rs", optional = true, features = ["blocking"] } +svm-builds = { package = "svm-rs-builds", version = "0.1.0", git = "https://github.com/roynalnaruto/svm-rs", optional = true} [target.'cfg(target_arch = "wasm32")'.dependencies] # NOTE: this enables wasm compatibility for getrandom indirectly diff --git a/examples/ethers-wasm/Cargo.toml b/examples/ethers-wasm/Cargo.toml index 35a4ab52..ccc36499 100644 --- a/examples/ethers-wasm/Cargo.toml +++ b/examples/ethers-wasm/Cargo.toml @@ -19,7 +19,7 @@ crate-type = ["cdylib", "rlib"] default = ["console_error_panic_hook"] [dependencies] -ethers = { path = "../..", features = ["abigen", "legacy", "ws"] } +ethers = { path = "../..", version = "0.6.0", features = ["abigen", "legacy", "ws"] } serde_derive = "1.0.126" wasm-bindgen-futures = "0.4.30" serde_json = "1.0.64" diff --git a/release.toml b/release.toml new file mode 100644 index 00000000..d55f4e95 --- /dev/null +++ b/release.toml @@ -0,0 +1,2 @@ +consolidate-commits = false +consolidate-pushes = true