GitHub Actions is the CI tool. It runs automatically on every push to main in the fintrack-backend and fintrack-frontend repositories.
The full pipeline for the backend:
Developer pushes code to fintrack-backend
↓
GitHub Actions triggers
↓
Assumes AWS IAM role via OIDC (no stored keys)
↓
Builds Docker image → pushes to ECR
↓
Creates prisma-migrate Job inside EKS cluster
(cluster has VPC access to RDS - CI runner does not)
↓
Waits for migration to complete → prints logs
↓
Updates image tag in fintrack-gitops/manifests/backend/deployment.yaml
↓
ArgoCD detects the change → rolling update deploy
Traditional CI stores AWS access keys as GitHub secrets - a security risk. We use OIDC instead.
When GitHub Actions runs, it:
The only secrets stored in GitHub are:
| Secret | Value | Purpose |
|---|---|---|
AWS_ROLE_ARN |
arn:aws:iam::203637463799:role/fintrack-dev-github-actions-role |
Role to assume via OIDC |
GITOPS_PAT |
GitHub Personal Access Token | Push image tag updates to fintrack-gitops |
Located at .github/workflows/ci.yaml in fintrack-backend:
name: Backend CI
on:
push:
branches: [main]
env:
AWS_REGION: us-east-1
ECR_REPOSITORY: fintrack-backend
GITOPS_REPO: qezman/fintrack-gitops
jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
id-token: write # required for OIDC
contents: read
steps:
- uses: actions/checkout@v4
- name: Configure AWS credentials via OIDC
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
aws-region: ${{ env.AWS_REGION }}
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
- name: Build and push Docker image
id: build
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
IMAGE_TAG: ${{ github.sha }}
run: |
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest
- name: Run Prisma migrations in cluster
run: |
aws eks update-kubeconfig --name fintrack-dev --region $AWS_REGION
kubectl delete job prisma-migrate -n fintrack 2>/dev/null || true
# applies migration Job with current image tag
# Job runs inside cluster → has VPC access to RDS
# waits 120s for completion → prints logs → Job self-destructs
- name: Update image tag in gitops repo
run: |
# clones fintrack-gitops
# replaces image tag in manifests/backend/deployment.yaml
# commits and pushes → ArgoCD detects → deploys