feat: Add CI/CD workflows for testing and publishing SAL crates
Some checks failed
Test Publishing Setup / Test Publishing Setup (pull_request) Has been cancelled
Some checks failed
Test Publishing Setup / Test Publishing Setup (pull_request) Has been cancelled
- Add a workflow for testing the publishing setup - Add a workflow for publishing SAL crates to crates.io - Improve crate metadata and version management - Add optional dependencies for modularity - Improve documentation for publishing and usage
This commit is contained in:
227
.github/workflows/publish.yml
vendored
Normal file
227
.github/workflows/publish.yml
vendored
Normal file
@@ -0,0 +1,227 @@
|
||||
name: Publish SAL Crates
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: 'Version to publish (e.g., 0.1.0)'
|
||||
required: true
|
||||
type: string
|
||||
dry_run:
|
||||
description: 'Dry run (do not actually publish)'
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
name: Publish to crates.io
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install Rust toolchain
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
toolchain: stable
|
||||
|
||||
- name: Cache Cargo dependencies
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/bin/
|
||||
~/.cargo/registry/index/
|
||||
~/.cargo/registry/cache/
|
||||
~/.cargo/git/db/
|
||||
target/
|
||||
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-cargo-
|
||||
|
||||
- name: Install cargo-edit for version management
|
||||
run: cargo install cargo-edit
|
||||
|
||||
- name: Set version from release tag
|
||||
if: github.event_name == 'release'
|
||||
run: |
|
||||
VERSION=${GITHUB_REF#refs/tags/v}
|
||||
echo "PUBLISH_VERSION=$VERSION" >> $GITHUB_ENV
|
||||
echo "Publishing version: $VERSION"
|
||||
|
||||
- name: Set version from workflow input
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
run: |
|
||||
echo "PUBLISH_VERSION=${{ github.event.inputs.version }}" >> $GITHUB_ENV
|
||||
echo "Publishing version: ${{ github.event.inputs.version }}"
|
||||
|
||||
- name: Update version in all crates
|
||||
run: |
|
||||
echo "Updating version to $PUBLISH_VERSION"
|
||||
|
||||
# Update root Cargo.toml
|
||||
cargo set-version $PUBLISH_VERSION
|
||||
|
||||
# Update each crate
|
||||
CRATES=(os process text net git vault kubernetes virt redisclient postgresclient zinit_client mycelium rhai)
|
||||
for crate in "${CRATES[@]}"; do
|
||||
if [ -d "$crate" ]; then
|
||||
cd "$crate"
|
||||
cargo set-version $PUBLISH_VERSION
|
||||
cd ..
|
||||
echo "Updated $crate to version $PUBLISH_VERSION"
|
||||
fi
|
||||
done
|
||||
|
||||
- name: Run tests
|
||||
run: cargo test --workspace --verbose
|
||||
|
||||
- name: Check formatting
|
||||
run: cargo fmt --all -- --check
|
||||
|
||||
- name: Run clippy
|
||||
run: cargo clippy --workspace --all-targets --all-features -- -D warnings
|
||||
|
||||
- name: Dry run publish (check packages)
|
||||
run: |
|
||||
echo "Checking all packages can be published..."
|
||||
|
||||
CRATES=(os process text net git vault kubernetes virt redisclient postgresclient zinit_client mycelium rhai)
|
||||
for crate in "${CRATES[@]}"; do
|
||||
if [ -d "$crate" ]; then
|
||||
echo "Checking $crate..."
|
||||
cd "$crate"
|
||||
cargo publish --dry-run
|
||||
cd ..
|
||||
fi
|
||||
done
|
||||
|
||||
echo "Checking main crate..."
|
||||
cargo publish --dry-run
|
||||
|
||||
- name: Publish crates (dry run)
|
||||
if: github.event.inputs.dry_run == 'true'
|
||||
run: |
|
||||
echo "🔍 DRY RUN MODE - Would publish the following crates:"
|
||||
echo "Individual crates: sal-os, sal-process, sal-text, sal-net, sal-git, sal-vault, sal-kubernetes, sal-virt, sal-redisclient, sal-postgresclient, sal-zinit-client, sal-mycelium, sal-rhai"
|
||||
echo "Meta-crate: sal"
|
||||
echo "Version: $PUBLISH_VERSION"
|
||||
|
||||
- name: Publish individual crates
|
||||
if: github.event.inputs.dry_run != 'true'
|
||||
env:
|
||||
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
|
||||
run: |
|
||||
echo "Publishing individual crates..."
|
||||
|
||||
# Crates in dependency order
|
||||
CRATES=(os process text net git vault kubernetes virt redisclient postgresclient zinit_client mycelium rhai)
|
||||
|
||||
for crate in "${CRATES[@]}"; do
|
||||
if [ -d "$crate" ]; then
|
||||
echo "Publishing sal-$crate..."
|
||||
cd "$crate"
|
||||
|
||||
# Retry logic for transient failures
|
||||
for attempt in 1 2 3; do
|
||||
if cargo publish --token $CARGO_REGISTRY_TOKEN; then
|
||||
echo "✅ sal-$crate published successfully"
|
||||
break
|
||||
else
|
||||
if [ $attempt -eq 3 ]; then
|
||||
echo "❌ Failed to publish sal-$crate after 3 attempts"
|
||||
exit 1
|
||||
else
|
||||
echo "⚠️ Attempt $attempt failed, retrying in 30 seconds..."
|
||||
sleep 30
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
cd ..
|
||||
|
||||
# Wait for crates.io to process
|
||||
if [ "$crate" != "rhai" ]; then
|
||||
echo "⏳ Waiting 30 seconds for crates.io to process..."
|
||||
sleep 30
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
- name: Publish main crate
|
||||
if: github.event.inputs.dry_run != 'true'
|
||||
env:
|
||||
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
|
||||
run: |
|
||||
echo "Publishing main sal crate..."
|
||||
|
||||
# Wait a bit longer before publishing the meta-crate
|
||||
echo "⏳ Waiting 60 seconds for all individual crates to be available..."
|
||||
sleep 60
|
||||
|
||||
# Retry logic for the main crate
|
||||
for attempt in 1 2 3; do
|
||||
if cargo publish --token $CARGO_REGISTRY_TOKEN; then
|
||||
echo "✅ Main sal crate published successfully"
|
||||
break
|
||||
else
|
||||
if [ $attempt -eq 3 ]; then
|
||||
echo "❌ Failed to publish main sal crate after 3 attempts"
|
||||
exit 1
|
||||
else
|
||||
echo "⚠️ Attempt $attempt failed, retrying in 60 seconds..."
|
||||
sleep 60
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
- name: Create summary
|
||||
if: always()
|
||||
run: |
|
||||
echo "## 📦 SAL Publishing Summary" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Version:** $PUBLISH_VERSION" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Trigger:** ${{ github.event_name }}" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
if [ "${{ github.event.inputs.dry_run }}" == "true" ]; then
|
||||
echo "**Mode:** Dry Run" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "**Mode:** Live Publishing" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "### Published Crates" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- sal-os" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- sal-process" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- sal-text" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- sal-net" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- sal-git" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- sal-vault" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- sal-kubernetes" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- sal-virt" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- sal-redisclient" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- sal-postgresclient" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- sal-zinit-client" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- sal-mycelium" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- sal-rhai" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- sal (meta-crate)" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "### Usage" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo '```bash' >> $GITHUB_STEP_SUMMARY
|
||||
echo "# Individual crates" >> $GITHUB_STEP_SUMMARY
|
||||
echo "cargo add sal-os sal-process sal-text" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "# Meta-crate with features" >> $GITHUB_STEP_SUMMARY
|
||||
echo "cargo add sal --features core" >> $GITHUB_STEP_SUMMARY
|
||||
echo "cargo add sal --features all" >> $GITHUB_STEP_SUMMARY
|
||||
echo '```' >> $GITHUB_STEP_SUMMARY
|
233
.github/workflows/test-publish.yml
vendored
Normal file
233
.github/workflows/test-publish.yml
vendored
Normal file
@@ -0,0 +1,233 @@
|
||||
name: Test Publishing Setup
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, master ]
|
||||
paths:
|
||||
- '**/Cargo.toml'
|
||||
- 'scripts/publish-all.sh'
|
||||
- '.github/workflows/publish.yml'
|
||||
pull_request:
|
||||
branches: [ main, master ]
|
||||
paths:
|
||||
- '**/Cargo.toml'
|
||||
- 'scripts/publish-all.sh'
|
||||
- '.github/workflows/publish.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
jobs:
|
||||
test-publish-setup:
|
||||
name: Test Publishing Setup
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Rust toolchain
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
toolchain: stable
|
||||
|
||||
- name: Cache Cargo dependencies
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/bin/
|
||||
~/.cargo/registry/index/
|
||||
~/.cargo/registry/cache/
|
||||
~/.cargo/git/db/
|
||||
target/
|
||||
key: ${{ runner.os }}-cargo-publish-test-${{ hashFiles('**/Cargo.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-cargo-publish-test-
|
||||
${{ runner.os }}-cargo-
|
||||
|
||||
- name: Install cargo-edit
|
||||
run: cargo install cargo-edit
|
||||
|
||||
- name: Test workspace structure
|
||||
run: |
|
||||
echo "Testing workspace structure..."
|
||||
|
||||
# Check that all expected crates exist
|
||||
EXPECTED_CRATES=(os process text net git vault kubernetes virt redisclient postgresclient zinit_client mycelium rhai herodo)
|
||||
|
||||
for crate in "${EXPECTED_CRATES[@]}"; do
|
||||
if [ -d "$crate" ] && [ -f "$crate/Cargo.toml" ]; then
|
||||
echo "✅ $crate exists"
|
||||
else
|
||||
echo "❌ $crate missing or invalid"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
- name: Test feature configuration
|
||||
run: |
|
||||
echo "Testing feature configuration..."
|
||||
|
||||
# Test that features work correctly
|
||||
cargo check --features os
|
||||
cargo check --features process
|
||||
cargo check --features text
|
||||
cargo check --features net
|
||||
cargo check --features git
|
||||
cargo check --features vault
|
||||
cargo check --features kubernetes
|
||||
cargo check --features virt
|
||||
cargo check --features redisclient
|
||||
cargo check --features postgresclient
|
||||
cargo check --features zinit_client
|
||||
cargo check --features mycelium
|
||||
cargo check --features rhai
|
||||
|
||||
echo "✅ All individual features work"
|
||||
|
||||
# Test feature groups
|
||||
cargo check --features core
|
||||
cargo check --features clients
|
||||
cargo check --features infrastructure
|
||||
cargo check --features scripting
|
||||
|
||||
echo "✅ All feature groups work"
|
||||
|
||||
# Test all features
|
||||
cargo check --features all
|
||||
|
||||
echo "✅ All features together work"
|
||||
|
||||
- name: Test dry-run publishing
|
||||
run: |
|
||||
echo "Testing dry-run publishing..."
|
||||
|
||||
# Test each individual crate can be packaged
|
||||
CRATES=(os process text net git vault kubernetes virt redisclient postgresclient zinit_client mycelium rhai)
|
||||
|
||||
for crate in "${CRATES[@]}"; do
|
||||
echo "Testing sal-$crate..."
|
||||
cd "$crate"
|
||||
cargo publish --dry-run
|
||||
cd ..
|
||||
echo "✅ sal-$crate can be published"
|
||||
done
|
||||
|
||||
# Test main crate
|
||||
echo "Testing main sal crate..."
|
||||
cargo publish --dry-run
|
||||
echo "✅ Main sal crate can be published"
|
||||
|
||||
- name: Test publishing script
|
||||
run: |
|
||||
echo "Testing publishing script..."
|
||||
|
||||
# Make script executable
|
||||
chmod +x scripts/publish-all.sh
|
||||
|
||||
# Test dry run
|
||||
./scripts/publish-all.sh --dry-run --version 0.1.0-test
|
||||
|
||||
echo "✅ Publishing script works"
|
||||
|
||||
- name: Test version consistency
|
||||
run: |
|
||||
echo "Testing version consistency..."
|
||||
|
||||
# Get version from root Cargo.toml
|
||||
ROOT_VERSION=$(grep '^version = ' Cargo.toml | head -1 | sed 's/version = "\(.*\)"/\1/')
|
||||
echo "Root version: $ROOT_VERSION"
|
||||
|
||||
# Check all crates have the same version
|
||||
CRATES=(os process text net git vault kubernetes virt redisclient postgresclient zinit_client mycelium rhai herodo)
|
||||
|
||||
for crate in "${CRATES[@]}"; do
|
||||
if [ -f "$crate/Cargo.toml" ]; then
|
||||
CRATE_VERSION=$(grep '^version = ' "$crate/Cargo.toml" | head -1 | sed 's/version = "\(.*\)"/\1/')
|
||||
if [ "$CRATE_VERSION" = "$ROOT_VERSION" ]; then
|
||||
echo "✅ $crate version matches: $CRATE_VERSION"
|
||||
else
|
||||
echo "❌ $crate version mismatch: $CRATE_VERSION (expected $ROOT_VERSION)"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
- name: Test metadata completeness
|
||||
run: |
|
||||
echo "Testing metadata completeness..."
|
||||
|
||||
# Check that all crates have required metadata
|
||||
CRATES=(os process text net git vault kubernetes virt redisclient postgresclient zinit_client mycelium rhai)
|
||||
|
||||
for crate in "${CRATES[@]}"; do
|
||||
echo "Checking sal-$crate metadata..."
|
||||
cd "$crate"
|
||||
|
||||
# Check required fields exist
|
||||
if ! grep -q '^name = "sal-' Cargo.toml; then
|
||||
echo "❌ $crate missing or incorrect name"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! grep -q '^description = ' Cargo.toml; then
|
||||
echo "❌ $crate missing description"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! grep -q '^repository = ' Cargo.toml; then
|
||||
echo "❌ $crate missing repository"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! grep -q '^license = ' Cargo.toml; then
|
||||
echo "❌ $crate missing license"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ sal-$crate metadata complete"
|
||||
cd ..
|
||||
done
|
||||
|
||||
- name: Test dependency resolution
|
||||
run: |
|
||||
echo "Testing dependency resolution..."
|
||||
|
||||
# Test that all workspace dependencies resolve correctly
|
||||
cargo tree --workspace > /dev/null
|
||||
echo "✅ All dependencies resolve correctly"
|
||||
|
||||
# Test that there are no dependency conflicts
|
||||
cargo check --workspace
|
||||
echo "✅ No dependency conflicts"
|
||||
|
||||
- name: Generate publishing report
|
||||
if: always()
|
||||
run: |
|
||||
echo "## 🧪 Publishing Setup Test Report" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "### ✅ Tests Passed" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- Workspace structure validation" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- Feature configuration testing" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- Dry-run publishing simulation" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- Publishing script validation" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- Version consistency check" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- Metadata completeness verification" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- Dependency resolution testing" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "### 📦 Ready for Publishing" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "All SAL crates are ready for publishing to crates.io!" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Individual Crates:** 13 modules" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Meta-crate:** sal with optional features" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Binary:** herodo script executor" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "### 🚀 Next Steps" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "1. Create a release tag (e.g., v0.1.0)" >> $GITHUB_STEP_SUMMARY
|
||||
echo "2. The publish workflow will automatically trigger" >> $GITHUB_STEP_SUMMARY
|
||||
echo "3. All crates will be published to crates.io" >> $GITHUB_STEP_SUMMARY
|
||||
echo "4. Users can install with: \`cargo add sal-os\` or \`cargo add sal --features all\`" >> $GITHUB_STEP_SUMMARY
|
Reference in New Issue
Block a user