diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 92c9d7549..010522574 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,7 +6,7 @@ on: pull_request: branches: [ master ] schedule: - - cron: "0 8 * * *" + - cron: "0 0 * * Fri" defaults: run: @@ -23,7 +23,7 @@ jobs: - ubuntu-24.04 - macos-12 - macos-13 - - macos-14 # M1 CPU + - macos-14 - windows-2019 - windows-2022 steps: @@ -47,15 +47,24 @@ jobs: SERVICE_NAME: ${{ steps.postgres.outputs.service-name }} EXPECTED_CONNECTION_URI: postgresql://postgres:postgres@localhost:5432/postgres EXPECTED_SERVICE_NAME: postgres + EXPECTED_SERVER_VERSION: "16" parametrized: runs-on: ${{ matrix.os }} strategy: matrix: os: - - ubuntu-latest - - macos-latest - - windows-latest + - ubuntu-20.04 + - ubuntu-22.04 + - ubuntu-24.04 + - macos-12 + - macos-13 + - macos-14 + - windows-2019 + - windows-2022 + postgres-version: + - "14" + - "15" steps: - uses: actions/checkout@v4 @@ -66,6 +75,7 @@ jobs: password: GrandMaster database: jedi_order port: 34837 + postgres-version: ${{ matrix.postgres-version }} id: postgres - name: Run setup-python @@ -82,3 +92,4 @@ jobs: SERVICE_NAME: ${{ steps.postgres.outputs.service-name }} EXPECTED_CONNECTION_URI: postgresql://yoda:GrandMaster@localhost:34837/jedi_order EXPECTED_SERVICE_NAME: yoda + EXPECTED_SERVER_VERSION: ${{ matrix.postgres-version }} diff --git a/README.md b/README.md index 5115bceb3..8aefbe802 100644 --- a/README.md +++ b/README.md @@ -9,12 +9,13 @@ key features: * Runs on Linux, macOS and Windows action runners. * Adds PostgreSQL [client applications][1] to `PATH`. -* Uses PostgreSQL binaries baked into [GitHub Actions Runner Images][2]. -* Easy [to prove][3] that it DOES NOT contain malicious code. +* PostgreSQL version can be parametrized. +* Easy [to verify][2] that it DOES NOT contain malicious code. + +By default PostgreSQL 15 is used. [1]: https://www.postgresql.org/docs/current/reference-client.html -[2]: https://github.com/actions/runner-images -[3]: action.yml +[2]: action.yml ## Usage @@ -33,12 +34,13 @@ key features: #### Action Parameters -| Key | Value | Default | -|------------|------------------------------------------------------------------------------------------------------|-------------| -| username | The username of the user to setup. | `postgres` | -| password | The password of the user to setup. | `postgres` | -| database | The database name to setup and grant permissions to created user. | `postgres` | -| port | The server port to listen on. | `5432` | +| Key | Value | Default | +|------------------|------------------------------------------------------------------------------------|-------------| +| username | The username of the user to setup. | `postgres` | +| password | The password of the user to setup. | `postgres` | +| database | The database name to setup and grant permissions to created user. | `postgres` | +| port | The server port to listen on. | `5432` | +| postgres-version | The PostgreSQL major version to install. Supported values: "14", "15", "16". | `16` | #### Outputs @@ -58,19 +60,20 @@ key features: ```yaml steps: - - uses: ikalnytskyi/action-setup-postgres@v6 + - uses: ikalnytskyi/action-setup-postgres@v6 ``` #### Advanced ```yaml steps: - - uses: ikalnytskyi/action-setup-postgres@v6 + - uses: ikalnytskyi/action-setup-postgres@v6 with: username: ci password: sw0rdfish database: test port: 34837 + postgres-version: "14" id: postgres - run: pytest -vv tests/ @@ -88,7 +91,7 @@ steps: ```yaml steps: - - uses: ikalnytskyi/action-setup-postgres@v6 + - uses: ikalnytskyi/action-setup-postgres@v6 - run: | createuser myuser @@ -110,7 +113,7 @@ steps: ```yaml steps: - - uses: ikalnytskyi/action-setup-postgres@v6 + - uses: ikalnytskyi/action-setup-postgres@v6 ``` ```python diff --git a/action.yml b/action.yml index d63da77a1..14c95da76 100644 --- a/action.yml +++ b/action.yml @@ -21,6 +21,10 @@ inputs: description: The server port to listen on. default: "5432" required: false + postgres-version: + description: The PostgreSQL major version to install. Either "14", "15", or "16". + default: "16" + required: false outputs: connection-uri: description: The connection URI to connect to PostgreSQL. @@ -31,38 +35,63 @@ outputs: runs: using: composite steps: - - name: Prerequisites + - name: Install PostgreSQL run: | + if [[ ! "${{ inputs.postgres-version }}" =~ ^(14|15|16)$ ]]; then + echo "::error::postgres-version must be one of: 14, 15, 16." + exit 1 + fi + if [ "$RUNNER_OS" == "Linux" ]; then - echo "$(pg_config --bindir)" >> $GITHUB_PATH - elif [ "$RUNNER_OS" == "Windows" ]; then - echo "$PGBIN" >> $GITHUB_PATH - echo "PQ_LIB_DIR=$PGROOT\lib" >> $GITHUB_ENV + APT_ENTRY="deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" + APT_KEY="https://www.postgresql.org/media/keys/ACCC4CF8.asc" + + echo "$APT_ENTRY" | sudo tee /etc/apt/sources.list.d/pgdg.list + wget --quiet -O - "$APT_KEY" | sudo apt-key add - + sudo apt-get update + sudo apt-get -y install postgresql-${{ inputs.postgres-version }} + + PG_BINDIR=$("/usr/lib/postgresql/${{ inputs.postgres-version }}/bin/pg_config" --bindir) + echo "$PG_BINDIR" >> $GITHUB_PATH + elif [ "$RUNNER_OS" == "Windows" ]; then # The Windows runner has some PostgreSQL environment variables set # that may confuse users since they may be irrelevant to the - # PostgreSQL server we're using. + # PostgreSQL server we're using. Since GitHub actions does not + # support unsetting environment variables, the best we can do is to + # clear their values in order to indicate they must not be used. for name in "PGROOT" "PGDATA" "PGBIN" "PGUSER" "PGPASSWORD"; do echo "$name=" >> $GITHUB_ENV done + + choco install postgresql${{ inputs.postgres-version }} \ + --params "/Password:${{ inputs.password }}" \ + --ia "--enable-components server,commandlinetools --extract-only 1" \ + --no-progress + + PG_BINDIR=$("$PROGRAMFILES/PostgreSQL/${{ inputs.postgres-version }}/bin/pg_config.exe" --bindir) + PG_LIBDIR=$("$PROGRAMFILES/PostgreSQL/${{ inputs.postgres-version }}/bin/pg_config.exe" --libdir) + + echo "$PG_BINDIR" >> $GITHUB_PATH + echo "PQ_LIB_DIR=$PG_LIBDIR" >> $GITHUB_ENV + elif [ "$RUNNER_OS" == "macOS" ]; then - case "$(sw_vers -productVersion)" in - 13.*|14.*) - # Unfortunately, the macOS 13 runner image doesn't come w/ - # pre-installed PostgreSQL server. - export HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 - export HOMEBREW_NO_INSTALL_CLEANUP=1 - export HOMEBREW_NO_INSTALL_UPGRADE=1 - brew install --skip-post-install postgresql@14 - ;; - esac + export HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 + export HOMEBREW_NO_INSTALL_CLEANUP=1 + export HOMEBREW_NO_INSTALL_UPGRADE=1 + brew install --skip-post-install postgresql@${{ inputs.postgres-version }} + + # Link PostgreSQL binaries from /usr/local/bin in order to make them + # available globally. The overwrite option is required since some + # GitHub runners come with preinstalled PostgreSQL binaries. + brew link --overwrite postgresql@${{ inputs.postgres-version }} fi shell: bash - name: Setup and start PostgreSQL run: | - export PGDATA="$RUNNER_TEMP/pgdata" - export PWFILE="$RUNNER_TEMP/pwfile" + PGDATA="$RUNNER_TEMP/pgdata" + PWFILE="$RUNNER_TEMP/pwfile" DEFAULT_ENCODING="UTF-8" DEFAULT_LOCALE="en_US.$DEFAULT_ENCODING" @@ -91,6 +120,7 @@ runs: # # [1] https://www.postgresql.org/docs/15/reference-client.html initdb \ + --pgdata="$PGDATA" \ --username="${{ inputs.username }}" \ --pwfile="$PWFILE" \ --auth="scram-sha-256" \ @@ -102,7 +132,7 @@ runs: # directory we have no permissions to (owned by system postgres user). echo "unix_socket_directories = ''" >> "$PGDATA/postgresql.conf" echo "port = ${{ inputs.port }}" >> "$PGDATA/postgresql.conf" - pg_ctl start + pg_ctl start --pgdata="$PGDATA" # Save required connection parameters for created superuser to the # connection service file [1]. This allows using these connection diff --git a/test_action.py b/test_action.py index 537d3fd62..809b2aa9c 100644 --- a/test_action.py +++ b/test_action.py @@ -140,6 +140,13 @@ def test_environment_variables(is_windows: bool): assert pg_environ == pg_environ_exp +def test_server_version(connection: psycopg.Connection): + """Test that PostgreSQL's version is expected.""" + + server_version = connection.execute("SHOW SERVER_VERSION").fetchone()[0] + assert server_version.split(".")[0] == os.getenv("EXPECTED_SERVER_VERSION") + + def test_user_permissions(connection: psycopg.Connection): """Test that a user has super/createdb permissions."""