From b20738ab1976367252b4927399a145c631d0d970 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 28 Oct 2026 10:40:54 +0000 Subject: [PATCH] ci: fail a pull request that starts before the latest release MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A pull request made from an old main undoes what was fixed since and conflicts (strata#60 started 32 commits back, before 0.7.0). The new `base` job checks out the branch as pushed, not the merge GitHub prepares, and fails when it does not include the latest v… tag of the base branch, with the commands to update it. A branch a few commits behind only gets a notice. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Ke7yEW5dhDYFVpV2cdgs87 Signed-off-by: Claude --- .github/workflows/ci.yml | 24 ++++++++++++++++++++++++ README.md | 2 ++ 2 files changed, 26 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b0ea5e0..9ca3388 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,6 +9,30 @@ permissions: contents: read jobs: + # A pull request must include the latest release of its base branch. One made from an old main undoes what + # was fixed since, and conflicts. Lagging a few commits behind is fine: it only gets a notice. + base: + if: github.event_name == 'pull_request' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + # the branch as pushed, not the merge GitHub prepares (that one always contains the base branch) + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 0 + - name: The branch includes the latest release + env: + BASE: ${{ github.event.pull_request.base.ref }} + run: | + git fetch --quiet origin "+refs/heads/$BASE:refs/remotes/origin/$BASE" '+refs/tags/*:refs/tags/*' + behind=$(git rev-list --count HEAD..origin/$BASE) + tag=$(git tag --merged origin/$BASE --list 'v[0-9]*.[0-9]*.[0-9]*' --sort=-v:refname | head -n 1) + if [ -n "$tag" ] && ! git merge-base --is-ancestor "$tag" HEAD; then + echo "::error::This branch starts before $tag: it is $behind commits behind $BASE. Update it from $BASE (git fetch upstream && git rebase upstream/$BASE, or git merge upstream/$BASE), then push again." + exit 1 + fi + if [ "$behind" -gt 0 ]; then echo "::notice::This branch includes $tag but is $behind commits behind $BASE."; else echo "Up to date with $BASE."; fi + test: runs-on: ubuntu-latest strategy: diff --git a/README.md b/README.md index 193967d..cba8c7f 100644 --- a/README.md +++ b/README.md @@ -592,6 +592,8 @@ The tests start a real server on a temporary data folder, create one account per The `CI` workflow runs them on Node 20 and 22 on every push to `main` and every pull request. A change that touches the API must come with a test. +A pull request must start from the latest release or later: the `base` job fails when the branch does not include the latest `v…` tag of `main`, and says how to update it (rebase or merge `main`). A few commits behind `main` only gets a notice. + `npm run test:e2e` walks through the interface in Chromium with Playwright (`tests/e2e.mjs`): an admin loads the demo and sees the 3D model and the 2D diagram, a contributor proposes a change, an approver sees it highlighted and approves it. Any JavaScript error in a page fails it. The first time, install the browser with `npx playwright install chromium`. The `CI` workflow runs it too (`e2e` job). A change to the interface must keep it green. ### Releasing