Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,59 @@ The following inputs can be used as `step.with` keys:
| `timeout` | `5m` | The timeout for the Helm command |
| `working-directory` | `.` | The working directory where the action commands will operate |

### Setup PostgreSQL Preview Schema

Sets up a PostgreSQL preview schema by cloning a base schema.

#### Example

```yaml
- uses: aboutbits/github-actions-kubernetes/setup-postgres-preview-schema@v3
with:
deployment-name: my-app
namespace: my-namespace
preview-number: ${{ github.event.number }}
```

#### Inputs

The following inputs can be used as `step.with` keys:

| Name | Required/Default | Description |
|-------------------|------------------|--------------------------------------------|
| `deployment-name` | required | Name of the deployment |
| `namespace` | required | Kubernetes namespace |
| `preview-number` | required | Preview number (PR number) |
| `secret-name` | `app-secrets` | Name of the secret containing PostgreSQL password |
| `postgres-image` | `postgres:18` | PostgreSQL image to use |
| `base-schema` | `main` | Base schema to copy from |

### Teardown PostgreSQL Preview Schema

Drops the PostgreSQL preview schema.

#### Example

```yaml
- uses: aboutbits/github-actions-kubernetes/teardown-postgres-preview-schema@v3
with:
deployment-name: my-app
namespace: my-namespace
preview-number: ${{ github.event.number }}
```

#### Inputs

The following inputs can be used as `step.with` keys:

| Name | Required/Default | Description |
|-------------------|------------------|--------------------------------------------|
| `deployment-name` | required | Name of the deployment |
| `namespace` | required | Kubernetes namespace |
| `preview-number` | required | Preview number (PR number) |
| `secret-name` | `app-secrets` | Name of the secret containing PostgreSQL password |
| `postgres-image` | `postgres:18` | PostgreSQL image to use |

## Build & Publish

To build and publish the action, visit the GitHub Actions page of the repository and trigger the workflow "Release Package" manually.
Expand Down
74 changes: 74 additions & 0 deletions setup-postgres-preview-schema/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
name: 'Setup PostgreSQL Preview Schema'
description: 'Sets up a PostgreSQL preview schema by cloning a base schema'
inputs:
deployment-name:
description: 'Name of the deployment (used for ConfigMap name)'
required: true
namespace:
description: 'Kubernetes namespace'
required: true
preview-number:
description: 'Preview number (PR number)'
required: true
secret-name:
description: 'Name of the secret containing DB password'
required: false
default: 'app-secrets'
postgres-image:
description: 'PostgreSQL image to use'
required: false
default: 'postgres:18'
base-schema:
description: 'Base schema to copy from'
required: false
default: 'main'

runs:
using: "composite"
steps:
- name: Prepare setup-schema job
env:
JOB_NAME: "prepare-schema-preview-${{ inputs.preview-number }}"
CONFIGMAP_NAME: "${{ inputs.deployment-name }}-environments"
SECRET_NAME: "${{ inputs.secret-name }}"
PREVIEW_SCHEMA_NAME: "preview_${{ inputs.preview-number }}"
POSTGRES_IMAGE: "${{ inputs.postgres-image }}"
BASE_SCHEMA: "${{ inputs.base-schema }}"
run: |
envsubst '
$JOB_NAME
$CONFIGMAP_NAME
$SECRET_NAME
$PREVIEW_SCHEMA_NAME
$POSTGRES_IMAGE
$BASE_SCHEMA
' < ${{ github.action_path }}/job-template.yml > job-setup-schema.yml
Comment on lines +38 to +45

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, I did not know this. That is something I will add to my tooling


echo "Prepared job manifest: job-setup-schema.yml"
shell: bash

- name: Create setup-schema job
run: |
kubectl apply --namespace ${{ inputs.namespace }} -f job-setup-schema.yml
shell: bash

- name: Wait for setup-schema job to complete
env:
JOB_NAME: "prepare-schema-preview-${{ inputs.preview-number }}"
NAMESPACE: "${{ inputs.namespace }}"
run: |
echo "Waiting for job $JOB_NAME in namespace $NAMESPACE..."

