feat: CLI-first container image + robust technique count; fixes red wheel job (roadmap #14) - #96
Merged
Merged
Conversation
) The pip-installable CLI already exists (console_scripts + [web] optional extra); this adds the container half and a robust build gate. - Dockerfile: a CLI-first image (python:3.12-slim, non-root, ENTRYPOINT replicant). Web UI deliberately excluded so a CLI evaluator does not build a React bundle to see one FortiGate line. .dockerignore keeps everything but the package out of the build context, including the in-tree backup git repos and the checked-in webui_dist. - CI 'container' job builds the image and drives the CLI inside it (the positive control the author cannot run locally: no Docker daemon on the dev Mac). A broken Dockerfile fails there rather than being merged on inspection. - README documents 'pip install replicant' / '[web]' and the container trial, noting the PyPI publish itself is a release step. Also fixes a regression this session introduced: the transferability-notes footer (item #5) made 'replicant list | grep -c REP-0' return 28, turning the wheel job red on main. Both the wheel and container checks now count DISTINCT technique ids (grep -oE 'REP-[0-9]{3}' | sort -u), which is what '24 techniques' means and is immune to the footer.
…rrect docs From /code-review on PR #96, verified before fixing: 1. (main) The README's headline 'docker run -v ... run' example failed on native Linux: the non-root image (uid 10001) cannot write a host-owned bind mount. Now documents --user $(id -u):$(id -g), and a new CI step exercises exactly that bind-mounted run on the Linux runner (previously untested). 2/4. The Dockerfile/README claimed 'replicant web' serves its build-it page (it errors 'web dependencies missing', no fastapi) and called webui_dist 'checked-in' (it is gitignored). Both corrected. 3. The 'no web assets' CI guard could never fail: webui_dist is gitignored and the job never built it, so the image lacked it regardless of .dockerignore. The container job now builds the frontend first (like the wheel job), so the guard actually tests the .dockerignore exclusion; deleting that line now fails it. Finding 5 (the distinct-count one-liner duplicated across wheel and container jobs) left as-is: both correct, a shared composite action would over-engineer a one-liner.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Roadmap 2026-09 item 14, unblocked by the rank-2 OSS/CLI-first decision. The pip-installable CLI already exists (console_scripts +
[web]optional extra); this adds the container half and hardens the build gate.What's new
Dockerfile— a CLI-first image (python:3.12-slim, non-rootrunner,ENTRYPOINT ["replicant"]). The web UI is deliberately not installed, so a CLI-first evaluator does not build a React bundle to see one FortiGate line.replicant webin the image serves its build-it page..dockerignore— keeps everything but the package and its metadata out of the build context, including the in-tree backup git repos (replicant-backup-*/,replicant-rewrite/) and the checked-inwebui_dist.containerjob — builds the image and drives the CLI inside it (--version, all 24 techniques, a fullrun ... --to-file --no-sendthat produces a FortiGate CEF line, and an assertion the UI assets are absent). This is the positive control I cannot run locally (no Docker daemon on the dev Mac); a broken Dockerfile fails here.pip install replicant/[web]and the container trial, noting the PyPI publish itself is a release step.Also: fixes a red wheel job on main
The transferability-notes footer from item #5 made
replicant list | grep -c 'REP-0'return 28, which turned thewheeljob red onmain(confirmed on the latest main run — I missed it relying ongh pr checks --watchexit codes). Both the wheel and container checks now count distinct technique ids (grep -oE 'REP-[0-9]{3}' | sort -u), which is what "24 techniques" means and is immune to the footer. This PR restores the gate.No Python changed; suite unaffected. Decision record:
docs/roadmap-2026-09.md.