feat(deployments): build and deploy the stack

This commit is contained in:
Mrugesh Mohapatra
2025-01-16 00:13:33 +05:30
parent 76c0b29b14
commit 528b2e4d2b
3 changed files with 172 additions and 43 deletions

View File

@@ -1,43 +0,0 @@
name: CI - Build Images
on:
workflow_dispatch:
jobs:
build:
name: Build (Image)
runs-on: ubuntu-22.04
strategy:
matrix:
node-version: [20.x]
apps: [api]
site_tlds: [dev, org]
fail-fast: false
steps:
- name: Checkout Source Files
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Create a tagname
id: tagname
run: |
echo "tagname=$(git rev-parse --short HEAD)-$(date +%Y%m%d)-$(date +%H%M)" >> $GITHUB_ENV
- name: Build & Tag Image
run: |
docker build \
--tag registry.digitalocean.com/${{ secrets.DOCR_NAME }}/${{ matrix.site_tlds }}/learn-${{ matrix.apps }}:$tagname \
--tag registry.digitalocean.com/${{ secrets.DOCR_NAME }}/${{ matrix.site_tlds }}/learn-${{ matrix.apps }}:latest \
--file docker/${{ matrix.apps }}/Dockerfile .
- name: Install doctl
uses: digitalocean/action-doctl@v2
with:
token: ${{ secrets.DIGITALOCEAN_ACCESS_TOKEN }}
- name: Log in to DigitalOcean Container Registry with short-lived credentials
run: doctl registry login --expiry-seconds 1200
- name: Push image to DigitalOcean Container Registry
run: |
docker push registry.digitalocean.com/${{ secrets.DOCR_NAME }}/${{ matrix.site_tlds }}/learn-${{ matrix.apps }}:$tagname
docker push registry.digitalocean.com/${{ secrets.DOCR_NAME }}/${{ matrix.site_tlds }}/learn-${{ matrix.apps }}:latest

100
.github/workflows/deploy.yml vendored Normal file
View File

@@ -0,0 +1,100 @@
name: CD -- Deploy - API (Docker Swarm)
on:
workflow_dispatch:
jobs:
static:
runs-on: ubuntu-24.04
outputs:
site_tld: ${{ steps.static_data.outputs.site_tld }}
environment: ${{ steps.static_data.outputs.environment }}
steps:
- name: Set site_tld
id: static_data
run: |
if [ "${{ github.ref }}" == "refs/heads/prod-staging" ]; then
echo "site_tld=dev" >> $GITHUB_OUTPUT
echo "environment=staging" >> $GITHUB_OUTPUT
elif [ "${{ github.ref }}" == "refs/heads/prod-current" ]; then
echo "site_tld=org" >> $GITHUB_OUTPUT
echo "environment=production" >> $GITHUB_OUTPUT
else
echo "site_tld=dev" >> $GITHUB_OUTPUT
echo "environment=staging" >> $GITHUB_OUTPUT
fi
build:
name: Build & Push Docker Image
needs: static
uses: ./.github/workflows/re--docker-docr.yml
with:
site_tld: ${{ needs.static.outputs.site_tld }}
app: api
deploy:
runs-on: ubuntu-24.04
needs: [static, build]
permissions:
deployments: write
environment:
name: ${{ needs.static.outputs.environment }}
url: https://api.freecodecamp.${{ needs.static.outputs.site_tld }}/status/ping?version=${{ needs.build.outputs.tagname }}
steps:
- name: Setup and connect to Tailscale network
uses: tailscale/github-action@v3
with:
oauth-client-id: ${{ secrets.TS_OAUTH_CLIENT_ID }}
oauth-secret: ${{ secrets.TS_OAUTH_SECRET }}
tags: tag:ci
version: latest
- name: Configure SSH
# This is a workaround to avoid the SSH warning about known hosts & strict host key checking.
# It's not a problem for us, because we're using Tailscale to connect.
run: |
mkdir -p ~/.ssh
echo "Host *
UserKnownHostsFile=/dev/null
StrictHostKeyChecking no" > ~/.ssh/config
- name: Check connection to Deployment Target
run: |
tailscale status | grep -q "$TS_MACHINE_NAME" || { echo "Machine not found"; exit 1; }
ssh $TS_USERNAME@$TS_MACHINE_NAME "uptime"
- name: Deploy with Docker Stack
env:
STACK_NAME: stg-api
RUNTIME_ENVS: ${{ secrets.RUNTIME_ENVS }}
DEPLOYMENT_VERSION: ${{ needs.build.outputs.tagname }}
run: |
REMOTE_USER=$TS_USERNAME
ssh $TS_USERNAME@$TS_MACHINE_NAME /bin/bash << EOF
# Change to the config directory
cd /home/${REMOTE_USER}/docker-swarm-config/stacks/api || exit 1
echo "Debug: Current directory: \$(pwd)"
# Create temp file for the environment variables
echo "${RUNTIME_ENVS}" > .env.tmp
echo "DEPLOYMENT_VERSION=${DEPLOYMENT_VERSION}" >> .env.tmp
# Source the environment variables
set -a # Automatically export all variables
source .env.tmp || exit 1
set +a
# Clean up the temp file
rm -f .env.tmp
# Verify the environment variables
echo "Debug: Sanity check variables: "
env | grep -E '^DEPLOYMENT' || echo 'Vars not found'
echo "Debug: Sanity check config: "
docker stack config -c stack-api.yml | rg 'DOMAIN' || echo 'Config not found'
EOF
shell: bash

