Skip to content

feat: multi-ext-versions-pgrcron #1549

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 30 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
72e5c82
feat: multi-ext-versios-pgrcron
samrose Apr 15, 2025
f8ada92
feat: add version to drv and patch instead of postPatch rewrite
samrose Apr 15, 2025
12e68ff
chore: newline
samrose Apr 15, 2025
94579d4
feat: auto create multi version
samrose Apr 15, 2025
9c4fc2c
chore: do not re-intro maintainers here not needed
samrose Apr 15, 2025
b2a5fd9
chore: bump version
samrose Apr 16, 2025
4683fd3
feat: pg_cron version switcher in pkg and prestart
samrose Apr 24, 2025
16766b9
test: a tmp test for this branch to test older versions
samrose Apr 24, 2025
8b73849
test: temp test for ext handling
samrose Apr 24, 2025
3658fdc
test: instead of patch, add prior to start of machine in testinfra
samrose Apr 24, 2025
697a781
test: only run on pg 15 for this test, as 1.3.1 limited to 15
samrose Apr 24, 2025
1f212ef
feat: use jq from nixpkgs
samrose Apr 24, 2025
5c5dc30
test: handle braces properly
samrose Apr 24, 2025
5d767cc
test: propagate errors from any failure
samrose Apr 25, 2025
0907162
test: more logging for healthcheck
samrose Apr 25, 2025
ccfb26d
chore: bump version
samrose Apr 25, 2025
ca2d39d
test: adding even more logging
samrose Apr 25, 2025
631c30b
test: extend logging more to see what happens when pg starts
samrose Apr 25, 2025
4621729
test: handle lib extension names per system
samrose Apr 28, 2025
2ffe4ab
chore: bump versions
samrose Apr 28, 2025
e8903e4
test: more debugging
samrose Apr 28, 2025
3b74d8f
test: move logging here
samrose Apr 28, 2025
0ff3e87
test: try direct
samrose Apr 28, 2025
ed76a2c
test: use the right alias on machine
samrose Apr 28, 2025
1184112
test: do not unpack result
samrose Apr 29, 2025
f32610f
test: reorg and print logs while waiting continue on other checks whe…
samrose Apr 29, 2025
96702ad
test: restructure checks to avoid race
samrose Apr 29, 2025
298c0a1
Update nix/ext/pg_cron.nix
samrose May 1, 2025
2f7b163
chore: refactor based on review
samrose May 2, 2025
e070474
fix: fixing broken elements of script
samrose May 5, 2025
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
4 changes: 2 additions & 2 deletions .github/workflows/testinfra-ami-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -108,13 +108,13 @@ jobs:
df -h / # Display available space

- name: Run tests
timeout-minutes: 10
timeout-minutes: 30
env:
AMI_NAME: "supabase-postgres-${{ steps.random.outputs.random_string }}"
run: |
# TODO: use poetry for pkg mgmt
pip3 install boto3 boto3-stubs[essential] docker ec2instanceconnectcli pytest pytest-testinfra[paramiko,docker] requests
pytest -vv -s testinfra/test_ami_nix.py
pytest -vvvv -s testinfra/test_ami_nix.py

- name: Cleanup resources on build cancellation
if: ${{ cancelled() }}
Expand Down
55 changes: 55 additions & 0 deletions ansible/files/postgres_prestart.sh.j2
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,62 @@ update_orioledb_buffers() {
fi
}

check_extensions_file() {
local extensions_file="/root/pg_extensions.json"
if [ ! -f "$extensions_file" ]; then
echo "extensions: No extensions file found, skipping extensions versions check"
return 1
fi
return 0
}

