mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-10-28 06:22:22 +00:00
* chore(deps): consolidate Dependabot GitHub Actions updates * chore(deps): consolidate web updates and secure transitive dependencies * fix(web): preserve diagram appearance with Mermaid 12 * test(ci): align workflow security tests with updated action pins * fix(ci): split coverage across eight shards to avoid job timeout CI run 38693066214 cancelled Ubuntu coverage shard 1 after 25 minutes while tests were still passing. The missing coverage blob then caused the execution audit and CI gate to fail. Increase only the coverage shard count from four to eight. Keep the timeout, full suite, coverage thresholds, and execution audit intact. Validation: all 1,247 test files form a complete, disjoint eight-shard partition using the configured Vitest sequencer; 117 targeted tests passed (2 existing skips); workflow generator, Prettier, concurrency validation, and diff checks passed. * fix(ci): leave headroom for Windows test shards Run 38697469283 exhausted the 20-minute Windows watchdog. Use ten platform shards while retaining eight coverage shards and all existing timeouts, coverage gates, and execution audits. The accompanying timing refresh and recorded-profile regression keep all 145 platform-sensitive test files covered exactly once. * fix(ci): refresh underestimated Windows suite timings Refresh eight materially underestimated timing weights using Windows runs 38697469283 and 38693066214. The old partition placed native suites ahead of cli-e2e with insufficient time left under the watchdog. Keep every suite and the partitioning algorithm unchanged. * test(ci): replay the Windows timeout workload Add a deterministic regression from recorded Windows CI timings, independent of the scheduling table. It failed before the fix with a 1,426-second shard and now protects three minutes of watchdog headroom. Validation: 118 targeted tests passed (2 existing skips); typecheck, formatting, workflow generation, concurrency and diff checks passed. Independent review found no actionable issues. All 145 platform test files are selected exactly once; replaying the complete observed profile gives a 973-second maximum across ten shards. Hosted CI remains the final elapsed-time check.
146 lines
6.4 KiB
YAML
146 lines
6.4 KiB
YAML
name: PR Autofix
|
|
|
|
# UNTRUSTED HALF of the autofix pipeline.
|
|
#
|
|
# Runs `npm run lint:fix` + `npm run format` against the PR head
|
|
# (including fork heads) and uploads the resulting diff as an artifact.
|
|
# This job has NO privileged token and CANNOT post to the PR. The trusted
|
|
# `pr-autofix-publish.yml` workflow downloads the artifact via
|
|
# `workflow_run` and posts a sticky summary comment + Check Run.
|
|
# Contributors apply the patch by commenting `/autofix` on the PR —
|
|
# handled by the separate `pr-autofix-apply.yml` ChatOps workflow.
|
|
#
|
|
# Why the split:
|
|
# ESLint loads plugins from fork-controlled `node_modules`, so running
|
|
# it in a job with `pull-requests: write` would let a malicious fork PR
|
|
# ship a poisoned eslint plugin and execute arbitrary code under that
|
|
# token. By keeping fork code execution in this job (token: read-only)
|
|
# and posting from a separate trusted job that never touches fork
|
|
# code, we get the autofix UX for fork PRs without the supply-chain
|
|
# hole. (See autofix.ci for the same pattern.)
|
|
#
|
|
# Removes unused imports via `eslint-plugin-unused-imports`, already in
|
|
# devDependencies and wired into the `lint` config.
|
|
|
|
on:
|
|
pull_request:
|
|
types: [opened, synchronize, reopened]
|
|
# Skip lockfile / generated-file PRs entirely — `action-suggester`
|
|
# cannot post on diffs > ~3k lines (GitHub returns 406) and these
|
|
# paths produce massive diffs no human wants suggested back inline.
|
|
paths-ignore:
|
|
- '**/package-lock.json'
|
|
- '**/*.snap'
|
|
- '**/dist/**'
|
|
- '**/node_modules/**'
|
|
|
|
concurrency:
|
|
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
|
|
# Don't cancel in-flight runs; the publish workflow may already be
|
|
# downloading the artifact and a cancelled untrusted run produces no
|
|
# signal at all (worse DX than waiting).
|
|
cancel-in-progress: false
|
|
|
|
# This workflow runs untrusted fork code. Top-level deny-all and NO
|
|
# job-level grants — the job can only read its own checkout.
|
|
permissions: {}
|
|
|
|
jobs:
|
|
autofix:
|
|
name: autofix
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 10
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
with:
|
|
# PR head commit (not the synthetic merge ref) — we need the
|
|
# exact tree the contributor pushed so suggestions line up.
|
|
ref: ${{ github.event.pull_request.head.sha }}
|
|
repository: ${{ github.event.pull_request.head.repo.full_name }}
|
|
persist-credentials: false
|
|
|
|
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
|
with:
|
|
node-version: 22
|
|
cache: npm
|
|
cache-dependency-path: package-lock.json
|
|
|
|
# `--ignore-scripts` blocks pre/postinstall lifecycle hooks. ESLint
|
|
# plugins still load from node_modules (that is the actual escape
|
|
# hatch on a typical fork), but this job has no token to abuse —
|
|
# which is the whole point of the split.
|
|
- run: npm ci --ignore-scripts
|
|
|
|
- name: ESLint --fix (removes unused imports)
|
|
run: npm run lint:fix
|
|
# Lint errors that --fix can't auto-resolve must not block the
|
|
# diff artifact — partial fixes are still useful as suggestions.
|
|
continue-on-error: true
|
|
|
|
- name: Prettier --write
|
|
run: npm run format
|
|
continue-on-error: true
|
|
|
|
- name: Capture diff and metadata
|
|
id: capture
|
|
# Pass GitHub-context values via env: rather than `${{ }}`
|
|
# interpolated directly into the bash body. `head.ref` and
|
|
# `head.repo.full_name` are fork-controlled strings; expanding
|
|
# them into shell source is the canonical template-injection
|
|
# vector zizmor flags. Even though this job has `permissions: {}`,
|
|
# routing through env: makes it impossible for a future scope
|
|
# grant to turn into RCE. Inside bash, reference as `$HEAD_REF`
|
|
# etc. — the values are then plain strings, not code.
|
|
env:
|
|
PR_NUMBER: ${{ github.event.pull_request.number }}
|
|
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
|
HEAD_REF: ${{ github.event.pull_request.head.ref }}
|
|
HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }}
|
|
BASE_REPO: ${{ github.repository }}
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
mkdir -p autofix-out
|
|
|
|
# Produce a unified diff of the working tree vs. the PR head.
|
|
# Empty diff => nothing to suggest; the publish job short-circuits.
|
|
git diff --no-color > autofix-out/autofix.patch
|
|
|
|
# NOTE: `changed_lines` is the line-count of the patch file,
|
|
# (hunk headers + context lines + added/removed). Surfaced in
|
|
# the sticky comment so contributors and AI agents have a
|
|
# quick size hint before invoking `/autofix`.
|
|
changed_lines=$(wc -l < autofix-out/autofix.patch | tr -d ' ')
|
|
echo "changed_lines=${changed_lines}" >> "$GITHUB_OUTPUT"
|
|
|
|
# Carry PR identity over to the trusted job. workflow_run
|
|
# context is base-repo-only, so the publish job needs these
|
|
# to call the GitHub PR API on the right resource.
|
|
# CONTRACT: keep this schema in sync with pr-autofix-publish.yml's
|
|
# `assert_field` validators and the agent-facing JSON block in
|
|
# the sticky comment. Bump `schema` when changing field names.
|
|
jq -n \
|
|
--arg schema 'gitnexus.pr-autofix/v1' \
|
|
--argjson pr_number "${PR_NUMBER}" \
|
|
--arg head_sha "${HEAD_SHA}" \
|
|
--arg head_ref "${HEAD_REF}" \
|
|
--arg head_repo "${HEAD_REPO}" \
|
|
--arg base_repo "${BASE_REPO}" \
|
|
--argjson changed_lines "${changed_lines}" \
|
|
'{schema:$schema, pr_number:$pr_number, head_sha:$head_sha, head_ref:$head_ref, head_repo:$head_repo, base_repo:$base_repo, changed_lines:$changed_lines}' \
|
|
> autofix-out/metadata.json
|
|
|
|
echo "--- metadata ---"
|
|
cat autofix-out/metadata.json
|
|
echo "--- diff (head) ---"
|
|
head -c 2000 autofix-out/autofix.patch || true
|
|
|
|
# Pinned to v7.0.1. Verify SHA via:
|
|
# gh api repos/actions/upload-artifact/git/refs/tags/v7.0.1
|
|
- name: Upload autofix artifact
|
|
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
|
with:
|
|
name: autofix
|
|
path: autofix-out/
|
|
retention-days: 1
|
|
if-no-files-found: error
|