Helm
Deploy a Helm chart from a GitHub Actions workflow that runs on the
deployment events Deliverybot creates. The workflow installs Helm with
azure/setup-helm, runs
helm upgrade --install and reports the result back to GitHub with
deliverybot/deployment-status.
Setup
- Add a
KUBECONFIGrepository secret holding a kubeconfig for your cluster. Use a service account that can only manage the namespaces you deploy to. - Describe the release in each target’s
payloadin.github/deploy.yml. The workflow reads the payload, so one workflow serves every target:
# .github/deploy.yml
staging:
auto_deploy_on: refs/heads/master
required_contexts: ["build"]
environment: staging
payload:
release: myapp-staging
namespace: myapp-staging
values_file: deploy/values-staging.yaml
production:
production_environment: true
required_contexts: ["build"]
environment: production
payload:
release: myapp
namespace: myapp-production
values_file: deploy/values-production.yaml
- Add the workflow:
# .github/workflows/deploy.yml
name: Deploy
on: [deployment]
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
contents: read
deployments: write
concurrency:
group: deploy-${{ github.event.deployment.environment }}
env:
RELEASE: ${{ github.event.deployment.payload.release }}
NAMESPACE: ${{ github.event.deployment.payload.namespace }}
VALUES_FILE: ${{ github.event.deployment.payload.values_file }}
SHA: ${{ github.event.deployment.sha }}
steps:
- uses: actions/checkout@v7
with:
ref: ${{ github.event.deployment.sha }}
- uses: deliverybot/deployment-status@v2
with:
state: in_progress
- uses: azure/setup-helm@v5
- name: Deploy
env:
KUBECONFIG_DATA: ${{ secrets.KUBECONFIG }}
run: |
export KUBECONFIG="$RUNNER_TEMP/kubeconfig"
printf '%s' "$KUBECONFIG_DATA" > "$KUBECONFIG"
helm upgrade "$RELEASE" ./chart \
--install --rollback-on-failure \
--namespace "$NAMESPACE" --create-namespace \
--values "$VALUES_FILE" \
--set image.tag="$SHA"
- if: success()
uses: deliverybot/deployment-status@v2
with:
state: success
- if: failure()
uses: deliverybot/deployment-status@v2
with:
state: failure
--rollback-on-failure waits for the release to become ready and rolls it
back if it doesn’t, so a failed deployment leaves the previous version running. Replace ./chart with the path
to your chart, or with a chart from a repository.
Pull request environments
A target with a variable in its payload gives
every pull request its own release. Deploy it with /deploy review in the pull
request, or set auto_deploy_on: pr to deploy on every push:
# .github/deploy.yml
review:
transient_environment: true
environment: pr${{ pr }}
payload:
release: myapp-pr${{ pr }}
namespace: myapp-review
values_file: deploy/values-review.yaml
Remove the release when the pull request closes:
# .github/workflows/pr-cleanup.yml
name: PR cleanup
on:
pull_request:
types: [closed]
jobs:
cleanup:
runs-on: ubuntu-latest
steps:
- uses: azure/setup-helm@v5
- env:
KUBECONFIG_DATA: ${{ secrets.KUBECONFIG }}
RELEASE: myapp-pr${{ github.event.pull_request.number }}
run: |
export KUBECONFIG="$RUNNER_TEMP/kubeconfig"
printf '%s' "$KUBECONFIG_DATA" > "$KUBECONFIG"
helm uninstall "$RELEASE" --namespace myapp-review --ignore-not-found
Canary deployments
A canary is a second, smaller release of the new version next to the stable one. Give it its own target that deploys to the same environment with a different release and values, and let your chart route a share of the traffic to it:
# .github/deploy.yml
canary:
production_environment: true
required_contexts: ["build"]
environment: production
description: Canary
payload:
release: myapp-canary
namespace: myapp-production
values_file: deploy/values-canary.yaml