Capstone: End-to-End Agent Pipeline
From code commit to running agent. That's the entire journey this capstone walks you through.
You've built your FastAPI agent in Module 6. You've containerized it with Docker (Chapter 79). You've deployed it with Kubernetes (Chapter 80). You've managed it with Helm (Chapter 81). Now you'll automate the entire path: push code, trigger tests, build a container, push to a registry, detect the new image in Git, and sync it automatically to your cluster.
This capstone is specification-first. Before writing a single YAML file, you'll write the specification that defines what your pipeline does, when it triggers, and how it validates. Then you'll implement it using GitHub Actions (CI) and ArgoCD (CD). Finally, you'll demonstrate the complete flow: code push → deployment → validation → rollback.
This lesson produces a fully automated, auditable pipeline for your agent. Every deployment is version-controlled, every rollback is a git revert, and every step is automated.
Pipeline Specification
Intent
Deploy your FastAPI agent from code push to accessible endpoint with full automation:
- Trigger: Every push to main branch automatically starts the pipeline
- CI Stage: Run tests, build container image, push to registry with SHA tag
- CD Stage: ArgoCD detects new image, syncs automatically, health checks confirm service is ready
- Validation: Agent endpoint responds to requests within 30 seconds of deployment
- Rollback: Git revert triggers ArgoCD to deploy previous version
Success Criteria
- ✅ Push to main triggers GitHub Actions within 30 seconds
- ✅ Tests pass with minimum 80% coverage before image build
- ✅ Container image pushed to registry in under 10 minutes
- ✅ ArgoCD detects new image and syncs within 3 minutes of registry push
- ✅ Agent endpoint returns HTTP 200 after deployment
- ✅ Rollback via git revert restores previous version within 5 minutes
- ✅ Complete flow logs are visible in GitHub Actions UI and ArgoCD UI
Components
Non-Goals
- Multi-environment deployments (dev/staging/prod) — Lesson 10 covers this with ApplicationSets
- Progressive delivery (canary/blue-green) — Lesson 13 covers this with Argo Rollouts
- Secrets management — Lesson 14 covers sealed secrets and external secrets
- Multi-cluster sync — Lesson 15 covers hub-spoke patterns
Step 1: GitHub Actions CI Workflow
Your GitHub Actions workflow automates the CI stage: trigger → test → build → push.
The flow:
GitHub Actions Workflow File
Create .github/workflows/ci.yaml:
Output when successful:
What This Workflow Does
- Trigger: Every push to main (and PRs for safety checks)
- Test Job: Runs pytest, enforces 80% coverage, uploads to Codecov
- Build Job: Waits for test success, builds multi-platform image, caches layers
- Push Job: Authenticates to GHCR with GitHub token, pushes image with SHA tag
- Update Job: Checks out GitOps repo, updates image reference in kustomization.yaml, commits and pushes
The entire flow is auditable: every commit links to a workflow run, which links to a container image, which links to a GitOps commit.
Step 2: GitOps Repository Structure
ArgoCD watches a Git repository for your desired state. The structure tells ArgoCD what to deploy.
Create a separate repository called gitops-repo (not the code repo):
Kustomization Configuration
File: gitops-repo/fastapi-agent/base/kustomization.yaml
File: gitops-repo/fastapi-agent/base/deployment.yaml
File: gitops-repo/fastapi-agent/base/service.yaml
Output when kustomize applies this:
Step 3: ArgoCD Application
ArgoCD watches the GitOps repository and syncs changes to your cluster.
File: argocd/applications/fastapi-agent.yaml
Apply this to your cluster:
Output:
Step 4: Image Update Automation
When CI pushes a new image to the registry, how does ArgoCD know?
The answer: The CI workflow updates kustomization.yaml in the GitOps repo. ArgoCD watches Git. When Git changes, ArgoCD syncs.
Kustomize Image Updater
The update-gitops job in your CI workflow updates the image tag:
What kustomize edit does:
Output: fastapi-agent/base/kustomization.yaml now contains:
ArgoCD sees this change in Git, pulls the new image reference, and syncs.
Alternative: Helm Values Update
If using Helm instead of Kustomize:
This updates values.yaml:
Step 5: End-to-End Validation
After deployment, validate that your pipeline worked.
Step 1: Trigger the Pipeline
Push code to main:
Expected output: GitHub Actions workflow starts automatically (check Actions tab in GitHub).
Step 2: Monitor GitHub Actions
In your GitHub repository → Actions tab:
Wait for all three jobs to complete. Total time: 8-12 minutes.
Output when complete:
Step 3: Verify Image in Registry
Step 4: Verify GitOps Repository Updated
Check the image tag in kustomization:
Step 5: Verify ArgoCD Synced
Step 6: Verify Agent is Running
Get the Service IP:
Test the agent endpoint (port-forward or use external IP):
Test an agent endpoint:
Validation Checklist
- ✅ GitHub Actions workflow completed with all three jobs passing
- ✅ Test coverage ≥ 80%
- ✅ Container image pushed to registry with correct SHA tag
- ✅ GitOps repository updated with new image reference
- ✅ ArgoCD app status shows "Synced" and "Healthy"
- ✅ All Deployment pods are Running and Ready (2/2 replicas)
- ✅ Agent endpoint responds with HTTP 200
- ✅ Health check endpoint returns healthy status
- ✅ Agent can process requests (create tasks, etc.)
If all checks pass, your complete CI/CD pipeline is working. From code push to running agent: fully automated.
Step 6: Rollback Demonstration
Production issue? A commit introduced a bug? Kubernetes makes rollback trivial: revert the Git commit.
Scenario: Detect an Issue
Your agent is running with the new deployment. You get a bug report:
Step 1: Identify the Problem Commit
Step 2: Revert the Commit
Step 3: Push the Revert
Expected output: GitHub Actions triggers automatically.
Step 4: Monitor the Rollback
In GitHub Actions:
Image built: ghcr.io/org/repo/fastapi-agent:main-2d4e5f6 (the reverted version)
Step 5: Watch ArgoCD Sync Old Version
Step 6: Verify Rollback Successful
Test the endpoint again:
Timeline of Rollback
Complete Pipeline Reference
Here's the entire automation flow in one diagram:
Capstone Completion Checklist
Use this checklist to verify you've completed the entire capstone:
GitHub Actions Setup
- ✅ .github/workflows/ci.yaml created with all three jobs
- ✅ Tests run and enforce 80% coverage minimum
- ✅ Multi-platform build configured (linux/amd64, linux/arm64)
- ✅ Image pushed to GHCR with SHA tag
- ✅ GitOps repository token configured in GitHub Secrets
GitOps Repository
- ✅ Separate gitops-repo created (not code repo)
- ✅ Directory structure: fastapi-agent/base/ and fastapi-agent/overlays/
- ✅ kustomization.yaml configures image and namespace
- ✅ deployment.yaml includes health checks and resource limits
- ✅ service.yaml exposes agent on port 80
- ✅ CI workflow updates image tag on every push
ArgoCD Configuration
- ✅ ArgoCD Application created at argocd/applications/fastapi-agent.yaml
- ✅ Application points to GitOps repo (https://github.com/org/gitops-repo)
- ✅ Auto-sync enabled (prune + selfHeal)
- ✅ Namespace created automatically (CreateNamespace=true)
- ✅ Application syncs within 3 minutes of Git update
End-to-End Validation
- ✅ Pushed code to main, triggered workflow automatically
- ✅ Tests passed with coverage ≥ 80%
- ✅ Image built and pushed to GHCR
- ✅ GitOps repo updated with new image tag
- ✅ ArgoCD synced (status: Synced + Healthy)
- ✅ Agent pods running (2/2 Ready)
- ✅ Agent endpoint responds (HTTP 200)
- ✅ Health check passes (/health → 200)
Rollback Demonstration
- ✅ Identified a problem commit
- ✅ Ran git revert to revert the commit
- ✅ Pushed revert, triggered workflow automatically
- ✅ New image built with reverted code
- ✅ ArgoCD synced old image to cluster
- ✅ Agent pods restarted with previous version
- ✅ Verified agent works again
- ✅ Total rollback time < 10 minutes
Advanced Extensions (Optional)
- ⭐ Add ApplicationSet for multi-environment deployment (dev/staging/prod)
- ⭐ Configure Slack notifications (Lesson 12)
- ⭐ Implement canary/blue-green with Argo Rollouts (Lesson 13)
- ⭐ Add sealed secrets for database credentials (Lesson 14)
- ⭐ Scale to multiple clusters with hub-spoke (Lesson 15)
Try With AI
You've built a complete, automated CI/CD pipeline. Now collaborate with Claude to troubleshoot and extend it.
Setup for This Section
You'll need:
- Your FastAPI agent code in a GitHub repository
- A working Kubernetes cluster (Minikube, GKE, EKS, etc.)
- ArgoCD installed with admin access
- Container registry access (GHCR, Docker Hub, etc.)
- GitHub repository with Actions enabled
Scenario 1: Pipeline is Stuck
Your situation: You pushed code, GitHub Actions started, but the workflow is hanging on the build step.
Exploration prompt:
"I pushed code 15 minutes ago and GitHub Actions is still building. The log shows:
It seems stuck. What are common reasons Docker builds hang in CI? How do I debug this?"
Ask Claude about:
- Network issues (registry timeout, DNS problems)
- Disk space in the runner
- Memory constraints
- Large dependency downloads without caching
- How to add debugging output to your workflow
Refine your question:
- Build output logging: docker buildx build --progress=plain
- Timeout settings: timeout: 15m on the step
- Debug environment variables: BUILDX_BUILDER_OUTPUT_VERBOSE=true
Scenario 2: ArgoCD Not Syncing
Your situation: The GitOps repo has the new image tag, but ArgoCD says "out of sync."
Exploration prompt:
"ArgoCD shows my app is 'OutOfSync' but the kustomization.yaml has the correct image tag:
Why isn't it syncing? The app repo is set to auto-sync. What am I missing?"
Ask Claude about:
- Is the app watching the right Git branch? (Check targetRevision)
- Is the path correct? (Check path in Application spec)
- Are there differing fields? (Use argocd app diff)
- Is the Git token working? (Check SSH key or HTTPS token)
- Run: argocd app sync --force to force reconciliation
Refine your question:
- Diagnose with: argocd app diff fastapi-agent
- Check Git access: argocd repo add ...
- Enable debug logging: --loglevel debug
Scenario 3: Image Never Gets Updated
Your situation: CI completes successfully, image is pushed to GHCR, but kustomization.yaml never updates in the GitOps repo.
Exploration prompt:
"My workflow completed:
- ✅ Tests passed
- ✅ Image pushed: ghcr.io/org/repo/fastapi-agent:main-a1b2c3d
- ❌ But GitOps repo kustomization.yaml still has the old tag: main-old
The update-gitops job logs show 'success' but the commit never appeared. What could be wrong?"
Ask Claude about:
- Is secrets.GITOPS_REPO_TOKEN configured? (Authentication fails silently)
- Does the token have write access to the GitOps repo?
- Is the branch protection rule blocking commits?
- Is the git config correct? (user.name, user.email)
- How to check GitHub Actions logs for actual error
Refine your question:
- Add explicit error handling: git push || { echo "Push failed"; exit 1; }
- Verify token permissions: List allowed actions
- Test locally: git clone with the token to verify it works
- Add verbose logging: git config core.logallrefupdates true
Scenario 4: Rollback Didn't Work
Your situation: You reverted a commit and pushed, but ArgoCD is deploying the new image instead of the old one.
Exploration prompt:
"I ran:
But ArgoCD is deploying image main-newSHA (the reverted commit) instead of main-oldSHA (the version before the reverted commit).
The kustomization.yaml shows the correct image tag. Why is it deploying the wrong one?"
Ask Claude about:
- Image cache issues (pullPolicy should be Always, not IfNotPresent)
- Pod using cached local image instead of pulling new one
- ArgoCD showing correct image but deployment pulling cached version
- Using kubectl describe pod -n agents to check actual image
Refine your question:
- Force image pull: Change to imagePullPolicy: Always
- Delete old pods: kubectl delete pods -n agents -l app=fastapi-agent
- Verify image exists in registry: crane ls ghcr.io/org/repo/fastapi-agent
- Check pull secret if registry is private
Scenario 5: Add Multi-Environment Deployment
Your situation: You want to deploy to dev and prod with different replicas and resources.
Exploration prompt:
"I have a working pipeline deploying to production. Now I need to deploy the same agent to a dev environment with:
- 1 replica instead of 2
- Smaller resource limits (128Mi RAM instead of 256Mi)
- Same code, different configuration
Should I create another Application? Use ApplicationSets? How do I keep them in sync?"
Ask Claude about:
- ApplicationSet with List generator (one entry per environment)
- Overlays pattern (base + dev/prod patches)
- Environment variables for different configs
- Helm values overrides
Refine your question:
- ApplicationSet YAML with List generator for dev, prod
- Kustomize overlays: base/ + overlays/dev/ + overlays/prod/
- How to parameterize replicas and resources
- How CI deploys to both environments in sequence
Core Concept
Build a complete CI/CD pipeline from code push to running agent using GitHub Actions (test, build, push, update GitOps repo) and ArgoCD (detect change, sync, health check), with rollback via git revert.
Key Mental Models
- Specification-First: Define intent, success criteria, components, and non-goals before writing YAML
- CI/CD Flow: Push triggers test (80% coverage), build (multi-platform), push (GHCR), update-gitops (kustomize edit)
- GitOps Separation: Code repo (source) separate from GitOps repo (manifests); CI updates GitOps repo image tag
- Audit Trail: Every deployment traceable to Git commit; rollback is git revert, not kubectl delete
Critical Patterns
- GitHub Actions jobs: test (pytest coverage), build-and-push (docker/build-push-action), update-gitops (kustomize edit set image)
- GitOps repo structure: fastapi-agent/base/ with kustomization.yaml, deployment.yaml, service.yaml
- ArgoCD Application with auto-sync watches GitOps repo, syncs within 3 seconds of change detection
- Rollback workflow: identify commit, git revert, push triggers new build with reverted code
AI Collaboration Keys
- Ask Claude to troubleshoot stuck builds (layer caching, network timeouts, disk space)
- Request diagnosis for OutOfSync status (targetRevision, path, Git token issues)
- Have AI explain GitOps repo token configuration when image tag updates fail
Common Mistakes
- Missing secrets.GITOPS_REPO_TOKEN preventing CI from pushing to GitOps repo
- Using imagePullPolicy: IfNotPresent causing cached old images during rollback
- Not testing complete flow before relying on it for production
Connections
- Builds on: Lesson 16 - AI-Assisted GitOps Workflows
- Leads to: Lesson 18 - Building the GitOps Deployment Skill
📋Quick Reference
Unlock Lesson Summary
Access condensed key takeaways and quick reference notes for efficient review.
- Key concepts at a glance
- Perfect for revision
- Save study time
Free forever. No credit card required.