Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions .github/workflows/job-deploy-release.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: Deploy

# Builds the prerendered site and deploys it to Cloudflare Pages, but only
# when a GitHub Release is published. Nothing else triggers a deploy: no
# push, no pull_request, no workflow_dispatch. Publishing the release is the
# one and only "go live" action for this site.
#
# The Cloudflare Pages project (cryptos-pki-www) and its custom domains
# (cryptos-pki.com, www.cryptos-pki.com) are created by hand in the
# Cloudflare dashboard, not by this workflow -- see README.md. The org
# secrets CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID must hold real
# values before the first release is published; this workflow never prints
# either one.
on:
release:
types: [published]

permissions:
contents: read

# Deploys queue rather than race: a release is a one-time event, but if two
# ever land close together (e.g. a published release immediately followed by
# an edit-and-republish), the second deploy should wait for the first to
# finish, not cancel it mid-upload.
concurrency:
group: ${{ github.workflow }}
cancel-in-progress: false

jobs:
deploy:
name: 🚀 Deploy to Cloudflare Pages
runs-on: ubuntu-24.04
timeout-minutes: 15
steps:
- name: Checkout
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.0.0
with:
ref: ${{ github.event.release.tag_name }}

- name: Set up Node
uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.0.0
with:
node-version: lts/*
cache: npm

- name: Install dependencies
run: npm ci

- name: Build (prerender)
run: npm run build

- name: Deploy build/client to Cloudflare Pages
uses: cloudflare/wrangler-action@953926a2e2182532811c01a25e53647d93bf07c0 # v4.1.3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: pages deploy build/client --project-name=cryptos-pki-www --branch=main
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@ npm run typecheck # react-router typegen + tsc --noEmit

`build/client/` is the whole deployable site: static files, no server required.

## 🚀 Deploy

The site goes live on Cloudflare Pages (project `cryptos-pki-www`, domains `cryptos-pki.com` and
`www.cryptos-pki.com`) the moment a GitHub Release is published here -- nothing else deploys it.
See [`docs/deploy.md`](docs/deploy.md) for what that build contains, the Cloudflare side of the
setup, and how to roll back.

## 🙏 Acknowledgements

CryptOS was originally written by [@Bugs5382](https://github.com/Bugs5382).
Expand Down
39 changes: 39 additions & 0 deletions docs/deploy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Deploying the site

## What goes live, and when

This site deploys only when I publish a GitHub Release in this repo. The `Deploy`
workflow (`.github/workflows/job-deploy-release.yaml`) listens for the `release: published`
event and nothing else -- not a push to `main`, not a pull request, not a manual dispatch. That
means merging a PR never puts anything on the internet by itself: content and code land on `main`
first, and I choose when to cut and publish the release that actually ships it.

When a release is published, the workflow checks out that release's tag, runs `npm ci` and
`npm run build` the same way CI does on every PR, and uploads the prerendered `build/client/`
folder to Cloudflare Pages with `cloudflare/wrangler-action`, pinned to a specific commit so a
tag can't silently move the code I'm trusting with deploy credentials.

## Where it lives

- **Cloudflare Pages project:** `cryptos-pki-www`.
- **Domains:** `cryptos-pki.com` and `www.cryptos-pki.com`. I attach both to the Pages project by
hand in the Cloudflare dashboard (Custom domains); because the domains' DNS already runs on
Cloudflare, attaching a domain creates its DNS record and certificate automatically. This
workflow never touches DNS or creates the Pages project itself.
- **Credentials:** the org secrets `CLOUDFLARE_API_TOKEN` and `CLOUDFLARE_ACCOUNT_ID`, scoped to
Cloudflare Pages Edit on my account only. They live in GitHub org secrets, never in this repo or
its workflow logs.

## Rolling back

Two ways, depending on how fast I need it:

1. **Publish an older release.** Re-publishing a previous GitHub Release re-runs the `Deploy`
workflow against that release's tag, which rebuilds and re-uploads that version's
`build/client/` to the same Cloudflare Pages project. This is the normal rollback path, because
it goes through the same build the original release did.
2. **Redeploy from the Cloudflare dashboard.** Every Pages deployment Wrangler uploads stays
listed under the `cryptos-pki-www` project's Deployments tab. Picking an older one and choosing
"Rollback to this deployment" switches production traffic to it immediately, without rebuilding
anything. This is the faster path when I need the old content back right away and can fix the
release properly afterward.
Loading