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
85 changes: 85 additions & 0 deletions .github/workflows/deploy-website.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
name: Deploy website

on:
push:
branches: [main]
paths:
- "apps/website/**"
- "install.sh"
- "install.ps1"
- ".github/workflows/deploy-website.yml"
workflow_dispatch:

permissions:
contents: read

jobs:
deploy:
name: Deploy
runs-on: ubuntu-latest
environment: production
permissions:
contents: read
defaults:
run:
working-directory: apps/website
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 11.21.0

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
cache-dependency-path: apps/website/pnpm-lock.yaml

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Deploy to Cloudflare
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_ACCOUNT_ID: ${{ vars.CLOUDFLARE_ACCOUNT_ID }}
run: |
set -euo pipefail
if [ -z "${CLOUDFLARE_API_TOKEN}" ]; then
echo "::error::Missing secret CLOUDFLARE_API_TOKEN on Environment production"
exit 1
fi
if [ -z "${CLOUDFLARE_ACCOUNT_ID}" ]; then
echo "::error::Missing variable CLOUDFLARE_ACCOUNT_ID on Environment production"
exit 1
fi
if ! pnpm run deploy; then
echo "::error::wrangler deploy failed; Worker and static assets were not published"
exit 1
fi

# wrangler 4.x takes {bucket}/{key}; --bucket is not a valid flag on r2 object put.
# Quote content-type so the charset parameter is not split by the shell.
- name: Upload install scripts to R2
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_ACCOUNT_ID: ${{ vars.CLOUDFLARE_ACCOUNT_ID }}
run: |
set -euo pipefail
if ! npx wrangler r2 object put amber-dist/install.sh \
--file=../../install.sh \
--remote \
--content-type "text/plain; charset=utf-8"; then
echo "::error::Failed to upload install.sh to R2 bucket amber-dist"
exit 1
fi
if ! npx wrangler r2 object put amber-dist/install.ps1 \
--file=../../install.ps1 \
--remote \
--content-type "text/plain; charset=utf-8"; then
echo "::error::Failed to upload install.ps1 to R2 bucket amber-dist"
exit 1
fi
14 changes: 10 additions & 4 deletions apps/website/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,13 @@ The production bundle is written to `dist/`. The `prebuild` step copies repo-roo

## Cloudflare Deploy

`get.amberjs.com` is a custom domain on the same Worker as `amberjs.com` (`apps/website/wrangler.toml`). There is no GitHub Actions deploy job; publishing is a local Wrangler deploy (needs a Cloudflare account with access to this Worker):
`get.amberjs.com` is a custom domain on the same Worker as `amberjs.com` (`apps/website/wrangler.toml`).

Production deploys run through GitHub Actions on the **`production`** Environment (secret `CLOUDFLARE_API_TOKEN`, variable `CLOUDFLARE_ACCOUNT_ID`). The workflow publishes on push to `main` when `apps/website/**`, `install.sh`, `install.ps1`, or the workflow file change. Tokens are not stored in the YAML.

To publish manually: **Actions → Deploy website → Run workflow**.

Local Wrangler is still available for dry-run and development (needs a Cloudflare account with access to this Worker):

```bash
pnpm run deploy:dry-run
Expand All @@ -28,9 +34,9 @@ pnpm run deploy

`wrangler.toml` serves `dist/` as static assets and uses `single-page-application` fallback so direct links such as `/docs/installation` work on Cloudflare.

`src/worker.ts` serves `/install.sh` and `/install.ps1` from the R2 bucket `amber-dist` **when that object exists**, otherwise from the Worker static assets. Live `get.amberjs.com/install.sh` currently matches the asset-hosted copy (`content-type: application/x-sh`, `max-age=0`), so a Wrangler deploy updates the installer. If R2 later has `install.sh` / `install.ps1`, it shadows the deploy — also upload:
`src/worker.ts` serves `/install.sh` and `/install.ps1` from the R2 bucket `amber-dist` **when that object exists**, otherwise from the Worker static assets. If R2 has `install.sh` / `install.ps1`, it shadows the Worker assets. The production workflow also uploads both scripts to `amber-dist` after deploy so `get.amberjs.com` stays in sync. Local equivalent (wrangler 4.x uses `{bucket}/{key}`):

```bash
npx wrangler r2 object put install.sh --file=../../install.sh --bucket=amber-dist --remote --content-type text/plain
npx wrangler r2 object put install.ps1 --file=../../install.ps1 --bucket=amber-dist --remote --content-type text/plain
npx wrangler r2 object put amber-dist/install.sh --file=../../install.sh --remote --content-type "text/plain; charset=utf-8"
npx wrangler r2 object put amber-dist/install.ps1 --file=../../install.ps1 --remote --content-type "text/plain; charset=utf-8"
```
Loading