diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8506567..082e22b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,23 +6,44 @@ on: pull_request: branches: [main, master] +# Cancel in-progress runs for the same ref so stale PR builds don't burn minutes. +concurrency: + group: ci-${{ github.ref }} + cancel-in-progress: true + +# Deny all permissions at workflow level; each job declares only what it needs. +permissions: {} + env: CARGO_TERM_COLOR: always RUST_BACKTRACE: 1 jobs: + fmt: + name: Format + runs-on: ubuntu-latest + timeout-minutes: 10 + permissions: + contents: read + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - run: rustup component add rustfmt + - run: cargo fmt --all -- --check + test: name: Test runs-on: macos-latest - + timeout-minutes: 30 + permissions: + contents: read steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Install Rust toolchain run: rustup show - name: Cache cargo registry - uses: actions/cache@v4 + uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: | ~/.cargo/registry/index/ @@ -32,13 +53,13 @@ jobs: restore-keys: ${{ runner.os }}-cargo- - name: Cache build artifacts - uses: actions/cache@v4 + uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: target/ - key: ${{ runner.os }}-build-${{ hashFiles('**/Cargo.toml') }}-${{ hashFiles('**/*.rs') }} + key: ${{ runner.os }}-build-ci-${{ hashFiles('**/Cargo.toml') }}-${{ hashFiles('**/*.rs') }} restore-keys: | - ${{ runner.os }}-build-${{ hashFiles('**/Cargo.toml') }}- - ${{ runner.os }}-build- + ${{ runner.os }}-build-ci-${{ hashFiles('**/Cargo.toml') }}- + ${{ runner.os }}-build-ci- - name: Check dependency isolation run: | @@ -54,24 +75,17 @@ jobs: - name: Unit tests run: cargo test --lib --workspace - - name: Build release binary - run: cargo build --release + # Use the ci profile (no LTO, opt-level 1) — fast compile, still checks the binary builds. + - name: Build binary (ci profile) + run: cargo build --profile ci - name: Check binary size run: | - SIZE=$(stat -f%z target/release/agent-desktop) + SIZE=$(stat -f%z target/ci/agent-desktop) LIMIT=$((15 * 1024 * 1024)) - echo "Binary size: $(du -sh target/release/agent-desktop | cut -f1)" + echo "Binary size: $(du -sh target/ci/agent-desktop | cut -f1)" if [ "$SIZE" -gt "$LIMIT" ]; then echo "FAIL: binary exceeds 15MB limit (${SIZE} bytes)" exit 1 fi echo "OK: binary within 15MB limit" - - fmt: - name: Format - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - run: rustup component add rustfmt - - run: cargo fmt --all -- --check diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 274149b..8736528 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -4,6 +4,13 @@ on: push: branches: [main] +# One release run per commit — never cancel, just queue. +concurrency: + group: release-${{ github.sha }} + +# Deny all permissions at workflow level; each job declares only what it needs. +permissions: {} + env: CARGO_TERM_COLOR: always @@ -11,6 +18,7 @@ jobs: release-please: name: Release Please runs-on: ubuntu-latest + timeout-minutes: 10 permissions: contents: write pull-requests: write @@ -19,7 +27,7 @@ jobs: tag_name: ${{ steps.release.outputs.tag_name }} version: ${{ steps.release.outputs.major }}.${{ steps.release.outputs.minor }}.${{ steps.release.outputs.patch }} steps: - - uses: googleapis/release-please-action@v4 + - uses: googleapis/release-please-action@5c625bfb5d1ff62eadeeb3772007f7f66fdcf071 # v4.4.1 id: release with: config-file: release-please-config.json @@ -30,13 +38,18 @@ jobs: needs: release-please if: needs.release-please.outputs.release_created == 'true' runs-on: macos-latest + timeout-minutes: 30 + permissions: + contents: read + # Both arch targets build in parallel; one failure doesn't block the other. strategy: + fail-fast: false matrix: target: - aarch64-apple-darwin - x86_64-apple-darwin steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: ref: ${{ needs.release-please.outputs.tag_name }} @@ -46,7 +59,7 @@ jobs: rustup target add ${{ matrix.target }} - name: Cache cargo registry - uses: actions/cache@v4 + uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: | ~/.cargo/registry/index/ @@ -74,25 +87,26 @@ jobs: TARBALL="agent-desktop-v${VERSION}-${{ matrix.target }}.tar.gz" tar -czf "${TARBALL}" -C target/${{ matrix.target }}/release agent-desktop shasum -a 256 "${TARBALL}" > "${TARBALL}.sha256" - echo "TARBALL=${TARBALL}" >> "$GITHUB_ENV" - name: Upload artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: binary-${{ matrix.target }} path: | agent-desktop-v*.tar.gz agent-desktop-v*.tar.gz.sha256 + retention-days: 1 publish-github: name: Publish to GitHub Release needs: [release-please, build] runs-on: ubuntu-latest + timeout-minutes: 10 permissions: contents: write steps: - name: Download all artifacts - uses: actions/download-artifact@v4 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: pattern: binary-* merge-multiple: true @@ -116,17 +130,18 @@ jobs: name: Publish to npm needs: [release-please, publish-github] runs-on: ubuntu-latest + timeout-minutes: 15 permissions: contents: read id-token: write steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: ref: ${{ needs.release-please.outputs.tag_name }} - - uses: actions/setup-node@v4 + - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: - node-version: 20 + node-version: '24' registry-url: https://registry.npmjs.org - name: Verify GitHub Release assets @@ -164,14 +179,17 @@ jobs: needs: [release-please] if: needs.release-please.outputs.release_created == 'true' runs-on: ubuntu-latest + timeout-minutes: 10 + permissions: + contents: read steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: ref: ${{ needs.release-please.outputs.tag_name }} - - uses: actions/setup-node@v4 + - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: - node-version: "22" + node-version: '24' - name: Install ClawHub CLI run: npm i -g clawhub diff --git a/Cargo.toml b/Cargo.toml index 8f88a9a..f27ebc9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,3 +25,13 @@ lto = true codegen-units = 1 strip = true panic = "abort" + +# Fast build for CI: skip LTO and size optimisations, keep debug info for +# better test failure messages. Inherits release settings not listed here. +[profile.ci] +inherits = "release" +opt-level = 1 +lto = false +codegen-units = 16 +strip = false +debug = 1