Monday, 27 April 2026

Building a Safer PostgreSQL CI/CD Pipeline with GitHub Actions: Dev → PR Review → Test Promotion

In my previous post, we explored a simple push-to-main deployment strategy. While functional, that model is not considered an industry best practice for most teams.

A more reliable and professional approach is a multi-stage deployment workflow:

  • Developers push code to a develop branch
  • A Pull Request to main triggers deployment to the Dev environment
  • After validation and approval, merging into main promotes the change to the Test environment

This creates better control, safer releases, and cleaner change management.

Why This Approach Is Better Than Direct Push to Main

With a direct push-to-main model:

  • No review process
  • No early validation environment
  • Higher risk of broken deployments
  • Harder rollback management

With a staged PR model:

  • Code review before merge
  • Automated validation in Dev
  • Controlled promotion to Test
  • Better audit trail
  • Aligns with real DevOps workflows

Initial Setup – Create the Develop Branch

We begin from the existing repository.

postgres@oel01db$ cd Psql-Scrtips/

postgres@oel01db$ ls -lrt

total 4

-rw-r--r-- 1 postgres postgres 712 Apr 25 22:16 Create_gisdb.sql

postgres@oel01db$ git status

# On branch main

nothing to commit, working directory clean

postgres@oel01db$ git pull origin main

From github.com:mahekarthya/devops-demo-pub

* branch main -> FETCH_HEAD

Already up-to-date.

postgres@oel01db$

postgres@oel01db$ git checkout -b develop

Switched to a new branch 'develop'

postgres@oel01db$ git status

# On branch develop

nothing to commit, working directory clean

At this point, development work is isolated from production-style branches.

Modify the Deployment script from the develop branch

We update the file Create_gisdb.sql.

postgres@oel01db$ vi Create_gisdb.sql

postgres@oel01db$ cat Create_gisdb.sql

\conninfo

\echo ==== List Databases before change ====

select datname from pg_database;

\echo ==== Dropping Database gisdb if exist ====

DROP DATABASE IF EXISTS gisdb;

\echo ==== Creating Database gisdb ====

CREATE DATABASE gisdb;

\echo ==== Switching to gisdb ====

\c gisdb

\conninfo

\echo ==== Creating customer table in gisdb ====

CREATE TABLE customer (

id INT,

custname VARCHAR(100)

);

\echo ==== Inserting rows into customer ====

INSERT INTO customer (id, custname) VALUES

(1, 'ABC Co'),

(2, 'Honda Co'),

(3, 'Yamaha'),

(4, 'Hyundai'),

(5, 'IBM'),

(5, 'ICICI');

\echo ==== Display customer data ====

Select * from customer;

\echo ==== Final database list after change ====

select datname from pg_database;

Commit and Push to Develop

postgres@oel01db$ git status

# On branch develop

# Changes not staged for commit:

# (use "git add <file>..." to update what will be committed)

# (use "git checkout -- <file>..." to discard changes in working directory)

#

# modified: Create_gisdb.sql

#

no changes added to commit (use "git add" and/or "git commit -a")

postgres@oel01db$ git add .

postgres@oel01db$ git commit -m "added another insert - (5, 'ICICI')"

[develop 91ea18f] added another insert - (5, 'ICICI')

1 file changed, 2 insertions(+), 1 deletion(-)

postgres@oel01db$ git push origin develop

GitHub now detects a new branch and suggests creating a Pull Request.



















Create Pull Request from Develop → Main

Once you click Compare & Pull Request, GitHub begins the review workflow.

After approval, click Merge.

Now the changes are available in the main branch.

































Now click on merge.























Now you can see the changes in the main branch















Update GitHub Actions Workflow

postgres@oel01db$ cat .github/workflows/Create_gisdb_action.yml
name: Deploy Postgres script
run-name: Setting up new postgres database & deploy script

on:
push:
branches:
- main

pull_request:
types:
- opened
- synchronize
branches:
- main


jobs:
deploy-dev:
runs-on: ubuntu-latest
if: github.event_name == 'pull_request' && github.event.pull_request.base.ref == 'main'
environment: Dev

