├── .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 |
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
--------------------------------------------------------------------------------