Cold debug build + 1/3 partition test execution observed at 300m+ on VPS2
(14 CPU, 28GB RAM). First pipeline after a Cargo.lock change triggers a cold
CACHE_KEY rebuild (~180-190m), leaving insufficient time for test execution.
420m provides headroom for cold-cache pipelines; warm cache runs complete in
45-90m well within the limit.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1. Add -Clink-arg=-fuse-ld=lld to .test-base RUSTFLAGS.
LLD uses significantly less RAM than ld when linking large debug binaries
(pezkuwi-availability-distribution, pezsc-service). On kurditv with 8G
container memory limit, ld Bus-errors during the link step. LLD resolves
this without raising the memory cap.
2. Apply the same fmt resilience pattern to check-core-crypto-features:
CARGO_HOME=/root/.cargo, before_script:[], retry: when:always max:2.
The job hits server_timeout_running on vps3 (same root cause as fmt —
GitLab CI cache download hangs before the script produces any output).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Two changes:
1. Use CARGO_HOME=/root/.cargo + before_script:[] + cache:[] for fmt.
cargo fmt --check does not compile and needs no registry download.
GitLab CI cache downloads happen before any log output — if the download
hangs on a flaky runner, the job silently times out with server_timeout_running
and an empty trace, blocking all downstream jobs.
2. Switch retry when: to `always`. GitLab has no retry keyword for
server_timeout_running (internal code). `always` ensures infrastructure
failures (container-start, cache-download, runner crash) are retried on
a different runner. Real format violations fail deterministically on all
retries and still produce a correct FAIL outcome; max: 2 caps wasted runs.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Two root-cause fixes for repeated disk-full (ENOSPC) failures on VPS runners:
1. Add -Cdebuginfo=1 to RUSTFLAGS in .test-base.
Line-tables-only strips variable/type debug info while keeping file:line
in panic stack traces. On a full Substrate workspace this cuts the debug/
artifacts from ~52 G to ~20 G (~60% reduction).
2. Change wasm-check CARGO_TARGET_DIR from its own per-job dir to the shared
test-release dir. The wasm32v1-none artifacts land in test-release/wasm32v1-none/
which is orthogonal to test-release/debug/ used by test-partition jobs.
Removing the intra-key find…rm prevents wasm-check from wiping the 52 G
test-release dir mid-pipeline when test-no-try-runtime jobs are still queued.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
test-doc has SKIP_WASM_BUILD=0 which compiles WASM runtimes and doc tests,
producing 27G+ of artifacts. It was persisting those to /cache/cargo-target/
alongside the test-release dir, filling the 96G kurditv volume to 100%.
Since test-doc is allow_failure and the warm-cache benefit doesn't justify
the disk cost, switch it to the ephemeral container filesystem (same approach
as clippy). The before_script no longer sets CARGO_TARGET_DIR.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Root cause: server_timeout_running (kurditv disk-full Docker failures) hits
GitLab's 60m default timeout and is not caught by stuck_or_timeout_failure,
runner_system_failure, or unknown_failure — meaning no retry triggers, and fmt
(a pipeline blocker) fails permanently, skipping ALL downstream jobs.
Fix: give every quick-check and security job an explicit tight timeout. A stuck
runner now hits job_execution_timeout (a matchable retry condition) in seconds
or minutes, not 60m. The retry then lands on one of the two healthy runners.
Timeouts added (worst-case real duration shown):
fmt: 10m (normally ~90s) retry: max 2
check-toml-format: 5m
check-dependency-rules: 5m
check-fail-ci: 5m
check-workspace-integrity: 15m
check-zepter: 20m
test-rust-features: 10m
check-umbrella: 30m
check-licenses-headers: 10m
check-core-crypto-features: 15m
cargo-deny-licenses: 20m
cargo-deny-sources: 20m
cargo-audit: 20m retry: max 2
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Two root causes from pipeline 2480888929:
1. /cache volume bloat — kurditv hit 93G/96G (97% full). The before_script
pruned old cache KEYS but never cleaned other job dirs within the SAME key.
Old test-partition-1/, test-partition-2/, wasm-check/, … accumulated across
pipelines alongside the new test-release/ dir, filling the volume.
Fix: add a second find that removes every sibling dir in CACHE_KEY/ except
the current job's dir. .test-base keeps only test-release/; wasm-check keeps
only wasm-check/. Each pipeline run starts with a clean slate per job type.
2. Release builds exceeded 300m — vps3 was still compiling
pezbridge-hub-zagros-runtime at minute 300 in --release mode.
Clippy (debug) took 162m cold; release mode is 2-3x slower.
Fix: remove --release from all cargo nextest run commands. RUSTFLAGS already
includes -Cdebug-assertions=y so assertion coverage is identical. Debug
artifacts are smaller (less disk pressure) and compile faster.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Three root causes from pipeline 2480399247 (b756499b):
1. kurditv runner failures: `server_timeout_running` and `no_updates_running`
are internal GitLab failure codes NOT caught by stuck_or_timeout_failure or
runner_system_failure. Added unknown_failure to all retry conditions so
retries trigger and land on a healthy runner.
2. Test partition job_execution_timeout (150m): tests run with --release so
C deps (jemalloc/rocksdb) take hours to compile on cold VPS cache. CARGO_TARGET_DIR
was per-CI_JOB_NAME so each partition compiled independently. Changed to shared
test-release dir — C deps compiled once per runner per cache key, all partitions
reuse. Timeout bumped from 150m to 300m to survive a full cold build.
3. wasm-check: no explicit timeout → hit 60m GitLab default. Added timeout: 2h
and retry conditions.
Also: test-doc/build-rustdoc/build-implementers-guide got retry conditions;
build-implementers-guide got explicit 15m timeout (mdbook is fast).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Unstable runners occasionally get stuck in the prepare phase with no
log output. Any job can be affected. Adding retry: max: 1, when:
stuck_or_timeout_failure to all remaining jobs that lacked it:
quick-checks: check-dependency-rules, check-fail-ci,
check-workspace-integrity, check-zepter, test-rust-features,
check-umbrella, check-licenses-headers
security: cargo-deny-sources, cargo-audit
checks: check-core-crypto-features
Clippy and check-try-runtime excluded — retrying 36m/81m jobs on
actual timeout would be too expensive; those get runner_system_failure
coverage for runner crashes instead.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
fmt occasionally gets stuck on unstable runners (empty log, 17+ min
with no output). Since clippy depends on fmt, a stuck fmt blocks the
entire critical path: clippy → check-try-runtime → all tests.
retry: max: 1, when: stuck_or_timeout_failure covers runner freeze
without masking actual cargo fmt formatting failures.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Both jobs occasionally get stuck on unstable runners with no output
for 40-50+ minutes (empty log, runner preparing phase freeze). Without
explicit retry, they fail the pipeline with stuck_or_timeout_failure.
retry: max: 1, when: stuck_or_timeout_failure retries only on genuine
runner freezes, not on taplo format errors or license violations.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
librocksdb-sys debug build writes a multi-GB librocksdb.a static archive
to /cache/cargo-target, filling the volume and causing build failure.
Persistent cache is not safe for C++ heavy dependencies.
Keep CARGO_HOME=/root/.cargo (avoids re-downloading the Rust crate
registry on every run). CARGO_TARGET_DIR stays ephemeral (Docker
container fs has ample space).
Timeout stays at 3h to cover cold builds on slower runners.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Two root causes for clippy taking 100+ minutes on cold runners:
1. CARGO_HOME=$CI_PROJECT_DIR/.cargo (global default) is wiped each job,
forcing re-download of the entire crate registry on every run.
Fix: override CARGO_HOME=/root/.cargo (pre-baked in the CI image).
2. CARGO_TARGET_DIR not persisted — compiled artifacts discarded after
each run, forcing full recompile on the same runner.
Fix: same /cache/cargo-target/$CACHE_KEY/clippy setup as test jobs.
First run on a fresh runner: still slow (~100m, cold compile).
Subsequent runs on same runner: ~10-15m (warm cache reuse).
Timeout bumped to 3h to safely cover the cold-build case.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
VPS2 Docker daemon crashed mid-run, killing test-partition-1/2 and
leaving wasm-check/test-no-try-runtime-2 with 404 exec errors. None
of these were test failures — all were runner infrastructure failures.
retry: max: 1, when: runner_system_failure retries only on runner
crashes, never on actual test failures. Correct safeguard for
multi-runner setups where any VPS can restart unexpectedly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
advisory-db is cloned from GitHub (rustsec/advisory-db). The runner
(merkez-server) occasionally fails to reach GitHub — the clone fails
silently, the advisory-dbs/ directory is not created, and cargo-deny
then tries to run git-log on a non-existent path, producing:
'fatal: cannot change to ...' parsed as an ISO-8601 date → crash
Real fix: GitLab native retry (max: 2, when: script_failure).
This retries the full job on infrastructure failures without bypassing
the security check — if all 3 attempts fail, the job still fails.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Two root causes fixed:
1. test-partition-* timeout (90m):
- WASM runtime sub-builds were running during test compilation.
SKIP_WASM_BUILD=1 skips them — unit/integration tests use mock
environments and don't need actual WASM blobs.
- WASM_BUILD_WORKSPACE_HINT=$CI_PROJECT_DIR: when CARGO_TARGET_DIR is
outside the project directory, wasm-builder's build script searches
upward for Cargo.lock and fails to find it. Without Cargo.lock it
resolves deps fresh (no --locked), selecting alloy-eips@1.8.3 and
ruint@1.18.0 which require Rust 1.91/1.90 (toolchain is 1.88).
- Timeout increased 90m → 150m for cold-cache headroom.
2. wasm-check arrayvec compile failure (197 errors):
cargo check --target wasm32v1-none uses whole-workspace feature
unification, which enables arrayvec's std feature. wasm32v1-none is
a bare-metal target with no libstd, so arrayvec must be no_std there.
Fixed in arrayvec fork: force no_std when
target_arch=wasm32 && target_os=none, regardless of feature flags.
Cargo.lock updated to new arrayvec commit (0c417574).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Three sequential cargo check commands were causing a 90m timeout on GitLab
shared runners (no persistent target/ cache). Command 3 (try-runtime,experimental)
is a strict superset of commands 1 and 2:
- cmd 1: --all --features try-runtime → redundant, cmd 3 covers it
- cmd 2: -p teyrchain-template-node --features try-runtime → redundant,
teyrchain-template-node is in the workspace (templates/teyrchain/node)
so --all already includes it
Keep only the most comprehensive check. Increase timeout to 120m to give the
single compile sufficient headroom on shared runners (~60-70m observed).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
'propagate-features' is not a valid zepter workflow. The correct workflow
is 'default' which runs propagate-feature --fix for workspace + umbrella.
Since check-zepter validates workspace cleanliness first, the workspace
step is a no-op — only umbrella feature lists get populated by Zepter.
Generator intentionally emits empty feature lists (filled by Zepter).
Without running propagate-features after generate, diff always exists.
Add zepter run propagate-features step so check reflects actual state.
- Add tags: [pezkuwi-runner] to .test-base, wasm-check, test-doc
- Set CARGO_TARGET_DIR to /var/cache/cargo-target/<hash>/<job-name> on VPS2
- Hash is md5(Cargo.lock + rust-toolchain.toml) — auto-deletes old keys
- Set CARGO_HOME: /root/.cargo (persistent volume, skip GitLab cache upload)
- Disable GitLab registry cache for self-hosted jobs (cache: [])
- Fix basic-authorship doc test: mark as no_run (requires compiled WASM at runtime)
wasm32-unknown-unknown with build-std=core,alloc on Rust >=1.88 now ships
a pre-built std in the sysroot, causing E0152 duplicate core lang items when
serde_core is compiled. Switching to wasm32v1-none (target_os=none, no sysroot
std) eliminates the conflict. Also fixes wasm-check getrandom compile_error
which only triggers on wasm*-unknown-unknown, not wasm32v1-none.
target-main cache key doesn't invalidate on Cargo.lock changes, so
pre-fix serde_core compiled artifacts were restored into test builds,
reintroducing duplicate alloc lang items after the serde fork fix.
check-zepter: CARGO_HOME=$CI_PROJECT_DIR/.cargo but export used $HOME/.cargo/bin;
switched to $CARGO_HOME/bin so installed zepter 1.82.1 takes precedence.
cargo-audit: set -o pipefail caused the pipe to fail with cargo-audit's exit
code (1 when vulns exist) even when python check passed; redirect to file first.
- deny.toml: add all-features=true to [graph] — prevents krates 0.20+ panic
on workspace crates that have std feature but don't enable it by default
- deny.toml: allow pezkuwichain/serde.git in [sources] (our wasm32v1-none fork)
- deny.toml: remove stale RUSTSEC ignores (2023-0071, 2024-0428, 2025-0055)
- deny.toml: add new wasmtime/rand/webpki advisories to ignore list
- ci: remove --exclude flag from cargo-deny jobs (flag removed in new versions)
- ci: rewrite cargo-audit to use JSON + python summary (prevents 4MB log overflow)
and add all current advisories to ignore set with documented rationale
- ci: fix check-zepter to use --force (not --locked) so 1.82.1 actually installs
- Cargo.toml: add default=[std] to bizinikiwi-test-runtime-transaction-pool
(std crate that was missing default feature, confusing krates graph builder)