Repository navigation
feat(server): deploy the API to Serverpod Cloud (re-land #115 on main) - #117
Conversation
Copy serverpod_auth_idp_rate_limited_request_attempt rows through a transaction-scoped temp table while the generator recreates the table to rename nonce to key. Document the upgrade, migration and rollback steps. Refs #110
…f the image Serverpod 4 dependencies use Dart build hooks, so the image now uses dart build cli and ships the emitted bundle. The new .dockerignore keeps .env files and config/passwords.yaml out of the build context, which previously baked local secrets into the runtime image. Refs #110
Add a docker job, triggered by server, domain, lockfile and .dockerignore changes, that builds the image with planted secret files and asserts the bundle exists and passwords.yaml is excluded. Refs #110
…itory The Pages build command cloned Flutter 3.41.4 from the dashboard, so every branch on Serverpod 4 (Dart ^3.12.2) failed version solving. The build now runs scripts/cloudflare-pages-build.sh, which installs the branch's pinned Flutter. A test keeps its version in sync with CI. Refs #110
…-upgrade Brings in the hire and hire_payment tables from #93. The generated protocol files are regenerated with serverpod_cli 4.0.4 instead of resolved by hand. The forced upgrade-4-0 migration is removed here because its snapshot predates migration 20261006210458593; it is recreated in the next commit.
… the hire tables The forced upgrade-4-0 migration was created before #93 added migration 20261006210458593 with the hire and hire_payment tables, so its snapshot did not know about them. Recreate it with serverpod_cli 4.0.4 as 20261007214534790-upgrade-4-0 so it now sorts after 20261006210458593 and its definition includes hire, hire_payment, chain_submission and the Serverpod 4 module tables. The migration does not create, drop or alter the hire tables. The hand edit is re-applied: rows of serverpod_auth_idp_rate_limited_request_attempt are copied to a temporary table before Serverpod drops and recreates it, with nonce mapped to key, and restored afterwards, so rate-limit history still survives the upgrade. Refs #110
scripts/tests/*.test.sh were never run in CI, so main broke the env inventory (PULS3_HIRE_JOB_DURATION_SECONDS) without a red check. The new scripts job runs them all and gates the merge. Refs #110
…nd CORS gate (#115) * feat(server): report the deployed commit in the health version health.check returns the package version, plus +<sha> when PULS3_GIT_SHA is set, so a deployed server names the commit it runs. A unit test keeps the version constant equal to pubspec.yaml, and an invalid value stops the server at startup. * feat(server): restrict browser callers to allowed origins Serverpod 3.4.13 sends a static wildcard Access-Control-Allow-Origin and answers preflights in its core middleware, before added middleware runs. An origin gate on the API server now rejects requests whose Origin is not loopback or listed in PULS3_ALLOWED_ORIGINS with 403 before any endpoint runs, and echoes allowed origins with Vary: Origin. Requests without an Origin header (curl, probes) pass through. * chore(server): add Serverpod Cloud project config scloud.yaml uses the format serverpod_cloud_cli 1.0.0 writes, with a placeholder project id that scloud project link replaces, and no pre-deploy scripts: the Flutter web app ships to Cloudflare Pages and the generated code is committed. The root .scloudignore keeps passwords, run-mode configs, tests, Docker files and web/app out of the upload; paths are workspace-relative because scloud reads it from the workspace root. * docs: add Serverpod Cloud deploy and redeploy steps Document the first deploy (scloud install, login, project create and link, variables, platform-managed passwords), the mapping of each secret in docs/infra/secrets.md (#30) to Serverpod Cloud, the redeploy flow with the health check, the PULS3_GIT_SHA version and the PULS3_ALLOWED_ORIGINS allow-list. The tracker stays off in this deployment. * fix(server): allow loopback origins only in development Loopback origins (localhost, 127.0.0.1, [::1]) are now allowed only in the development run mode; production, staging and test allow just the origins listed in PULS3_ALLOWED_ORIGINS. A request with several Origin headers is rejected. server.dart builds the gate through originGateFromEnvironment, which is tested end to end over HTTP, and new cases cover default-port and duplicate normalization, Vary merging, an existing Access-Control-Allow-Origin and lookalike loopback hosts. * feat(server): set PULS3_GIT_SHA in a Serverpod Cloud pre-deploy script scloud 1.0.0 runs scripts.pre_deploy on the deploying machine, in the server directory, through cmd /c on Windows and bash -c elsewhere, before it zips the project, and stops the deploy on a non-zero exit. The new tool/set_deploy_sha.dart sets PULS3_GIT_SHA to git rev-parse --short HEAD (suffixed -dirty when tracked files changed) with scloud variable set. scloud.yaml now runs it and explains the project id placeholder. * docs(server): make the Serverpod Cloud first deploy one linear path First deploy is now seven ordered steps without jumps: a pinned CLI install (1.0.1 on Dart 3.12.2+, or 1.0.0 with serverpod_cloud_shared pinned on older Dart), login, project create with an explicit plan, link, variables, deploy with the PULS3_GIT_SHA pre-deploy script, and verification including CORS checks (200 for the Pages origin, 403 for another). Adds a failure section (build log, logs, deployment status, fix forward or redeploy a good commit) that marks the Cloud behaviour the CLI cannot confirm, and documents that loopback origins are allowed in development only. * chore(server): recommend --from-file for Serverpod Cloud passwords * docs(server): check that the deployed API rejects localhost origins Loopback origins are allowed only in the development run mode, and Serverpod Cloud's run mode is not verified yet. A localhost-origin call that returns 200 after deploy reveals a non-production run mode. * chore(server): link Serverpod Cloud project puls3-hub-on-stellar Refs #31 * docs(server): record the Serverpod Cloud API URL and send a body in health checks The Cloud load balancer answers 411 to a POST without Content-Length, so the verify commands now send an empty JSON body. Refs #31 * feat(flutter): point the Pages build at the deployed API through PULS3_API_URL When the Pages project sets PULS3_API_URL, the build passes it as a dart-define, so the web app calls the Serverpod Cloud server. Refs #31 * docs(env): list PULS3_ALLOWED_ORIGINS and PULS3_GIT_SHA in .env.example Refs #31
…-upgrade # Conflicts: # .env.example # scripts/cloudflare-pages-build.sh # scripts/tests/cloudflare-pages-build.test.sh
Deploying puls3 with
|
| Latest commit: |
80ea9d0
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://299339e0.puls3-4lw.pages.dev |
| Branch Preview URL: | https://chore-110-serverpod-4-upgrad.puls3-4lw.pages.dev |
|
@moises-cisneros @fercodes @Pericena @XxHugheadxX this needs a quick review and approval, with priority: it is P0 and blocks the Serverpod Cloud redeploy (#31). It is the same content as #115. Moises already tested it there, but it was merged into the parent branch instead of Moises, your non-blocking notes from #114 and #115 will go into a follow-up, so they don't hold this up. Once it merges I'll wipe the Cloud DB and redeploy from |
XxHugheadxX
left a comment
There was a problem hiding this comment.
Reviewed and verified locally. Approving.
Re-land is exact
git diff fc8b9e6 pr117is empty, so the tree equals #115.- The merge base is the current tip of
main, and the diff againstmainis the 17 files of #115 (+1011/-4). scripts/tests/cloudflare-pages-build.test.sh: 7 passed, 0 failed.scripts/tests/env-inventory.test.sh: 68 passed, 0 failed.
CORS gate checked against Serverpod 4.0.4 source
- In 4.0.4,
Server.injectInstill registers the core_headersmiddleware around user middleware, and_headersanswersOPTIONSbeforeoriginGateruns. The documented preflight behavior still holds. - The native
SERVERPOD_ALLOWED_ORIGINSin 4.0.4 only guards the WebSocket handshake and credentialed CORS whenauthCookieis set. We don't useauthCookie, so the custom gate is still the only thing rejecting cross-origin POSTs.
Non-blocking, for the follow-up list
puls3_server/README.md("Health version and allowed origins") and theoriginGatedocstring still say "Serverpod 3.4.13". The behavior is the same in 4.0.4; only the version number in the text is stale.- The Deploy table in the root
README.mdstill showshttps://<project-id>.api.serverpod.space/("set after the first deploy"). The real URL,https://puls3-hub-on-stellar.api.serverpod.space/, is already in the server README. Needed for the "Both URLs are in the README" criterion of #31. - Minor: the gate's 403 response gets
Access-Control-Allow-Origin: *, because core_headersfills absent headers with??=. Harmless, since the endpoint never runs.
I couldn't run dart analyze / dart test locally, so I'm relying on the CI checks being green before merge. After merge: wipe the DB, redeploy from main, and run the three curl checks from step 7 (200 / 403 / 403).
Refs #31
Summary
This PR re-lands #115 on
main. #115 was merged intochore/110-serverpod-4-upgradeafter #114 had already merged, because its base was never retargeted. Its code (Serverpod Cloud deploy, CORS gate, health version) therefore never reachedmain.The branch is the same one:
origin/mainis merged in, and the conflicts are resolved by keeping the branch side, whose tree equalsfc8b9e6. The squash of #114 left identical content on both sides, so nothing new is introduced. The diff againstmainis exactly the 17 files of #115 (+1011/-4).The content is unchanged from #115, which @moises-cisneros already tested: analysis is clean, the unit tests pass, and the live API returns the health version and the 200/403 CORS responses.
What lands:
/health/checkreports1.0.0+<sha>.PULS3_GIT_SHAis set by thescloudpre-deploy script (tool/set_deploy_sha.dart).PULS3_ALLOWED_ORIGINSsets the allowed origins, and loopback origins are allowed only in development.scloud.yamlis linked topuls3-hub-on-stellar, and.scloudignoreexcludes.env,passwords.yamland the tests.puls3_server/README.md.scripts/cloudflare-pages-build.shpassesPULS3_API_URLas a dart-define..env.example:PULS3_ALLOWED_ORIGINSandPULS3_GIT_SHA.Acceptance criteria
Unchanged from #115:
healthreturns the deployed version.Verification evidence
Notes for reviewers
main. The live DB carries the pre-rebaseupgrade-4-0migration name. It holds no real data, and the team agreed to the wipe.ENTRYPOINTalpine:latest-dirtyPULS3_GIT_SHAset before the uploadOPTIONSheaderdelete_branch_on_mergeis now enabled on the repo. When a parent PR merges, GitHub deletes its branch and retargets stacked PRs tomain, which prevents this from happening again.