gitea-saas-core#38: assemble one create_app() + a real entrypoint #43
No reviewers
Labels
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: pbwraith/gitea-saas-core#43
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "issue-38"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Assembly only (issue #38): one
create_app()that composes the 15 modules onmaininto a single runnable Flask app, plus the real entrypoints. No behaviour changes to billing, factory, dashboard or review.Files this issue owns, all new or touched here:
gitea_saas/app.py(new) —create_app(config=None) -> Flask:config.pyloader (no new env vars;SAAS_API_KEY/SAAS_PORT/SAAS_DB_PATHare the only knobs),db.py(throughBillingCore, which owns the connection + idempotent schema bootstrap) and constructsBillingCore,server.py(server.create_app),register_factory_routes(factory),mount_dashboard(dashboard),SAAS_API_KEYunset the app still starts but every authed route returns503 SERVICE_UNAVAILABLE— not 500, not 200. No second auth path: key validation stays ingitea_saas.auth(key_is_valid), and the front-ends' own canonical-401 guards apply unchanged once a key IS configured (covered by tests below). The 503 gate is installed only when no key is configured, only at the assembler layer, ahead of the front-ends' guards; liveness routes inauth.PUBLIC_PATHS(/health,/healthz,/api/factory/health) stay public.SAAS_DB_PATHis unset the assembler falls back to an ephemeral file in a fresh temp dir so billing/factory/dashboard share one coherent dataset (config.py's in-memory default can't be shared by the factory/dashboard, which open their own connections).wsgi.py(new, repo root) —application = create_app()for gunicorn.pyproject.toml—[project.scripts] gitea-saas = "gitea_saas.app:main"plus runtimedependencies = ["flask>=3.0"](a real entrypoint implies declaring the runtime dep; matchesrequirements.txt).tests/test_app.py(new) — acceptance 1 + 2 + configured-key/401 regression + entrypoint wiring.gitea_saas/__main__.py(new) — one extra file beyond the four listed: acceptance 3 requirespython -m gitea_saasto serve/health, and the issue's Outcome section lists__main__.pyamong the four missing pieces. It delegates togitea_saas.app:main.No symbols needed exporting:
server.create_app,register_factory_routesandmount_dashboardwere already importable;server.py,intake_factory.pyanddashboard.pyare untouched beyond importing.Note on 503 vs the #24 consolidation: standalone front-ends return canonical 401 for an unset key (pre-#24 they returned 503; #24 consolidated to 401). Acceptance 2 of this issue explicitly requires the ASSEMBLED app to report 503 for the unconfigured deployment — implemented as an unconfigured-state gate at the assembly layer only, so existing per-front-end 401 behaviour and tests are untouched.
Test evidence
python3 -m pytest(full suite): 244 passed, 1 skipped (34s).git diff --check: clean.env -u SAAS_API_KEY -u SAAS_DB_PATH SAAS_PORT=8137 python3 -m gitea_saasstarts with zero config; thenGET /health→ 200GET /healthz→ 200GET /api/factory/health→ 200GET /api/clients/1(authed route, no key) → 503{"error":{"code":"SERVICE_UNAVAILABLE", ...}}Closes #38
[worker-done] gitea-saas-core#38 assembled: one create_app() + real entrypoints.
Commit:
0f9d2a9(branch issue-38, PR #43).Test evidence:
python3 -m pytest).python3 -m gitea_saaswith zero SAAS env started on 127.0.0.1:8137; /health 200, /healthz 200, /api/factory/health 200, authed GET /api/clients/1 -> 503 SERVICE_UNAVAILABLE (not 500/200); server stopped after.Ready for manual review (PR #43, branch only, Closes #38).
Held —
mainis red, and it is not this PR's faultGated against the real merge result. The comparison that matters:
origin/main@71cc263(no PR)main+ this PRThe same 10 failures, and this PR adds 9 passing tests and zero new
failures. Every failure is in
tests/test_review_workspace.py/tests/test_reviewer.py— files this PR does not touch.So this is not a bounce and nothing is being asked of you. The work is good; it
is queued behind a pre-existing defect filed as #48: on Windows the shell
eats the
^ingit rev-parse --verify <sha>^{commit}, soReviewWorkspacecannot build a synthetic merge on the review box at all.
I will not merge onto a red
main— with the baseline broken there is no way totell a genuine regression from the existing noise, which is exactly how
botmanager shipped a broken
masterlast week. Once #48 is green I willre-gate and merge.
Merged — verified against green
mainorigin/main(after !49)main+ this PR0 conflicts. This PR was held, never bounced — it was queued behind the Windows caret defect (#48), which !49 fixed. The service can finally be started by someone who does not know its internals —
create_app(),wsgi.pyand a console entrypoint. 15 working modules had no ignition.