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
This commit is contained in:
parent
135bca4680
commit
6d5bebd860
|
@ -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));
|
|
@ -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' }}
|
|
@ -189,7 +189,7 @@ of `ethers-rs` will create an instance of `Provider` is by using
|
|||
`Provider::<T>::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 <CRATE NAME> <CRATE VERSION>
|
||||
```
|
||||
|
||||
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 <release_type>`
|
||||
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 <NAME OF CRATE> <VERSION>
|
||||
cargo release --workspace <release_type> --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
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "ethers"
|
||||
version = "0.6.0"
|
||||
version = "0.6.2"
|
||||
authors = ["Georgios Konstantopoulos <me@gakonst.com>"]
|
||||
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"]
|
||||
required-features = ["yubi"]
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -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 <me@gakonst.com>"]
|
||||
edition = "2018"
|
||||
description = "Smart contract bindings for the ethers-rs crate"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "ethers-contract-abigen"
|
||||
version = "0.6.0"
|
||||
version = "0.6.3"
|
||||
authors = ["Nicholas Rodrigues Lordello <nlordell@gmail.com>", "Georgios Konstantopoulos <me@gakonst.com>"]
|
||||
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"] }
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "ethers-contract-derive"
|
||||
version = "0.6.0"
|
||||
version = "0.6.3"
|
||||
authors = ["Nicholas Rodrigues Lordello <nlordell@gmail.com>", "Georgios Konstantopoulos <me@gakonst.com>"]
|
||||
edition = "2018"
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
|
|
@ -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 <me@gakonst.com>"]
|
||||
edition = "2018"
|
||||
description = "Core structures for the ethers-rs crate"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "ethers-etherscan"
|
||||
version = "0.2.0"
|
||||
version = "0.2.2"
|
||||
authors = ["Matthias Seitz <matthias.seitz@outlook.de>", "Georgios Konstantopoulos <me@gakonst.com>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2018"
|
||||
|
|
|
@ -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 <me@gakonst.com>"]
|
||||
edition = "2018"
|
||||
description = "Middleware implementations for the ethers-rs crate"
|
||||
|
|
|
@ -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 <me@gakonst.com>"]
|
||||
edition = "2018"
|
||||
description = "Provider implementations for the ethers-rs crate"
|
||||
|
|
|
@ -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 <me@gakonst.com>"]
|
||||
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"] }
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
consolidate-commits = false
|
||||
consolidate-pushes = true
|
Loading…
Reference in New Issue