opengeos--geolibre
7df9ebf22c
Sync labels / sync (push) Failing after 1m9s
Publish Container Image / Build and publish container image (push) Has been cancelled
Deploy Website / Deploy to GitHub Pages (push) Has been cancelled
Deploy Website / Build website and demo (push) Has been cancelled
Deploy viewer / Deploy viewer proxy to Cloudflare Workers (push) Has been cancelled
Deploy tiles / Deploy planetary tile proxy to Cloudflare Workers (push) Has been cancelled
Deploy collab / Deploy collaboration relay to Cloudflare Workers (push) Has been cancelled
CI / Dependency audit (push) Has been cancelled
CI / E2E smoke (Playwright) (push) Has been cancelled
CI / Validate CITATION.cff (push) Has been cancelled
CI / Build and test (push) Has been cancelled
166 行
6.9 KiB
YAML
166 行
6.9 KiB
YAML
name: Cloudflare preview
|
|
|
|
# Builds the docs site + web demo for every pull request and uploads it to a
|
|
# Cloudflare Pages project as a *preview* deployment, then comments the URL on
|
|
# the PR. This replaces the old Netlify Deploy Previews.
|
|
#
|
|
# The build mirrors .github/workflows/pages.yml (the GitHub Pages production
|
|
# deploy) so previews match what ships:
|
|
# docs deps -> jupyterlite deps -> npm ci -> web demo build -> docs build ->
|
|
# bundle demo into site/demo.
|
|
#
|
|
# NOTE on fork PRs: the `pull_request` event does NOT expose repository secrets
|
|
# to PRs opened from forks, so previews only run for branches pushed to this
|
|
# repo (maintainers and collaborators). External fork PRs are skipped — the job
|
|
# guard below short-circuits them instead of failing with a missing token.
|
|
#
|
|
# Required repository secrets (already present for the Workers deploys):
|
|
# CLOUDFLARE_API_TOKEN - needs the "Cloudflare Pages: Edit" permission
|
|
# CLOUDFLARE_ACCOUNT_ID
|
|
# Optional (baked into the client bundle, same as pages.yml):
|
|
# VITE_GEE_OAUTH_CLIENT_ID, VITE_PROTOMAPS_API_KEY,
|
|
# VITE_GOOGLE_MAPS_API_KEY or GOOGLE_MAPS_API_KEY
|
|
|
|
on:
|
|
pull_request:
|
|
branches: [main]
|
|
workflow_dispatch:
|
|
|
|
permissions:
|
|
contents: read
|
|
pull-requests: write
|
|
|
|
concurrency:
|
|
group: cf-preview-${{ github.event.pull_request.number || github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
preview:
|
|
name: Build and deploy preview
|
|
runs-on: ubuntu-latest
|
|
# Skip fork PRs: secrets are unavailable there, so the deploy would fail.
|
|
if: github.event_name == 'workflow_dispatch' || github.event.pull_request.head.repo.full_name == github.repository
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v6
|
|
with:
|
|
# Match ci.yml: don't leave the GITHUB_TOKEN in .git/config where an
|
|
# npm lifecycle script during `npm ci`/`npm run build` could read it.
|
|
persist-credentials: false
|
|
|
|
- name: Set up Python
|
|
uses: actions/setup-python@v6
|
|
with:
|
|
python-version: "3.12"
|
|
cache: pip
|
|
cache-dependency-path: |
|
|
requirements-docs.txt
|
|
apps/geolibre-desktop/jupyterlite/requirements.txt
|
|
|
|
- name: Install documentation dependencies
|
|
run: python -m pip install -r requirements-docs.txt
|
|
|
|
- name: Install JupyterLite build dependencies
|
|
run: python -m pip install -r apps/geolibre-desktop/jupyterlite/requirements.txt
|
|
|
|
- name: Set up Node.js
|
|
uses: actions/setup-node@v6
|
|
with:
|
|
node-version: lts/*
|
|
cache: npm
|
|
cache-dependency-path: package-lock.json
|
|
|
|
- name: Install frontend dependencies
|
|
run: npm ci
|
|
|
|
- name: Build web demo
|
|
run: npm run build -w geolibre-desktop
|
|
env:
|
|
GEOLIBRE_APP_BASE: ./
|
|
VITE_GEE_OAUTH_CLIENT_ID: ${{ secrets.VITE_GEE_OAUTH_CLIENT_ID }}
|
|
VITE_PROTOMAPS_API_KEY: ${{ secrets.VITE_PROTOMAPS_API_KEY }}
|
|
VITE_GOOGLE_MAPS_API_KEY: ${{ secrets.VITE_GOOGLE_MAPS_API_KEY }}
|
|
GOOGLE_MAPS_API_KEY: ${{ secrets.GOOGLE_MAPS_API_KEY }}
|
|
VITE_MAPILLARY_ACCESS_TOKEN: ${{ secrets.VITE_MAPILLARY_ACCESS_TOKEN || vars.VITE_MAPILLARY_ACCESS_TOKEN }}
|
|
VITE_GEOLIBRE_COLLAB_URL: wss://collab.geolibre.app
|
|
|
|
- name: Build documentation
|
|
run: zensical build --strict
|
|
|
|
- name: Add web demo to site
|
|
run: |
|
|
mkdir -p site/demo
|
|
cp -R apps/geolibre-desktop/dist/. site/demo/
|
|
test -f site/demo/index.html
|
|
test -f site/demo/jupyterlite/lab/index.html
|
|
|
|
- name: Offload oversized DuckDB WASM to CDN
|
|
# Cloudflare Pages rejects any single file > 25 MiB. The bundled DuckDB
|
|
# WASM modules (duckdb-eh ~35 MiB, duckdb-mvp ~40 MiB) exceed that, so we
|
|
# drop the local copies and redirect their hashed URLs to jsDelivr at the
|
|
# exact pinned version (byte-identical to the bundled file). This only
|
|
# affects the Cloudflare preview; GitHub Pages still serves them locally.
|
|
# Any OTHER oversized file is a hard error so we never ship a broken site.
|
|
run: |
|
|
set -euo pipefail
|
|
version=$(node -e "console.log(require('./node_modules/@duckdb/duckdb-wasm/package.json').version)")
|
|
echo "duckdb-wasm version: $version"
|
|
redirects=site/_redirects
|
|
touch "$redirects"
|
|
moved=0
|
|
# 26214400 bytes = 25 MiB, Cloudflare Pages' exact per-file limit.
|
|
while IFS= read -r -d '' f; do
|
|
rel=${f#site}
|
|
base=$(basename "$f")
|
|
case "$base" in
|
|
duckdb-eh-*) cdn=duckdb-eh.wasm ;;
|
|
duckdb-mvp-*) cdn=duckdb-mvp.wasm ;;
|
|
duckdb-coi-*) cdn=duckdb-coi.wasm ;;
|
|
*)
|
|
echo "::error::Oversized file not handled by CDN redirect: $rel ($(du -h "$f" | cut -f1)). Cloudflare Pages rejects files > 25 MiB."
|
|
exit 1 ;;
|
|
esac
|
|
echo "$rel https://cdn.jsdelivr.net/npm/@duckdb/duckdb-wasm@${version}/dist/${cdn} 302" >> "$redirects"
|
|
rm "$f"
|
|
echo "redirect: $rel -> $cdn"
|
|
moved=$((moved + 1))
|
|
done < <(find site -type f -size +26214400c -print0)
|
|
echo "offloaded $moved oversized file(s)"
|
|
echo "----- site/_redirects -----"
|
|
cat "$redirects"
|
|
|
|
- name: Deploy to Cloudflare Pages
|
|
id: deploy
|
|
uses: cloudflare/wrangler-action@v4
|
|
with:
|
|
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
|
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
|
# --branch is anything other than the project's production branch, so
|
|
# every run here is a preview deployment with its own URL.
|
|
command: >-
|
|
pages deploy site
|
|
--project-name=geolibre-preview
|
|
--branch="${{ github.head_ref || github.ref_name }}"
|
|
--commit-dirty=true
|
|
|
|
- name: Comment preview URL on PR
|
|
if: github.event_name == 'pull_request'
|
|
uses: actions/github-script@v9
|
|
env:
|
|
DEPLOY_URL: ${{ steps.deploy.outputs.deployment-url }}
|
|
with:
|
|
script: |
|
|
const url = process.env.DEPLOY_URL;
|
|
if (!url) return;
|
|
const marker = '<!-- cloudflare-preview -->';
|
|
const body = `${marker}\n### ⚡ Cloudflare Pages preview\n\n| Item | Value |\n| --- | --- |\n| Preview | ${url} |\n| Demo app | ${url}/demo/ |\n| Commit | \`${context.sha.slice(0, 7)}\` |`;
|
|
const { owner, repo } = context.repo;
|
|
const issue_number = context.issue.number;
|
|
const { data: comments } = await github.rest.issues.listComments({ owner, repo, issue_number, per_page: 100 });
|
|
const existing = comments.find((c) => c.body && c.body.includes(marker));
|
|
if (existing) {
|
|
await github.rest.issues.updateComment({ owner, repo, comment_id: existing.id, body });
|
|
} else {
|
|
await github.rest.issues.createComment({ owner, repo, issue_number, body });
|
|
}
|