Skip to content

Commit 0eeadbd

Browse files
committed
chore: github actions
1 parent 822b391 commit 0eeadbd

File tree

3 files changed

+291
-0
lines changed

3 files changed

+291
-0
lines changed
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
name: PGSchema Plan - Multi File
2+
3+
on:
4+
pull_request:
5+
types: [opened, synchronize, reopened]
6+
paths:
7+
- 'multifile/**'
8+
- '.github/workflows/pgschema-plan-multi.yml'
9+
10+
permissions:
11+
contents: read
12+
pull-requests: write
13+
14+
jobs:
15+
pgschema-plan-multi:
16+
runs-on: ubuntu-latest
17+
18+
steps:
19+
- name: Checkout code
20+
uses: actions/checkout@v4
21+
22+
- name: Setup Go
23+
uses: actions/setup-go@v5
24+
with:
25+
go-version: 'stable'
26+
27+
- name: Install pgschema
28+
run: go install github.com/pgschema/pgschema@latest
29+
30+
- name: Run pgschema plan
31+
id: plan
32+
run: |
33+
# Run pgschema plan with directory of SQL files
34+
PLAN_OUTPUT=$(pgschema plan \
35+
--host "${{ secrets.DB_HOST }}" \
36+
--port "${{ secrets.DB_PORT }}" \
37+
--db "${{ secrets.DB_NAME }}" \
38+
--user "${{ secrets.DB_USER }}" \
39+
--file "${{ github.workspace }}/multifile/main.sql" \
40+
--format human 2>&1)
41+
42+
# Escape special characters for GitHub Actions
43+
PLAN_OUTPUT="${PLAN_OUTPUT//'%'/'%25'}"
44+
PLAN_OUTPUT="${PLAN_OUTPUT//$'\n'/'%0A'}"
45+
PLAN_OUTPUT="${PLAN_OUTPUT//$'\r'/'%0D'}"
46+
47+
# Set output
48+
echo "plan<<EOF" >> $GITHUB_OUTPUT
49+
echo "$PLAN_OUTPUT" >> $GITHUB_OUTPUT
50+
echo "EOF" >> $GITHUB_OUTPUT
51+
env:
52+
PGPASSWORD: ${{ secrets.DB_PASSWORD }}
53+
54+
- name: Comment PR
55+
uses: actions/github-script@v7
56+
with:
57+
github-token: ${{secrets.GITHUB_TOKEN}}
58+
script: |
59+
const planOutput = `${{ steps.plan.outputs.plan }}`;
60+
61+
// Decode the escaped output
62+
const decodedOutput = decodeURIComponent(planOutput);
63+
64+
const body = `## PGSchema Plan Output (Multi File)
65+
66+
<details>
67+
<summary>Click to expand plan details</summary>
68+
69+
\`\`\`
70+
${decodedOutput}
71+
\`\`\`
72+
73+
</details>
74+
75+
---
76+
*This comment was automatically generated by the PGSchema Multi File Plan workflow.*`;
77+
78+
// Try to find existing comment
79+
const { data: comments } = await github.rest.issues.listComments({
80+
...context.repo,
81+
issue_number: context.issue.number,
82+
});
83+
84+
const botComment = comments.find(comment =>
85+
comment.user.type === 'Bot' &&
86+
comment.body.includes('PGSchema Plan Output (Multi File)')
87+
);
88+
89+
if (botComment) {
90+
// Update existing comment
91+
await github.rest.issues.updateComment({
92+
...context.repo,
93+
comment_id: botComment.id,
94+
body: body
95+
});
96+
} else {
97+
// Create new comment
98+
await github.rest.issues.createComment({
99+
...context.repo,
100+
issue_number: context.issue.number,
101+
body: body
102+
});
103+
}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
name: PGSchema Plan - Single File
2+
3+
on:
4+
pull_request:
5+
types: [opened, synchronize, reopened]
6+
paths:
7+
- 'singlefile/**'
8+
- '.github/workflows/pgschema-plan-single.yml'
9+
10+
permissions:
11+
contents: read
12+
pull-requests: write
13+
14+
jobs:
15+
pgschema-plan-single:
16+
runs-on: ubuntu-latest
17+
18+
steps:
19+
- name: Checkout code
20+
uses: actions/checkout@v4
21+
22+
- name: Setup Go
23+
uses: actions/setup-go@v5
24+
with:
25+
go-version: 'stable'
26+
27+
- name: Install pgschema
28+
run: go install github.com/pgschema/pgschema@latest
29+
30+
- name: Run pgschema plan
31+
id: plan
32+
run: |
33+
# Run pgschema plan and capture output
34+
PLAN_OUTPUT=$(pgschema plan \
35+
--host "${{ secrets.DB_HOST }}" \
36+
--port "${{ secrets.DB_PORT }}" \
37+
--db "${{ secrets.DB_NAME }}" \
38+
--user "${{ secrets.DB_USER }}" \
39+
--file "${{ github.workspace }}/singlefile/schema.sql" \
40+
--format human 2>&1)
41+
42+
# Escape special characters for GitHub Actions
43+
PLAN_OUTPUT="${PLAN_OUTPUT//'%'/'%25'}"
44+
PLAN_OUTPUT="${PLAN_OUTPUT//$'\n'/'%0A'}"
45+
PLAN_OUTPUT="${PLAN_OUTPUT//$'\r'/'%0D'}"
46+
47+
# Set output
48+
echo "plan<<EOF" >> $GITHUB_OUTPUT
49+
echo "$PLAN_OUTPUT" >> $GITHUB_OUTPUT
50+
echo "EOF" >> $GITHUB_OUTPUT
51+
env:
52+
PGPASSWORD: ${{ secrets.DB_PASSWORD }}
53+
54+
- name: Comment PR
55+
uses: actions/github-script@v7
56+
with:
57+
github-token: ${{secrets.GITHUB_TOKEN}}
58+
script: |
59+
const planOutput = `${{ steps.plan.outputs.plan }}`;
60+
61+
// Decode the escaped output
62+
const decodedOutput = decodeURIComponent(planOutput);
63+
64+
const body = `## PGSchema Plan Output (Single File)
65+
66+
<details>
67+
<summary>Click to expand plan details</summary>
68+
69+
\`\`\`
70+
${decodedOutput}
71+
\`\`\`
72+
73+
</details>
74+
75+
---
76+
*This comment was automatically generated by the PGSchema Single File Plan workflow.*`;
77+
78+
// Try to find existing comment
79+
const { data: comments } = await github.rest.issues.listComments({
80+
...context.repo,
81+
issue_number: context.issue.number,
82+
});
83+
84+
const botComment = comments.find(comment =>
85+
comment.user.type === 'Bot' &&
86+
comment.body.includes('PGSchema Plan Output (Single File)')
87+
);
88+
89+
if (botComment) {
90+
// Update existing comment
91+
await github.rest.issues.updateComment({
92+
...context.repo,
93+
comment_id: botComment.id,
94+
body: body
95+
});
96+
} else {
97+
// Create new comment
98+
await github.rest.issues.createComment({
99+
...context.repo,
100+
issue_number: context.issue.number,
101+
body: body
102+
});
103+
}