get_pg_cron_version() {
if ! check_extensions_file; then
return
fi

local version
version=$(sudo -u postgres /var/lib/postgresql/.nix-profile/bin/jq -r '.pg_cron // empty' "/root/pg_extensions.json")
if [ -z "$version" ]; then
echo "pg_cron: Not specified in extensions file"
return
fi

if ! [[ "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "pg_cron: Invalid version format: $version"
return
fi

echo "$version"
}

switch_pg_cron_version() {
local version="$1"
local switch_script="/var/lib/postgresql/.nix-profile/bin/switch_pg_cron_version"

if [ ! -x "$switch_script" ]; then
echo "pg_cron: No version switch script available"
return
fi

echo "pg_cron: Switching to version $version"
sudo -u postgres "$switch_script" "$version"
echo "pg_cron: Version switch completed"
}

handle_pg_cron_version() {
local version
version=$(get_pg_cron_version)
if [ -n "$version" ]; then
switch_pg_cron_version "$version"
fi
}

main() {
# 1. pg_cron version handling
handle_pg_cron_version

# 2. orioledb handling
local has_orioledb=$(check_orioledb_enabled)
if [ "$has_orioledb" -lt 1 ]; then
return 0
Expand Down
6 changes: 6 additions & 0 deletions ansible/tasks/stage2-setup-postgres.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,12 @@
shell: |
sudo -u postgres bash -c ". /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh && nix profile install github:supabase/postgres/{{ git_commit_sha }}#{{postgresql_version}}_src"
when: stage2_nix

- name: Install jq from nix binary cache
become: yes
shell: |
sudo -u postgres bash -c ". /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh && nix profile install nixpkgs#jq"
when: stage2_nix

- name: Set ownership and permissions for /etc/ssl/private
become: yes
Expand Down
6 changes: 3 additions & 3 deletions ansible/vars.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ postgres_major:

# Full version strings for each major version
postgres_release:
postgresorioledb-17: "17.0.1.078-orioledb"
postgres17: "17.4.1.028"
postgres15: "15.8.1.085"
postgresorioledb-17: "17.0.1.067-orioledb-pgcron-4"
postgres17: "17.4.1.017-pgcron-4"
postgres15: "15.8.1.074-pgcron-4"

# Non Postgres Extensions
pgbouncer_release: "1.19.0"
Expand Down
241 changes: 104 additions & 137 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -637,157 +637,124 @@
--prefix PATH : ${pkgs.nushell}/bin
'';
# Script to run the AMI build and tests locally
build-test-ami = pkgs.runCommand "build-test-ami"
{
buildInputs = with pkgs; [
packer
awscli2
yq
jq
openssl
git
coreutils
aws-vault
];
} ''
mkdir -p $out/bin
cat > $out/bin/build-test-ami << 'EOL'
#!/usr/bin/env bash
set -euo pipefail
build-test-ami = pkgs.writeScriptBin "build-test-ami" ''
#!/usr/bin/env bash
set -euo pipefail

show_help() {
cat << EOF
Usage: build-test-ami [--help] <postgres-version>
show_help() {
cat << EOF
Usage: build-test-ami [--help] <postgres-version>

Build AMI images for PostgreSQL testing.
Build AMI images for PostgreSQL testing.

This script will:
1. Check for required tools and AWS authentication
2. Build two AMI stages using Packer
3. Clean up any temporary instances
4. Output the final AMI name for use with run-testinfra
This script will:
1. Check for required tools and AWS authentication
2. Build two AMI stages using Packer
3. Clean up any temporary instances
4. Output the final AMI name for use with run-testinfra

Arguments:
postgres-version PostgreSQL major version to build (required)
Arguments:
postgres-version PostgreSQL major version to build (required)

Options:
--help Show this help message and exit
Options:
--help Show this help message and exit

Requirements:
- AWS Vault profile must be set in AWS_VAULT environment variable
- Packer, AWS CLI, yq, jq, and OpenSSL must be installed
- Must be run from a git repository
Requirements:
- AWS Vault profile must be set in AWS_VAULT environment variable
- Packer, AWS CLI, yq, jq, and OpenSSL must be installed
- Must be run from a git repository

Example:
aws-vault exec <profile-name> -- nix run .#build-test-ami 15
EOF
}

# Handle help flag
if [[ "$#" -gt 0 && "$1" == "--help" ]]; then
show_help
exit 0
fi
Example:
aws-vault exec <profile-name> -- nix run .#build-test-ami 15
EOF
}

export PATH="${pkgs.lib.makeBinPath (with pkgs; [
packer
awscli2
yq
jq
openssl
git
coreutils
aws-vault
])}:$PATH"
# Handle help flag
if [[ "$#" -gt 0 && "$1" == "--help" ]]; then
show_help
exit 0
fi

