Module 8: Capstone The Andes Cargo Pipeline

1. Capstone introduction: the complete pipeline, end-to-end

Description

Seven modules built, piece by piece, a complete, real infrastructure CI/CD pipeline: ci.yml calculates a plan on every Pull Request and blocks it if it tries to destroy the Shipments table; apply.yml applies exactly that plan —never a recalculated one— only when that PR merges to main; drift.yml watches, with a scheduled check, that nobody has touched infrastructure outside Terraform. This last module doesn't add a single new step to any of the three files. What it does is what no previous module had room to do: run the complete pipeline, end-to-end, on two scenarios that together prove this entire guide's thesis —a real change the pipeline approves and applies, and a dangerous change the same pipeline stops before it ever touches anything—, close with the final honesty about which part of all this you only get to live with a real GitHub account, trace the exact boundary toward the security this guide named but didn't build, and deliver the complete repository as a portfolio piece you can defend in a technical interview without hesitation.

Connection to the module

This module doesn't introduce any new mechanism — it's, on purpose, this guide's only module that doesn't build anything. Lessons 3 and 4 are the end-to-end walkthrough that gives this capstone its title: a real change crossing ci.ymlapply.yml, and a destruction attempt Module 6's guardrail stops before any chance to apply exists. Lessons 5, 6, and 7 are boundary honesty —what's missing, and which guide it lives in—. Lesson 8 is the close: the same andes-cargo-infra/ repository you started preparing in Module 1, now complete, documented, and ready to show.


What you already have, module by module

Before running anything, it's worth having the complete inventory in your head — not as an abstract summary, but as the exact list of pieces you're going to see work together in this module:

ModuleWhat it builtLives in
1act installed (0.2.89), .actrc pinned, andes-cargo-infra/ initialized as a Git repository, LocalStack started on the host.actrc, .git/
2A workflow's complete anatomy; pr-event.json (PR #42, feature/add-shipment-tagsmain) to simulate events with no real GitHub account; .secrets gitignored.github/act-events/pr-event.json, .secrets
3ci.yml: fmtinitvalidate → connection to LocalStack → plan → summary published in $GITHUB_STEP_SUMMARY.github/workflows/ci.yml
4Credentials migrated to secrets.AWS_ACCESS_KEY_ID/secrets.AWS_SECRET_ACCESS_KEY; OIDC shown in real YAML, without executing it; dev/production Environments explained, with act confirmed ignoring them.github/workflows/ci.yml (migrated), SECRETS-AND-ENVIRONMENTS.md
5apply.yml: needs: + upload-artifact/download-artifact to apply the exact plan, concurrency: against the double apply, drift.yml with terraform_wrapper: false.github/workflows/apply.yml, .github/workflows/drift.yml
6git revert as infrastructure rollback; branch protection explained (representative); the guardrail: a grep over terraform show -json that blocks any plan destroying Shipments, tested with a seeded state fixture.github/workflows/ci.yml (with guardrail), .github/workflows/guardrail-demo.yml, .github/guardrail-fixtures/
7The market landscape (GitLab CI, CircleCI, Jenkins), pull-based GitOps (ArgoCD/Flux, named), the boundary with application CI/CD, an ADR documenting why Andes Cargo chose GitHub Actionsdoc/adr/0001-choosing-cicd-tooling.md

Nothing in this table is theoretical — every row is a real file you ran with act, against the same LocalStack, with the same 000000000000 account and the same us-east-1 region terraform-and-iac-guide set up from the start. The only thing missing was seeing all of them work together, under pressure, on a change that genuinely matters and one that shouldn't go through.


This module's map: the 8 lessons

   MODULE 8 — CAPSTONE: THE ANDES CARGO PIPELINE

   L1  Introduction (this one)              the complete inventory, what gets delivered
   L2  Architecture review                  complete diagram: ci.yml + apply.yml +
                                             drift.yml + guardrail + act↔LocalStack network
   L3  A real change, end-to-end            EXECUTED — a new tag crosses the whole pipeline
   L4  A rejected change, end-to-end        EXECUTED — the guardrail stops a destruction
   L5  What only real GitHub shows          REPRESENTATIVE — real PR comments, approval,
                                             branch protection
   L6  The security this guide didn't build boundary → cloud-security-and-guardrails-guide
   L7  What Andes Cargo still needs         ecosystem map: EKS, SRE, FinOps
   L8  Project: the complete capstone       EXECUTED — the repository as portfolio