steps:
- name: Checkout Code
uses: actions/checkout@v4

- name: Run SQL file on DEV
run: |
psql -h "${{ secrets.DB_HOSTNAME }}" \
-p 5432 \
-U "${{ secrets.DB_USER }}" \
-d "${{ secrets.DB_NAME }}" \
-f "Create_gisdb.sql"
env:
PGPASSWORD: ${{ secrets.DB_PASSWORD }}

deploy-test:
runs-on: ubuntu-latest
if: github.event_name == 'push' && github.ref_name == 'main'
environment: Test

steps:
- name: Checkout Code
uses: actions/checkout@v4

- name: Run SQL file on TEST
run: |
psql -h "${{ secrets.DB_HOSTNAME }}" \
-p 5432 \
-U "${{ secrets.DB_USER }}" \
-d "${{ secrets.DB_NAME }}" \
-f "Create_gisdb.sql"
env:
PGPASSWORD: ${{ secrets.DB_PASSWORD }}
postgres@oel01db$

In this specific scenario, we should not use needs: deploy-dev in deploy-test job, because deploy-dev and deploy-test are triggered by different GitHub events:

So this workflow will,

  • Deploy SQL to Dev when a Pull Request is created/updated to main
  • Deploy SQL to Test when code is pushed/merged to main. 

  • High-Level Flow

    Develope Branch

    Pull Request to main

    Deploy to DEV database

    PR approved + merged

    Push to main

    Deploy to TEST database

    1. The develop Branch

    • Action: You work on your SQL scripts here.

    • Result: Nothing happens to your databases yet. Your code is isolated.

    2. Pull Request (PR) to main

    • Action: You "propose" your changes to the main branch.

    • Result: This triggers the deploy-dev job because the event is a pull_request.

    • Database: Your DEV database is updated. You can now verify that the script works in a real environment.

    3. PR Approved + Merged

    • Action: You or a teammate reviews the code. Since the "Dev" check passed, you hit Merge.

    • Result: This creates a push event on the main branch.

    4. Deploy to TEST Database

    • Action: The push event triggers the deploy-test job.

    • Result: The deploy-dev job is skipped (because it’s no longer a PR), and your TEST database is updated with the final, approved code.


    Modify SQL Again for New Release

    Now we update the script again.

    postgres@oel01db$ cat Create_gisdb.sql
    \conninfo

    \echo ==== List Databases before change ====
    select datname from pg_database;

    \echo ==== Dropping Database gisdb if exist ====
    DROP DATABASE IF EXISTS gisdb;

    \echo ==== Creating Database gisdb ====
    CREATE DATABASE gisdb;

    \echo ==== Switching to gisdb ====
    \c gisdb

    \conninfo

    \echo ==== Creating customer table in gisdb ====
    CREATE TABLE customer (
    id INT,
    custname VARCHAR(100)
    );

    \echo ==== Inserting rows into customer ====
    INSERT INTO customer (id, custname) VALUES
    (1, 'ABC Co'),
    (2, 'Honda Co'),
    (3, 'Yamaha'),
    (4, 'Hyundai'),
    (5, 'IBM'),
    (5, 'ICICI');

    UPDATE customer
    SET id = 6
    WHERE custname = 'ICICI';


    \echo ==== Display customer data ====
    Select * from customer;

    \echo ==== Final database list after change ====
    select datname from pg_database;
    postgres@oel01db$

    Push New Changes


    postgres@oel01db$ git status
    # On branch develop
    # Changes not staged for commit:
    #   (use "git add <file>..." to update what will be committed)
    #   (use "git checkout -- <file>..." to discard changes in working directory)
    #
    #       modified:   .github/workflows/Create_gisdb_action.yml
    #       modified:   Create_gisdb.sql
    #
    # Untracked files:
    #   (use "git add <file>..." to include in what will be committed)
    #
    #       1
    no changes added to commit (use "git add" and/or "git commit -a")
    postgres@oel01db$
    postgres@oel01db$ git status
    # On branch develop
    # Changes not staged for commit:
    #   (use "git add <file>..." to update what will be committed)
    #   (use "git checkout -- <file>..." to discard changes in working directory)
    #
    #       modified:   .github/workflows/Create_gisdb_action.yml
    #       modified:   Create_gisdb.sql
    #
    # Untracked files:
    #   (use "git add <file>..." to include in what will be committed)
    #
    #       1
    no changes added to commit (use "git add" and/or "git commit -a")
    postgres@oel01db$ git add .
    postgres@oel01db$ git commit -m "modifed files"
    [develop ac6d933] modifed files
     3 files changed, 75 insertions(+), 5 deletions(-)
     create mode 100644 1
    postgres@oel01db$
    postgres@oel01db$ git push origin develop
    Counting objects: 11, done.
    Compressing objects: 100% (5/5), done.
    Writing objects: 100% (6/6), 778 bytes | 0 bytes/s, done.
    Total 6 (delta 2), reused 0 (delta 0)
    remote: Resolving deltas: 100% (2/2), completed with 2 local objects.
    To git@github.com:mahekarthya/devops-demo-pub.git
       91ea18f..ac6d933  develop -> develop
    postgres@oel01db$

    At this moment:

    No action is triggered yet because no PR event occurred.















    Trigger Pull Request Again






































    Once the Pull Request is created or updated:
    • deploy-dev runs
    • deploy-test is skipped

    Exactly as expected.















    As you could see the pull request has triggered the deployment to Dev database 

















    The workflow skipped the deploy-test job because the if condition was not met for a Pull Request event.

    Validate Dev Deployment

    postgres@oel01db$ psql -h postgres-db-1.ckp44ikeq3w2.us-east-1.rds.amazonaws.com -U postgres -p 5432 -d postgres
    Password for user postgres:
    psql (15.17, server 17.6)
    WARNING: psql major version 15, server major version 17.
             Some psql features might not work.
    SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES128-GCM-SHA256, compression: off)
    Type "help" for help.

    postgres@postgres> \c gisdb
    psql (15.17, server 17.6)
    WARNING: psql major version 15, server major version 17.
             Some psql features might not work.
    SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES128-GCM-SHA256, compression: off)
    You are now connected to database "gisdb" as user "postgres".
    postgres@gisdb> select datname from pg_database;
      datname
    -----------
     template0
     template1
     postgres
     rdsadmin
     gisdb
    (5 rows)

    postgres@postgres> \c gisdb
    psql (15.17, server 17.6)
    WARNING: psql major version 15, server major version 17.
             Some psql features might not work.
    SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES128-GCM-SHA256, compression: off)
    You are now connected to database "gisdb" as user "postgres".
    postgres@gisdb> select * from customer ;
     id | custname
    ----+----------
      1 | ABC Co
      2 | Honda Co
      3 | Yamaha
      4 | Hyundai
      5 | IBM
      6 | ICICI
    (6 rows)


    Merge Pull Request












































    After clicking Merge, GitHub triggers:
    • push event on main

    Now:

    • deploy-test runs
    • deploy-dev is skipped

    Perfect separation of responsibilities.
















    This time it skip the deploy-dev job




















    Validate Test Deployment


    postgres@oel01db$ psql -h postgres-db-test.ckp44ikeq3w2.us-east-1.rds.amazonaws.com -U postgres -p 5432 -d postgres
    Password for user postgres:
    psql (15.17, server 18.3)
    WARNING: psql major version 15, server major version 18.
             Some psql features might not work.
    SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES128-GCM-SHA256, compression: off)
    Type "help" for help.

    postgres@postgres> \c gisdb
    psql (15.17, server 18.3)
    WARNING: psql major version 15, server major version 18.
             Some psql features might not work.
    SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES128-GCM-SHA256, compression: off)
    You are now connected to database "gisdb" as user "postgres".
    postgres@gisdb> select datname from pg_database;
      datname
    -----------
     template0
     template1
     postgres
     rdsadmin
     gisdb
    (5 rows)

    postgres@postgres> \c gisdb
    psql (15.17, server 17.6)
    WARNING: psql major version 15, server major version 17.
             Some psql features might not work.
    SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES128-GCM-SHA256, compression: off)
    You are now connected to database "gisdb" as user "postgres".
    postgres@gisdb> select * from customer ;
     id | custname
    ----+----------
      1 | ABC Co
      2 | Honda Co
      3 | Yamaha
      4 | Hyundai
      5 | IBM
      6 | ICICI
    (6 rows)



    Deploy PostgreSQL Database Code to Dev and Test Environments Sequentially Using GitHub Actions

     Modern database deployments should be repeatable, automated, and version-controlled. Instead of manually logging into servers and running SQL scripts, we can use GitHub + GitHub Actions to automatically deploy PostgreSQL changes whenever code is pushed to the main branch.

    In this walkthrough, I’ll show how to:

    • Test your script in the sandpit first to play it safe
    • Store PostgreSQL scripts in GitHub
    • When code gets pushed to main , automatically deploy to Development database first
    • Then deploy to Test database only if Dev succeeds
    • Use GitHub Environment Secrets for secure credentials
    • Maintain a simple CI/CD pipeline for PostgreSQL

    Architecture Overview

    When a developer pushes SQL code to GitHub:

    1. GitHub Actions starts automatically.
    2. The SQL script is deployed to the Dev PostgreSQL database.
    3. If successful, deployment continues to the Test PostgreSQL database.
    4. This ensures controlled promotion of changes across environments.

    Push Code to to Main Branch
    ↓ (it trigger GitHub Actions)
    GitHub Actions
    ↓ (first deploy the code to Dev database)
    Deploy to DEV
    ↓ (deploy to test database only if Dev succeeds)
    Deploy to TEST

    Step 1: Generate SSH Key for GitHub Access

    From the PostgreSQL sandpit server, generate an SSH key:

    postgres@oel01db$ ssh-keygen -t ed25519 -C "mahekarthya@gmail.com"

    Output:

    Generating public/private ed25519 key pair.
    Enter file in which to save the key (/var/lib/pgsql/.ssh/id_ed25519):
    Enter passphrase (empty for no passphrase):
    Enter same passphrase again:

    Key files created:

    • Private Key: /var/lib/pgsql/.ssh/id_ed25519
    • Public Key: /var/lib/pgsql/.ssh/id_ed25519.pub

    Step 2: Copy Public Key

    postgres@oel01db$ cd /var/lib/pgsql/.ssh/
    postgres@oel01db$ cat id_ed25519.pub

    Output:

    ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBSVTawU0nB11iPH2Qj7x5MWOwDBdAzdwysdQxwhVqHN mahekarthya@gmail.com

    Step 3: Add SSH Key to GitHub

    In GitHub:

    • Click Profile Picture → Settings
    • Select SSH and GPG Keys
    • Click New SSH Key
    • Title: OEL-Database-Server
    • Paste the public key
    • Click Add SSH Key












    Step 4: Verify GitHub SSH Connectivity

    postgres@oel01db$ ssh -T git@github.com

    Expected result:

    Hi mahekarthya! You've successfully authenticated, but GitHub does not provide shell access.


    Step 5: Create PostgreSQL Deployment Script

    Current working directory:

    postgres@oel01db$ pwd
    /var/lib/pgsql/Psql-Scrtips

    SQL file:

    postgres@oel01db$ cat Create_gisdb.sql
    \conninfo
    
    \echo ==== List Databases before change ====
    select datname from pg_database;
    
    \echo ==== Dropping Database gisdb if exist ====
    DROP DATABASE IF EXISTS gisdb;
    
    \echo ==== Creating Database gisdb ====
    CREATE DATABASE gisdb;
    
    \echo ==== Switching to gisdb ====
    \c gisdb
    
    \conninfo
    
    \echo ==== Creating customer table in gisdb ====
    CREATE TABLE customer (
      id INT,
      custname VARCHAR(100)
    );
    
    \echo ==== Inserting rows into customer  ====
    INSERT INTO customer (id, custname) VALUES
    (1, 'ABC Co'),
    (2, 'Honda Co'),
    (3, 'Yamaha'),
    (4, 'Hyundai'),
    (5, 'IBM');
    
    \echo ==== Display customer data ====
    Select * from customer;
    
    \echo ==== Final database list after change ====
    select datname from pg_database;

    Step 6: Validate Script Locally First

    Before automation, always test locally (on Sandpit)

    postgres@postgres# \i /var/lib/pgsql/Psql-Scrtips/Create_gisdb.sql

    The script successfully:

    • Dropped old database if present
    • Created gisdb
    • Created customer table
    • Inserted rows
    • Verified output

    postgres@postgres# \i /var/lib/pgsql/Psql-Scrtips/Create_gisdb.sql
    You are connected to database "postgres" as user "postgres" via socket in "/run/postgresql" at port "5432".
    ==== List Databases before change ====
      datname
    -----------
     postgres
     template1
     template0
     hrdb
     salesdb
     repmgrdb
    (6 rows)

    ==== Dropping Database gisdb if exist ====
    psql:/var/lib/pgsql/Psql-Scrtips/Create_gisdb.sql:7: NOTICE:  database "gisdb" does not exist, skipping
    DROP DATABASE
    ==== Creating Database gisdb ====
    CREATE DATABASE
    ==== Switching to gisdb ====
    psql (15.17, server 15.13)
    You are now connected to database "gisdb" as user "postgres".
    You are connected to database "gisdb" as user "postgres" via socket in "/run/postgresql" at port "5432".
    ==== Creating customer table in gisdb ====
    CREATE TABLE
    ==== Inserting rows into customer ====
    INSERT 0 5
    ==== Display customer data ====
     id | custname
    ----+----------
      1 | ABC Co
      2 | Honda Co
      3 | Yamaha
      4 | Hyundai
      5 | IBM
    (5 rows)

    ==== Final database list after change ====
      datname
    -----------
     postgres
     template1
     template0
     hrdb
     salesdb
     repmgrdb
     gisdb
    (7 rows)

    postgres@gisdb#

    Step 7: Target AWS RDS Environments

    Two PostgreSQL RDS instances were prepared.

    Development Database

    postgres-db-1.ckp44ikeq3w2.us-east-1.rds.amazonaws.com

    Test Database

    postgres-db-test.ckp44ikeq3w2.us-east-1.rds.amazonaws.com

    Both instances were configured with public accessibility enabled.

    In production environments, private networking with VPN, VPC peering, or self-hosted GitHub runners is recommended instead of public exposure.

    Verif the Dev connectivity:

    postgres@oel01db$  psql -h postgres-db-1.ckp44ikeq3w2.us-east-1.rds.amazonaws.com -U postgres -p 5432 -d postgres

    Password for user postgres:

    psql (15.17, server 17.6)

    WARNING: psql major version 15, server major version 17.

             Some psql features might not work.

    SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES128-GCM-SHA256, compression: off)

    Type "help" for help.

    postgres@postgres>  SELECT inet_server_addr(), inet_server_port();

     inet_server_addr | inet_server_port

    ------------------+------------------

     172.31.12.65     |             5432

    (1 row)

    postgres@postgres>  select datname from pg_database;

      datname

    -----------

     template0

     template1

     postgres

     rdsadmin

    (4 rows)

    postgres@postgres>


    Verif the Test connectivity:

    postgres@oel01db$  psql -h postgres-db-test.ckp44ikeq3w2.us-east-1.rds.amazonaws.com -U postgres -p 5432 -d postgres

    Password for user postgres:

    psql (15.17, server 18.3)

    WARNING: psql major version 15, server major version 18.

             Some psql features might not work.

    SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES128-GCM-SHA256, compression: off)

    Type "help" for help.

    postgres@postgres> SELECT inet_server_addr(), inet_server_port();

     inet_server_addr | inet_server_port

    ------------------+------------------

     172.31.89.220    |             5432

    (1 row)

    postgres@postgres>  select datname from pg_database;

      datname

    -----------

     template0

     template1

     postgres

     rdsadmin

    (4 rows)

    postgres@postgres>


    Step 8: Create GitHub Environments

    Inside GitHub repository:

    Settings → Secrets and variables → Actions

    Create two environments:

    • Dev
    • Test

    For each environment, add secrets:

    Secret NameDescription
    DB_HOSTNAMERDS endpoint
    DB_USERPostgreSQL username
    DB_NAMEDatabase name
    DB_PASSWORDPassword

    This allows the same workflow to use different credentials safely.

    Select your  git repo , then click Setting --> secret and variable and then action 












    Click on New environment 

















    Now we can add envioemnet secret here 






















    Configure the DB_HOSTNAMEDB_USERDB_NAME, and DB_PASSWORD as GitHub Secrets to be utilized by the workflow














    add DB_USER















    Add DB_NAME















    & finally DB_PASSWORD















    Now we have 4 secret for envioemnt Dev 












    Create a 'Test' environment and configure the corresponding database secrets following the same procedure





    And add similar secret that we added for Dev.








































    Step 9: Create GitHub Actions Workflow

    Create folder:

    postgres@oel01db$ mkdir -p .github/workflows/
    postgres@oel01db$ cd .github/workflows/
    postgres@oel01db$ vi Create_gisdb_action.yml

    Note: The .github/workflows/ directory is a special folder recognized by GitHub. It is where you store GitHub Actions workflow files (YAML files) that automate tasks for your repository.

    Workflow file:

    postgres@oel01db$ cat .github/workflows/Create_gisdb_action.yml
    name: Deploy Postgres script
    run-name: Setting up new postgres database & deploy scritpt
    
    on:
      push:
        branches:
          - main
    jobs: # --- DEVELOPMENT JOB --- deploy-dev: runs-on: ubuntu-latest environment: Dev # <--- This keyword tells GitHub to use Dev secrets/vars steps: - name: Checkout Code uses: actions/checkout@v4 - name: Run SQL file on DEV run: | psql -h "${{ secrets.DB_HOSTNAME }}" \ -p 5432 \ -U "${{ secrets.DB_USER }}" \ -d "${{ secrets.DB_NAME }}" \ -f "Create_gisdb.sql" env: PGPASSWORD: ${{ secrets.DB_PASSWORD }} # --- TEST JOB --- deploy-test: runs-on: ubuntu-latest needs: deploy-dev # Ensures Test only runs after Dev is successful environment: Test # <--- This keyword swaps the secrets to Test values steps: - name: Checkout Code uses: actions/checkout@v4 - name: Run SQL file on TEST run: | psql -h "${{ secrets.DB_HOSTNAME }}" \ -p 5432 \ -U "${{ secrets.DB_USER }}" \ -d "${{ secrets.DB_NAME }}" \ -f "Create_gisdb.sql" env: PGPASSWORD: ${{ secrets.DB_PASSWORD }} postgres@oel01db$

    Why This Workflow Is Good

    Serial Deployment Control

    needs: deploy-dev

    This ensures:

    • Dev runs first
    • Test runs only if Dev succeeds

    Environment-Based Secrets

    Same YAML file, different credentials.

    Branch Protection

    Only pushes to main trigger deployments.

    Step 10: Initialize Git Repository

    postgres@oel01db$ git init
    postgres@oel01db$ git remote add origin git@github.com:mahekarthya/devops-demo-pub.git
    postgres@oel01db$ git add .
    postgres@oel01db$ git commit -m "Initial commit"
    postgres@oel01db$ git branch -M main
    postgres@oel01db$ git push -u origin main















    Step 11: Automatic Deployment Triggered

    Since the workflow trigger is:

    on:
      push:

    Any push to main automatically starts:

    1. Deploy to Dev
    2. Then Deploy to Test

    No manual intervention required.

    Let’s push the code and watch the GitHub Action workflow in action!

    postgres@oel01db$ ls -lart

    total 8

    -rw-r--r--  1 postgres postgres  712 Apr 25 22:16 Create_gisdb.sql

    drwxr-xr-x  3 postgres postgres   23 Apr 25 23:17 .github

    drwx------. 7 postgres postgres 4096 Apr 25 23:33 ..

    drwxr-xr-x  3 postgres postgres   45 Apr 25 23:39 .

    postgres@oel01db$

    postgres@oel01db$  git config --global user.name "mahekarthya"

    postgres@oel01db$

    postgres@oel01db$ git config --global user.email "mahekarthya@gmail.com"

    postgres@oel01db$

    postgres@oel01db$ git init

    Initialized empty Git repository in /var/lib/pgsql/Psql-Scrtips/.git/

    postgres@oel01db$

    postgres@oel01db$  git remote -v

    postgres@oel01db$

    postgres@oel01db$ git remote add origin git@github.com:mahekarthya/devops-demo-pub.git

    postgres@oel01db$

    postgres@oel01db$  git remote -v

    origin  git@github.com:mahekarthya/devops-demo-pub.git (fetch)

    origin  git@github.com:mahekarthya/devops-demo-pub.git (push)

    postgres@oel01db$

    postgres@oel01db$ git add .

    postgres@oel01db$

    postgres@oel01db$ git status

    # On branch master

    #

    # Initial commit

    #

    # Changes to be committed:

    #   (use "git rm --cached <file>..." to unstage)

    #

    #       new file:   .github/workflows/Create_gisdb_action.yml

    #       new file:   Create_gisdb.sql

    #

    postgres@oel01db$  git commit -m "Initial commit"

    [master (root-commit) e4a7760] Initial commit

     2 files changed, 77 insertions(+)

     create mode 100644 .github/workflows/Create_gisdb_action.yml

     create mode 100644 Create_gisdb.sql

    postgres@oel01db$

    postgres@oel01db$  git branch -M main

    postgres@oel01db$

    postgres@oel01db$ git status

    # On branch main

    nothing to commit, working directory clean

    postgres@oel01db$

    postgres@oel01db$ git branch

    * main

    postgres@oel01db$ git push -u origin main

    To git@github.com:mahekarthya/devops-demo-pub.git

     ! [rejected]        main -> main (fetch first)

    error: failed to push some refs to 'git@github.com:mahekarthya/devops-demo-pub.git'

    hint: Updates were rejected because the remote contains work that you do

    hint: not have locally. This is usually caused by another repository pushing

    hint: to the same ref. You may want to first merge the remote changes (e.g.,

    hint: 'git pull') before pushing again.

    hint: See the 'Note about fast-forwards' in 'git push --help' for details.

    postgres@oel01db$

    postgres@oel01db$ git pull origin main

    warning: no common commits

    remote: Enumerating objects: 85, done.

    remote: Counting objects: 100% (85/85), done.

    remote: Compressing objects: 100% (56/56), done.

    remote: Total 85 (delta 21), reused 19 (delta 6), pack-reused 0 (from 0)

    Unpacking objects: 100% (85/85), done.

    From github.com:mahekarthya/devops-demo-pub

     * branch            main       -> FETCH_HEAD

    Already up-to-date!

    Merge made by the 'recursive' strategy.

    postgres@oel01db$ git push origin main

    Counting objects: 8, done.

    Compressing objects: 100% (6/6), done.

    Writing objects: 100% (7/7), 1.26 KiB | 0 bytes/s, done.

    Total 7 (delta 1), reused 0 (delta 0)

    remote: Resolving deltas: 100% (1/1), done.

    To git@github.com:mahekarthya/devops-demo-pub.git

       63b8816..12083ba  main -> main

    postgres@oel01db$


    Since the trigger is set to 'push,' the workflow will kick off automatically every time we commit and push our code,  you could see it has been completed .



































    Step 12: Verify Deployment

    After workflow completion, connect to both RDS databases and validate:

    select datname from pg_database;
    select * from customer;

    You should see:

    • gisdb
    • customer table
    • Inserted sample rows
    Dev database:






















    Test database:



    Building a Safer PostgreSQL CI/CD Pipeline with GitHub Actions: Dev → PR Review → Test Promotion

    In my previous post, we explored a simple push-to-main deployment strategy . While functional, that model is not considered an industry best...