diff --git a/.gitea/actions/rust-cache/action.yml b/.gitea/actions/rust-cache/action.yml index 1edb970..40f4fe1 100644 --- a/.gitea/actions/rust-cache/action.yml +++ b/.gitea/actions/rust-cache/action.yml @@ -7,43 +7,39 @@ inputs: description: Rust toolchain to install (e.g., stable, 1.75.0, nightly) default: stable required: false + cache-prefix: + description: Prefix for cache keys. + default: rust + required: false outputs: cache-hit: description: "Whether a cache entry was found" - value: ${{ steps.cache.outputs.cache-hit }} + value: ${{ steps.cache-restore.outputs.cache-hit }} runs: using: composite steps: - # Gitea Actions does not have Cargo.lock by default (cargo generates it on first build), - # and hashFiles() globs don't work reliably here. Use shell hashing instead. - name: Compute cache key id: cache-key shell: bash run: | - # Hash both files; if Cargo.lock doesn't exist yet, only Cargo.toml is hashed - HASH=$( (cat Cargo.toml 2>/dev/null || true; cat Cargo.lock 2>/dev/null || true) | sha256sum | cut -d' ' -f1) + { + printf 'toolchain=%s\n' '${{ inputs.toolchain }}' + find . \ + \( -path './.git' -o -path './target' \) -prune -o \ + \( -name Cargo.toml -o -name Cargo.lock -o -name rust-toolchain -o -name rust-toolchain.toml \) \ + -type f -print0 \ + | sort -z \ + | xargs -0 sha256sum 2>/dev/null || true + } > /tmp/rust-cache-fingerprint + HASH=$(sha256sum /tmp/rust-cache-fingerprint | cut -d' ' -f1) echo "hash=$HASH" >> $GITHUB_OUTPUT - echo "fingerprint=$HASH" >> $GITHUB_ENV + echo "key=${{ inputs.cache-prefix }}-${{ runner.os }}-${{ runner.arch }}-${{ inputs.toolchain }}-$HASH" >> $GITHUB_OUTPUT + echo "restore-prefix=${{ inputs.cache-prefix }}-${{ runner.os }}-${{ runner.arch }}-${{ inputs.toolchain }}-" >> $GITHUB_OUTPUT - - name: Setup Rust - shell: bash - run: | - # If toolchain was cached, rustup will skip download — install still runs for metadata - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \ - | sh -s -- -y --default-toolchain ${{ inputs.toolchain }} - # Add cargo bin to PATH for subsequent steps - echo "$HOME/.cargo/bin" >> $GITHUB_PATH - - - name: Show sizes before cache - shell: bash - run: | - echo "=== ~/.cargo ===" && du -sh ~/.cargo 2>/dev/null || echo "(empty)" - echo "=== ~/.rustup ===" && du -sh ~/.rustup 2>/dev/null || echo "(empty)" - - - name: Save cache - id: cache-save + - name: Restore Rust cache + id: cache-restore env: ACTIONS_CACHE_SERVICE_V2: "0" uses: https://gitea.com/actions/cache@v3 @@ -54,71 +50,13 @@ runs: ~/.rustup/toolchains ~/.rustup/settings.toml target - key: rust-linux-${{ steps.cache-key.outputs.hash }} - save-always: true + key: ${{ steps.cache-key.outputs.key }} + restore-keys: | + ${{ steps.cache-key.outputs.restore-prefix }} - - name: Debug print save outputs + - name: Setup Rust shell: bash run: | - echo "=== Save action outputs ===" - echo "cache-hit: '${{ steps.cache-save.outputs.cache-hit }}'" - echo "key: '${{ steps.cache-save.outputs.key }}'" - echo "=== All outputs ===" - env | grep -i ACTIONS_CACHE || echo "No ACTIONS_CACHE env vars in shell" - - - name: Twirp probe via curl (debug) - shell: bash - env: - ACTIONS_CACHE_URL: ${{ env.ACTIONS_CACHE_URL }} - ACTIONS_RUNTIME_TOKEN: ${{ env.ACTIONS_RUNTIME_TOKEN }} - ACTIONS_RESULTS_URL: ${{ env.ACTIONS_RESULTS_URL }} - run: | - echo "=== Cache env vars ===" - echo "ACTIONS_CACHE_URL=$ACTIONS_CACHE_URL" - echo "ACTIONS_RUNTIME_TOKEN len=${#ACTIONS_RUNTIME_TOKEN}" - if [ -n "$ACTIONS_CACHE_URL" ]; then - HASH="${{ steps.cache-key.outputs.hash }}" - KEY="rust-linux-$HASH" - echo "=== Twirp v1: GetCacheEntryDownloadURL ===" - BODY=$(printf '{"key":"%s","restoreKeys":[],"version":"%s"}' "$KEY" "$HASH") - echo "POST $ACTIONS_CACHE_URL/twirp/github.actions.results.api.v1.CacheService/GetCacheEntryDownloadURL" - echo "Body: $BODY" - RESP=$(curl -si -X POST \ - -H "Content-Type: application/json" \ - -H "Authorization: Bearer $ACTIONS_RUNTIME_TOKEN" \ - "$ACTIONS_CACHE_URL/twirp/github.actions.results.api.v1.CacheService/GetCacheEntryDownloadURL" \ - -d "$BODY" \ - 2>&1) - echo "$RESP" - echo "" - echo "=== Also try list cache API ===" - LIST_RESP=$(curl -si \ - -H "Authorization: Bearer $ACTIONS_RUNTIME_TOKEN" \ - "$ACTIONS_CACHE_URL/_apis/artifactcache/caches?key=$KEY&version=$HASH" \ - 2>&1) - echo "$LIST_RESP" - else - echo "ACTIONS_CACHE_URL is empty" - fi - - - name: Lookup same key immediately after save - id: cache-lookup - env: - ACTIONS_CACHE_URL: ${{ env.ACTIONS_CACHE_URL }} - ACTIONS_RUNTIME_TOKEN: ${{ env.ACTIONS_RUNTIME_TOKEN }} - ACTIONS_CACHE_SERVICE_V2: "0" - ACTIONS_RESULTS_URL: ${{ env.ACTIONS_RESULTS_URL }} - uses: https://gitea.com/actions/cache@v3 - with: - path: ~/.cargo/registry - key: rust-linux-${{ steps.cache-key.outputs.hash }} - lookup-only: true - - - name: Show sizes after cache - shell: bash - run: | - echo "=== ~/.cargo ===" && du -sh ~/.cargo 2>/dev/null || echo "(empty)" - echo "=== ~/.rustup ===" && du -sh ~/.rustup 2>/dev/null || echo "(empty)" - echo "save result: ${{ steps.cache-save.outputs.cache-hit }}" - echo "lookup result: ${{ steps.cache-lookup.outputs.cache-hit }}" - echo "ACTIONS_CACHE_URL=$ACTIONS_CACHE_URL" + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \ + | sh -s -- -y --profile minimal --default-toolchain ${{ inputs.toolchain }} + echo "$HOME/.cargo/bin" >> $GITHUB_PATH diff --git a/README.md b/README.md index ab146c2..97a22f6 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Reusable Gitea Actions for Rust projects. ## actions/rust-cache -Composite action that installs a Rust toolchain and caches cargo/crate dependencies. +Composite action that restores Rust build caches, installs a Rust toolchain, and saves updated cargo/rustup/target caches after the job. ### Usage @@ -18,7 +18,8 @@ jobs: - name: Setup Rust + Cache uses: https://git.ericxliu.me/eric/actions-rust/.gitea/actions/rust-cache@main with: - toolchain: stable # optional, defaults to stable + toolchain: stable # optional, defaults to stable + cache-prefix: rust # optional, defaults to rust - run: cargo build --release - run: cargo test @@ -26,14 +27,15 @@ jobs: ### What it does -1. **Cache restore** — Restores `~/.cargo/registry`, `~/.cargo/git`, `~/.rustup/toolchains`, and `target/` using Gitea's native `actions/cache`. -2. **Rust install** — Runs `rustup` to install or verify the requested toolchain. -3. **PATH setup** — Appends `$HOME/.cargo/bin` to `$GITHUB_PATH` so cargo/rustc are available in subsequent steps. +1. **Cache key** — Hashes root/workspace `Cargo.toml`, `Cargo.lock`, and `rust-toolchain*` files without relying on `hashFiles()`. +2. **Cache restore/save** — Restores `~/.cargo/registry`, `~/.cargo/git`, `~/.rustup/toolchains`, and `target/` using Gitea's native `actions/cache`. The cache action saves updated paths in its post step after later build/test steps have populated them. +3. **Rust install** — Runs `rustup` with the minimal profile to install or verify the requested toolchain. +4. **PATH setup** — Appends `$HOME/.cargo/bin` to `$GITHUB_PATH` so cargo/rustc are available in subsequent steps. ### Cache key format ``` -rust-linux-{hash(Cargo.lock)}{hash(Cargo.toml)} +{cache-prefix}-{runner.os}-{runner.arch}-{toolchain}-{hash(manifests/toolchain files)} ``` Warm builds run in ~40–60s vs ~3min for a cold build.