Skip to content

ci: replace Fleek deployment with Cloudflare Pages direct upload - #1181

Merged
levalleux-ludo merged 4 commits into
mainfrom
ci/cloudflare-pages-direct-upload
Sep 7, 2026
Merged

ci: replace Fleek deployment with Cloudflare Pages direct upload#1181
levalleux-ludo merged 4 commits into
mainfrom
ci/cloudflare-pages-direct-upload

Conversation

@levalleux-ludo

Copy link
Copy Markdown
Member

Why

The committed workflows still deploy to Fleek, while the real deployments run through Cloudflare Pages' Git integration. That means build settings and ~30 REACT_APP_* values are maintained by hand across 7 dashboard configurations — invisible to code review, undiffable, and impossible to reproduce.

What changes

Build in GitHub Actions and upload with wrangler (Direct Upload). Because every REACT_APP_* is inlined at build time by CRA, Cloudflare no longer needs to build anything — so its dashboard build settings and env vars become irrelevant, not merely duplicated.

Configuration now comes from GitHub:

  • Repository variables/secrets → values shared by all environments
  • testing / staging / production Environments → override only what differs

GitHub resolves environment values first and falls back to repository ones, which removes the _TESTING/_STAGING/_PRODUCTION name suffixes and with them the four near-identical 40-line blocks in ci.yaml.

Deploy triggers

Env Trigger Builds
preview every PR one deployment, REACT_APP_VIEW_MODE=dapp,dr_center, serving both halves at #/dapp and #/dr_center
testing push to main dapp + dr-center, gated on the CI checks
staging release published that tag
production manual dispatch with a tag that tag

deploy/staging and deploy/production are no longer used

They only ever existed to trigger Cloudflare's Git integration. The release tag is now the deploy identity, and what is live is recorded by GitHub Environments, the Cloudflare deployment list (--commit-message=<tag>), and REACT_APP_RELEASE_TAG — which becomes more accurate, since it is passed exactly instead of guessed via git describe. The branches are deleted separately, once this flow is proven.

Incidental fixes

  • Preflight check for REACT_APP_ENV_NAME / REACT_APP_INFURA_KEY / REACT_APP_WIDGETS_URL. config.ts throws on these at module load, so an empty value currently builds green and serves a blank page.
  • Non-mutating gates. pnpm prettier and pnpm lint are --write/--fix, so as CI steps they gated nothing and left the build compiling something other than the committed code. Added prettier:check / lint:check and run them first. Both pass clean on the current tree.
  • Parallel matrix builds per view mode, replacing the sequential rebuild that overwrote build/ in place.
  • Node pinning: CI said 24, .nvmrc said 20, volta said 18.19.1. Collapsed onto .nvmrc (24, the version CI has actually been shipping with); pnpm pinned via packageManager.
  • Fixed the always-empty deploy URL (the old summary read steps.deploy, but the step id was Deploy).

Verification done locally

  • pnpm build with the preview configuration (REACT_APP_VIEW_MODE=dapp,dr_center, both view-mode URLs same_origin) — succeeds.
  • Served build/ and loaded it in Chromium: #/dapp renders "Sell on Boson / Explore Products", #/dr_center renders "Dispute Resolution Center / Raise a dispute". One upload genuinely serves both halves.
  • actionlint — clean across all workflows.
  • pnpm prettier:check, pnpm lint:check, pnpm tsc — all pass.
  • pnpm install --frozen-lockfile resolves after dropping the Fleek CLI.

Required before merge

