Skip to content

Latest commit

 

History

History
 
 

workflows

README.md

GitHub Actions Workflows

This directory contains CI/CD workflows for the QBO-FIRS application. The workflows automate building, testing, and deploying the application to Kubernetes using DigitalOcean Container Registry.

Workflows Overview

1. Continuous Integration (ci.yml)

Triggers: Pull requests and pushes to any branch

Purpose: Validates code quality and builds

Jobs:

  • Lint - Runs ESLint on the codebase
  • Test - Runs unit tests and generates coverage reports
  • Build - Builds the NestJS application
  • Docker Build - Builds Docker images (without pushing)
  • Security Scan - Scans Docker images for vulnerabilities using Trivy
  • Validate K8s - Validates Kubernetes manifests

2. Deploy to Production (deploy-production.yml)

Triggers: Push to main branch or manual workflow dispatch

Purpose: Deploys to production environment

Jobs:

  1. Build and Push - Builds production Docker image and pushes to DigitalOcean registry
  2. Deploy - Deploys to qbo-firs-prod namespace in Kubernetes
  3. Notify - Sends deployment status notification

Image Tags:

  • latest - Latest production release
  • main-{sha} - Git commit SHA
  • Semantic versions if tagged

3. Deploy to Development (deploy-development.yml)

Triggers: Push to develop branch, PRs to develop, or manual dispatch

Purpose: Deploys to development environment

Jobs:

  1. Build and Push - Builds development Docker image
  2. Test - Runs tests before deployment
  3. Deploy - Deploys to qbo-firs-dev namespace
  4. Notify - Sends deployment status

Image Tags:

  • dev - Latest development release
  • dev-latest - Alternative dev tag
  • dev-{sha} - Git commit SHA

4. Manual Deploy (manual-deploy.yml)

Triggers: Manual workflow dispatch only

Purpose: Deploy specific image tags to any environment

Inputs:

  • environment - Choose production or development
  • image_tag - Specify the Docker image tag to deploy
  • skip_build - Option to skip building and use existing image

Required GitHub Secrets

Configure these secrets in your GitHub repository settings (Settings > Secrets and variables > Actions):

Required Secrets

Secret Name Description How to Get
DIGITALOCEAN_TOKEN DigitalOcean API token Create in DigitalOcean Console
K8S_CLUSTER_NAME Kubernetes cluster name Your DigitalOcean Kubernetes cluster name

