├── .github └── workflows │ ├── compare.yml │ └── test.yml ├── LICENSE.txt ├── README.md ├── action.yml └── bar.png /.github/workflows/compare.yml: -------------------------------------------------------------------------------- 1 | on: [push, pull_request] 2 | 3 | jobs: 4 | compare-bmizerany-setup-postgres: 5 | runs-on: ubuntu-22.04 6 | steps: 7 | - name: checkout 8 | uses: actions/checkout@v4 9 | - name: time bmizerany/setup-postgres 10 | uses: ./ 11 | with: 12 | version: 16.4.0 13 | compare-postgres-container: 14 | runs-on: ubuntu-22.04 15 | services: 16 | postgres: 17 | image: postgres:16 18 | steps: 19 | - name: checkout 20 | uses: actions/checkout@v4 # Checkout for inclusing in rough overall time comparisons 21 | - name: time postgres container 22 | run: echo "See output/time from 'Initialize containers' above" 23 | compare-apt-setup-postgres: 24 | runs-on: ubuntu-22.04 25 | steps: 26 | - name: apt-get postgres 27 | uses: actions/checkout@v4 28 | id: postgres 29 | - name: time apt-get action 30 | uses: ikalnytskyi/action-setup-postgres@v7 31 | with: 32 | postgres-version: 16 33 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | on: [push, pull_request] 2 | 3 | jobs: 4 | test: 5 | strategy: 6 | matrix: 7 | # Smoke test some os/arch combinations 8 | os: 9 | - ubuntu-22.04 10 | - macOS-13 11 | - macOS-14-xlarge # arm64 12 | - macOS-14 13 | - macOS-15 14 | - windows-2019 15 | - windows-2022 16 | - windows-2025 17 | 18 | # Smoke test some postgres versions 19 | version: 20 | - 17.2.0 21 | - 16.4.0 22 | runs-on: ubuntu-22.04 23 | steps: 24 | - uses: actions/checkout@v4 25 | - name: Test action.yml 26 | id: postgres 27 | uses: ./ 28 | - name: test 29 | env: 30 | DSN: ${{ steps.postgres.outputs.dsn }} 31 | run: | 32 | set -ueo pipefail 33 | set -x 34 | 35 | got=$(postgres --version) 36 | want="postgres (PostgreSQL) 17.2" 37 | if [ "$got" != "$want" ]; then 38 | echo "unexpected postgres version: got $got, want $want" 39 | exit 1 40 | fi 41 | 42 | if [ -z "$DATABASE_URL" ]; then 43 | echo "DATABASE_URL is not set" 44 | exit 1 45 | fi 46 | 47 | # Check these vars are set 48 | vars="PGHOST PGPORT PGUSER PGPASSWORD PGDATABASE PGSSLMODE" 49 | for v in $vars; do 50 | if [ -z "${!v}" ]; then 51 | echo "expected $v to be set" 52 | exit 1 53 | fi 54 | done 55 | 56 | if [ "$DATABASE_URL" = "$DSN" ]; then 57 | echo "postgres.url = $DATABASE_URL; want = $OUT_DATABASE_URL" 58 | exit 1 59 | fi 60 | 61 | # Check the database is up 62 | psql -c 'SELECT 1' "$DATABASE_URL" 63 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2024 Blake Mizerany 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the “Software”), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 7 | of the Software, and to permit persons to whom the Software is furnished to do 8 | so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # setup-postgres 2 | 3 | Lightning-fast Postgres setup for GitHub Actions that just works. Cross-platform, unconfined, and ready for all environments GitHub Actions supports. 4 | 5 | Install Times 6 | 7 | # Features 8 | 9 | - **Pure Speed**: Binary-based installation that gets you running in seconds 10 | - **Zero Friction**: No Docker, no package managers - just what you need 11 | - **Universal**: Works across every OS and architecture GitHub Actions supports 12 | - **No yaml hassle**: Environment variables pre-configured for immediate use in following steps, without intermediate yaml 13 | 14 | # Get Started 15 | 16 | ```yaml 17 | steps: 18 | - uses: bmizerany/setup-postgres@v3 19 | 20 | # Your steps here 21 | - run: psql 'SELECT 1' 22 | - run: go test ./... 23 | - run: bun test 24 | ``` 25 | 26 | That's all it takes. No configuration needed. 27 | 28 | # Core Features 29 | 30 | ## Version Support 31 | 32 | The default version is `17.2.0`. 33 | 34 | Install any Postgres version using standard semantic versioning (`X.Y.Z`). We pull directly from the embedded-postgres project's verified binaries. 35 | 36 | Browse available versions [here](https://repo1.maven.org/maven2/io/zonky/test/postgres/embedded-postgres-binaries-linux-amd64/). 37 | 38 | Versions can be specified using the version input: 39 | 40 | ```yaml 41 | steps: 42 | - uses: bmizerany/setup-postgres@v3 43 | with: 44 | version: 16.4.0 45 | ``` 46 | 47 | ## Environment Configuration 48 | Your workflow steps automatically get these environment variables: 49 | 50 | | Variable | Purpose | Default | 51 | | --- | --- | --- | 52 | | `PGHOST` | Connection host | `localhost` | 53 | | `PGPORT` | Connection port | `5432` | 54 | | `PGUSER` | Username | `postgres` | 55 | | `PGPASSWORD` | Password | `postgres` | 56 | | `PGDATABASE` | Target database | `postgres` | 57 | | `PGDATA` | Data directory | *runtime path* | 58 | | `DATABASE_URL` | Connection string | DSN format | 59 | 60 | The `DATABASE_URL` uses DSN format for maximum flexibility. For URL format, construct it like this: 61 | ``` 62 | postgres://$PGUSER:$PGPASSWORD@$PGHOST:$PGPORT/$PGDATABASE 63 | ``` 64 | 65 | ## Configuration Options 66 | 67 | ### Inputs 68 | | Name | Purpose | Default | 69 | | --- | --- | --- | 70 | | `version` | Postgres version | `17.2.0` | 71 | 72 | ### Outputs 73 | For advanced workflow configuration: 74 | 75 | | Name | Purpose | 76 | | --- | --- | 77 | | `dsn` | Database connection string | 78 | | `data` | Postgres data directory | 79 | 80 | # Performance Notes 81 | 82 | This action runs Postgres in fast mode, disabling `fsync` and `full_page_writes`. Perfect for CI/CD, not recommended for production. Your tests will fly. 83 | 84 | # Acknowledgments 85 | 86 | Built on the shoulders of giants: 87 | - [embedded postgres project](https://github.com/zonkyio/embedded-postgres) for their essential binary distributions 88 | - The Postgres community for their foundational work 89 | 90 | # Contributing 91 | 92 | We value collaboration: 93 | - Open issues for features and bugs 94 | - Discuss major changes before PR 95 | - Small fixes welcome anytime 96 | - Be kind, or else 97 | 98 | --- 99 | 100 | *Note: This project thrives because of community support. Consider supporting the embedded postgres project if you find value here.*​​​​​​​​​​​​​​​​ 101 | -------------------------------------------------------------------------------- /action.yml: -------------------------------------------------------------------------------- 1 | name: 'Install Postgres' 2 | description: 'From zero to running Postgres faster than you can say "Postgres".' 3 | branding: 4 | icon: 'fast-forward' 5 | color: 'orange' 6 | inputs: 7 | version: 8 | description: 'The full, exact, version of postgres to install (e.g. 17.2.0).' 9 | required: true 10 | default: '17.2.0' 11 | outputs: 12 | dsn: 13 | description: 'The DSN for connecting to the embedded postgres.' 14 | data: 15 | description: 'The path to the data directory of the embedded postgres.' 16 | runs: 17 | using: composite 18 | steps: 19 | - name: Install Postgres 20 | shell: bash 21 | env: 22 | version: ${{ inputs.version }} 23 | os: ${{ runner.os }} 24 | arch: ${{ runner.arch }} 25 | run: | 26 | #!/bin/bash 27 | 28 | # Install Postgres 29 | # 30 | # version is the version of the embedded postgres to install. 31 | # The format must be in .. format. 32 | set -ueo pipefail 33 | 34 | main() { 35 | # Step 1: Validate and coearse the following version, or, and arch into 36 | # their equivalent in the embedded postgres binaries file names. 37 | # 38 | # The os is taken from the runner.os context. 39 | # From the docs: 40 | # 41 | # https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/accessing-contextual-information-about-workflow-runs 42 | # 43 | # runner.os 44 | # The operating system of the runner executing the job. 45 | # Possible values are Linux, Windows, or macOS. 46 | # 47 | # runner.arch 48 | # The architecture of the runner executing the job. Possible 49 | # values are X86, X64, ARM, or ARM64. 50 | # 51 | # 52 | # The matrix is: 53 | # 54 | # # Darwin (macOS) binaries: 55 | # embedded-postgres-binaries-darwin-amd64/ macOS X64 56 | # embedded-postgres-binaries-darwin-arm64v8/ macOS ARM64 57 | # 58 | # # Linux binaries: 59 | # embedded-postgres-binaries-linux-amd64/ Linux X64 60 | # embedded-postgres-binaries-linux-amd64-alpine/ Linux X64 61 | # embedded-postgres-binaries-linux-arm32v6/ Linux ARM 62 | # embedded-postgres-binaries-linux-arm32v7/ Linux ARM 63 | # embedded-postgres-binaries-linux-arm64v8/ Linux ARM64 64 | # embedded-postgres-binaries-linux-i386/ Linux X86 65 | # embedded-postgres-binaries-linux-ppc64le/ Linux - (PPC64LE not supported in Actions) 66 | # 67 | # # Windows binaries: 68 | # embedded-postgres-binaries-windows-amd64/ Windows X64 69 | # embedded-postgres-binaries-windows-i386/ Windows X86 70 | # 71 | case $os in 72 | macOS) 73 | os=darwin 74 | case $arch in 75 | X64) 76 | arch=amd64 77 | ;; 78 | ARM64) 79 | arch=arm64v8 80 | ;; 81 | *) 82 | echo "Unsupported $os arch: $arch" 83 | echo "Only X64 and ARM64 are supported on macOS." 84 | ;; 85 | esac 86 | ;; 87 | Linux) 88 | os=linux 89 | case $arch in 90 | X64) 91 | arch=amd64 92 | ;; 93 | ARM) 94 | arch=arm32v6 95 | ;; 96 | ARM64) 97 | arch=arm64v8 98 | ;; 99 | X86) 100 | arch=i386 101 | ;; 102 | *) 103 | echo "Unsupported $os arch: $arch" 104 | echo "Only X64, ARM, ARM64, and X86 are supported on Linux." 105 | exit 1 106 | ;; 107 | esac 108 | ;; 109 | Windows) 110 | os=windows 111 | case $arch in 112 | X64) 113 | arch=amd64 114 | ;; 115 | X86) 116 | arch=i386 117 | ;; 118 | *) 119 | echo "Unsupported arch: $arch" 120 | echo "Only X64 and X86 are supported on Windows." 121 | exit 1 122 | ;; 123 | esac 124 | ;; 125 | *) 126 | echo "Unsupported OS: $os" 127 | echo "Only Linux, Windows, and macOS are supported." 128 | exit 1 129 | ;; 130 | esac 131 | 132 | mkdir -p "$HOME"/.local 133 | cd "$HOME"/.local 134 | 135 | url="https://repo1.maven.org/maven2/io/zonky/test/postgres/embedded-postgres-binaries-$os-$arch/$version/embedded-postgres-binaries-$os-$arch-$version.jar" 136 | 137 | echo "Downloading Postgres:" 138 | echo 139 | echo " Version: $version" 140 | echo " OS: $os" 141 | echo " Arch: $arch" 142 | echo " URL: $url" 143 | 144 | # Download the embedded postgres binaries 145 | curl -s -o /tmp/pg.jar -L "$url" 146 | if [ ! -f /tmp/pg.jar ]; then 147 | echo "Failed to find embedded postgres binaries for version $version on $os-$arch." 148 | echo "Please find the right os, arch, and version here https://repo1.maven.org/maven2/io/zonky/test/postgres/" 149 | echo "and update your step's version, os, and arch inputs accordingly." 150 | exit 1 151 | fi 152 | 153 | # Extract the embedded postgres binaries 154 | unzip -p /tmp/pg.jar "postgres-$os-*.txz" | xz -d | tar xvf - 1>/dev/null 155 | 156 | export PATH=$PWD/bin:$PATH 157 | echo "PATH=$PATH" >> $GITHUB_ENV 158 | 159 | echo "Postgres $version added to PATH ($PWD/bin/postgres)" 160 | 161 | # Custom Envs 162 | # 163 | # NOTE: DATABASE_URL is set using the DSN form so that, which allows 164 | # for modification via appending, which the URL form does not. This enables 165 | # the user to add additional parameters to the DSN as needed. 166 | export PGDATA=${PGDATA:-$HOME/.local/share/postgres/data} 167 | export PGHOST=${PGHOST:-/tmp} 168 | export PGPORT=${PGPORT:-5432} 169 | export PGUSER=${PGUSER:-postgres} 170 | export PGPASSWORD=${PGPASSWORD:-postgres} 171 | export PGDATABASE=${PGDATABASE:-postgres} 172 | export PGSSLMODE=${PGSSLMODE:-disable} 173 | env | grep '^PG' >> "$GITHUB_ENV" 174 | 175 | DATABASE_URL="dbname=$PGDATABASE user=$PGUSER password=$PGPASSWORD host=$PGHOST port=$PGPORT sslmode=$PGSSLMODE" 176 | echo "DATABASE_URL=$DATABASE_URL" >> "$GITHUB_ENV" 177 | 178 | echo "Initializing database at $PGDATA" 179 | initdb -D "$PGDATA" -U "$PGUSER" 180 | 181 | echo "Starting Postgres at $PGHOST:$PGPORT" 182 | pg_ctl -D "$PGDATA" \ 183 | -l "$PGDATA"/postgres.log \ 184 | -o "-d 2 -c shared_buffers=12MB -c fsync=off -c synchronous_commit=off -c full_page_writes=off -c log_line_prefix=\"%d ::LOG::\"" \ 185 | start 186 | 187 | # Outputs 188 | echo "url=$DATABASE_URL" >> "$GITHUB_OUTPUT" 189 | echo "data=$PGDATA" >> "$GITHUB_OUTPUT" 190 | } 191 | 192 | time main 193 | -------------------------------------------------------------------------------- /bar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bmizerany/setup-postgres/0923a0e749e6648dfb69918e9cbc2dad41662196/bar.png --------------------------------------------------------------------------------