Skip to content

[codex] Allow leg splitting in edit modes #1989

[codex] Allow leg splitting in edit modes

[codex] Allow leg splitting in edit modes #1989

Workflow file for this run

name: CI
# Lint / static checks for the static web app. Enforces the rules
# AGENTS.md describes (node --check, JSON parse, consistent ?v=N) so
# PRs into main / dev can't ship broken JS or stale cache busts.
on:
pull_request:
branches: [main, dev]
push:
branches: [main, dev]
workflow_dispatch:
permissions:
contents: read
jobs:
dev-history:
if: github.event_name == 'push' && github.ref == 'refs/heads/dev'
runs-on: ubuntu-latest
timeout-minutes: 3
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Ensure dev received no merge commits
run: |
set -e
BEFORE="${{ github.event.before }}"
AFTER="${{ github.sha }}"
if [ "$BEFORE" = "0000000000000000000000000000000000000000" ]; then
RANGE="$AFTER"
else
RANGE="$BEFORE..$AFTER"
fi
COUNT=$(git rev-list --count "$RANGE")
# Reject real merge commits (squash-merge policy), but tolerate
# no-op merges — a "Merge branch 'main' into dev" whose tree is
# identical to its first parent brings no changes and is harmless
# (happens when main is already behind dev). Such a merge has an
# empty diff against its first parent.
BAD=""
for m in $(git rev-list --merges "$RANGE"); do
if ! git diff --quiet "$m^1" "$m"; then
BAD="$BAD $m"
fi
done
if [ -n "$BAD" ]; then
echo "❌ dev received a non-trivial merge commit. Use squash merge."
for m in $BAD; do git show -s --oneline "$m"; done
exit 1
fi
echo "✅ dev received $COUNT commit(s); any merges were no-ops."
lint:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Check PR is rebased
if: github.event_name == 'pull_request'
run: |
if ! git merge-base --is-ancestor ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }}; then
echo "❌ PR branch is not rebased on ${{ github.base_ref }}. Run 'git rebase origin/${{ github.base_ref }}' and push."
exit 1
fi
echo "✅ PR is rebased on ${{ github.base_ref }}"
- name: Set up Node
uses: actions/setup-node@v6
with:
node-version: 22
cache: npm
- name: Install npm dependencies
run: npm ci
- name: JS syntax check (node --check)
run: |
set -e
for f in docs/app/core.js docs/app/draw.js docs/app/interact.js docs/app/io.js docs/app/ui.js docs/sw.js docs/i18n/he/strings.js docs/i18n/en/strings.js; do
echo "node --check $f"
node --check "$f"
done
- name: JSON validation
run: |
set -e
for f in docs/manifest.json docs/data/nav-waypoints.json; do
echo "validating $f"
node -e "JSON.parse(require('fs').readFileSync('$f','utf8'));"
done
- name: XML validation (sitemap.xml, BingSiteAuth.xml)
run: |
set -e
python3 -c "import xml.etree.ElementTree as ET; ET.parse('docs/sitemap.xml'); print('sitemap.xml ok')"
python3 -c "import xml.etree.ElementTree as ET; ET.parse('docs/BingSiteAuth.xml'); print('BingSiteAuth.xml ok')"
- name: HTML well-formedness (html-validate)
run: npx --yes html-validate@8 --formatter=stylish docs/index.html docs/en/index.html docs/he/index.html
- name: Cache-bust consistency (?v= in docs/index.html)
run: |
# Source HTML may carry a placeholder integer (e.g. ?v=134) or a
# short commit SHA (e.g. ?v=abc1234) — Deploy rewrites it at upload
# time. Either form is fine here; all values just have to agree so
# nobody accidentally leaves one stale.
vs=$(grep -oE '\?v=[A-Za-z0-9]+' docs/index.html | sort -u)
n=$(printf "%s\n" "$vs" | wc -l | tr -d ' ')
if [ "$n" -gt 1 ]; then
echo "Inconsistent ?v= values in docs/index.html:"
printf "%s\n" "$vs"
exit 1
fi
echo "cache-bust ok: $vs"
- name: Service worker cache name sanity (docs/sw.js)
run: |
if ! grep -qE "^const CACHE = 'navaid-v[0-9]+';" docs/sw.js; then
echo "docs/sw.js is missing the expected 'const CACHE = \"navaid-vN\"' constant."
echo "Found:"
grep -nE "CACHE" docs/sw.js || true
exit 1
fi
line=$(grep -E "^const CACHE = 'navaid-v[0-9]+';" docs/sw.js)
echo "sw cache ok: $line"
- name: Spell check (English + Hebrew)
run: npm run lint:spell
e2e:
runs-on: ubuntu-latest
timeout-minutes: 10
needs: lint
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Check PR is rebased
if: github.event_name == 'pull_request'
run: |
if ! git merge-base --is-ancestor ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }}; then
echo "❌ PR branch is not rebased on ${{ github.base_ref }}. Run 'git rebase origin/${{ github.base_ref }}' and push."
exit 1
fi
echo "✅ PR is rebased on ${{ github.base_ref }}"
- name: Set up Node
uses: actions/setup-node@v6
with:
node-version: 22
cache: npm
- name: Install npm dependencies
run: npm ci
- name: Cache Playwright browsers
uses: actions/cache@v4
with:
path: ~/.cache/ms-playwright
key: playwright-${{ runner.os }}-${{ hashFiles('package-lock.json') }}
restore-keys: |
playwright-${{ runner.os }}-
- name: Install Playwright browsers
run: npx playwright install --with-deps chromium
- name: Start local server and run tests
run: |
python3 -m http.server -d docs 8000 --bind 127.0.0.1 & SERVER=$!
# Run tests against local server
BASE_URL="http://127.0.0.1:8000" npm test
EXIT=$?
kill $SERVER 2>/dev/null
exit $EXIT
- name: Upload Playwright report
if: always()
uses: actions/upload-artifact@v4
with:
name: playwright-report
path: |
playwright-report/
test-results/
retention-days: 7