Catch the deterministic CI failures reachable from your diff before pushing, with `hogli ci:preflight`. Use when the pre-push hook blocks a push, before reporting a task done, or after editing Python, serializers, migrations, workflows, or dependency manifests — to avoid burning a CI matrix on a failure you could catch locally (formatting, lint, broken lockfiles, OpenAPI drift, migration conflict, stale branch). Trigger terms: ci:preflight, preflight, pre-push checks, pre-push hook failed, "w...
40,048 stars
0 votes
0 copies
3 views
Added September 1, 2026
developmentpythonnodegitapi
Works with
cli
api
Security analysis
A92/100
mediumInstalls packages at runtime which could introduce malicious dependencies
Installs into .claude/skills of the current project.
Are you the author of Running Ci Preflight?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/posthog-running-ci-preflight-posthog)
---
name: running-ci-preflight
description: >
Catch the deterministic CI failures reachable from your diff before pushing, with `hogli ci:preflight`.
Use when the pre-push hook blocks a push, before reporting a task done, or after editing Python,
serializers, migrations, workflows, or dependency manifests — to avoid burning a CI matrix on a failure
you could catch locally (formatting, lint, broken lockfiles, OpenAPI drift, migration conflict, stale branch).
Trigger terms: ci:preflight, preflight, pre-push checks, pre-push hook failed, "will this break CI".
---
# Running ci:preflight
`hogli ci:preflight` scopes a curated set of checks to the files your branch touched — each mapped to a
CI failure class that has taken master down — plus an always-on branch-freshness check. It is the
pre-push counterpart to `hogli ci:insights` (what is _already_ broken on master).
The pre-push hook runs `ci:preflight --strict` automatically and blocks the push on failed checks.
**Never bypass it with `--no-verify`** — fix what it reports instead.
## The loop (when the hook blocks, or before reporting done)
```sh
hogli ci:preflight --fix
```
1. Run with `--fix` — it formats, lints, and auto-fixes what is safe.
2. Read each line: `✓ pass`, `✗ fail`, `⚠ warning` (non-blocking finding), `→ advisory` (do it yourself), `· skipped` (capability absent).
3. Resolve every `✗ fail` — these are what `--fix` could not (real lint error, broken lockfile, migration conflict). These block the push.
4. Act on every `→ advisory` — e.g. `openapi` advisory → run `hogli build:openapi` and commit the drift; `staleness` advisory → `git merge origin/master`. Advisories never block, but ignoring them ships the failure to CI. **Resolve them before pushing, including drift you didn't introduce — you own the branch state you push.**
5. Re-run until clean, then push.
## Notes
- **Strict = failures only.** `--strict` (what the hook runs) exits non-zero only on `✗ fail` — advisories are unverifiable-locally classes, so they warn without blocking. A clean exit means "nothing left to fix", not "CI will pass" — CI stays the authoritative gate. Non-blocking is a mechanism limit, not permission to skip.
- **`type-check` is a nudge, not a run.** Only a repo-wide mypy run matches CI (mypy follows imports, so a changed-file subset misses reverse-dependency breakage), and that costs minutes cold — too much to tax every push with. So preflight names the command instead of running it: judge whether your change is type-risky and run it yourself. CI blocks on the same command, so a type error you skip here comes back as a full re-run.
- **`complexity` warns only.** Cyclomatic complexity above 10 in a changed file shows as `⚠ warning` and never blocks; CI annotates the same warning and posts it to the CI report comment. Simplify the function when you next touch it rather than gaming the number.
- **Staleness is risk-based.** It fires when merging master _now_ would actually break something — textual merge conflicts (computed via `git merge-tree`, working tree untouched), migrations added on both sides, generated-file inputs changed on both sides, or CI workflows changed on master — plus a behind/age backstop, aggressive by default (5 commits / 2 days; env-tunable via `HOGLI_PREFLIGHT_STALE_COMMITS`/`HOGLI_PREFLIGHT_STALE_DAYS`) so we over-warn to start and tune down from telemetry. Merge master in when it fires. Advisory only, never auto-merged.
- **`· skipped (needs …)`** is expected on a bare checkout or sandbox. `needs stack`/`needs clickhouse` want a running dev stack (`hogli start`), `needs node` wants `pnpm install`, `needs desktop-node` wants `pnpm --dir products/desktop install` (the nested desktop workspace is excluded from the root install and has its own lockfile), and `needs python-env` wants `uv sync`, so the synced project environment is the `python` on PATH. Satisfy what you can, or let CI cover the rest. No hooks in your environment (no `node_modules`)? Run the loop yourself before pushing.
- **Flags.** `--against <ref>` diffs against an explicit base; `--json` emits a machine-readable summary.
- **Kill switch.** `HOGLI_PREFLIGHT_DISABLED=1` makes the command (and the hook) a no-op with exit 0. It is a rollout/emergency lever — respect it; never unset it to force a run.
## Why it matters
Drafts already run a trimmed CI subset; the expensive waste is a ready PR that fails the full matrix on
something deterministic, gets fixed, and re-runs the whole matrix. Catching that locally is the cheapest
CI saving available.