posit-dev / posit-dev/images-shared

Add `bakery create image --interactive` wizard with template assembly

Open
#701 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

cvp:3 docker tdp:0
Dominant language
Python
Stars
2
Forks
0
Avg merge
4d 13h
Merged PRs (30d)
22

Description

Problem

bakery create image scaffolds a commented-out stub Containerfile.jinja2 (posit_bakery/config/templating/templates/Containerfile.jinja2) — real macro imports are pre-written, but every section is just a comment telling a human what to fill in. Nothing about OS family, R/Python/Quarto versions, or system packages flows into it; a user has to already know bakery's macro vocabulary (apt.j2/dnf.j2/python.j2/r.j2/quarto.j2/goss.j2) to produce a working Containerfile.

This is the residual gap identified from analyzing michaelmayer2/container-generator: its UI walks a customer through exactly these choices and writes a working Dockerfile. This issue is bakery's answer, as an opt-in CLI wizard rather than a second tool to maintain.

Design

Flag: -i, --interactive on the existing bakery create image command, opt-in (tool remains non-interactive by default, consistent with create version/create matrix/create project, all used from CI). Any flag given explicitly on the command line is never re-prompted.

Prompt sequence:

  1. Image name (skipped if given positionally)
  2. OS family + version, sourced from SUPPORTED_OS (build_os.py), defaulting to bakery's existing DEFAULT_OS
  3. Languages to include (multi-select: R, Python, Quarto, or none)
  4. Per selected language: version(s) — space-separated, or latest (resolved via the same DependencyConstraint/"latest" machinery create matrix --dependency-constraint already uses)
  5. Extra system packages (optional free text → deps/packages.txt)
  6. Generate goss tests for these installs? [Y/n]
  7. If any language got multiple versions: create a matrix instead of one version? [Y/n]
  8. Version name (or matrix name-pattern)
  9. Confirmation gate: a summary of every file to be created/changed (reusing the existing dirdiff/render_markdown helpers create_version --diff-against already uses). Nothing is written until explicit confirmation — a Ctrl-C or "no" leaves zero side effects, since all writes happen in one place at the end.

Architecture (three new pieces, nothing existing modified):

  • posit_bakery/cli/interactive.py — prompt flow + confirmation gate; builds a WizardAnswers object, then calls the existing, unmodified BakeryConfig.create_image()/create_version()/create_matrix().
  • posit_bakery/config/templating/interactive_assembly.py — pure functions (assemble_containerfile, assemble_deps_file, assemble_goss_file), no I/O, no prompting. Loads and concatenates fragment files into the same section-header shape the current stub already has.
  • posit_bakery/config/templating/templates/interactive_fragments/ — small .jinja2 fragments, one per concern (apt_setup.jinja2, dnf_setup.jinja2, r_install.jinja2, python_install.jinja2, quarto_install.jinja2, goss/{r,python,quarto}.jinja2), each just the macro call a human would write by hand.

Chosen over curated per-combination presets (combinatorial — 2 package managers × 8 language combinations — and drifts from real macros over time, the exact problem with container-generator's own hardcoded duplicate of bakery's OS/version logic) and over Python-side string-built Jinja2 (fragile, hard to unit-test in isolation). Adding a language later means adding one fragment file, not touching assembly logic.

Error handling:

  • Version input validated via the existing RDependencyVersions/PythonDependencyVersions/QuartoDependencyVersions pydantic models, catching ValidationError for a re-prompt.
  • Network failure fetching available versions surfaces the same as everywhere else in bakery today (hard error) — no new silent-degradation path specific to this command.
  • Image name collision checked immediately after the name is entered, not after the full wizard.
  • Version/matrix render failures reuse create_version/create_matrix's existing cleanup (already removes a partially-created version directory on BakeryRenderError).

Testing: assembler as pure input→string tests; full wizard flow via typer's CliRunner with scripted stdin; explicit test that declining confirmation leaves the filesystem and bakery.yaml untouched; bad-version retry behavior.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the existing bakery create image, create version, and create matrix entry points, then read posit_bakery/cli/interactive.py and posit_bakery/config/templating/interactive_assembly.py alongside the named templating helpers. Check the pure assembler tests and Typer CliRunner flow, including invalid-version retries and declined confirmation. Done means the wizard creates the requested files without side effects before confirmation and reuses the existing image, version, and matrix creation paths.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
cli, tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.