if kubectl wait --namespace $NAMESPACE --for=condition=complete --timeout=60s job/$JOB_NAME; then
echo "Job finished with status: Complete"
kubectl logs job/$JOB_NAME --namespace $NAMESPACE
elif kubectl wait --namespace $NAMESPACE --for=condition=failed --timeout=1s job/$JOB_NAME; then
echo "Job finished with status: Failed"
kubectl logs job/$JOB_NAME --namespace $NAMESPACE
exit 1
else
echo "Timeout waiting for job to complete."
kubectl logs job/$JOB_NAME --namespace $NAMESPACE || true
exit 1
fi
shell: bash
86 changes: 86 additions & 0 deletions setup-postgres-preview-schema/job-template.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
apiVersion: batch/v1
kind: Job
metadata:
name: ${JOB_NAME}
labels:
app.kubernetes.io/managed-by: github-actions
app.kubernetes.io/component: database-schema-setup
spec:
ttlSecondsAfterFinished: 60
template:
spec:
restartPolicy: Never
containers:
- name: prepare-preview-schema
image: ${POSTGRES_IMAGE}
command: [ "bash", "-c" ]
args:
- |
set -e

echo "### START $(date --iso-8601=seconds) ###"

if psql -t -A -c "SELECT 1 FROM information_schema.schemata WHERE schema_name = '${PREVIEW_SCHEMA_NAME}'" | grep -q 1; then
echo "Schema ${PREVIEW_SCHEMA_NAME} already exists. Skipping setup."
echo "Script finished successfully!"
echo "### END $(date --iso-8601=seconds) ###"
exit 0
fi
Comment on lines +23 to +28

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like that you added this check 💪🏼


echo "Dumping base schema ${BASE_SCHEMA}..."
pg_dump --schema=${BASE_SCHEMA} \
--no-comments \
--no-owner \
--no-acl \
--quote-all-identifiers \
--format=plain \
--file=preview-dump.sql

echo "Modifying dump file..."
sed -i preview-dump.sql \
-e "s/\"${BASE_SCHEMA}\"/\"${PREVIEW_SCHEMA_NAME}\"/g" \
-e 's/SET /--SET /g' \
-e 's/SELECT pg_catalog/--SELECT pg_catalog/g' \
-e 's/--SELECT pg_catalog.setval/SELECT pg_catalog.setval/g'

echo "Creating schema ${PREVIEW_SCHEMA_NAME} with modified dump file..."
psql --echo-queries \
--echo-errors \
--single-transaction \
--set=ON_ERROR_STOP=1 \
--set=SESSION_REPLICATION_ROLE=replica \
--file=preview-dump.sql

echo "Script finished successfully!"
echo "### END $(date --iso-8601=seconds) ###"
env:
- name: PGHOST
valueFrom:
configMapKeyRef:
name: ${CONFIGMAP_NAME}
key: DB_HOST
- name: PGPORT
valueFrom:
configMapKeyRef:
name: ${CONFIGMAP_NAME}
key: DB_PORT
- name: PGDATABASE
valueFrom:
configMapKeyRef:
name: ${CONFIGMAP_NAME}
key: DB_NAME
- name: PGSCHEMA
valueFrom:
configMapKeyRef:
name: ${CONFIGMAP_NAME}
key: DB_SCHEMA
- name: PGUSER
valueFrom:
configMapKeyRef:
name: ${CONFIGMAP_NAME}
key: DB_USERNAME
- name: PGPASSWORD
valueFrom:
secretKeyRef:
name: ${SECRET_NAME}
key: DB_PASSWORD
68 changes: 68 additions & 0 deletions teardown-postgres-preview-schema/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
name: 'Teardown PostgreSQL Preview Schema'
description: 'Drops the PostgreSQL preview schema'
inputs:
deployment-name:
description: 'Name of the deployment (used for ConfigMap name)'
required: true
namespace:
description: 'Kubernetes namespace'
required: true
preview-number:
description: 'Preview number (PR number)'
required: true
secret-name:
description: 'Name of the secret containing DB password'
required: false
default: 'app-secrets'
postgres-image:
description: 'PostgreSQL image to use'
required: false
default: 'postgres:18'

