Repository navigation
ibrarahmad is running the unit tests. #191
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Docker tests | |
| run-name: ${{ github.actor }} is running the unit tests. | |
| on: | |
| push: | |
| branches: | |
| - main | |
| pull_request: | |
| jobs: | |
| run-scripts: | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest] | |
| pgver: [16, 17, 18, 19] | |
| include: | |
| # Spock PG 19 support is merged but not yet released; build Spock | |
| # from this branch for PG 19 and drop the override once a Spock | |
| # release includes it | |
| - pgver: 19 | |
| spock_ref: main | |
| runs-on: ${{ matrix.os }} | |
| # Without this a hung tester burns the 6 hour job ceiling on every matrix | |
| # entry, and the run is cancelled rather than failed, which skips the | |
| # diagnostic steps below. Leave room for image build and container startup | |
| # ahead of the 25 minute test wait, so the wait's own deadline is what fires | |
| # and the diagnostics actually run. | |
| timeout-minutes: 60 | |
| steps: | |
| - name: Checkout lolor | |
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| with: | |
| ref: ${{ github.ref }} | |
| - name: Add permissions | |
| run: | | |
| sudo chmod -R a+w ${GITHUB_WORKSPACE} | |
| - name: Set up Docker | |
| uses: docker/setup-buildx-action@885d1462b80bc1c1c7f0b00334ad271f09369c55 # v2 | |
| - name: Set up docker-compose | |
| uses: docker/setup-compose-action@2fe291b7677a45ee1269ec56a42604c143505e7e # v1 | |
| # Resolve the exact source tags on the runner and pass them in as build | |
| # args: the docker layer cache then reuses the compiled PostgreSQL and | |
| # Spock until a new release is tagged. | |
| - name: Resolve PostgreSQL and Spock release tags | |
| id: tags | |
| run: | | |
| PG_TAGS=$(git ls-remote --tags https://github.com/postgres/postgres.git "REL_${{ matrix.pgver }}_*" \ | |
| | awk -F/ '{print $NF}' | grep -v '\^{}') | |
| PG_TAG=$(echo "$PG_TAGS" | grep -E "^REL_${{ matrix.pgver }}_[0-9]+$" | sort -t_ -k3,3n | tail -n 1) | |
| # A pre-GA major has no stable minor tag yet: latest RC, else BETA | |
| [ -n "$PG_TAG" ] || PG_TAG=$(echo "$PG_TAGS" | grep -E "^REL_${{ matrix.pgver }}_RC[0-9]+$" | sort -V | tail -n 1) | |
| [ -n "$PG_TAG" ] || PG_TAG=$(echo "$PG_TAGS" | grep -E "^REL_${{ matrix.pgver }}_BETA[0-9]+$" | sort -V | tail -n 1) | |
| if [ -n "${{ matrix.spock_ref }}" ]; then | |
| # Pin the moving branch to its current SHA so the docker layer | |
| # cache is invalidated by every Spock merge | |
| SPOCK_TAG=$(git ls-remote https://github.com/pgEdge/spock.git "refs/heads/${{ matrix.spock_ref }}" | cut -f1) | |
| else | |
| SPOCK_TAG=$(git ls-remote --tags https://github.com/pgEdge/spock.git \ | |
| | awk -F/ '{print $NF}' \ | |
| | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' \ | |
| | sort -V | tail -n 1) | |
| fi | |
| if [ -z "$PG_TAG" ] || [ -z "$SPOCK_TAG" ]; then | |
| echo "::error::Failed to resolve tags (PG_TAG='$PG_TAG', SPOCK_TAG='$SPOCK_TAG')" | |
| exit 1 | |
| fi | |
| echo "Using PostgreSQL $PG_TAG and Spock $SPOCK_TAG" | |
| echo "pg_tag=$PG_TAG" >> $GITHUB_OUTPUT | |
| echo "spock_tag=$SPOCK_TAG" >> $GITHUB_OUTPUT | |
| - name: Build node image | |
| uses: docker/build-push-action@4f58ea79222b3b9dc2c8bbdd6debcef730109a75 # v6.9.0 | |
| with: | |
| context: docker | |
| file: docker/Dockerfile.el9 | |
| tags: lolor | |
| load: true | |
| build-args: | | |
| PGVER=${{ matrix.pgver }} | |
| PG_TAG=${{ steps.tags.outputs.pg_tag }} | |
| SPOCK_TAG=${{ steps.tags.outputs.spock_tag }} | |
| cache-from: type=gha,scope=pg${{ matrix.pgver }} | |
| cache-to: type=gha,mode=max,scope=pg${{ matrix.pgver }} | |
| - name: Build tester image | |
| uses: docker/build-push-action@4f58ea79222b3b9dc2c8bbdd6debcef730109a75 # v6.9.0 | |
| with: | |
| context: docker | |
| file: docker/Dockerfile.tester | |
| tags: lolor-tester | |
| load: true | |
| cache-from: type=gha,scope=tester | |
| cache-to: type=gha,scope=tester | |
| - name: Run docker images | |
| run: | | |
| cd docker | |
| echo PG_VER=${{ matrix.pgver }} >> pgedge.env | |
| docker compose up -d | |
| env: | |
| PG_VER: ${{ matrix.pgver }} | |
| - name: Dump container logs on failure | |
| if: failure() | |
| run: | | |
| cd docker | |
| docker compose logs --no-color || true | |
| for c in n1 n2 n3 tester; do | |
| echo "===== $c =====" | |
| docker logs "$c" 2>&1 || true | |
| done | |
| - name: Wait for tests to complete | |
| id: test_step | |
| continue-on-error: true | |
| run: | | |
| # Cap the wait so a test blocked on a lock or on sub_wait_for_sync() | |
| # fails the step while the cluster is still up to be inspected. | |
| deadline=$(( SECONDS + 25 * 60 )) | |
| while [ "$(docker inspect -f '{{.State.Running}}' tester)" == "true" ]; do | |
| if [ "$SECONDS" -ge "$deadline" ]; then | |
| echo "::error::Tests did not finish within 25 minutes; dumping cluster state" | |
| # These run precisely because the cluster is wedged, so bound each | |
| # one: "|| true" catches a bad exit status but not a hang, and a | |
| # blocked query here would burn the job timeout and skip the | |
| # failure-log step below. | |
| PGV=${{ matrix.pgver }} | |
| echo "===== tester output so far =====" | |
| tail -n 200 tests/out.txt || true | |
| for n in n1 n2 n3; do | |
| echo "===== $n: sessions and what they are waiting on =====" | |
| timeout --kill-after=5s 20s docker exec "$n" bash -c "source /home/pgedge/pgedge/pg${PGV}/pg${PGV}.env && psql -U admin -d demo -x -c \" | |
| SELECT pid, state, wait_event_type, wait_event, now() - xact_start AS xact_age, | |
| left(query, 400) AS query | |
| FROM pg_stat_activity | |
| WHERE datname = 'demo' AND pid <> pg_backend_pid() | |
| ORDER BY xact_start\"" || true | |
| echo "===== $n: ungranted locks =====" | |
| timeout --kill-after=5s 20s docker exec "$n" bash -c "source /home/pgedge/pgedge/pg${PGV}/pg${PGV}.env && psql -U admin -d demo -c \" | |
| SELECT l.pid, l.locktype, l.mode, l.granted, | |
| coalesce(c.relname, l.classid::text) AS object | |
| FROM pg_locks l LEFT JOIN pg_class c ON c.oid = l.relation | |
| WHERE NOT l.granted OR l.mode LIKE 'Share%' OR l.mode LIKE '%Exclusive%' | |
| ORDER BY l.granted, l.pid\"" || true | |
| echo "===== $n: subscription status =====" | |
| timeout --kill-after=5s 20s docker exec "$n" bash -c "source /home/pgedge/pgedge/pg${PGV}/pg${PGV}.env && psql -U admin -d demo -c 'SELECT * FROM spock.sub_show_status()'" || true | |
| done | |
| exit 1 | |
| fi | |
| echo "Waiting for tests to complete..." | |
| sleep 1 | |
| done | |
| docker logs n1 | |
| docker logs n2 | |
| docker logs n3 | |
| # grep exits 2 when the file is missing, which "|| exit 0" would turn | |
| # into a pass: a tester that died before writing anything would look | |
| # green. Check for output first, then for failures in it. | |
| if [ ! -s tests/out.txt ]; then | |
| echo "::error::tests/out.txt is missing or empty; the tester produced no output" | |
| exit 1 | |
| fi | |
| if grep -Eq "FAIL|ERROR" tests/out.txt; then | |
| exit 1 | |
| fi | |
| - name: Dump container logs when the tests failed | |
| if: steps.test_step.outcome == 'failure' | |
| run: | | |
| cd docker | |
| for c in n1 n2 n3 tester; do | |
| echo "===== $c =====" | |
| docker logs "$c" > /tmp/$c.log 2>&1 || true | |
| echo "--- first 120 lines (setup) ---"; head -n 120 /tmp/$c.log || true | |
| echo "--- last 120 lines ---"; tail -n 120 /tmp/$c.log || true | |
| done | |
| - name: Upload Log File as Artifact | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | |
| with: | |
| name: latest-log-${{ matrix.pgver }} | |
| path: tests/out.txt | |
| if: always() | |
| - name: Fail the Job if tests failed | |
| if: steps.test_step.outcome == 'failure' | |
| run: exit 1 |