#LessonWhat gets executed/practiced
1Introduction (this one)Modules 1-7's complete inventory; what gets delivered when this guide closes
2Architecture review: the complete pipelineComplete ASCII diagram: ci.yml + apply.yml + drift.yml, the guardrail, and the network connecting act's job ↔ host.docker.internal ↔ LocalStack
3End-to-end walkthrough: a real changeEXECUTED: a new tag on the bucket, branch → simulated PR → ci.yml → simulated merge → apply.yml, verified with awslocal
4End-to-end walkthrough: a rejected changeEXECUTED: an attempt to destroy Shipments the guardrail stops before applying
5What you only get with a real GitHub accountREPRESENTATIVE: real PR comments, real environment approval, real branch protection
6The security this guide didn't buildExplicit boundary: end-to-end OIDC, SAST/DAST, SBOM/cosign/Trivy, policies as a system → cloud-security-and-guardrails-guide
7What Andes Cargo still needsEcosystem map: EKS + ArgoCD, deployment SRE, infrastructure FinOps
8Final project: the pipeline as a deliverableEXECUTED: the complete repository as a portfolio piece defensible in an interview

Notice this module's shape: lessons 3 and 4 are the technical proof —the same "nothing gets simulated in prose" discipline that held throughout this guide, applied one last time, with the added pressure that now everything has to work together, not in isolation—. Lessons 5, 6, and 7 are boundary honesty, the same kind you already saw at specific points in Module 4 (OIDC) and Module 6 (conftest), now consolidated in one place before closing the guide. Lesson 8 turns the previous seven into a single deliverable.


