Skip to content

test(worker): Tier-1 job integration round-trips (billing/deletion) — toward worker coverage floor #182

test(worker): Tier-1 job integration round-trips (billing/deletion) — toward worker coverage floor

test(worker): Tier-1 job integration round-trips (billing/deletion) — toward worker coverage floor #182

Workflow file for this run

name: CI
on:
push:
branches: [master]
# CI-minute savings (2026-05-21): skip CI on docs-only commits.
paths-ignore:
- '**.md'
- 'docs/**'
- 'CLAUDE.md'
- '.gitignore'
- 'LICENSE'
- 'BUGBASH-*/**'
pull_request:
branches: [master]
paths-ignore:
- '**.md'
- 'docs/**'
- 'CLAUDE.md'
- '.gitignore'
- 'LICENSE'
- 'BUGBASH-*/**'
concurrency:
# CI-minute savings (2026-05-21): cancel prior in-flight CI for the same
# branch/PR when a new commit lands.
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
# Stale-green guard. A PR can show a green CI run that was executed BEFORE a
# breaking commit landed on the base branch — merging it would ship a broken
# master. This job FAILS if the PR branch does not contain origin/<base> as
# an ancestor, forcing an "Update branch" before the PR can merge.
up-to-date-with-base:
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Fail if PR branch is behind its base branch
run: |
BASE="${{ github.event.pull_request.base.ref }}"
git fetch origin "${BASE}" --depth=1
if git merge-base --is-ancestor "origin/${BASE}" HEAD; then
echo "PR branch contains origin/${BASE} — up to date."
else
echo "::error::PR branch is behind origin/${BASE}. Update the branch (merge/rebase ${BASE}) and re-run CI so it validates against current base."
exit 1
fi
build-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Checkout proto sibling (replace ../proto)
uses: actions/checkout@v6
with:
repository: ${{ vars.PROTO_REPO || format('{0}/proto', github.repository_owner) }}
# REPO_ACCESS_TOKEN is a fine-grained PAT with read on the private
# sibling repos; GITHUB_TOKEN is scoped to THIS repo only and 404s.
token: ${{ secrets.REPO_ACCESS_TOKEN || secrets.GITHUB_TOKEN }}
path: _proto_ci
- run: mv _proto_ci ../proto
- name: Checkout common sibling (replace ../common)
uses: actions/checkout@v6
with:
repository: ${{ vars.COMMON_REPO || format('{0}/common', github.repository_owner) }}
token: ${{ secrets.REPO_ACCESS_TOKEN || secrets.GITHUB_TOKEN }}
path: _common_ci
- run: mv _common_ci ../common
# Cross-repo registry-iterating tests (CLAUDE.md rule 18) text-walk
# api/internal/models/audit_kinds.go and api/e2e/reliability_contract_test.go
# to assert worker auditKind* wire values match the api source. Without
# this checkout the tests SKIP in CI, leaving cross-repo drift detection
# to developer machines only. INSTANT_API_REPO is set on the test step
# below so findApiRepoRoot() locates the sibling deterministically.
- name: Checkout api sibling (for cross-repo registry-iterating tests)
uses: actions/checkout@v6
with:
repository: ${{ vars.API_REPO || format('{0}/api', github.repository_owner) }}
token: ${{ secrets.REPO_ACCESS_TOKEN || secrets.GITHUB_TOKEN }}
path: _api_ci
fetch-depth: 1
- run: mv _api_ci ../api
- uses: actions/setup-go@v6
with:
go-version: '1.25'
- run: go build ./...
- run: go vet ./...
- name: Run tests (with INSTANT_API_REPO for cross-repo gate)
env:
INSTANT_API_REPO: ${{ github.workspace }}/../api
run: go test ./... -v -race -count=1
# ------------------------------------------------------------------
# GATING integration job (W2-T1).
#
# WHY: the worker's real-DB integration tests
# (internal/jobs/*_integration_test.go) skip under `-short` AND when
# TEST_DATABASE_URL is unset. The fast `build-and-test` job above runs
# `-race` with NO DB service and the deploy.yml test step runs
# `-short` — so in BOTH the integration tests SKIP and gate NOTHING.
# This job runs them WITHOUT `-short` against a real Postgres so the
# trigger→DB round-trip is actually asserted in CI. It mirrors
# coverage.yml's proven Postgres+Redis service block. Per the two-gate
# rule (root CLAUDE.md rule 15 / project_api_two_test_gates_ci_and_deploy),
# the same job is mirrored in deploy.yml — a worker test-infra change
# must land in BOTH or the deploy wedges while PR CI stays green.
integration:
runs-on: ubuntu-latest
timeout-minutes: 15
services:
postgres:
image: postgres:16-alpine
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: instant_dev_test
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
redis:
image: redis:7-alpine
ports:
- 6379:6379
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
env:
# Integration tests read TEST_DATABASE_URL and run the real-DB path
# (they SKIP when it's unset). TEST_REDIS_URL is wired for parity
# with coverage.yml and for the redis-touching jobs as they land.
TEST_DATABASE_URL: postgres://postgres:postgres@localhost:5432/instant_dev_test?sslmode=disable
TEST_REDIS_URL: redis://localhost:6379/15
steps:
- uses: actions/checkout@v6
- name: Checkout proto sibling (replace ../proto)
uses: actions/checkout@v6
with:
repository: ${{ vars.PROTO_REPO || format('{0}/proto', github.repository_owner) }}
token: ${{ secrets.REPO_ACCESS_TOKEN || secrets.GITHUB_TOKEN }}
path: _proto_ci
- run: mv _proto_ci ../proto
- name: Checkout common sibling (replace ../common)
uses: actions/checkout@v6
with:
repository: ${{ vars.COMMON_REPO || format('{0}/common', github.repository_owner) }}
token: ${{ secrets.REPO_ACCESS_TOKEN || secrets.GITHUB_TOKEN }}
path: _common_ci
- run: mv _common_ci ../common
- name: Checkout api sibling (for migrations + cross-repo tests)
uses: actions/checkout@v6
with:
repository: ${{ vars.API_REPO || format('{0}/api', github.repository_owner) }}
token: ${{ secrets.REPO_ACCESS_TOKEN || secrets.GITHUB_TOKEN }}
path: _api_ci
fetch-depth: 1
- run: mv _api_ci ../api
- uses: actions/setup-go@v6
with:
go-version: '1.25'
- name: Apply DB migrations to the test database
# Mirrors coverage.yml: api owns the platform_db schema
# (teams / resources / deployments / pending_propagations /
# audit_log) the integration tests round-trip against; apply those
# first, then any worker-local SQL on top (IF NOT EXISTS-guarded).
env:
PGPASSWORD: postgres
run: |
if [ -d ../api/internal/db/migrations ]; then
for f in $(ls ../api/internal/db/migrations/*.sql | sort); do
echo "→ applying api migration $(basename "$f")"
psql -h localhost -U postgres -d instant_dev_test -f "$f" >/dev/null
done
echo "all api migrations applied to instant_dev_test"
else
echo "::error::no api migrations directory found at ../api/internal/db/migrations — integration tests would skip"
exit 1
fi
if [ -d sql ]; then
for f in $(ls sql/*.sql 2>/dev/null | sort); do
echo "→ applying worker migration $(basename "$f")"
psql -h localhost -U postgres -d instant_dev_test -f "$f" >/dev/null || echo "::warning::worker migration $(basename "$f") failed — likely overlap with api schema; continuing"
done
fi
- name: Run real-DB integration tests (NO -short, so they do not skip)
# `-run Integration` scopes the run to the _integration_test.go
# funcs (all carry "Integration" in their name); `-p 1` because
# every package shares the single instant_dev_test DB and default
# parallelism corrupts shared state. Dropping `-short` is what
# makes testhelpers.SetupTestDB's testing.Short() guard pass and
# the real-DB path run instead of skipping.
env:
INSTANT_API_REPO: ${{ github.workspace }}/../api
run: go test ./internal/... -run Integration -count=1 -p 1 -v