diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 689425d..cd43f30 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -198,21 +198,46 @@ jobs: -e POSTGRES_DB=mcpg_test mcpg-ci-db if [ "${{ matrix.postgres }}" = "warehousepg-latest" ]; then DB_USER=gpadmin - # A single-node Greenplum-family coordinator+segment cluster - # takes much longer to initialize than a plain postgres - # container, so this lane gets a longer, coarser poll. + else + DB_USER=postgres + fi + echo "DB_USER=$DB_USER" >> "$GITHUB_ENV" + if [ "${{ matrix.postgres }}" = "warehousepg-latest" ]; then + # `woblerr/warehousepg` doesn't ship `pg_isready` on PATH — not + # documented upstream, confirmed by direct observation: every + # poll attempt with the pg_isready-based probe below fails with + # "executable file not found in $PATH", so it can never detect + # readiness and always burns its full poll budget (previously + # 90 * 4s = 360s) as dead time regardless of how fast the + # database actually comes up. Probe with `psql` instead — the + # runner's default client works here (see the "Install + # PostgreSQL client tools" step above, which skips a custom + # client for this lane on purpose) — connecting straight + # through the published port, the same path pytest itself + # uses. This also doubles as a stronger check than + # `pg_isready`: it only succeeds once the target database + # actually accepts queries, not just once the postmaster + # process is up. Keep the longer, coarser poll ceiling as a + # safety net — a single-node Greenplum-family + # coordinator+segment cluster can still legitimately take + # longer to initialize than a plain postgres container — but + # now the loop breaks as soon as it's actually ready instead + # of always waiting out the full ceiling. max_attempts=90 sleep_secs=4 + for _ in $(seq 1 "$max_attempts"); do + PGPASSWORD=postgres psql -h localhost -U "$DB_USER" -d mcpg_test -c 'SELECT 1' -q \ + >/dev/null 2>&1 && break + sleep "$sleep_secs" + done else - DB_USER=postgres max_attempts=30 sleep_secs=2 + for _ in $(seq 1 "$max_attempts"); do + docker exec mcpg-db pg_isready -U "$DB_USER" && break + sleep "$sleep_secs" + done fi - echo "DB_USER=$DB_USER" >> "$GITHUB_ENV" - for _ in $(seq 1 "$max_attempts"); do - docker exec mcpg-db pg_isready -U "$DB_USER" && break - sleep "$sleep_secs" - done - name: Set up uv uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1 with: diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b15a19..7700993 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,29 @@ adheres to [Semantic Versioning](https://semver.org/). ## [Unreleased] +### Fixed + +- **Broken readiness probe on the `warehousepg-latest` CI lane was + burning ~6 minutes of dead time on every run.** The lane's readiness + poll used `docker exec mcpg-db pg_isready -U gpadmin`, but + `woblerr/warehousepg:7.4.1-WHPG` doesn't ship `pg_isready` on PATH — + every poll attempt failed with `exec: "pg_isready": executable file + not found in $PATH`, so the loop could never observe success and + always waited out its full 90 × 4s = 360s budget regardless of how + fast the database actually came up. Swapped the probe to `psql` + against the published port, the same path pytest itself uses — + identified from real `gh run view` timings (the "Start PostgreSQL" + step accounted for ~6-6.5 min of the lane's ~9-10 min total vs. + ~20-30s on every other PG version; the `pytest` step itself was + already the same duration as any other lane). + +### Security + +- **Bumped transitive `pip` 26.1.2 → 26.2.1 (PYSEC-2026-3721).** + `pip-audit`'s own `pip_api` dependency pulled in a `pip` version with + a known vulnerability, flagged by the local pre-commit hook's + dependency audit. + ## [0.8.0] - 2026-08-19 ### Security diff --git a/uv.lock b/uv.lock index fb52315..ea081a0 100644 --- a/uv.lock +++ b/uv.lock @@ -1759,11 +1759,11 @@ wheels = [ [[package]] name = "pip" -version = "26.1.2" +version = "26.2.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/01/91/47e7d486260f618783899587af63ccf7980fb60245c3e63dd4571c6b57ad/pip-26.1.2.tar.gz", hash = "sha256:f49cd134c61cf2fd75e0ce2676db03e4054504a5a4986d00f8299ae632dc4605", size = 1840799, upload-time = "2026-05-31T17:33:58.56Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ae/15/4500e320e6b101ec3b719ae85b697d9940b6cda672bc555bd6016fc60c6f/pip-26.2.1.tar.gz", hash = "sha256:f6ad667e89a1fe78046c8f13232b247200f5258d7828f3f7883d660878e0813f", size = 1848877, upload-time = "2026-08-04T22:51:14.148Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5d/95/6b5cb3461ea5673ba0995989746db58eb18b91b54dbf331e72f569540946/pip-26.1.2-py3-none-any.whl", hash = "sha256:382ff9f685ee3bc25864f820aa50505825f10f5458ffff07e30a6d96e5715cab", size = 1813144, upload-time = "2026-05-31T17:33:56.772Z" }, + { url = "https://files.pythonhosted.org/packages/f3/6e/1736e5b4ae2b778ef2f81c47d797de9f891d4d8acb047a24ca37a60294dd/pip-26.2.1-py3-none-any.whl", hash = "sha256:71138adf1f4ca900cdb7d289c21b7494329f2332b6d85f0e1c42108c0384ed3e", size = 1816632, upload-time = "2026-08-04T22:51:12.472Z" }, ] [[package]]