Skip to content

feat(netlify): add Netlify cloud substrate (--on netlify)#6

Merged
snowmead merged 1 commit into
feat/flyio-substratefrom
feat/netlify-substrate
Jun 17, 2026
Merged

feat(netlify): add Netlify cloud substrate (--on netlify)#6
snowmead merged 1 commit into
feat/flyio-substratefrom
feat/netlify-substrate

Conversation

@snowmead

Copy link
Copy Markdown
Owner

Summary

Adds Netlify as a --on netlify cloud substrate — the second hosting target in the suite (after Fly; stacked on #5, base is feat/flyio-substrate). v0 is static upload: a service's source files (under [services.X.netlify].root or the repo root) are deployed via Netlify's file-digest API.

How it works

  • Stripe Projects provisions netlify/project (free) and returns a Stripe-managed token + site id (pinned by mise run discover netlify/project — the token surfaces on a refreshed env read; the suffix is NETLIFY_AUTH_TOKEN).
  • The substrate clones the pinned ref and runs the file-digest deploy: SHA1 per file → POST /sites/{id}/deploys with the digest map → PUT only the files Netlify reports as required → poll the deploy to ready → health-gate on the deploy's ssl_url.
  • The token is ephemeral, so observe/destroy key off the Stripe resource registration; the Netlify API is touched only at deploy time.
  • netlify_api.rs is hand-written reqwest/serde (Swagger-2.0 source, ~5 endpoints).
  • One-row registration across every seam (substrates.rs row + builder + global codes-uniqueness test, workspace member, binary dep, --on help, integrations KNOWN).

Validation

  • ✅ 235 hermetic workspace tests; clippy / rustfmt / taplo clean
  • Live smoke green end-to-end (mise run smoke-netlify): provision → token → clone → SHA1 upload → poll ready → HTTPS health at *.netlify.app → verified teardown

Notes

  • Free-tier — no --confirm-paid and no billing-card setup (unlike Fly).
  • The first smoke surfaced one real detail: Stripe prefixes the provider's native var, so the output suffix is NETLIFY_AUTH_TOKEN (not AUTH_TOKEN) and it only appears on a refresh pull — provision_with_env already does env --pull --refresh, so once the suffix was correct it resolved with no change to shared code.
  • Docs: README, ARCHITECTURE §4d, docs/SCHEMA.md.

🤖 Generated with Claude Code

The second hosting target in the suite, after Fly. v0 is static-upload: a
service's source files (under [services.X.netlify].root or the repo root) are
deployed via Netlify's file-digest API.

- crates/stackless-netlify impl Substrate: Stripe Projects provisions
  `netlify/project` (free) and returns a Stripe-managed token + site id (pinned
  by `mise run discover netlify/project`; the token surfaces on a refreshed env
  read). The substrate clones the pinned ref and runs the file-digest deploy
  (SHA1 per file, PUT only the `required` files, poll to `ready`),
  health-gating on the deploy's ssl_url. observe/destroy key off the Stripe
  resource registration (the token is ephemeral).
- netlify_api.rs is hand-written reqwest/serde (Swagger-2.0 source, ~5
  endpoints).
- Registered across the one-row seams: workspace member, binary dep,
  substrates.rs (row + builder + global codes-uniqueness test), --on help,
  SubstrateRequired remediation, integrations KNOWN.
- Tests: hermetic catalog-gap + config + Stripe-scripted observe/destroy +
  mock-API file-digest deploy (15). Live-validated end-to-end via
  `mise run smoke-netlify` (provision -> upload deploy -> HTTPS health ->
  verified teardown).
- Docs: README, ARCHITECTURE 4d, docs/SCHEMA.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@snowmead snowmead merged commit ff1c766 into feat/flyio-substrate Jun 17, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant