Skip to content

feat(026): year-aware NeuroScape backdrop density (compressed-proportional per-year sampling) #302

feat(026): year-aware NeuroScape backdrop density (compressed-proportional per-year sampling)

feat(026): year-aware NeuroScape backdrop density (compressed-proportional per-year sampling) #302

Workflow file for this run

name: pr-preview
# Stage 15 (spec 015-neuroscape-context, T049): mirrors the
# multi-mode build in `deploy-ui.yml`. Each PR preview produces
# three per-mode bundles under `/pr-<N>/`:
# • atlas-root → `/pr-<N>/` (cross-conference landing page)
# • ohbm2026 → `/pr-<N>/ohbm2026/` (existing OHBM 2026 site)
# • neuroscape → `/pr-<N>/neuroscape/` (NeuroScape PubMed subsite)
on:
pull_request:
types: [opened, synchronize, reopened]
paths:
- 'site/**'
- '.github/workflows/pr-preview.yml'
- 'specs/008-ui-rewrite/contracts/references.yaml'
- 'src/ohbm2026/ui_data/link_check.py'
workflow_dispatch:
permissions:
contents: write
pages: write
deployments: write
pull-requests: read
concurrency:
group: deploy-ui-preview-pr-${{ github.event.pull_request.number }}
cancel-in-progress: true
jobs:
preview:
runs-on: ubuntu-latest
if: github.event.pull_request.head.repo.full_name == github.repository
environment:
name: pr-preview-${{ github.event.pull_request.number }}
# The environment URL points at the bare-root cross-conference
# landing page now that atlas-root is the root. The two sibling
# subsites are reachable from the landing page's outbound
# header links (LandingPageHeader).
url: https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/pr-${{ github.event.pull_request.number }}/
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Node 20 + pnpm
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Enable pnpm
run: npm install --global pnpm@10
- name: Install site deps
working-directory: site
run: pnpm install --frozen-lockfile
- name: Run JS unit tests (Vitest)
working-directory: site
run: pnpm test:unit --run
- name: Set up Python 3.14
uses: actions/setup-python@v5
with:
python-version: '3.14'
- name: Install link-check deps
run: pip install requests pyyaml
- name: References link check (FR-017)
# Same check that gates the production deploy in deploy-ui.yml —
# mirrored here so PR previews surface a broken reference BEFORE
# the merge instead of failing at deploy time.
run: PYTHONPATH=src python -m ohbm2026.ui_data.link_check specs/008-ui-rewrite/contracts/references.yaml
# Resolve the parquet URLs from the keyed registry variable, using the
# channel this PR branch declares in site/data-channel.json. A PR can
# point its preview at a different data set (a new channel key) without
# touching production's — they no longer share flat URL vars.
# See .github/scripts/resolve-data-channel.sh.
- name: Resolve data-package URLs from channel registry
env:
DATA_URLS_REGISTRY: ${{ vars.OHBM2026_UI_DATA_PACKAGE_URLS }}
run: .github/scripts/resolve-data-channel.sh
- name: Build all three SITE_MODE bundles (T049)
working-directory: site
env:
BASE_PATH_ROOT: /pr-${{ github.event.pull_request.number }}
STAGE_ROOT_RELATIVE: site/publish
VITE_BUILD_SHA: ${{ github.event.pull_request.head.sha }}
VITE_BUILD_AT: ${{ github.event.pull_request.head.repo.pushed_at }}
# VITE_DATA_PACKAGE_URL_{OHBM2026,NEUROSCAPE,ATLAS,NEUROSCAPE_VECTORS}
# are exported to $GITHUB_ENV by the "Resolve data-package URLs"
# step above (keyed registry → channel from site/data-channel.json).
run: |
set -euo pipefail
export VITE_BUILD_SHA_SHORT="${VITE_BUILD_SHA:0:7}"
STAGE_ROOT="../${STAGE_ROOT_RELATIVE}"
rm -rf "$STAGE_ROOT"
build_mode() {
local mode="$1"
local base_path="$2"
local dest="$3"
echo "::group::Build SITE_MODE=$mode BASE_PATH=$base_path → $dest"
rm -rf build .svelte-kit/output
VITE_SITE_MODE="$mode" BASE_PATH="$base_path" pnpm build
mkdir -p "$dest"
cp -r build/. "$dest/"
echo "::endgroup::"
}
build_mode atlas-root "$BASE_PATH_ROOT" "$STAGE_ROOT"
build_mode ohbm2026 "$BASE_PATH_ROOT/ohbm2026" "$STAGE_ROOT/ohbm2026"
build_mode neuroscape "$BASE_PATH_ROOT/neuroscape" "$STAGE_ROOT/neuroscape"
# Stage 15 — gh-pages serves the PR-root 404.html (the first
# one found walking up from the requested path) for any
# unresolved path under /pr-N/. The atlas-root build's
# SvelteKit-generated 404.html only handles atlas-root home
# routes; a deep link like
# /pr-N/neuroscape/abstract/<pubmed_id>/ would 404 into the
# atlas-root SPA shell and lose its target. Overwrite with
# the multi-mode-aware redirect shim from
# conference-root-redirect/404.html, which bounces each
# mode's deep link to that mode's own SPA via
# ?spa=<original-path>.
cp conference-root-redirect/404.html "$STAGE_ROOT/404.html"
echo "404 redirect shim installed at $STAGE_ROOT/404.html ($(wc -c < "$STAGE_ROOT/404.html") bytes)"
- name: Publish to gh-pages /pr-${{ github.event.pull_request.number }}
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: site/publish
publish_branch: gh-pages
destination_dir: pr-${{ github.event.pull_request.number }}
keep_files: false
enable_jekyll: false
commit_message: 'preview(ui): pr-${{ github.event.pull_request.number }} ${{ github.sha }}'