Skip to content

ci(validate): unbreak Validate learner branches (git identity + gitleaks OSS) - #2

Merged
GeekTrainer merged 10 commits into
mainfrom
geektrainer/congenial-train
Aug 26, 2026
Merged

ci(validate): unbreak Validate learner branches (git identity + gitleaks OSS)#2
GeekTrainer merged 10 commits into
mainfrom
geektrainer/congenial-train

Conversation

@GeekTrainer

Copy link
Copy Markdown
Contributor

Description

The Validate learner branches workflow (runs on any PR touching course-build/**) fails on every PR for two environment/config reasons that are independent of any code change. They surfaced on PR #1 (the first PR to exercise this workflow) and remain broken on main. This PR fixes both so the gate can actually run.

Related Issue

N/A

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 💥 Breaking change (fix or feature that would cause existing functionality to change)
  • 📚 Documentation update
  • 🧪 Test update
  • 🔧 Refactor (no functional changes)

Affected Services

  • web (Astro SSR + React)
  • assets-svc (.NET 10)
  • workforce-svc (Java 21 / Spring Boot 3)
  • reporting-svc (Python FastAPI)
  • notifications-svc (Python FastAPI)
  • audit-svc (legacy Java 11 / Spring Boot 2.7)
  • auth-svc (legacy Java 11 / Spring Boot 2.7)
  • devcontainer / tooling / docs

Changes Made

  • verify-deltas: configure a git identity before git am. The job applies the module delta patches via build-branches.mjs --check, which shells out to git am. On a fresh runner git has no committer identity, so it aborted with fatal: empty ident name. Added the same "Configure git identity" step the sibling build-and-test job already uses.
  • secret-scan: run the gitleaks OSS binary instead of the licensed action. gitleaks/gitleaks-action@v2 refuses to run on organization repos without a paid GITLEAKS_LICENSE secret (missing gitleaks license). Switched to downloading the pinned gitleaks OSS binary (v8.30.1) and running gitleaks git ., which preserves the full commit-history secret scan (non-zero exit on any finding) with no license dependency. The scanner is not disabled or weakened.

Testing

  • End-to-end (web): npm run test:e2e (Playwright) passes
  • .NET: dotnet test in services/assets-svc passes
  • Python: pytest in services/reporting-svc and/or services/notifications-svc passes
  • Modern Java: mvn test in services/workforce-svc passes
  • Currency-lagging Java: mvn test in services/audit-svc and/or services/auth-svc passes
  • Manually verified the app runs (npm run dev or docker compose up --build) and the affected flow works at http://localhost:4321

Verified the gitleaks change locally: downloaded gitleaks v8.30.1 and ran gitleaks git . against this repo (scanned all commits, "no leaks found", exit 0). The git-identity fix mirrors the step the build-and-test job already relies on for the same git am. The workflow's own verify-deltas gate (delta check + selftest.mjs) will exercise both changes on this PR.

Checklist

  • My change targets main (I have not hand-edited generated learner branches or promoted refs — see CONTRIBUTING.md)
  • My code follows the project's coding standards for the affected language/stack
  • My changes are focused on a single concern
  • I have added or updated tests where it makes sense
  • I have updated documentation (README, per-service READMEs, exercises.md) if needed
  • I have written clear commit messages explaining what and why

Additional Notes

These two fixes were originally authored while landing PR #1 but arrived after that PR had already merged, so they never reached main. This PR carries just those two commits (only .github/workflows/validate-branches.yml changes). Provisioning a GITLEAKS_LICENSE secret and reverting to the action would also work if the org prefers the hosted action; the OSS-binary route was chosen to keep the gate running without a license dependency.

GeekTrainer and others added 2 commits August 26, 2026 09:57
The verify-deltas job runs `build-branches.mjs --check`, which applies the
module delta patches with `git am`. On a fresh CI runner git has no
committer identity, so `git am` aborts with "fatal: empty ident name",
failing the job for any PR that touches course-build/. The sibling
build-and-test job already configures an identity for the same reason;
add the equivalent step to verify-deltas.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 3750cefd-d322-4f02-9184-c8ac3eba2fff
gitleaks/gitleaks-action@v2 refuses to run without a paid GITLEAKS_LICENSE
secret on organization repos, so the secret-scan gate failed on every PR
with "missing gitleaks license". Download and run the pinned gitleaks OSS
binary (v8.30.1) directly with `gitleaks git`, preserving the full
commit-history secret scan (non-zero exit on any finding) without the
license dependency.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 3750cefd-d322-4f02-9184-c8ac3eba2fff
Copilot AI lite review requested due to automatic review settings August 26, 2026 17:08

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes the Validate learner branches GitHub Actions workflow so it can run successfully on PRs that touch course-build/**, by addressing two environment/config failures on fresh runners (git identity for git am) and removing the dependency on a paid Gitleaks license.

Changes:

  • Configure a git committer identity in verify-deltas before running the delta application step that shells out to git am.
  • Replace gitleaks/gitleaks-action@v2 with a pinned download/run of the OSS gitleaks binary to avoid requiring GITLEAKS_LICENSE.
Show a summary per file
File Description
.github/workflows/validate-branches.yml Unblocks the workflow by setting git identity for git am and running Gitleaks OSS directly instead of the licensed action.

Review details

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

  • Files reviewed: 1/1 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment thread .github/workflows/validate-branches.yml
GeekTrainer and others added 8 commits August 26, 2026 10:16
The learner-branch services default their SQLite DBs to /data/<svc>.db
(overridable via *_DB_PATH), where /data is a mounted volume under docker
compose. The build-and-test job runs `mvn test` / `dotnet test` / `pytest`
directly on the runner, which has no such volume, so the Spring services
(workforce/audit/auth) abort at context load with "path to
'/data/workforce.db': '/data' does not exist", failing every module.

Create a writable /data on the runner to mirror the runtime contract.
The fix stays at the CI layer: touching the app config instead would alter
the learner-branch trees that verify-deltas pins via manifest.expectedTreeSha.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 3750cefd-d322-4f02-9184-c8ac3eba2fff
The build-and-test job failed with "No module named pytest": the Python
step ran `python -m pytest` but only `pip install -e services/<svc>`, which
omits pytest (declared in the service's `dev` extra). It also ran pytest
whenever a tests/ dir existed, but early modules ship a tests/ dir with only
a README, so pytest would exit 5 (no tests collected).

Only run pytest when real test files (test_*.py / *_test.py) are present, and
in that case install the dev extra (pins pytest/pytest-asyncio) with a direct
pytest install as a fallback so `python -m pytest` is always available.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 3750cefd-d322-4f02-9184-c8ac3eba2fff
The QR e2e (present from start-of-module-06) failed with "element not
found": the asset detail page fetches assets-svc AND workforce-svc and
hides its body (including the QR card) if either call throws. Playwright's
webServer starts `npm run dev` (the whole stack) but only waits for the web
app on :4321, so the slower JVM workforce-svc was usually still booting when
the spec ran, and both retries lost the same race.

Pre-start the stack, wait for web + assets-svc + workforce-svc /health, then
run Playwright reusing the warm server (reuseExistingServer is true when CI
is unset), keeping --retries=2. Only the services the current specs need are
gated, so earlier modules whose specs never touch the backends are unaffected.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 3750cefd-d322-4f02-9184-c8ac3eba2fff
Temporary diagnostics on Playwright e2e failure: dump the web /assets links,
assets-svc responses, the rendered detail page's QR/error markers, and
Playwright's error-context, to pinpoint why the QR spec fails with a warm stack.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 3750cefd-d322-4f02-9184-c8ac3eba2fff
…context)

Curl the actual first-by-tag asset id, its /qr endpoint, and dump the full
Playwright error-context ARIA snapshot plus assets-svc stack log lines, all
set -e safe, to pinpoint why the QR heading is absent with a warm stack.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 3750cefd-d322-4f02-9184-c8ac3eba2fff
…heory)

The QR e2e failure was misdiagnosed as dev-server watcher flakiness. It is
actually a deterministic selector bug in the test itself (fixed separately in
the module-05 delta). Revert validate-branch.sh's e2e block to the original
CI=1 npm run test:e2e; the elaborate stack pre-start/health-gate and the
temporary diagnostics were built on the wrong theory and add no value (YAGNI).
The /data provisioning and pytest fixes are unaffected.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 3750cefd-d322-4f02-9184-c8ac3eba2fff
…ssets/new

The QR Playwright spec (shipped in the module-05 delta, present in
start-of-module-06 and -07) used `page.locator('a[href^="/assets/"]').first()`.
On the assets list page the "+ New asset" button (href="/assets/new") renders
before the asset table rows, so `.first()` opened the create form -- which has
no "QR code" heading -- and the test failed deterministically on every run.
This is why start-of-module-06/07 were the only build-and-test jobs failing.

Scope the selector to the asset table body (`tbody a[href^="/assets/"]`) so it
selects the first real asset detail link. Verified deterministically with
Playwright against the page's DOM structure (old selector -> /assets/new, new
selector -> first asset), and the asset detail page is already confirmed to
render the QR card.

Because module deltas are cumulative, this changes the reconstructed trees for
start-of-module-06 and -07, so the two expectedTreeSha values in manifest.json
are updated to match. `build-branches.mjs --check` passes for all modules.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 3750cefd-d322-4f02-9184-c8ac3eba2fff
Address CodeQL/Copilot review: the secret-scan job downloaded and executed a
release tarball with no integrity verification, an avoidable supply-chain risk
for the CI runner. Pin the upstream SHA256 (from gitleaks_8.30.1_checksums.txt)
and verify the download with `sha256sum -c` before extracting or running it.
The checksum was verified against the real release artifact.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 3750cefd-d322-4f02-9184-c8ac3eba2fff
@GeekTrainer
GeekTrainer merged commit 91bada3 into main Aug 26, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants