From 5e1b228ce83c3f5e980f3122b28df3baaa9507e9 Mon Sep 17 00:00:00 2001 From: Amarachi Iheanacho Date: Fri, 19 Jul 2024 14:27:11 +0100 Subject: [PATCH 1/4] added staging workflow --- .github/workflows/staging.yml | 96 +++++++++++++++++++++++++++++++++++ run_learnai_staging.sh | 3 ++ 2 files changed, 99 insertions(+) create mode 100644 .github/workflows/staging.yml create mode 100644 run_learnai_staging.sh diff --git a/.github/workflows/staging.yml b/.github/workflows/staging.yml new file mode 100644 index 00000000..0a7f9984 --- /dev/null +++ b/.github/workflows/staging.yml @@ -0,0 +1,96 @@ +name: Build, Test, and Deploy for Staging + +on: + push: + branches: + - staging + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout Code + uses: actions/checkout@v4 + - name: Set Golang + uses: actions/setup-go@v4 + with: + go-version: "1.22.1" + - name: Build the application + run: go build -o learnai_staging + + test: + runs-on: ubuntu-latest + needs: build + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: password + POSTGRES_DB: db_name + services: + postgres: + image: postgres:latest + env: + POSTGRES_USER: ${{ env.POSTGRES_USER }} + POSTGRES_PASSWORD: ${{ env.POSTGRES_PASSWORD }} + POSTGRES_DB: ${{ env.POSTGRES_DB }} + ports: + - 5432:5432 + steps: + - name: Checkout Code + uses: actions/checkout@v4 + - name: Create the app config file + run: cp app-sample.env app.env + - name: Run The Project + run: nohup go run main.go > /dev/null 2>&1 & + - name: Wait for application to start + run: sleep 30s + - name: Test for reachability + run: curl http://localhost:8019 + - name: Run All Tests + run: go test ./... -timeout 99999s + + deploy: + runs-on: ubuntu-latest + needs: test + env: + SSH_USERNAME: ${{ secrets.SSH_USERNAME }} + SSH_HOST: ${{ secrets.SSH_HOST }} + SSH_PORT: ${{ secrets.SSH_PORT }} + SSH_PASSWORD: ${{ secrets.SSH_PASSWORD }} + PROCESS_NAME: run_learnai_staging + + steps: + - name: SSH into server and deploy + uses: appleboy/ssh-action@v1.0.3 + with: + host: ${{ env.SSH_HOST }} + username: ${{ env.SSH_USERNAME }} + password: ${{ env.SSH_PASSWORD }} + port: ${{ env.SSH_PORT }} + script: | + export APPROOT=~/deployments/staging + export PATH=$PATH:~/.nvm/versions/node/v20.15.1/bin + export PATH=$PATH:/usr/local/go/bin + + mkdir -p $APPROOT + cd $APPROOT + + if [ -d "$APPROOT/.git" ]; then + # Navigate to the repository directory and pull changes + cd $APPROOT || { echo "Failed to navigate to web root directory"; exit 1; } + git reset --hard HEAD || { echo "Failed to reset local changes"; exit 1; } + git pull origin main || { echo "Failed to pull latest changes"; exit 1; } + else + git clone -b staging http://github.com/${{ github.repository }} . || { echo "Failed to clone repository"; exit 1; } + fi + + cp app-sample.env app.env + go build -o ~/deployments/staging/learnai_staging + + # Check if pm2 is already running + if pm2 list | grep -q "${{ env.PROCESS_NAME }}"; then + echo "Process ${{ env.PROCESS_NAME }} is running. Restarting..." + pm2 restart "${{ env.PROCESS_NAME }}" + else + echo "Process ${{ env.PROCESS_NAME }} is not running. Starting..." + pm2 start "${{ env.PROCESS_NAME }}".sh + fi diff --git a/run_learnai_staging.sh b/run_learnai_staging.sh new file mode 100644 index 00000000..e337e64e --- /dev/null +++ b/run_learnai_staging.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +~/deployments/staging/learnai_staging \ No newline at end of file From a36bdb9e0049f52239e764ba0e5fbbe13f13938e Mon Sep 17 00:00:00 2001 From: Osinachi Chukwujama Date: Fri, 19 Jul 2024 14:47:46 +0100 Subject: [PATCH 2/4] feat: add other nginx config --- scripts/install_and_setup_nginx.sh | 56 ++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/scripts/install_and_setup_nginx.sh b/scripts/install_and_setup_nginx.sh index ba36d2c6..40edb8d0 100644 --- a/scripts/install_and_setup_nginx.sh +++ b/scripts/install_and_setup_nginx.sh @@ -1,25 +1,43 @@ -#! /bin/bash -WEB_ROOT="/var/www/production" -CONFIG_FILE="/etc/nginx/conf.d/production.conf" -DOMAIN_OR_IP="91.229.239.238" +#!/bin/bash -sudo mkdir -p $WEB_ROOT +# Define environment configurations +declare -A environments +environments=( + ["development"]="7000 deployment.api-golang.boilerplate.hng.tech" + ["staging"]="8000 staging.api-golang.boilerplate.hng.tech" + ["production"]="9000 api-golang.boilerplate.hng.tech" +) + +# General setup sudo apt update sudo apt install -y nginx -# Configuring Nginx Reverse Proxy for the Production Server -content='server { - listen 80; - server_name 91.229.239.238; - location / { - proxy_pass http://127.0.0.1:8019; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - } -}' +# Create directories and configure Nginx for each environment +for env in "${!environments[@]}"; do + # Split the value into port and domain using parameter expansion + port="${environments[$env]%% *}" + domain="${environments[$env]#* }" + web_root="~/deployments/$env" + config_file="/etc/nginx/conf.d/$env.conf" + + # Create web root directory + sudo mkdir -p $web_root -echo "$content" | sudo tee $CONFIG_FILE > /dev/null -sudo chmod 664 $CONFIG_FILE + # Nginx configuration content + content="server { + listen 80; + server_name $domain; + location / { + proxy_pass http://127.0.0.1:$port; + proxy_set_header Host \$host; + proxy_set_header X-Real-IP \$remote_addr; + } + }" + + # Write Nginx configuration file + echo "$content" | sudo tee $config_file > /dev/null + sudo chmod 664 $config_file +done # Delete Default Nginx Webpage sudo rm /etc/nginx/sites-available/default && sudo rm /etc/nginx/sites-enabled/default @@ -27,4 +45,6 @@ sudo rm /etc/nginx/sites-available/default && sudo rm /etc/nginx/sites-enabled/d # Validate the Configuration sudo nginx -t sudo systemctl restart nginx -echo "PRODUCTION SERVER URL: http://$DOMAIN_OR_IP" \ No newline at end of file + +# Output +echo "Nginx setup for the applications to reverse proxy requests to them" From 216252a4c21fd7346cde7269464bebdbbc8452c8 Mon Sep 17 00:00:00 2001 From: Favour Lawrence Date: Fri, 19 Jul 2024 16:36:54 +0100 Subject: [PATCH 3/4] feat: add-ecosystem-config Signed-off-by: Favour Lawrence --- ecosystem.config.js | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 ecosystem.config.js diff --git a/ecosystem.config.js b/ecosystem.config.js new file mode 100644 index 00000000..401e3f5a --- /dev/null +++ b/ecosystem.config.js @@ -0,0 +1,34 @@ +module.exports = { + apps: [ + { + name: 'run_learnai_prod', + script: '/home/vicradon/deployments/production/learnai_prod', + env: { + SERVER_PORT: 9000, + DB_NAME: 'db_name', + APP_NAME: 'production', + APP_URL: 'http://localhost:9000' + } + }, + { + name: 'run_learnai_staging', + script: '/home/vicradon/deployments/staging/learnai_staging', + env: { + SERVER_PORT: 8000, + DB_NAME: 'db_name', + APP_NAME: 'staging', + APP_URL: 'http://localhost:8000' + } + }, + { + name: 'run_learnai_dev', + script: '/home/vicradon/deployments/development/learnai_dev', + env: { + SERVER_PORT: 7000, + DB_NAME: 'db_name', + APP_NAME: 'development', + APP_URL: 'http://localhost:7000' + } + } + ] +}; From 9e311d8ec243a99cddb85e088ad143b4c75aa9ff Mon Sep 17 00:00:00 2001 From: Osinachi Chukwujama Date: Fri, 19 Jul 2024 17:05:03 +0100 Subject: [PATCH 4/4] chore: setup specific databases --- .github/workflows/development.yml | 6 ++--- .github/workflows/production.yml | 6 ++--- .github/workflows/staging.yml | 6 ++--- Dockerfile | 6 ++--- ecosystem.config.js | 43 +++++++++++++++++-------------- run_development_app.sh | 3 +++ run_learnai_dev.sh | 3 --- run_learnai_prod.sh | 3 --- run_learnai_staging.sh | 3 --- run_production_app.sh | 3 +++ run_staging_app.sh | 3 +++ scripts/setup_postgres.sh | 40 ++++++++++++++++++---------- 12 files changed, 70 insertions(+), 55 deletions(-) create mode 100644 run_development_app.sh delete mode 100644 run_learnai_dev.sh delete mode 100644 run_learnai_prod.sh delete mode 100644 run_learnai_staging.sh create mode 100644 run_production_app.sh create mode 100644 run_staging_app.sh diff --git a/.github/workflows/development.yml b/.github/workflows/development.yml index dbd8750f..04926253 100644 --- a/.github/workflows/development.yml +++ b/.github/workflows/development.yml @@ -16,7 +16,7 @@ jobs: with: go-version: "1.22.1" - name: Build the application - run: go build -o learnai_dev + run: go build -o development_app test: runs-on: ubuntu-latest @@ -56,7 +56,7 @@ jobs: SSH_HOST: ${{ secrets.SSH_HOST }} SSH_PORT: ${{ secrets.SSH_PORT }} SSH_PASSWORD: ${{ secrets.SSH_PASSWORD }} - PROCESS_NAME: run_learnai_dev + PROCESS_NAME: run_development_app steps: - name: SSH into server and deploy @@ -84,7 +84,7 @@ jobs: fi cp app-sample.env app.env - go build -o ~/deployments/development/learnai_dev + go build -o ~/deployments/development/development_app # Check if pm2 is already running if pm2 list | grep -q "${{ env.PROCESS_NAME }}"; then diff --git a/.github/workflows/production.yml b/.github/workflows/production.yml index 7301f505..efde205e 100644 --- a/.github/workflows/production.yml +++ b/.github/workflows/production.yml @@ -16,7 +16,7 @@ jobs: with: go-version: "1.22.1" - name: Build the application - run: go build -o learnai_prod + run: go build -o production_app test: runs-on: ubuntu-latest @@ -56,7 +56,7 @@ jobs: SSH_HOST: ${{ secrets.SSH_HOST }} SSH_PORT: ${{ secrets.SSH_PORT }} SSH_PASSWORD: ${{ secrets.SSH_PASSWORD }} - PROCESS_NAME: run_learnai_prod + PROCESS_NAME: run_production_app steps: - name: SSH into server and deploy @@ -84,7 +84,7 @@ jobs: fi cp app-sample.env app.env - go build -o ~/deployments/production/learnai_prod + go build -o ~/deployments/production/production_app # Check if pm2 is already running if pm2 list | grep -q "${{ env.PROCESS_NAME }}"; then diff --git a/.github/workflows/staging.yml b/.github/workflows/staging.yml index 0a7f9984..36056249 100644 --- a/.github/workflows/staging.yml +++ b/.github/workflows/staging.yml @@ -16,7 +16,7 @@ jobs: with: go-version: "1.22.1" - name: Build the application - run: go build -o learnai_staging + run: go build -o staging_app test: runs-on: ubuntu-latest @@ -56,7 +56,7 @@ jobs: SSH_HOST: ${{ secrets.SSH_HOST }} SSH_PORT: ${{ secrets.SSH_PORT }} SSH_PASSWORD: ${{ secrets.SSH_PASSWORD }} - PROCESS_NAME: run_learnai_staging + PROCESS_NAME: run_staging_app steps: - name: SSH into server and deploy @@ -84,7 +84,7 @@ jobs: fi cp app-sample.env app.env - go build -o ~/deployments/staging/learnai_staging + go build -o ~/deployments/staging/staging_app # Check if pm2 is already running if pm2 list | grep -q "${{ env.PROCESS_NAME }}"; then diff --git a/Dockerfile b/Dockerfile index 2521a6b1..64d880b0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,7 +11,7 @@ RUN go mod download COPY . . -RUN go build -o learnai_app main.go +RUN go build -o production_app main.go FROM alpine:latest @@ -21,7 +21,7 @@ RUN addgroup -S nonroot && adduser -S nonroot -G nonroot WORKDIR / -COPY --from=build-stage learnai_app . +COPY --from=build-stage production_app . EXPOSE 8080 @@ -30,4 +30,4 @@ EXPOSE 8080 USER nonroot:nonroot -ENTRYPOINT ["./learnai_app"] \ No newline at end of file +ENTRYPOINT ["./production_app"] \ No newline at end of file diff --git a/ecosystem.config.js b/ecosystem.config.js index 401e3f5a..71914418 100644 --- a/ecosystem.config.js +++ b/ecosystem.config.js @@ -1,34 +1,37 @@ module.exports = { apps: [ { - name: 'run_learnai_prod', - script: '/home/vicradon/deployments/production/learnai_prod', + name: "run_production_app", + script: "/home/vicradon/deployments/production/production_app", env: { SERVER_PORT: 9000, - DB_NAME: 'db_name', - APP_NAME: 'production', - APP_URL: 'http://localhost:9000' - } + DB_NAME: "production_db", + USERNAME: "production_user", + APP_NAME: "production", + APP_URL: "http://localhost:9000", + }, }, { - name: 'run_learnai_staging', - script: '/home/vicradon/deployments/staging/learnai_staging', + name: "run_staging_app", + script: "/home/vicradon/deployments/staging/staging_app", env: { SERVER_PORT: 8000, - DB_NAME: 'db_name', - APP_NAME: 'staging', - APP_URL: 'http://localhost:8000' - } + DB_NAME: "staging_db", + USERNAME: "staging_user", + APP_NAME: "staging", + APP_URL: "http://localhost:8000", + }, }, { - name: 'run_learnai_dev', - script: '/home/vicradon/deployments/development/learnai_dev', + name: "run_development_app", + script: "/home/vicradon/deployments/development/development_app", env: { SERVER_PORT: 7000, - DB_NAME: 'db_name', - APP_NAME: 'development', - APP_URL: 'http://localhost:7000' - } - } - ] + DB_NAME: "development_db", + USERNAME: "development_user", + APP_NAME: "development", + APP_URL: "http://localhost:7000", + }, + }, + ], }; diff --git a/run_development_app.sh b/run_development_app.sh new file mode 100644 index 00000000..7331f00b --- /dev/null +++ b/run_development_app.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +~/deployments/development/development_app \ No newline at end of file diff --git a/run_learnai_dev.sh b/run_learnai_dev.sh deleted file mode 100644 index 7b6a2850..00000000 --- a/run_learnai_dev.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -~/deployments/development/learnai_dev \ No newline at end of file diff --git a/run_learnai_prod.sh b/run_learnai_prod.sh deleted file mode 100644 index 54954d03..00000000 --- a/run_learnai_prod.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -~/deployments/production/learnai_prod \ No newline at end of file diff --git a/run_learnai_staging.sh b/run_learnai_staging.sh deleted file mode 100644 index e337e64e..00000000 --- a/run_learnai_staging.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -~/deployments/staging/learnai_staging \ No newline at end of file diff --git a/run_production_app.sh b/run_production_app.sh new file mode 100644 index 00000000..2030af1f --- /dev/null +++ b/run_production_app.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +~/deployments/production/production_app \ No newline at end of file diff --git a/run_staging_app.sh b/run_staging_app.sh new file mode 100644 index 00000000..04d6d417 --- /dev/null +++ b/run_staging_app.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +~/deployments/staging/staging_app \ No newline at end of file diff --git a/scripts/setup_postgres.sh b/scripts/setup_postgres.sh index 46937f07..f9b9c136 100644 --- a/scripts/setup_postgres.sh +++ b/scripts/setup_postgres.sh @@ -1,31 +1,43 @@ #! /bin/bash # Variables for credentials -DB_USER="postgres" DB_PASSWORD="password" -DB_NAME="db_name" -# Check if the DB_USER is postgres and alter the password of this user else create a new user -if [ "$DB_USER" == "postgres" ]; then +# Define the databases and users +DATABASES=("development" "staging" "production") +USERS=("development_user" "staging_user" "production_user") + +# Check if the script is running as root (necessary for changing PostgreSQL settings) +if [ "$(id -u)" -ne "0" ]; then + echo "This script must be run as root." + exit 1 +fi + +# Check if the DB_USER is postgres and alter the password of this user if necessary +if echo "${USERS[@]}" | grep -qw "postgres"; then sudo -i -u postgres psql <