ci(website): publish Cloudflare and Pages from one artifact
This commit is contained in:
parent
54c0ed42aa
commit
761881cec3
|
|
@ -19,12 +19,33 @@ jobs:
|
|||
contents: read
|
||||
pages: read
|
||||
steps:
|
||||
- name: Require Cloudflare publishing credentials
|
||||
env:
|
||||
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||
run: |
|
||||
if [[ -z "$CLOUDFLARE_API_TOKEN" || -z "$CLOUDFLARE_ACCOUNT_ID" ]]; then
|
||||
echo "::error::Set CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID in repository Actions secrets before publishing."
|
||||
exit 1
|
||||
fi
|
||||
- name: Check out the repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Prepare the example download
|
||||
run: python3 scripts/prepare-website.py
|
||||
- name: Check website links and publishing configuration
|
||||
run: python3 scripts/verify-website.py
|
||||
- name: Record the published commit
|
||||
run: |
|
||||
python3 - <<'PY'
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
Path("website/public/deployment.json").write_text(
|
||||
json.dumps({"commit": os.environ["GITHUB_SHA"]}) + "\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
PY
|
||||
- name: Configure Pages
|
||||
uses: actions/configure-pages@v5
|
||||
- name: Upload the website
|
||||
|
|
@ -35,14 +56,81 @@ jobs:
|
|||
deploy:
|
||||
needs: prepare
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
timeout-minutes: 15
|
||||
permissions:
|
||||
contents: read
|
||||
actions: read
|
||||
pages: write
|
||||
id-token: write
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
steps:
|
||||
- name: Check out publishing configuration
|
||||
uses: actions/checkout@v4
|
||||
- name: Set up Node.js for Wrangler
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: .nvmrc
|
||||
- name: Download the verified website
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: github-pages
|
||||
path: ${{ runner.temp }}/website-archive
|
||||
- name: Extract the shared publishing artifact
|
||||
run: |
|
||||
mkdir -p "$RUNNER_TEMP/rea-website-public"
|
||||
tar -xf "$RUNNER_TEMP/website-archive/artifact.tar" -C "$RUNNER_TEMP/rea-website-public"
|
||||
- name: Publish the website to Cloudflare
|
||||
uses: cloudflare/wrangler-action@v4
|
||||
with:
|
||||
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||
wranglerVersion: "4.149.0"
|
||||
packageManager: npm
|
||||
command: deploy --cwd website --env production --assets "${{ runner.temp }}/rea-website-public"
|
||||
- name: Publish to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v4
|
||||
- name: Verify both published revisions
|
||||
env:
|
||||
PAGES_URL: ${{ steps.deployment.outputs.page_url }}
|
||||
run: |
|
||||
python3 - <<'PY'
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
from urllib.error import URLError
|
||||
from urllib.parse import urljoin
|
||||
from urllib.request import Request, urlopen
|
||||
|
||||
expected = os.environ["GITHUB_SHA"]
|
||||
pages_url = os.environ["PAGES_URL"]
|
||||
if not pages_url:
|
||||
sys.exit("GitHub Pages returned no published URL.")
|
||||
pending = {"Cloudflare": "https://rea.tools/", "GitHub Pages": pages_url}
|
||||
for attempt in range(24):
|
||||
for name, base in list(pending.items()):
|
||||
url = urljoin(base, "deployment.json") + "?commit=" + expected
|
||||
try:
|
||||
request = Request(url, headers={"Cache-Control": "no-cache"})
|
||||
with urlopen(request, timeout=10) as response:
|
||||
actual = json.load(response).get("commit")
|
||||
if actual == expected:
|
||||
print(f"{name} serves {expected}: {base}")
|
||||
del pending[name]
|
||||
else:
|
||||
print(f"Waiting for {name}: observed revision {actual}")
|
||||
except (URLError, TimeoutError, ValueError) as error:
|
||||
print(f"Waiting for {name}: {error}")
|
||||
if not pending:
|
||||
break
|
||||
if attempt < 23:
|
||||
time.sleep(5)
|
||||
if pending:
|
||||
sys.exit("Published revision did not match on: " + ", ".join(pending))
|
||||
with open(os.environ["GITHUB_STEP_SUMMARY"], "a", encoding="utf-8") as summary:
|
||||
summary.write(f"Published commit `{expected}` to [rea.tools](https://rea.tools/) "
|
||||
f"and [GitHub Pages]({pages_url}).\n")
|
||||
PY
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ Thumbs.db
|
|||
|
||||
# Generated website download
|
||||
/website/public/examples/notes-example.zip
|
||||
/website/public/deployment.json
|
||||
|
||||
# Local Cloudflare development state
|
||||
/website/.wrangler/
|
||||
|
|
|
|||
|
|
@ -19,5 +19,6 @@ for asset notes and the source of case-study claims.
|
|||
- Check both local root and `/rea/` paths, mobile layouts, expanded details,
|
||||
copying and downloads. Run `scripts/prepare-website.py` followed by
|
||||
`scripts/verify-website.py`.
|
||||
- Keep `website-pages.yml` as the sole, manual Pages publisher. Follow the
|
||||
publication procedure in the website README.
|
||||
- Keep `website-pages.yml` as the sole, manual production publisher for
|
||||
Cloudflare and Pages. Both hosts must receive the same verified artifact and
|
||||
pass the published-commit check. Follow the website README.
|
||||
|
|
|
|||
|
|
@ -185,7 +185,7 @@ Wrangler version without adding it to REA's package dependencies.
|
|||
Cloudflare documents static-asset requests as free and unlimited, with no
|
||||
additional storage cost. See [billing and limitations](https://developers.cloudflare.com/workers/static-assets/billing-and-limitations/).
|
||||
|
||||
### Preview and deploy
|
||||
### Local and hosted previews
|
||||
|
||||
Run these commands from the repository root. `--cwd website` makes the build
|
||||
paths consistent with the website configuration. Preview locally first:
|
||||
|
|
@ -230,13 +230,7 @@ See Cloudflare's [nameserver setup procedure](https://developers.cloudflare.com/
|
|||
for the complete migration steps. A CNAME to the preview's `workers.dev` hostname
|
||||
at the current DNS provider does not configure a Workers Custom Domain.
|
||||
|
||||
Publish to the production Worker:
|
||||
|
||||
```sh
|
||||
npx wrangler@4.149.0 deploy --cwd website --env production
|
||||
```
|
||||
|
||||
This creates or updates `rea-website`, attaches `rea.tools`, and lets Cloudflare
|
||||
The production environment creates or updates `rea-website`, attaches `rea.tools`, and lets Cloudflare
|
||||
manage its DNS record and HTTPS certificate. Deployment can succeed while the
|
||||
zone is pending; verify public HTTPS after activation and certificate issuance.
|
||||
An existing CNAME at `rea.tools`
|
||||
|
|
@ -250,15 +244,34 @@ Verify <https://rea.tools/>, <https://rea.tools/guides/javascript/>,
|
|||
resolve correctly. The root README and browser guide use `https://rea.tools/`
|
||||
as the public website URL.
|
||||
|
||||
Deployments are manual. The existing GitHub Pages publisher remains available
|
||||
as a separate host; it does not publish to Cloudflare.
|
||||
Production publication uses the synchronized GitHub Actions workflow below.
|
||||
Local Wrangler commands above publish only the separate preview Worker.
|
||||
|
||||
## GitHub Pages
|
||||
## Synchronized production publishing
|
||||
|
||||
`.github/workflows/website-pages.yml` prepares and deploys only `website/public`.
|
||||
It is the sole Pages publisher, manually triggered and restricted to `main`;
|
||||
`.github/workflows/website-pages.yml` prepares `website/public` once and deploys
|
||||
the same artifact to Cloudflare (`rea.tools`) and GitHub Pages. It is the sole
|
||||
production publisher, manually triggered and restricted to `main`;
|
||||
ordinary pushes and pull requests do not publish the site.
|
||||
|
||||
Configure these repository **Actions secrets** before publishing:
|
||||
|
||||
- `CLOUDFLARE_API_TOKEN`: a Cloudflare token using the **Edit Cloudflare Workers**
|
||||
template, scoped to the website's account and zone.
|
||||
- `CLOUDFLARE_ACCOUNT_ID`: that Cloudflare account's ID.
|
||||
|
||||
See Cloudflare's [GitHub Actions authentication instructions](https://developers.cloudflare.com/workers/ci-cd/external-cicd/github-actions/).
|
||||
The workflow checks that both secrets are present before preparing a release.
|
||||
Cloudflare deploys first; GitHub Pages deploys after that step succeeds.
|
||||
|
||||
Preparation adds `deployment.json` with the workflow's commit SHA. Cloudflare
|
||||
receives the extracted Pages artifact through Wrangler's explicit assets path;
|
||||
the local custom-build output is not the uploaded directory. The workflow then
|
||||
checks both public version markers and reports success only when they match
|
||||
that commit. A failed publication remains failed; fix its cause and rerun the
|
||||
workflow to complete both deployments. The two hosts can update at different
|
||||
times while a run is in progress.
|
||||
|
||||
Website checks run only for pull requests that change `website/`, the verification
|
||||
script or workflow definitions. They check local links, HTML fragments, SVG XML
|
||||
and the single Pages publisher without installing npm dependencies. The same
|
||||
|
|
@ -277,8 +290,9 @@ the old site.
|
|||
|
||||
After the site is approved and merged, select **GitHub Actions** under the
|
||||
repository's **Settings → Pages → Build and deployment**. Then run **Publish REA
|
||||
website** from the Actions tab on `main`. The workflow uses the `github-pages`
|
||||
environment and the official Pages actions.
|
||||
website** from the Actions tab on `main`. This publishes both production hosts.
|
||||
The workflow uses the `github-pages` environment, the official Pages actions and
|
||||
Cloudflare's Wrangler action.
|
||||
|
||||
The equivalent CLI command is:
|
||||
|
||||
|
|
|
|||
|
|
@ -233,6 +233,8 @@ New analysis or behavior claims need the real evidence that supports them; a moc
|
|||
or a page-loading check cannot establish those claims.
|
||||
|
||||
Follow the PR review and CI process, then publish using the existing manual
|
||||
`website-pages.yml` workflow on `main`. Ordinary commits should not publish the
|
||||
site. After deployment, check the live page and confirm it matches the reviewed
|
||||
version. The legacy VitePress build remains separate from the Pages publisher.
|
||||
`website-pages.yml` workflow on `main`. It publishes the same verified artifact
|
||||
to Cloudflare and GitHub Pages and checks both published commit markers.
|
||||
Ordinary commits should not publish the site. After deployment, check both live
|
||||
pages and confirm they match the reviewed version. The legacy VitePress build
|
||||
remains separate from the Pages publisher.
|
||||
|
|
|
|||
Loading…
Reference in New Issue