README.md

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,86 @@
1+
# PGSchema GitHub Actions Example
12

3+
This repository demonstrates how to use [pgschema](https://www.pgschema.com/) with GitHub Actions to automatically run schema migration plans on pull requests. It includes examples for both single-file and multi-file schema approaches.
4+
5+
## Overview
6+
7+
This repository contains two workflows:
8+
1. **Single File Workflow** - For projects with all schema definitions in one file
9+
2. **Multi File Workflow** - For projects with schema split across multiple SQL files
10+
11+
Both workflows automatically:
12+
- Run `pgschema plan` when a PR modifies schema files
13+
- Post the migration plan as a comment on the PR
14+
- Update the comment if the PR is synchronized with new changes
15+
16+
## Setup
17+
18+
### 1. Required GitHub Secrets
19+
20+
Configure the following secrets in your repository settings:
21+
22+
- `DB_HOST` - PostgreSQL database host (default: localhost)
23+
- `DB_PORT` - PostgreSQL database port (default: 5432)
24+
- `DB_NAME` - Database name
25+
- `DB_USER` - Database username
26+
- `DB_PASSWORD` - Database password
27+
28+
### 2. Schema Organization
29+
30+
#### Single File Approach
31+
- Place your complete schema in `singlefile/schema.sql`
32+
- All tables, indexes, functions, and triggers in one file
33+
- Workflow: `.github/workflows/pgschema-plan-single.yml`
34+
35+
#### Multi File Approach
36+
- Place SQL files in the `multifile/` directory
37+
- Uses `main.sql` as the entry point with psql `\i` directives
38+
- Organize files by type in subdirectories (tables/, functions/, views/, etc.)
39+
- Each file contains a specific database object
40+
- Workflow: `.github/workflows/pgschema-plan-multi.yml`
41+
42+
## Usage
43+
44+
1. Choose your schema approach (single file or multi file)
45+
2. Create or update schema files in the appropriate directory
46+
3. Open a pull request
47+
4. The relevant workflow will automatically run and comment with the migration plan
48+
5. Review the plan to understand what changes will be applied
49+
6. The comment will be updated if you push more changes to the PR
50+
51+
## Example Schemas
52+
53+
### Single File Example
54+
See `singlefile/schema.sql` for a complete schema with:
55+
- Users and posts tables
56+
- Foreign key relationships
57+
- Indexes for performance
58+
- Triggers for auto-updating timestamps
59+
60+
### Multi File Example
61+
See `multifile/` directory for a comprehensive schema organization:
62+
- `main.sql` - Entry file using psql `\i` directives to include other files
63+
- `domains/` - Custom domain types (email_address, positive_integer)
64+
- `types/` - Custom types (address, order_status, user_status)
65+
- `sequences/` - Sequence definitions (global_id_seq, order_number_seq)
66+
- `tables/` - Table definitions (users, orders)
67+
- `functions/` - Database functions (get_user_count, update_timestamp)
68+
- `procedures/` - Stored procedures (cleanup_orders, update_status)
69+
- `views/` - Database views (order_details, user_summary)
70+
71+
This structure demonstrates how to organize complex schemas across multiple files and directories.
72+
73+
## Security Notes
74+
75+
- Database credentials are stored as encrypted GitHub secrets
76+
- The workflow only has read access to your database (it runs `plan`, not `apply`)
77+
- Consider using a read-only database user for additional security
78+
79+
## Next Steps
80+
81+
To apply migrations, you would typically:
82+
1. Review and approve the PR
83+
2. Run `pgschema apply` in your deployment pipeline
84+
3. Consider using `--auto-approve` flag for automated deployments
85+
86+
For more information, visit the [pgschema documentation](https://www.pgschema.com/).

0 commit comments

Comments
 (0)