Skip to content

Latest commit

 

History

History
58 lines (49 loc) · 3.75 KB

README.md

File metadata and controls

58 lines (49 loc) · 3.75 KB

cfpb-backend

Python sidecar hosting the CFEngine toolchain. Electron spawns it once per action: input on stdin, result on stdout, diagnostics on stderr with a non-zero exit.

Subcommand stdin stdout exit codes
format (also the default with no subcommand) policy formatted policy 1 syntax error, 2 other
init {"directory", "name", "description", "masterfiles", "git", "content"?} {"path", "masterfiles"} 1 failed (cleaned up), 2 invalid input (nothing touched)
masterfiles {"version"} (3.27.1 or master) the masterfiles build entry cfbs init writes 1 failed, 2 invalid input
compile the project's .policy-builder/project.json {"files": {<path>: <contents>}, "source_map": {<path>: {<block or group id>: [[first, last], …]}}} 1 can't compile, 2 compiler fault
deploy {"path", "host": "user@host[:port]", "key"?} {"deployed", "log"}: cf-remote deploy's outcome and output 2 invalid input
testenv doctor / images nothing one JSON object: Docker's state / the base images and which are pulled 1 can't answer
testenv package {edition, version, platform, arch, hub} {url, sha256, version, filename} from CFEngine's release data 1 no such package
testenv pull {image} streamed: one JSON event per line (progress, log, then done or error) 1 failed

init runs cfbs init in-process (non-interactive, --git=no) in directory, which must be absent or empty, with an existing parent. masterfiles is an exact version (3.27.1), master, or no; cfbs 5.7.0 mishandles branch names like 3.24.x, so they are refused. It then writes name/description into cfbs.json via cfbs.pretty, and with git makes one commit (falling back to cfbs's cfbs <cfbs@hostname> identity if git has none). The result's masterfiles is the build entry cfbs wrote, or null. All cfbs output goes to stderr; the last stderr line is a one-line summary for the UI. Any failure removes what init created. With content (the builder's modules and its project data, optionally testEnvironments), it also writes the modules into cfbs.json, the data into .policy-builder/project.json (and test-environments.json) and the compiled files, before the commit. With "type": "module" there's no cfbs init and no masterfiles: cfbs.json is a module project ("type": "module", named after the module) whose provides holds the project as one module.

masterfiles runs cfbs init in a throwaway folder and returns the masterfiles entry it wrote: how a module project gets masterfiles when it becomes a policy set.

compile (cfpb_compiler.py) turns the builder's canvases into policy, one formatted .cf per policy file plus the template files its blocks render (in ./templates/, which ships as one directory module), following the contract in blocks/README.md. It reads the descriptors from the repo's blocks/, which the PyInstaller bundle carries as data.

Managed with uv, which also fetches the interpreter pinned in .python-version.

uv sync                                                    # .venv + deps
uv run pytest                                              # CFPB_NETWORK_TESTS=1 adds masterfiles downloads
uv run black .                                             # no linter here
uv run pyinstaller --clean --noconfirm cfpb-backend.spec   # → dist/cfpb-backend/

Also available from the repo root as npm run backend:*, which is what CI and the packaging scripts use.

deploy runs cf-remote deploy in-process in the built project, which ships its out/masterfiles.tgz; a chosen key goes in as CF_REMOTE_SSH_KEY. Bundling cf-remote brings ~27 MB of libcloud drivers along.