Skip to content

Commit 819949d

Browse files
Merge pull request #25 from nitrictech/database-migration-docs
docs: Add database migrations and guides overview pages
2 parents abaf0ef + 1038fd0 commit 819949d

File tree

5 files changed

+312
-12
lines changed

5 files changed

+312
-12
lines changed
Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
name: Docs Test
1+
name: Test Docs
22

33
on:
44
push:
5-
branches: [ main ]
5+
branches: [main]
66
paths:
7-
- 'docs/**'
7+
- "docs/**"
88
pull_request:
9-
branches: [ main ]
9+
branches: [main]
1010
paths:
11-
- 'docs/**'
11+
- "docs/**"
1212

1313
jobs:
1414
vale:
@@ -22,7 +22,8 @@ jobs:
2222
uses: errata-ai/vale-action@v2
2323
with:
2424
files: '["docs"]'
25-
vale_flags: '--config=docs/.vale.ini'
25+
vale_flags: "--config=docs/.vale.ini"
26+
fail_on_error: true
2627
env:
2728
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
2829

@@ -36,8 +37,8 @@ jobs:
3637
- name: Setup Node.js
3738
uses: actions/setup-node@v4
3839
with:
39-
node-version: '22'
40+
node-version: "22"
4041

4142
- name: Check for broken links
4243
working-directory: docs
43-
run: npx --yes mint@latest broken-links
44+
run: npx --yes mint@latest broken-links

docs/.vale/styles/config/vocabularies/Suga/accept.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ Dockerfile
66
Subcommands
77
SDKs
88
Supabase
9-
9+
Planetscale
10+
liquibase
11+
allowlisting
1012

1113
# Defaults from mintlify
1214
Mintlify

docs/docs.json

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,16 @@
2828
},
2929
{
3030
"dropdown": "Guides",
31-
"description": "In-depth guides for Suga",
31+
"description": "Learn how to use Suga",
3232
"icon": "graduation-cap",
3333
"groups": [
3434
{
35-
"group": "Migrations",
36-
"pages": ["guides/migrate-existing"]
35+
"group": "Overview",
36+
"pages": ["guides/overview"]
37+
},
38+
{
39+
"group": "Guides",
40+
"pages": ["guides/database-migration", "guides/migrate-existing"]
3741
}
3842
]
3943
},

