diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml
new file mode 100644
index 0000000..6df125c
--- /dev/null
+++ b/.github/workflows/check.yml
@@ -0,0 +1,44 @@
+name: Quality Checks
+
+on:
+ workflow_call:
+
+jobs:
+ check:
+ name: Quality Checks
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ target:
+ - x86_64-unknown-linux-gnu
+ - x86_64-unknown-none
+ - riscv64gc-unknown-none-elf
+ - aarch64-unknown-none-softfloat
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Install Rust toolchain
+ uses: dtolnay/rust-toolchain@nightly
+ with:
+ components: rust-src, clippy, rustfmt
+ targets: ${{ matrix.target }}
+
+ - name: Check rust version
+ run: rustc --version --verbose
+
+ - name: Check code format
+ run: cargo fmt --all -- --check
+
+ - name: Build
+ run: cargo build --target ${{ matrix.target }} --all-features
+
+ - name: Run clippy
+ run: cargo clippy --target ${{ matrix.target }} --all-features -- -D warnings
+
+ - name: Build documentation
+ env:
+ RUSTDOCFLAGS: -D rustdoc::broken_intra_doc_links -D missing-docs
+ run: cargo doc --no-deps --target ${{ matrix.target }} --all-features
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
deleted file mode 100644
index fb4a181..0000000
--- a/.github/workflows/ci.yml
+++ /dev/null
@@ -1,86 +0,0 @@
-name: CI
-
-on:
- push:
- branches: [main, dev]
- pull_request:
- branches: [main, dev]
-
-env:
- CARGO_TERM_COLOR: always
- RUST_BACKTRACE: 1
-
-jobs:
- # Quick checks: format, clippy, build
- quick-check:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- - uses: dtolnay/rust-toolchain@nightly
- with:
- components: rustfmt, clippy
- - name: Check rust version
- run: rustc --version --verbose
- - name: Check code format
- run: cargo fmt --all -- --check
- - name: Clippy
- run: cargo clippy --all-targets --all-features -- -D warnings -A clippy::new_without_default
- - name: Build
- run: cargo build --all-features
-
- # Full test suite
- test:
- runs-on: ubuntu-latest
- needs: quick-check
- steps:
- - uses: actions/checkout@v4
- - uses: dtolnay/rust-toolchain@nightly
- - name: Run tests
- run: cargo test --all-features -- --nocapture
- - name: Run doc tests
- run: cargo test --doc
-
- # Multi-platform build
- build:
- runs-on: ubuntu-latest
- needs: quick-check
- strategy:
- fail-fast: false
- matrix:
- target:
- - x86_64-unknown-linux-gnu
- - x86_64-unknown-none
- - riscv64gc-unknown-none-elf
- - aarch64-unknown-none-softfloat
- steps:
- - uses: actions/checkout@v4
- - uses: dtolnay/rust-toolchain@nightly
- with:
- components: rust-src
- targets: ${{ matrix.target }}
- - name: Build for ${{ matrix.target }}
- run: cargo build --target ${{ matrix.target }} --all-features
-
- # Documentation build and deploy
- doc:
- runs-on: ubuntu-latest
- needs: quick-check
- permissions:
- contents: write
- env:
- default-branch: ${{ format('refs/heads/{0}', github.event.repository.default_branch) }}
- RUSTDOCFLAGS: -D rustdoc::broken_intra_doc_links -D missing-docs
- steps:
- - uses: actions/checkout@v4
- - uses: dtolnay/rust-toolchain@nightly
- - name: Build docs
- run: |
- cargo doc --no-deps --all-features
- printf '' $(cargo tree | head -1 | cut -d' ' -f1) > target/doc/index.html
- - name: Deploy to Github Pages
- if: ${{ github.ref == env.default-branch }}
- uses: JamesIves/github-pages-deploy-action@v4
- with:
- single-commit: true
- branch: gh-pages
- folder: target/doc
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
new file mode 100644
index 0000000..99f5a00
--- /dev/null
+++ b/.github/workflows/deploy.yml
@@ -0,0 +1,66 @@
+name: Deploy
+
+on:
+ push:
+ branches:
+ - '**'
+ tags-ignore:
+ - 'v*'
+ - 'v*-pre.*'
+ pull_request:
+
+permissions:
+ contents: read
+ pages: write
+ id-token: write
+
+concurrency:
+ group: 'pages'
+ cancel-in-progress: false
+
+env:
+ CARGO_TERM_COLOR: always
+ RUST_BACKTRACE: 1
+
+jobs:
+ quality-check:
+ uses: ./.github/workflows/check.yml
+
+ test:
+ uses: ./.github/workflows/test.yml
+
+ build-doc:
+ name: Build documentation
+ runs-on: ubuntu-latest
+ needs: quality-check
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Install Rust toolchain
+ uses: dtolnay/rust-toolchain@nightly
+
+ - name: Build docs
+ env:
+ RUSTDOCFLAGS: -D rustdoc::broken_intra_doc_links -D missing-docs
+ run: |
+ cargo doc --no-deps --all-features
+ printf '' > target/doc/index.html
+
+ - name: Upload artifact
+ uses: actions/upload-pages-artifact@v3
+ with:
+ path: target/doc
+
+ deploy-doc:
+ name: Deploy to GitHub Pages
+ environment:
+ name: github-pages
+ url: ${{ steps.deployment.outputs.page_url }}
+ runs-on: ubuntu-latest
+ needs: build-doc
+ if: github.ref == format('refs/heads/{0}', github.event.repository.default_branch)
+ steps:
+ - name: Deploy to GitHub Pages
+ id: deployment
+ uses: actions/deploy-pages@v4
diff --git a/.github/workflows/release-check.yml b/.github/workflows/release-check.yml
deleted file mode 100644
index b9e1c68..0000000
--- a/.github/workflows/release-check.yml
+++ /dev/null
@@ -1,58 +0,0 @@
-name: Release Check
-
-on:
- push:
- tags:
- - 'v*'
-
-env:
- CARGO_TERM_COLOR: always
- RUST_BACKTRACE: 1
-
-jobs:
- release-check:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- - uses: dtolnay/rust-toolchain@nightly
- with:
- components: rustfmt, clippy
-
- - name: Verify version consistency
- run: |
- # Extract version from git tag (remove 'v' prefix)
- TAG_VERSION="${GITHUB_REF#refs/tags/v}"
- # Extract version from Cargo.toml
- CARGO_VERSION=$(grep -m1 '^version' Cargo.toml | sed 's/.*"\(.*\)"/\1/')
- echo "Git tag version: $TAG_VERSION"
- echo "Cargo.toml version: $CARGO_VERSION"
- if [ "$TAG_VERSION" != "$CARGO_VERSION" ]; then
- echo "ERROR: Version mismatch! Tag version ($TAG_VERSION) != Cargo.toml version ($CARGO_VERSION)"
- exit 1
- fi
- echo "Version check passed!"
-
- - name: Check code format
- run: cargo fmt --all -- --check
-
- - name: Clippy
- run: cargo clippy --all-targets --all-features -- -D warnings -A clippy::new_without_default
-
- - name: Build
- run: cargo build --all-features
-
- - name: Run tests
- run: cargo test --all-features -- --nocapture
-
- - name: Build documentation
- env:
- RUSTDOCFLAGS: -D rustdoc::broken_intra_doc_links -D missing-docs
- run: cargo doc --no-deps --all-features
-
- - name: Dry run publish
- run: cargo publish --dry-run
-
- - name: Package verification
- run: |
- cargo package --list
- echo "Package contents verified!"
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000..ea5d548
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,156 @@
+name: Release
+
+on:
+ push:
+ tags:
+ - 'v*.*.*'
+ - 'v*.*.*-pre.*'
+
+permissions:
+ contents: write
+
+jobs:
+ check:
+ uses: ./.github/workflows/check.yml
+
+ test:
+ uses: ./.github/workflows/test.yml
+ needs: check
+
+ create-release:
+ name: Create GitHub Release
+ runs-on: ubuntu-latest
+ needs: check
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - name: Validate tag and branch (HEAD-based)
+ shell: bash
+ run: |
+ set -e
+
+ TAG="${{ github.ref_name }}"
+ TAG_COMMIT=$(git rev-list -n 1 "$TAG")
+
+ git fetch origin main dev
+
+ MAIN_HEAD=$(git rev-parse origin/main)
+ DEV_HEAD=$(git rev-parse origin/dev)
+
+ echo "Tag: $TAG"
+ echo "Tag commit: $TAG_COMMIT"
+ echo "main HEAD: $MAIN_HEAD"
+ echo "dev HEAD: $DEV_HEAD"
+
+ if [[ "$TAG" == *-pre.* ]]; then
+ if [ "$TAG_COMMIT" != "$DEV_HEAD" ]; then
+ echo "❌ prerelease tag must be created from dev HEAD"
+ exit 1
+ fi
+ echo "✅ prerelease tag validated on dev"
+ else
+ if [ "$TAG_COMMIT" != "$MAIN_HEAD" ]; then
+ echo "❌ stable release tag must be created from main HEAD"
+ exit 1
+ fi
+ echo "✅ stable release tag validated on main"
+ fi
+
+ - name: Verify version consistency
+ run: |
+ # Extract version from git tag (remove 'v' prefix)
+ TAG_VERSION="${{ github.ref_name }}"
+ TAG_VERSION="${TAG_VERSION#v}"
+ # Extract version from Cargo.toml
+ CARGO_VERSION=$(grep -m1 '^version' Cargo.toml | sed 's/.*"\(.*\)"/\1/')
+ echo "Git tag version: $TAG_VERSION"
+ echo "Cargo.toml version: $CARGO_VERSION"
+ if [ "$TAG_VERSION" != "$CARGO_VERSION" ]; then
+ echo "ERROR: Version mismatch! Tag version ($TAG_VERSION) != Cargo.toml version ($CARGO_VERSION)"
+ exit 1
+ fi
+ echo "Version check passed!"
+
+ - name: Create GitHub Release
+ uses: softprops/action-gh-release@v2
+ with:
+ draft: false
+ prerelease: ${{ contains(github.ref_name, '-pre.') }}
+ body: |
+ ## ${{ github.ref_name }}
+
+ - [Documentation](https://docs.rs/axhvc)
+ - [crates.io](https://crates.io/crates/axhvc)
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
+ publish-crates:
+ name: Publish to crates.io
+ runs-on: ubuntu-latest
+ needs: check
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - name: Validate tag and branch (HEAD-based)
+ shell: bash
+ run: |
+ set -e
+
+ TAG="${{ github.ref_name }}"
+ TAG_COMMIT=$(git rev-list -n 1 "$TAG")
+
+ git fetch origin main dev
+
+ MAIN_HEAD=$(git rev-parse origin/main)
+ DEV_HEAD=$(git rev-parse origin/dev)
+
+ echo "Tag: $TAG"
+ echo "Tag commit: $TAG_COMMIT"
+ echo "main HEAD: $MAIN_HEAD"
+ echo "dev HEAD: $DEV_HEAD"
+
+ if [[ "$TAG" == *-pre.* ]]; then
+ if [ "$TAG_COMMIT" != "$DEV_HEAD" ]; then
+ echo "❌ prerelease tag must be created from dev HEAD"
+ exit 1
+ fi
+ echo "✅ prerelease tag validated on dev"
+ else
+ if [ "$TAG_COMMIT" != "$MAIN_HEAD" ]; then
+ echo "❌ stable release tag must be created from main HEAD"
+ exit 1
+ fi
+ echo "✅ stable release tag validated on main"
+ fi
+
+ - name: Verify version consistency
+ run: |
+ # Extract version from git tag (remove 'v' prefix)
+ TAG_VERSION="${{ github.ref_name }}"
+ TAG_VERSION="${TAG_VERSION#v}"
+ # Extract version from Cargo.toml
+ CARGO_VERSION=$(grep -m1 '^version' Cargo.toml | sed 's/.*"\(.*\)"/\1/')
+ echo "Git tag version: $TAG_VERSION"
+ echo "Cargo.toml version: $CARGO_VERSION"
+ if [ "$TAG_VERSION" != "$CARGO_VERSION" ]; then
+ echo "ERROR: Version mismatch! Tag version ($TAG_VERSION) != Cargo.toml version ($CARGO_VERSION)"
+ exit 1
+ fi
+ echo "Version check passed!"
+
+ - name: Install Rust toolchain
+ uses: dtolnay/rust-toolchain@nightly
+
+ - name: Dry run publish
+ run: cargo publish --dry-run
+
+ - name: Publish to crates.io
+ run: cargo publish --token ${{ secrets.CARGO_REGISTRY_TOKEN }}
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
new file mode 100644
index 0000000..cd99d90
--- /dev/null
+++ b/.github/workflows/test.yml
@@ -0,0 +1,21 @@
+name: Test
+
+on:
+ workflow_call:
+
+jobs:
+ test:
+ name: Test
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Install Rust toolchain
+ uses: dtolnay/rust-toolchain@nightly
+
+ - name: Run tests
+ run: cargo test --all-features -- --nocapture
+
+ - name: Run doc tests
+ run: cargo test --doc