Building a Production-Ready CI/CD Pipeline
What a production-ready CI/CD pipeline actually needs — quality gates, approval checkpoints, and rollback — built with Jenkins, using a Java Maven app as the example.
Overview
What does it actually take for a CI/CD pipeline to be production-ready, not just functional? This project works through that question by building one end-to-end — using Jenkins, Docker, SonarQube, and Ansible, with a Java Maven app as the working example — triggered from GitHub, with Discord notifications and k6 smoke tests. The goal was to remove manual, error-prone steps from build-and-deploy (someone SSH-ing in to run a jar by hand), while still requiring manual approval before a build reaches production.
It’s split into two independent pipelines. CI focuses on code quality — testing, generating reports, and only building an artifact if the quality gate passes. CD focuses on deployment — taking that tested artifact, deploying it to a chosen environment through a manual checkpoint, and rolling back automatically if the deploy or the post-deploy smoke test fails. Both pipelines send a notification with the outcome.
CI Highlights

- Build runs in an ephemeral Docker environment — clean and reproducible every run
- JUnit 5 + JaCoCo run tests and generate a coverage report for further review/tracking
- SonarQube also plays as a quality gate — code quality and vulnerability scan
- Artifact only gets built (
mvn package -DskipTests) if the quality gate passes — no rebuild, compile’s already cached from the test step - Passing artifact publishes to Nexus as a versioned jar
CD Highlights

- Deploy environment (dev/staging/prod) selected before anything runs
- Supervisor approval gate — a manual checkpoint before anything touches production
- Exact jar already tested in CI gets deployed, no rebuild step in CD
- Ansible locates and deploys to the specific target host(s)
- Rollback mechanism ensures service availability
Why the approval gate
Fully automatic deploys are appealing until a bad build goes straight to production. The approval gate is a deliberate speed/safety tradeoff: CI stays fully automatic (build, test, scan all happen without anyone touching a button), but CD keeps one manual checkpoint right before production traffic is affected — cheap insurance against shipping a build nobody actually looked at.
Why rollback matters more than the happy path
Most of the actual engineering time here went into the failure path, not the success path — anyone can script “build, deploy, done.” Automatic rollback on smoke-test failure means a bad deploy self-heals in the time it takes k6 to notice, instead of waiting for someone to spot an alert and manually revert.
Why test before packaging
Packaging isn’t free — it takes time, and that cost adds up as the number of CI runs grows. Running the quality gate before packaging means a failing build never reaches that step at all — no wasted time or resources on an artifact that was going to get thrown out anyway.
Looking Ahead
Java can also ship as a native image — Quarkus is one path to that. Right now this pipeline sticks to a jar artifact, since that’s what the current deployment target expects.
← Back to projects