Creating DigitalOcean API Token

  1. Go to DigitalOcean API Tokens
  2. Click Generate New Token
  3. Name: GitHub Actions - QBO FIRS
  4. Scopes: Select both Read and Write
  5. Click Generate Token
  6. Copy the token immediately (it won't be shown again)
  7. Add to GitHub Secrets as DIGITALOCEAN_TOKEN

Finding Kubernetes Cluster Name

# List your clusters
doctl kubernetes cluster list

# Get cluster name
doctl kubernetes cluster get <cluster-id> --format Name

Setting Up Kubernetes Secrets

Before the first deployment, create Kubernetes secrets manually:

Production

# Configure kubectl
doctl kubernetes cluster kubeconfig save <cluster-name>

# Create namespace
kubectl create namespace qbo-firs-prod

# Create secret
kubectl create secret generic qbo-firs-secret \
  --from-literal=QB_CLIENT_ID='your_production_client_id' \
  --from-literal=QB_CLIENT_SECRET='your_production_client_secret' \
  --from-literal=QB_WEBHOOK_VERIFIER='your_production_verifier' \
  --from-literal=SUPABASE_URL='https://your-project.supabase.co' \
  --from-literal=SUPABASE_ANON_KEY='your_production_supabase_key' \
  --from-literal=RABBITMQ_URL='amqp://user:password@rabbitmq:5672' \
  --namespace=qbo-firs-prod

Development

# Create namespace
kubectl create namespace qbo-firs-dev

# Create secret
kubectl create secret generic qbo-firs-secret \
  --from-literal=QB_CLIENT_ID='your_dev_client_id' \
  --from-literal=QB_CLIENT_SECRET='your_dev_client_secret' \
  --from-literal=QB_WEBHOOK_VERIFIER='your_dev_verifier' \
  --from-literal=SUPABASE_URL='https://your-dev-project.supabase.co' \
  --from-literal=SUPABASE_ANON_KEY='your_dev_supabase_key' \
  --from-literal=RABBITMQ_URL='amqp://user:password@rabbitmq:5672' \
  --namespace=qbo-firs-dev

GitHub Environments (Optional but Recommended)

Setting up GitHub environments adds an extra layer of control and visibility:

Creating Environments

  1. Go to Settings > Environments
  2. Click New environment
  3. Create two environments:
    • production
    • development

Environment Configuration

Production Environment

  • Protection Rules:
    • Required reviewers: Add team members who must approve deployments
    • Wait timer: Optional delay before deployment
    • Deployment branches: Only main branch
  • Environment Secrets: Can override repository secrets if needed
  • URL: https://your-production-domain.com

Development Environment

Workflow Usage

Automatic Deployments

Development

  1. Create a feature branch from develop
  2. Make your changes and commit
  3. Push to develop branch
  4. CI runs automatically
  5. On push to develop, deployment workflow triggers

Production

  1. Merge PR to main branch
  2. CI validates the code
  3. Deployment workflow builds and deploys automatically
  4. If environments are configured, wait for approval

Manual Deployments

Using Manual Deploy Workflow

  1. Go to Actions tab in GitHub
  2. Select Manual Deploy workflow
  3. Click Run workflow
  4. Choose options:
    • Environment: production or development
    • Image tag: Enter tag (e.g., latest, dev, v1.2.3)
    • Skip build: Check to deploy existing image
  5. Click Run workflow

Deploying Specific Commits

# Tag a specific commit
git tag v1.2.3
git push origin v1.2.3

# Use Manual Deploy workflow with tag `v1.2.3`

Monitoring Workflows

Viewing Workflow Runs

  1. Go to Actions tab
  2. Select a workflow from the left sidebar
  3. Click on a run to see details
  4. Expand jobs to see step-by-step logs

Checking Deployment Status

# Configure kubectl
doctl kubernetes cluster kubeconfig save <cluster-name>

# Check production
kubectl get pods -n qbo-firs-prod
kubectl get svc -n qbo-firs-prod
kubectl get ingress -n qbo-firs-prod

# Check development
kubectl get pods -n qbo-firs-dev
kubectl get svc -n qbo-firs-dev
kubectl get ingress -n qbo-firs-dev

# Check specific deployment
kubectl describe deployment qbo-firs -n qbo-firs-prod

# View logs
kubectl logs -f deployment/qbo-firs -n qbo-firs-prod

Rollback Procedures

Rollback Using GitHub Actions

  1. Use Manual Deploy workflow
  2. Select the environment to rollback
  3. Enter the previous working image tag
  4. Check Skip build
  5. Run workflow

Rollback Using kubectl

# View rollout history
kubectl rollout history deployment/qbo-firs -n qbo-firs-prod

# Rollback to previous version
kubectl rollout undo deployment/qbo-firs -n qbo-firs-prod

# Rollback to specific revision
kubectl rollout undo deployment/qbo-firs -n qbo-firs-prod --to-revision=2

Image Management

Listing Images

# List images in DigitalOcean registry
doctl registry repository list-tags qbo-firs

# List all tags
doctl registry repository list-tags qbo-firs --format Tag,UpdatedAt

Cleaning Up Old Images

# Delete specific tag
doctl registry repository delete-tag qbo-firs old-tag-name

# Run garbage collection
doctl registry garbage-collection start

Troubleshooting

Workflow Fails at Build Step

Check:

  • Docker build errors in workflow logs
  • Dockerfile syntax
  • Dependencies in package.json

Fix:

# Test locally
docker build --target production -t test .

Workflow Fails at Deploy Step

Check:

  • Kubernetes secrets exist
  • kubectl can connect to cluster
  • Deployment manifests are valid

Fix:

# Verify secrets
kubectl get secret qbo-firs-secret -n qbo-firs-prod

# Test manifests
kubectl apply --dry-run=client -f k8s/production/

Image Pull Errors

Check:

  • Image exists in registry
  • Image name and tag are correct
  • Kubernetes can access DigitalOcean registry

Fix:

# Verify image exists
doctl registry repository list-tags qbo-firs

# Check pod events
kubectl describe pod <pod-name> -n qbo-firs-prod

Health Check Failures

Check:

  • Application is starting correctly
  • Health endpoint is accessible
  • Port configuration is correct

Fix:

# Check pod logs
kubectl logs <pod-name> -n qbo-firs-prod

# Exec into pod
kubectl exec -it <pod-name> -n qbo-firs-prod -- sh

# Test health endpoint inside pod
curl http://localhost:8443/companies/health/check

Best Practices

  1. Always test in development first - Deploy to dev environment before production
  2. Use semantic versioning - Tag releases with version numbers (v1.2.3)
  3. Monitor deployments - Watch logs and metrics after deployment
  4. Keep secrets secure - Never commit secrets to repository
  5. Regular updates - Keep dependencies and base images updated
  6. Backup configurations - Keep backup of working configurations
  7. Document changes - Update CHANGELOG for each deployment

Branch Strategy

main (production)
  ├── develop (development)
  │   ├── feature/new-feature
  │   ├── bugfix/fix-issue
  │   └── hotfix/urgent-fix
  • main - Production-ready code, triggers prod deployment
  • develop - Development code, triggers dev deployment
  • feature/ - New features, tested via CI
  • bugfix/ - Bug fixes, tested via CI
  • hotfix/ - Urgent fixes, can be merged directly to main

Support

For issues with:

  • Workflows - Check GitHub Actions logs
  • Kubernetes - Check pod logs and events
  • DigitalOcean - Contact DigitalOcean support
  • Application - Check application logs

Additional Resources