docs/guides/database-migration.mdx

Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
---
2+
title: 'Database Migrations'
3+
description: 'Running migrations for a database deployed with Suga'
4+
---
5+
6+
## With public database (Neon, Supabase, Planetscale etc.)
7+
8+
Running database migrations against services like Neon, Supabase or Planetscale is simple with Suga.
9+
10+
### Prerequisites
11+
12+
1. **Ensure your application build is up to date** by running `suga build` to generate the necessary Terraform configuration
13+
14+
2. **Identify your database module name** from your `suga.yaml` file:
15+
16+
```yaml
17+
databases:
18+
database: # <-- 👀 This will be the terraform module name
19+
env_var_key: DATABASE_URL
20+
```
21+
22+
3. **Ensure your migration tool is available** in your CI/CD environment (e.g., golang-migrate, flyway, liquibase, or a custom migration script)
23+
24+
### Migration Strategy
25+
26+
The recommended approach follows a four-phase deployment pattern:
27+
28+
1. **Deploy database infrastructure first** - Create or update database resources
29+
2. **Extract connection details** - Get the database connection string from Terraform state
30+
3. **Run migrations** - Apply schema changes before deploying application code
31+
4. **Deploy application** - Roll out the updated application that depends on the new schema
32+
33+
### Implementation Steps
34+
35+
<Steps>
36+
<Step title="Deploy Database Module">
37+
First, apply only the database module using Terraform's `-target` flag:
38+
39+
```bash
40+
# Initialize Terraform
41+
terraform init
42+
43+
# Plan database module deployment
44+
terraform plan -target=module.database -out=tfplan-database
45+
46+
# Apply database module
47+
terraform apply tfplan-database
48+
```
49+
</Step>
50+
51+
<Step title="Extract Database Connection String">
52+
After the database module is deployed, extract the connection details from Terraform state:
53+
54+
```bash
55+
# Extract database connection components
56+
terraform output -json database_connection_string
57+
58+
# Or extract from state directly
59+
terraform state show module.database
60+
```
61+
62+
For Neon databases specifically, you'll typically need:
63+
- Role name and password
64+
- Endpoint host
65+
- Database name
66+
- SSL mode (usually `require`)
67+
</Step>
68+
69+
<Step title="Run Migrations">
70+
With the connection string available, run your migrations:
71+
72+
```bash
73+
# Example using golang-migrate
74+
migrate -database "$DATABASE_URL" -path ./migrations up
75+
76+
# Example using a custom migration tool
77+
./run-migrations.sh --database-url "$DATABASE_URL"
78+
79+
# Example using Node.js migration tool
80+
npm run migrate:up
81+
```
82+
</Step>
83+
84+
<Step title="Deploy Application">
85+
After migrations succeed, deploy the complete application stack:
86+
87+
```bash
88+
# Plan full deployment
89+
terraform plan -out=tfplan-app
90+
91+
# Apply all modules
92+
terraform apply tfplan-app
93+
```
94+
</Step>
95+
</Steps>
96+
97+
### Best Practices
98+
99+
1. **Use environment-specific workspaces** to isolate different stages (dev, staging, production)
100+
2. **Implement proper concurrency control** to prevent simultaneous migrations
101+
3. **Always backup data** before running migrations in production
102+
4. **Test migrations** in lower environments first
103+
5. **Use transactional migrations** when possible to enable rollback on failure
104+
6. **Version control your migration files** alongside your application code
105+
106+
### Full Example: Platform-Agnostic Script
107+
108+
Here's a general approach that can be adapted to any CI/CD platform:
109+
110+
```bash
111+
#!/bin/bash
112+
set -e
113+
114+
# Configuration
115+
WORKSPACE="${ENVIRONMENT:-dev}"
116+
TERRAFORM_DIR="./terraform/stacks/suga_platform"
117+
118+
# Step 1: Initialize and select workspace
119+
cd "$TERRAFORM_DIR"
120+
terraform init
121+
terraform workspace select "$WORKSPACE" || terraform workspace new "$WORKSPACE"
122+
123+
# Step 2: Deploy database module
124+
terraform plan -target=module.database -out=tfplan-database
125+
terraform apply tfplan-database
126+
127+
# Step 3: Extract connection string
128+
DATABASE_URL=$(terraform output -raw database_connection_string)
129+
export DATABASE_URL
130+
131+
# Step 4: Run migrations
132+
cd ../../../backend # Adjust path as needed
133+
./migrate up # Replace with your migration command
134+
135+
# Step 5: Deploy application
136+
cd "$TERRAFORM_DIR"
137+
terraform plan -out=tfplan-app
138+
terraform apply tfplan-app
139+
```
140+
141+
### Example: GitHub Actions Implementation
142+
143+
Here's a complete GitHub Actions workflow that implements the migration pattern:
144+
> This is a copy of the workflow used to deploy the Suga platform itself 😃
145+
146+
```yaml
147+
name: Deploy with Database Migrations
148+
149+
on:
150+
push:
151+
branches: [main]
152+
tags: ['v[0-9]+.[0-9]+.[0-9]+']
153+
154+
jobs:
155+
terraform-apply:
156+
name: Deploy Terraform Stack
157+
runs-on: ubuntu-latest
158+
steps:
159+
- name: Checkout code
160+
uses: actions/checkout@v4
161+
162+
- name: Configure AWS credentials
163+
uses: aws-actions/configure-aws-credentials@v4
164+
with:
165+
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
166+
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
167+
aws-region: us-east-2
168+
169+
- name: Setup Terraform
170+
uses: hashicorp/setup-terraform@v3
171+
172+
- name: Set Terraform Workspace
173+
id: workspace
174+
run: |
175+
if [[ "${{ github.ref }}" =~ ^refs/tags/v[0-9]+\.[0-9]+\.[0-9]+ ]]; then
176+
WORKSPACE="production"
177+
elif [[ "${{ github.ref }}" == "refs/heads/main" ]]; then
178+
WORKSPACE="staging"
179+
else
180+
WORKSPACE="dev"
181+
fi
182+
echo "workspace=$WORKSPACE" >> $GITHUB_OUTPUT
183+
184+
- name: Terraform Init
185+
working-directory: ./terraform/stacks/suga_platform
186+
run: terraform init
187+
188+
- name: Create or Select Terraform Workspace
189+
working-directory: ./terraform/stacks/suga_platform
190+
run: |
191+
terraform workspace select ${{ steps.workspace.outputs.workspace }} || \
192+
terraform workspace new ${{ steps.workspace.outputs.workspace }}
193+
194+
# Step 1: Deploy Database Module First
195+
- name: Deploy Database Module
196+
working-directory: ./terraform/stacks/suga_platform
197+
run: |
198+
terraform plan -target=module.database -out=tfplan-database
199+
terraform apply -auto-approve tfplan-database
200+
201+
# Step 2: Extract Database Connection String
202+
- name: Extract Database Connection String
203+
id: db-connection
204+
working-directory: ./terraform/stacks/suga_platform
205+
run: |
206+
# Extract from Terraform state (example for Neon)
207+
STATE_JSON=$(terraform state pull)
208+
209+
ROLE_NAME=$(echo "$STATE_JSON" | jq -r '.resources[] |
210+
select(.module == "module.database" and .type == "neon_role") |
211+
.instances[0].attributes.name')
212+
ROLE_PASSWORD=$(echo "$STATE_JSON" | jq -r '.resources[] |
213+
select(.module == "module.database" and .type == "neon_role") |
214+
.instances[0].attributes.password')
215+
ENDPOINT_HOST=$(echo "$STATE_JSON" | jq -r '.resources[] |
216+
select(.module == "module.database" and .type == "neon_endpoint") |
217+
.instances[0].attributes.host')
218+
DATABASE_NAME=$(echo "$STATE_JSON" | jq -r '.resources[] |
219+
select(.module == "module.database" and .type == "neon_database") |
220+
.instances[0].attributes.name')
221+
222+
DATABASE_URL="postgresql://${ROLE_NAME}:${ROLE_PASSWORD}@${ENDPOINT_HOST}/${DATABASE_NAME}?sslmode=require"
223+
echo "DATABASE_URL=$DATABASE_URL" >> $GITHUB_OUTPUT
224+
225+
# Step 3: Run Database Migrations
226+
- name: Setup Go # Or your migration tool runtime
227+
uses: actions/setup-go@v5
228+
with:
229+
go-version: "1.23"
230+
231+
- name: Run Database Migrations
232+
working-directory: ./backend
233+
env:
234+
DATABASE_URL: ${{ steps.db-connection.outputs.DATABASE_URL }}
235+
run: |
236+
go mod download
237+
go run cmd/migrate/main.go -action=up
238+
239+
# Step 4: Deploy Complete Application
240+
- name: Deploy Application
241+
working-directory: ./terraform/stacks/suga_platform
242+
run: |
243+
terraform plan -out=tfplan-app
244+
terraform apply -auto-approve tfplan-app
245+
```
246+
247+
### Security Considerations
248+
249+
- **Never log database credentials** - Use masked outputs in CI/CD logs
250+
- **Use secure secret management** - Store credentials in CI/CD secret stores
251+
- **Rotate credentials regularly** - Implement credential rotation policies
252+
- **Limit network access** - Use private endpoints or IP allowlisting where possible
253+
254+
## With private databases (Cloud SQL, RDS, etc.)
255+
256+
Coming soon...

