Skip to content

Fix: allow safe update for postgres user #591

Fix: allow safe update for postgres user

Fix: allow safe update for postgres user #591

Workflow file for this run

name: CLI Release
on:
push:
tags:
- "v*-cli"
pull_request:
workflow_dispatch:
inputs:
version:
description: "Version tag (e.g., v1.0.0-cli)"
required: true
type: string
jobs:
build-native:
name: Build ${{ matrix.arch }}
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
- system: aarch64-darwin
runner: macos-14
arch: darwin-arm64
- system: x86_64-linux
runner: ubuntu-latest
arch: linux-x64
- system: aarch64-linux
runner: ubuntu-24.04-arm
arch: linux-arm64
steps:
- name: Checkout repository
uses: supabase/postgres/.github/actions/shared-checkout@HEAD
- name: Install Nix
uses: ./.github/actions/nix-install-ephemeral
- name: Run portability check
run: |
nix build .#checks.${{ matrix.system }}.psql_17_cli_portable --system ${{ matrix.system }} -L --accept-flake-config
- name: Build portable CLI bundle
run: |
nix build .#psql_17_cli_portable --system ${{ matrix.system }} -L --accept-flake-config
- name: Determine version
id: version
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
VERSION="${{ github.event.inputs.version }}"
else
VERSION="${{ github.ref_name }}"
fi
# Sanitize version by replacing slashes with dashes
VERSION="${VERSION//\//-}"
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
- name: Prepare build directory
run: |
VERSION="${{ steps.version.outputs.version }}"
ARCH="${{ matrix.arch }}"
BUILD_DIR="supabase-postgres-${VERSION}-${ARCH}"
mkdir -p "${BUILD_DIR}"
shopt -s dotglob
cp -rL result/* "${BUILD_DIR}/"
shopt -u dotglob
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: supabase-postgres-${{ matrix.arch }}
path: supabase-postgres-${{ steps.version.outputs.version }}-${{ matrix.arch }}
retention-days: 90
include-hidden-files: true
test-portability:
name: ${{ matrix.arch }} without Nix
needs: [build-native]
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
- runner: macos-14
arch: darwin-arm64
- runner: ubuntu-latest
arch: linux-x64
- runner: ubuntu-24.04-arm
arch: linux-arm64
steps:
- name: Download artifact
uses: actions/download-artifact@v4
with:
name: supabase-postgres-${{ matrix.arch }}
path: .
- name: Test binaries work without Nix
run: |
cd bin
find . -maxdepth 1 -type f -exec chmod +x {} +
ls -la
echo "Testing postgres --version..."
./postgres --version
echo "Testing pg_config --version..."
./pg_config --version
echo "Testing psql --version..."
./psql --version
echo "Testing initdb --version..."
./initdb --version
- name: Test initialization script
run: |
set -e
echo "=========================================="
echo "Testing supabase-postgres-init.sh"
echo "=========================================="
# Make init script executable
chmod +x ./share/supabase-cli/bin/supabase-postgres-init.sh
# Test 1: Initialize database with init script
export PGDATA="$(pwd)/pgdata-init-test"
export POSTGRES_USER="test_user"
export POSTGRES_PASSWORD="test_password"
export POSTGRES_DB="test_db"
echo "Starting PostgreSQL with init script..."
./share/supabase-cli/bin/supabase-postgres-init.sh -p 54321 > init.log 2>&1 &
INIT_PID=$!
# Wait for PostgreSQL to be ready
for i in {1..30}; do
if ./bin/pg_isready -p 54321 -h 127.0.0.1 -U test_user > /dev/null 2>&1; then
echo "PostgreSQL is ready"
break
fi
if [ $i -eq 30 ]; then
echo "PostgreSQL failed to start"
cat init.log
exit 1
fi
sleep 1
done
echo ""
echo "=========================================="
echo "Testing password authentication"
echo "=========================================="
# Test password authentication (should work with scram-sha-256)
PGPASSWORD="test_password" ./bin/psql -p 54321 -h 127.0.0.1 -U test_user -d test_db -c "SELECT version();" > /dev/null
if [ $? -eq 0 ]; then
echo "✓ Password authentication successful"
else
echo "✗ Password authentication failed"
exit 1
fi
# Test wrong password (should fail) - temporarily disable set -e
set +e
PGPASSWORD="wrong_password" ./bin/psql -p 54321 -h 127.0.0.1 -U test_user -d test_db -c "SELECT 1;" > /dev/null 2>&1
WRONG_PW_STATUS=$?
set -e
if [ $WRONG_PW_STATUS -ne 0 ]; then
echo "✓ Wrong password correctly rejected"
else
echo "✗ Wrong password was accepted (security issue!)"
exit 1
fi
echo ""
echo "=========================================="
echo "Testing database initialization"
echo "=========================================="
# Verify database exists
PGPASSWORD="test_password" ./bin/psql -p 54321 -h 127.0.0.1 -U test_user -d test_db -v ON_ERROR_STOP=1 -c "SELECT current_database();" | grep "test_db"
if [ $? -eq 0 ]; then
echo "✓ Custom database created"
else
echo "✗ Custom database not found"
exit 1
fi
# Verify configuration files were set up
if [ -f "$PGDATA/postgresql.conf" ] && [ -f "$PGDATA/pg_hba.conf" ]; then
echo "✓ Configuration files created"
else
echo "✗ Configuration files missing"
exit 1
fi
# Verify pgsodium/vault getkey scripts are configured
if grep -q "pgsodium.getkey_script" "$PGDATA/postgresql.conf" && grep -q "vault.getkey_script" "$PGDATA/postgresql.conf"; then
echo "✓ Getkey scripts configured"
else
echo "✗ Getkey scripts not configured"
exit 1
fi
echo ""
echo "=========================================="
echo "Testing idempotency"
echo "=========================================="
# Stop PostgreSQL
./bin/pg_ctl -D "$PGDATA" stop -m fast
wait $INIT_PID 2>/dev/null || true
# Run init script again (should skip initialization)
./share/supabase-cli/bin/supabase-postgres-init.sh -p 54321 > init2.log 2>&1 &
INIT_PID2=$!
# Wait for PostgreSQL to be ready
for i in {1..30}; do
if ./bin/pg_isready -p 54321 -h 127.0.0.1 -U test_user > /dev/null 2>&1; then
echo "PostgreSQL is ready after re-init"
break
fi
if [ $i -eq 30 ]; then
echo "PostgreSQL failed to start on second run"
cat init2.log
exit 1
fi
sleep 1
done
# Verify we can still connect with same password
PGPASSWORD="test_password" ./bin/psql -p 54321 -h 127.0.0.1 -U test_user -d test_db -c "SELECT 1;" > /dev/null
if [ $? -eq 0 ]; then
echo "✓ Idempotency verified - database not re-initialized"
else
echo "✗ Failed to connect after re-running init script"
exit 1
fi
# Check log to verify it skipped initialization
if grep -q "already initialized" init2.log; then
echo "✓ Init script correctly detected existing database"
else
echo "⚠ Warning: Init script may have re-initialized (check init2.log)"
fi
# Stop PostgreSQL
./bin/pg_ctl -D "$PGDATA" stop -m fast
wait $INIT_PID2 2>/dev/null || true
echo ""
echo "=========================================="
echo "Init script tests completed successfully"
echo "=========================================="
echo ""
- name: Test migrations with CLI variant
run: |
set -e
# Use bundled pgsodium getkey script
GETKEY_SCRIPT="$(pwd)/share/supabase-cli/config/pgsodium_getkey.sh"
chmod +x "$GETKEY_SCRIPT"
# Initialize test database
PGDATA="$(pwd)/pgdata-test"
./bin/initdb -D "$PGDATA" -U supabase_admin --no-instructions
# Copy CLI config and add pgsodium/vault getkey scripts
cp share/supabase-cli/config/postgresql.conf.template "$PGDATA/postgresql.conf"
cat >> "$PGDATA/postgresql.conf" << EOF
# pgsodium and vault configuration for testing
pgsodium.getkey_script = '$GETKEY_SCRIPT'
vault.getkey_script = '$GETKEY_SCRIPT'
EOF
# Start PostgreSQL
./bin/postgres -D "$PGDATA" -p 54322 > postgres.log 2>&1 &
PG_PID=$!
# Wait for PostgreSQL to be ready
for i in {1..30}; do
if ./bin/pg_isready -p 54322 -h 127.0.0.1 -U supabase_admin > /dev/null 2>&1; then
echo "PostgreSQL is ready"
break
fi
if [ $i -eq 30 ]; then
echo "PostgreSQL failed to start"
cat postgres.log
exit 1
fi
sleep 1
done
# Run migrations
cd share/supabase-cli/migrations
chmod +x migrate.sh
echo "=========================================="
echo "Running migrations..."
echo "=========================================="
PATH="$(pwd)/../../../bin:$PATH" \
POSTGRES_PASSWORD=postgres \
POSTGRES_PORT=54322 \
POSTGRES_DB=postgres \
POSTGRES_USER=supabase_admin \
./migrate.sh 2>&1 | tee migration.log
MIGRATION_STATUS=${PIPESTATUS[0]}
echo ""
echo "=========================================="
echo "Migration output complete"
echo "=========================================="
# Check migration results - all migrations must succeed
if [ $MIGRATION_STATUS -ne 0 ]; then
echo "Migrations failed"
cat migration.log
exit 1
fi
echo "All migrations applied successfully"
# Verify extensions are installed
cd ../../..
./bin/psql -p 54322 -h 127.0.0.1 -U supabase_admin -d postgres -v ON_ERROR_STOP=1 -c "\dx" | tee extensions.log
# Check for required extensions
for ext in pg_graphql pgcrypto uuid-ossp supabase_vault; do
if ! grep -q "$ext" extensions.log; then
echo "Required extension $ext not found"
exit 1
fi
done
echo ""
echo "=========================================="
echo "Testing timezone functionality with bundled timezone data"
echo "=========================================="
cat > timezone_test.sql << 'EOF'
-- Test basic timezone conversion
SELECT now() AT TIME ZONE 'America/New_York' AS ny_time;
SELECT now() AT TIME ZONE 'Europe/London' AS london_time;
SELECT now() AT TIME ZONE 'Asia/Tokyo' AS tokyo_time;
-- Verify timezone database is accessible
SELECT COUNT(*) AS timezone_count FROM pg_timezone_names;
-- Test that we have reasonable number of timezones (should be 500+)
DO $$
DECLARE
tz_count INTEGER;
BEGIN
SELECT COUNT(*) INTO tz_count FROM pg_timezone_names;
IF tz_count < 500 THEN
RAISE EXCEPTION 'Insufficient timezones: found %, expected 500+', tz_count;
END IF;
RAISE NOTICE 'Timezone test passed: found % timezones', tz_count;
END $$;
-- Show current timezone setting
SHOW timezone;
EOF
# Run timezone tests from file
./bin/psql -p 54322 -h 127.0.0.1 -U supabase_admin -d postgres -v ON_ERROR_STOP=1 -f timezone_test.sql | tee timezone.log
TIMEZONE_STATUS=${PIPESTATUS[0]}
if [ $TIMEZONE_STATUS -ne 0 ]; then
echo "Timezone tests failed"
cat timezone.log
exit 1
fi
echo "Timezone tests passed successfully"
echo ""
# Stop PostgreSQL
./bin/pg_ctl -D "$PGDATA" stop -m fast
echo "Migration test completed successfully"
release:
name: Create GitHub Release
needs: [build-native, test-portability]
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/')
permissions:
contents: write
steps:
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
- name: Prepare release assets
run: |
mkdir -p release temp
# Determine version
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
VERSION="${{ github.event.inputs.version }}"
else
VERSION="${{ github.ref_name }}"
fi
VERSION="${VERSION//\//-}"
# Create tarballs from each artifact directory
for dir in artifacts/*; do
if [ -d "$dir" ]; then
ARTIFACT_NAME=$(basename "$dir")
# Extract arch from artifact name (e.g., "supabase-postgres-darwin-arm64" -> "darwin-arm64")
ARCH="${ARTIFACT_NAME#supabase-postgres-}"
BUILD_DIR="supabase-postgres-${VERSION}-${ARCH}"
echo "Creating tarball for ${BUILD_DIR}..."
# Create temp directory with proper structure
mkdir -p "temp/${BUILD_DIR}"
cp -r "$dir"/* "temp/${BUILD_DIR}/"
# Create tarball with directory structure
tar -czhf "release/${BUILD_DIR}.tar.gz" -C temp "${BUILD_DIR}"
# Generate checksum
sha256sum "release/${BUILD_DIR}.tar.gz" > "release/${BUILD_DIR}.tar.gz.sha256"
# Cleanup temp directory for this artifact
rm -rf "temp/${BUILD_DIR}"
echo "✓ Created release/${BUILD_DIR}.tar.gz"
fi
done
ls -lh release/
- name: Create Release
uses: softprops/action-gh-release@v2
with:
files: release/*
generate_release_notes: true