From 7cfac64d0f50972784f150ad899b741c118faa9a Mon Sep 17 00:00:00 2001 From: Bruno Devic Date: Fri, 23 Jan 2026 11:06:42 +0100 Subject: [PATCH 1/4] chore: initial commit with test crates --- .../workflows/release-80_publish-crates.yml | 214 ++++++++++++++++++ Cargo.lock | 19 ++ Cargo.toml | 5 + .../release/test-parity-publish-staging.sh | 202 +++++++++++++++++ scripts/release/test-staging-publish.sh | 158 +++++++++++++ test-crates/parity-staging-test-a/Cargo.toml | 9 + test-crates/parity-staging-test-a/src/lib.rs | 14 ++ test-crates/parity-staging-test-b/Cargo.toml | 10 + test-crates/parity-staging-test-b/src/lib.rs | 17 ++ test-crates/parity-staging-test-c/Cargo.toml | 11 + test-crates/parity-staging-test-c/src/lib.rs | 24 ++ 11 files changed, 683 insertions(+) create mode 100644 .github/workflows/release-80_publish-crates.yml create mode 100755 scripts/release/test-parity-publish-staging.sh create mode 100755 scripts/release/test-staging-publish.sh create mode 100644 test-crates/parity-staging-test-a/Cargo.toml create mode 100644 test-crates/parity-staging-test-a/src/lib.rs create mode 100644 test-crates/parity-staging-test-b/Cargo.toml create mode 100644 test-crates/parity-staging-test-b/src/lib.rs create mode 100644 test-crates/parity-staging-test-c/Cargo.toml create mode 100644 test-crates/parity-staging-test-c/src/lib.rs diff --git a/.github/workflows/release-80_publish-crates.yml b/.github/workflows/release-80_publish-crates.yml new file mode 100644 index 0000000000000..b049cebac09c7 --- /dev/null +++ b/.github/workflows/release-80_publish-crates.yml @@ -0,0 +1,214 @@ +name: Release - Publish Crates + +on: + workflow_dispatch: + inputs: + release_name: + description: 'Release name (e.g., stable2509-3). Base branch is derived by removing the last -N suffix.' + required: true + type: string + dry_run: + description: 'Dry run - do not actually publish crates' + required: true + type: boolean + default: true + +permissions: + contents: write + +jobs: + set-image: + runs-on: ubuntu-latest + outputs: + IMAGE: ${{ steps.set_image.outputs.IMAGE }} + steps: + - name: Checkout + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + + - id: set_image + run: cat .github/env >> $GITHUB_OUTPUT + + publish-crates: + needs: set-image + runs-on: ubuntu-latest + environment: release + env: + PGP_KMS_KEY: ${{ secrets.PGP_KMS_SIGN_COMMITS_KEY }} + PGP_KMS_HASH: ${{ secrets.PGP_KMS_HASH }} + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + AWS_DEFAULT_REGION: ${{ secrets.AWS_DEFAULT_REGION }} + container: + image: ${{ needs.set-image.outputs.IMAGE }} + + steps: + - name: Install pgpkms + run: | + # Install pgpkms that is used to sign commits + pip install git+https://github.com/paritytech-release/pgpkms.git@6cb1cecce1268412189b77e4b130f4fa248c4151 + + - name: Derive stable branch from release name + id: derive_branch + run: | + RELEASE_NAME="${{ inputs.release_name }}" + echo "Release name: $RELEASE_NAME" + + # Extract stable branch by removing the last -N suffix + # e.g., stable2509-3 -> stable2509 + if [[ "$RELEASE_NAME" =~ ^(.+)-[0-9]+$ ]]; then + STABLE_BRANCH="${BASH_REMATCH[1]}" + else + # If no suffix, use the release name as-is (first release) + STABLE_BRANCH="$RELEASE_NAME" + fi + + echo "Stable branch: $STABLE_BRANCH" + echo "STABLE_BRANCH=$STABLE_BRANCH" >> $GITHUB_OUTPUT + + # I am calling it like this because we will call post crates workflow after on this one + echo "RELEASE_BRANCH=post-crates-release-$RELEASE_NAME" >> $GITHUB_OUTPUT + + - name: Checkout stable branch + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + ref: ${{ steps.derive_branch.outputs.STABLE_BRANCH }} + fetch-depth: 0 + + - name: Import GPG keys + shell: bash + run: | + . ./.github/scripts/common/lib.sh + import_gpg_keys + + - name: Configure git + shell: bash + run: | + git config --global --add safe.directory "${GITHUB_WORKSPACE}" + git config --global commit.gpgsign true + PGPKMS_PATH=$(which pgpkms-git) + echo "Using pgpkms-git at: $PGPKMS_PATH" + git config --global gpg.program "$PGPKMS_PATH" + git config --global user.name "ParityReleases" + git config --global user.email "release-team@parity.io" + git config --global user.signingKey "D8018FBB3F534D866A45998293C5FB5F6A367B51" + + - name: Create release branch + run: | + RELEASE_BRANCH="${{ steps.derive_branch.outputs.RELEASE_BRANCH }}" + echo "Creating branch: $RELEASE_BRANCH" + + git checkout -b "$RELEASE_BRANCH" + echo "Successfully created branch $RELEASE_BRANCH" + + - name: Rust Cache + uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 + with: + cache-on-failure: true + + - name: Install parity-publish + run: cargo install parity-publish --locked -q + + - name: Run parity-publish plan + run: | + echo "Running parity-publish plan..." + parity-publish plan --prdoc prdoc + + - name: Save Plan.toml diff + run: | + RELEASE_NAME="${{ inputs.release_name }}" + mkdir -p release-artifacts + + echo "Saving Plan.toml diff..." + git diff Plan.toml > "release-artifacts/changed_crates_${RELEASE_NAME}.txt" + + echo "Plan.toml changes:" + cat "release-artifacts/changed_crates_${RELEASE_NAME}.txt" + + - name: Parse crate names for release notes + run: | + RELEASE_NAME="${{ inputs.release_name }}" + + echo "Parsing crate names..." + python3 scripts/release/parse-crates-names.py \ + "release-artifacts/changed_crates_${RELEASE_NAME}.txt" \ + scripts/release/templates/crates_list.md.tera + + echo "Crates list:" + cat scripts/release/templates/crates_list.md.tera + + - name: Commit Plan.toml and crates list + shell: bash + run: | + . ./.github/scripts/release/release_lib.sh + + git add Plan.toml scripts/release/templates/crates_list.md.tera + + if [[ -n $(git status --porcelain) ]]; then + commit_with_message "chore: update Plan.toml and crates list for ${{ inputs.release_name }}" + echo "Committed Plan.toml and crates list" + else + echo "No changes to commit" + fi + + - name: Run parity-publish apply + run: | + echo "Running parity-publish apply..." + parity-publish apply + + - name: Update Cargo.lock + run: | + echo "Updating Cargo.lock..." + cargo update --workspace --offline || cargo update --workspace + echo "Cargo.lock updated" + + - name: Commit version bumps + shell: bash + run: | + . ./.github/scripts/release/release_lib.sh + + git add -A + + if [[ -n $(git status --porcelain) ]]; then + commit_with_message "chore: apply version bumps for ${{ inputs.release_name }}" + echo "Committed version bumps" + else + echo "No changes to commit" + fi + + - name: Push release branch + run: | + RELEASE_BRANCH="${{ steps.derive_branch.outputs.RELEASE_BRANCH }}" + echo "Pushing branch $RELEASE_BRANCH..." + git push origin "$RELEASE_BRANCH" + echo "Successfully pushed $RELEASE_BRANCH" + + - name: Configure cargo for staging.crates.io + run: | + echo "Configuring cargo to use staging.crates.io..." + mkdir -p ~/.cargo + + cat >> ~/.cargo/config.toml << 'EOF' + [registries.crates-io] + index = "sparse+https://index.staging.crates.io/" + EOF + + echo "Cargo config:" + cat ~/.cargo/config.toml + + - name: Publish crates to staging.crates.io + env: + PARITY_PUBLISH_CRATESIO_TOKEN: ${{ secrets.CRATESIO_PUBLISH_TOKEN }} + run: | + DRY_RUN="${{ inputs.dry_run }}" + + if [ "$DRY_RUN" = "true" ]; then + echo "DRY RUN - Not actually publishing crates" + echo "Would run: parity-publish apply -p --batch-delay 15 --max-concurrent 1 --batch-size 1" + echo "" + echo "Crates that would be published:" + parity-publish apply --print || true + else + echo "Publishing crates to staging.crates.io..." + parity-publish apply -p --batch-delay 15 --max-concurrent 1 --batch-size 1 + echo "Crates published successfully!" + fi diff --git a/Cargo.lock b/Cargo.lock index c8658f9c4e892..888db99733a56 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14457,6 +14457,25 @@ dependencies = [ "syn 2.0.98", ] +[[package]] +name = "parity-staging-test-a" +version = "0.1.0" + +[[package]] +name = "parity-staging-test-b" +version = "0.1.0" +dependencies = [ + "parity-staging-test-a", +] + +[[package]] +name = "parity-staging-test-c" +version = "0.1.0" +dependencies = [ + "parity-staging-test-a", + "parity-staging-test-b", +] + [[package]] name = "parity-wasm" version = "0.45.0" diff --git a/Cargo.toml b/Cargo.toml index a873db170b9f2..d723c047d8ef7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -578,6 +578,11 @@ members = [ "templates/solochain/runtime", "templates/zombienet", "umbrella", + + # Test crates for staging.crates.io validation (temporary) + "test-crates/parity-staging-test-a", + "test-crates/parity-staging-test-b", + "test-crates/parity-staging-test-c", ] default-members = [ diff --git a/scripts/release/test-parity-publish-staging.sh b/scripts/release/test-parity-publish-staging.sh new file mode 100755 index 0000000000000..c576531c551d4 --- /dev/null +++ b/scripts/release/test-parity-publish-staging.sh @@ -0,0 +1,202 @@ +#!/bin/bash +# +# Test parity-publish workflow against staging.crates.io +# +# This script tests the full parity-publish workflow: +# 1. parity-publish plan --prdoc prdoc +# 2. parity-publish apply +# 3. parity-publish apply -p (publish) +# +# Uses environment variables to redirect to staging.crates.io without +# modifying your local cargo config. +# +# Usage: +# ./scripts/release/test-parity-publish-staging.sh [options] +# +# Options: +# --dry-run Don't actually publish +# --token TOKEN crates.io API token (or set STAGING_CRATESIO_TOKEN env var) +# --parity-publish PATH Path to parity-publish binary +# --step STEP Run only specific step: plan, apply, publish, or all (default: all) +# --help Show this help message +# +# Examples: +# # Full dry run +# ./scripts/release/test-parity-publish-staging.sh --dry-run +# +# # Run only the plan step +# ./scripts/release/test-parity-publish-staging.sh --step plan +# +# # Full publish to staging +# ./scripts/release/test-parity-publish-staging.sh --token YOUR_TOKEN +# + +set -e + +# Default values +DRY_RUN=false +TOKEN="${STAGING_CRATESIO_TOKEN:-}" +PARITY_PUBLISH_PATH="${PARITY_PUBLISH_PATH:-../parity-publish/target/release/parity-publish}" +STEP="all" + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +print_help() { + sed -n '2,/^$/p' "$0" | sed 's/^# //' | sed 's/^#//' +} + +log_info() { + echo -e "${GREEN}[INFO]${NC} $1" +} + +log_step() { + echo -e "${BLUE}[STEP]${NC} $1" +} + +log_warn() { + echo -e "${YELLOW}[WARN]${NC} $1" +} + +log_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +# Parse arguments +while [[ $# -gt 0 ]]; do + case $1 in + --dry-run) + DRY_RUN=true + shift + ;; + --token) + TOKEN="$2" + shift 2 + ;; + --parity-publish) + PARITY_PUBLISH_PATH="$2" + shift 2 + ;; + --step) + STEP="$2" + shift 2 + ;; + --help|-h) + print_help + exit 0 + ;; + *) + log_error "Unknown option: $1" + print_help + exit 1 + ;; + esac +done + +# Validate step +if [[ ! "$STEP" =~ ^(plan|apply|publish|all)$ ]]; then + log_error "Invalid step: $STEP. Must be: plan, apply, publish, or all" + exit 1 +fi + +# Check parity-publish exists +if [[ ! -x "$PARITY_PUBLISH_PATH" ]]; then + log_error "parity-publish not found at: $PARITY_PUBLISH_PATH" + log_info "Set PARITY_PUBLISH_PATH environment variable or use --parity-publish flag" + log_info "Example: export PARITY_PUBLISH_PATH=../parity-publish/target/release/parity-publish" + exit 1 +fi + +log_info "Using parity-publish at: $PARITY_PUBLISH_PATH" +log_info "parity-publish version:" +"$PARITY_PUBLISH_PATH" --version || true +echo "" + +# Check token for publish step +if [[ "$STEP" == "publish" || "$STEP" == "all" ]] && [[ -z "$TOKEN" ]] && [[ "$DRY_RUN" == "false" ]]; then + log_error "No token provided for publish step. Use --token or set STAGING_CRATESIO_TOKEN env var" + log_info "For dry run, use --dry-run flag" + exit 1 +fi + +# Set environment variables for staging.crates.io +export CARGO_REGISTRIES_CRATES_IO_INDEX="sparse+https://index.staging.crates.io/" +export PARITY_PUBLISH_CRATESIO_TOKEN="$TOKEN" + +log_info "============================================" +log_info " Testing parity-publish with staging.crates.io" +log_info "============================================" +log_info "Registry: staging.crates.io" +log_info "Step: $STEP" +log_info "Dry run: $DRY_RUN" +echo "" + +# Step 1: Plan +if [[ "$STEP" == "plan" || "$STEP" == "all" ]]; then + log_step "1/3 - Running parity-publish plan..." + echo "" + + "$PARITY_PUBLISH_PATH" plan --prdoc prdoc + + log_info "Plan completed. Check Plan.toml for the publish plan." + echo "" + + if [[ "$STEP" == "plan" ]]; then + log_info "Plan step completed. Run with --step apply to continue." + exit 0 + fi +fi + +# Step 2: Apply +if [[ "$STEP" == "apply" || "$STEP" == "all" ]]; then + log_step "2/3 - Running parity-publish apply..." + echo "" + + "$PARITY_PUBLISH_PATH" apply + + log_info "Apply completed. Version bumps have been applied to Cargo.toml files." + echo "" + + # Update Cargo.lock + log_info "Updating Cargo.lock..." + cargo update --workspace --offline || cargo update --workspace + log_info "Cargo.lock updated." + echo "" + + if [[ "$STEP" == "apply" ]]; then + log_info "Apply step completed. Run with --step publish to publish." + exit 0 + fi +fi + +# Step 3: Publish +if [[ "$STEP" == "publish" || "$STEP" == "all" ]]; then + log_step "3/3 - Publishing crates..." + echo "" + + if [[ "$DRY_RUN" == "true" ]]; then + log_warn "DRY RUN - Not actually publishing" + log_info "Would run: $PARITY_PUBLISH_PATH apply -p --batch-delay 15 --max-concurrent 1 --batch-size 1" + echo "" + log_info "Crates that would be published:" + "$PARITY_PUBLISH_PATH" apply --print || true + else + log_info "Publishing to staging.crates.io..." + "$PARITY_PUBLISH_PATH" apply -p --batch-delay 15 --max-concurrent 1 --batch-size 1 + + log_info "Publish completed!" + fi + echo "" +fi + +log_info "============================================" +log_info " All steps completed!" +log_info "============================================" + +if [[ "$DRY_RUN" == "false" ]] && [[ "$STEP" == "publish" || "$STEP" == "all" ]]; then + log_info "Check your crates at: https://staging.crates.io" +fi diff --git a/scripts/release/test-staging-publish.sh b/scripts/release/test-staging-publish.sh new file mode 100755 index 0000000000000..f39c2d04375ab --- /dev/null +++ b/scripts/release/test-staging-publish.sh @@ -0,0 +1,158 @@ +#!/bin/bash +# +# Test script for publishing crates to staging.crates.io +# +# This script allows you to test the crate publishing flow without affecting +# production crates.io. It uses environment variables to redirect cargo to +# staging.crates.io instead of modifying your local cargo config. +# +# Usage: +# ./scripts/release/test-staging-publish.sh [options] +# +# Options: +# --dry-run Don't actually publish, just show what would be published +# --token TOKEN crates.io API token (or set STAGING_CRATESIO_TOKEN env var) +# --crates LIST Comma-separated list of crates to publish (default: test crates) +# --help Show this help message +# +# Examples: +# # Dry run with test crates +# ./scripts/release/test-staging-publish.sh --dry-run +# +# # Publish test crates to staging +# ./scripts/release/test-staging-publish.sh --token YOUR_TOKEN +# +# # Publish specific crates +# ./scripts/release/test-staging-publish.sh --crates "parity-staging-test-a,parity-staging-test-b" +# + +set -e + +# Default values +DRY_RUN=false +TOKEN="${STAGING_CRATESIO_TOKEN:-}" +CRATES="parity-staging-test-a,parity-staging-test-b,parity-staging-test-c" +PARITY_PUBLISH_PATH="${PARITY_PUBLISH_PATH:-../parity-publish/target/release/parity-publish}" + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +print_help() { + sed -n '2,/^$/p' "$0" | sed 's/^# //' | sed 's/^#//' +} + +log_info() { + echo -e "${GREEN}[INFO]${NC} $1" +} + +log_warn() { + echo -e "${YELLOW}[WARN]${NC} $1" +} + +log_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +# Parse arguments +while [[ $# -gt 0 ]]; do + case $1 in + --dry-run) + DRY_RUN=true + shift + ;; + --token) + TOKEN="$2" + shift 2 + ;; + --crates) + CRATES="$2" + shift 2 + ;; + --parity-publish) + PARITY_PUBLISH_PATH="$2" + shift 2 + ;; + --help|-h) + print_help + exit 0 + ;; + *) + log_error "Unknown option: $1" + print_help + exit 1 + ;; + esac +done + +# Check parity-publish exists +if [[ ! -x "$PARITY_PUBLISH_PATH" ]]; then + log_error "parity-publish not found at: $PARITY_PUBLISH_PATH" + log_info "Set PARITY_PUBLISH_PATH environment variable or use --parity-publish flag" + log_info "Example: export PARITY_PUBLISH_PATH=/path/to/parity-publish" + exit 1 +fi + +log_info "Using parity-publish at: $PARITY_PUBLISH_PATH" + +# Check token +if [[ -z "$TOKEN" ]] && [[ "$DRY_RUN" == "false" ]]; then + log_error "No token provided. Use --token or set STAGING_CRATESIO_TOKEN env var" + log_info "For dry run, use --dry-run flag" + exit 1 +fi + +# Set environment variables for staging.crates.io +# This redirects cargo to use staging without modifying your config files +export CARGO_REGISTRIES_CRATES_IO_INDEX="sparse+https://index.staging.crates.io/" +export PARITY_PUBLISH_CRATESIO_TOKEN="$TOKEN" + +log_info "Configured to publish to: staging.crates.io" +log_info "Crates to publish: $CRATES" +log_info "Dry run: $DRY_RUN" +echo "" + +# Convert comma-separated crates to array +IFS=',' read -ra CRATE_ARRAY <<< "$CRATES" + +if [[ "$DRY_RUN" == "true" ]]; then + log_info "=== DRY RUN MODE ===" + log_info "Would publish the following crates to staging.crates.io:" + echo "" + for crate in "${CRATE_ARRAY[@]}"; do + echo " - $crate" + done + echo "" + log_info "To actually publish, run without --dry-run flag" +else + log_info "=== PUBLISHING TO STAGING.CRATES.IO ===" + echo "" + + # Publish each crate in order (respecting dependencies) + for crate in "${CRATE_ARRAY[@]}"; do + log_info "Publishing $crate..." + + # Use cargo publish directly for individual crates + # This is simpler than using parity-publish for test crates + cargo publish \ + -p "$crate" \ + --registry crates-io \ + --allow-dirty \ + 2>&1 || { + log_error "Failed to publish $crate" + exit 1 + } + + log_info "Successfully published $crate" + + # Wait a bit between publishes to avoid rate limiting + log_info "Waiting 30 seconds before next publish..." + sleep 30 + done + + echo "" + log_info "=== ALL CRATES PUBLISHED SUCCESSFULLY ===" + log_info "Check them at: https://staging.crates.io" +fi diff --git a/test-crates/parity-staging-test-a/Cargo.toml b/test-crates/parity-staging-test-a/Cargo.toml new file mode 100644 index 0000000000000..1a6efa5b50567 --- /dev/null +++ b/test-crates/parity-staging-test-a/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "parity-staging-test-a" +version = "0.1.0" +edition = "2021" +description = "Test crate A for staging.crates.io publishing validation" +license = "Apache-2.0" +repository = "https://github.com/paritytech/polkadot-sdk" + +[dependencies] diff --git a/test-crates/parity-staging-test-a/src/lib.rs b/test-crates/parity-staging-test-a/src/lib.rs new file mode 100644 index 0000000000000..a39f98ea0f4de --- /dev/null +++ b/test-crates/parity-staging-test-a/src/lib.rs @@ -0,0 +1,14 @@ +/// A simple function for testing +pub fn hello_from_a() -> &'static str { + "Hello from crate A!" +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn it_works() { + assert_eq!(hello_from_a(), "Hello from crate A!"); + } +} diff --git a/test-crates/parity-staging-test-b/Cargo.toml b/test-crates/parity-staging-test-b/Cargo.toml new file mode 100644 index 0000000000000..f70f8e494a699 --- /dev/null +++ b/test-crates/parity-staging-test-b/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "parity-staging-test-b" +version = "0.1.0" +edition = "2021" +description = "Test crate B for staging.crates.io publishing validation - depends on A" +license = "Apache-2.0" +repository = "https://github.com/paritytech/polkadot-sdk" + +[dependencies] +parity-staging-test-a = { path = "../parity-staging-test-a" } diff --git a/test-crates/parity-staging-test-b/src/lib.rs b/test-crates/parity-staging-test-b/src/lib.rs new file mode 100644 index 0000000000000..1c3d6f874e7ec --- /dev/null +++ b/test-crates/parity-staging-test-b/src/lib.rs @@ -0,0 +1,17 @@ +use parity_staging_test_a::hello_from_a; + +/// A function that uses crate A +pub fn hello_from_b() -> String { + format!("Hello from crate B! Also, {}", hello_from_a()) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn it_works() { + assert!(hello_from_b().contains("crate B")); + assert!(hello_from_b().contains("crate A")); + } +} diff --git a/test-crates/parity-staging-test-c/Cargo.toml b/test-crates/parity-staging-test-c/Cargo.toml new file mode 100644 index 0000000000000..aec1c77e67266 --- /dev/null +++ b/test-crates/parity-staging-test-c/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "parity-staging-test-c" +version = "0.1.0" +edition = "2021" +description = "Test crate C for staging.crates.io publishing validation - depends on A and B" +license = "Apache-2.0" +repository = "https://github.com/paritytech/polkadot-sdk" + +[dependencies] +parity-staging-test-a = { path = "../parity-staging-test-a" } +parity-staging-test-b = { path = "../parity-staging-test-b" } diff --git a/test-crates/parity-staging-test-c/src/lib.rs b/test-crates/parity-staging-test-c/src/lib.rs new file mode 100644 index 0000000000000..eff5377e67cf4 --- /dev/null +++ b/test-crates/parity-staging-test-c/src/lib.rs @@ -0,0 +1,24 @@ +use parity_staging_test_a::hello_from_a; +use parity_staging_test_b::hello_from_b; + +/// A function that uses both crate A and B +pub fn hello_from_c() -> String { + format!( + "Hello from crate C! I can use A directly: '{}' and B: '{}'", + hello_from_a(), + hello_from_b() + ) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn it_works() { + let result = hello_from_c(); + assert!(result.contains("crate C")); + assert!(result.contains("crate A")); + assert!(result.contains("crate B")); + } +} From 1a2852bedebf272c3f545c80f499233b4e9a154d Mon Sep 17 00:00:00 2001 From: Bruno Devic Date: Mon, 26 Jan 2026 18:33:57 +0100 Subject: [PATCH 2/4] feat: handle staging token --- .../workflows/release-80_publish-crates.yml | 31 ++++++++++++++----- scripts/release/test-staging-publish.sh | 7 +++-- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/.github/workflows/release-80_publish-crates.yml b/.github/workflows/release-80_publish-crates.yml index b049cebac09c7..661d838d3b6ce 100644 --- a/.github/workflows/release-80_publish-crates.yml +++ b/.github/workflows/release-80_publish-crates.yml @@ -7,6 +7,14 @@ on: description: 'Release name (e.g., stable2509-3). Base branch is derived by removing the last -N suffix.' required: true type: string + registry: + description: 'Registry to publish crates to' + required: true + type: choice + options: + - staging.crates.io + - crates.io + default: staging.crates.io dry_run: description: 'Dry run - do not actually publish crates' required: true @@ -182,33 +190,40 @@ jobs: git push origin "$RELEASE_BRANCH" echo "Successfully pushed $RELEASE_BRANCH" - - name: Configure cargo for staging.crates.io + - name: Configure cargo registry run: | - echo "Configuring cargo to use staging.crates.io..." + REGISTRY="${{ inputs.registry }}" + echo "Configuring cargo for $REGISTRY..." mkdir -p ~/.cargo - cat >> ~/.cargo/config.toml << 'EOF' + if [ "$REGISTRY" = "staging.crates.io" ]; then + cat >> ~/.cargo/config.toml << 'EOF' [registries.crates-io] index = "sparse+https://index.staging.crates.io/" EOF + else + echo "Using default crates.io registry" + fi echo "Cargo config:" - cat ~/.cargo/config.toml + cat ~/.cargo/config.toml || echo "(using defaults)" - - name: Publish crates to staging.crates.io + - name: Publish crates env: - PARITY_PUBLISH_CRATESIO_TOKEN: ${{ secrets.CRATESIO_PUBLISH_TOKEN }} + PARITY_PUBLISH_CRATESIO_TOKEN: ${{ inputs.registry == 'staging.crates.io' && secrets.STAGING_CRATESIO_PUBLISH_TOKEN || secrets.CRATESIO_PUBLISH_TOKEN }} run: | DRY_RUN="${{ inputs.dry_run }}" + REGISTRY="${{ inputs.registry }}" if [ "$DRY_RUN" = "true" ]; then echo "DRY RUN - Not actually publishing crates" + echo "Target registry: $REGISTRY" echo "Would run: parity-publish apply -p --batch-delay 15 --max-concurrent 1 --batch-size 1" echo "" echo "Crates that would be published:" parity-publish apply --print || true else - echo "Publishing crates to staging.crates.io..." + echo "Publishing crates to $REGISTRY..." parity-publish apply -p --batch-delay 15 --max-concurrent 1 --batch-size 1 - echo "Crates published successfully!" + echo "Crates published successfully to $REGISTRY!" fi diff --git a/scripts/release/test-staging-publish.sh b/scripts/release/test-staging-publish.sh index f39c2d04375ab..ec5f157ad1cd6 100755 --- a/scripts/release/test-staging-publish.sh +++ b/scripts/release/test-staging-publish.sh @@ -107,7 +107,7 @@ fi # Set environment variables for staging.crates.io # This redirects cargo to use staging without modifying your config files export CARGO_REGISTRIES_CRATES_IO_INDEX="sparse+https://index.staging.crates.io/" -export PARITY_PUBLISH_CRATESIO_TOKEN="$TOKEN" +export CARGO_REGISTRY_TOKEN="$TOKEN" log_info "Configured to publish to: staging.crates.io" log_info "Crates to publish: $CRATES" @@ -135,10 +135,11 @@ else log_info "Publishing $crate..." # Use cargo publish directly for individual crates - # This is simpler than using parity-publish for test crates + # Use --index to publish directly to staging (not --registry which still uploads to prod) cargo publish \ -p "$crate" \ - --registry crates-io \ + --index "sparse+https://index.staging.crates.io/" \ + --token "$TOKEN" \ --allow-dirty \ 2>&1 || { log_error "Failed to publish $crate" From e02f0788bc8234a5b5652550e55093d857131797 Mon Sep 17 00:00:00 2001 From: Bruno Devic Date: Tue, 27 Jan 2026 16:30:08 +0100 Subject: [PATCH 3/4] chore: scripts for staging crates publish --- Cargo.lock | 2 +- scripts/release/test-staging-publish.sh | 75 +++++++++++++++++--- test-crates/parity-staging-test-a/Cargo.toml | 2 +- test-crates/parity-staging-test-b/Cargo.toml | 2 +- test-crates/parity-staging-test-c/Cargo.toml | 4 +- 5 files changed, 70 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 888db99733a56..2be92d8a096ca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14459,7 +14459,7 @@ dependencies = [ [[package]] name = "parity-staging-test-a" -version = "0.1.0" +version = "0.2.0" [[package]] name = "parity-staging-test-b" diff --git a/scripts/release/test-staging-publish.sh b/scripts/release/test-staging-publish.sh index ec5f157ad1cd6..e186d12b578bf 100755 --- a/scripts/release/test-staging-publish.sh +++ b/scripts/release/test-staging-publish.sh @@ -104,19 +104,57 @@ if [[ -z "$TOKEN" ]] && [[ "$DRY_RUN" == "false" ]]; then exit 1 fi -# Set environment variables for staging.crates.io -# This redirects cargo to use staging without modifying your config files -export CARGO_REGISTRIES_CRATES_IO_INDEX="sparse+https://index.staging.crates.io/" -export CARGO_REGISTRY_TOKEN="$TOKEN" +# Create a temporary mini-workspace with only the test crates. +# This avoids the full polkadot-sdk workspace resolution, which would try to +# resolve all 500+ crates (scale-info, etc.) against staging and fail. +REPO_ROOT="$(pwd)" +TEMP_WORKSPACE=$(mktemp -d) + +cleanup_temp() { + rm -rf "$TEMP_WORKSPACE" + log_info "Cleaned up temporary workspace" +} +trap cleanup_temp EXIT + +# Copy ALL test crates into the temp workspace (not just the ones being published) +# so that path dependencies between them resolve correctly. +IFS=',' read -ra CRATE_ARRAY <<< "$CRATES" +MEMBERS="" +for crate_dir in "$REPO_ROOT"/test-crates/*/; do + crate_name=$(basename "$crate_dir") + cp -r "$crate_dir" "$TEMP_WORKSPACE/$crate_name" + MEMBERS="$MEMBERS\"$crate_name\"," +done + +# Create temp workspace Cargo.toml +cat > "$TEMP_WORKSPACE/Cargo.toml" << EOF +[workspace] +members = [${MEMBERS}] +resolver = "2" +EOF + +# Create .cargo/config.toml: +# - [source] replacement so dependency resolution uses staging +# - [registries] so cargo publish uploads to staging +mkdir -p "$TEMP_WORKSPACE/.cargo" +cat > "$TEMP_WORKSPACE/.cargo/config.toml" << EOF +[source.crates-io] +replace-with = "staging" + +[source.staging] +registry = "sparse+https://index.staging.crates.io/" + +[registries.staging] +index = "sparse+https://index.staging.crates.io/" +EOF + +log_info "Created temporary workspace at: $TEMP_WORKSPACE" log_info "Configured to publish to: staging.crates.io" log_info "Crates to publish: $CRATES" log_info "Dry run: $DRY_RUN" echo "" -# Convert comma-separated crates to array -IFS=',' read -ra CRATE_ARRAY <<< "$CRATES" - if [[ "$DRY_RUN" == "true" ]]; then log_info "=== DRY RUN MODE ===" log_info "Would publish the following crates to staging.crates.io:" @@ -130,19 +168,34 @@ else log_info "=== PUBLISHING TO STAGING.CRATES.IO ===" echo "" + # Fix path dependencies to be relative within the temp workspace + for crate in "${CRATE_ARRAY[@]}"; do + TOML="$TEMP_WORKSPACE/$crate/Cargo.toml" + # Rewrite path deps to point within the temp workspace + for dep_crate in "${CRATE_ARRAY[@]}"; do + if [[ "$crate" != "$dep_crate" ]]; then + sed -i.bak "s|path = \"../[^\"]*$dep_crate\"|path = \"../$dep_crate\"|g" "$TOML" + rm -f "${TOML}.bak" + fi + done + done + + # Publish from the temp workspace so cargo picks up its .cargo/config.toml + pushd "$TEMP_WORKSPACE" > /dev/null + # Publish each crate in order (respecting dependencies) for crate in "${CRATE_ARRAY[@]}"; do log_info "Publishing $crate..." - # Use cargo publish directly for individual crates - # Use --index to publish directly to staging (not --registry which still uploads to prod) cargo publish \ -p "$crate" \ - --index "sparse+https://index.staging.crates.io/" \ + --registry staging \ --token "$TOKEN" \ --allow-dirty \ + --no-verify \ 2>&1 || { log_error "Failed to publish $crate" + popd > /dev/null exit 1 } @@ -153,6 +206,8 @@ else sleep 30 done + popd > /dev/null + echo "" log_info "=== ALL CRATES PUBLISHED SUCCESSFULLY ===" log_info "Check them at: https://staging.crates.io" diff --git a/test-crates/parity-staging-test-a/Cargo.toml b/test-crates/parity-staging-test-a/Cargo.toml index 1a6efa5b50567..ebf9f62862eb0 100644 --- a/test-crates/parity-staging-test-a/Cargo.toml +++ b/test-crates/parity-staging-test-a/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "parity-staging-test-a" -version = "0.1.0" +version = "0.2.0" edition = "2021" description = "Test crate A for staging.crates.io publishing validation" license = "Apache-2.0" diff --git a/test-crates/parity-staging-test-b/Cargo.toml b/test-crates/parity-staging-test-b/Cargo.toml index f70f8e494a699..93bf9822c2fa5 100644 --- a/test-crates/parity-staging-test-b/Cargo.toml +++ b/test-crates/parity-staging-test-b/Cargo.toml @@ -7,4 +7,4 @@ license = "Apache-2.0" repository = "https://github.com/paritytech/polkadot-sdk" [dependencies] -parity-staging-test-a = { path = "../parity-staging-test-a" } +parity-staging-test-a = { path = "../parity-staging-test-a", version = "0.2.0" } diff --git a/test-crates/parity-staging-test-c/Cargo.toml b/test-crates/parity-staging-test-c/Cargo.toml index aec1c77e67266..9fbd284ddf7d5 100644 --- a/test-crates/parity-staging-test-c/Cargo.toml +++ b/test-crates/parity-staging-test-c/Cargo.toml @@ -7,5 +7,5 @@ license = "Apache-2.0" repository = "https://github.com/paritytech/polkadot-sdk" [dependencies] -parity-staging-test-a = { path = "../parity-staging-test-a" } -parity-staging-test-b = { path = "../parity-staging-test-b" } +parity-staging-test-a = { path = "../parity-staging-test-a", version = "0.2.0" } +parity-staging-test-b = { path = "../parity-staging-test-b", version = "0.1.0" } From 34bf8a459fd8037c015aecfa232c0ced08d69c57 Mon Sep 17 00:00:00 2001 From: Bruno Devic Date: Tue, 27 Jan 2026 16:35:41 +0100 Subject: [PATCH 4/4] chore: remove duplicated script --- .../release/test-parity-publish-staging.sh | 202 ------------------ 1 file changed, 202 deletions(-) delete mode 100755 scripts/release/test-parity-publish-staging.sh diff --git a/scripts/release/test-parity-publish-staging.sh b/scripts/release/test-parity-publish-staging.sh deleted file mode 100755 index c576531c551d4..0000000000000 --- a/scripts/release/test-parity-publish-staging.sh +++ /dev/null @@ -1,202 +0,0 @@ -#!/bin/bash -# -# Test parity-publish workflow against staging.crates.io -# -# This script tests the full parity-publish workflow: -# 1. parity-publish plan --prdoc prdoc -# 2. parity-publish apply -# 3. parity-publish apply -p (publish) -# -# Uses environment variables to redirect to staging.crates.io without -# modifying your local cargo config. -# -# Usage: -# ./scripts/release/test-parity-publish-staging.sh [options] -# -# Options: -# --dry-run Don't actually publish -# --token TOKEN crates.io API token (or set STAGING_CRATESIO_TOKEN env var) -# --parity-publish PATH Path to parity-publish binary -# --step STEP Run only specific step: plan, apply, publish, or all (default: all) -# --help Show this help message -# -# Examples: -# # Full dry run -# ./scripts/release/test-parity-publish-staging.sh --dry-run -# -# # Run only the plan step -# ./scripts/release/test-parity-publish-staging.sh --step plan -# -# # Full publish to staging -# ./scripts/release/test-parity-publish-staging.sh --token YOUR_TOKEN -# - -set -e - -# Default values -DRY_RUN=false -TOKEN="${STAGING_CRATESIO_TOKEN:-}" -PARITY_PUBLISH_PATH="${PARITY_PUBLISH_PATH:-../parity-publish/target/release/parity-publish}" -STEP="all" - -# Colors for output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -NC='\033[0m' # No Color - -print_help() { - sed -n '2,/^$/p' "$0" | sed 's/^# //' | sed 's/^#//' -} - -log_info() { - echo -e "${GREEN}[INFO]${NC} $1" -} - -log_step() { - echo -e "${BLUE}[STEP]${NC} $1" -} - -log_warn() { - echo -e "${YELLOW}[WARN]${NC} $1" -} - -log_error() { - echo -e "${RED}[ERROR]${NC} $1" -} - -# Parse arguments -while [[ $# -gt 0 ]]; do - case $1 in - --dry-run) - DRY_RUN=true - shift - ;; - --token) - TOKEN="$2" - shift 2 - ;; - --parity-publish) - PARITY_PUBLISH_PATH="$2" - shift 2 - ;; - --step) - STEP="$2" - shift 2 - ;; - --help|-h) - print_help - exit 0 - ;; - *) - log_error "Unknown option: $1" - print_help - exit 1 - ;; - esac -done - -# Validate step -if [[ ! "$STEP" =~ ^(plan|apply|publish|all)$ ]]; then - log_error "Invalid step: $STEP. Must be: plan, apply, publish, or all" - exit 1 -fi - -# Check parity-publish exists -if [[ ! -x "$PARITY_PUBLISH_PATH" ]]; then - log_error "parity-publish not found at: $PARITY_PUBLISH_PATH" - log_info "Set PARITY_PUBLISH_PATH environment variable or use --parity-publish flag" - log_info "Example: export PARITY_PUBLISH_PATH=../parity-publish/target/release/parity-publish" - exit 1 -fi - -log_info "Using parity-publish at: $PARITY_PUBLISH_PATH" -log_info "parity-publish version:" -"$PARITY_PUBLISH_PATH" --version || true -echo "" - -# Check token for publish step -if [[ "$STEP" == "publish" || "$STEP" == "all" ]] && [[ -z "$TOKEN" ]] && [[ "$DRY_RUN" == "false" ]]; then - log_error "No token provided for publish step. Use --token or set STAGING_CRATESIO_TOKEN env var" - log_info "For dry run, use --dry-run flag" - exit 1 -fi - -# Set environment variables for staging.crates.io -export CARGO_REGISTRIES_CRATES_IO_INDEX="sparse+https://index.staging.crates.io/" -export PARITY_PUBLISH_CRATESIO_TOKEN="$TOKEN" - -log_info "============================================" -log_info " Testing parity-publish with staging.crates.io" -log_info "============================================" -log_info "Registry: staging.crates.io" -log_info "Step: $STEP" -log_info "Dry run: $DRY_RUN" -echo "" - -# Step 1: Plan -if [[ "$STEP" == "plan" || "$STEP" == "all" ]]; then - log_step "1/3 - Running parity-publish plan..." - echo "" - - "$PARITY_PUBLISH_PATH" plan --prdoc prdoc - - log_info "Plan completed. Check Plan.toml for the publish plan." - echo "" - - if [[ "$STEP" == "plan" ]]; then - log_info "Plan step completed. Run with --step apply to continue." - exit 0 - fi -fi - -# Step 2: Apply -if [[ "$STEP" == "apply" || "$STEP" == "all" ]]; then - log_step "2/3 - Running parity-publish apply..." - echo "" - - "$PARITY_PUBLISH_PATH" apply - - log_info "Apply completed. Version bumps have been applied to Cargo.toml files." - echo "" - - # Update Cargo.lock - log_info "Updating Cargo.lock..." - cargo update --workspace --offline || cargo update --workspace - log_info "Cargo.lock updated." - echo "" - - if [[ "$STEP" == "apply" ]]; then - log_info "Apply step completed. Run with --step publish to publish." - exit 0 - fi -fi - -# Step 3: Publish -if [[ "$STEP" == "publish" || "$STEP" == "all" ]]; then - log_step "3/3 - Publishing crates..." - echo "" - - if [[ "$DRY_RUN" == "true" ]]; then - log_warn "DRY RUN - Not actually publishing" - log_info "Would run: $PARITY_PUBLISH_PATH apply -p --batch-delay 15 --max-concurrent 1 --batch-size 1" - echo "" - log_info "Crates that would be published:" - "$PARITY_PUBLISH_PATH" apply --print || true - else - log_info "Publishing to staging.crates.io..." - "$PARITY_PUBLISH_PATH" apply -p --batch-delay 15 --max-concurrent 1 --batch-size 1 - - log_info "Publish completed!" - fi - echo "" -fi - -log_info "============================================" -log_info " All steps completed!" -log_info "============================================" - -if [[ "$DRY_RUN" == "false" ]] && [[ "$STEP" == "publish" || "$STEP" == "all" ]]; then - log_info "Check your crates at: https://staging.crates.io" -fi