Build with clawstor cache / Cargo build (clawstor-cached) (pull_request) Failing after 4s
Ships the wire-up piece for real CI: a composite Gitea Action that wraps `claw-cargo build` with cache-outcome reporting, plus a matching workflow file that opts the clawstor repo itself into being cache-hit-tested on every push. Also docs the one-time per-runner provisioning (leaf cert, PATH install, config.toml). * `.gitea/actions/cargo-cache/action.yml` — composite Action. Inputs: workspace, profile, no-upload, parallel-restore. Outputs: cache-outcome (HIT|MISS|POPULATED|SKIPPED), fingerprint, elapsed-seconds. Runner-side config lives in `~/.config/claw-cargo/config.toml` (not in the workflow — no secrets shipped from repos). * `.gitea/workflows/build-with-cache.yml` — dogfoods the action on clawstor's own repo. `no-upload` set from event_name so PRs from forks can't poison the cache. * `docs/runner-integration.md` — one-time setup steps, sample workflow snippet, expected numbers (Pi 5: 2.79× wall, tank: 2.18×), and troubleshooting for the failures I hit in the tank and Pi pilots (bind_lan on fabric-only, missing CLI/config, rustc drift warn). Test protocol: push this branch → main triggers the workflow → the runner on tank has claw-cargo + tls + config provisioned already (2026-07-13 pilot setup) → first build should MISS + populate, subsequent build on same fingerprint should HIT.
109 lines
4.1 KiB
YAML
109 lines
4.1 KiB
YAML
name: 'Clawstor cargo cache'
|
|
description: >
|
|
Wraps `cargo build` with a peer-cache lookup: HIT restores the
|
|
target dir from the runner-local clawstor daemon (skipping dep
|
|
compile); MISS runs cargo build then captures + uploads the target
|
|
dir to the daemon. Config comes from
|
|
`~/.config/claw-cargo/config.toml` on the runner host — provisioned
|
|
by the fleet-admin, not from the workflow.
|
|
|
|
inputs:
|
|
workspace:
|
|
description: 'Path to the cargo workspace root'
|
|
required: false
|
|
default: '.'
|
|
profile:
|
|
description: 'Cargo profile (dev, release, custom)'
|
|
required: false
|
|
default: 'dev'
|
|
no-upload:
|
|
description: >
|
|
When "true", skip capture + upload on a miss. Useful for
|
|
read-only CI jobs (PR builds, forks). Defaults to false so
|
|
main-branch jobs populate the cache.
|
|
required: false
|
|
default: 'false'
|
|
parallel-restore:
|
|
description: >
|
|
Concurrent chunk fetches on cache HIT. Default 1 (sequential
|
|
BlobGetStream) — measured faster than parallel on loopback. Set
|
|
to 8+ on cross-node deployments where per-stream throughput
|
|
caps bite.
|
|
required: false
|
|
default: '1'
|
|
|
|
outputs:
|
|
cache-outcome:
|
|
description: 'One of: HIT, MISS, POPULATED, SKIPPED'
|
|
value: ${{ steps.build.outputs.cache-outcome }}
|
|
fingerprint:
|
|
description: 'The fingerprint claw-cargo computed for this build'
|
|
value: ${{ steps.build.outputs.fingerprint }}
|
|
elapsed-seconds:
|
|
description: 'Wall-clock seconds elapsed in the build step'
|
|
value: ${{ steps.build.outputs.elapsed-seconds }}
|
|
|
|
runs:
|
|
using: 'composite'
|
|
steps:
|
|
- name: Preflight check (claw-cargo + config)
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
if ! command -v claw-cargo >/dev/null 2>&1; then
|
|
echo "::error::claw-cargo not on PATH — fleet admin needs to install /usr/local/bin/claw-cargo on this runner"
|
|
exit 1
|
|
fi
|
|
claw-cargo --version
|
|
# The daemon config is per-runner; the action expects it to
|
|
# exist under $HOME/.config/claw-cargo/config.toml. We do not
|
|
# ship secrets from the workflow.
|
|
cfg="${HOME}/.config/claw-cargo/config.toml"
|
|
if [ ! -s "$cfg" ]; then
|
|
echo "::error::missing $cfg — fleet admin needs to provision peer + tls_dir for this runner"
|
|
exit 1
|
|
fi
|
|
|
|
- name: Build with clawstor cache
|
|
id: build
|
|
shell: bash
|
|
env:
|
|
WS: ${{ inputs.workspace }}
|
|
PROFILE: ${{ inputs.profile }}
|
|
NO_UPLOAD: ${{ inputs.no-upload }}
|
|
PAR_RESTORE: ${{ inputs.parallel-restore }}
|
|
run: |
|
|
set -euo pipefail
|
|
args=(build --workspace "$WS" --profile "$PROFILE" --parallel-restore "$PAR_RESTORE")
|
|
if [ "$NO_UPLOAD" = "true" ]; then
|
|
args+=(--no-upload)
|
|
fi
|
|
started=$SECONDS
|
|
# Tee the summary so we can grep the outcome out for the output.
|
|
set +e
|
|
claw-cargo "${args[@]}" 2>&1 | tee /tmp/clawstor-build.out
|
|
rc=${PIPESTATUS[0]}
|
|
set -e
|
|
elapsed=$((SECONDS - started))
|
|
|
|
# Parse `cache:` line. Shapes we handle:
|
|
# cache: HIT (... bytes downloaded)
|
|
# cache: MISS
|
|
# cache: MISS -> populated (... bytes uploaded)
|
|
# cache: MISS (no upload performed)
|
|
outcome="SKIPPED"
|
|
if grep -q 'cache: *HIT' /tmp/clawstor-build.out; then
|
|
outcome="HIT"
|
|
elif grep -q 'cache: *MISS -> populated' /tmp/clawstor-build.out \
|
|
|| grep -q 'cache: *MISS → populated' /tmp/clawstor-build.out; then
|
|
outcome="POPULATED"
|
|
elif grep -q 'cache: *MISS' /tmp/clawstor-build.out; then
|
|
outcome="MISS"
|
|
fi
|
|
fingerprint="$(grep -oE 'fingerprint: [0-9a-f]+' /tmp/clawstor-build.out | head -1 | awk '{print $2}')"
|
|
echo "cache-outcome=$outcome" >> "$GITHUB_OUTPUT"
|
|
echo "fingerprint=${fingerprint:-unknown}" >> "$GITHUB_OUTPUT"
|
|
echo "elapsed-seconds=$elapsed" >> "$GITHUB_OUTPUT"
|
|
echo "::notice::clawstor $outcome fingerprint=${fingerprint:-unknown} elapsed=${elapsed}s"
|
|
exit "$rc"
|