From c4d8360eb4dcd5db834869d134569ec2120f3e91 Mon Sep 17 00:00:00 2001 From: "Calvin A. Allen" Date: Fri, 9 Jan 2026 10:36:37 -0500 Subject: [PATCH 1/2] ci: add GitHub Actions workflows - Add build.yml: Rust build/test on Linux, macOS, Windows - Rustfmt check - Clippy linting (all platforms) - Tests (all platforms) - Release builds (4 targets) - Add commit-lint.yml: PR title and commit message validation - Add contributors.yml: Uses reusable workflow from .github - Add .commitlintrc.yml: Conventional commits configuration --- .commitlintrc.yml | 80 +++++++++++++ .github/workflows/build.yml | 176 +++++++++++++++++++++++++++++ .github/workflows/commit-lint.yml | 59 ++++++++++ .github/workflows/contributors.yml | 11 ++ 4 files changed, 326 insertions(+) create mode 100644 .commitlintrc.yml create mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/commit-lint.yml create mode 100644 .github/workflows/contributors.yml diff --git a/.commitlintrc.yml b/.commitlintrc.yml new file mode 100644 index 0000000..9d61732 --- /dev/null +++ b/.commitlintrc.yml @@ -0,0 +1,80 @@ +# Commitlint configuration for conventional commits +# Based on: https://www.conventionalcommits.org/ + +extends: + - '@commitlint/config-conventional' + +rules: + # Type enum - allowed commit types + type-enum: + - 2 # Level: error + - always + - # Allowed types: + - feat # New feature + - fix # Bug fix + - docs # Documentation only changes + - style # Code style changes (formatting, missing semi-colons, etc) + - refactor # Code refactoring (neither fixes a bug nor adds a feature) + - perf # Performance improvements + - test # Adding or updating tests + - build # Changes to build system or dependencies + - ci # CI/CD configuration changes + - chore # Other changes that don't modify src or test files + - revert # Revert a previous commit + + # Type case should be lowercase + type-case: + - 2 + - always + - lower-case + + # Type must not be empty + type-empty: + - 2 + - never + + # Scope case should be lowercase + scope-case: + - 2 + - always + - lower-case + + # Subject must not be empty + subject-empty: + - 2 + - never + + # Subject must not end with a period + subject-full-stop: + - 2 + - never + - '.' + + # Disable subject-case to allow uppercase abbreviations (PR, API, CLI, etc.) + subject-case: + - 0 + + # Header (first line) max length + header-max-length: + - 2 + - always + - 72 + + # Body should have a blank line before it + body-leading-blank: + - 1 # Warning level + - always + + # Footer should have a blank line before it + footer-leading-blank: + - 1 # Warning level + - always + + # Body max line length + body-max-line-length: + - 1 # Warning level + - always + - 100 + +# Help URL shown in error messages +helpUrl: 'https://www.conventionalcommits.org/' diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..997217f --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,176 @@ +name: Build & Test + +on: + workflow_dispatch: + push: + branches: [ main ] + paths-ignore: + - '**.md' + - '.github/ISSUE_TEMPLATE/**' + - '.github/workflows/contributors.yml' + - '.idea/**' + - '.claude/**' + - '.gitignore' + - '.commitlintrc.yml' + - 'LICENSE' + pull_request: + branches: [ main ] + paths-ignore: + - '**.md' + - '.github/ISSUE_TEMPLATE/**' + - '.github/workflows/contributors.yml' + - '.idea/**' + - '.claude/**' + - '.gitignore' + - '.commitlintrc.yml' + - 'LICENSE' + +permissions: + contents: read + +env: + CARGO_TERM_COLOR: always + +jobs: + fmt: + name: Rustfmt + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@stable + with: + components: rustfmt + + - name: Check formatting + run: cargo fmt --all -- --check + + clippy: + name: Clippy (${{ matrix.os }}) + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@stable + with: + components: clippy + + - name: Cache cargo registry + uses: actions/cache@v4 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + target + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + restore-keys: | + ${{ runner.os }}-cargo- + + - name: Run Clippy + run: cargo clippy --all-targets --all-features -- -D warnings + + test: + name: Test (${{ matrix.os }}) + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install Rust toolchain + 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') }} + restore-keys: | + ${{ runner.os }}-cargo- + + - name: Run tests + run: cargo test --verbose + + - name: Generate test summary + if: always() + shell: bash + run: | + echo "## Test Results - ${{ matrix.os }}" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "✅ Tests completed" >> $GITHUB_STEP_SUMMARY + + build: + name: Build ${{ matrix.platform }} + needs: [fmt, clippy, test] + runs-on: ${{ matrix.os }} + strategy: + matrix: + include: + - os: ubuntu-latest + target: x86_64-unknown-linux-gnu + platform: linux-amd64 + binary: rnr + + - os: macos-latest + target: x86_64-apple-darwin + platform: macos-amd64 + binary: rnr + + - os: macos-latest + target: aarch64-apple-darwin + platform: macos-arm64 + binary: rnr + + - os: windows-latest + target: x86_64-pc-windows-msvc + platform: windows-amd64 + binary: rnr.exe + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@stable + with: + targets: ${{ matrix.target }} + + - name: Cache cargo registry + uses: actions/cache@v4 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + target + key: ${{ runner.os }}-${{ matrix.target }}-cargo-${{ hashFiles('**/Cargo.lock') }} + restore-keys: | + ${{ runner.os }}-${{ matrix.target }}-cargo- + + - name: Build release binary + run: cargo build --release --target ${{ matrix.target }} + + - name: Verify build + if: matrix.target != 'aarch64-apple-darwin' + shell: bash + run: | + ./target/${{ matrix.target }}/release/${{ matrix.binary }} --version + ./target/${{ matrix.target }}/release/${{ matrix.binary }} --help + + - name: Upload build artifact + uses: actions/upload-artifact@v4 + with: + name: rnr-${{ matrix.platform }} + path: target/${{ matrix.target }}/release/${{ matrix.binary }} + retention-days: 7 diff --git a/.github/workflows/commit-lint.yml b/.github/workflows/commit-lint.yml new file mode 100644 index 0000000..e765427 --- /dev/null +++ b/.github/workflows/commit-lint.yml @@ -0,0 +1,59 @@ +name: Lint Commit Messages + +on: + pull_request: + types: [opened, edited, reopened, synchronize] + +permissions: + contents: read + pull-requests: read + +jobs: + lint-pr-title: + name: Lint PR Title + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Install commitlint + run: | + npm install --save-dev @commitlint/cli@18.4.3 @commitlint/config-conventional@18.4.3 + + - name: Validate PR title + env: + PR_TITLE: ${{ github.event.pull_request.title }} + run: | + echo "Validating PR title: $PR_TITLE" + echo "$PR_TITLE" | npx commitlint --verbose + + commitlint: + name: Lint Commit Messages + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 # Fetch all history for all branches and tags + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Install commitlint + run: | + npm install --save-dev @commitlint/cli@18.4.3 @commitlint/config-conventional@18.4.3 + + - name: Validate PR commits + run: | + # Get the base branch (usually main) + BASE_SHA=$(git merge-base origin/${{ github.base_ref }} HEAD) + + # Lint all commits in the PR + npx commitlint --from $BASE_SHA --to HEAD --verbose diff --git a/.github/workflows/contributors.yml b/.github/workflows/contributors.yml new file mode 100644 index 0000000..3d381f2 --- /dev/null +++ b/.github/workflows/contributors.yml @@ -0,0 +1,11 @@ +name: Update Contributors + +on: + schedule: + - cron: '0 0 * * *' # Run daily at midnight UTC + workflow_dispatch: # Allow manual trigger + +jobs: + contributors: + uses: CodingWithCalvin/.github/.github/workflows/contributors.yml@main + secrets: inherit From 1669f05c2c1d17dfd0368966735fc58a4102c6ea Mon Sep 17 00:00:00 2001 From: "Calvin A. Allen" Date: Fri, 9 Jan 2026 10:42:59 -0500 Subject: [PATCH 2/2] ci: add preview-changelog workflow --- .github/workflows/preview-changelog.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .github/workflows/preview-changelog.yml diff --git a/.github/workflows/preview-changelog.yml b/.github/workflows/preview-changelog.yml new file mode 100644 index 0000000..ca8d17c --- /dev/null +++ b/.github/workflows/preview-changelog.yml @@ -0,0 +1,12 @@ +name: Preview Changelog + +run-name: Preview release notes for next release + +on: + workflow_dispatch: + +jobs: + preview: + name: Preview + uses: CodingWithCalvin/.github/.github/workflows/generate-changelog.yml@main + secrets: inherit