From 0442f85d5648186905381085fa57937d68ec3c66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C5=ABdolfs=20O=C5=A1i=C5=86=C5=A1?= Date: Tue, 13 Oct 2026 11:21:14 +0200 Subject: [PATCH] Add `check:ci` script Runs the checks from the GitHub workflows in one go, like desktop's `scripts/check-ci`, and logs them to `tests/tmp/check-ci.log`. --- .ryph/environment.md | 3 ++ CLAUDE.md | 5 +++ package.json | 1 + scripts/check-ci | 94 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 103 insertions(+) create mode 100755 scripts/check-ci diff --git a/.ryph/environment.md b/.ryph/environment.md index 567f48f1f..94fd85d71 100644 --- a/.ryph/environment.md +++ b/.ryph/environment.md @@ -47,6 +47,9 @@ RUSTDOCFLAGS="-D warnings" cargo doc --workspace --all-features npm run test:e2e -- --project chromium ``` +`npm run check:ci` runs all of the explorer's checks in order, plus the build +smoke test, and logs to `tests/tmp/check-ci.log`. + Desktop, from `desktop/`: ```sh diff --git a/CLAUDE.md b/CLAUDE.md index 03269420c..ca34f531d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -170,6 +170,11 @@ and fall back when they're absent. ### Pre-push checklist +`npm run check:ci` runs everything below except the `:local` variants, plus +the build smoke test, from the GitHub workflows, and stops at the first +failure. It logs each step's output, duration and exit code to +`tests/tmp/check-ci.log`. + 1. `npm run check` 2. `npm run test:unit` 3. `npm run test:http-client:unit` diff --git a/package.json b/package.json index 8e4895634..5191bc683 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "serve": "vite preview", "build": "vite build", "check": "scripts/check", + "check:ci": "scripts/check-ci", "check:radicle-httpd": "cargo clippy --all --tests && cargo fmt --all --check", "format": "npx prettier '**/*.@(ts|js|svelte|json|css|html|yml)' --write", "test:unit": "TZ='UTC' vitest run", diff --git a/scripts/check-ci b/scripts/check-ci new file mode 100755 index 000000000..3062eb6ee --- /dev/null +++ b/scripts/check-ci @@ -0,0 +1,94 @@ +#!/usr/bin/env bash +# Runs the same checks as the explorer's GitHub workflows (.github/workflows/ +# check*.yml) and keeps the full output with per-step timings in +# tests/tmp/check-ci.log. That log lives outside tests/artifacts, which +# Playwright clears when the e2e run starts. +# +# Leaves out check-visual.yml: its baselines exist only as CI artifacts. The +# desktop app in desktop/ has its own desktop/scripts/check-ci. +set -uo pipefail + +cd "$(dirname "$0")/.." || exit + +log=tests/tmp/check-ci.log +mkdir -p "$(dirname "$log")" +echo "check-ci started $(date -u +%Y-%m-%dT%H:%M:%SZ) at $(git rev-parse --short HEAD)" >"$log" + +if [ -t 1 ]; then + bold=$'\e[1m' dim=$'\e[2m' green=$'\e[32m' red=$'\e[31m' reset=$'\e[0m' +else + bold="" dim="" green="" red="" reset="" +fi + +# Prints to the terminal with styling and to the log without. +say() { + printf '%s\n' "$1" + printf '%s\n' "$2" >>"$log" +} + +width=$(tput cols 2>/dev/null || echo 80) +[ "$width" -gt 100 ] && width=100 + +# A full-width rule with a title, like "━━ check-js ━━━━━━". +rule() { + local text="━━ $1 " + local fill=$((width - ${#text})) + [ "$fill" -lt 3 ] && fill=3 + printf '%s%s' "$text" "$(printf '━%.0s' $(seq 1 "$fill"))" +} + +steps=( + "check|npm run check" + "unit-test|npm run test:unit" + "install-binaries|mkdir -p tests/artifacts && scripts/install-binaries" + "http-client-unit-test|npm run test:http-client:unit" + "rust build|RUSTFLAGS='-D warnings' cargo build --workspace --all-features" + "rust test|cargo test --workspace --all-features && cargo test -p radicle-httpd" + "rust lint|RUSTFLAGS='-D warnings' cargo clippy --workspace --all-features --tests && RUSTFLAGS='-D warnings' cargo clippy -p radicle-httpd --no-default-features --tests && cargo fmt --all -- --check" + "playwright install|npx playwright install chromium" + "build|npm run build && npm run test:e2e -- --project chromium --config playwright.buildSmoke.config.ts" + "e2e|npm run test:e2e -- --project chromium" +) +summary=() +status=0 +total_start=$SECONDS + +for step in "${steps[@]}"; do + name=${step%%|*} + command=${step#*|} + if [ "$status" -ne 0 ]; then + summary+=("$(printf '%s- %-18s skipped%s' "$dim" "$name" "$reset")|$(printf -- '- %-18s skipped' "$name")") + continue + fi + + say "" "" + say "${bold}$(rule "$name")${reset}" "$(rule "$name")" + say "${dim} \$ $command${reset}" " \$ $command" + say "" "" + start=$SECONDS + bash -c "$command" 2>&1 | awk '{ print " " $0; fflush() }' | tee -a "$log" + status=${PIPESTATUS[0]} + took=$((SECONDS - start)) + + if [ "$status" -eq 0 ]; then + summary+=("$(printf '%s✓%s %-18s %4ss' "$green" "$reset" "$name" "$took")|$(printf '✓ %-18s %4ss' "$name" "$took")") + else + summary+=("$(printf '%s✗ %-18s %4ss exit %s%s' "$red" "$name" "$took" "$status" "$reset")|$(printf '✗ %-18s %4ss exit %s' "$name" "$took" "$status")") + fi +done + +say "" "" +say "${bold}$(rule summary)${reset}" "$(rule summary)" +say "" "" +for line in "${summary[@]}"; do + say " ${line%%|*}" " ${line#*|}" +done +say "" "" + +took=$((SECONDS - total_start)) +if [ "$status" -eq 0 ]; then + say " ${bold}${green}All checks passed in ${took}s${reset} ${dim}· log: $log${reset}" " All checks passed in ${took}s" +else + say " ${bold}${red}Checks failed after ${took}s${reset} ${dim}· log: $log${reset}" " Checks failed after ${took}s" +fi +exit "$status"