mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-28 11:32:22 +00:00
ci: run only the lanes a PR affects (python/frontend/site)
Heavy PR checks run on every PR because the workflows deliberately avoid `on.paths` filters — a path-gated workflow leaves its required check pending forever when no matching file changes, blocking merge. So a docs-only PR still spins up the TypeScript matrix, the full Python suite, and ruff/ty. Keep every workflow triggering on every PR (checks always report) but gate the expensive *steps* on what the PR touches. Skipping a step (not the job) leaves the job green, so required checks never hang — the same idiom already proven in contributor-check.yml. A classifier (scripts/ci/classify_changes.py) maps the PR diff to three lanes — python, frontend, site — surfaced as step outputs by a composite action (.github/actions/detect-changes). Fail-open: an empty diff or any .github/ change runs everything; python is a denylist (skipped only when every file is provably prose or a frontend-only package); skills/**/SKILL.md counts as python-relevant since the skill-doc tests read that tree. Non-PR events always run the full pipeline.
This commit is contained in:
parent
351afd353d
commit
45540cfb5e
7 changed files with 272 additions and 5 deletions
48
.github/actions/detect-changes/action.yml
vendored
Normal file
48
.github/actions/detect-changes/action.yml
vendored
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
name: Detect affected areas
|
||||
description: >-
|
||||
Classify a PR's changed files into CI work categories (python, frontend,
|
||||
site) so heavy jobs can skip work they cannot be affected by. Outputs are
|
||||
always "true" on push/dispatch events and fail open (everything "true") when
|
||||
the diff cannot be computed — a skipped category must never be a false
|
||||
negative.
|
||||
|
||||
# The caller must check out the repo with `fetch-depth: 0` BEFORE using this
|
||||
# action, so both the PR base and head commits are present for `git diff`.
|
||||
|
||||
outputs:
|
||||
python:
|
||||
description: Run Python tests / ruff / ty / windows-footguns.
|
||||
value: ${{ steps.classify.outputs.python }}
|
||||
frontend:
|
||||
description: Run the TypeScript typecheck matrix + desktop build.
|
||||
value: ${{ steps.classify.outputs.frontend }}
|
||||
site:
|
||||
description: Build the Docusaurus docs site.
|
||||
value: ${{ steps.classify.outputs.site }}
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Classify changed files
|
||||
id: classify
|
||||
shell: bash
|
||||
env:
|
||||
EVENT_NAME: ${{ github.event_name }}
|
||||
BASE_SHA: ${{ github.event.pull_request.base.sha }}
|
||||
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# Only pull_request events are gated. Other events (push, release,
|
||||
# dispatch) leave CHANGED empty, so the classifier fails open and every
|
||||
# lane runs — post-merge / on-demand validation is never weakened.
|
||||
if [ "$EVENT_NAME" = "pull_request" ]; then
|
||||
# Three-dot diff = what the PR introduces vs its merge base, matching
|
||||
# how a reviewer reads it. An uncomputable diff (shallow clone, etc.)
|
||||
# yields an empty list, which the classifier also fails open on.
|
||||
CHANGED="$(git diff --name-only "${BASE_SHA}...${HEAD_SHA}" || true)"
|
||||
fi
|
||||
echo "Changed files:"
|
||||
printf '%s\n' "${CHANGED:-(none)}"
|
||||
# Caller already checked out the repo, so the classifier is at its
|
||||
# repo-relative path. It is the single source of the fail-open default.
|
||||
printf '%s\n' "${CHANGED:-}" | python3 scripts/ci/classify_changes.py
|
||||
Loading…
Add table
Add a link
Reference in a new issue