Skip to main content

Standards and conventions

CI Tools is an opinionated catalog. The conventions on this page are the defaults for projects that use it and for contributors who extend it. Follow a different convention only when a project requirement makes the exception explicit.

Component inclusion and versions

  • Start every component pipeline with the common component. It supplies the shared CI Tools version and bootloader used by the other components.
  • Use the same CI Tools reference for every component in one pipeline. Mixing component versions can combine incompatible inputs and Bash functions.
  • Use stable for the maintained release channel, or pin all components to one semantic version and let Renovate update them together. Use main only when testing unreleased catalog changes.
  • Prefer component inputs over copied job definitions. Override a default only when the project needs different behavior.

See the release components and Renovate components.

Repository and pipeline structure

  • Keep the pipeline entry point at .gitlab-ci.yml and reusable catalog components below templates/<component-name>/.
  • Use lowercase kebab-case for component names and job-name segments.
  • Keep a component's contract in template.yml, its component-specific tests in test.yml, and user guidance in docs.md.
  • Put application container build contexts in a dedicated directory when a repository builds more than one image. Name the build file Containerfile.
  • Put a Helm application chart in chart/ unless the component input selects a different path.
  • Keep pipeline stages coarse-grained. Use component inputs such as stage, needs, rules, and runner tags to integrate jobs into an existing pipeline.

Source control and releases

  • Protect the default branch and release tags. Deliver changes through merge requests with a successful exact-head pipeline and resolved discussions.
  • Use Conventional Commit titles. feat produces a minor release, fix produces a patch release, and a breaking change produces a major release. Documentation, test, build, CI, and maintenance changes do not release by default.
  • Prefer short-lived feat/* and fix/* branches. Choose either the Git flow or trunk-based workflow for a project and apply it consistently.
  • Treat semantic version tags as immutable release identifiers. Use the stable branch as the moving maintained channel for component catalogs.

See the workflow components and release components.

Containers, Helm, and deployment

  • Build OCI images from trusted, version-pinned base images. Publish standard OCI labels so every image can be traced to its source project, commit, and release.
  • Use branch and commit tags for development images. Reserve semantic version and latest tags for releases from the default branch; an older retried pipeline must not replace a newer latest image.
  • Use semantic versions for Helm chart releases. Keep development chart versions distinguishable from stable releases and keep appVersion aligned with the application image.
  • Deliver Kubernetes changes through Helm and GitOps. Use review environments for merge-request validation and make stop jobs idempotent.

See the OCI components, Kubernetes components, and review components.

Quality and security

  • Run format and lint checks for the file types a project owns. Keep the same checks available locally through pre-commit when practical.
  • Test component behavior in templates/<component-name>/test.yml. Add a test to the example project only when the behavior cannot be proven inside the component pipeline.
  • Scan source trees and images for vulnerabilities and misconfiguration. Do not hide findings with allow_failure or skip rules unless a check is explicitly informational and the exception is documented.
  • Pin external tools and base images, keep dependencies current with Renovate, and never print credentials in job output.

See the quality components and security components.

Variables, credentials, and runners

  • Use GitLab predefined variables before introducing project-specific names.
  • Store credentials as masked variables and mark them protected when only protected branches and tags may use them. Prefer group service accounts over personal access tokens for shared automation.
  • Use file variables for structured credentials such as KUBECONFIG and SSH keys. Do not commit generated secrets or decoded credentials.
  • Keep runner tags configurable through component inputs. Use the least privileged runner and token that can perform the job.

Component authoring

  • Give every input a description, stable default where possible, and an explicit type for boolean values and arrays. A required input has no usable default.
  • Keep component YAML declarative. Put reusable business logic in the Bash library and prefix public library functions with ci_.
  • Load the Bash library through the bootloader so the library version matches the included component version.
  • Document the smallest working include example and any required variables. Add front matter tags that describe the component's purpose so users can discover related components.
  • Preserve backward compatibility within a major release. Deprecate an input or behavior before removing it.

Documentation

  • Write user-facing Markdown in docs/ and component guidance in templates/<component-name>/docs.md. Generated component pages combine that guidance with the input contract from template.yml.
  • Use descriptive headings and fenced code blocks with a language identifier. Keep links relative for repository documentation and verify that tag links resolve in the Docusaurus build.
  • Apply a small, consistent set of lowercase tags. Reuse an existing tag before creating a synonym.

See the documentation components.