8 improve ci for speed and maintainability #15
Workflow file for this run
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
| name: Release | |
| on: | |
| push: | |
| branches: | |
| - main | |
| pull_request: | |
| branches: | |
| - main | |
| permissions: | |
| contents: write | |
| packages: write | |
| pull-requests: read | |
| env: | |
| CARGO_TERM_COLOR: always | |
| RUST_BACKTRACE: 1 | |
| jobs: | |
| test: | |
| name: Run Tests | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v5 | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Cache dependencies | |
| uses: Swatinem/rust-cache@v2 | |
| - name: Run tests | |
| run: cargo test --all-features | |
| - name: Run clippy | |
| run: cargo clippy --all-targets --all-features -- -D warnings | |
| - name: Check formatting | |
| run: cargo fmt --all -- --check | |
| semantic-version: | |
| name: Determine Version | |
| needs: test | |
| runs-on: ubuntu-latest | |
| outputs: | |
| version: ${{ steps.version.outputs.version }} | |
| version_tag: ${{ steps.version.outputs.version_tag }} | |
| changed: ${{ steps.version.outputs.changed }} | |
| changelog: ${{ steps.version.outputs.changelog }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v5 | |
| with: | |
| fetch-depth: 0 | |
| - name: Semantic Version | |
| id: version | |
| uses: paulhatch/semantic-version@v5.4.0 | |
| with: | |
| tag_prefix: "v" | |
| major_pattern: "(MAJOR)" | |
| minor_pattern: "(MINOR)" | |
| version_format: "${major}.${minor}.${patch}" | |
| change_path: "src" | |
| namespace: "" | |
| bump_each_commit: false | |
| search_commit_body: true | |
| user_format_type: "csv" | |
| enable_prerelease_mode: false | |
| create-release: | |
| name: Create Release | |
| runs-on: ubuntu-latest | |
| needs: semantic-version | |
| if: needs.semantic-version.outputs.changed == 'true' && github.event_name == 'push' | |
| outputs: | |
| upload_url: ${{ steps.create_release.outputs.upload_url }} | |
| version: ${{ needs.semantic-version.outputs.version }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v5 | |
| - name: Update Cargo.toml version | |
| run: | | |
| sed -i.bak 's/^version = ".*"/version = "${{ needs.semantic-version.outputs.version }}"/' Cargo.toml && rm Cargo.toml.bak | |
| git config --local user.email "action@github.com" | |
| git config --local user.name "GitHub Action" | |
| git add Cargo.toml | |
| git commit -m "chore: bump version to ${{ needs.semantic-version.outputs.version }}" || exit 0 | |
| - name: Create Release | |
| id: create_release | |
| uses: softprops/action-gh-release@v2 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| with: | |
| tag_name: ${{ needs.semantic-version.outputs.version_tag }} | |
| name: Release ${{ needs.semantic-version.outputs.version }} | |
| draft: false | |
| prerelease: false | |
| generate_release_notes: true | |
| body: | | |
| ## Changes | |
| ${{ needs.semantic-version.outputs.changelog }} | |
| ## Installation | |
| ### Binary Downloads | |
| You can download pre-built binaries for your platform from the assets below. | |
| ### Cargo Install | |
| ```bash | |
| cargo install repos | |
| ``` | |
| ### From Source | |
| ```bash | |
| git clone https://github.com/${{ github.repository }}.git | |
| cd repos | |
| cargo build --release | |
| ``` | |
| build-release: | |
| name: Build Release Binary | |
| needs: [semantic-version, create-release] | |
| if: needs.semantic-version.outputs.changed == 'true' && github.event_name == 'push' | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| matrix: | |
| include: | |
| - os: ubuntu-latest | |
| target: x86_64-unknown-linux-gnu | |
| suffix: "" | |
| - os: ubuntu-latest | |
| target: x86_64-unknown-linux-musl | |
| suffix: "" | |
| - os: windows-latest | |
| target: x86_64-pc-windows-msvc | |
| suffix: ".exe" | |
| - os: macos-latest | |
| target: x86_64-apple-darwin | |
| suffix: "" | |
| - os: macos-latest | |
| target: aarch64-apple-darwin | |
| suffix: "" | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v5 | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| targets: ${{ matrix.target }} | |
| - name: Install musl tools | |
| if: matrix.target == 'x86_64-unknown-linux-musl' | |
| run: sudo apt-get update && sudo apt-get install -y musl-tools | |
| - name: Cache dependencies | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| key: ${{ matrix.target }} | |
| - name: Build for ${{ matrix.target }} | |
| run: | | |
| cargo build --release --target ${{ matrix.target }} | |
| if [[ "${{ matrix.target }}" == *"windows"* ]]; then | |
| mv target/${{ matrix.target }}/release/repos.exe repos-${{ matrix.target }}.exe | |
| else | |
| mv target/${{ matrix.target }}/release/repos repos-${{ matrix.target }} | |
| fi | |
| - name: Strip binary (Unix only) | |
| if: matrix.suffix == '' | |
| run: | | |
| if [[ "${{ runner.os }}" == "macOS" ]]; then | |
| strip -x repos-${{ matrix.target }} | |
| else | |
| strip repos-${{ matrix.target }} | |
| fi | |
| - name: Create archive | |
| shell: bash | |
| run: | | |
| staging="repos-${{ needs.semantic-version.outputs.version }}-${{ matrix.target }}" | |
| mkdir -p "$staging" | |
| cp repos-${{ matrix.target }}${{ matrix.suffix }} "$staging/" | |
| cp README.md "$staging/" 2>/dev/null || true | |
| if [ -f LICENSE ]; then cp LICENSE "$staging/"; fi | |
| tar czf "$staging.tar.gz" "$staging" | |
| echo "ASSET=$staging.tar.gz" >> $GITHUB_ENV | |
| - name: Upload Release Asset | |
| uses: softprops/action-gh-release@v2 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| with: | |
| tag_name: ${{ needs.semantic-version.outputs.version_tag }} | |
| files: ${{ env.ASSET }} | |
| build-universal-macos: | |
| name: Build Universal macOS Binary | |
| needs: [semantic-version, create-release] | |
| runs-on: macos-latest | |
| if: needs.semantic-version.outputs.changed == 'true' && github.event_name == 'push' | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v5 | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| targets: x86_64-apple-darwin,aarch64-apple-darwin | |
| - name: Cache dependencies | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| key: universal-macos | |
| - name: Build for both architectures | |
| run: | | |
| cargo build --release --target x86_64-apple-darwin | |
| cargo build --release --target aarch64-apple-darwin | |
| - name: Create universal binary | |
| run: | | |
| lipo -create \ | |
| target/x86_64-apple-darwin/release/repos \ | |
| target/aarch64-apple-darwin/release/repos \ | |
| -output repos-universal-apple-darwin | |
| # Verify the universal binary | |
| lipo -info repos-universal-apple-darwin | |
| - name: Strip universal binary | |
| run: strip -x repos-universal-apple-darwin | |
| - name: Create universal archive | |
| run: | | |
| staging="repos-${{ needs.semantic-version.outputs.version }}-universal-apple-darwin" | |
| mkdir -p "$staging" | |
| cp repos-universal-apple-darwin "$staging/repos" | |
| cp README.md "$staging/" 2>/dev/null || true | |
| if [ -f LICENSE ]; then cp LICENSE "$staging/"; fi | |
| tar czf "$staging.tar.gz" "$staging" | |
| echo "UNIVERSAL_ASSET=$staging.tar.gz" >> $GITHUB_ENV | |
| - name: Upload Universal macOS Asset | |
| uses: softprops/action-gh-release@v2 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| with: | |
| tag_name: ${{ needs.semantic-version.outputs.version_tag }} | |
| files: ${{ env.UNIVERSAL_ASSET }} | |
| publish-crate: | |
| name: Publish to crates.io | |
| needs: [semantic-version, create-release, build-release, build-universal-macos] | |
| runs-on: ubuntu-latest | |
| if: needs.semantic-version.outputs.changed == 'true' && github.event_name == 'push' && !contains(needs.semantic-version.outputs.version, 'alpha') && !contains(needs.semantic-version.outputs.version, 'beta') && !contains(needs.semantic-version.outputs.version, 'rc') | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v5 | |
| - name: Update Cargo.toml version | |
| run: | | |
| sed -i.bak 's/^version = ".*"/version = "${{ needs.semantic-version.outputs.version }}"/' Cargo.toml && rm Cargo.toml.bak | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Cache dependencies | |
| uses: Swatinem/rust-cache@v2 | |
| - name: Publish to crates.io | |
| run: cargo publish --token ${{ secrets.CARGO_REGISTRY_TOKEN }} | |
| docker-release: | |
| name: Build and Push Docker Image | |
| needs: [semantic-version, create-release] | |
| runs-on: ubuntu-latest | |
| if: needs.semantic-version.outputs.changed == 'true' && github.event_name == 'push' | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Log in to Docker Hub | |
| uses: docker/login-action@v3 | |
| with: | |
| username: ${{ secrets.DOCKER_USERNAME }} | |
| password: ${{ secrets.DOCKER_PASSWORD }} | |
| - name: Log in to GitHub Container Registry | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Extract metadata | |
| id: meta | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: | | |
| ${{ secrets.DOCKER_USERNAME }}/repos | |
| ghcr.io/${{ github.repository }} | |
| tags: | | |
| type=semver,pattern={{version}},value=${{ needs.semantic-version.outputs.version }} | |
| type=semver,pattern={{major}}.{{minor}},value=${{ needs.semantic-version.outputs.version }} | |
| type=semver,pattern={{major}},value=${{ needs.semantic-version.outputs.version }} | |
| type=raw,value=latest | |
| - name: Build and push Docker image | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: . | |
| platforms: linux/amd64,linux/arm64 | |
| push: true | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| provenance: false | |
| sbom: false | |
| build-args: | | |
| VERSION=${{ needs.semantic-version.outputs.version }} |