Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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.

StagePurposeCommands to runCluster access
VerifyGuarantee that tazuna.yaml is not brokentazuna check, tazuna build, tazuna planplan only (read-only)
ApplyReflect the contents of main into the clustertazuna apply (with --sync / --prune as needed)Required
RemoveDelete Tazuna-managed resourcestazuna destroyRequired

“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 apply is exactly the kubeconfig current-context. In CI, always explicitly include a step that sets the current-context.
  • Including spec.context_matches in tazuna.yaml makes the system fail fast if it would apply against 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).

ModeWhen what runsDrift detection
tazuna applyRuns every Manifest in tazuna.yaml through its Manager and saves stateNo (always overwrites)
tazuna apply --syncCompares the Build result with State, and only reflects the differences (added / modified / always-sync)Yes
tazuna apply --sync --pruneIn addition to the above, deletes resources present in State but absent from the Build resultYes

Rough guidance:

  • Bootstrap phase / small number of Manifests: tazuna apply is simple and predictable.
  • Manifest count grows and a single apply becomes heavy: narrow to the diff only with --sync.
  • You want automatic removed deletion: --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=true permanently in CI leaves only the prompt as a guard against accidental firing (and since CI cannot respond to prompts, combined with --force it 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.