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