What gets executed and what stays representative in this module, with no ambiguity

   Lesson  Executed?             Why

   L2      No (it's a diagram)   Review of what's already built, no new code to run
   L3      Yes                   act pull_request + act push, on a real HCL change
   L4      Yes                   act workflow_dispatch, on Module 6's guardrail
   L5      No                    PR comments/approval/branch protection are real
                                  GitHub.com — you already saw why act can't reach them
   L6      No                    Names, doesn't build — the same boundary from Module 4
   L7      No                    Ecosystem map, touches no new resource
   L8      Yes                   The complete repository audit, real commands

Four of the eight lessons —half— are boundary honesty with no execution, and that's intentional, not filler at the close: closing a complete guide demands, with the same rigor as opening it, precisely saying what's left out. The other four —2, 3, 4, and 8— are where this module earns its place: lesson 2 gives you the complete map before running anything; lessons 3 and 4 are the final proof, under pressure, that every piece built across the seven previous modules still works when put together; lesson 8 turns all of that into something you can teach another person.


Common mistakes

Expecting this module to add a ninth step, a fourth workflow, or a new technical piece (expectation-based). What happens: someone, used to every previous module ending with at least one new or extended .yml file, looks for that same pattern here and doesn't find it. How to spot it: if your question opening lesson 2 is "what am I building today?" instead of "what did I already build, and what does it look like complete?" How to fix it: this module integrates and tests, it doesn't build — the one real exception is lesson 8's portfolio README.md, which documents, automates nothing new.

Skipping lessons 5-7 for seeming "just theory" (scope-based, the most costly mistake in closing a guide badly). What happens: someone, driven by lessons 3 and 4's tangible execution, jumps straight to lesson 8 without reading lessons 5, 6, and 7's boundary honesty. Why it happens: after seeing act genuinely run, a lesson with no commands feels less important. How to fix it: in a real technical interview, the question "what's this pipeline missing?" is as common as "how does it work?" — lessons 5-7 are, literally, the complete script for that answer, with the exact boundary toward each sister guide in this ecosystem.

Thinking "capstone" means "repeat what's already done, nothing new to learn" (conceptual). What happens: someone assumes lessons 3 and 4 are just a repeat of Module 3's, Module 5's, and Module 6's projects, and skims them. How to fix it: each earlier project tested one half of the pipeline separately (CI alone, CD alone, the guardrail in isolation). This module's lessons 3 and 4 are the first time you see all three layers —review, application, safety net— act in the same run, on the same change, with no shortcuts — the final integration test, not a repeat.


Exercises

Exercise 1 — Reconstruct the seven modules' inventory, from memory. Without looking at this lesson's table, write what each of Modules 1 through 7 built, in one sentence per module.

See solution

M1: act installed and verified, andes-cargo-infra/ initialized as a Git repository, LocalStack started. M2: a workflow's complete anatomy, event simulation with act -e (pr-event.json), secrets with .secrets. M3: the complete ci.ymlfmt/validate/plan/summary. M4: secrets migrated to secrets.<NAME>, OIDC shown without executing, Environments explained. M5: apply.yml with needs:/artifacts/concurrency, scheduled drift.yml. M6: rollback with git revert, branch protection explained, the real guardrail against destroying Shipments. M7: the market landscape and the tooling decision ADR. If you reconstructed all seven without looking, you have the complete inventory internalized, not just copied from a table.

Exercise 2 — Predict what would happen if Module 6 didn't exist. Without Module 6's guardrail, what would stop, today, a Pull Request trying to destroy the Shipments table? Answer precisely, using what you already know from Modules 3 and 4.

See solution

Nothing would stop it automatically. ci.yml, without the guardrail, would calculate the plan with the destruction included and publish it in the job summary —exactly like it calculates any other plan—, but the job would end green anyway, because a plan that destroys something isn't, on its own, a Terraform error. The only defense, without the guardrail, would be a person reviewing the plan's content in time and deciding not to approve the merge — that is, it would depend entirely on human judgment at the exact moment of review, with no automated backup control. This is exactly why Module 6 exists: turning "someone should notice" into "the pipeline doesn't let it through, even if nobody notices."

Exercise 3 — Anticipate lessons 3 and 4's structure. Based on the "What to expect (literal)" pattern that held throughout this guide, what kind of evidence would you expect to see in lesson 4 confirming the guardrail blocked the change, beyond reading the word "failed" somewhere?

See solution

Following the same pattern as Module 6, lesson 7, the complete evidence should include: (1) the plan's exact number (something like X to add, 1 to destroy, with the 1 to destroy as the concrete signal), (2) the guardrail's exact error message, citing the specific resource (aws_dynamodb_table.shipments), and (3), the piece most important to this module's thesis, confirmation that no later step ran — specifically, that no artifact called terraform-plan ever got uploaded, meaning apply.yml, even if someone triggered it by hand, would have nothing to apply. Seeing only "Job failed" without these three pieces wouldn't be enough evidence that the safety net worked for the right reason.


Summary and next step

In this lesson you reviewed the seven previous modules' complete inventory —every real piece, every file still living in andes-cargo-infra/— and saw the map of the eight lessons that close this guide: two final technical proof lessons (3 and 4), three of boundary honesty (5, 6, and 7), and a project that turns everything into a portfolio deliverable (8), preceded by this introduction and an architecture review (2).

Before moving on you should be able to: name, without looking, what each of Modules 1 through 7 built; explain why this module adds no new technical piece to the pipeline; and anticipate, precisely, what kind of evidence you'd expect to see in a successful end-to-end walkthrough and in a rejected one.

Lesson 2 assembles the pipeline's complete diagram —the three workflows, the guardrail, and the network connecting act's container with the host's LocalStack— before running anything, so lessons 3 and 4 have, from the very first command, the complete map in your head.

Resources

  1. nektosact.com — User Guide — complete act reference, the tool this module uses again end-to-end.
  2. GitHub Docs — GitHub Actions — official documentation for the complete engine behind Andes Cargo's three workflows.
  3. HashiCorp Developer — Automate Terraform with GitHub Actions — the plan/apply pattern that holds up the entire pipeline, cited since Module 3.
  4. src/paths/aws-cloud-ecosystem/VALIDACION.md (NIEVA) — the market gap this complete guide closes, cited since Module 1.