Skip to main content

CI/CD Pipelines

All projects use GitHub Actions for CI/CD with a devmain promotion workflow. Backend, background-tasks, frontend, and documentation all run on GitHub-hosted ubuntu-latest runners with OIDC against github-actions-role for AWS access. The historical self-hosted EC2 runner has been terminated — see Self-Hosted Runner for context.

Workflow

warning

Never push directly to main. Always go through dev → PR → main.

Pipeline Details

Backend (aiqlick-backend)

aws-deploy.yml — runs on every push to dev or main.

  1. Resolve per-env variables (service name, task definition path, secret ARNs, API URL).
  2. Detect Prisma schema change (git diff HEAD^ HEAD prisma/schema.prisma) — gates step 5.
  3. Configure AWS credentials via OIDC (github-actions-role).
  4. Build + push Docker image to ECR (aiqlick-backend) with BuildKit registry cache.
  5. If schema changed, render + register task-definition-prisma-migrate.json, then aws ecs run-task for the one-shot Fargate task that runs prisma db push. Wait for tasks-stopped, fail the run if exit code ≠ 0.
  6. Render task-definition-{dev,prod}.json with the new image SHA, then aws-actions/amazon-ecs-deploy-task-definition@v2 against backend-{dev,prod} (wait-for-service-stability: true, 10 min cap).
  7. External smoke test: poll https://api(.dev).aiqlick.com/health until 200, then GraphQL introspection.

The deployment circuit breaker on the ECS service auto-rolls back on health-check failure — see ECS Fargate. Typical end-to-end: ~3-4 min (cold cache push dominates; warm deploys with no schema change land in ~2 min).

Background Tasks (background-tasks)

aws-deploy.yml — same shape as backend, minus the Prisma migrate step.

  1. Resolve per-env variables.
  2. Configure AWS credentials via OIDC.
  3. Build + push Docker image to ECR (background-tasks) with BuildKit cache.
  4. Render task-definition-{dev,prod}.json with the new image SHA.
  5. amazon-ecs-deploy-task-definition@v2 against bg-tasks-{dev,prod} (wait-for-stability).
  6. External smoke test against the internal ALB Cloud Map name from inside the workflow's runner network is not possible — instead the workflow trusts ECS health-check + circuit breaker to assert task healthiness.

Typical end-to-end: ~3 min. Rollback is handled by the deployment circuit breaker (no :previous tag dance — that was an EC2-era pattern and is gone).

Frontend (aiqlick-frontend)

  • Amplify auto-builds on push — this is the actual deploy path. No GitHub Actions deploy workflow.
    • dev branch → dev.aiqlick.com
    • main branch → www.aiqlick.com
  • Secrets fetched from Secrets Manager at build time via the Amplify build role.
  • Companion workflow ci.yaml polls Amplify after each push, streams build logs into the Actions tab, and fails the run if Amplify returns FAILED/CANCELLED.
  • A sync-docs.yml workflow mirrors DOCS/** changes into the documentation repo's docs/platform/frontend/guides/ (legacy bridge — see the docs sync caveat).

The previous playwright.yml workflow and the matching e2e/ test suite were removed in April 2026. There is no automated UI test coverage; the pre-commit verify-build.sh script is the only gate.

Documentation (documentation)

deploy.yml — runs on push to dev or main.

  1. npm ci + npm run build (Docusaurus).
  2. S3 sync (aiqlick-docs for prod, aiqlick-docs-dev for dev) via OIDC github-actions-role.
  3. CloudFront invalidation (auto-detects distribution by domain alias).

Jitsi Deploy (jitsi-deploy)

This is the only workload that still uses SSM in CI/CD because Jitsi runs on EC2 (not ECS).

  1. SSM send-command to i-0620d2e23695f5bfc (the Jitsi EC2).
  2. git pull on instance.
  3. docker compose pull && docker compose up -d --force-recreate.
  4. Health check.

Jitsi Meeting Web UI (aiqlick-meeting)

  1. Build Docker image.
  2. Push to ECR (aiqlick-meeting).
  3. SSM redeploy web container on the Jitsi EC2.

Jigasi (jigasi)

  1. Build Docker image.
  2. Push to ECR (aiqlick-jigasi).
  3. SSM deploy to the Jitsi EC2.

ECR Repositories

RepositoryImage SizeTagsUsed by
aiqlick-backend~240MBlatest, dev-latest, <git-sha>, buildcache, dev-buildcacheECS backend-{dev,prod}
background-tasks~699MBlatest, dev-latest, <git-sha>, buildcache, dev-buildcacheECS bg-tasks-{dev,prod}
aiqlick-meeting~142MBlatest, <git-sha>Jitsi EC2 (Docker Compose)
aiqlick-jigasi~505MBlatest, <git-sha>Jitsi EC2 (Docker Compose)
support-backend-rust(varies)per support-backend-rust workflowsupport-backend-alb

The *-buildcache tags hold BuildKit mode=max cache manifests (~1.1 GB for the backend), not runnable images. Branch-specific tags (dev-buildcache vs buildcache) prevent dev and main from overwriting each other's cache. The :previous tag from the BG EC2 era is gone — ECS deployment circuit breaker has replaced it.

Schema migration model (backend only)

Backend's deploy includes a one-shot Fargate task running prisma db push between the image build and the rolling service update. Triggered only when prisma/schema.prisma actually changed in the diff (cheap path otherwise). The same image used by the long-lived service runs the migrate task — same code, same env, same RDS endpoint. Failure of the migrate task fails the deploy before the service is touched.

Detail: Backend Deployment.

Git Workflow

git checkout dev
git add <specific files>
git commit -m "type(scope): description"
git push origin dev
# Create PR: dev → main
# Merge triggers production deploy

The /ship skill automates this end-to-end including the deploy status poll. See /ship skill.