runs:
using: "composite"
steps:
- name: Prepare teardown-schema job
env:
JOB_NAME: "drop-schema-preview-${{ inputs.preview-number }}"
CONFIGMAP_NAME: "${{ inputs.deployment-name }}-environments"
SECRET_NAME: "${{ inputs.secret-name }}"
PREVIEW_SCHEMA_NAME: "preview_${{ inputs.preview-number }}"
POSTGRES_IMAGE: "${{ inputs.postgres-image }}"
run: |
envsubst '
$JOB_NAME
$CONFIGMAP_NAME
$SECRET_NAME
$PREVIEW_SCHEMA_NAME
$POSTGRES_IMAGE
' < ${{ github.action_path }}/job-template.yml > job-teardown-schema.yml

echo "Prepared job manifest: job-teardown-schema.yml"
shell: bash

- name: Create teardown-schema job
run: |
kubectl apply --namespace ${{ inputs.namespace }} -f job-teardown-schema.yml
shell: bash

- name: Wait for teardown-schema job to complete
env:
JOB_NAME: "drop-schema-preview-${{ inputs.preview-number }}"
NAMESPACE: "${{ inputs.namespace }}"
run: |
echo "Waiting for job $JOB_NAME in namespace $NAMESPACE..."

if kubectl wait --namespace $NAMESPACE --for=condition=complete --timeout=60s job/$JOB_NAME; then
echo "Job finished with status: Complete"
kubectl logs job/$JOB_NAME --namespace $NAMESPACE
elif kubectl wait --namespace $NAMESPACE --for=condition=failed --timeout=1s job/$JOB_NAME; then
echo "Job finished with status: Failed"
kubectl logs job/$JOB_NAME --namespace $NAMESPACE
exit 1
else
echo "Timeout waiting for job to complete."
kubectl logs job/$JOB_NAME --namespace $NAMESPACE || true
exit 1
fi
shell: bash
61 changes: 61 additions & 0 deletions teardown-postgres-preview-schema/job-template.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
apiVersion: batch/v1
kind: Job
metadata:
name: ${JOB_NAME}
labels:
app.kubernetes.io/managed-by: github-actions
app.kubernetes.io/component: database-schema-teardown
spec:
ttlSecondsAfterFinished: 60
template:
spec:
restartPolicy: Never
containers:
- name: drop-preview-schema
image: ${POSTGRES_IMAGE}
command: [ "bash", "-c" ]
args:
- |
set -e

echo "### START $(date --iso-8601=seconds) ###"
echo "Drop schema ${PREVIEW_SCHEMA_NAME}..."
psql --echo-queries \
--echo-errors \
--single-transaction \
--set=ON_ERROR_STOP=1 \
--command="drop schema if exists ${PREVIEW_SCHEMA_NAME} cascade;"

echo "Script finished successfully!"
echo "### END $(date --iso-8601=seconds) ###"
env:
- name: PGHOST
valueFrom:
configMapKeyRef:
name: ${CONFIGMAP_NAME}
key: DB_HOST
- name: PGPORT
valueFrom:
configMapKeyRef:
name: ${CONFIGMAP_NAME}
key: DB_PORT
- name: PGDATABASE
valueFrom:
configMapKeyRef:
name: ${CONFIGMAP_NAME}
key: DB_NAME
- name: PGSCHEMA
valueFrom:
configMapKeyRef:
name: ${CONFIGMAP_NAME}
key: DB_SCHEMA
- name: PGUSER
valueFrom:
configMapKeyRef:
name: ${CONFIGMAP_NAME}
key: DB_USERNAME
- name: PGPASSWORD
valueFrom:
secretKeyRef:
name: ${SECRET_NAME}
key: DB_PASSWORD