Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: automate the release process #984

Merged
merged 7 commits into from
Nov 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Attempts to perform a release when a particular tag is pushed. This uses the
# `./scripts/release.sh`, and assumes that the CRATES_TOKEN secret has been set
# and contains an API token with which we can publish our crates to crates.io.
#
# If release operation fails partway through due to a temporary error (e.g. the
# crate being published depends on the crate published just prior, but the prior
# crate isn't yet available via crates.io), one can simply rerun this workflow.
# The release.sh script aims to be an idempotent operation, skipping the
# publishing of crates that have already been published.
name: Release

on:
push:
tags:
- "v[0-9]+.[0-9]+.[0-9]+" # Push events to matching v*, i.e. v0.26.0, v1.0.0
- "v[0-9]+.[0-9]+.[0-9]+-pre.[0-9]+" # e.g. v0.26.0-pre.1

jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- name: Publish crates
run: ./scripts/release.sh
env:
CRATES_TOKEN: ${{ secrets.CRATES_TOKEN }}
3 changes: 1 addition & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ members = [
"ibc-clients/ics07-tendermint/types",
"ibc-clients/ics07-tendermint",
"ibc-clients",
"ibc-core/ics24-host/cosmos",
"ibc-apps/ics20-transfer/types",
"ibc-apps/ics20-transfer",
"ibc-apps",
"ibc-core/ics24-host/cosmos",
"ibc-data-types",
"ibc",
"ibc-query",
Expand Down Expand Up @@ -68,7 +68,6 @@ ibc-core = { version = "0.48.0", path = "./ibc-core", default-feature
ibc-clients = { version = "0.48.0", path = "./ibc-clients", default-features = false }
ibc-apps = { version = "0.48.0", path = "./ibc-apps", default-features = false }
ibc-primitives = { version = "0.48.0", path = "./ibc-primitives", default-features = false }
ibc-testkit = { version = "0.48.0", path = "./ibc-testkit" }
ibc-derive = { version = "0.4.0", path = "./ibc-derive" }

ibc-core-client = { version = "0.48.0", path = "./ibc-core/ics02-client", default-features = false }
Expand Down
25 changes: 18 additions & 7 deletions RELEASES.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Our release process is as follows:
2. Publish `ibc-derive` with `cargo publish -p ibc-derive`
4. Bump the versions of all crates to the new version in their Cargo.toml and in
the root `Cargo.toml` as well, and push these changes to the release PR.
- If you released a new version of `ibc-derive` in step 3, make sure to
- If you released a new version of `ibc-derive` in step 3, make sure to
update that dependency.
5. Run `cargo doc -p ibc --all-features --open` locally to double-check that all
the documentation compiles and seems up-to-date and coherent. Fix any
Expand All @@ -32,14 +32,25 @@ Our release process is as follows:
work. Fix any potential issues here and push them to the release PR.
7. Mark the PR as **Ready for Review** and incorporate feedback on the release.
8. Once approved, merge the PR, and pull the `main` branch.
9. Publish each package to crates.io by running `cargo publish -p <PACKAGE_NAME>`
in the order specified in the workspace `Cargo.toml`.
10. Create a signed tag and push it to GitHub: `git tag -s -a vX.Y.Z`. In the
tag message, write the version and the link to the corresponding section of
the changelog.
- Push the tag with `git push --tags`
9. Create a signed tag `git tag -s -a vX.Y.Z`. In the tag message, write the
version and the link to the corresponding section of the changelog. Then push
the tag to GitHub with `git push --tags`.
- The [release workflow][release.yml] will run the [`release.sh`] script in a
CI worker.
10. If some crates have not been released, check the cause of the failure and
act accordingly:
1. In case of intermittent problems with the registry, rerun the script
locally to publish any missing crates from this release. This step
requires the appropriate privileges to push crates to [crates.io].
2. In case the problems arise from the source files, fix them, bump a new
patch version (e.g. `v0.48.1`) and repeat the process with its
corresponding new tag.
11. Once the tag is pushed, create a GitHub release and append
`[📖CHANGELOG](https://github.com/cosmos/ibc-rs/blob/main/CHANGELOG.md#vXYZ)`
to the release description.

All done! 🎉

[crates.io]: https://crates.io
[`release.sh`]: https://github.com/cosmos/ibc-rs/blob/main/scripts/release.sh
[release.yml]: https://github.com/cosmos/ibc-rs/blob/main/.github/workflows/release.yml
2 changes: 1 addition & 1 deletion ibc-clients/ics07-tendermint/types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ edition = { workspace = true }
rust-version = { workspace = true }
license = { workspace = true }
repository = { workspace = true }
keywords = ["blockchain", "cosmos", "ibc", "transfer", "ics20", "types"]
keywords = ["blockchain", "cosmos", "ibc", "tendermint", "types"]
readme = "./../../README.md"
description = """
Maintained by `ibc-rs`, encapsulates essential ICS-07 Tendermint Client data structures and domain types,
Expand Down
107 changes: 107 additions & 0 deletions scripts/release.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#!/bin/bash

# release.sh will hopefully allow us to publish all of the necessary crates in
# this repo in the right order. It is assumed that only one person will be
# releasing all crates at the same time.

set -euo pipefail

# A space-separated list of all the crates we want to publish, in the order in
# which they must be published. It's important to respect this order, since
# each subsequent crate depends on one or more of the preceding ones.
DEFAULT_CRATES=(
"ibc-primitives"
"ibc-core-host-types"
"ibc-core-router-types"
"ibc-core-commitment-types"
"ibc-core-client-types"
"ibc-core-connection-types"
"ibc-core-channel-types"
"ibc-core-handler-types"
"ibc-core-client-context"
"ibc-core-host"
"ibc-core-router"
"ibc-core-client"
"ibc-core-connection"
"ibc-core-channel"
"ibc-core-handler"
"ibc-core"
"ibc-client-tendermint-types"
"ibc-client-tendermint"
"ibc-clients"
"ibc-app-transfer-types"
"ibc-app-transfer"
"ibc-apps"
"ibc-core-host-cosmos"
"ibc-data-types"
"ibc"
"ibc-query"
"ibc-testkit"
)

# Allows us to override the crates we want to publish.
CRATES=("${@:-${DEFAULT_CRATES[@]}}")

# Additional flags to pass to the "cargo publish" operation for every crate we
# publish.
CARGO_PUBLISH_FLAGS=""

# Allow us to specify a crates.io API token via environment variables. Mostly
# for CI use.
if [ "$CRATES_TOKEN" != "" ]; then
CARGO_PUBLISH_FLAGS="${CARGO_PUBLISH_FLAGS} --token ${CRATES_TOKEN}"
fi

get_manifest_path() {
cargo metadata --format-version 1 | jq -r '.packages[]|select(.name == "'"${1}"'")|.manifest_path'
}

get_local_version() {
cargo metadata --format-version 1 | jq -r '.packages[]|select(.name == "'"${1}"'")|.version'
}

check_version_online() {
curl -s "https://crates.io/api/v1/crates/${1}" | jq -r 'try .versions[]|select(.num == "'"${2}"'").updated_at'
}

publish() {
echo "Publishing crate $1..."
cargo publish --manifest-path "$(get_manifest_path "${1}")" "$CARGO_PUBLISH_FLAGS"
echo ""
}

wait_until_available() {
echo "Waiting for crate ${1} to become available via crates.io..."
for retry in {1..5}; do
sleep 5
ONLINE_DATE="$(check_version_online "${1}" "${2}")"
if [ "$ONLINE_DATE" != "" ]; then
echo "Crate ${crate} is now available online"
break
else
if [ "$retry" == 5 ]; then
echo "ERROR: Crate should have become available by now"
exit 1
else
echo "Not available just yet. Waiting a few seconds..."
fi
fi
done
echo "Waiting an additional 10 seconds for crate to propagate through CDN..."
sleep 10
}

echo "Attempting to publish crate(s): ${CRATES}"

for crate in "$CRATES"; do
VERSION="$(get_local_version "$crate")"
ONLINE_DATE="$(check_version_online "$crate" "$VERSION")"
echo "${crate} version number: ${VERSION}"
if [ "$ONLINE_DATE" != "" ]; then
echo "${crate} ${VERSION} has already been published at ${ONLINE_DATE}, skipping"
continue
fi

publish "$crate"
wait_until_available "$crate" "$VERSION"
done
Loading