[Spec] Cache REST API (scaffold) #69
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Publish site (main + drafts overlay) | |
on: | |
workflow_dispatch: | |
inputs: | |
ref: | |
description: "Base ref to stage (usually main)" | |
required: false | |
default: "main" | |
force_deploy: | |
description: "Deploy even if no source diff detected" | |
type: boolean | |
required: false | |
default: false | |
push: | |
branches: [main] | |
paths: | |
- "_specs/**" | |
- "_layouts/**" | |
- "_includes/**" | |
- "_data/**" | |
- "assets/**" | |
- "_config.yml" | |
- "index.html" | |
- "spec.html" | |
- "style.css" | |
- ".github/workflows/**" | |
pull_request_target: | |
types: [opened, reopened, synchronize, labeled, unlabeled, closed] | |
permissions: | |
pages: write | |
id-token: write | |
# contents: write # not needed since we don't push any branches | |
concurrency: | |
group: publish-common-specs | |
cancel-in-progress: true | |
jobs: | |
publish: | |
runs-on: ubuntu-latest | |
env: | |
BASE_REF: ${{ inputs.ref || 'main' }} | |
steps: | |
- name: Checkout base ref | |
uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 | |
ref: ${{ env.BASE_REF }} | |
- name: Stage current source into /tmp/site | |
run: | | |
set -e | |
rm -rf /tmp/site && mkdir -p /tmp/site | |
rsync -a --delete --exclude '.git' ./ /tmp/site/ | |
rm -rf /tmp/site/_draft_specs | |
- name: Build _draft_specs overlay from open proposal PRs | |
id: build_drafts | |
uses: actions/github-script@v7 | |
with: | |
script: | | |
const { execSync } = require('node:child_process'); | |
const fs = require('fs'); const path = require('path'); | |
const owner = context.repo.owner, repo = context.repo.repo; | |
// Collect OPEN PRs that look like proposals (or marked in-progress) | |
const prs = await github.paginate(github.rest.pulls.list, { | |
owner, repo, state: 'open', per_page: 100 | |
}); | |
let overlayCount = 0; | |
for (const pr of prs) { | |
const hasWanted = (pr.labels || []).some(l => | |
/^(spec:proposal|in-progress)$/i.test((l.name||'')) | |
); | |
if (!hasWanted) continue; | |
const files = await github.paginate(github.rest.pulls.listFiles, { | |
owner, repo, pull_number: pr.number, per_page: 100 | |
}); | |
const dirs = [...new Set( | |
files.map(f => f.filename) | |
.filter(p => p.startsWith('_specs/')) | |
.map(p => p.replace(/^(_specs\/[^/]+\/[^/]+)\/.*/, '$1')) | |
)]; | |
for (const dir of dirs) { | |
const m = dir.match(/^_specs\/([^/]+)\/([^/]+)/); | |
if (!m) continue; | |
const [_, family, version] = m; | |
const dst = path.join('/tmp/site/_draft_specs', family, version); | |
fs.mkdirSync(dst, { recursive: true }); | |
const list = execSync(`git ls-tree -r --name-only ${pr.head.sha} '${dir}'`, {encoding:'utf8'}) | |
.trim().split('\n').filter(Boolean); | |
for (const p of list) { | |
const rel = p.slice(dir.length + 1); | |
const out = path.join(dst, rel); | |
fs.mkdirSync(path.dirname(out), { recursive: true }); | |
const blob = execSync(`git show ${pr.head.sha}:'${p.replace(/'/g,"'\\''")}'`, {encoding:'utf8'}); | |
fs.writeFileSync(out, blob); | |
} | |
// inject PR metadata into the draft index.md (if present) | |
const idx = path.join(dst, 'index.md'); | |
if (fs.existsSync(idx)) { | |
const src = fs.readFileSync(idx, 'utf8'); | |
const parts = src.split(/^---\s*$/m); | |
if (parts.length >= 3) { | |
parts[1] += `\npr: ${pr.number}\npr_url: ${pr.html_url}\npr_updated_at: ${pr.updated_at}\n`; | |
fs.writeFileSync(idx, parts.join('---\n')); | |
} | |
} | |
overlayCount++; | |
} | |
} | |
core.setOutput('overlay_count', String(overlayCount)); | |
# ---------- Build Jekyll locally ---------- | |
- name: Set up Ruby for Jekyll | |
uses: ruby/setup-ruby@v1 | |
with: | |
ruby-version: '3.2' | |
bundler-cache: true | |
working-directory: /tmp/site | |
- name: Install Jekyll (if no Gemfile) | |
run: | | |
set -e | |
cd /tmp/site | |
if [ ! -f Gemfile ]; then | |
gem install jekyll -N | |
fi | |
- name: Build Jekyll site | |
env: | |
JEKYLL_ENV: production | |
run: | | |
set -e | |
cd /tmp/site | |
if [ -f Gemfile ]; then | |
bundle exec jekyll build --trace | |
else | |
jekyll build --trace | |
fi | |
test -d /tmp/site/_site | |
# ---------- Deploy to GitHub Pages via Actions ---------- | |
- name: Configure Pages | |
if: ${{ github.event_name == 'push' || github.event_name == 'workflow_dispatch' }} | |
uses: actions/configure-pages@v5 | |
- name: Upload site artifact | |
if: ${{ github.event_name == 'push' || github.event_name == 'workflow_dispatch' }} | |
uses: actions/upload-pages-artifact@v3 | |
with: | |
path: /tmp/site/_site | |
- name: Deploy to Pages | |
if: ${{ github.event_name == 'push' || github.event_name == 'workflow_dispatch' }} | |
id: deploy | |
uses: actions/deploy-pages@v4 | |
with: | |
preview: ${{ inputs.force_deploy || false }} |