Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
147 changes: 144 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,158 @@
name: Test PostgreSQL Upgrade Images
name: Test

on:
push:
branches:
- main
- master
pull_request:
branches:
- main
- master
workflow_dispatch:

env:
TEST_DB: mission_control
TEST_USER: testuser
TEST_PASSWORD: testpass123

jobs:
test-env-variables:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Build Docker image (amd64 only)
uses: docker/build-push-action@v5
with:
context: .
platforms: linux/amd64
load: true
tags: postgres-test:local
cache-from: type=gha
cache-to: type=gha,mode=max

- name: Start PostgreSQL with environment variables
run: |
echo "Starting PostgreSQL container with:"
echo " POSTGRES_DB=${{ env.TEST_DB }}"
echo " POSTGRES_USER=${{ env.TEST_USER }}"
echo " POSTGRES_PASSWORD=${{ env.TEST_PASSWORD }}"

CONTAINER_ID=$(docker run -d \
-e POSTGRES_DB=${{ env.TEST_DB }} \
-e POSTGRES_USER=${{ env.TEST_USER }} \
-e POSTGRES_PASSWORD=${{ env.TEST_PASSWORD }} \
postgres-test:local)

echo "CONTAINER_ID=$CONTAINER_ID" >> $GITHUB_ENV
echo "Container started: $CONTAINER_ID"

- name: Wait for PostgreSQL to be ready
run: |
echo "Waiting for PostgreSQL to start..."
sleep 15

echo "=== Container Logs ==="
docker logs ${{ env.CONTAINER_ID }}
echo "======================"

- name: Check if custom database was created
run: |
echo "Checking if database '${{ env.TEST_DB }}' exists..."

DATABASES=$(docker exec ${{ env.CONTAINER_ID }} \
psql -h localhost -U ${{ env.TEST_USER }} -d ${{ env.TEST_DB }} -t -c "\l" 2>&1)

echo "=== All Databases ==="
echo "$DATABASES"
echo "====================="

if echo "$DATABASES" | grep -q "${{ env.TEST_DB }}"; then
echo "✅ PASS: Database '${{ env.TEST_DB }}' exists"
else
echo "❌ FAIL: Database '${{ env.TEST_DB }}' was NOT created"
echo "Only these databases exist:"
docker exec ${{ env.CONTAINER_ID }} \
psql -h localhost -U ${{ env.TEST_USER }} -d ${{ env.TEST_DB }} -t -c "SELECT datname FROM pg_database;"
exit 1
fi

- name: Check if custom user was created
run: |
echo "Checking if user '${{ env.TEST_USER }}' exists..."

USERS=$(docker exec ${{ env.CONTAINER_ID }} \
psql -h localhost -U ${{ env.TEST_USER }} -d ${{ env.TEST_DB }} -t -c "SELECT usename FROM pg_user;")

echo "=== All Users ==="
echo "$USERS"
echo "================="

if echo "$USERS" | grep -q "${{ env.TEST_USER }}"; then
echo "✅ PASS: User '${{ env.TEST_USER }}' exists"
else
echo "❌ FAIL: User '${{ env.TEST_USER }}' was NOT created"
exit 1
fi

- name: Test authentication with custom credentials
run: |
echo "Testing authentication as '${{ env.TEST_USER }}' to database '${{ env.TEST_DB }}'..."

if docker exec ${{ env.CONTAINER_ID }} \
psql -h localhost -U ${{ env.TEST_USER }} -d ${{ env.TEST_DB }} -c "SELECT version();" > /dev/null 2>&1; then
echo "✅ PASS: Authentication successful"
else
echo "❌ FAIL: Could not authenticate with provided credentials"
exit 1
fi

- name: Verify database permissions
run: |
echo "Verifying user can create tables in the database..."

docker exec ${{ env.CONTAINER_ID }} \
psql -h localhost -U ${{ env.TEST_USER }} -d ${{ env.TEST_DB }} -c \
"CREATE TABLE test_table (id SERIAL PRIMARY KEY, data TEXT);"

docker exec ${{ env.CONTAINER_ID }} \
psql -h localhost -U ${{ env.TEST_USER }} -d ${{ env.TEST_DB }} -c \
"INSERT INTO test_table (data) VALUES ('test data');"

RESULT=$(docker exec ${{ env.CONTAINER_ID }} \
psql -h localhost -U ${{ env.TEST_USER }} -d ${{ env.TEST_DB }} -t -c \
"SELECT data FROM test_table WHERE id = 1;")

if echo "$RESULT" | grep -q "test data"; then
echo "✅ PASS: User has correct permissions"
else
echo "❌ FAIL: User permissions issue"
exit 1
fi

- name: Show final status
if: always()
run: |
echo "========================================="
echo "Environment Variable Test Results"
echo "========================================="
echo ""
echo "Test Configuration:"
echo " POSTGRES_DB: ${{ env.TEST_DB }}"
echo " POSTGRES_USER: ${{ env.TEST_USER }}"
echo " POSTGRES_PASSWORD: ********"
echo ""
docker logs ${{ env.CONTAINER_ID }} 2>&1 | tail -50

