chore: fix permission error in ci #74
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: Build and Test PostgreSQL Upgrade Container | |
| on: | |
| push: | |
| branches: [ main ] | |
| tags: [ 'v*' ] | |
| pull_request: | |
| branches: [ main ] | |
| workflow_dispatch: | |
| env: | |
| REGISTRY: ghcr.io | |
| IMAGE_NAME: ${{ github.repository_owner }}/postgres-upgrade | |
| jobs: | |
| build: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| packages: write | |
| outputs: | |
| image: ${{ steps.image.outputs.image }} | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Set up QEMU | |
| uses: docker/setup-qemu-action@v3 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Log in to the Container registry | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Extract metadata | |
| id: meta | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} | |
| tags: | | |
| type=ref,event=branch | |
| type=ref,event=pr | |
| type=semver,pattern={{version}} | |
| type=semver,pattern={{major}}.{{minor}} | |
| type=sha | |
| - name: Build and push Docker image | |
| id: build | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: . | |
| platforms: linux/amd64,linux/arm64 | |
| push: true | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| cache-from: | | |
| type=gha | |
| type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache | |
| cache-to: | | |
| type=gha,mode=max | |
| type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache,mode=max | |
| - name: Output image | |
| id: image | |
| run: echo "image=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }}" >> $GITHUB_OUTPUT | |
| test: | |
| needs: build | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false # Don't cancel other tests if one fails | |
| matrix: | |
| include: | |
| # AMD64 tests - full matrix | |
| - platform: linux/amd64 | |
| test: { from: 14, to: 15, name: "14 to 15" } | |
| - platform: linux/amd64 | |
| test: { from: 15, to: 16, name: "15 to 16" } | |
| - platform: linux/amd64 | |
| test: { from: 16, to: 17, name: "16 to 17" } | |
| - platform: linux/amd64 | |
| test: { from: 14, to: 16, name: "14 to 16 (multi-step)" } | |
| - platform: linux/amd64 | |
| test: { from: 15, to: 17, name: "15 to 17 (multi-step)" } | |
| - platform: linux/amd64 | |
| test: { from: 14, to: 17, name: "14 to 17 (full upgrade)" } | |
| # ARM64 test - just one to verify it works | |
| - platform: linux/arm64 | |
| test: { from: 14, to: 17, name: "14 to 17 (full upgrade)" } | |
| name: Test ${{ matrix.platform }} - ${{ matrix.test.name }} | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Set up QEMU | |
| if: matrix.platform == 'linux/arm64' | |
| uses: docker/setup-qemu-action@v3 | |
| - name: Log in to the Container registry | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Set image name | |
| run: | | |
| echo "TEST_IMAGE=${{ needs.build.outputs.image }}" >> $GITHUB_ENV | |
| - name: Pull test image | |
| run: | | |
| echo "Pulling test image: ${{ env.TEST_IMAGE }}" | |
| docker pull ${{ env.TEST_IMAGE }} | |
| - name: Create test data directory | |
| run: | | |
| mkdir -p test-data/${{ matrix.test.from }} | |
| chmod 777 test-data/${{ matrix.test.from }} | |
| # Set SELinux context to allow Docker access | |
| sudo chcon -Rt svirt_sandbox_file_t test-data/ 2>/dev/null || true | |
| - name: Initialize PostgreSQL ${{ matrix.test.from }} with test data | |
| run: | | |
| docker run --rm \ | |
| -v $PWD/test-data/${{ matrix.test.from }}:/var/lib/postgresql/data \ | |
| -e POSTGRES_PASSWORD=testpass \ | |
| -e POSTGRES_DB=testdb \ | |
| postgres:${{ matrix.test.from }}-bookworm \ | |
| bash -c " | |
| set -e | |
| set -o pipefail | |
| docker-entrypoint.sh postgres & | |
| PGPID=\$! | |
| sleep 10 | |
| # Create testuser and test database | |
| psql -U postgres -d testdb -v ON_ERROR_STOP=1 <<EOF | |
| CREATE USER testuser WITH PASSWORD 'testpass'; | |
| GRANT ALL PRIVILEGES ON DATABASE testdb TO testuser; | |
| GRANT ALL ON SCHEMA public TO testuser; | |
| GRANT CREATE ON SCHEMA public TO testuser; | |
| EOF | |
| # Create test data as testuser | |
| psql -U testuser -d testdb -v ON_ERROR_STOP=1 <<EOF | |
| CREATE TABLE test_data ( | |
| id SERIAL PRIMARY KEY, | |
| data TEXT, | |
| created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP | |
| ); | |
| INSERT INTO test_data (data) | |
| SELECT 'Test record ' || generate_series(1, 1000); | |
| CREATE INDEX idx_test_data ON test_data(created_at); | |
| SELECT COUNT(*) as record_count FROM test_data; | |
| EOF | |
| # Gracefully stop PostgreSQL | |
| su postgres -c 'pg_ctl -D /var/lib/postgresql/data stop -m smart -w' | |
| sleep 5 | |
| # Fix permissions for GitHub Actions runner | |
| chown -R 999:999 /var/lib/postgresql/data | |
| " | |
| - name: Run upgrade from ${{ matrix.test.from }} to ${{ matrix.test.to }} | |
| timeout-minutes: 10 | |
| run: | | |
| CONTAINER_ID=$(docker run -d \ | |
| ${{ matrix.platform == 'linux/arm64' && '--platform linux/arm64' || '' }} \ | |
| -v $PWD/test-data/${{ matrix.test.from }}:/var/lib/postgresql/data \ | |
| -e POSTGRES_INITDB_ARGS="--auth-local=trust --auth-host=md5" \ | |
| -e PG_VERSION=${{ matrix.test.to }} \ | |
| ${{ env.TEST_IMAGE }}) | |
| echo "Container started: $CONTAINER_ID" | |
| # Stream logs in real-time | |
| docker logs -f $CONTAINER_ID & | |
| LOGS_PID=$! | |
| sleep 150 | |
| # Stop streaming logs | |
| kill $LOGS_PID 2>/dev/null || true | |
| # Stop and remove container | |
| docker stop -t 10 $CONTAINER_ID 2>/dev/null || true | |
| docker rm $CONTAINER_ID 2>/dev/null || true | |
| exit 0 | |
| - name: Verify upgraded data | |
| run: | | |
| docker run --rm \ | |
| -v $PWD/test-data/${{ matrix.test.from }}:/var/lib/postgresql/data \ | |
| -e POSTGRES_PASSWORD=testpass \ | |
| postgres:${{ matrix.test.to }}-bookworm \ | |
| bash -c " | |
| set -e | |
| set -o pipefail | |
| docker-entrypoint.sh postgres & | |
| PGPID=\$! | |
| sleep 10 | |
| # Verify data | |
| psql -U testuser -d testdb -v ON_ERROR_STOP=1 <<EOF | |
| -- Check table exists | |
| SELECT COUNT(*) as record_count FROM test_data; | |
| -- Check index exists | |
| SELECT indexname FROM pg_indexes WHERE tablename = 'test_data'; | |
| -- Verify data integrity - this will fail if count is not 1000 | |
| DO \$\$ | |
| DECLARE | |
| record_count INT; | |
| BEGIN | |
| SELECT COUNT(*) INTO record_count FROM test_data; | |
| IF record_count != 10000 THEN | |
| RAISE EXCEPTION 'FAIL: Expected 1000 records, found %', record_count; | |
| END IF; | |
| RAISE NOTICE 'PASS: All 1000 records present'; | |
| END \$\$; | |
| EOF | |
| # Stop PostgreSQL | |
| su postgres -c 'pg_ctl -D /var/lib/postgresql/data stop -m smart -w' | |
| sleep 5 | |
| # Fix permissions for GitHub Actions runner | |
| chown -R $(id -u):$(id -g) /var/lib/postgresql/data | |
| " | |
| - name: Fix permissions after test | |
| if: always() | |
| run: | | |
| # Always fix permissions after test, regardless of success/failure | |
| sudo chown -R $USER:$USER test-data/ || true | |
| - name: Collect and show test artifacts on failure | |
| if: failure() | |
| run: | | |
| echo "=== Test failed, collecting available information ===" | |
| # Try to fix permissions first | |
| sudo chown -R $USER:$USER test-data/ || true | |
| # Show directory structure | |
| echo "Test data directory structure:" | |
| find test-data/ -type f -name "*.log" 2>/dev/null || echo "No log files found" | |
| # Show any pg_upgrade output if available | |
| find test-data/ -name "pg_upgrade_output.d" -type d 2>/dev/null | while read dir; do | |
| echo "=== Contents of $dir ===" | |
| ls -la "$dir" 2>/dev/null || echo "Cannot access $dir" | |
| done | |
| # Show recent log entries | |
| find test-data/ -name "*.log" -type f 2>/dev/null | head -5 | while read logfile; do | |
| echo "=== Last 20 lines of $logfile ===" | |
| tail -20 "$logfile" 2>/dev/null || echo "Cannot read $logfile" | |
| done | |