Appendix

Appendix: Build and Deploy with GitLab CI

Turn the verified commands into a reviewable pipeline that builds two images and deploys pinned chart version 4.8.0.

Just started Saved in this browser.

Continuous integration should automate commands you already understand. The persistent stage includes an example pipeline at persistent-app/.gitlab-ci.yml; it builds frontend and backend images with Buildah, then deploys their immutable commit tags with Helm.

Step by step

Download this chapter's files

Use your browser to download either ivia-chapter-12.tar.gz or ivia-chapter-12.zip. The archive is self-contained; you do not need this tutorial repository.

Open a terminal after the browser download:

cd ~/Downloads
tar -xzf ivia-chapter-12.tar.gz
cd ivia-chapter-12

All remaining relative paths in this chapter start from that extracted directory.

Do this

The challenge

Challenge: validate the example pipeline configuration and map every required CI/CD variable to its purpose without placing a secret in Git.

Prepare

Prerequisites

  • A GitLab project with Container Registry enabled.
  • A runner capable of Buildah jobs and a deploy runner that can reach the Kubernetes API.
  • A target namespace and authorized kubeconfig.
  • The persistent stage source and chart values.
  • Maintainer access to configure protected/masked CI/CD variables.
Outcome

Learning goals

  • Explain pipeline stages and artifacts
  • Use commit SHA image tags
  • Pass registry credentials safely
  • Pin chart version 4.8.0
  • Understand deployment serialization and rollback behavior
Step by step

Inspect and validate

sed -n '1,260p' persistent-app/.gitlab-ci.yml

If the GitLab CLI is installed and authenticated, validate through the project API:

glab ci lint persistent-app/.gitlab-ci.yml

Otherwise copy the file contents into Build > Pipeline editor > Validate in GitLab. To run this package unchanged, push the extracted directory as the project root and set Settings > CI/CD > General pipelines > CI/CD configuration file to persistent-app/.gitlab-ci.yml. Its paths are relative to that self-contained project root.

Step by step

Configure variables in GitLab

In Settings > CI/CD > Variables, add:

  • KUBECONFIG_B64: base64-encoded least-privilege kubeconfig; masked and protected.
  • K8S_NAMESPACE: target namespace; protected if production-like.
  • FRONTEND_HOST: for example simple-app.example.org.
  • BACKEND_HOST: for example api.simple-app.example.org.

GitLab supplies CI_REGISTRY, CI_REGISTRY_IMAGE, CI_REGISTRY_USER, CI_REGISTRY_PASSWORD, and CI_COMMIT_SHA. Do not copy their values into YAML.

Create the kubeconfig value:

base64 -w 0 path/to/limited-kubeconfig

Treat the output as a secret. Paste it directly into GitLab, not a shell history shared with others.

Step by step

Understand the pipeline

The test job compiles Python modules and builds the React bundle. Two Buildah jobs log in to the GitLab registry, build independent images, and push tags equal to CI_COMMIT_SHA. The deploy job decodes kubeconfig, logs Helm into the registry, and executes:

helm upgrade --install simple-app \
  oci://harbor.ivia.ch/ivia-generic-helm-chart/ivia-generic-helm-chart \
  --version 4.8.0 \
  --namespace "$K8S_NAMESPACE" --create-namespace \
  --atomic --timeout 10m \
  -f persistent-app/values.yaml \
  --set components.frontend.image.repository="$CI_REGISTRY_IMAGE/frontend" \
  --set components.frontend.image.tag="$CI_COMMIT_SHA" \
  --set components.backend.image.repository="$CI_REGISTRY_IMAGE/backend" \
  --set components.backend.image.tag="$CI_COMMIT_SHA" \
  --set components.frontend.ingress.url="$FRONTEND_HOST" \
  --set components.backend.ingress.url="$BACKEND_HOST"

Immutable commit tags tie a deployment to exact source. --atomic rolls back failed upgrades and returns failure to GitLab. A resource_group prevents two deploy jobs from changing the same release concurrently.

Verify

Expected validation

GitLab's linter reports valid syntax. On a configured runner, test and both build jobs pass before deploy starts; the registry contains /frontend:$CI_COMMIT_SHA and /backend:$CI_COMMIT_SHA; helm status simple-app -n "$K8S_NAMESPACE" reports deployed.

Troubleshoot

Troubleshooting and common pitfalls

  • Pipeline valid but job cannot run: runner tags must match available runners; tags are organization-specific.
  • Buildah permission or mount errors: use a runner configured for rootless or privileged Buildah according to your platform policy.
  • Registry unauthorized: use GitLab-provided credentials and --password-stdin; verify registry access from the runner.
  • Kubeconfig decode fails: remove wrapped lines before storing the base64 value and keep file permissions at 600.
  • Deploy cannot pull images: create an image pull secret or attach the appropriate regcred through chart values.
  • Concurrent deployments race: retain one resource_group for the environment.
  • Using latest: commit SHA tags are auditable and avoid node cache ambiguity.
  • Secrets echoed in logs: never enable shell tracing around login or kubeconfig commands.

A good pipeline is simply your tested workflow made repeatable. You now have a clear path from commit to a controlled Helm release.

Reference

Official references

Just started Saved in this browser.