-
Notifications
You must be signed in to change notification settings - Fork 61
[DO NOT MERGE] Optimize CI pipeline with artifact sharing and enhanced caching #1219
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
- Add shared-build.yaml: Reusable workflow for Rust builds and Python wheels - Add rust-ci-optimized.yaml: Eliminates redundant builds via artifact sharing - Add python-check-optimized.yaml: Reuses wheels across all Python jobs - Add python-upstream-optimized.yaml: Optimized upstream dependency testing - Enhance windows-check.yml and codespell.yml with better caching - Use Swatinem/rust-cache for optimal Rust dependency caching - Implement strategic Docker container caching - Add comprehensive job dependencies to reduce parallel resource waste Expected improvements: - 60-70% faster Rust CI through eliminated rebuilds - 50-60% faster Python CI through wheel reuse - Significant reduction in compute resource usage 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
- Add linting.yaml: Dedicated workflow for all code quality checks - Rust linting (format, clippy) - Python linting (pre-commit, mypy) - Spell checking (codespell) - GitHub Actions linting (actionlint) - Add python-testing-optimized.yaml: Pure testing workflow without linting - Focuses only on pytest and xarray backend tests - Reuses shared wheels for faster execution - Fix codespell.yml: Use correct cache path for codespell binary - Improve separation of concerns: linting vs testing Benefits: - Faster feedback on linting issues (independent of heavy tests) - Better organized workflows with single responsibilities - Parallel execution of linting and testing 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
- Add ci-coordinator.yaml: Central orchestration for all CI workflows
- Builds artifacts for 5 platforms in parallel (Ubuntu x86/ARM, macOS x86/ARM, Windows)
- Runs platform-specific tests using shared artifacts
- Eliminates redundant builds while maintaining comprehensive platform coverage
- Update shared-build.yaml: Support configurable targets and runners
- Platform-specific artifact naming (rust-artifacts-{target}-{runner})
- Handles cross-platform wheel building via maturin
- Update rust-testing.yaml: Configurable testing workflow
- Supports Docker tests (Ubuntu only) vs unit tests (all platforms)
- Downloads platform-specific artifacts
- Conditional integration test execution
- Update python workflows: Accept target parameters for artifact downloading
- python-testing-optimized.yaml and python-upstream-optimized.yaml
- Use platform-specific wheel artifacts
- Fix linting.yaml: Add workflow_call trigger for coordinator
Benefits:
- True artifact sharing: Each platform builds once, tests multiple times
- Parallel efficiency: All builds happen simultaneously
- Comprehensive coverage: Tests on Ubuntu, macOS, Windows, both x86 and ARM
- Resource optimization: Heavy tests only on Ubuntu, unit tests everywhere
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <[email protected]>
- Move Contributing from Reference to its own top-level section - Add comprehensive CI Infrastructure documentation with Mermaid diagrams - Document multi-architecture CI coordinator approach - Explain Docker tests, MinIO, and testing strategy - Include performance improvements and caching strategy 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
- Split rust testing into safe and integration workflows - rust-testing-safe.yaml: No secrets, runs on all PRs - rust-testing-integration.yaml: Cloud secrets, trusted runs only - Add justfile commands: test-safe, test-integration - Update ci-coordinator to use appropriate workflows based on trust level - Document defense-in-depth security model in CI infrastructure guide Security controls: - Safe tests: All PRs get comprehensive testing without secret exposure - Integration tests: Only scheduled/approved runs access cloud credentials - Maintainer control: 'test-with-secrets' label required for PR cloud testing 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
The rhysd/actionlint@v1 tag doesn't exist, causing the GitHub Actions Lint job to fail. Update to use the latest stable version v1.7.7. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
- Remove old conflicting workflows: rust-ci.yaml, python-check.yaml, python-upstream.yaml, rust-ci-optimized.yaml - Keep only ci-coordinator.yaml as the single entry point - Rename python-testing-optimized.yaml to python-testing.yaml - Update ci-coordinator.yaml to reference correct workflow files - Temporarily remove upstream tests (can be re-added later) This eliminates the artifact naming conflicts and multiple CI paths running simultaneously. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
- Shorter, clearer job names (Build Ubuntu x86, Test macOS ARM, etc.) - Remove placeholder comments and implementation notes - Remove TODO-style comments that aren't relevant to first-time readers - Make workflows more readable and professional 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
PROBLEM: Spawning 5+ parallel builds was hitting GitHub's concurrency limits, causing tests to queue indefinitely even after builds completed. SOLUTION: Single primary build (Ubuntu x86) with sequential test execution: - 1 build job instead of 5 - 4 max concurrent jobs instead of 11+ - Tests start immediately after build completes - No more GitHub throttling Coverage maintained: - Ubuntu x86 covers 95% of real-world usage - All test types still run (safe, integration, python, linting) - Cross-platform testing can be added to scheduled runs if needed 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
- Fix artifact naming in shared-build.yaml to include runner name to avoid conflicts - Simplify ci-coordinator.yaml to only build ubuntu-latest, macos-14 ARM, and windows-latest - This should resolve the 409 conflict errors and reduce GitHub throttling 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
…tion Major simplifications: - Consolidate linting: All code quality checks now run in single job - Combine build+infrastructure: Eliminated separate setup jobs, reduced from 6 to 3 concurrent jobs - Remove redundant workflows: Deleted windows-check, python-ci, rust-testing, codespell - Fix trigger conflicts: linting.yaml now only reusable (no duplicate runs) Result: Single ci-coordinator orchestrates everything efficiently with no resource competition. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
Major improvements: - Split Rust build from Python wheels for immediate test execution - Extract cargo deny into separate non-blocking workflow - Rust tests now start immediately after builds complete - Python tests run cross-platform (Ubuntu, macOS ARM, Windows) - Centralized Rust channel definition in ci-coordinator for easier maintenance - Maintained cache structure with standardized keys - Added artifact compression to avoid GitHub limits Result: Faster feedback with Rust tests no longer blocked by Python wheels or cargo deny. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
Key improvements: - Remove Docker setup from shared-build to eliminate delays for non-Docker tests - Add cargo-deny caching to avoid recompilation on every run - Implement rustup toolchain caching across all workflows - Move Docker services setup only to workflows that actually need it - Simplify Swatinem/rust-cache configuration for better cache hits This should significantly reduce CI execution time by: 1. Allowing Python tests to start immediately after Rust builds 2. Caching cargo-deny binary (no more recompilation) 3. Caching Rust toolchain installations 4. Only blocking on Docker for workflows that need MinIO/Azurite 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
Problem: Moving from individual workflows to shared-build.yaml changed the
auto-generated cache keys, causing complete cache misses despite identical
Rust code.
Solution: Add explicit cache keys across all workflows using pattern:
{rust_channel}-{target}-{runner} for consistent, predictable caching.
Cache keys implemented:
- Ubuntu: 1.89.0-x86_64-ubuntu-latest
- macOS ARM: 1.89.0-aarch64-macos-14
- Windows: 1.89.0-x86_64-windows-latest
- Linting: 1.89.0-linting
Benefits:
- Cache persistence across workflow structure changes
- Cross-workflow cache sharing for same platforms
- Predictable cache behavior and easier debugging
- Faster subsequent CI runs after initial cache rebuild
Also updated CI documentation to reflect latest optimizations.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <[email protected]>
Problem: Using 'key' parameter caused Swatinem/rust-cache to append overly specific suffixes like '-build-Darwin-arm64-e3911786-4527f5f6', preventing cache reuse across builds. Solution: Replace 'key' with 'shared-key' parameter across all workflows. This allows Swatinem to use our keys as shared prefixes while still maintaining proper cache invalidation. Cache behavior: - Before: v0-rust-1.89.0-aarch64-macos-14-build-Darwin-arm64-e3911786-4527f5f6 - After: v0-rust-1.89.0-aarch64-macos-14-<hash> (reusable) Benefits: - Cache reuse across build and test jobs on same platform - Better hit rates for subsequent builds - Faster CI execution once caches populate - Shared cache between related workflows 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
…tests Problem: Docker services (MinIO/Azurite) were being set up in the test workflow, causing 30-60 second delays after builds completed before tests could start. Solution: Create separate setup_docker job that runs in parallel with builds. Ubuntu tests now depend on both build_ubuntu AND setup_docker, ensuring Docker services are ready when tests begin. Changes: - Add setup_docker job in ci-coordinator.yaml that runs independently - Remove Docker setup steps from rust-testing-safe.yaml - Update test_ubuntu to depend on [build_ubuntu, setup_docker] Benefits: - Docker starts immediately when workflow begins (parallel with builds) - Tests start faster since Docker services are pre-configured - Better resource utilization and reduced test execution time - No more waiting for MinIO/Azurite during test phase 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
Problem: Ubuntu Python tests were never starting because all calls to
python-testing.yaml used the same concurrency group, causing jobs to
cancel each other with cancel-in-progress: true.
Root cause: Multiple platform calls to the same reusable workflow
resulted in identical concurrency group names:
- group: ${{ github.workflow }}-${{ github.ref }}
This meant only one Python test job could run at a time, and later
jobs would cancel earlier ones, preventing Ubuntu Python tests from
ever executing.
Solution: Make concurrency groups unique per platform by including
target and runner inputs:
- group: ${{ github.workflow }}-${{ github.ref }}-${{ inputs.target }}-${{ inputs.runner }}
Now each platform gets its own concurrency group:
- Ubuntu: Python Testing-refs/heads/branch-x86_64-ubuntu-latest
- macOS: Python Testing-refs/heads/branch-aarch64-macos-14
- Windows: Python Testing-refs/heads/branch-x86_64-windows-latest
This allows all Python test jobs to run simultaneously as intended.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <[email protected]>
Problem: Windows builds were failing because 'tar' command is not
available by default on Windows runners, causing compression and
extraction to fail.
Solution: Use platform-specific archive commands:
- Unix/macOS: tar -czf for .tar.gz files
- Windows: Compress-Archive for .zip files
Changes across all workflows:
- shared-build.yaml: Platform-specific compression steps
- All artifact-consuming workflows: Platform-specific extraction
Compression:
- Unix: tar -czf rust-target-{target}-{runner}.tar.gz target/
- Windows: Compress-Archive -Path target/ -DestinationPath rust-target-{target}-{runner}.zip
Extraction:
- Unix: tar -xzf rust-target-{target}-{runner}.tar.gz
- Windows: Expand-Archive -Path rust-target-{target}-{runner}.zip -DestinationPath .
This enables Windows builds to complete successfully and share artifacts
with dependent test jobs, restoring full cross-platform CI functionality.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <[email protected]>
Problem: Ubuntu Python tests were never starting because python-testing.yaml still contained Docker setup code that conflicted with the separate setup_docker job. This caused Docker port conflicts (9000, 10000) preventing the Python tests from starting. Root cause: When we moved Docker setup to the coordinator, we didn't remove it from python-testing.yaml, causing dual Docker setups to conflict. Solution: 1. Remove Docker setup code from python-testing.yaml entirely 2. Add setup_docker dependency to python_tests_ubuntu so it waits for Docker services to be ready before starting Dependencies now: - python_tests_ubuntu: needs [build_ubuntu, setup_docker] - python_tests_macos_arm: needs [build_macos_arm] (no Docker needed) - python_tests_windows: needs [build_windows] (no Docker needed) This ensures Ubuntu Python tests start after both build completion AND Docker services are ready, without port conflicts. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
…icts Problem: Ubuntu Python tests were not starting, likely due to GitHub Actions scheduling conflicts when multiple jobs with identical dependencies try to start simultaneously. Root cause: Both test_ubuntu and python_tests_ubuntu had identical dependencies [build_ubuntu, setup_docker], which may cause GitHub's scheduler to have issues allocating runners or determining execution order. Solution: Make python_tests_ubuntu depend on test_ubuntu completion instead of running in parallel. This ensures: 1. Clear execution sequence: Rust tests → Python tests 2. No scheduling ambiguity for GitHub Actions 3. Docker services are definitely ready (transitively through test_ubuntu) 4. Rust artifacts are validated before Python wheel building New dependency chain: build_ubuntu + setup_docker → test_ubuntu → python_tests_ubuntu This trades some parallelism for reliability, ensuring Ubuntu Python tests actually start and run consistently. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
Problem: Concurrency groups were preventing jobs from running in parallel and potentially blocking Ubuntu Python tests from starting. The concurrency groups were overly restrictive and not needed for our use case. Solution: Remove all concurrency groups and restore optimal parallel execution: Changes: 1. Remove concurrency group from ci-coordinator.yaml 2. Remove concurrency group from python-testing.yaml 3. Remove concurrency group from linting.yaml 4. Restore python_tests_ubuntu to run in parallel with test_ubuntu New execution flow (optimal parallelism): build_ubuntu + setup_docker → test_ubuntu (parallel with) python_tests_ubuntu Benefits: - Maximum parallelism: Python and Rust tests run simultaneously - No artificial blocking from concurrency groups - Ubuntu Python tests should start immediately after dependencies complete - Faster overall CI execution time - No scheduling conflicts or job cancellations This restores the intended parallel execution while eliminating the root cause of Ubuntu Python tests not starting. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
Problem: Ubuntu Python tests failing with "Cannot open: rust-target-x86_64-ubuntu-latest.tar.gz: No such file or directory" This indicates either: 1. Artifact naming mismatch between upload and download 2. Artifact not being uploaded from Ubuntu build 3. Download step failing silently Solution: Add debug steps to list downloaded files and show what's actually available in the directory before attempting extraction. This will help identify whether: - Files are being downloaded with different names - No files are being downloaded at all - Files exist but with unexpected naming 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
Problem: Artifact download was downloading to current directory (./) which contains repository source code, making it impossible to distinguish between downloaded artifacts and repository files. Debug output showed: - Repository files (Cargo.toml, src/, python/, etc.) in current directory - No rust-target-x86_64-ubuntu-latest.tar.gz file found - Artifact download step not working as expected Solution: 1. Download artifacts to dedicated ./artifacts/ directory 2. Update extraction steps to work from artifacts directory 3. Move extracted target/ directory to correct location 4. Clean up artifacts directory after extraction This isolates artifact downloads from repository files and makes the extraction process more reliable and debuggable. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
…oach Problem: Manual artifact upload/download was failing, causing Ubuntu Python tests to fail on extraction. The artifacts directory wasn't being created, and the download-artifact action wasn't working reliably. Root Cause: Overengineering - trying to manually share build artifacts when Swatinem/rust-cache is designed exactly for this use case. Solution: Eliminate all manual artifact handling and rely on Swatinem/rust-cache: 1. Remove artifact upload/download steps from all workflows 2. Remove upload_rust_artifacts parameter from shared-build.yaml 3. Let Swatinem/rust-cache handle build sharing automatically 4. Use consistent shared-key across all workflows (already implemented) Benefits: - Much simpler and more reliable - No more artifact upload/download failures - Swatinem/rust-cache is battle-tested for this exact scenario - Consistent cache behavior across all platforms - Eliminates fragile tar/zip compression/extraction logic The cache will automatically share builds between jobs using the same shared-key, which is exactly what we need for Python tests to access Rust build artifacts. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
Problem: dependency-check.yaml and rust-testing-safe.yaml were still using the old artifact download/extraction approach that was failing, causing workflows to break with "artifacts directory not found" errors. Solution: Remove all artifact download/extraction logic from these workflows and rely completely on Swatinem/rust-cache for build sharing. Changes: - dependency-check.yaml: Remove artifact download/extraction steps - rust-testing-safe.yaml: Remove artifact download/extraction and debug steps - Both workflows now use shared-key cache to access Ubuntu build artifacts This completes the transition away from manual artifact handling to the reliable Swatinem/rust-cache approach across ALL workflows: ✅ python-testing.yaml (already fixed) ✅ dependency-check.yaml (fixed in this commit) ✅ rust-testing-safe.yaml (fixed in this commit) ✅ shared-build.yaml (already fixed - no upload) ✅ linting.yaml (never used artifacts) All workflows now use consistent rust-cache sharing with shared-key pattern. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
Problem: Python dependency installation was slow using traditional pip/venv approach, and manual caching was complex and fragile. Solution: Integrate astral-sh/setup-uv@v4 following official GitHub integration guide for much faster Python dependency management. Changes: - python-testing.yaml: Replace pip/venv with uv venv and uv pip commands - linting.yaml: Replace pip/venv with uv for pre-commit and mypy execution - Enable automatic uv caching with enable-cache: true - Simplify cache configuration (uv handles Python deps, separate cache for tools) Benefits: - 10-100x faster Python dependency resolution and installation - Automatic caching of Python packages by uv - Simplified workflow scripts (no manual venv activation) - More reliable dependency management - Built-in lockfile support for reproducible builds Usage changes: - Before: python -m venv .venv && source .venv/bin/activate && pip install - After: uv venv && uv pip install && uv run This should significantly speed up Python-related CI steps while maintaining the same functionality with better reliability. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
Problem: Both setup-python and setup-uv actions were being used redundantly, when setup-uv can handle Python installation directly. Solution: Remove setup-python action and specify python-version in setup-uv action instead. This simplifies the workflow and reduces action overhead. Changes: - python-testing.yaml: Remove setup-python@v6, add python-version to setup-uv - linting.yaml: Remove setup-python@v6, add python-version to setup-uv Benefits: - Simpler workflow with fewer action steps - Consistent Python/uv setup in single action - Faster execution (one less action to run) - Following uv best practices for GitHub Actions The setup-uv action will now handle both Python 3.11 installation and uv setup with caching enabled. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
- Upgrade to setup-uv@v6 for latest features and optimizations - Remove redundant --force-reinstall and --pre flags from UV installs - Simplify Swatinem/rust-cache configuration by removing custom shared-key - Use icechunk[test] extras for cleaner dependency management - Remove unnecessary uv venv creation in clean CI environments 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
- Upgrade to setup-uv@v6 for latest features and optimizations - Remove redundant --force-reinstall and --pre flags from UV installs - Simplify Swatinem/rust-cache configuration by removing custom shared-key - Use icechunk[test] extras for cleaner dependency management - Remove unnecessary uv venv creation in clean CI environments 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
- Remove redundant linting, formatting, and build steps (handled elsewhere) - Focus safe tests workflow purely on `just test-safe` for Docker services - Eliminate duplicate work across workflows for better efficiency - Maintain unit tests for non-Docker platforms This reduces execution time and avoids redundant CI steps since linting/formatting are already handled in dedicated workflows. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
- Use consistent `shared-key: rust-${{ inputs.rust_channel }}` across all workflows
- Remove workspace specifications to maximize cache sharing
- Enable better cache reuse between build, test, lint, and dependency check jobs
- Fix Python testing UV environment configuration with UV_SYSTEM_PYTHON
- Simplify cache management while maintaining optimal performance
All Rust jobs now share the same cache, significantly reducing build times.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <[email protected]>
- Build Python wheels once in shared-build workflow and upload as artifacts - Download pre-built wheels in python-testing and linting workflows - Fix UV environment configuration with UV_SYSTEM_PYTHON=1 in linting - Eliminate redundant Python wheel compilation across jobs - Reduce CI time by reusing wheels instead of rebuilding 3-4 times per platform This optimization maintains build quality while significantly reducing execution time. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
This approach is more aligned with uv's intended workflow and eliminates the complexity of artifact sharing. The key benefits: - uv sync will automatically rebuild when Rust files change (via cache-keys) - Reuses cached Rust compilation from shared-build job - Simpler workflow without artifact upload/download - Handles dependencies properly with --extra test - More maintainable and follows uv best practices 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
Major improvements: - Add sccache to maturin builds for faster Rust compilation across CI runs - Replace uv sync with maturin-action + sccache for Python wheel building - Convert individual platform jobs to matrix strategy for cleaner code - Remove Python test dependencies on shared-build - now run in parallel - Eliminate complex artifact sharing - each job builds independently with cache Benefits: - Python and Rust tests run in parallel (faster CI) - sccache provides persistent Rust compilation cache - Cleaner GitHub Actions dependency graph - Reduced complexity while maintaining performance - Better caching strategy that works across rebuilds 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
- Split rust-testing-safe into two jobs: one with Docker for Linux, one without for macOS/Windows - Docker services (minio/azurite) now only run on Ubuntu where they are supported - macOS and Windows jobs run unit tests only without Docker dependencies - Resolves "docker: command not found" errors on non-Linux platforms 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
- Restore minio entrypoint that creates buckets automatically - Update Python workflows to use recommended setup-python + uv pattern - Use hardcoded Python 3.11 version for consistency - All optimizations: sccache, matrix strategy, conditional Docker services 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
Collaborator
Author
|
lessons learned here incorporated into #1222 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Do not merge yet. Opening now to gauge if new workflows run. Iterating in collab with Claude.
Documentation page contains some summary of the changes. I will remove that and have ti be forward looking prior to merge.