diff --git a/.claude/skills/release-finalize/SKILL.md b/.claude/skills/release-finalize/SKILL.md new file mode 100644 index 0000000000..428db15888 --- /dev/null +++ b/.claude/skills/release-finalize/SKILL.md @@ -0,0 +1,128 @@ +--- +name: release-finalize +description: Tag, publish, and verify a merged substrate-relay release +--- + +# Release Finalize + +After a release PR has been merged, create the git tag, verify the Docker build, and create a GitHub Release. + +## Usage + +``` +/release-finalize +``` + +No arguments required. The skill reads the version from `substrate-relay/Cargo.toml` on the current branch. + +## Prerequisites + +- The release PR must be merged to `master` +- You should be on (or able to switch to) the `master` branch with the merged changes + +## Procedure + +### Step 1: Verify State + +Ensure we're on `master` with the latest changes: + +```bash +git checkout master +git pull +``` + +Read the version: + +```bash +grep '^version' substrate-relay/Cargo.toml +``` + +Check that the version doesn't already have a tag: + +```bash +git tag -l "v" +``` + +If the tag already exists, inform the user and skip to Step 4. + +### Step 2: Create Annotated Tag + +**Ask user for confirmation before proceeding.** + +Show the user what will happen: +- Tag: `v` +- This will trigger the `build-tag.yml` workflow +- Docker images will be pushed to Docker Hub + +Create the tag: + +```bash +git tag -a v -m "Release v" +``` + +### Step 3: Push Tag + +**Ask user for confirmation before pushing.** + +```bash +git push origin v +``` + +This triggers the `build-tag.yml` pipeline which builds and pushes: +- `docker.io/paritytech/substrate-relay:v` +- `docker.io/paritytech/bridges-common-relay:v` + +### Step 4: Wait for Docker Build + +Monitor the build-tag pipeline: + +```bash +gh run list --workflow=build-tag.yml --limit=5 +``` + +Wait for the run to complete. Check status periodically: + +```bash +gh run watch +``` + +### Step 5: Create GitHub Release + +Collect bundled chain versions for the release notes: + +```bash +grep 'spec_version' relay-clients/client-*/src/lib.rs +``` + +Create the release: + +```bash +gh release create v --title "Release v" --notes "$(cat <<'EOF' +Docker reference: `paritytech/substrate-relay:v` + +Bundled Chain Versions: + +- Rococo: `` +- Westend: `` +- Kusama: `` +- Polkadot: `` +- Rococo Bridge Hub: `` +- Westend Bridge Hub: `` +- Kusama Bridge Hub: `` +- Polkadot Bridge Hub: `` +- Rococo Bulletin: `None` (must be specified in CLI) +- Polkadot Bulletin: `None` (must be specified in CLI) +EOF +)" --generate-notes +``` + +### Step 6: Post-Release + +Report completion: +- Tag: `v` +- Docker image: `paritytech/substrate-relay:v` +- GitHub Release URL + +Suggest next steps: +1. Deploy via ArgoCD: go to [deploy.yml](https://github.com/paritytech/parity-bridges-common/actions/workflows/deploy.yml) and run workflow with the new version tag +2. After deployment: run `/check-health all` to verify relay health diff --git a/.claude/skills/release-pr/SKILL.md b/.claude/skills/release-pr/SKILL.md new file mode 100644 index 0000000000..9b273213ae --- /dev/null +++ b/.claude/skills/release-pr/SKILL.md @@ -0,0 +1,102 @@ +--- +name: release-pr +description: Create a release PR from prepared release changes +--- + +# Release PR + +Create a release pull request from changes prepared by `/release-prepare`. + +## Usage + +``` +/release-pr +``` + +No arguments required. The skill detects the release details from the current workspace changes. + +## Prerequisites + +- Changes from `/release-prepare` must be present in the working tree (not yet committed) +- Working tree should be on a clean base (no unrelated uncommitted changes) + +## Procedure + +### Step 1: Detect Release Details + +Read the current state to determine what was changed: + +```bash +git diff --name-only +``` + +From the diff, identify: +- Which chain was updated (check `relay-clients/client-bridge-hub-*/src/lib.rs` for spec_version changes) +- The new relay version from `substrate-relay/Cargo.toml` +- The new spec_version from the modified `lib.rs` + +If no release-related changes are detected, inform the user and suggest running `/release-prepare` first. + +### Step 2: Final Verification + +Run build and lint checks: + +```bash +cargo check --workspace +SKIP_WASM_BUILD=1 cargo clippy --all-targets --locked --workspace +``` + +If either fails, report the errors and stop. Do not create a PR with failing checks. + +### Step 3: Read All Bundled Chain Versions + +Collect spec_version from every relay-client for the PR body: + +```bash +grep 'spec_version' relay-clients/client-*/src/lib.rs +``` + +### Step 4: Create Branch and Commit + +```bash +git checkout -b release-v +git add relay-clients/ substrate-relay/Cargo.toml Cargo.lock +git commit -m "Release v" +``` + +Use the actual relay version read from `substrate-relay/Cargo.toml`. + +### Step 5: Push and Create PR + +```bash +git push -u origin release-v +``` + +Create the PR with the `A-release` label: + +```bash +gh pr create --title "Release v" --label "A-release" --body "$(cat <<'EOF' +## Summary +- Bump substrate-relay version to +- Update spec_version: +- Regenerate runtime codegen + +## Bundled Chain Versions + + +Docker reference: `paritytech/substrate-relay:v` + +## Test plan +- [ ] CI passes (fmt, clippy, check, test, deny) +- [ ] Verify spec_version matches on-chain runtime +- [ ] Verify codegen_runtime.rs regenerated correctly +EOF +)" +``` + +### Step 6: Report + +Output: +- PR URL +- Summary of changes included +- Remind: "After PR is merged, run `/release-finalize` to tag and publish" diff --git a/.claude/skills/release-prepare/SKILL.md b/.claude/skills/release-prepare/SKILL.md new file mode 100644 index 0000000000..1d09eedb08 --- /dev/null +++ b/.claude/skills/release-prepare/SKILL.md @@ -0,0 +1,80 @@ +--- +name: release-prepare +description: Prepare a BridgeHub runtime upgrade for substrate-relay +argument-hint: " " +--- + +# Release Prepare + +Prepare the workspace for a BridgeHub runtime upgrade by running the automated script and verifying the result. + +## Usage + +``` +/release-prepare BridgeHubKusama v1.1.6 +/release-prepare BridgeHubPolkadot v1.4.1 +``` + +`$ARGUMENTS` must contain two values: the chain name and the Fellows runtimes release version (vX.Y.Z). + +## Procedure + +### Step 1: Validate Arguments + +Parse `$ARGUMENTS` into `CHAIN` (first word) and `VERSION` (second word). + +Valid chains: `BridgeHubKusama`, `BridgeHubPolkadot`. +Version must match `vX.Y.Z`. + +If arguments are missing or invalid, explain the usage and ask the user. + +### Step 2: Record Current State + +Before making changes, read the current values for comparison: + +```bash +grep 'spec_version' relay-clients/client-bridge-hub-kusama/src/lib.rs +grep 'spec_version' relay-clients/client-bridge-hub-polkadot/src/lib.rs +grep '^version' substrate-relay/Cargo.toml +``` + +### Step 3: Run the Release Script + +Execute the preparation script: + +```bash +./scripts/prepare-bridge-hub-release.sh $CHAIN $VERSION +``` + +This script will: +1. Download the WASM runtime from polkadot-fellows/runtimes +2. Update `spec_version` in the relay-client `lib.rs` +3. Regenerate `codegen_runtime.rs` using runtime-codegen +4. Apply the BlakeTwo256 workaround and format +5. Bump the substrate-relay patch version + +If the script fails, report the error and suggest remediation. + +### Step 4: Verify Build + +Run workspace checks to confirm the changes compile: + +```bash +cargo check --workspace +``` + +If it fails, inspect the errors. Common issues: +- Missing type imports in codegen (BlakeTwo256 fix may need adjustment) +- Version mismatch between runtime and expected types + +### Step 5: Report Results + +Summarize the changes: + +- **Chain**: which chain was updated +- **Spec version**: old → new +- **Relay version**: old → new +- **Files modified**: list from git diff +- **Build status**: pass/fail + +Suggest next step: run `/release-pr` to create the release PR. diff --git a/.claude/skills/release/SKILL.md b/.claude/skills/release/SKILL.md new file mode 100644 index 0000000000..6d00d73156 --- /dev/null +++ b/.claude/skills/release/SKILL.md @@ -0,0 +1,86 @@ +--- +name: release +description: Guide the substrate-relay release lifecycle +argument-hint: "[BridgeHubKusama|BridgeHubPolkadot] [runtime-version]" +--- + +# substrate-relay Release + +Orchestrate the full release lifecycle for substrate-relay. This skill chains the sub-skills `/release-prepare`, `/release-pr`, and `/release-finalize` into a single flow. + +Reference `RELEASE.md` for upstream documentation. + +## Usage + +``` +/release # Interactive: detect or ask which chain +/release BridgeHubKusama v1.1.6 # Direct: specify chain and runtime version +``` + +If `$ARGUMENTS` contains a chain name and version, pass them through. Otherwise, detect the need or ask the user. + +## Procedure + +### Step 1: Verify Release Need + +Determine why a release is needed: + +1. Check if version guard alerts are firing (suggests chain runtime upgrade): + - Look for `"Aborting relay"` in recent logs +2. Check recent commits for chain version bumps: `git log --oneline -20` +3. Check if any relay-client `SimpleRuntimeVersion` constants are outdated + +If `$ARGUMENTS` provides a chain and version, skip detection and proceed to Step 2. + +If no arguments and no clear signal, ask the user which chain needs updating and what Fellows runtime version to use. Valid chains: `BridgeHubKusama`, `BridgeHubPolkadot`. + +### Step 2: Prepare Release + +Run the `/release-prepare` skill logic: + +1. Execute `./scripts/prepare-bridge-hub-release.sh ` +2. Run `cargo check --workspace` to verify +3. Report: old spec_version → new spec_version, old relay version → new relay version + +If this step fails, report errors and stop. + +### Step 3: Create Release PR + +Run the `/release-pr` skill logic: + +1. Run final checks (`cargo check`, `cargo clippy`) +2. Create branch `release-v` +3. Stage relevant files, commit, push +4. Create PR with `A-release` label via `gh pr create` +5. Output the PR URL + +### Step 4: Wait for Merge + +Print: +> PR created. After the PR is reviewed and merged, run `/release-finalize` to tag, publish the Docker image, and create a GitHub Release. + +Stop here. The remaining steps happen after merge via `/release-finalize`. + +### Step 5: Post-Merge (via /release-finalize) + +After merge, `/release-finalize` handles: +- Creating annotated git tag `v` (with user confirmation) +- Pushing tag to trigger `build-tag.yml` +- Waiting for Docker build to complete +- Creating GitHub Release with bundled chain versions + +### Step 6: Deploy via ArgoCD + +After `/release-finalize` completes: + +1. Go to [deploy.yml](https://github.com/paritytech/parity-bridges-common/actions/workflows/deploy.yml) +2. Run workflow with the new version tag +3. This deploys to ArgoCD app `bridges-common-relay` with packages: `headers-a`, `headers-b`, `parachains-a`, `parachains-b`, `messages-a`, `messages-b` + +### Step 7: Post-Deploy Verification + +After deployment, run `/check-health all` to verify: +- Finality sync resumes +- Message delivery resumes +- Version guard alerts clear +- Relay balances stable diff --git a/scripts/prepare-bridge-hub-release.sh b/scripts/prepare-bridge-hub-release.sh new file mode 100755 index 0000000000..6f24473e46 --- /dev/null +++ b/scripts/prepare-bridge-hub-release.sh @@ -0,0 +1,202 @@ +#!/usr/bin/env bash +# +# Prepare a BridgeHub runtime upgrade for substrate-relay. +# +# Downloads the new WASM runtime, updates spec_version, regenerates codegen, +# applies the BlakeTwo256 workaround, and bumps the relay version. +# +# Usage: ./scripts/prepare-bridge-hub-release.sh +# Example: ./scripts/prepare-bridge-hub-release.sh BridgeHubKusama v1.1.6 +# +# Does NOT: run cargo check, commit, create PR, or touch git. + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +MATRIX_FILE="$SCRIPT_DIR/runtime-matrix.json" + +usage() { + echo "Usage: $0 " + echo "" + echo " runtime-version: Fellows runtimes release tag, e.g. v1.1.6" + echo "" + echo "Example: $0 BridgeHubKusama v1.1.6" + exit 1 +} + +die() { + echo "ERROR: $*" >&2 + exit 1 +} + +# --- Validate inputs --- + +if [[ $# -ne 2 ]]; then + usage +fi + +CHAIN_NAME="$1" +RUNTIME_VERSION="$2" + +if ! command -v jq &>/dev/null; then + die "jq is required but not found. Install it with: brew install jq" +fi + +if [[ ! -f "$MATRIX_FILE" ]]; then + die "Runtime matrix file not found: $MATRIX_FILE" +fi + +# Check chain name exists in matrix +CHAIN_ENTRY=$(jq -r --arg name "$CHAIN_NAME" '.[] | select(.name == $name)' "$MATRIX_FILE") +if [[ -z "$CHAIN_ENTRY" ]]; then + VALID_NAMES=$(jq -r '.[].name' "$MATRIX_FILE" | tr '\n' ', ' | sed 's/,$//') + die "Unknown chain: $CHAIN_NAME. Valid chains: $VALID_NAMES" +fi + +# Validate version format: vX.Y.Z +if [[ ! "$RUNTIME_VERSION" =~ ^v([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then + die "Invalid version format: $RUNTIME_VERSION. Expected vX.Y.Z (e.g. v1.1.6)" +fi + +MAJOR="${BASH_REMATCH[1]}" +MINOR="${BASH_REMATCH[2]}" +PATCH="${BASH_REMATCH[3]}" + +# --- Parse version --- + +# v1.1.6 → RELEASE_VERSION=v1001006, SPEC_VERSION=1_001_006 +RELEASE_VERSION="v$(printf '%d%03d%03d' "$MAJOR" "$MINOR" "$PATCH")" +SPEC_VERSION="$(printf '%d_%03d_%03d' "$MAJOR" "$MINOR" "$PATCH")" + +echo "=== Preparing $CHAIN_NAME release ===" +echo " Runtime version: $RUNTIME_VERSION" +echo " Release version: $RELEASE_VERSION" +echo " Spec version: $SPEC_VERSION" + +# --- Read matrix entry --- + +RUNTIME_URI_TEMPLATE=$(echo "$CHAIN_ENTRY" | jq -r '.runtime_uri') +RUNTIME_FILE_TEMPLATE=$(echo "$CHAIN_ENTRY" | jq -r '.runtime_file') +TARGET_DIR=$(echo "$CHAIN_ENTRY" | jq -r '.target_dir') + +# Substitute placeholders +RUNTIME_URI="${RUNTIME_URI_TEMPLATE//\$\{RUNTIME_VERSION\}/$RUNTIME_VERSION}" +RUNTIME_URI="${RUNTIME_URI//\$\{RELEASE_VERSION\}/$RELEASE_VERSION}" +RUNTIME_FILE="${RUNTIME_FILE_TEMPLATE//\$\{RUNTIME_VERSION\}/$RUNTIME_VERSION}" +RUNTIME_FILE="${RUNTIME_FILE//\$\{RELEASE_VERSION\}/$RELEASE_VERSION}" + +echo " Download URL: $RUNTIME_URI" +echo " Target dir: $TARGET_DIR" + +# --- Download WASM --- + +TMPDIR=$(mktemp -d) +trap 'rm -rf "$TMPDIR"' EXIT + +WASM_PATH="$TMPDIR/$RUNTIME_FILE" + +echo "" +echo "--- Downloading WASM runtime ---" +if ! curl -sL --fail -o "$WASM_PATH" "$RUNTIME_URI"; then + die "Failed to download WASM from: $RUNTIME_URI" +fi + +WASM_SIZE=$(wc -c < "$WASM_PATH" | tr -d ' ') +echo " Downloaded: $RUNTIME_FILE ($WASM_SIZE bytes)" + +# --- Update spec_version --- + +LIB_RS="$REPO_ROOT/$TARGET_DIR/lib.rs" +if [[ ! -f "$LIB_RS" ]]; then + die "lib.rs not found: $LIB_RS" +fi + +echo "" +echo "--- Updating spec_version in $TARGET_DIR/lib.rs ---" + +OLD_SPEC=$(grep 'spec_version:' "$LIB_RS" | sed 's/.*spec_version: *\([0-9_]*\).*/\1/' || true) +if [[ -z "$OLD_SPEC" ]]; then + die "Could not find spec_version in $LIB_RS" +fi + +echo " Old spec_version: $OLD_SPEC" +echo " New spec_version: $SPEC_VERSION" + +# Replace spec_version value (preserves surrounding whitespace and format) +sed -i'' -e "s/spec_version: ${OLD_SPEC}/spec_version: ${SPEC_VERSION}/" "$LIB_RS" + +# Verify the replacement happened +if ! grep -q "spec_version: ${SPEC_VERSION}" "$LIB_RS"; then + die "Failed to update spec_version in $LIB_RS" +fi + +# --- Regenerate codegen --- + +echo "" +echo "--- Regenerating codegen_runtime.rs ---" + +CODEGEN_OUTPUT="$REPO_ROOT/$TARGET_DIR/codegen_runtime.rs" + +( + cd "$REPO_ROOT/tools/runtime-codegen" + cargo run --bin runtime-codegen --release -- --from-wasm-file "$WASM_PATH" +) > "$CODEGEN_OUTPUT" + +echo " Generated: $TARGET_DIR/codegen_runtime.rs" + +# --- Apply BlakeTwo256 fix --- + +echo "" +echo "--- Applying BlakeTwo256 workaround ---" + +(cd "$REPO_ROOT" && cargo +nightly fmt --all) + +find "$REPO_ROOT" -name codegen_runtime.rs -exec \ + sed -i'' -e 's/::sp_runtime::generic::Header<::core::primitive::u32>/::sp_runtime::generic::Header<::core::primitive::u32, ::sp_runtime::traits::BlakeTwo256>/g' {} + + +(cd "$REPO_ROOT" && cargo +nightly fmt --all) + +echo " BlakeTwo256 fix applied and formatted" + +# --- Bump substrate-relay version --- + +echo "" +echo "--- Bumping substrate-relay patch version ---" + +CARGO_TOML="$REPO_ROOT/substrate-relay/Cargo.toml" +OLD_RELAY_VERSION=$(grep '^version' "$CARGO_TOML" | head -1 | sed 's/.*"\(.*\)".*/\1/') + +if [[ ! "$OLD_RELAY_VERSION" =~ ^([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then + die "Could not parse relay version: $OLD_RELAY_VERSION" +fi + +RELAY_MAJOR="${BASH_REMATCH[1]}" +RELAY_MINOR="${BASH_REMATCH[2]}" +RELAY_PATCH="${BASH_REMATCH[3]}" +NEW_RELAY_VERSION="${RELAY_MAJOR}.${RELAY_MINOR}.$((RELAY_PATCH + 1))" + +sed -i'' -e "s/^version = \"${OLD_RELAY_VERSION}\"/version = \"${NEW_RELAY_VERSION}\"/" "$CARGO_TOML" + +echo " Old relay version: $OLD_RELAY_VERSION" +echo " New relay version: $NEW_RELAY_VERSION" + +# --- Summary --- + +echo "" +echo "=== Release preparation complete ===" +echo "" +echo " Chain: $CHAIN_NAME" +echo " Runtime version: $RUNTIME_VERSION" +echo " Spec version: $OLD_SPEC → $SPEC_VERSION" +echo " Relay version: $OLD_RELAY_VERSION → $NEW_RELAY_VERSION" +echo "" +echo "Modified files:" +echo " - $TARGET_DIR/lib.rs" +echo " - $TARGET_DIR/codegen_runtime.rs" +echo " - substrate-relay/Cargo.toml" +echo "" +echo "Next steps:" +echo " 1. Run: cargo check --workspace" +echo " 2. Run: cargo test --workspace" +echo " 3. Commit and create a release PR" diff --git a/scripts/runtime-matrix.json b/scripts/runtime-matrix.json new file mode 100644 index 0000000000..13cdb70cd9 --- /dev/null +++ b/scripts/runtime-matrix.json @@ -0,0 +1,14 @@ +[ + { + "name": "BridgeHubPolkadot", + "runtime_uri": "https://github.com/polkadot-fellows/runtimes/releases/download/${RUNTIME_VERSION}/bridge-hub-polkadot_runtime-${RELEASE_VERSION}.compact.compressed.wasm", + "runtime_file": "bridge-hub-polkadot_runtime-${RELEASE_VERSION}.compact.compressed.wasm", + "target_dir": "relay-clients/client-bridge-hub-polkadot/src" + }, + { + "name": "BridgeHubKusama", + "runtime_uri": "https://github.com/polkadot-fellows/runtimes/releases/download/${RUNTIME_VERSION}/bridge-hub-kusama_runtime-${RELEASE_VERSION}.compact.compressed.wasm", + "runtime_file": "bridge-hub-kusama_runtime-${RELEASE_VERSION}.compact.compressed.wasm", + "target_dir": "relay-clients/client-bridge-hub-kusama/src" + } +]