Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions .depot/workflows/ci-backend.yml
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,11 @@ on:
# Draft PRs run the snob-selected Django subset (≤3 shards); turbo-tests
# still skip drafts. Ready PRs run the full matrices — the merge gate —
# and ready_for_review re-triggers them when a PR leaves draft. Add the
# `run-ci-backend` label (labeled/unlabeled re-trigger) to force the full
# matrices on a draft; the `no-ci` label silences the workflow on a draft
# entirely. Mirrors canonical.
types: [opened, synchronize, reopened, ready_for_review, labeled, unlabeled]
# `run-ci-backend` label to force the full matrices on a draft; the
# `no-ci` label silences the workflow on a draft entirely. No
# labeled/unlabeled triggers, so a label takes effect from the next push
# or from ready_for_review. Mirrors canonical.
types: [opened, synchronize, reopened, ready_for_review]
concurrency:
# PRs: one active run per branch, cancel stale. Push: per-SHA so master
# pushes never cancel each other (check-migrations always completes).
Expand Down
6 changes: 6 additions & 0 deletions .github/workflows/ci-agent-skills.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ jobs:
- 'products/posthog_ai/**'
- '.github/workflows/ci-agent-skills.yml'
- 'services/mcp/schema/**'
# check-skills zips products/*/skills/* via `hogli build:skills`
# (see build.py's affected-path map), so posthog_ai's frontend
# can't affect it. Scoped to posthog_ai, not
# 'products/*/frontend/**', so a future deliberate frontend
# include here isn't silently vetoed.
- '!products/posthog_ai/frontend/**'

check-skills:
name: Check agent skills
Expand Down
12 changes: 7 additions & 5 deletions .github/workflows/ci-backend.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,17 @@ on:
# turbo-tests (product tests) still skip drafts. Ready PRs run the full
# matrices — that full run is the merge gate, and ready_for_review re-triggers
# it when a PR leaves draft. To force the full matrices on a draft, add the
# `run-ci-backend` label — labeled/unlabeled re-trigger the run so the matrices
# start without needing a new push. Cheap checks still run on drafts.
# `run-ci-backend` label. Cheap checks still run on drafts.
# The `no-ci` label does the opposite: it silences this workflow on a draft
# entirely (prototypes/spikes), until the label is removed or the PR is
# marked ready for review.
# entirely (prototypes/spikes).
# No labeled/unlabeled triggers: GitHub cannot filter a label trigger by name,
# so every unrelated label re-ran these matrices against a commit CI had
# already covered. A label here takes effect from the next push, or from
# ready_for_review.
# The `test-new-events-schema` label opts a PR into the doubled matrices that
# rerun everything with CLICKHOUSE_HOGQL_USE_NEW_EVENTS_SCHEMA=true; unlabeled
# PRs run legacy-schema only (master runs always cover both).
types: [opened, synchronize, reopened, ready_for_review, labeled, unlabeled]
types: [opened, synchronize, reopened, ready_for_review]

concurrency:
# PRs: one active run per branch, cancel stale. Push: per-SHA so master
Expand Down
15 changes: 15 additions & 0 deletions .github/workflows/ci-e2e-playwright.yml
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,21 @@ jobs:
# boot the whole stack.
- '!**/*.md'
- '!**/*.mdx'
# Same for Django's pytest modules: the suite drives the app through a
# browser and never loads them. Narrow on purpose:
# - modules, not whole test/ dirs: posthog/test/ also holds live
# server code, notably playwright_setup_functions.py, which
# posthog/urls.py serves at api/setup_test/.
# - no '*_test.py': under posthog/ that suffix names production code
# (ClickHouse migrations, ClickHouse UDF scripts), not tests.
# - per-tree prefixes, because an exclude is tested against every file
# the filter sees, not just the include it sits next to: a bare
# '!**/test_*.py' would also veto the include above for
# tools/test_playwright_spec_selection.py.
- '!posthog/**/test_*.py'
- '!posthog/**/conftest.py'
- '!ee/**/test_*.py'
- '!ee/**/conftest.py'

# Visual Review auto-commits a snapshot baseline after human review and CI
# approval. Re-running the ~25-min E2E stack for that bot push is pure waste;
Expand Down
12 changes: 7 additions & 5 deletions .github/workflows/ci-frontend.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ on:
# Draft PRs run a narrowed jest selection; ready PRs run the full matrix
# (the merge gate). ready_for_review re-triggers the full run on the
# current head when a PR leaves draft. To force the full matrix on a
# draft, add the `run-ci-frontend` label — labeled/unlabeled re-trigger
# the run so it starts without needing a new push. The `no-ci` label does
# the opposite: it silences this workflow on a draft entirely (prototypes),
# until the label is removed or the PR is marked ready for review.
types: [opened, synchronize, reopened, ready_for_review, labeled, unlabeled]
# draft, add the `run-ci-frontend` label. The `no-ci` label does the
# opposite: it silences this workflow on a draft entirely (prototypes).
# No labeled/unlabeled triggers: GitHub cannot filter a label trigger by
# name, so every unrelated label re-ran the full jest matrix against a
# commit CI had already covered. A label here takes effect from the next
# push, or from ready_for_review.
types: [opened, synchronize, reopened, ready_for_review]
push:
branches:
- master
Expand Down
36 changes: 29 additions & 7 deletions .github/workflows/ci-mcp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ on:
branches: [master]
pull_request:
# Draft PRs run build + unit tests only; the integration tests (which boot
# the full PostHog backend and trigger on any Python change) run when the
# PR is marked ready for review that full run is the merge gate.
# the full PostHog backend and trigger on any non-pytest Python change) run
# when the PR is marked ready for review; that full run is the merge gate.
# The `no-ci` label silences this workflow on a draft entirely (prototypes).
# No labeled/unlabeled triggers here, so it takes effect from the next push.
types: [opened, synchronize, reopened, ready_for_review]
Expand Down Expand Up @@ -43,8 +43,8 @@ jobs:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

