feat(backend): enforce required store parity (#3459)
This commit is contained in:
@@ -178,6 +178,15 @@ jobs:
|
||||
- name: Build
|
||||
run: go build -v ./cmd/kandev
|
||||
|
||||
- name: Check required-store SQL portability
|
||||
run: go run ./cmd/sqlguard ./internal
|
||||
|
||||
- name: Run catalog and SQLite conformance gates
|
||||
run: |
|
||||
set -euo pipefail
|
||||
go test -v -race ./internal/persistence/storeconformance \
|
||||
-run '^(TestStoreCatalogCompleteness|TestStoreConformance|TestUpgradeFixtureManifest|TestPreviousStableUpgrade)$'
|
||||
|
||||
# Assert the run/dev/start-debug targets expand to the right per-shell
|
||||
# command line (native Windows / Git Bash / Unix). The windows-latest job
|
||||
# below compiles Go but never exercises this Make-target dispatch, so a
|
||||
@@ -475,6 +484,7 @@ jobs:
|
||||
- test_shards
|
||||
- test_ambient_env
|
||||
- postgres-boot
|
||||
- postgres-18
|
||||
- test-windows
|
||||
if: ${{ always() }}
|
||||
steps:
|
||||
@@ -486,6 +496,7 @@ jobs:
|
||||
TEST_SHARDS_RESULT: ${{ needs.test_shards.result }}
|
||||
TEST_AMBIENT_ENV_RESULT: ${{ needs.test_ambient_env.result }}
|
||||
POSTGRES_BOOT_RESULT: ${{ needs['postgres-boot'].result }}
|
||||
POSTGRES_18_RESULT: ${{ needs['postgres-18'].result }}
|
||||
TEST_WINDOWS_RESULT: ${{ needs['test-windows'].result }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
@@ -496,6 +507,7 @@ jobs:
|
||||
echo "Test shards: ${TEST_SHARDS_RESULT}"
|
||||
echo "Ambient env tests: ${TEST_AMBIENT_ENV_RESULT}"
|
||||
echo "Postgres boot: ${POSTGRES_BOOT_RESULT}"
|
||||
echo "Postgres 18: ${POSTGRES_18_RESULT}"
|
||||
echo "Windows tests: ${TEST_WINDOWS_RESULT}"
|
||||
|
||||
# Runner planning must succeed because its outputs select the runner
|
||||
@@ -525,6 +537,7 @@ jobs:
|
||||
"test_shards:${TEST_SHARDS_RESULT}" \
|
||||
"test_ambient_env:${TEST_AMBIENT_ENV_RESULT}" \
|
||||
"postgres-boot:${POSTGRES_BOOT_RESULT}" \
|
||||
"postgres-18:${POSTGRES_18_RESULT}" \
|
||||
"test-windows:${TEST_WINDOWS_RESULT}"; do
|
||||
name="${entry%%:*}"
|
||||
result="${entry#*:}"
|
||||
@@ -578,31 +591,103 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Run env-gated Postgres tests
|
||||
- name: Run fixed PostgreSQL 16 persistence gates
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
mapfile -t postgres_packages < <(
|
||||
grep -RIl 'PostgresDSNFromEnv' . --include='*_test.go' \
|
||||
| xargs -r dirname \
|
||||
| sort -u
|
||||
# Keep this package list explicit. PostgreSQL coverage is a reviewed
|
||||
# contract, not a grep over test source markers that can silently
|
||||
# omit a package when a test is renamed or moved.
|
||||
POSTGRES_PACKAGES=(
|
||||
./internal/agent/settings/store
|
||||
./internal/analytics/repository/sqlite
|
||||
./internal/automation
|
||||
./internal/azuredevops
|
||||
./internal/backendapp
|
||||
./internal/db
|
||||
./internal/delivery
|
||||
./internal/github
|
||||
./internal/gitlab
|
||||
./internal/jira
|
||||
./internal/linear
|
||||
./internal/notifications/store
|
||||
./internal/office/configsync
|
||||
./internal/office/repository/sqlite
|
||||
./internal/orchestrator/messagequeue
|
||||
./internal/persistence
|
||||
./internal/persistence/storeconformance
|
||||
./internal/plugins/state
|
||||
./internal/prompts/store
|
||||
./internal/runs/service
|
||||
./internal/runtimeflags
|
||||
./internal/secrets
|
||||
./internal/sentry
|
||||
./internal/system/settings
|
||||
./internal/system/storage
|
||||
./internal/task/repository/sqlite
|
||||
./internal/telemetrycontract
|
||||
./internal/terminal/repository
|
||||
./internal/user/store
|
||||
./internal/workflow/repository
|
||||
./internal/workflowsync
|
||||
./internal/worktree
|
||||
)
|
||||
go test -v -race "${POSTGRES_PACKAGES[@]}"
|
||||
|
||||
if [[ "${#postgres_packages[@]}" -eq 0 ]]; then
|
||||
echo "::error::No Postgres test packages found"
|
||||
exit 1
|
||||
fi
|
||||
postgres-18:
|
||||
name: Backend Postgres 18
|
||||
needs: changes
|
||||
if: needs.changes.outputs.run == 'true'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: read
|
||||
timeout-minutes: 20
|
||||
container: ghcr.io/kdlbs/kandev-ci:build-latest
|
||||
services:
|
||||
postgres:
|
||||
image: ghcr.io/kdlbs/kandev-ci:postgres-18@sha256:4ef4dbc939d61acea57712655ddb4b4ab27419c913f94cca0cd57cb3ea3c2280
|
||||
credentials:
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
env:
|
||||
POSTGRES_USER: kandev
|
||||
POSTGRES_PASSWORD: kandev
|
||||
POSTGRES_DB: kandev_admin
|
||||
options: >-
|
||||
--health-cmd "pg_isready -U kandev -d kandev_admin"
|
||||
--health-interval 5s
|
||||
--health-timeout 5s
|
||||
--health-retries 12
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
working-directory: apps/backend
|
||||
env:
|
||||
KANDEV_TEST_POSTGRES_DSN: host=postgres port=5432 user=kandev password=kandev dbname=kandev_admin sslmode=disable
|
||||
|
||||
printf 'Running Postgres tests in:\n'
|
||||
printf ' %s\n' "${postgres_packages[@]}"
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Run PostgreSQL 18 boot and upgrade gates
|
||||
run: |
|
||||
set -euo pipefail
|
||||
output_file="$(mktemp)"
|
||||
go test -v -race "${postgres_packages[@]}" 2>&1 | tee "${output_file}"
|
||||
go test -v -race \
|
||||
./internal/persistence/storeconformance ./internal/backendapp \
|
||||
-run '^(TestPreviousStableUpgrade|TestPostgresBootInitializesRepositories)$' \
|
||||
2>&1 | tee "${output_file}"
|
||||
|
||||
if ! grep -q '^=== RUN TestPostgresBootInitializesRepositories$' "${output_file}"; then
|
||||
echo "::error::Postgres boot smoke test matched no tests"
|
||||
exit 1
|
||||
fi
|
||||
for test_name in \
|
||||
'=== RUN TestPreviousStableUpgrade' \
|
||||
'=== RUN TestPostgresBootInitializesRepositories'; do
|
||||
if ! grep -q "^${test_name}$" "${output_file}"; then
|
||||
echo "::error::PostgreSQL 18 gate matched no ${test_name#* } test"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
test-windows:
|
||||
name: Backend (windows)
|
||||
|
||||
@@ -28,6 +28,9 @@ env:
|
||||
POSTGRES_DIGEST: sha256:fe03a7605299a34ddf5e4f285dff78c3d7190a576b3c6b46f2fcff69f4bffd54
|
||||
POSTGRES_SOURCE: docker.io/library/postgres:16@sha256:fe03a7605299a34ddf5e4f285dff78c3d7190a576b3c6b46f2fcff69f4bffd54
|
||||
POSTGRES_TARGET: ghcr.io/kdlbs/kandev-ci:postgres-16
|
||||
POSTGRES_18_DIGEST: sha256:4ef4dbc939d61acea57712655ddb4b4ab27419c913f94cca0cd57cb3ea3c2280
|
||||
POSTGRES_18_SOURCE: docker.io/library/postgres:18@sha256:4ef4dbc939d61acea57712655ddb4b4ab27419c913f94cca0cd57cb3ea3c2280
|
||||
POSTGRES_18_TARGET: ghcr.io/kdlbs/kandev-ci:postgres-18
|
||||
|
||||
jobs:
|
||||
build-and-push:
|
||||
@@ -69,6 +72,10 @@ jobs:
|
||||
--tag "${POSTGRES_TARGET}" \
|
||||
"${POSTGRES_SOURCE}"
|
||||
|
||||
docker buildx imagetools create \
|
||||
--tag "${POSTGRES_18_TARGET}" \
|
||||
"${POSTGRES_18_SOURCE}"
|
||||
|
||||
mirrored_digest="sha256:$(
|
||||
docker buildx imagetools inspect --raw "${POSTGRES_TARGET}" \
|
||||
| sha256sum \
|
||||
@@ -79,6 +86,16 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mirrored_18_digest="sha256:$(
|
||||
docker buildx imagetools inspect --raw "${POSTGRES_18_TARGET}" \
|
||||
| sha256sum \
|
||||
| cut -d ' ' -f 1
|
||||
)"
|
||||
if [[ "${mirrored_18_digest}" != "${POSTGRES_18_DIGEST}" ]]; then
|
||||
echo "::error::Postgres 18 mirror digest ${mirrored_18_digest} does not match ${POSTGRES_18_DIGEST}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Compute image tag
|
||||
id: tag
|
||||
run: |
|
||||
@@ -159,6 +176,7 @@ jobs:
|
||||
echo "- build: \`${IMAGE_NAME}:build-sha-${IMAGE_TAG}\` / \`build-latest\`"
|
||||
echo "- desktop: \`${IMAGE_NAME}:desktop-sha-${IMAGE_TAG}\` / \`desktop-latest\`"
|
||||
echo "- postgres: \`${POSTGRES_TARGET}@${POSTGRES_DIGEST}\`"
|
||||
echo "- postgres 18: \`${POSTGRES_18_TARGET}@${POSTGRES_18_DIGEST}\`"
|
||||
echo "- pushed: \`${PUSHED}\`"
|
||||
} >> "$GITHUB_STEP_SUMMARY"
|
||||
env:
|
||||
|
||||
@@ -93,6 +93,9 @@ jobs:
|
||||
- name: Test managed runtime pin update workflow contract
|
||||
run: python3 .github/scripts/update-agent-runtime-pins-workflow-contract_test.py
|
||||
|
||||
- name: Test backend tests workflow contract
|
||||
run: python3 .github/scripts/backend-tests-workflow-contract_test.py
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
|
||||
with:
|
||||
|
||||
Reference in New Issue
Block a user