CI Pipeline
This page covers the typical layout for incorporating Tazuna into a CI / CD pipeline in a repository that holds tazuna.yaml. Tazuna can be used both to apply from your local machine and to apply from CI. This page primarily focuses on the latter.
Typical Setup
By role, the pipeline divides into the following three stages.
| Stage | Purpose | Commands to run | Cluster access |
|---|---|---|---|
| Verify | Guarantee that tazuna.yaml is not broken | tazuna check, tazuna build, tazuna plan | plan only (read-only) |
| Apply | Reflect the contents of main into the cluster | tazuna apply (with --sync / --prune as needed) | Required |
| Remove | Delete Tazuna-managed resources | tazuna destroy | Required |
“Verify” is fine to run on every PR. “Apply” is usually triggered by pushes to main. We recommend not making “Remove” a permanent fixture in CI (see Operating tazuna destroy).
Verification Stage
If you put tazuna.yaml on CI, the minimum bar to clear is to run tazuna check. It runs without touching the cluster, so the PR cost is nearly zero.
# GitHub Actions example (essentials only)
- name: tazuna check
run: tazuna check -f tazuna.yaml
- name: tazuna build (preview)
run: tazuna build -f tazuna.yaml > rendered.yaml
Keeping build output as an artifact on PRs lets reviewers verify “what will ultimately be applied” from the rendered result. If you use type: oras, you can also consider running with --offline to leverage a pre-warmed cache (see tazuna build).
If you can grant CI read access to the cluster, running tazuna plan on PRs lets you paste “which fields actually change” into a PR comment as a unified diff.
- name: tazuna plan
if: github.event_name == 'pull_request'
run: tazuna plan -f tazuna.yaml > plan.txt
- name: post plan to PR
if: github.event_name == 'pull_request'
run: |
gh pr comment "$PR_NUMBER" --body-file <(printf '```\n%s\n```\n' "$(cat plan.txt)")
Because tazuna plan is read-only, its advantage is that it fits easily within a PR’s permission boundary.
Apply Stage
The basic setup runs tazuna apply triggered by pushes to main.
on:
push:
branches: ["main"]
jobs:
apply:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write # if you connect to the cluster via OIDC
steps:
- uses: actions/checkout@v6
- name: install tazuna
run: |
curl -L https://github.com/pepabo/tazuna/releases/download/v0.1.0/tazuna_Linux_x86_64.tar.gz \
| tar xz -C /usr/local/bin tazuna
- name: configure kubeconfig
run: |
# Set current-context using aws-iam-authenticator / gke-gcloud-auth-plugin
# / kubeconfig secret etc., depending on cluster-side specifics
aws eks update-kubeconfig --name prod-tokyo --region ap-northeast-1
- name: tazuna apply
run: tazuna apply -f tazuna.yaml
Points to note:
- The current-context for
tazuna applyis exactly the kubeconfig current-context. In CI, always explicitly include a step that sets the current-context. - Including
spec.context_matchesintazuna.yamlmakes the system fail fast if it wouldapplyagainst a kubeconfig pointing to the wrong cluster. It is a useful safety net in CI as well. - Tazuna exits non-zero on failure, so no special error handling is needed on the CI side (see CLI - Exit Codes).
apply operating modes
tazuna apply has three operating modes (see tazuna apply for details).
| Mode | When what runs | Drift detection |
|---|---|---|
tazuna apply | Runs every Manifest in tazuna.yaml through its Manager and saves state | No (always overwrites) |
tazuna apply --sync | Compares the Build result with State, and only reflects the differences (added / modified / always-sync) | Yes |
tazuna apply --sync --prune | In addition to the above, deletes resources present in State but absent from the Build result | Yes |
Rough guidance:
- Bootstrap phase / small number of Manifests:
tazuna applyis simple and predictable. - Manifest count grows and a single
applybecomes heavy: narrow to the diff only with--sync. - You want automatic
removeddeletion:--sync --prune. Weigh it against the risk of accidental deletion.
Whether to Use --atomic
With tazuna apply --sync --atomic, it exits without updating State if any resource errors out. The apply itself still progresses partway, so CI cannot treat the run as the binary “either everything went in or nothing did,” but State-level consistency is preserved. See tazuna apply for details.
Removal Stage
We do not recommend running tazuna destroy from CI.
- Setting the environment variable
TAZUNA_DESTROY_EXECUTABLE=truepermanently in CI leaves only the prompt as a guard against accidental firing (and since CI cannot respond to prompts, combined with--forceit would delete unconditionally). - If you absolutely need to delete from CI, create a dedicated manually-triggered workflow and pass the env var only for that job.
See Operating tazuna destroy for details.
Phased Apply With Tags
tazuna apply --tags lets you narrow down which Manifests CI applies. For example, this fits patterns like “run the infrastructure layer and the application layer in separate CI passes” or “run experimental add-ons in a separate job.”
tazuna apply --tags infra # Install the foundation first
tazuna apply --tags application # Then the application side
Tag design happens on the tazuna.yaml side via manifests[].tags.
Wiring Up Monitoring and Notifications
The recommended setup is to run periodic tazuna state diff on a separate path from CI. See Drift Monitoring for details. If you only watch the success/failure of CI apply, you will miss cases where drift occurs without any tazuna.yaml update.
Related
- Spec:
tazuna apply/tazuna build/tazuna check/tazuna plan - Incident prevention: Operating
tazuna destroy - Drift detection: Drift Monitoring
- tracing: Observability