Sitelet https://github.com/Mindfeast/feastdocs/actions/runs/32826690157/workflow
Skip to content

feat: one source-control panel, in every mode #84

feat: one source-control panel, in every mode

feat: one source-control panel, in every mode #84

Workflow file for this run

# Build and test on every push and PR; optionally deploy to Cloudflare Pages.
#
# Two ways to deploy, pick one:
#
# 1. Cloudflare Pages Git integration (dashboard-driven): connect the repo in
# the Cloudflare dashboard with build command `npm run build` and output
# directory `dist/feastdocs/browser`. This workflow then just provides CI
# checks — the deploy job below stays skipped because the secrets are absent.
# Caveat: Cloudflare's own builder may clone shallowly, which can blank out
# the "last updated by" authors (they come from git history at build time).
#
# 2. Deploy from this workflow (recommended — guarantees full git history):
# create a Pages project once (`wrangler pages project create feastdocs`),
# then add two repository secrets:
# CLOUDFLARE_API_TOKEN (API token with the "Cloudflare Pages — Edit" permission)
# CLOUDFLARE_ACCOUNT_ID (dashboard → Workers & Pages → account ID)
# The deploy job activates by itself once they exist.
name: ci
on:
push:
branches: [main]
pull_request:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
# Full history — "last updated by" on every page is read from git log
# at build time; a shallow clone would blank out most authors.
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- run: npm test
- run: npm run build
- uses: actions/upload-artifact@v4
with:
name: site
path: dist/feastdocs/browser
retention-days: 7
deploy:
needs: build
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
# Job-level `if` cannot read secrets, so the gate lives in a step: when
# the Cloudflare secrets are not configured, every later step is skipped
# and the job succeeds as a no-op.
- name: Check Cloudflare secrets
id: cf
run: echo "configured=${{ secrets.CLOUDFLARE_API_TOKEN != '' && secrets.CLOUDFLARE_ACCOUNT_ID != '' }}" >> "$GITHUB_OUTPUT"
- name: Download site
if: steps.cf.outputs.configured == 'true'
uses: actions/download-artifact@v4
with:
name: site
path: site
# Functions (e.g. the GitHub OAuth exchange) deploy alongside the assets.
- name: Include Pages Functions
if: steps.cf.outputs.configured == 'true'
uses: actions/checkout@v4
with:
path: repo
- name: Stage functions next to the site
if: steps.cf.outputs.configured == 'true'
run: cp -r repo/functions functions
# Project name: repo variable CLOUDFLARE_PAGES_PROJECT, or "feastdocs".
# Created on first run if it does not exist yet (harmless when it does).
- name: Ensure the Pages project exists
if: steps.cf.outputs.configured == 'true'
continue-on-error: true
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: pages project create ${{ vars.CLOUDFLARE_PAGES_PROJECT || 'feastdocs' }} --production-branch=main
# "Sign in with GitHub" needs two variables on the Pages project. Syncing
# them from GitHub secrets guarantees they land on the right project and
# environment — no dashboard hunting. Optional: skipped when unset.
- name: Sync OAuth secrets to the Pages project
if: steps.cf.outputs.configured == 'true'
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
OAUTH_ID: ${{ secrets.OAUTH_GITHUB_CLIENT_ID }}
OAUTH_SECRET: ${{ secrets.OAUTH_GITHUB_CLIENT_SECRET }}
PROJECT: ${{ vars.CLOUDFLARE_PAGES_PROJECT || 'feastdocs' }}
run: |
if [ -n "$OAUTH_ID" ] && [ -n "$OAUTH_SECRET" ]; then
printf '%s' "$OAUTH_ID" | npx --yes wrangler@4 pages secret put GITHUB_CLIENT_ID --project-name "$PROJECT"
printf '%s' "$OAUTH_SECRET" | npx --yes wrangler@4 pages secret put GITHUB_CLIENT_SECRET --project-name "$PROJECT"
else
echo "OAuth secrets not set in GitHub — skipping (the dashboard route works too)."
fi
- name: Deploy to Cloudflare Pages
if: steps.cf.outputs.configured == 'true'
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: pages deploy site --project-name=${{ vars.CLOUDFLARE_PAGES_PROJECT || 'feastdocs' }} --branch=main
# Keeps the starter template in step with this repository. The template is a
# derived artifact — every feature that lands here is in it on the next push,
# so nobody has to remember to port anything.
#
# Needs a repository secret TEMPLATE_SYNC_TOKEN: a fine-grained PAT with
# Contents: Read and write on the template repository. The automatic
# GITHUB_TOKEN cannot push to another repository. Skipped when absent.
template:
runs-on: ubuntu-latest
needs: build
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
steps:
- uses: actions/checkout@v4
- name: Sync the starter template
env:
TOKEN: ${{ secrets.TEMPLATE_SYNC_TOKEN }}
TARGET: ${{ vars.TEMPLATE_REPO || 'Mindfeast/feastdocs-template' }}
run: |
if [ -z "$TOKEN" ]; then
echo "TEMPLATE_SYNC_TOKEN not set — skipping template sync."
exit 0
fi
git config --global user.name "github-actions[bot]"
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
git clone --quiet "https://x-access-token:$TOKEN@github.com/$TARGET.git" /tmp/template
node tools/sync-template.mjs /tmp/template --push