Skip to content

dev-tooling

dev-tooling #103

Workflow file for this run

name: dev-tooling
# Shape+flow analyzer gate (pyright + semgrep) — ADVISORY in CI, matching the testbed's
# "all test workflows advisory; informative red without gating merges" philosophy. The
# hard zero-FP gate lives in pre-commit (agent-work/dev-tooling/.pre-commit-config.experiment.yaml),
# which runs locally on your own commits. CodeQL is a separate, disabled job (NOTES_codeql.md):
# add it only once the in-editor tools are tuned and a residual flow class remains.
#
# Cross-repo: these analyzers target the gramps SOURCE, not the testbed. We check out the
# sibling gramps fork at ../gramps so the include paths resolve, mirroring the local
# four-sibling workspace layout. Repo/ref resolution matches the other test workflows:
# workflow_dispatch input -> repository variable -> same-owner default.
on:
push:
branches: [main]
pull_request:
schedule:
- cron: "0 5 * * 1" # weekly, Monday 05:00 UTC — matches the cron cadence of the suite
workflow_dispatch:
inputs:
gramps_repo:
description: "owner/repo of the gramps fork to analyze"
required: false
gramps_ref:
description: "branch/tag/SHA of the gramps fork to analyze"
required: false
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
jobs:
shape-and-flow:
runs-on: ubuntu-24.04
# Cap a hung analyzer (pyright/semgrep can spin on a pathological input).
# The analyzers normally finish in a few minutes; 15 is generous.
timeout-minutes: 15
# ADVISORY at the JOB level — same pattern as unit-tests.yml / addon-unit-tests.yml.
# `continue-on-error` here makes the WORKFLOW conclusion stay green even when the
# JOB is red, so findings don't gate merges. The check-run / job conclusion still
# accurately reflects findings — pyright exits non-zero on type errors, semgrep is
# invoked with --error below so it exits non-zero on rule matches.
#
# Putting `continue-on-error` at the STEP level (as this workflow originally did)
# was wrong: it made the step "succeed" regardless of findings, so the check-run
# went green even when 39 None-flow errors were live in gramps. Findings were
# silently invisible. The job-level placement matches the convention the testbed
# already uses elsewhere.
continue-on-error: true
steps:
- name: Checkout testbed
uses: actions/checkout@v4
with:
path: gramps-testbed
# Resolve gramps repo/ref: input -> repository variable -> same-owner default.
- name: Resolve gramps source
id: src
run: |
repo="${{ github.event.inputs.gramps_repo }}"
ref="${{ github.event.inputs.gramps_ref }}"
repo="${repo:-${{ vars.GRAMPS_REPO }}}"
ref="${ref:-${{ vars.GRAMPS_REF }}}"
repo="${repo:-${{ github.repository_owner }}/gramps}"
# gramps61: this job is core-defect analysis (pyright/semgrep over
# gramps core source); its findings become CORE PRs, which target
# maintenance/gramps61. So it analyzes the branch core fixes land
# on — distinct from the addon-conformance jobs (which pair gramps60
# addons against gramps61 core). Analyzing gramps60 here would flag
# against code the fixes won't be written on.
ref="${ref:-maintenance/gramps61}"
echo "repo=$repo" >> "$GITHUB_OUTPUT"
echo "ref=$ref" >> "$GITHUB_OUTPUT"
echo "Analyzing $repo @ $ref"
- name: Checkout gramps fork (sibling)
uses: actions/checkout@v4
with:
repository: ${{ steps.src.outputs.repo }}
ref: ${{ steps.src.outputs.ref }}
path: gramps
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.13"
- name: Install analyzers
run: pip install --break-system-packages pyright semgrep
# Both analyzers exit non-zero on findings — pyright by default, semgrep via
# --error (without it, semgrep exits 0 regardless of matches). The job-level
# continue-on-error: true above keeps the workflow green; the job/check-run
# accurately reflects whether findings exist. Hard zero-FP blocking lives in
# pre-commit (.pre-commit-config.experiment.yaml), local.
- name: pyright (scoped None-flow)
id: pyright
working-directory: gramps-testbed
run: pyright --project agent-work/dev-tooling/pyright/pyrightconfig.experiment.json
- name: semgrep (gramps shape patterns)
id: semgrep
working-directory: gramps-testbed
run: semgrep --error --config agent-work/dev-tooling/semgrep/rules/ ../gramps/gramps/gui/
# Rule self-test is NOT advisory: a rule that no longer pairs with its labeled
# fixtures is a tooling regression, not an informative finding about gramps. Fail.
- name: semgrep rule self-test
working-directory: gramps-testbed/agent-work/dev-tooling/semgrep
run: semgrep --test --config rules/ tests/
- name: Advisory summary
if: always()
run: |
{
echo "## dev-tooling analyzers (advisory)"
echo ""
echo "Source: \`${{ steps.src.outputs.repo }}\` @ \`${{ steps.src.outputs.ref }}\`"
echo ""
echo "| Analyzer | Result |"
echo "| --- | --- |"
echo "| pyright (None-flow) | ${{ steps.pyright.outcome }} |"
echo "| semgrep (shape) | ${{ steps.semgrep.outcome }} |"
echo ""
echo "_Advisory: findings do not gate merges. The hard zero-FP gate is pre-commit, local._"
} >> "$GITHUB_STEP_SUMMARY"
# ---------------------------------------------------------------------------
# CodeQL — DISABLED until the residual flow class is reached (see NOTES_codeql.md).
# Owns ONLY path-sensitive flow pyright misses (e.g. 14177 init-order). Do not
# re-implement generic None-deref here. Uncomment + flip `if` when ready.
# ---------------------------------------------------------------------------
# codeql-residual-flow:
# if: false
# runs-on: ubuntu-24.04
# permissions:
# security-events: write
# steps:
# - uses: actions/checkout@v4
# with:
# repository: ${{ github.repository_owner }}/gramps
# ref: maintenance/gramps61 # core-analysis branch; see Resolve step
# - uses: github/codeql-action/init@v3
# with:
# languages: python
# # queries: ./agent-work/dev-tooling/codeql/queries # custom init-order query
# - uses: github/codeql-action/analyze@v3