# MCP integration tests boot the full PostHog backend (Django web server,
# Celery worker, migrations, demo data), so the filter mirrors the Dagster
# approach: trigger on any Python change across the app.
# Celery worker, migrations, demo data), so the filter stays broad: any
# non-pytest Python change across the app triggers it.
- uses: actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v3.1.1
id: app-token
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository
Expand Down Expand Up @@ -109,6 +109,28 @@ jobs:
# CI config
- '.github/workflows/ci-mcp.yml'
- '.github/workflows/mcp-publish.yml'
# The integration tests drive a running Django server over HTTP and
# never import pytest modules, so exclude them. Narrow on purpose:
# - modules, not whole test/ dirs: those also hold runtime code, such
# as posthog/test/base.py, which the backend boot imports via
# setup_test_environment.
# - '*_test.py' only under products/*/backend, where it is the
# colocated-test convention. Under posthog/ that suffix names
# production code this suite runs (ClickHouse migrations, UDF
# scripts copied into ClickHouse during setup).
# - per-tree prefixes, because an exclude is tested against every file
# the filter sees, not just the include it sits next to: a bare
# '!**/conftest.py' would also veto tools/hogli/tests/conftest.py,
# which the tools/hogli/** include above covers.
- '!posthog/**/test_*.py'
- '!posthog/**/conftest.py'
- '!ee/**/test_*.py'
- '!ee/**/conftest.py'
- '!common/**/test_*.py'
- '!common/**/conftest.py'
- '!products/*/backend/**/test_*.py'
- '!products/*/backend/**/*_test.py'
- '!products/*/backend/**/conftest.py'
build:
name: Build Package
runs-on: ubuntu-latest
Expand Down Expand Up @@ -253,9 +275,9 @@ jobs:
needs: changes
timeout-minutes: 30
# Skipped on drafts: these boot the full PostHog backend and trigger on any
# Python change, so they're the expensive half of this workflow. Build and
# unit tests still run on drafts; the `MCP Tests Pass` aggregator treats
# skipped as success, and the ready-for-review run is the merge gate.
# non-pytest Python change, so they're the expensive half of this workflow.
# Build and unit tests still run on drafts; the `MCP Tests Pass` aggregator
# treats skipped as success, and the ready-for-review run is the merge gate.
if: needs.changes.outputs.mcp == 'true' && (github.event.pull_request.draft != true || startsWith(github.head_ref, 'trunk-merge/'))
env:
DOCKERHUB_USERNAME: ${{ vars.DOCKERHUB_USER }}
Expand Down
5 changes: 4 additions & 1 deletion .github/workflows/ci-nodejs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,11 @@ jobs:
- 'posthog/management/commands/setup_test_environment.py'
- 'posthog/migrations/**'
- 'posthog/plugins/**'
# Compose files only, no Dockerfile glob: these jobs run the suites from
# source via pnpm and the compose stack's only build contexts are rust/,
# so no app image is built here. Dockerfile.node is gated separately in
# ci-nodejs-container.yml.
- 'docker*.yml'
- '*Dockerfile'
rust:
- 'rust/**'
- 'proto/**'
Expand Down
12 changes: 7 additions & 5 deletions .github/workflows/ci-storybook.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ on:
# Draft PRs run a narrowed visual-regression matrix when the Storybook module
# graph can safely identify affected stories. Ready PRs run the full chromium
# matrix as the merge gate. To force the full matrix on a draft, add the
# `run-ci-frontend` label —
# labeled/unlabeled re-trigger the run so it starts without needing a push.
# The `no-ci` label does the opposite: it silences this workflow on a draft
# entirely (prototypes), until it is removed or the PR is marked ready.
types: [opened, synchronize, reopened, ready_for_review, labeled, unlabeled]
# `run-ci-frontend` label. The `no-ci` label does the opposite: it silences
# this workflow on a draft entirely (prototypes).
# No labeled/unlabeled triggers: GitHub cannot filter a label trigger by name,
# so every unrelated label re-ran the full chromium matrix against a commit CI
# had already covered. A label here takes effect from the next push, or from
# ready_for_review.
types: [opened, synchronize, reopened, ready_for_review]
push:
branches:
- master
Expand Down
14 changes: 14 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,20 @@ NEVER share sensitive information in a PR description. Users may share sensitive
Once a branch already has an open PR, push incremental changes and fixes to it without waiting for human guidance — keeping the PR current is part of the work.
Pushes still trigger CI, which burns runner credits, so batch related commits and push once the increment is ready rather than after every change.

#### Forcing the full CI matrix on a draft

Draft PRs run a narrowed matrix.
The `run-ci-backend` and `run-ci-frontend` labels force the full one, but a label alone starts nothing: it takes effect on the next push, or when the PR is marked ready for review.
An empty commit is enough.

```bash
git commit --allow-empty -m "chore(ci): run the full matrix" && git push
```

Do not add `labeled`/`unlabeled` back to a merge gate's `on.pull_request.types` to avoid that push.
GitHub cannot filter a label trigger by name, so every unrelated label re-runs the full matrices against a commit CI has already covered.
Guarding it inside the workflow is worse: skipping the gate job cascades to the `if: always()` aggregator, which counts a skipped dependency as success and posts a green required check with no tests behind it.

#### Stacked PRs

Restacking force-pushes every branch, and each push triggers a full CI fan-out.
Expand Down
Loading