# Check for required tools
for cmd in packer aws-vault yq jq openssl; do
if ! command -v $cmd &> /dev/null; then
echo "Error: $cmd is required but not found"
exit 1
fi
done
export PATH="${pkgs.lib.makeBinPath (with pkgs; [
packer
awscli2
yq
jq
openssl
git
coreutils
aws-vault
])}:$PATH"

# Check AWS Vault profile
if [ -z "''${AWS_VAULT:-}" ]; then
echo "Error: AWS_VAULT environment variable must be set with the profile name"
echo "Usage: aws-vault exec <profile-name> -- nix run .#build-test-ami <postgres-version>"
# Check for required tools
for cmd in packer aws-vault yq jq openssl; do
if ! command -v $cmd &> /dev/null; then
echo "Error: $cmd is required but not found"
exit 1
fi
done

# Set values
REGION="ap-southeast-1"
POSTGRES_VERSION="$1"
RANDOM_STRING=$(openssl rand -hex 8)
GIT_SHA=$(git rev-parse HEAD)
RUN_ID=$(date +%s)

# Generate common-nix.vars.pkr.hcl
PG_VERSION=$(yq -r ".postgres_release[\"postgres$POSTGRES_VERSION\"]" ansible/vars.yml)
echo "postgres-version = \"$PG_VERSION\"" > common-nix.vars.pkr.hcl

# Build AMI Stage 1
packer init amazon-arm64-nix.pkr.hcl
packer build \
-var "git-head-version=$GIT_SHA" \
-var "packer-execution-id=$RUN_ID" \
-var-file="development-arm.vars.pkr.hcl" \
-var-file="common-nix.vars.pkr.hcl" \
-var "ansible_arguments=" \
-var "postgres-version=$RANDOM_STRING" \
-var "region=$REGION" \
-var 'ami_regions=["'"$REGION"'"]' \
-var "force-deregister=true" \
-var "ansible_arguments=-e postgresql_major=$POSTGRES_VERSION" \
amazon-arm64-nix.pkr.hcl

# Build AMI Stage 2
packer init stage2-nix-psql.pkr.hcl
packer build \
-var "git-head-version=$GIT_SHA" \
-var "packer-execution-id=$RUN_ID" \
-var "postgres_major_version=$POSTGRES_VERSION" \
-var-file="development-arm.vars.pkr.hcl" \
-var-file="common-nix.vars.pkr.hcl" \
-var "postgres-version=$RANDOM_STRING" \
-var "region=$REGION" \
-var 'ami_regions=["'"$REGION"'"]' \
-var "force-deregister=true" \
-var "git_sha=$GIT_SHA" \
stage2-nix-psql.pkr.hcl

# Cleanup instances from AMI builds
cleanup_instances() {
echo "Terminating EC2 instances with tag testinfra-run-id=$RUN_ID..."
aws ec2 --region $REGION describe-instances \
--filters "Name=tag:testinfra-run-id,Values=$RUN_ID" \
--query "Reservations[].Instances[].InstanceId" \
--output text | xargs -r aws ec2 terminate-instances \
--region $REGION --instance-ids || true
}

# Set up traps for various signals to ensure cleanup
trap cleanup_instances EXIT HUP INT QUIT TERM

# Create and activate virtual environment
VENV_DIR=$(mktemp -d)
trap 'rm -rf "$VENV_DIR"' EXIT HUP INT QUIT TERM
python3 -m venv "$VENV_DIR"
source "$VENV_DIR/bin/activate"

# Install required Python packages
echo "Installing required Python packages..."
pip install boto3 boto3-stubs[essential] docker ec2instanceconnectcli pytest paramiko requests

# Run the tests with aws-vault
echo "Running tests for AMI: $RANDOM_STRING using AWS Vault profile: $AWS_VAULT_PROFILE"
aws-vault exec $AWS_VAULT_PROFILE -- pytest -vv -s testinfra/test_ami_nix.py
# Check AWS Vault profile
if [ -z "''${AWS_VAULT:-}" ]; then
echo "Error: AWS_VAULT environment variable must be set with the profile name"
echo "Usage: aws-vault exec <profile-name> -- nix run .#build-test-ami <postgres-version>"
exit 1
fi

