From 7aa978f13fd1588d74a8c868ac9ae9715ddb9286 Mon Sep 17 00:00:00 2001 From: Levi Cook Date: Mon, 9 Jun 2025 15:05:01 -0600 Subject: [PATCH 1/4] feat: implement Makefile-driven CI/CD with GitHub Actions - Add comprehensive Makefile with ci-quick, ci-full, and ci-local targets - Create GitHub Actions workflows that delegate to Makefile targets - Implement automated publishing pipeline with version validation - Add complete workflow documentation and troubleshooting guide - Include CHANGELOG.md template for release management - Fix clippy warnings in build.rs doctests - Enhance Cargo.toml metadata for crates.io publication - Ensure zero drift between local development and CI environments The Makefile serves as the single source of truth for all build operations, ensuring consistency between local development and CI while providing fast feedback loops and easy debugging capabilities. --- .github/WORKFLOW_SETUP.md | 214 ++++++++++++++++++ .github/workflows/ci.yml | 67 ++++++ .github/workflows/release.yml | 99 ++++++++ CHANGELOG.md | 42 ++++ Cargo.toml | 14 +- Makefile | 96 ++++++++ crates/litesvm-testing/Cargo.toml | 18 +- .../src/anchor_testing/build.rs | 2 +- crates/litesvm-testing/src/lib.rs | 2 +- .../src/pinocchio_testing/build.rs | 18 +- 10 files changed, 551 insertions(+), 21 deletions(-) create mode 100644 .github/WORKFLOW_SETUP.md create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/release.yml create mode 100644 CHANGELOG.md create mode 100644 Makefile diff --git a/.github/WORKFLOW_SETUP.md b/.github/WORKFLOW_SETUP.md new file mode 100644 index 0000000..1d14679 --- /dev/null +++ b/.github/WORKFLOW_SETUP.md @@ -0,0 +1,214 @@ +# GitHub Workflows Setup Guide + +This repository uses **Makefile-driven CI/CD** where the Makefile is the single source of truth for all build operations. + +## ๐Ÿ—๏ธ **Architecture: Makefile as Single Source of Truth** + +**Philosophy:** All build logic lives in the `Makefile`. GitHub workflows are just thin orchestration layers that call Makefile targets. + +**Benefits:** + +- โœ… **Consistency** - Same commands work locally and in CI +- โœ… **No drift** - Only one place to maintain build logic +- โœ… **Fast feedback** - Test locally with exact same commands as CI +- โœ… **Debugging** - Reproduce CI issues locally with `make ci-full` + +## ๐Ÿ”ง **Workflows Overview** + +### 1. **CI Workflow** (`.github/workflows/ci.yml`) + +**Triggers:** Every push to `main` and all pull requests +**Purpose:** Continuous integration with parallel quality gates + +**What it does:** + +- โœ… **Publishable Crate Job** โ†’ `make ci-quick` +- โœ… **Full Workspace Job** โ†’ `make ci-full` (includes Solana programs) + +**Key insight:** No custom build logic in workflow - just calls Makefile targets! + +### 2. **Release Workflow** (`.github/workflows/release.yml`) + +**Triggers:** Version tags (e.g., `v0.1.0`, `v1.2.3`) +**Purpose:** Automated publishing with quality gates + +**What it does:** + +1. **Pre-release checks** โ†’ `make ci-full` (full validation) +2. **Version validation** - Ensures tag matches `Cargo.toml` +3. **Publish to crates.io** - Uses `CARGO_REGISTRY_TOKEN` secret +4. **GitHub release** - Extracts notes from `CHANGELOG.md` + +## ๐ŸŽฏ **Makefile Targets (The Real CI)** + +```bash +# Development workflow +make check # Fast workspace validation +make test # All tests including Solana programs +make fmt # Format code +make ci-local # Full local CI with all checks + +# CI targets (what workflows call) +make ci-quick # Fast feedback - publishable crate only +make ci-full # Complete validation - all packages +``` + +## โš™๏ธ **Setup Requirements** + +### **Required GitHub Secrets** + +Add these in **Settings โ†’ Secrets and variables โ†’ Actions**: + +1. **`CARGO_REGISTRY_TOKEN`** (Required for publishing) + + ```bash + # Get token from https://crates.io/me + # Add as repository secret + ``` + +2. **`GITHUB_TOKEN`** (Automatically provided) + - Used for creating GitHub releases + - No setup required + +### **Required Branch Protection** + +Configure **Settings โ†’ Branches โ†’ Add rule** for `main`: + +- โœ… Require status checks: `Publishable Crate Quality`, `Full Workspace (inc. Solana Programs)` +- โœ… Require up-to-date branches +- โœ… Include administrators + +## ๐Ÿš€ **Publishing Workflow** + +### **Automatic Publishing (Recommended)** + +```bash +# 1. Update version in Cargo.toml +vim crates/litesvm-testing/Cargo.toml + +# 2. Update CHANGELOG.md with new version section +vim CHANGELOG.md + +# 3. Commit and push +git add -A && git commit -m "Release v0.1.0" +git push + +# 4. Create and push tag +git tag v0.1.0 +git push origin v0.1.0 + +# 5. Watch the magic happen โœจ +# - CI validates everything +# - Publishes to crates.io +# - Creates GitHub release +``` + +### **Manual Publishing (Fallback)** + +```bash +# Test locally first +make ci-full + +# Publish manually +cargo publish --manifest-path crates/litesvm-testing/Cargo.toml +``` + +## ๐Ÿ› **Debugging CI Issues** + +**The beauty of Makefile-driven CI:** + +```bash +# Reproduce exact CI failure locally +make ci-full + +# Or run specific CI subset +make ci-quick + +# Debug individual steps +make check && make test +``` + +**No more "works on my machine" - if `make ci-full` passes locally, CI will pass!** + +## ๐Ÿ“Š **Local Development Workflow** + +```bash +# Fast feedback loop +make check # Quick validation +make test # Run all tests + +# Before pushing +make ci-full # Complete CI simulation + +# Code quality +make fmt # Format code +make ci-local # Everything including clippy +``` + +## ๐ŸŽฏ **Key Design Decisions** + +1. **Makefile is canonical** - Workflows delegate to `make` targets +2. **Parallel CI jobs** - Fast feedback + comprehensive validation +3. **Solana toolchain isolation** - Different cache keys, proper setup +4. **Version validation** - Tag must match `Cargo.toml` +5. **Changelog integration** - Release notes from `CHANGELOG.md` + +This architecture ensures your CI/CD is **maintainable, debuggable, and reliable**! ๐ŸŽ‰ + +## ๐Ÿ“‹ Quality Standards + +The workflows enforce these standards: + +- **Zero clippy warnings** (using `-D warnings`) +- **Proper formatting** (using `cargo fmt`) +- **All tests pass** +- **Documentation builds** without errors +- **Version consistency** between tags and Cargo.toml +- **Dry-run publish success** before real publication + +## ๐Ÿ” Monitoring + +**CI Status:** + +- Check the "Actions" tab for build status +- PR checks must pass before merging +- Main branch status visible in repository badges + +**Release Status:** + +- Failed releases are visible in Actions tab +- GitHub releases are created automatically on success +- crates.io publication status is logged in workflow + +## ๐Ÿ› ๏ธ Troubleshooting + +**Common Issues:** + +1. **"Tag version doesn't match Cargo.toml"** + + - Ensure the git tag matches the version in `crates/litesvm-testing/Cargo.toml` + - Format: tag `v0.1.0` should match version `0.1.0` + +2. **"crates.io token invalid"** + + - Check that `CRATES_IO_TOKEN` secret is set correctly + - Ensure the token has publishing permissions + +3. **"Clippy warnings blocking CI"** + + - Run `cargo clippy --all-features -- -D warnings` locally + - Fix all warnings before pushing + +4. **"Examples failing"** + - Examples are non-blocking in CI + - Check Solana CLI installation and toolchain setup + +## ๐ŸŽฏ Benefits + +This setup provides: + +- **Quality assurance** - No broken code reaches main +- **Automated publishing** - Reduces manual errors +- **Consistent releases** - Standardized process +- **Visibility** - Clear status of builds and releases +- **Professional polish** - Shows attention to quality diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..936e91e --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,67 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + +env: + CARGO_TERM_COLOR: always + +jobs: + # Quick CI for the publishable crate + publishable-crate: + name: Publishable Crate Quality + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + with: + components: rustfmt, clippy + + - name: Cache cargo registry + uses: actions/cache@v4 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + target + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + + - name: Run quick CI checks (Makefile) + run: make ci-quick + + # Full workspace validation including Solana programs + workspace-validation: + name: Full Workspace (inc. Solana Programs) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + with: + components: rustfmt, clippy + + - name: Install Solana CLI + run: | + sh -c "$(curl -sSfL https://release.anza.xyz/stable/install)" + echo "$HOME/.local/share/solana/install/active_release/bin" >> $GITHUB_PATH + + - name: Cache cargo registry + uses: actions/cache@v4 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + target + key: ${{ runner.os }}-solana-cargo-${{ hashFiles('**/Cargo.lock') }} + + - name: Run full CI validation (Makefile) + run: make ci-full + + # Note: We skip clippy on Solana programs as they require special toolchain handling + # The core library clippy is covered in the publishable-crate job diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..90bf47e --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,99 @@ +name: Release + +on: + push: + tags: + - "v*.*.*" # Triggers on version tags like v0.1.0, v1.2.3, etc. + +env: + CARGO_TERM_COLOR: always + +jobs: + # Run all quality checks first using our Makefile + pre-release-checks: + name: Pre-Release Quality Checks + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + with: + components: rustfmt, clippy + + - name: Install Solana CLI + run: | + sh -c "$(curl -sSfL https://release.anza.xyz/stable/install)" + echo "$HOME/.local/share/solana/install/active_release/bin" >> $GITHUB_PATH + + - name: Cache cargo registry + uses: actions/cache@v4 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + target + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + + - name: Verify tag matches Cargo.toml version + run: | + TAG_VERSION="${GITHUB_REF#refs/tags/v}" + CARGO_VERSION=$(grep '^version = ' crates/litesvm-testing/Cargo.toml | sed 's/version = "\(.*\)"/\1/') + if [ "$TAG_VERSION" != "$CARGO_VERSION" ]; then + echo "โŒ Tag version $TAG_VERSION doesn't match Cargo.toml version $CARGO_VERSION" + exit 1 + fi + echo "โœ… Tag version matches Cargo.toml version: $TAG_VERSION" + + - name: Run full CI validation (Makefile) + run: make ci-full + + # Publish to crates.io + publish-crate: + name: Publish to crates.io + runs-on: ubuntu-latest + needs: pre-release-checks + steps: + - uses: actions/checkout@v4 + + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + + - name: Cache cargo registry + uses: actions/cache@v4 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + target + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + + - name: Publish to crates.io + run: cargo publish --manifest-path crates/litesvm-testing/Cargo.toml --token ${{ secrets.CARGO_REGISTRY_TOKEN }} + + # Create GitHub release with changelog + create-github-release: + name: Create GitHub Release + runs-on: ubuntu-latest + needs: publish-crate + steps: + - uses: actions/checkout@v4 + + - name: Extract changelog for this version + run: | + TAG_VERSION="${GITHUB_REF#refs/tags/v}" + # Extract changelog section for this version + sed -n "/## \[$TAG_VERSION\]/,/## \[/p" CHANGELOG.md | sed '$d' > release_notes.md + echo "Release notes for v$TAG_VERSION:" + cat release_notes.md + + - name: Create GitHub Release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ github.ref }} + release_name: Release ${{ github.ref }} + body_path: release_notes.md + draft: false + prerelease: false diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..9607886 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,42 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +### Added + +- Steel framework support (planned) +- Enhanced testing utilities (compute units, account state validation) +- Integration with popular Solana testing patterns + +## [0.1.0] - TBD + +### Added + +- Complete error testing framework for transaction, instruction, and system errors +- Type-safe system error assertions using `SystemError` enums +- Log assertion utilities with detailed error messages +- Dual API styles: direct function calls and fluent method chaining +- Precision control: "anywhere" matching vs surgical instruction-index targeting +- Anchor framework integration with automatic compilation and IDL support +- Pinocchio framework integration with lightweight build utilities +- Educational examples showing API progression from verbose to elegant +- Comprehensive documentation with working examples +- Setup utilities for quick SVM and fee payer initialization + +### Documentation + +- Complete API documentation with examples +- Framework-specific integration guides +- Educational test suite demonstrating best practices +- Progressive examples showing Good โ†’ Better โ†’ Best โ†’ Best+ patterns + +### Examples + +- Working Anchor program integration +- Working Pinocchio program integration +- Educational test cases for common error scenarios diff --git a/Cargo.toml b/Cargo.toml index 44bcb3d..8804bc9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,10 +23,13 @@ simple-anchor-tests = { path = "examples/anchor/simple-anchor-tests" } simple-pinocchio-program = { path = "examples/pinocchio/simple-pinocchio-program" } simple-pinocchio-tests = { path = "examples/pinocchio/simple-pinocchio-tests" } -litesvm-testing = { path = "crates/litesvm-testing" } -litesvm = "0.6.1" - anchor-lang = "0.31.1" +litesvm = "0.6.1" +litesvm-testing = { path = "crates/litesvm-testing" } +num-traits = "0.2.19" +pinocchio = "0.8.4" +pinocchio-log = "0.4.0" +pinocchio-pubkey = "0.2.4" solana-compute-budget-interface = "2.2" solana-instruction = "2.2" solana-keypair = "2.2" @@ -36,11 +39,6 @@ solana-system-interface = "1" solana-transaction = "2.2" solana-transaction-error = "2.2" -pinocchio = "0.8.4" -pinocchio-log = "0.4.0" -pinocchio-pubkey = "0.2.4" - - [workspace.lints.rust] unexpected_cfgs = { level = "allow", check-cfg = [ 'cfg(feature, values("custom-heap", "custom-panic", "anchor-debug", "no-idl", "no-log-ix-name"))', diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..13e75ba --- /dev/null +++ b/Makefile @@ -0,0 +1,96 @@ +# LiteSVM Testing - Build and CI Tasks +# +# This Makefile provides fast feedback loops for development and +# standardizes the exact commands that CI should run. + +.PHONY: help check test fmt clean ci-quick ci-full ci-local + +# Default target +help: + @echo "LiteSVM Testing Build Tasks" + @echo "" + @echo "Development:" + @echo " check - Fast workspace check (what CI runs)" + @echo " test - Run all tests including Solana programs" + @echo " fmt - Format all code" + @echo " clean - Clean all build artifacts" + @echo "" + @echo "CI Simulation:" + @echo " ci-quick - Fast CI checks (publishable crate only)" + @echo " ci-full - Complete workspace validation" + @echo " ci-local - Full local CI simulation (requires Solana CLI)" + +# Fast workspace validation - exactly what works +check: + @echo "๐Ÿ” Checking workspace..." + cargo check --workspace + @echo "โœ… Workspace check passed" + +# Complete test suite including Solana program compilation +test: + @echo "๐Ÿงช Running all tests (including Solana programs)..." + cargo test --workspace --verbose + @echo "โœ… All tests passed" + +# Format all code +fmt: + @echo "๐ŸŽจ Formatting code..." + cargo fmt --all + @echo "โœ… Code formatted" + +# Check formatting +fmt-check: + @echo "๐ŸŽจ Checking code formatting..." + cargo fmt --all -- --check + @echo "โœ… Code formatting OK" + +# Clean build artifacts +clean: + @echo "๐Ÿงน Cleaning build artifacts..." + cargo clean + @echo "โœ… Clean complete" + +# Quick CI checks - focuses on publishable crate ONLY +ci-quick: + @echo "โšก Running quick CI checks (publishable crate)..." + $(MAKE) fmt-check + @echo "Core library check:" + cargo check --manifest-path crates/litesvm-testing/Cargo.toml --all-features + @echo "Core library clippy:" + cargo clippy --manifest-path crates/litesvm-testing/Cargo.toml --all-features -- -D warnings + @echo "Core library tests:" + cargo test --manifest-path crates/litesvm-testing/Cargo.toml --all-features + @echo "Documentation check:" + cargo doc --manifest-path crates/litesvm-testing/Cargo.toml --all-features --no-deps + @echo "Publish dry run:" + cargo publish --manifest-path crates/litesvm-testing/Cargo.toml --dry-run --allow-dirty + @echo "โœ… Quick CI passed" + +# Full CI validation - what can reliably work in CI +ci-full: + @echo "๐Ÿš€ Running full CI validation..." + $(MAKE) fmt-check + $(MAKE) check + $(MAKE) test + @echo "Core library publish check:" + cargo publish --manifest-path crates/litesvm-testing/Cargo.toml --dry-run --allow-dirty + @echo "โœ… Full CI passed" + +# Local development CI - includes everything possible +ci-local: + @echo "๐Ÿ  Running local CI (includes all checks)..." + $(MAKE) fmt-check + $(MAKE) check + $(MAKE) test + @echo "Core library clippy (all features):" + cargo clippy --manifest-path crates/litesvm-testing/Cargo.toml --all-features -- -D warnings + @echo "Core library publish check:" + cargo publish --manifest-path crates/litesvm-testing/Cargo.toml --dry-run --allow-dirty + @echo "โœ… Local CI passed" + +# Install tools needed for development +install-tools: + @echo "๐Ÿ› ๏ธ Installing development tools..." + cargo install cargo-edit + @command -v act >/dev/null 2>&1 || (echo "Consider installing 'act' for local GitHub Actions: brew install act") + @echo "โœ… Tools installed" \ No newline at end of file diff --git a/crates/litesvm-testing/Cargo.toml b/crates/litesvm-testing/Cargo.toml index 32f6e0c..969fcd5 100644 --- a/crates/litesvm-testing/Cargo.toml +++ b/crates/litesvm-testing/Cargo.toml @@ -2,6 +2,22 @@ name = "litesvm-testing" version = "0.1.0" edition = "2021" +authors = ["LiteSVM Testing Framework Contributors"] +license = "GPL-3.0-or-later" +description = "Comprehensive testing framework for Solana programs using LiteSVM with ergonomic assertions" +repository = "https://github.com/levicook/litesvm-testing" +homepage = "https://github.com/levicook/litesvm-testing" +documentation = "https://docs.rs/litesvm-testing" +readme = "../../README.md" +keywords = ["solana", "testing", "blockchain", "litesvm", "framework"] +categories = ["development-tools::testing"] +include = [ + "src/**/*", + "tests/**/*", + "Cargo.toml", + "../../README.md", + "../../LICENSE", +] [lib] name = "litesvm_testing" @@ -13,7 +29,7 @@ pinocchio = [] [dependencies] litesvm = { workspace = true } -num-traits = "0.2.19" +num-traits = { workspace = true } solana-compute-budget-interface = { workspace = true } solana-instruction = { workspace = true } solana-keypair = { workspace = true } diff --git a/crates/litesvm-testing/src/anchor_testing/build.rs b/crates/litesvm-testing/src/anchor_testing/build.rs index 954ca65..ae4aea3 100644 --- a/crates/litesvm-testing/src/anchor_testing/build.rs +++ b/crates/litesvm-testing/src/anchor_testing/build.rs @@ -16,7 +16,7 @@ pub fn build_anchor_program>(program_path: P) { // Build the anchor program let output = Command::new("cargo") - .args(&[ + .args([ "build-sbf", "--manifest-path", &program_manifest.to_string_lossy(), diff --git a/crates/litesvm-testing/src/lib.rs b/crates/litesvm-testing/src/lib.rs index be043da..0eda5e4 100644 --- a/crates/litesvm-testing/src/lib.rs +++ b/crates/litesvm-testing/src/lib.rs @@ -1,5 +1,5 @@ //! # LiteSVM Testing Utilities -//! Copyright (C) 2024 Levi Cook - Licensed under GPL v3.0-or-later +//! Copyright (C) 2024 LiteSVM Testing Framework Contributors - Licensed under GPL v3.0-or-later //! //! A comprehensive testing framework for Solana programs using LiteSVM. Provides ergonomic, //! type-safe assertions for transaction results, logs, and all levels of Solana errors. diff --git a/crates/litesvm-testing/src/pinocchio_testing/build.rs b/crates/litesvm-testing/src/pinocchio_testing/build.rs index 1b1eb2a..b06062e 100644 --- a/crates/litesvm-testing/src/pinocchio_testing/build.rs +++ b/crates/litesvm-testing/src/pinocchio_testing/build.rs @@ -30,12 +30,10 @@ //! ## Example usage: //! //! In your test crate's `build.rs`: -//! ```rust +//! ```rust,no_run //! use litesvm_testing::pinocchio_testing::build_pinocchio_program; //! -//! fn main() { -//! build_pinocchio_program("../my-pinocchio-program"); -//! } +//! build_pinocchio_program("../my-pinocchio-program"); //! ``` use std::{path::Path, process::Command}; @@ -55,13 +53,11 @@ use std::{path::Path, process::Command}; /// /// # Example /// -/// ```rust +/// ```rust,no_run /// // In build.rs /// use litesvm_testing::pinocchio_testing::build_pinocchio_program; /// -/// fn main() { -/// build_pinocchio_program("../simple-pinocchio-program"); -/// } +/// build_pinocchio_program("../simple-pinocchio-program"); /// ``` /// /// For custom feature configurations, use [`build_pinocchio_program_with_features`]. @@ -89,8 +85,10 @@ pub fn build_pinocchio_program>(program_path: P) { /// /// # Example /// -/// ```rust +/// ```rust,no_run /// // Custom features for specialized builds +/// use litesvm_testing::pinocchio_testing::build_pinocchio_program_with_features; +/// /// build_pinocchio_program_with_features( /// "../my-program", /// &["bpf-entrypoint", "custom-feature", "debug-mode"] @@ -122,7 +120,7 @@ pub fn build_pinocchio_program_with_features>(program_path: P, fe // Build the pinocchio program let output = Command::new("cargo") - .args(&[ + .args([ "build-sbf", "--manifest-path", &program_manifest.to_string_lossy(), From 51764f76e705d059cf08559e1c9327cefa4655dc Mon Sep 17 00:00:00 2001 From: Levi Cook Date: Mon, 9 Jun 2025 15:14:53 -0600 Subject: [PATCH 2/4] fix: improve Solana CLI installation robustness in CI workflows - Use stable channel instead of hardcoded version for future-proof builds - Add explicit directory creation with proper permissions - Include installation verification steps (solana --version, cargo --version) - Enhance caching to include Solana directories for better performance - Add cargo-build-sbf availability check for debugging - Align installation method with official Solana documentation This addresses the "Failed to install platform-tools" errors encountered in GitHub Actions by using more robust installation practices. --- .github/workflows/ci.yml | 30 ++++++++++++++++++++++++++---- .github/workflows/release.yml | 20 ++++++++++++++++++-- 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 936e91e..95b2904 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,6 +8,7 @@ on: env: CARGO_TERM_COLOR: always + SOLANA_CHANNEL: stable jobs: # Quick CI for the publishable crate @@ -46,19 +47,40 @@ jobs: with: components: rustfmt, clippy - - name: Install Solana CLI + - name: Setup Solana CLI (robust installation) run: | - sh -c "$(curl -sSfL https://release.anza.xyz/stable/install)" + # Create directories with proper permissions + mkdir -p ~/.cache/solana + mkdir -p ~/.local/share/solana/install + + # Download and install Solana CLI using stable channel + echo "Installing Solana CLI $SOLANA_CHANNEL..." + sh -c "$(curl -sSfL https://release.anza.xyz/$SOLANA_CHANNEL/install)" + + # Add to PATH echo "$HOME/.local/share/solana/install/active_release/bin" >> $GITHUB_PATH - - name: Cache cargo registry + # Verify installation + export PATH="$HOME/.local/share/solana/install/active_release/bin:$PATH" + solana --version + cargo --version + + # Verify build-sbf is available + command -v cargo-build-sbf || echo "Warning: cargo-build-sbf not found in PATH" + + - name: Cache Solana and cargo uses: actions/cache@v4 with: path: | ~/.cargo/registry ~/.cargo/git + ~/.cache/solana + ~/.local/share/solana target - key: ${{ runner.os }}-solana-cargo-${{ hashFiles('**/Cargo.lock') }} + key: ${{ runner.os }}-solana-${{ env.SOLANA_CHANNEL }}-cargo-${{ hashFiles('**/Cargo.lock') }} + restore-keys: | + ${{ runner.os }}-solana-${{ env.SOLANA_CHANNEL }}-cargo- + ${{ runner.os }}-solana-${{ env.SOLANA_CHANNEL }}- - name: Run full CI validation (Makefile) run: make ci-full diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 90bf47e..1ec1b0a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -7,6 +7,7 @@ on: env: CARGO_TERM_COLOR: always + SOLANA_CHANNEL: stable jobs: # Run all quality checks first using our Makefile @@ -21,17 +22,32 @@ jobs: with: components: rustfmt, clippy - - name: Install Solana CLI + - name: Setup Solana CLI (robust installation) run: | - sh -c "$(curl -sSfL https://release.anza.xyz/stable/install)" + # Create directories with proper permissions + mkdir -p ~/.cache/solana + mkdir -p ~/.local/share/solana/install + + # Download and install Solana CLI using stable channel + echo "Installing Solana CLI $SOLANA_CHANNEL..." + sh -c "$(curl -sSfL https://release.anza.xyz/$SOLANA_CHANNEL/install)" + + # Add to PATH echo "$HOME/.local/share/solana/install/active_release/bin" >> $GITHUB_PATH + # Verify installation + export PATH="$HOME/.local/share/solana/install/active_release/bin:$PATH" + solana --version + cargo --version + - name: Cache cargo registry uses: actions/cache@v4 with: path: | ~/.cargo/registry ~/.cargo/git + ~/.cache/solana + ~/.local/share/solana target key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} From 2dcdda1fa4c59231946bf69fa35f1cd114849390 Mon Sep 17 00:00:00 2001 From: Levi Cook Date: Mon, 9 Jun 2025 15:23:00 -0600 Subject: [PATCH 3/4] fix(ci): pre-initialize Agave platform tools to prevent CI failures - Add `agave-install init --no-modify-path` after Solana CLI installation - Pre-download platform tools instead of relying on on-demand downloads - Prevent "Failed to install platform-tools" errors during cargo build-sbf - Add cargo-build-sbf version verification for debugging - Apply fix to both CI and release workflows for consistency This resolves the GitHub Actions failure where cargo build-sbf would try to dynamically download LLVM toolchain and hit filesystem permission issues. Based on solutions from solana-labs/solana#35719. --- .github/workflows/ci.yml | 10 +++++++--- .github/workflows/release.yml | 6 +++++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 95b2904..45c7c17 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -60,13 +60,17 @@ jobs: # Add to PATH echo "$HOME/.local/share/solana/install/active_release/bin" >> $GITHUB_PATH - # Verify installation + # Pre-initialize platform tools to avoid on-demand download issues export PATH="$HOME/.local/share/solana/install/active_release/bin:$PATH" + echo "Pre-initializing Agave platform tools..." + agave-install init --no-modify-path + + # Verify installation solana --version cargo --version - # Verify build-sbf is available - command -v cargo-build-sbf || echo "Warning: cargo-build-sbf not found in PATH" + # Verify build-sbf is available and platform tools are ready + cargo-build-sbf --version || echo "Warning: cargo-build-sbf version check failed" - name: Cache Solana and cargo uses: actions/cache@v4 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1ec1b0a..20e145a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -35,8 +35,12 @@ jobs: # Add to PATH echo "$HOME/.local/share/solana/install/active_release/bin" >> $GITHUB_PATH - # Verify installation + # Pre-initialize platform tools to avoid on-demand download issues export PATH="$HOME/.local/share/solana/install/active_release/bin:$PATH" + echo "Pre-initializing Agave platform tools..." + agave-install init --no-modify-path + + # Verify installation solana --version cargo --version From fe558ccef4d977681f97743616f1ec8f1fa056f1 Mon Sep 17 00:00:00 2001 From: Levi Cook Date: Mon, 9 Jun 2025 16:13:14 -0600 Subject: [PATCH 4/4] feat: simplify CI/CD with Docker + Makefile architecture Replaces complex Solana toolchain installation with official Anchor container (solanafoundation/anchor:v0.31.1) for reproducible builds. Changes: - GitHub workflows now trivially simple (just `make ci-docker-full`) - All Docker complexity moved to Makefile targets - Added Cargo registry caching for faster subsequent builds - Docker-based release validation with `make release-validation` - Updated documentation for new Docker-first approach Benefits: - Same environment locally and in CI (eliminates "works on my machine") - Battle-tested official Solana Foundation container - Zero Solana toolchain installation complexity - Easy debugging: `make ci-docker-full` reproduces CI exactly - Robust caching strategy for speed optimization The architecture ensures reliable, maintainable, and debuggable CI/CD using proven tools from the Solana ecosystem. --- .github/WORKFLOW_SETUP.md | 274 ++++++++++++++++++---------------- .github/workflows/ci.yml | 81 +++------- .github/workflows/release.yml | 92 ++---------- Makefile | 56 ++++++- 4 files changed, 234 insertions(+), 269 deletions(-) diff --git a/.github/WORKFLOW_SETUP.md b/.github/WORKFLOW_SETUP.md index 1d14679..be70e72 100644 --- a/.github/WORKFLOW_SETUP.md +++ b/.github/WORKFLOW_SETUP.md @@ -1,214 +1,228 @@ # GitHub Workflows Setup Guide -This repository uses **Makefile-driven CI/CD** where the Makefile is the single source of truth for all build operations. +This repository uses **ultra-simple workflows** powered by **Docker + Makefile** architecture. -## ๐Ÿ—๏ธ **Architecture: Makefile as Single Source of Truth** +## ๐Ÿ—๏ธ **Architecture: Docker + Makefile = Simple + Powerful** -**Philosophy:** All build logic lives in the `Makefile`. GitHub workflows are just thin orchestration layers that call Makefile targets. +**Core insight**: Keep GitHub workflows **trivially simple** by moving all complexity into Makefile Docker targets. + +```yaml +# GitHub workflows are dead simple: +steps: + - uses: actions/checkout@v4 + - run: make ci-docker-full +``` + +```makefile +# Makefile handles Docker complexity: +ci-docker-full: + docker run --rm -v $(PWD):/workspaces/project -w /workspaces/project \ + solanafoundation/anchor:v0.31.1 make ci-full +``` **Benefits:** -- โœ… **Consistency** - Same commands work locally and in CI -- โœ… **No drift** - Only one place to maintain build logic -- โœ… **Fast feedback** - Test locally with exact same commands as CI -- โœ… **Debugging** - Reproduce CI issues locally with `make ci-full` +- โœ… **Dead-simple workflows** - Minimal YAML, maximum power +- โœ… **Local = CI** - Same Docker environment everywhere +- โœ… **Battle-tested tools** - Official Solana Foundation container +- โœ… **Zero drift** - One source of truth in Makefile +- โœ… **Easy debugging** - `make ci-docker-full` reproduces CI exactly -## ๐Ÿ”ง **Workflows Overview** +## ๐Ÿ”ง **The Two Workflows** ### 1. **CI Workflow** (`.github/workflows/ci.yml`) -**Triggers:** Every push to `main` and all pull requests -**Purpose:** Continuous integration with parallel quality gates +**Triggers:** Push to `main`, all pull requests +**Jobs:** -**What it does:** +- **Quick Checks (Native)** โ†’ `make ci-quick` - Fast feedback on publishable crate +- **Docker Validation (Complete)** โ†’ `make ci-docker-full` - Full workspace in production environment -- โœ… **Publishable Crate Job** โ†’ `make ci-quick` -- โœ… **Full Workspace Job** โ†’ `make ci-full` (includes Solana programs) +### 2. **Release Workflow** (`.github/workflows/release.yml`) -**Key insight:** No custom build logic in workflow - just calls Makefile targets! +**Triggers:** Version tags (`v0.1.0`, `v1.2.3`, etc.) +**Jobs:** -### 2. **Release Workflow** (`.github/workflows/release.yml`) +1. **Release Validation** โ†’ `make release-validation` - Complete validation in Docker +2. **Publish** โ†’ `make publish` - Push to crates.io +3. **GitHub Release** - Extract changelog and create release -**Triggers:** Version tags (e.g., `v0.1.0`, `v1.2.3`) -**Purpose:** Automated publishing with quality gates +## ๐ŸŽฏ **Docker Container: solanafoundation/anchor:v0.31.1** -**What it does:** +This is the **official Anchor Docker image** used by `anchor build --verifiable`: -1. **Pre-release checks** โ†’ `make ci-full` (full validation) -2. **Version validation** - Ensures tag matches `Cargo.toml` -3. **Publish to crates.io** - Uses `CARGO_REGISTRY_TOKEN` secret -4. **GitHub release** - Extracts notes from `CHANGELOG.md` +- โœ… **Solana CLI** (2.1.0) +- โœ… **Anchor** (0.31.1) +- โœ… **Rust/Cargo** (latest) +- โœ… **cargo-build-sbf** (Solana BPF builder) +- โœ… **Platform tools** (v1.43) -## ๐ŸŽฏ **Makefile Targets (The Real CI)** +**No manual installation required** - everything just works! + +## ๐Ÿš€ **Makefile Targets** ```bash -# Development workflow -make check # Fast workspace validation -make test # All tests including Solana programs -make fmt # Format code -make ci-local # Full local CI with all checks - -# CI targets (what workflows call) -make ci-quick # Fast feedback - publishable crate only -make ci-full # Complete validation - all packages +# Development (native) +make check # Fast workspace check +make test # All tests +make fmt # Format code +make ci-local # Local CI with full tools + +# Docker CI (matches production) +make ci-docker-quick # Fast CI in Docker +make ci-docker-full # Complete CI in Docker +make ci # Main CI target (Docker-based) + +# Release +make release-validation # Complete release checks +make publish # Publish to crates.io ``` ## โš™๏ธ **Setup Requirements** ### **Required GitHub Secrets** -Add these in **Settings โ†’ Secrets and variables โ†’ Actions**: +**Settings โ†’ Secrets and variables โ†’ Actions:** -1. **`CARGO_REGISTRY_TOKEN`** (Required for publishing) +1. **`CARGO_REGISTRY_TOKEN`** (Required for releases) ```bash - # Get token from https://crates.io/me - # Add as repository secret + # Get from: https://crates.io/me + # Permissions: "Publish new crates" + "Publish updates" ``` -2. **`GITHUB_TOKEN`** (Automatically provided) - - Used for creating GitHub releases - - No setup required +2. **`GITHUB_TOKEN`** - Automatically provided, no setup needed -### **Required Branch Protection** +### **Branch Protection** -Configure **Settings โ†’ Branches โ†’ Add rule** for `main`: +**Settings โ†’ Branches โ†’ Add rule** for `main`: -- โœ… Require status checks: `Publishable Crate Quality`, `Full Workspace (inc. Solana Programs)` -- โœ… Require up-to-date branches +- โœ… Require status checks: `Quick Checks (Native)`, `Docker Validation (Complete)` +- โœ… Require up-to-date branches before merging - โœ… Include administrators -## ๐Ÿš€ **Publishing Workflow** +## ๐Ÿš€ **Publishing Process** -### **Automatic Publishing (Recommended)** +### **Automatic (Recommended)** ```bash -# 1. Update version in Cargo.toml +# 1. Update version vim crates/litesvm-testing/Cargo.toml -# 2. Update CHANGELOG.md with new version section +# 2. Update changelog vim CHANGELOG.md -# 3. Commit and push +# 3. Commit and tag git add -A && git commit -m "Release v0.1.0" -git push - -# 4. Create and push tag -git tag v0.1.0 -git push origin v0.1.0 +git tag v0.1.0 && git push origin main v0.1.0 -# 5. Watch the magic happen โœจ -# - CI validates everything -# - Publishes to crates.io -# - Creates GitHub release +# 4. Watch automation โœจ +# โ†’ Docker validation +# โ†’ crates.io publishing +# โ†’ GitHub release creation ``` -### **Manual Publishing (Fallback)** +### **Local Testing (Before Release)** ```bash -# Test locally first -make ci-full +# Test exact release process locally +TAG_VERSION="0.1.0" make release-validation -# Publish manually -cargo publish --manifest-path crates/litesvm-testing/Cargo.toml +# Or full Docker CI +make ci-docker-full ``` ## ๐Ÿ› **Debugging CI Issues** -**The beauty of Makefile-driven CI:** +**The magic of Docker-based CI:** ```bash -# Reproduce exact CI failure locally -make ci-full +# Reproduce CI failure exactly: +make ci-docker-full -# Or run specific CI subset -make ci-quick +# Or just the quick checks: +make ci-docker-quick -# Debug individual steps -make check && make test +# Debug step by step: +docker run --rm -v $(pwd):/workspaces/project -w /workspaces/project \ + solanafoundation/anchor:v0.31.1 bash +# Then run individual commands inside container ``` -**No more "works on my machine" - if `make ci-full` passes locally, CI will pass!** +**If `make ci-docker-full` passes locally, CI will pass!** ## ๐Ÿ“Š **Local Development Workflow** ```bash -# Fast feedback loop -make check # Quick validation -make test # Run all tests +# Fast development loop (native tools) +make check # Quick validation +make test # Run tests +make fmt # Format code -# Before pushing -make ci-full # Complete CI simulation +# Before pushing (Docker validation) +make ci-docker-full # Exact CI environment -# Code quality -make fmt # Format code -make ci-local # Everything including clippy +# Quick Docker check +make ci-docker-quick # Fast Docker validation ``` -## ๐ŸŽฏ **Key Design Decisions** - -1. **Makefile is canonical** - Workflows delegate to `make` targets -2. **Parallel CI jobs** - Fast feedback + comprehensive validation -3. **Solana toolchain isolation** - Different cache keys, proper setup -4. **Version validation** - Tag must match `Cargo.toml` -5. **Changelog integration** - Release notes from `CHANGELOG.md` - -This architecture ensures your CI/CD is **maintainable, debuggable, and reliable**! ๐ŸŽ‰ - -## ๐Ÿ“‹ Quality Standards - -The workflows enforce these standards: +## ๐ŸŽฏ **Key Design Principles** -- **Zero clippy warnings** (using `-D warnings`) -- **Proper formatting** (using `cargo fmt`) -- **All tests pass** -- **Documentation builds** without errors -- **Version consistency** between tags and Cargo.toml -- **Dry-run publish success** before real publication +1. **Workflows are thin wrappers** - Real logic in Makefile +2. **Docker for consistency** - Same environment everywhere +3. **Official containers** - Battle-tested, maintained by Solana Foundation +4. **Parallel jobs** - Fast feedback + thorough validation +5. **Version validation** - Tag must match `Cargo.toml` -## ๐Ÿ” Monitoring +## ๐Ÿ” **Quality Standards** -**CI Status:** +Enforced automatically: -- Check the "Actions" tab for build status -- PR checks must pass before merging -- Main branch status visible in repository badges +- โœ… **Zero clippy warnings** (`-D warnings`) +- โœ… **Proper formatting** (`cargo fmt --check`) +- โœ… **All tests pass** (including Solana programs) +- โœ… **Documentation builds** cleanly +- โœ… **Publish dry-run** succeeds +- โœ… **Version consistency** (tag โ†” Cargo.toml) -**Release Status:** +## ๐Ÿ› ๏ธ **Troubleshooting** -- Failed releases are visible in Actions tab -- GitHub releases are created automatically on success -- crates.io publication status is logged in workflow +### **Common Issues** -## ๐Ÿ› ๏ธ Troubleshooting +**"Tag version doesn't match Cargo.toml"** -**Common Issues:** - -1. **"Tag version doesn't match Cargo.toml"** - - - Ensure the git tag matches the version in `crates/litesvm-testing/Cargo.toml` - - Format: tag `v0.1.0` should match version `0.1.0` - -2. **"crates.io token invalid"** +```bash +# Check versions match: +git describe --tags # v0.1.0 +grep '^version = ' crates/litesvm-testing/Cargo.toml # version = "0.1.0" +``` - - Check that `CRATES_IO_TOKEN` secret is set correctly - - Ensure the token has publishing permissions +**"Docker container fails"** -3. **"Clippy warnings blocking CI"** +```bash +# Test Docker setup locally: +docker pull solanafoundation/anchor:v0.31.1 +make ci-docker-quick +``` - - Run `cargo clippy --all-features -- -D warnings` locally - - Fix all warnings before pushing +**"crates.io token invalid"** -4. **"Examples failing"** - - Examples are non-blocking in CI - - Check Solana CLI installation and toolchain setup +```bash +# Verify secret is set in GitHub: +# Settings โ†’ Secrets โ†’ CARGO_REGISTRY_TOKEN +``` -## ๐ŸŽฏ Benefits +### **Advanced Debugging** -This setup provides: +```bash +# Interactive Docker debugging: +docker run -it --rm -v $(pwd):/workspaces/project -w /workspaces/project \ + solanafoundation/anchor:v0.31.1 bash + +# Inside container: +make ci-full # Run full CI +solana --version # Check tool versions +cargo clippy # Test individual commands +``` -- **Quality assurance** - No broken code reaches main -- **Automated publishing** - Reduces manual errors -- **Consistent releases** - Standardized process -- **Visibility** - Clear status of builds and releases -- **Professional polish** - Shows attention to quality +This architecture ensures **reliable, maintainable, and debuggable** CI/CD! ๐ŸŽ‰ diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 45c7c17..a3a92e7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,86 +8,49 @@ on: env: CARGO_TERM_COLOR: always - SOLANA_CHANNEL: stable jobs: - # Quick CI for the publishable crate - publishable-crate: - name: Publishable Crate Quality + # Quick CI for the publishable crate (native) + quick-checks: + name: Quick Checks (Native) runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - - name: Install Rust - uses: dtolnay/rust-toolchain@stable + - uses: dtolnay/rust-toolchain@stable with: components: rustfmt, clippy - - - name: Cache cargo registry - uses: actions/cache@v4 + - uses: actions/cache@v4 with: path: | ~/.cargo/registry ~/.cargo/git target key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + - run: make ci-quick - - name: Run quick CI checks (Makefile) - run: make ci-quick - - # Full workspace validation including Solana programs - workspace-validation: - name: Full Workspace (inc. Solana Programs) + # Complete validation in Docker (matches production environment) + docker-validation: + name: Docker Validation (Complete) runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - name: Install Rust - uses: dtolnay/rust-toolchain@stable + # Cache Docker layers for faster subsequent builds + - name: Cache Docker layers + uses: actions/cache@v4 with: - components: rustfmt, clippy - - - name: Setup Solana CLI (robust installation) - run: | - # Create directories with proper permissions - mkdir -p ~/.cache/solana - mkdir -p ~/.local/share/solana/install - - # Download and install Solana CLI using stable channel - echo "Installing Solana CLI $SOLANA_CHANNEL..." - sh -c "$(curl -sSfL https://release.anza.xyz/$SOLANA_CHANNEL/install)" - - # Add to PATH - echo "$HOME/.local/share/solana/install/active_release/bin" >> $GITHUB_PATH - - # Pre-initialize platform tools to avoid on-demand download issues - export PATH="$HOME/.local/share/solana/install/active_release/bin:$PATH" - echo "Pre-initializing Agave platform tools..." - agave-install init --no-modify-path - - # Verify installation - solana --version - cargo --version - - # Verify build-sbf is available and platform tools are ready - cargo-build-sbf --version || echo "Warning: cargo-build-sbf version check failed" + path: /tmp/.buildx-cache + key: ${{ runner.os }}-docker-${{ hashFiles('**/Cargo.lock') }} + restore-keys: | + ${{ runner.os }}-docker- - - name: Cache Solana and cargo + # Cache Cargo registry (mounted into container) + - name: Cache Cargo registry uses: actions/cache@v4 with: - path: | - ~/.cargo/registry - ~/.cargo/git - ~/.cache/solana - ~/.local/share/solana - target - key: ${{ runner.os }}-solana-${{ env.SOLANA_CHANNEL }}-cargo-${{ hashFiles('**/Cargo.lock') }} + path: ~/.cargo + key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }} restore-keys: | - ${{ runner.os }}-solana-${{ env.SOLANA_CHANNEL }}-cargo- - ${{ runner.os }}-solana-${{ env.SOLANA_CHANNEL }}- - - - name: Run full CI validation (Makefile) - run: make ci-full + ${{ runner.os }}-cargo-registry- - # Note: We skip clippy on Solana programs as they require special toolchain handling - # The core library clippy is covered in the publishable-crate job + - run: make ci-docker-full diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 20e145a..692c22d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -7,108 +7,42 @@ on: env: CARGO_TERM_COLOR: always - SOLANA_CHANNEL: stable jobs: - # Run all quality checks first using our Makefile - pre-release-checks: - name: Pre-Release Quality Checks + # Validate release in Docker environment + validate: + name: Release Validation runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - - name: Install Rust - uses: dtolnay/rust-toolchain@stable - with: - components: rustfmt, clippy - - - name: Setup Solana CLI (robust installation) - run: | - # Create directories with proper permissions - mkdir -p ~/.cache/solana - mkdir -p ~/.local/share/solana/install - - # Download and install Solana CLI using stable channel - echo "Installing Solana CLI $SOLANA_CHANNEL..." - sh -c "$(curl -sSfL https://release.anza.xyz/$SOLANA_CHANNEL/install)" - - # Add to PATH - echo "$HOME/.local/share/solana/install/active_release/bin" >> $GITHUB_PATH - - # Pre-initialize platform tools to avoid on-demand download issues - export PATH="$HOME/.local/share/solana/install/active_release/bin:$PATH" - echo "Pre-initializing Agave platform tools..." - agave-install init --no-modify-path - - # Verify installation - solana --version - cargo --version - - - name: Cache cargo registry - uses: actions/cache@v4 - with: - path: | - ~/.cargo/registry - ~/.cargo/git - ~/.cache/solana - ~/.local/share/solana - target - key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} - - - name: Verify tag matches Cargo.toml version - run: | - TAG_VERSION="${GITHUB_REF#refs/tags/v}" - CARGO_VERSION=$(grep '^version = ' crates/litesvm-testing/Cargo.toml | sed 's/version = "\(.*\)"/\1/') - if [ "$TAG_VERSION" != "$CARGO_VERSION" ]; then - echo "โŒ Tag version $TAG_VERSION doesn't match Cargo.toml version $CARGO_VERSION" - exit 1 - fi - echo "โœ… Tag version matches Cargo.toml version: $TAG_VERSION" - - - name: Run full CI validation (Makefile) - run: make ci-full + - run: TAG_VERSION="${GITHUB_REF#refs/tags/v}" make release-validation # Publish to crates.io - publish-crate: + publish: name: Publish to crates.io runs-on: ubuntu-latest - needs: pre-release-checks + needs: validate steps: - uses: actions/checkout@v4 - - - name: Install Rust - uses: dtolnay/rust-toolchain@stable - - - name: Cache cargo registry - uses: actions/cache@v4 - with: - path: | - ~/.cargo/registry - ~/.cargo/git - target - key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} - - - name: Publish to crates.io - run: cargo publish --manifest-path crates/litesvm-testing/Cargo.toml --token ${{ secrets.CARGO_REGISTRY_TOKEN }} + - uses: dtolnay/rust-toolchain@stable + - run: make publish + env: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} # Create GitHub release with changelog - create-github-release: + github-release: name: Create GitHub Release runs-on: ubuntu-latest - needs: publish-crate + needs: publish steps: - uses: actions/checkout@v4 - - name: Extract changelog for this version run: | TAG_VERSION="${GITHUB_REF#refs/tags/v}" - # Extract changelog section for this version sed -n "/## \[$TAG_VERSION\]/,/## \[/p" CHANGELOG.md | sed '$d' > release_notes.md echo "Release notes for v$TAG_VERSION:" cat release_notes.md - - - name: Create GitHub Release - uses: actions/create-release@v1 + - uses: actions/create-release@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: diff --git a/Makefile b/Makefile index 13e75ba..26c075f 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ # This Makefile provides fast feedback loops for development and # standardizes the exact commands that CI should run. -.PHONY: help check test fmt clean ci-quick ci-full ci-local +.PHONY: help check test fmt clean ci-quick ci-full ci-local ci-docker-quick ci-docker-full ci release-validation publish # Default target help: @@ -19,6 +19,15 @@ help: @echo " ci-quick - Fast CI checks (publishable crate only)" @echo " ci-full - Complete workspace validation" @echo " ci-local - Full local CI simulation (requires Solana CLI)" + @echo "" + @echo "Docker CI (matches GitHub Actions exactly):" + @echo " ci-docker-quick - Fast CI in Docker container" + @echo " ci-docker-full - Complete CI in Docker container" + @echo " ci - Main CI target (Docker-based)" + @echo "" + @echo "Release:" + @echo " release-validation - Complete release validation" + @echo " publish - Publish to crates.io" # Fast workspace validation - exactly what works check: @@ -88,6 +97,51 @@ ci-local: cargo publish --manifest-path crates/litesvm-testing/Cargo.toml --dry-run --allow-dirty @echo "โœ… Local CI passed" +# Docker-based CI targets (matches CI environment exactly) +ci-docker-quick: + @echo "๐Ÿณ Running quick CI in Docker container..." + @docker pull solanafoundation/anchor:v0.31.1 > /dev/null 2>&1 || true + @mkdir -p ~/.cargo + docker run --rm \ + -v $$(pwd):/workspaces/project \ + -v ~/.cargo:/home/solana/.cargo \ + -w /workspaces/project \ + solanafoundation/anchor:v0.31.1 make ci-quick + +ci-docker-full: + @echo "๐Ÿณ Running full CI in Docker container..." + @docker pull solanafoundation/anchor:v0.31.1 > /dev/null 2>&1 || true + @mkdir -p ~/.cargo + docker run --rm \ + -v $$(pwd):/workspaces/project \ + -v ~/.cargo:/home/solana/.cargo \ + -w /workspaces/project \ + solanafoundation/anchor:v0.31.1 make ci-full + +# Main CI target for GitHub Actions (uses Docker for reproducible environment) +ci: ci-docker-full + +# Release validation - comprehensive checks before publishing +release-validation: + @echo "๐Ÿš€ Running release validation..." + @echo "Verifying tag matches Cargo.toml version..." + @if [ -n "$$TAG_VERSION" ] && [ -n "$$(grep '^version = ' crates/litesvm-testing/Cargo.toml | sed 's/version = "\(.*\)"/\1/')" ]; then \ + CARGO_VERSION=$$(grep '^version = ' crates/litesvm-testing/Cargo.toml | sed 's/version = "\(.*\)"/\1/'); \ + if [ "$$TAG_VERSION" != "$$CARGO_VERSION" ]; then \ + echo "โŒ Tag version $$TAG_VERSION doesn't match Cargo.toml version $$CARGO_VERSION"; \ + exit 1; \ + fi; \ + echo "โœ… Tag version matches Cargo.toml version: $$TAG_VERSION"; \ + fi + $(MAKE) ci-docker-full + @echo "โœ… Release validation passed" + +# Publish to crates.io (requires CARGO_REGISTRY_TOKEN) +publish: + @echo "๐Ÿ“ฆ Publishing to crates.io..." + cargo publish --manifest-path crates/litesvm-testing/Cargo.toml --token $$CARGO_REGISTRY_TOKEN + @echo "โœ… Published to crates.io" + # Install tools needed for development install-tools: @echo "๐Ÿ› ๏ธ Installing development tools..."