- name: Cleanup
if: always()
run: |
docker stop ${{ env.CONTAINER_ID }} || true
docker rm ${{ env.CONTAINER_ID }} || true

test-builds:
# Disabled: This workflow tries to run Go tests that don't exist.
# Use build-and-test.yml instead which provides comprehensive Docker-based testing.
Expand Down
2 changes: 1 addition & 1 deletion cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ Examples:
cmd.Flags().StringVar(&authMethod, "auth-method", lo.CoalesceOrEmpty(os.Getenv("PG_AUTH_METHOD"), string(pkg.AuthScramSHA)), "Authentication method for pg_hba.conf (auto-detected if not specified)")
cmd.Flags().BoolVar(&opts.Enabled, "pg-tune", true, "Run pg_tune to optimize postgresql.conf before starting")
cmd.Flags().Bool("auto-upgrade", true, "Automatically upgrade PostgreSQL if version mismatch detected")
cmd.Flags().Bool("auto-reset-password", true, "Reset postgres superuser password on start")
cmd.Flags().Bool("auto-reset-password", false, "Reset postgres superuser password on start")
cmd.Flags().Bool("auto-init", true, "Automatically initialize database if data directory doesn't exist")
cmd.Flags().Int("upgrade-to", 0, "Target PostgreSQL version for upgrade (default: auto-detect latest)")

Expand Down
20 changes: 20 additions & 0 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
services:
postgres:
container_name: "pg_test"
build:
context: .
dockerfile: Dockerfile
args:
PG_VERSION: 17
image: flanksource/postgres:17
environment:
POSTGRES_DB: mc
POSTGRES_USER: flanksource
POSTGRES_PASSWORD: testpassword
ports:
- "5435:5432"
volumes:
- pg-data-test:/var/lib/postgresql/data

volumes:
pg-data-test:
26 changes: 24 additions & 2 deletions docker-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,34 @@ fi

export PGBIN=/usr/lib/postgresql/${PG_VERSION}/bin

# Set defaults for PostgreSQL environment variables
POSTGRES_USER="${POSTGRES_USER:-postgres}"
POSTGRES_DB="${POSTGRES_DB:-$POSTGRES_USER}"

if [ ! -f $PGDATA/PG_VERSION ]; then
echo "Initializing database cluster at $PGDATA ..."
# starting and stopping the DB to initialize the directory for tuning
$PGBIN/initdb -D $PGDATA
echo "Using POSTGRES_USER: $POSTGRES_USER"

# Initialize database with specified user and password
if [ -n "$POSTGRES_PASSWORD" ]; then
echo "Initializing with password authentication"
$PGBIN/initdb -D $PGDATA -U "$POSTGRES_USER" --pwfile=<(printf "%s\n" "$POSTGRES_PASSWORD")
else
echo "WARNING: No password set. Initializing without password authentication."
$PGBIN/initdb -D $PGDATA -U "$POSTGRES_USER"
fi

# Start PostgreSQL temporarily to create database
$PGBIN/pg_ctl start -D $PGDATA --wait

# Create custom database if specified and different from default
if [ "$POSTGRES_DB" != "postgres" ]; then
Copy link

Copilot AI Nov 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The condition checks if POSTGRES_DB is different from 'postgres', but according to line 37, POSTGRES_DB defaults to $POSTGRES_USER. If a custom user is specified without a custom database, this will incorrectly skip database creation when POSTGRES_USER equals 'postgres'. The condition should check if POSTGRES_DB is different from the default database for the user, which would be created automatically by initdb.

Suggested change
if [ "$POSTGRES_DB" != "postgres" ]; then
if [ "$POSTGRES_DB" != "$POSTGRES_USER" ]; then

Copilot uses AI. Check for mistakes.
echo "Creating database: $POSTGRES_DB"
$PGBIN/psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname postgres <<-EOSQL
CREATE DATABASE "$POSTGRES_DB" OWNER "$POSTGRES_USER";
Copy link

Copilot AI Nov 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The SQL statement uses double quotes around the database name variable, which will fail if POSTGRES_DB contains double quotes. Consider using identifier quoting or escaping to prevent SQL injection and syntax errors. PostgreSQL's CREATE DATABASE should quote the identifier properly, such as using CREATE DATABASE ${POSTGRES_DB@Q} or validating the database name format.

Copilot uses AI. Check for mistakes.
EOSQL
fi
Comment on lines +56 to +61
Copy link

Copilot AI Nov 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When initdb is run with -U flag, it creates a database with the same name as the specified user. This means if POSTGRES_USER=flanksource and POSTGRES_DB=flanksource, the database already exists and the CREATE DATABASE statement will fail. The condition should check if the database name differs from both 'postgres' AND the username to avoid attempting to create a database that already exists.

Copilot uses AI. Check for mistakes.

$PGBIN/pg_ctl stop -D $PGDATA --wait
else
echo "Database cluster already initialized at $PGDATA with version $(cat $PGDATA/PG_VERSION)"
Expand Down
Loading