A deployment pipeline turns a code change into a repeatable route to a running microservice. Continuous integration (CI) checks changes when they are pushed to a repository. Continuous deployment (CD) extends that workflow: after a successful build and tests, it deploys the change to a testing or production environment. If the build or tests fail, deployment stops. This makes tests a checkpoint rather than a task someone must remember to run. section 8.4 section 8.5
Build the workflow from a process you can already run manually:
- Package and publish the microservice with Docker, then deploy it to Kubernetes with kubectl. Practice the manual deployment before automating it. section 10.9
- Put the deployment commands in shell scripts and test them locally. Keep unattended deployment code simple: failures are harder to debug when it runs in the cloud. section 8.5 section 8.8.1
- Configure a GitHub Actions workflow in YAML to run checks, tests, and the scripts. For a Node.js project with its test script configured in package.json, the workflow can invoke npm test. section 8.11 section 9.9
- Pass configuration through environment variables. Use GitHub secrets for sensitive values, github.sha as an image version, and envsubst to fill parameters in deployment configuration. section 8.11
One workflow per microservice
In a repository containing multiple microservices, a gateway workflow can listen for pushes that change gateway/**. Its YAML sets the service name, directory, image version, and registry values, then calls shell scripts to build and publish the image. Only changes to that service trigger its workflow, so it can have an independent deployment schedule even while sharing a repository. section 10.10.4 section 12.2.2
Listing 10.16 Enabling a separate CD pipeline for the gateway
name: Deploy gateway #1
on:
push:
branches:
- main #2
paths:
- gateway/** #3
workflow_dispatch: #4
jobs:
deploy:
runs-on: ubuntu-latest
env:
VERSION: ${{ github.sha }} #5
CONTAINER_REGISTRY: ${{ secrets.CONTAINER_REGISTRY }}
REGISTRY_UN: ${{ secrets.REGISTRY_UN }}
REGISTRY_PW: ${{ secrets.REGISTRY_PW }}
NAME: gateway
DIRECTORY: gateway #5
steps:
- uses: actions/checkout@v3
- name: Build
run: ./scripts/cd/build-image.sh #6
- name: Publish
run: ./scripts/cd/push-image.sh #7
- uses: tale/kubectl-action@v1 #8
with:
base64-kube-config: ${{ secrets.KUBE_CONFIG }}
kubectl-version: v1.24.2
- name: Deploy
run: ./scripts/cd/deploy.sh #9
Inspect the workflow’s branch and path filters, environment values, and build and publish steps. The listing shows how a shared repository selects one microservice for deployment. section 10.10.4
A push directly from the integration branch to production is a simple starting point, but it is risky. For a guarded release, use branches to target development, test, and production environments. Merge and test changes before promoting them; a failed automated test prevents deployment. A separate pipeline for each microservice avoids rebuilding and redeploying unchanged services. section 8.9.11 section 12.2.6 section 12.2.2





