docs/guides/overview.mdx

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
---
2+
title: 'Guides Overview'
3+
description: 'Learn how to leverage Suga for common infrastructure patterns and workflows'
4+
---
5+
6+
## Welcome to Suga Guides
7+
8+
These guides provide practical, hands-on instructions for implementing common infrastructure patterns and workflows with Suga. Whether you're setting up CI/CD pipelines, managing databases, or deploying applications, you'll find step-by-step instructions and best practices here.
9+
10+
## Featured Guides
11+
12+
<CardGroup cols={2}>
13+
<Card title="Migrate Existing Applications" icon="truck" href="/guides/migrate-existing">
14+
Step-by-step guide to migrate your existing applications to Suga infrastructure management.
15+
</Card>
16+
<Card title="Database Migrations" icon="database" href="/guides/database-migration">
17+
Learn how to run database migrations as part of your deployment pipeline.
18+
</Card>
19+
</CardGroup>
20+
21+
## Prerequisites
22+
23+
Before diving into the guides, ensure you have:
24+
25+
1. **Suga CLI installed** - See our [Installation Guide](/cli/installation)
26+
2. **A Suga project initialized** - Follow the [Quickstart](/quickstart) to create your first project
27+
3. **Basic Terraform knowledge** - Familiarity with Terraform concepts will help you customize the examples
28+
29+
## Getting Help
30+
31+
- **Documentation** - Browse the complete [CLI Reference](/cli/introduction) for detailed command information
32+
- **Support** - Contact us at [support@nitric.io](mailto:support@nitric.io)
33+
- **Community** - Join our [GitHub Discussions](https://github.com/nitrictech/suga/discussions) to connect with other users
34+
35+
## Contributing
36+
37+
Found an issue or have a suggestion for these guides? We welcome contributions! Please open an issue or pull request on our [GitHub repository](https://github.com/nitrictech/suga).

0 commit comments

Comments
 (0)