Files
acaua/scripts/check.sh
T
Lucas RayanandClaude Sonnet 5 8a80504c45
Release / Plan (reuse the published image?) (push) Successful in 3s
CI / Docker image (build and smoke test) (push) Skipped
CI / Format and clippy (push) Successful in 4m32s
CI / Dependency audit (push) Successful in 11s
CI / Tests (Linux) (push) Successful in 9m15s
Release / ci (push) Successful in 9m18s
Release / Build image (arm64) (push) Failing after 7m7s
Release / Build image (amd64) (push) Failing after 13m53s
Release / Publish tags (push) Skipped
Release / Gitea release (push) Skipped
refactor: distribute Acaua as a Docker image instead of a desktop app
Acaua is a collective SOC daemon consuming only Zeek log files, not a
single-user tool needing local hardware like its siblings. Drop the
Tauri desktop shell, installers and self-update entirely; the server
and its web dashboard ship as a container, updated by pulling a new
image tag.

Link against the official prebuilt libduckdb instead of compiling it
from source via the bundled feature, cutting image build time from
15+ minutes to about 3. Fix a real bug found along the way: as PID 1
in a container, the daemon ignored SIGTERM and was always killed
after the stop timeout; it now shuts down gracefully.

Also corrects the Pillar 1 beaconing score: the period estimate had a
harmonic alias (a perfectly periodic 4h series resolved to 600s), and
the old score formula flagged pure random traffic as suspicious
(p95 = 0.839 on Poisson noise). The new formula was validated against
300 samples per scenario.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VAyr8d7HuAdUGB6aA5xmDD
2026-10-31 19:54:45 -03:00

133 lines
4.3 KiB
Bash
Executable File

#!/usr/bin/env bash
# Local verification: runs the same fast checks as CI before pushing.
#
# scripts/check.sh fast (~1 min): fmt, clippy, i18n, scripts, workflows, semver
# scripts/check.sh --full also runs workspace tests and cargo audit
#
# CI takes 5 to 30 minutes per run; almost everything that breaks CI is caught
# here in seconds.
set -uo pipefail
cd "$(dirname "$0")/.."
full=0
[ "${1:-}" = "--full" ] || [ "${1:-}" = "--completo" ] && full=1
failures=()
step() { # step "name" command...
local name="$1"; shift
printf '\n\033[1m== %s\033[0m\n' "$name"
if "$@"; then printf '\033[32mok\033[0m %s\n' "$name"; else printf '\033[31mFAILED\033[0m %s\n' "$name"; failures+=("$name"); fi
}
duckdb_dir="${XDG_CACHE_HOME:-$HOME/.cache}/acaua/duckdb"
scripts/fetch-libduckdb.sh "$duckdb_dir" >/dev/null || { echo "could not install libduckdb" >&2; exit 1; }
export DUCKDB_LIB_DIR="$duckdb_dir" DUCKDB_INCLUDE_DIR="$duckdb_dir" LD_LIBRARY_PATH="$duckdb_dir${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
step "formatting (cargo fmt)" cargo fmt --all -- --check
# Same flags as CI: warnings are treated as errors across all targets, including tests
step "clippy (workspace, all targets)" env RUSTFLAGS="-D warnings" cargo clippy --workspace --all-targets
check_forbidden_terms() {
python3 - <<'PY'
from pathlib import Path
terms = [
'Fast' + 'API',
'Click' + 'House',
'latest' + '.json',
'updater' + '.pubkey',
'createUpdater' + 'Artifacts',
'plugin' + '-updater',
'Tau' + 'ri',
'App' + 'Image',
]
skip_dirs = {'.git', 'target', '.wolf', '.claude'}
allowed = {
Path('docs/architecture.md'),
Path('docs/pt-BR/arquitetura.md'),
Path('CHANGELOG.md'),
Path('CHANGELOG.pt-BR.md'),
}
hits = []
for path in Path('.').rglob('*'):
if not path.is_file() or any(part in skip_dirs for part in path.parts):
continue
if path in allowed:
continue
try:
text = path.read_text(errors='ignore')
except OSError:
continue
for term in terms:
if term in text:
hits.append(f'{path}: {term}')
if hits:
print('\n'.join(hits))
raise SystemExit(1)
PY
}
step "UI translation coverage" node scripts/check-ui-i18n.mjs
step "bash script syntax" bash -c 'for f in scripts/*.sh .githooks/*; do bash -n "$f" || exit 1; done'
step "workflows and templates (valid YAML)" python3 -c "
import glob, yaml
for f in glob.glob('.gitea/**/*.yml', recursive=True):
yaml.safe_load(open(f))
"
step "brand assets" test -s logo.png
step "consistent Semantic Versioning 2.0.0" python3 -c "
import re, sys
from pathlib import Path
semver_re = re.compile(
r'^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)'
r'(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?'
r'(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$'
)
def cargo_version(path):
m = re.search(r'^version\s*=\s*\"([^\"]+)\"', Path(path).read_text(), re.M)
if not m:
sys.exit(f'version not found in {path}')
return m.group(1)
version = cargo_version('Cargo.toml')
if not semver_re.match(version):
sys.exit(f'invalid SemVer 2.0.0 version: {version}')
print(version)
"
step "DuckDB pin matches the duckdb crate" python3 -c "
import re, sys
from pathlib import Path
lock = Path('Cargo.lock').read_text()
m = re.search(r'^name = \"duckdb\"\nversion = \"1\.(\d+)\.\d+\"', lock, re.M)
if not m:
sys.exit('duckdb crate not found in Cargo.lock')
enc = int(m.group(1))
crate = f'{enc // 10000}.{enc // 100 % 100}.{enc % 100}'
pin = re.search(r'^DUCKDB_VERSION=(\S+)$', Path('scripts/fetch-libduckdb.sh').read_text(), re.M).group(1)
if crate != pin:
sys.exit(f'DuckDB mismatch: duckdb crate targets {crate}, scripts/fetch-libduckdb.sh pins {pin}')
print(f'DuckDB {pin}')
"
step "forbidden stack terms" check_forbidden_terms
if command -v docker >/dev/null && docker compose version >/dev/null 2>&1; then
step "docker compose config" docker compose config --quiet
else
printf '\n(docker compose config: skipped, docker compose not available)\n'
fi
if [ "$full" = 1 ]; then
step "tests (cargo test --workspace)" cargo test --workspace
step "dependency audit (cargo audit)" cargo audit
fi
printf '\n'
if [ ${#failures[@]} -eq 0 ]; then
printf '\033[32mall checks passed\033[0m: ready to push.\n'
else
printf '\033[31mfailed:\033[0m %s\n' "${failures[*]}"
exit 1
fi