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
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
133 lines
4.3 KiB
Bash
Executable File
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
|