Prepare 0.0.1 public release: PyPI + npm packaging, release workflow, sm new CLI - #49
Merged
Merged
Conversation
Captures the decisions for publishing all 14 simple-module-* packages to PyPI: lockstep versioning from 0.0.1, manual-dispatch GitHub Actions workflow with PyPI Trusted Publishing, sm new CLI generator, per-package READMEs as a first-class deliverable, and TestPyPI rehearsal before real publication.
Extends the v0.0.1 release plan to publish the three JS packages (@simple-module/ui, i18n, tsconfig) to npm alongside the 14 Python packages. Lockstep versioning across all 17. Generator consumes npm packages as deps instead of vendoring. Adds npm Trusted Publisher setup, npm matrix publish jobs, cross-registry error handling, and npm pack smoke tests. Renamed: pypi-release-design.md -> public-release-design.md.
…yword - npm packages publish under @simple-module-py/ scope (was @simple-module/). Scope name communicates "Python framework's JS companion packages" more clearly. - Every one of the 17 packages MUST declare "simple-module" as a keyword/tag so the whole family is discoverable via a single search on both PyPI and npm. - Add scripts/check_metadata.py to lint: enforces the keyword, real description, license, repository URL, and publishConfig on every package.
Renames 10 module packages from bare names (auth, users, products, ...) to simple-module-<name> so they can be published to PyPI without name collisions. Python import names are unaffected — only the PyPI distribution name changes. Inter-module dependency references and [tool.uv.sources] keys updated to match. Also adds [tool.hatch.build.targets.wheel] packages to each module so hatchling can still find the source directory after the distribution name no longer matches the package directory layout, and updates host/pyproject.toml's dependencies and workspace sources.
PEP 503 treats hyphens and underscores as equivalent in distribution names, but the canonical display form can differ. This repo's Python import names are all underscored (simple_module_core, etc.), so the PyPI distribution names are aligned to match — simple-module-core becomes simple_module_core, and so on for all 14 packages. npm scope (@simple-module-py/*) is unchanged. CLI shell names (sm, simple-module) are unchanged. The 'simple-module' PyPI keyword is unchanged (it's a search tag).
Scaffolds a fresh app pre-wired with users, dashboard, and permissions. Generates a random SM_SECRET_KEY, sets the DB URL based on --db choice, pins simple_module_* deps to 0.0.1, and lists @simple-module-py/* npm deps. Respects --yes for non-interactive invocation and --no-install to skip uv/npm/alembic.
- README: `uvx simple-module` would fail because no PyPI package is named `simple-module` — the CLI ships inside `simple_module_hosting`. Use `uvx --from simple_module_hosting simple-module new …`. - release.yml smoke step: use underscored dist name for consistency with the rest of the workflow and the wheel metadata.
Resolves three conflicts with main's db-backed-settings feature (PR #47) and datasets view-routing fix (PR #48): - modules/settings/pyproject.toml: kept both new blocks added on either side — [project.scripts] sm-settings entry (from main) AND [project.urls] metadata (from this branch). - modules/settings/settings/pages/Modules.tsx: accepted main's deletion (replaced by ModulesEdit.tsx under the new admin UI). Our only edit here was the mechanical @simple-module → @simple-module-py scope rename, which no longer applies to a deleted file. - modules/settings/settings/pages/ModulesEdit.tsx (new in main): updated its @simple-module/* imports to @simple-module-py/* to stay consistent with the npm scope rename on this branch. Post-merge validators green: - scripts/check_metadata.py: All package metadata OK. - scripts/check_readmes.py: All READMEs OK. - scripts/bump_version.py 0.0.1 --check: All 17 packages at 0.0.1.
- framework/hosting/tests/test_cli_new.py: apply ruff format + organize
imports + replace `[... for ... in ...][0]` with `next(...)` (RUF015).
- packages/{ui,i18n,tsconfig}/package.json: re-apply biome's preferred
multiline formatting for `files` and `publishConfig` arrays/objects.
- pyproject.toml: add `scripts` to [tool.ty.environment].extra-paths so
ty can resolve bare imports like `from new_module import …` used by
the pre-existing `scripts/tests/*` suite. (`scripts/__init__.py` was
added in Phase 2 which made ty start treating scripts/ as a package;
extra-paths is the idiomatic fix, matching every other module entry.)
The module scaffolder used to emit \`contracts/service.py\` defining an \`IOrderService(Protocol)\`; it now emits only \`contracts/schemas.py\` with DTOs, keeping the concrete service implementation at the package root. These three test assertions predated that change and were failing CI. - test_scaffold.py::test_scaffold_creates_all_files — drop \`contracts/service.py\` from expected files. - test_generated.py::test_contracts_protocol_defined — remove; the Protocol file is no longer generated. - test_generated.py::test_contracts_init_exports_public_api — drop the \`"IOrderService"\` assertion; only DTO names are re-exported now.
…ugh and troubleshooting Keeps the existing reference material but fronts it with a TL;DR, a step-by-step first-publish walkthrough, a local pre-flight script, a troubleshooting section, and a table of what's published where. Aimed at someone who's never dispatched a GitHub Actions release workflow before, while staying useful as a reference once setup is done.
6 tasks
antosubash
added a commit
that referenced
this pull request
Apr 22, 2026
The README and .env.example tell users to set the first-boot admin credentials in .env, but the documented path silently did nothing: UsersSettings deliberately has no `env_file` (runtime fields come from the DB), and the `os.environ.get(...)` fallback doesn't see `.env`-only vars. Result: fresh `.env` + `make dev` created no admin, and logins failed with no clue why. - Add `simple_module_core.dotenv.parse_dotenv()` and swap the nearly identical parser already inlined in `simple_module_core.__main__` over to it. - In `users.bootstrap`, read the four `SM_USERS_BOOTSTRAP_*` keys from `.env` as a final fallback after settings → os.environ. Centralize the setting-attr → env-var mapping in `BOOTSTRAP_ENV_KEYS` so the test fixture and the resolver stay in sync. - Add commented-out bootstrap hints to `.env.example` and the `sm new`-scaffolded template so the knob is discoverable again (PR #49 trimmed it out). - Isolate users/tests/test_bootstrap.py from the developer's real `.env` via an autouse fixture.
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.
Summary
Makes
simple_module_pythonreleasable to PyPI (14 packages) and npm (3 packages) at version0.0.1, with a manual-dispatch GitHub Actions workflow, asimple-module newCLI generator for greenfield apps, and lockstep version bumping.Executes docs/superpowers/plans/2026-04-21-public-release.md end-to-end across 9 phases.
What changed
Packaging (Phases 0–5)
LICENSE(MIT) +CHANGELOG.mdseeded with 0.0.1simple_module_*(underscored) with full metadata: keywords, classifiers, URLs, hatchling build targets@simple-module-py/*scope withpublishConfig.access=publicscripts/check_metadata.py+scripts/check_readmes.pywired intomake lintTooling (Phases 6–7)
scripts/bump_version.py— lockstep bumper for all 17 packages (usestomlkitto preserve formatting), with--checkand--dry-runsimple-module new my-app/sm new my-app— greenfield app generator wrapping the existing host scaffolder, pre-wiresusers + dashboard + permissions, generates aSM_SECRET_KEY, picks a DB URL, pins framework versions inpyproject.toml+package.json. Invokable viauvx --from simple_module_hosting simple-module new …framework/hosting/tests/test_cli_new.py— 5 new tests cover the CLI end-to-endRelease infra (Phase 8)
.github/workflows/release.yml— manual-dispatch, OIDC Trusted Publishing (no tokens), matrix fan-out over 14 PyPI + 3 npm packages, with TestPyPI rehearsal path and a post-publish smoke testdocs/release.md— operator playbook: Trusted Publisher setup, GitHub Environments, partial-publish recoveryREADME.md— new "Use in a new project" sectionVerification (Phase 9)
simple-module new→uv build --all-packagesemits 14 wheels + 14 sdists →npm packemits 3 tarballsscripts/bump_version.py 0.0.1 --checkreports "All 17 packages at 0.0.1."Reviewer notes
simple_module_core), npm stays hyphenated (@simple-module-py/ui), CLI commands stay hyphenated (simple-module). PyPI normalizes both forms at resolution, but metadata, workflow matrices, and docs all use the underscored form for consistency with whatuv buildemits.main. If branch protection blocksgithub-actions[bot], setRELEASE_PUSH_TOKEN(fine-grained PAT, contents:write) — the workflow falls back to it.scripts/tests/test_generated.py+test_scaffold.pyexpect the module scaffolder to emitcontracts/service.pybut it now emitscontracts/schemas.py. Predates this PR; flagged as a separate task.@simple-module-pyorg owner, and repo URL (all assumedantosubash/simple_module_pythonthroughout).Test plan