feat(cli): ship Docker assets with every smpy new scaffold - #252
Merged
Conversation
Every new app now gets a working container story by default instead of only when background_tasks is selected: - docker/host.Dockerfile: uv + Node builder that runs gen-pages before the Vite build (the old optional template skipped it, so the frontend stage could not build any app with module pages), slim non-root runtime, /health healthcheck, `alembic upgrade heads` on start. - docker-compose.yml matched to the --db choice: sqlite scaffolds run the app container alone with the DB on a named volume, postgres scaffolds get a postgres service. Migration histories are dialect-frozen at autogenerate time (sa.false() renders as DEFAULT 0 under SQLite, which Postgres rejects), so containers must run the same dialect the migrations were generated against. - background_tasks adds redis/worker/beat services that reuse the app image with a celery command; the separate worker.Dockerfile is gone. The app service also gets the compose-network broker URLs because BackgroundTasksSettings refuses a localhost broker in production. - smpy new generates real SM_USERS_*_TOKEN_SECRET values into .env.example (like SM_SECRET_KEY) so UsersSettings passes its production-mode boot validation inside containers. - .dockerignore + make docker-up / docker-build / docker-down targets. The BackgroundTasksRecipe slims down to run_worker.py + broker env keys + Make targets; compose/Dockerfile emission moved to the always-run docker_assets step, which knows the whole module selection. Verified end-to-end: built a default scaffold's image and booted the stack — app container healthy, /health 200, landing page 200. Claude-Session: https://claude.ai/code/session_016YtWRT8AVeG84jf7uNMv2s
antosubash
marked this pull request as ready for review
August 7, 2026 21:00
antosubash
added a commit
that referenced
this pull request
Aug 9, 2026
) * docs: sync docs with recent changes (branding white-label, SM022/SM023, Docker scaffold) The docs had drifted behind several merged features: - modules/branding: rewritten. The page still described the pre-#237 module (name, logo, favicon, colour). Adds the dark-background logo variant, design pack, announcement banner, configurable footer + its limits and href allow-list, presets, the anonymous asset routes and their cache policy, and the magic-number upload check. Corrects the allowed-types list, which still advertised image/svg+xml — SVG is excluded on purpose (XML that can carry <script>, i.e. stored XSS from our own origin). - reference/diagnostic-codes: add the missing SM022/SM023 rows. Every other code in the framework was documented; these two shipped with #238. - framework/discovery: document i18n_audience and requires_framework in the ModuleMeta section, cross-linked to the i18n page. - reference/deployment: the Build section told operators to hand-roll a Dockerfile that every scaffold has shipped since #252 — and the example used a Node-only frontend stage, which cannot work, since gen-pages reads the installed Python modules. Replaced with the shipped assets plus why the single builder stage is load-bearing. - alembic upgrade head -> heads across guide/reference. Every real command (Makefile, smpy new, the container CMD) uses the plural; the singular errors once a second module ships a branch label. - Module count eleven -> twelve; branding was missing from the home page list, and its index row predated the white-label work. Verified: vitepress build clean, and the four cross-page anchors checked against the generated HTML (ignoreDeadLinks is on, so the build itself does not catch them). Claude-Session: https://claude.ai/code/session_013W1MJ3T4FJEBcx1Xs9Tea2 * docs: fix accuracy issues found in review - branding: the magic-number check was overstated. validate_image matches the head against *any* allowed signature, not the one the declared Content-Type implies, so a genuine PNG sent as image/jpeg passes and is stored as image/jpeg. Reworded to the property that actually holds (non-images are kept out) rather than type/content agreement. - branding: the file_storage download permission is `file_storage.download`, not `file-storage.download`. Copied the hyphen from the stale comment at branding/constants.py:76; the constant is FileStoragePermissions.DOWNLOAD. - framework/overview: module count said "ten first-party modules" — missed in the eleven -> twelve sweep, so two pages one click apart disagreed. - module-authoring: one more `alembic upgrade head` -> `heads`, in the publish-a-module flow whose very next subsection tells the author to add branch_labels — i.e. exactly the case the plural exists for. - deployment: the new "run make docker-up" Build section sat three lines under a checklist item requiring Postgres, while the default SQLite compose pins SM_ENVIRONMENT=production *and* a SQLite URL. Added a warning that the SQLite stack is local/demo only, and why it isn't a one-env-var swap (migration histories are dialect-frozen). Also fixes the scaffold README template, which shipped `upgrade head` into every generated project while that project's own Makefile and Dockerfile use `heads`. test_cli_new_scaffold_layout already asserts the singular form is gone from the Makefile, so the README was simply missed. Verified: 216 CLI tests pass, vitepress build clean. Claude-Session: https://claude.ai/code/session_013W1MJ3T4FJEBcx1Xs9Tea2
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.
Every
smpy newapp now gets a working container story by default — previously Docker files only appeared whenbackground_taskswas selected, and even those couldn't build a real app.What's included in every scaffold
docker/host.Dockerfile— uv + Node builder stage that runsgen-pagesbefore the Vite build (the old optional template skipped it, so the frontend stage failed on the missingmodules.generated.{ts,css}), slim non-root runtime,/healthhealthcheck,alembic upgrade headson container start.docker-compose.ymlmatched to the--dbchoice — sqlite scaffolds run the app container alone with the DB on a named volume;--db postgresscaffolds get apostgresservice. Migration histories are dialect-frozen at autogenerate time (sa.false()renders asDEFAULT 0under SQLite, which Postgres rejects), so containers must run the dialect the migrations were generated against — discovered by actually booting a scaffold against Postgres.background_tasksaddsredis/worker/beatservices reusing the app image with a celery command (separateworker.Dockerfiledeleted). The app service also gets the compose-network broker URLs, sinceBackgroundTasksSettingsrefuses a localhost broker in production.SM_USERS_*_TOKEN_SECRETs in.env.example(likeSM_SECRET_KEY) soUsersSettingspasses production boot validation in containers..dockerignoreandmake docker-up/docker-build/docker-downtargets.The
BackgroundTasksRecipeslims down torun_worker.py+ broker env keys + Make targets; compose/Dockerfile emission moved to an always-rundocker_assets.pystep that knows the whole module selection.Verification
make lintgreen (12 new tests intest_cli_docker_assets.py)./health200, landing page 200.docker compose configvalidates all four compose shapes (sqlite/postgres × plain/tasks).Design doc:
docs/superpowers/specs/2026-08-06-default-docker-scaffold-design.mdhttps://claude.ai/code/session_016YtWRT8AVeG84jf7uNMv2s