From ff8ffc03d2540db44f6c5e544c356e4a81cc053b Mon Sep 17 00:00:00 2001 From: Farhad Shabani Date: Thu, 23 Nov 2023 21:18:21 -0800 Subject: [PATCH] feat: add release.yaml to CI --- .github/workflows/release.yaml | 27 +++++++++ Cargo.toml | 3 +- scripts/release.sh | 105 +++++++++++++++++++++++++++++++++ 3 files changed, 133 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/release.yaml create mode 100755 scripts/release.sh diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 000000000..9428d4ace --- /dev/null +++ b/.github/workflows/release.yaml @@ -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 }} \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index c4c0367ee..aabc8d1c8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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", @@ -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 } diff --git a/scripts/release.sh b/scripts/release.sh new file mode 100755 index 000000000..168484fd2 --- /dev/null +++ b/scripts/release.sh @@ -0,0 +1,105 @@ +#!/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 -e + +# 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 [ -n "${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 [ -n "${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 [ -n "${ONLINE_DATE}" ]; then + echo "${crate} ${VERSION} has already been published at ${ONLINE_DATE}, skipping" + continue + fi + + publish "${crate}" + wait_until_available "${crate}" "${VERSION}" +done \ No newline at end of file