# Deactivate virtual environment (cleanup is handled by trap)
deactivate
EOL
chmod +x $out/bin/build-test-ami
'';
# Set values
REGION="ap-southeast-1"
POSTGRES_VERSION="$1"
RANDOM_STRING=$(openssl rand -hex 8)
GIT_SHA=$(git rev-parse HEAD)
RUN_ID=$(date +%s)

# Generate common-nix.vars.pkr.hcl
PG_VERSION=$(yq -r ".postgres_release[\"postgres$POSTGRES_VERSION\"]" ansible/vars.yml)
echo "postgres-version = \"$PG_VERSION\"" > common-nix.vars.pkr.hcl

# Build AMI Stage 1
packer init amazon-arm64-nix.pkr.hcl
packer build \
-var "git-head-version=$GIT_SHA" \
-var "packer-execution-id=$RUN_ID" \
-var-file="development-arm.vars.pkr.hcl" \
-var-file="common-nix.vars.pkr.hcl" \
-var "ansible_arguments=" \
-var "postgres-version=$RANDOM_STRING" \
-var "region=$REGION" \
-var 'ami_regions=["'"$REGION"'"]' \
-var "force-deregister=true" \
-var "ansible_arguments=-e postgresql_major=$POSTGRES_VERSION" \
amazon-arm64-nix.pkr.hcl

# Build AMI Stage 2
packer init stage2-nix-psql.pkr.hcl
packer build \
-var "git-head-version=$GIT_SHA" \
-var "packer-execution-id=$RUN_ID" \
-var "postgres_major_version=$POSTGRES_VERSION" \
-var-file="development-arm.vars.pkr.hcl" \
-var-file="common-nix.vars.pkr.hcl" \
-var "postgres-version=$RANDOM_STRING" \
-var "region=$REGION" \
-var 'ami_regions=["'"$REGION"'"]' \
-var "force-deregister=true" \
-var "git_sha=$GIT_SHA" \
stage2-nix-psql.pkr.hcl

# Cleanup instances from AMI builds
cleanup_instances() {
echo "Terminating EC2 instances with tag testinfra-run-id=$RUN_ID..."
aws ec2 --region $REGION describe-instances \
--filters "Name=tag:testinfra-run-id,Values=$RUN_ID" \
--query "Reservations[].Instances[].InstanceId" \
--output text | xargs -r aws ec2 terminate-instances \
--region $REGION --instance-ids || true
}

# Set up traps for various signals to ensure cleanup
trap cleanup_instances EXIT HUP INT QUIT TERM
'';

run-testinfra = pkgs.runCommand "run-testinfra"
{
Expand Down
31 changes: 31 additions & 0 deletions nix/ext/pg_cron-1.3.1-pg15.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
diff --git a/src/pg_cron.c b/src/pg_cron.c
index e0ca973..4d51b2c 100644
--- a/src/pg_cron.c
+++ b/src/pg_cron.c
@@ -14,6 +14,8 @@
#include <sys/resource.h>

#include "postgres.h"
+#include "commands/async.h"
+#include "miscadmin.h"
#include "fmgr.h"

/* these are always necessary for a bgworker */
@@ -1908,7 +1910,7 @@ CronBackgroundWorker(Datum main_arg)
/* Post-execution cleanup. */
disable_timeout(STATEMENT_TIMEOUT, false);
CommitTransactionCommand();
- ProcessCompletedNotifies();
+ /* ProcessCompletedNotifies removed */
pgstat_report_activity(STATE_IDLE, command);
pgstat_report_stat(true);

@@ -2025,7 +2027,7 @@ ExecuteSqlString(const char *sql)
*/
oldcontext = MemoryContextSwitchTo(parsecontext);
#if PG_VERSION_NUM >= 100000
- querytree_list = pg_analyze_and_rewrite(parsetree, sql, NULL, 0,NULL);
+ querytree_list = pg_analyze_and_rewrite_fixedparams(parsetree, sql, NULL, 0, NULL);
#else
querytree_list = pg_analyze_and_rewrite(parsetree, sql, NULL, 0);
#endif
Loading
Loading