Certified Jenkins Engineer

Kubernetes and GitOps

Demo Deploy to Prod

In this lesson, we'll extend our CI/CD pipeline to include a manual approval gate before deploying to AWS Lambda. Previously, we covered:

  • Deploying to AWS EC2 VMs
  • Running integration tests
  • Opening a pull request for Kubernetes via Argo CD
  • Performing a DAST scan with OWASP ZAP

Now, on the main branch, we'll pause for an admin’s go‐ahead, update Lambda configuration, and run function tests. All stages trigger only on new pushes to main.

StageBranch/TriggerPurpose
Integration Testing – AWS EC2any branchValidate code on EC2 instances
K8S – Update Image Tagany branchBump container image in manifests
K8S – Raise PRany branchCreate PR for K8s changes
App Deployed?any branchConfirm deployment status
DAST – OWASP ZAPany branchRun security scan via OWASP ZAP
Upload – AWS S3PR*, mainUpload test/report artifacts to S3
Deploy to Prod?mainManual approval gate for production deploy

The image is a flowchart illustrating a deployment approach, detailing processes for feature branches, pull requests, and main branches, including AWS EC2 deployment, Docker updates, and AWS Lambda deployment.

1. Add a Manual Approval Stage in Jenkinsfile

Edit your Jenkinsfile on the feature branch. After the AWS S3 upload, insert a Deploy to Prod? stage that runs only on main and waits up to one day for an admin to confirm.

1.1. Current CI Stages

stage('Integration Testing - AWS EC2') {
    // existing steps
}

stage('K8S - Update Image Tag') {
    // existing steps
}

stage('K8S - Raise PR') {
    // existing steps
}

stage('App Deployed?') {
    // existing steps
}

stage('DAST - OWASP ZAP') {
    // existing steps
}

stage('Upload - AWS S3') {
    // existing steps
}

post {
    always {
        // cleanup or notifications
    }
}

Note

The post { always { … } } block runs regardless of build outcome—ideal for reporting.

1.2. New Approval Stage

stage('Deploy to Prod?') {
    when {
        branch 'main'
    }
    steps {
        timeout(time: 1, unit: 'DAYS') {
            input message: 'Deploy to Production?',
                  ok: 'YES! Let us try this on Production',
                  submitter: 'admin'
        }
    }
}

Note

The submitter: 'admin' line restricts approval to users in the admin group.


2. Testing the Approval Mechanism

  1. Commit and push your updated Jenkinsfile.
  2. Open a pull request, merge it into main.
  3. Jenkins will start a fresh pipeline on main.

The image shows a pull request interface from a code repository, listing multiple commits with their statuses, and a sidebar with details like reviewers, labels, and participants.

Even if a prior build was aborted, merging triggers a new run:

The image shows a pull request interface with a list of commits and a warning about a build error. There is an option to create a merge commit despite the error.

In Jenkins Blue Ocean, all CI stages skip except the approval prompt:

The image shows a Jenkins pipeline interface for a project named "solar-system" with various stages like installing dependencies, unit testing, and deploying to production. It includes a prompt asking whether to deploy to production, with options to proceed or abort.


3. Adjusting Stage Conditions for AWS S3

If you’d like the AWS S3 upload to run on both PRs and main, update the when clause:

stage('Upload - AWS S3') {
    when {
        anyOf {
            branch 'PR*'
            branch 'main'
        }
    }
    steps {
        withAWS(credentials: 'aws-s3-ec2-lambda-creds', region: 'us-east-2') {
            sh '''
                ls -ltr
                mkdir reports-$BUILD_ID
                cp -rf coverage/ reports-$BUILD_ID/
                cp dependency* test-results.xml trivy* zap* reports-$BUILD_ID/
                ls -ltr reports-$BUILD_ID/
            '''
            s3Upload(file: "reports-$BUILD_ID",
                     bucket: "solar-system-jenkins-reports-bucket",
                     path: "jenkins-$BUILD_ID/")
        }
    }
}

Use the Declarative Directive Generator to craft complex allOf/anyOf logic:

The image shows a Jenkins interface with a "Declarative Directive Generator" tool open, allowing users to generate pipeline code for a declarative pipeline directive. The interface includes options for input, message, and other settings.


4. Verifying Submitter Restrictions

Our security uses a mock realm with matrix-based authorization. The admin group has full rights; developers are read-only:

The image shows a Jenkins security configuration screen with a matrix-based security setup, displaying permissions for different user groups such as admin, developer, manager, and QA. Various permissions are checked for each user group across categories like Overall, Credentials, Agent, Job, Run, View, SCM, and Metrics.

When a non-admin (for example, EMA) tries to approve, they’ll be blocked:

The image shows a Jenkins pipeline interface with various stages of deployment, including a prompt asking if the application should be deployed to production.

Warning

Ensure your Jenkins authorization matrix prevents unauthorized users from clicking Proceed.


That’s it for adding an approval gate! Next, we’ll cover deploying your application to AWS Lambda and running automated function tests.

Watch Video

Watch video content

Previous
Demo Publish Reports to AWS S3