CI/CD Integration¶
Integrate NthLayer into your deployment pipeline for automated reliability validation.
The Reliability Pipeline¶
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ Generate │ → │ Validate │ → │ Protect │ → │ Deploy │
└──────────┘ └──────────┘ └──────────┘ └──────────┘
apply validate-spec check-deploy kubectl
verify argocd
--lint
GitHub Actions¶
Complete Workflow¶
name: Deploy with Reliability Gates
on:
push:
branches: [main]
paths:
- 'services/**'
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install NthLayer
run: pip install nthlayer
- name: Validate Service Specs
run: nthlayer validate-spec services/
- name: Generate Configs
run: nthlayer apply services/*.yaml --lint
- name: Upload Artifacts
uses: actions/upload-artifact@v4
with:
name: generated-configs
path: generated/
verify:
needs: validate
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install NthLayer
run: pip install nthlayer
- name: Verify Metrics Exist
run: |
nthlayer verify services/*.yaml \
--prometheus-url ${{ secrets.STAGING_PROMETHEUS_URL }}
env:
PROMETHEUS_USERNAME: ${{ secrets.PROMETHEUS_USERNAME }}
PROMETHEUS_PASSWORD: ${{ secrets.PROMETHEUS_PASSWORD }}
gate:
needs: verify
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install NthLayer
run: pip install nthlayer
- name: Check Deployment Gate
id: gate
run: |
nthlayer check-deploy services/*.yaml \
--prometheus-url ${{ secrets.PROD_PROMETHEUS_URL }}
echo "exit_code=$?" >> $GITHUB_OUTPUT
continue-on-error: true
- name: Block on Budget Exhausted
if: steps.gate.outputs.exit_code == '2'
run: |
echo "::error::Deployment blocked - error budget exhausted"
exit 1
deploy:
needs: gate
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Download Configs
uses: actions/download-artifact@v4
with:
name: generated-configs
path: generated/
- name: Deploy to Kubernetes
run: kubectl apply -f generated/
Reusable Action (Coming Soon)¶
- uses: nthlayer/action@v1
with:
command: check-deploy
service-file: services/api.yaml
prometheus-url: ${{ secrets.PROMETHEUS_URL }}
GitLab CI¶
stages:
- validate
- verify
- gate
- deploy
variables:
PIP_CACHE_DIR: "$CI_PROJECT_DIR/.pip-cache"
.nthlayer:
image: python:3.11
before_script:
- pip install nthlayer
validate:
extends: .nthlayer
stage: validate
script:
- nthlayer validate-spec services/
- nthlayer apply services/*.yaml --lint
artifacts:
paths:
- generated/
verify:
extends: .nthlayer
stage: verify
script:
- nthlayer verify services/*.yaml --prometheus-url $STAGING_PROMETHEUS_URL
gate:
extends: .nthlayer
stage: gate
script:
- |
nthlayer check-deploy services/*.yaml \
--prometheus-url $PROD_PROMETHEUS_URL
EXIT_CODE=$?
if [ $EXIT_CODE -eq 2 ]; then
echo "Deployment blocked - error budget exhausted"
exit 1
fi
only:
- main
deploy:
stage: deploy
script:
- kubectl apply -f generated/
only:
- main
when: on_success
ArgoCD¶
PreSync Hook¶
Block ArgoCD sync when error budget is exhausted:
apiVersion: batch/v1
kind: Job
metadata:
name: nthlayer-gate
annotations:
argocd.argoproj.io/hook: PreSync
argocd.argoproj.io/hook-delete-policy: HookSucceeded
spec:
template:
spec:
containers:
- name: check-deploy
image: ghcr.io/nthlayer/nthlayer:latest
command:
- nthlayer
- check-deploy
- /config/service.yaml
- --prometheus-url
- $(PROMETHEUS_URL)
envFrom:
- secretRef:
name: prometheus-credentials
volumeMounts:
- name: service-config
mountPath: /config
volumes:
- name: service-config
configMap:
name: service-yaml
restartPolicy: Never
backoffLimit: 0
Application Manifest¶
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: payment-api
spec:
source:
repoURL: https://github.com/org/repo
path: services/payment-api
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
When the PreSync hook fails (exit code 2), ArgoCD blocks the sync.
Tekton¶
Task Definition¶
apiVersion: tekton.dev/v1
kind: Task
metadata:
name: nthlayer-check-deploy
spec:
params:
- name: service-file
type: string
- name: prometheus-url
type: string
steps:
- name: check
image: ghcr.io/nthlayer/nthlayer:latest
script: |
nthlayer check-deploy $(params.service-file) \
--prometheus-url $(params.prometheus-url)
EXIT_CODE=$?
if [ $EXIT_CODE -eq 2 ]; then
echo "Deployment blocked"
exit 1
fi
Pipeline¶
apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
name: deploy-with-gates
spec:
params:
- name: service-file
type: string
- name: prometheus-url
type: string
tasks:
- name: validate
taskRef:
name: nthlayer-validate
- name: generate
taskRef:
name: nthlayer-apply
runAfter: [validate]
- name: verify
taskRef:
name: nthlayer-verify
runAfter: [generate]
- name: gate
taskRef:
name: nthlayer-check-deploy
runAfter: [verify]
params:
- name: service-file
value: $(params.service-file)
- name: prometheus-url
value: $(params.prometheus-url)
- name: deploy
taskRef:
name: kubectl-apply
runAfter: [gate]
Jenkins¶
pipeline {
agent any
environment {
PROMETHEUS_URL = credentials('prometheus-url')
}
stages {
stage('Validate') {
steps {
sh 'pip install nthlayer'
sh 'nthlayer validate-spec services/'
sh 'nthlayer apply services/*.yaml --lint'
}
}
stage('Verify') {
steps {
sh """
nthlayer verify services/*.yaml \
--prometheus-url ${PROMETHEUS_URL}
"""
}
}
stage('Gate') {
steps {
script {
def exitCode = sh(
script: """
nthlayer check-deploy services/*.yaml \
--prometheus-url ${PROMETHEUS_URL}
""",
returnStatus: true
)
if (exitCode == 2) {
error('Deployment blocked - error budget exhausted')
}
}
}
}
stage('Deploy') {
steps {
sh 'kubectl apply -f generated/'
}
}
}
}
Environment Variables¶
All CI/CD integrations support these environment variables:
| Variable | Description |
|---|---|
PROMETHEUS_URL | Prometheus server URL |
PROMETHEUS_USERNAME | Basic auth username |
PROMETHEUS_PASSWORD | Basic auth password |
GRAFANA_URL | Grafana server URL |
GRAFANA_API_KEY | Grafana API key |
Best Practices¶
1. Validate Early, Protect Late¶
commit → validate-spec → apply --lint → verify → check-deploy → deploy
↑ ↑ ↑
No Prometheus Staging Prom Prod Prom
2. Use Staging for Verification¶
Verify metrics exist in staging before checking production gates:
- name: Verify in Staging
run: nthlayer verify services/*.yaml --prometheus-url $STAGING_URL
- name: Gate in Production
run: nthlayer check-deploy services/*.yaml --prometheus-url $PROD_URL
3. Cache NthLayer Installation¶
4. Fail Fast¶
Put validation early in your pipeline to catch issues quickly.