GitHub Actions Reference
Overview
The DineTogether infrastructure uses GitHub Actions for continuous deployment. This reference covers all workflows and their configuration.
Workflow Files
Reusable Deploy Workflow
Location: .github/workflows/deploy.yml
Purpose: Shared workflow that any repository can use for deployment.
name: Deploy to Kubernetes
on:
workflow_call:
inputs:
repository:
required: true
type: string
description: 'Repository name (owner/repo)'
environment:
required: false
type: string
default: 'staging'
description: 'Deployment environment'
secrets:
DEPLOY_TOKEN:
required: true
description: 'GitHub token with package read permissions'
Using the Deploy Workflow
Basic Usage
In your application repository, create .github/workflows/deploy.yml:
name: Build and Deploy
on:
push:
branches: [main]
pull_request:
types: [opened, synchronize]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: |
ghcr.io/${{ github.repository }}:latest
ghcr.io/${{ github.repository }}:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max
deploy:
needs: build
if: github.ref == 'refs/heads/main'
uses: dine-together/k8s-infrastructure/.github/workflows/deploy.yml@main
with:
repository: ${{ github.repository }}
environment: staging
secrets:
DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
Advanced Configuration
Multiple Environments
jobs:
deploy-staging:
uses: dine-together/k8s-infrastructure/.github/workflows/deploy.yml@main
with:
repository: ${{ github.repository }}
environment: staging
secrets:
DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
deploy-production:
if: github.ref == 'refs/heads/production'
uses: dine-together/k8s-infrastructure/.github/workflows/deploy.yml@main
with:
repository: ${{ github.repository }}
environment: production
secrets:
DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN_PROD }}
Manual Deployment
on:
workflow_dispatch:
inputs:
environment:
description: 'Environment to deploy to'
required: true
type: choice
options:
- staging
- production
Workflow Steps Explained
1. Checkout Infrastructure Code
- uses: actions/checkout@v4
with:
repository: dine-together/k8s-infrastructure
token: ${{ secrets.DEPLOY_TOKEN }}
2. Setup Tools
Installs kubectl for Kubernetes operations.3. Checkout App Repository
- uses: actions/checkout@v4
with:
repository: ${{ inputs.repository }}
path: app
token: ${{ secrets.DEPLOY_TOKEN }}
4. Convert Docker Compose
- name: Convert docker-compose to k8s
run: |
python scripts/compose-to-k8s.py \
app/docker-compose.yml \
k8s-manifests.yaml
5. Configure kubectl
- name: Configure kubectl
env:
KUBECONFIG_FILE: ${{ secrets.KUBECONFIG }}
run: |
mkdir -p ~/.kube
echo "$KUBECONFIG_FILE" | base64 -d > ~/.kube/config
6. Apply Manifests
Deploys the application to Kubernetes.Secrets Reference
Required Secrets
| Secret | Purpose | Scope |
|---|---|---|
DEPLOY_TOKEN |
GitHub PAT with package:read | Repository |
KUBECONFIG |
Base64-encoded kubeconfig | Infrastructure repo |
GITHUB_TOKEN |
Automatic token for builds | Automatic |
Creating DEPLOY_TOKEN
- Go to GitHub Settings → Developer settings → Personal access tokens
- Create token with permissions:
read:packages(required)repo(if accessing private repos)- Add to repository:
Setting KUBECONFIG
# Get kubeconfig from server
ssh user@server 'sudo cat /etc/rancher/k3s/k3s.yaml' > kubeconfig.yaml
# Update server URL
sed -i 's/127.0.0.1/YOUR_SERVER_IP/g' kubeconfig.yaml
# Encode and set
cat kubeconfig.yaml | base64 -w 0 > kubeconfig.b64
gh secret set KUBECONFIG < kubeconfig.b64 --repo dine-together/k8s-infrastructure
Environment Variables
Build Job
| Variable | Description | Example |
|---|---|---|
GIT_SHA |
Commit SHA for tagging | abc123... |
REGISTRY |
Container registry | ghcr.io |
IMAGE_NAME |
Full image path | ghcr.io/dine-together/app |
Deploy Job
| Variable | Description | Default |
|---|---|---|
NAMESPACE |
K8s namespace | test-staging or dine-together-production |
DOMAIN |
Base domain | test.dinetogether.co.uk |
ENVIRONMENT |
Environment name | staging |
Caching Strategies
Docker Build Cache
Uses GitHub Actions cache for faster builds.
Alternative: Registry Cache
cache-from: type=registry,ref=ghcr.io/${{ github.repository }}:buildcache
cache-to: type=registry,ref=ghcr.io/${{ github.repository }}:buildcache,mode=max
Conditional Deployment
Branch-based
Tag-based
PR Preview
if: github.event_name == 'pull_request'
with:
environment: pr-${{ github.event.pull_request.number }}
Error Handling
Retry Logic
- name: Deploy with retry
uses: nick-invision/retry@v2
with:
timeout_minutes: 10
max_attempts: 3
command: kubectl apply -f k8s-manifests.yaml
Rollback on Failure
- name: Rollback on failure
if: failure()
run: |
kubectl rollout undo deployment/myapp -n $NAMESPACE
Monitoring Deployment
Wait for Rollout
Health Check
- name: Verify deployment
run: |
kubectl wait --for=condition=ready pod \
-l app=myapp -n $NAMESPACE \
--timeout=300s
Advanced Patterns
Matrix Deployments
strategy:
matrix:
service: [frontend, backend, worker]
jobs:
deploy:
uses: ./.github/workflows/deploy.yml
with:
repository: dine-together/${{ matrix.service }}
Parallel Deployments
jobs:
deploy-frontend:
uses: ./.github/workflows/deploy.yml
# ...
deploy-backend:
uses: ./.github/workflows/deploy.yml
# ...
verify:
needs: [deploy-frontend, deploy-backend]
runs-on: ubuntu-latest
steps:
- run: echo "All deployments complete"
Blue-Green Deployment
- name: Deploy to green
run: |
kubectl apply -f k8s-manifests.yaml -n $NAMESPACE-green
kubectl wait --for=condition=ready pod -l app=myapp -n $NAMESPACE-green
- name: Switch traffic
run: |
kubectl patch ingress myapp -n $NAMESPACE \
-p '{"spec":{"rules":[{"host":"myapp.com","http":{"paths":[{"backend":{"service":{"name":"myapp-green"}}}]}}]}}'
Debugging Workflows
Enable Debug Logging
SSH into Runner
Artifact Upload
- name: Upload manifests
if: always()
uses: actions/upload-artifact@v3
with:
name: k8s-manifests
path: k8s-manifests.yaml
Security Best Practices
- Limit Token Permissions
- Use minimum required permissions
-
Separate tokens for different environments
-
Protect Secrets
- Never log secret values
-
Use GitHub Environments for protection
-
Verify Images
Troubleshooting
Common Issues
- 401 Unauthorized
- Check DEPLOY_TOKEN permissions
-
Verify token hasn't expired
-
kubectl connection refused
- Verify KUBECONFIG is correct
-
Check server IP and port
-
Deployment timeout
- Check pod logs
- Verify image can be pulled
- Check resource limits
Debug Commands
- name: Debug info
if: failure()
run: |
echo "Repository: ${{ inputs.repository }}"
echo "Environment: ${{ inputs.environment }}"
kubectl get all -n $NAMESPACE
kubectl describe pod -l app=myapp -n $NAMESPACE
Next Steps
- Learn about Configuration options
- Review Scripts used in workflows
- Check Deployment Guide for setup