Skip to content

First-push checklist & CI bring-up (WW-42)

Everything in WorkWingman has been built, gated, and committed locally — the repo has never been pushed. The first push is the user's call (the autonomous build never pushes). This doc is the pre-flight: what was verified before that push, what the push triggers, and how to confirm it landed clean. Clearing it unblocks WW-33 (prove the security CI jobs on a real GitHub runner).

1. Pre-push hygiene — verified

Run from the repo root; all of these were green at the time of writing.

Check Command Result
Remote configured git remote -v origingithub.com/andrewjonesdev/WorkWingman.git
No build artifacts tracked git ls-files \| grep -E '(^\|/)(bin\|obj\|node_modules)/\|\.(dll\|exe\|pdb)$' ✅ empty
.gitignore present test -f .gitignore
.gitattributes normalizes CI-sensitive files cat .gitattributes ✅ SVGs -text (byte-identical for the diagram drift-check), *.sh eol=lf (LF shebangs on Linux runners)
No large blobs (>500 KB) size sweep over git ls-files ✅ none
No hardcoded secrets in source git grep -nIE '(password\|secret\|apikey\|token)\s*=\s*["'"'"'][^"'"'"']{8,}' over src/frontend/src ✅ none (secrets live in the KeePass vault / env / IConfiguration, never in source)
Secret-scan config present test -e .gitleaks.toml ✅ (the secrets job runs gitleaks over full history against it)
Test settings present test -e test.runsettings
Dependency allowlist present .github/dependency-allowlist.txt
Stryker configs present per-project (tests/WorkWingman.Tests/stryker-config.json, frontend/stryker.conf.json)
SECURITY.md published docs/SECURITY.md (+ plain/technical variants)
Working tree clean git status --porcelain (excluding docs/business/)

Line endings note: the working copy is on Windows with core.autocrlf active, so git reports "LF will be replaced by CRLF" on commit. The repo stores LF; only the SVGs and shell scripts are pinned via .gitattributes (the two places CRLF would actually break CI). Source files round-trip fine. If line-ending churn ever shows up in diffs, add * text=auto — not needed today.

2. What the first push triggers

Two workflows fire on push / pull_request to the default branch. This is their first run on a hosted runner (they've only been validated locally in Docker so far — that's the WW-33 gap).

.github/workflows/ci.yml — the main gate, jobs: - backenddotnet build -c Release + dotnet test (with test.runsettings), Playwright chromium installed. - frontendnpm ci + Angular unit tests. - sast — Semgrep (p/csharp p/typescript p/javascript p/security-audit p/secrets), --error hard-fails on findings; inline // nosemgrep: <rule> -- <reason> suppressions. - secrets — gitleaks over the FULL history (fetch-depth: 0) against .gitleaks.toml. Hard gate. - dast — OWASP ZAP baseline against the running API on 127.0.0.1:5211. - securitynpm audit --audit-level=high (hard gate on high/critical). - churn / docs / diagrams — doc + diagram drift checks (the D2 SVGs must match their source). - dotnet-e2e — the Playwright E2E project builds and runs.

.github/workflows/mutation.yml — Stryker mutation testing (backend from tests/WorkWingman.Tests, frontend from frontend/). This is the WW-34 surface; it uploads the mutation report as an artifact.

3. The push (user action — the build never pushes)

git -C <repo> push -u origin master

If GitHub rejects the branch name or the repo wants main, rename first (git branch -m master main) — but confirm the workflows' branch filters match whatever you land on.

4. Post-push verification (this is WW-33)

  1. Open the repo's Actions tab; the two workflows should appear on the pushed commit.
  2. Confirm each ci.yml job goes green. The likely first-run friction points, and what they mean:
  3. dast needs the API reachable on :5211 inside the job — if it can't bind, the job step that launches the API is the thing to check, not the ZAP step.
  4. secrets scanning full history can surface something an incremental local scan missed — read any finding before assuming a false positive; add to .gitleaks.toml only with a justification.
  5. sast findings are hard failures — triage each; suppress inline only with a reason.
  6. If a hosted-runner-only failure appears (a tool version, a container permission, a path-case mismatch), fix it on a branch and re-push — do not disable the job to make it green.
  7. Once all jobs are green on the hosted runner, WW-33 is satisfied and can be closed.

5. Not covered here (still blocked, by design)

  • WW-32 — Workday selectors on a real tenant (needs a live tenant).
  • WW-34 — mutation-coverage thresholds for the apply vertical (the workflow runs; ratcheting the score is its own task).