72
.github/workflows/docker-docr.yml vendored Normal file
View File

@@ -0,0 +1,72 @@
name: Docker -- DOCR
on:
workflow_dispatch:
inputs:
site_tld:
required: true
type: choice
description: 'Input: The site tld (variant) to build'
options:
- dev
- org
default: 'dev'
app:
required: true
type: string
description: 'Input: The app (component) to build'
default: 'api'
workflow_call:
inputs:
site_tld:
required: true
type: string
description: 'Input: The site tld (variant) to build'
app:
required: true
type: string
description: 'Input: The app (component) to build'
outputs:
tagname:
description: 'Output: The tagname for the image built'
value: ${{ jobs.build.outputs.tagname }}
jobs:
build:
name: Build (Image)
runs-on: ubuntu-24.04
permissions:
contents: read
outputs:
tagname: ${{ steps.tagname.outputs.tagname }}
steps:
- name: Checkout Source Files
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Create a tagname
id: tagname
run: |
tagname=$(git rev-parse --short HEAD)-$(date +%Y%m%d)-$(date +%H%M)
echo "tagname=$tagname" >> $GITHUB_ENV
echo "tagname=$tagname" >> $GITHUB_OUTPUT
- name: Build & Tag Image
run: |
docker build \
--tag registry.digitalocean.com/${{ secrets.DOCR_NAME }}/${{ inputs.site_tld }}/learn-${{ inputs.app }}:$tagname \
--tag registry.digitalocean.com/${{ secrets.DOCR_NAME }}/${{ inputs.site_tld }}/learn-${{ inputs.app }}:latest \
--file docker/${{ inputs.app }}/Dockerfile .
- name: Install doctl
uses: digitalocean/action-doctl@v2
with:
token: ${{ secrets.DIGITALOCEAN_ACCESS_TOKEN }}
- name: Log in to DigitalOcean Container Registry with short-lived credentials
run: doctl registry login --expiry-seconds 1200
- name: Push image to DigitalOcean Container Registry
run: |
docker push registry.digitalocean.com/${{ secrets.DOCR_NAME }}/${{ inputs.site_tld }}/learn-${{ inputs.app }}:$tagname
docker push registry.digitalocean.com/${{ secrets.DOCR_NAME }}/${{ inputs.site_tld }}/learn-${{ inputs.app }}:latest