This PR cannot deploy until the Cloudflare and GitHub setup is done — see the checklist in the review comments. In short: create CLOUDFLARE_API_TOKEN / CLOUDFLARE_ACCOUNT_ID, populate the three Environments, and capture the exact project names from wrangler pages project list (the testing dapp's project is not named boson-dapp-testing — it serves from interface-a9d.pages.dev).

Disconnect Cloudflare's Git integration only after a preview and a testing deploy have succeeded, so there is never a window without a working deploy path.

Known trade-off

PR previews use the testing Environment to avoid duplicating ~9 secrets, so preview deployments appear in that environment's history alongside real testing deploys. A separate preview Environment would separate them at the cost of maintaining a second copy of the values.

Not addressed

pnpm test is not wired into CI: all 3 unit test suites currently fail to run (SyntaxError: Cannot use import statement outside a module — jest can't transform the e2e-tests/ import in src/lib/utils/hooks/offers/__tests_/memo.test.ts). That is pre-existing and unrelated; adding the step would make CI permanently red. Worth a follow-up.

🤖 Generated with Claude Code

The committed workflows still deployed to Fleek, while the real deployments ran
through Cloudflare Pages' Git integration - meaning build settings and ~30
REACT_APP_* values were maintained by hand across 7 dashboard configurations,
invisible to code review.

Build in GitHub Actions and upload with wrangler instead. Because every
REACT_APP_* is inlined at build time, Cloudflare no longer needs to build
anything, so its dashboard build settings and environment variables become
irrelevant rather than merely duplicated.

Configuration now comes from GitHub: values shared by all environments are
repository variables/secrets, and the testing/staging/production Environments
override only what differs. This removes the _TESTING/_STAGING/_PRODUCTION
secret-name suffixes and with them the four near-identical blocks in ci.yaml.

Deploy triggers:
- preview: every PR, one deployment built with REACT_APP_VIEW_MODE=dapp,dr_center
  so a single upload serves both halves at #/dapp and #/dr_center
- testing: push to main, gated on the CI checks
- staging: publishing a release, building that tag
- production: manual dispatch with a tag

The deploy/staging and deploy/production branches are no longer used; they only
ever existed to trigger Cloudflare's Git integration, and the release tag is now
the deploy identity. They are deleted separately, once this flow is proven.

Also:
- add a preflight check for the three variables config.ts throws on at module
  load, which otherwise build green and serve a blank page
- run prettier and eslint as non-mutating gates before the build, so they
  actually gate; the --fix/--write variants gated nothing
- build each view mode as a parallel matrix job, replacing the sequential
  rebuild that overwrote build/ in place
- collapse the three-way Node mismatch (CI 24, .nvmrc 20, volta 18.19.1) onto
  .nvmrc, and pin pnpm via packageManager

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings September 7, 2026 13:38
@levalleux-ludo
levalleux-ludo requested a review from a team as a code owner September 7, 2026 13:38

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The reusable Cloudflare deploy workflow currently pins --commit-hash to ${{ github.sha }}, which can mismatch the checked-out ref for tag-based deploys and should be corrected before relying on it operationally.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR migrates deployments from Fleek/IPFS workflows to Cloudflare Pages “Direct Upload” via wrangler, moving build-time configuration into GitHub (repo vars + environment overrides) so deploys are reproducible and reviewable.

Changes:

  • Replace Fleek-based deployment workflows with Cloudflare Pages uploads using a reusable deploy workflow and environment-scoped configuration.
  • Simplify CI to run non-mutating format/lint checks first, then typecheck and build; pin Node via .nvmrc and pnpm via packageManager.
  • Remove Fleek config files and the Fleek CLI dependency.
File summaries
File Description
README.md Updates environment/deploy documentation to reflect Cloudflare Pages + GitHub Actions.
pnpm-lock.yaml Removes Fleek CLI and associated transitive dependencies from the lockfile.
package.json Adds lint:check/prettier:check, removes Fleek CLI devDependency, pins pnpm via packageManager.
.nvmrc Pins Node to 24 to match CI and tooling expectations.
.github/workflows/fleek-deploy.yaml Removes legacy Fleek deployment workflow.
.github/workflows/deploy-testing.yaml Adds testing deployment on main pushes, gated by CI.
.github/workflows/deploy-staging.yaml Adds staging deployment on release publish (deploys the tag).
.github/workflows/deploy-production.yaml Adds manual production deployment by tag with tag existence verification.
.github/workflows/deploy-preview.yaml Adds PR preview deployments (skips fork PRs) and comments the preview URL.
.github/workflows/deploy_reusable.yaml Introduces shared build+deploy workflow using wrangler pages deploy with env/secret wiring and smoke checks.
.github/workflows/ci.yaml Replaces prior reusable CI setup with a single job for format/lint/types/build.
.github/workflows/ci_reusable.yaml Removes legacy reusable CI/deploy workflow.
.fleek.json Removes obsolete Fleek site config.
.fleek_staging.json Removes obsolete Fleek staging config.
.fleek_production.json Removes obsolete Fleek production config.
.fleek_dr_center_testing.json Removes obsolete Fleek DR center testing config.
.fleek_dr_center_staging.json Removes obsolete Fleek DR center staging config.
.fleek_dr_center_production.json Removes obsolete Fleek DR center production config.
Review details
  • Files reviewed: 17/18 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread .github/workflows/deploy_reusable.yaml Outdated
REACT_APP_RELEASE_TAG was set from `git describe --tags --always`, so it changed
on every commit rather than every release. The app treats a change in it as a new
release and clears the seller's in-progress create-product draft from
localStorage, so every merge to main would have wiped drafts on testing. Split it
back into two values as the old workflow had: REACT_APP_RELEASE_TAG names the
release (`git describe --abbrev=0`), REACT_APP_RELEASE_NAME names the build.

The preflight check covered 3 of ~20 build variables. Since every REACT_APP_* is
inlined at build time, an unset one is not an error - it becomes an empty string
and silently disables what it configures, in a bundle that builds and deploys
green. Extend the check to everything the app cannot work without, and validate
that REACT_APP_ENV_NAME is one the config recognises: `prod` passes an emptiness
test and then throws at module load, which is the blank page the check exists to
prevent. Declaring the secrets as `required: true` on workflow_call would not
help here - it proves the caller passed something, and these are resolved from
the GitHub Environment, not passed by callers.

Also:
- deploy the commit that was built. `github.sha` is the ref that triggered the
  run, so a production dispatch recorded main's tip rather than the tag it built
- validate the release tag, project and branch before they are spliced into the
  wrangler command line. The tag is free-form text from a dispatch form, and a
  value with a space or a shell metacharacter changes what runs
- create the Sentry release once per deploy, not once per view mode: the two
  matrix legs were racing on the same release object
- drop REACT_APP_ENABLE_SENTRY_LOGGING, which only has an effect when NODE_ENV is
  development and so did nothing in any deployed build
- build in ci.yaml only for fork PRs. Every other path builds the same commit
  again with real values, so a push to main was doing three full builds
- verify a production tag with one API call instead of cloning the whole
  repository onto a runner to answer a yes/no question
- extract the pnpm/node setup into a composite action
- skip the preview comment when there is no deployment URL, rather than posting
  links that are bare relative paths
- correct the fail-fast comment, which claimed the opposite of what the setting
  does, and the smoke-check comment, which overstated what it can catch

secrets: inherit stays. An explicit allow-list would make each caller supply its
own repository-scope value for secrets that are scoped to the Environment, which
for those is the empty string. The fork guard in deploy-preview.yaml is what
keeps them away from untrusted code.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Cloudflare Pages rejects any file over 25 MiB, and the main bundle's source map
is ~38 MiB, so every deploy failed before uploading anything.

Nothing reads these maps. The Sentry release is created before the build and
uploads no artifacts, and the deployments this workflow replaced were already
built without them - the bundles live on bosonapp.io carry no sourceMappingURL.
Generating them only published the full source alongside a deploy that could
not complete.

Set GENERATE_SOURCEMAP=false on the build step rather than switching to the
build:nomaps script, which drops the --max-old-space-size=8192 heap bump.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown

Preview deployment

View URL
dApp https://0a2933e0.interface-a9d.pages.dev/#/dapp
DR Center https://0a2933e0.interface-a9d.pages.dev/#/dr_center

Built from a5852ae.

@levalleux-ludo
levalleux-ludo merged commit 52c6119 into main Sep 7, 2026
5 checks passed
@levalleux-ludo
levalleux-ludo deleted the ci/cloudflare-pages-direct-upload branch September 7, 2026 17:08
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.

2 participants