Skip to content

fix(integration): ensure lookups/_versions/ + _trash/ exist in container #43

fix(integration): ensure lookups/_versions/ + _trash/ exist in container

fix(integration): ensure lookups/_versions/ + _trash/ exist in container #43

Workflow file for this run

name: CI — Validate & Package
# ═══════════════════════════════════════════════════════════════════════
# E2E TEST HARNESS GATE — READ BEFORE ENABLING E2E TESTS IN CI
# ═══════════════════════════════════════════════════════════════════════
#
# The E2E tests under tests/e2e/ are DESTRUCTIVE — they delete KV store
# records, mutate config files, clear tamper flags. Every destructive
# helper is gated behind TWO checks:
#
# 1. WL_TEST_HARNESS=1 environment variable
# 2. Container name "wl_manager_test"
#
# If you add an E2E job to this workflow, set WL_TEST_HARNESS=1 INLINE
# on each step that runs a test, NEVER as a job-wide env block:
#
# - name: Run harness gate verification
# run: WL_TEST_HARNESS=1 node tests/e2e/test_harness_gate.cjs
#
# - name: Run cooldown tamper tests
# run: WL_TEST_HARNESS=1 node tests/e2e/test_cooldown_tamper.cjs
#
# DO NOT set WL_TEST_HARNESS=1 under `env:` at workflow or job scope —
# that leaks the variable into unrelated steps and defeats the point
# of the gate.
#
# DO NOT copy this env var to any other repository, `.env` file, or
# shared shell profile.
#
# See tests/e2e/README.md for the full rationale.
# ═══════════════════════════════════════════════════════════════════════
on:
push:
branches: [main]
pull_request:
branches: [main]
permissions:
contents: read
jobs:
validate:
name: Validate App
runs-on: ubuntu-latest
# Per-job permissions (round 7, 2026-04-29). Even though the
# workflow declares `permissions: contents: read` at the top
# level, repeating it per-job means an audit of any single job
# answers "what can this job touch?" without scrolling. It also
# protects against a future workflow-level change (e.g., adding
# `pull-requests: write` for a comment-bot job) silently
# widening every existing job's scope.
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Run validation checks
run: bash scripts/validate.sh
- name: Build .spl package
run: bash scripts/package.sh
- name: Upload .spl artifact
uses: actions/upload-artifact@v4
with:
name: wl_manager-spl
path: dist/*.spl
retention-days: 30
doc-drift:
name: Doc Drift Check
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- name: Run doc-drift guard
# Same script the pre-commit hook runs locally. Verifies
# file paths in the docs exist + that bare "Build NNN" prose
# stays in sync with default/app.conf. Origin: 2026-04-19
# incident where build numbers drifted across 6 builds
# before the user noticed.
run: bash scripts/pre-commit-doc-drift.sh
unit-tests:
name: Unit Tests
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install Python dev deps
# Pytest + hypothesis + freezegun. Excludes Playwright (the
# E2E tests are gated by WL_TEST_HARNESS=1 and need a real
# Splunk container — see the gate notice at top of file).
# pytest 9.0.3+ required to close GHSA-6w46-j5rx-g56g
# (round 7 B4, 2026-04-29 pip-audit run).
run: |
python -m pip install --upgrade pip
pip install pytest==9.0.3 pytest-cov==5.0.0 freezegun==1.5.1 \
hypothesis==6.90.0 pytest-timeout==2.1.0
- name: Run unit tests
# The unit suite mocks Splunk REST + filesystem layers; no
# Splunk container required. ~7s for 539 tests locally.
run: python -m pytest tests/unit/ -q --tb=short
- name: Run module-level tests
# Top-level tests/test_*.py files cover lower-layer modules
# (wl_limits, wl_hmac_key, wl_fim_common, wl_expiration_cleanup)
# with HMAC and period-boundary coverage that tests/unit/ does
# not duplicate. Note: a former tests/test_wl_filelock.py
# reference was removed during round 7 B4 — no such file
# exists; the filelock paths are exercised inside
# tests/unit/test_filelock.py.
run: |
python -m pytest tests/test_wl_limits.py \
tests/test_wl_hmac_key.py \
tests/test_wl_fim_common.py \
tests/test_wl_expiration_cleanup.py \
-q --tb=short
js-unit-tests:
# Ring 4 Day 1-3 added 46 Vitest unit tests under
# tests/js/ that exercise pure-JS modules
# (parseCSV, csvEscape, validateImportedCSV,
# renderDiff, approval_ui helpers) via an AMD→CJS
# bridge. They run in <250ms with no Splunk
# container — ideal CI gate.
#
# Why a separate job (not folded into unit-tests):
# Python and JS have unrelated dep stacks. Mixing
# them in one job means a Python dep failure breaks
# the JS signal and vice versa. Keeping them split
# gives PR reviewers one green/red light per
# ecosystem.
name: JS Unit Tests
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- name: Set up Node.js
# Node 20 LTS. Vitest 3.x requires Node ≥18; we
# pin to the latest LTS so the toolchain matches
# what most contributors run locally.
uses: actions/setup-node@v4
with:
node-version: "20"
# Cache npm dependencies keyed on package-lock.json
# — every push reuses the cache unless deps
# changed, cutting ~30s off the run.
cache: "npm"
- name: Install dev dependencies
# `npm ci` requires package-lock.json (which exists)
# and is strictly reproducible — fails if
# package.json + lockfile are out of sync. Use
# this rather than `npm install` to catch
# accidentally-uncommitted lockfile drift.
run: npm ci
- name: Run JS unit tests
# ~250ms for 46 tests locally; allow a generous
# 2-minute hard cap in case GitHub runners are
# slow. Failures here surface as a separate
# check beside the Python unit-tests job.
run: npm run test:js
timeout-minutes: 2