Build with clawstor cache / Cargo build (clawstor-cached) (pull_request) Successful in 10s
Three fixes surfaced by the 2026-07-13 Gitea Actions wire-up.
## XDG config path
Before: `client_config::user_config_path` only looked at
`~/.claw-cargo/config.toml`. My runner-integration doc initially
told operators to install at `~/.config/claw-cargo/config.toml`
(XDG-style). Config wasn't loaded.
Now: three-way lookup, first hit wins.
1. `$XDG_CONFIG_HOME/claw-cargo/config.toml`
2. `$HOME/.config/claw-cargo/config.toml`
3. `$HOME/.claw-cargo/config.toml` (legacy, still honoured)
+3 tests: XDG env wins when the file exists, .config wins over
legacy dotfile when both present, legacy dotfile returned as
error-message fallback when none exist.
## Composite action
Before: composite action silently no-op'd. Log showed the script
lines echoed but only the `if command -v claw-cargo` fail branch
ran. Root cause: Gitea Actions composite steps run with a stripped
PATH that omits `/usr/local/bin`.
Now: composite step exports PATH defensively:
export PATH="/usr/local/bin:$HOME/.cargo/bin:$PATH"
And it looks for the config at BOTH the XDG-style path and the
legacy dotfile (same order as client_config).
Workflow file back to using the composite action.
## Docs
Runner-integration doc now:
- Explicitly warns that `ubuntu-latest` routes to container mode
even with `:host` suffix on runner labels (field-observed).
- Documents the dedicated `clawstor-cache` label pattern that
works.
- Sample workflow uses `runs-on: clawstor-cache` instead of
`ubuntu-latest`.
+3 tests, 262 total (baseline unchanged).
111 lines
4.1 KiB
YAML
111 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 the runner user's home
|
|
(~/.config/claw-cargo/config.toml or the legacy ~/.claw-cargo/) —
|
|
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: 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
|
|
# Field finding 2026-07-13: Gitea Actions composite steps run
|
|
# with a stripped PATH that omits /usr/local/bin. Force it +
|
|
# the runner user's cargo bin, so the CLI is found regardless
|
|
# of how the workflow was invoked.
|
|
export PATH="/usr/local/bin:$HOME/.cargo/bin:$PATH"
|
|
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
|
|
# Accept both the XDG-style path and the legacy dotfile
|
|
# location. client_config resolves them in the same order.
|
|
cfg=""
|
|
for cand in \
|
|
"${XDG_CONFIG_HOME:-$HOME/.config}/claw-cargo/config.toml" \
|
|
"$HOME/.claw-cargo/config.toml"; do
|
|
if [ -s "$cand" ]; then
|
|
cfg="$cand"
|
|
break
|
|
fi
|
|
done
|
|
if [ -z "$cfg" ]; then
|
|
echo "::error::no claw-cargo config found under \$HOME/.config/claw-cargo/ or \$HOME/.claw-cargo/ - fleet admin needs to provision peer + tls_dir for this runner"
|
|
exit 1
|
|
fi
|
|
|
|
args=(build --workspace "$WS" --profile "$PROFILE" --parallel-restore "$PAR_RESTORE")
|
|
if [ "$NO_UPLOAD" = "true" ]; then
|
|
args+=(--no-upload)
|
|
fi
|
|
|
|
started=$SECONDS
|
|
set +e
|
|
claw-cargo "${args[@]}" 2>&1 | tee /tmp/clawstor-build.out
|
|
rc=${PIPESTATUS[0]}
|
|
set -e
|
|
elapsed=$((SECONDS - started))
|
|
|
|
outcome=SKIPPED
|
|
if grep -q 'cache: *HIT' /tmp/clawstor-build.out; then
|
|
outcome=HIT
|
|
elif grep -qE '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"
|