Skip to content

Limitations

What these components do not do. Some of it is a deliberate design boundary, some is a consequence of how GitLab CI/CD components work, and some is simply not built yet. Each entry says which.

If you are looking for what a component does, start at the Reference index; for when it runs, the trigger matrix.

Can I use these components on GitHub Actions, or any CI that is not GitLab?

No, and there is no path to it. These are GitLab CI/CD components: the spec:inputs header, $[[ inputs.… ]] interpolation, rules:changes, id_tokens:, environment:on_stop and the component: include syntax are all GitLab features with no cross-platform equivalent. There is no translation layer and none is planned.

The tools the components run — OpenTofu, golangci-lint, cargo-nextest, goreleaser, Renovate — are all portable. The wiring is not.

Can tofu-plan / tofu-apply deploy to Azure, GCP, or a non-AWS backend?

Partly. The components carry one built-in identity, AWS via GitLab OIDC and AssumeRoleWithWebIdentity, and no other cloud's equivalent. Since spec 0093 that identity is optional: leave role_arn empty (or null in a deploy-generate catalog) and the job exports nothing, so a stack whose providers read their own environment variables runs unchanged. That covers Cloudflare, which has no workload identity federation at all, and any provider you are content to authenticate with a CI variable. What the components still do not do is exchange the GitLab OIDC token with another cloud's STS; a stack that needs that needs a new identity block, and a spec.

The three Tofu gates were always cloud-agnostic, because they never authenticate to a cloud: tofu-lint (fmt, tflint, terraform-docs), tofu-security (trivy config, checkov, gitleaks) and tofu-validate (init -backend=false && validate) work against any provider's HCL.

Can I point a component at a different container image?

Only some of them. Two input shapes are in use and they are not interchangeable:

  • image — a full image reference, fully overridable. go-lint, go-test, goreleaser, rust-lint, rust-test, rust-docs, release-plz, svelte-build, svelte-lint, svelte-test, hugo-pages. The four *-security components are the same idea split per scanner: trivy_image, gitleaks_image, semgrep_image and so on.
  • image_version — a tag only; the registry path is baked into the template. The eight tofu-* components, zensical-pages and renovate-merge are pinned to registry.gitlab.com/phpboyscout/images/infra-tools; renovate-self and renovate-group to renovate/renovate; releaser-pleaser to ghcr.io/apricote/releaser-pleaser.

For the second group you can choose the version of the image, not the image. Running tofu-plan on your own base image is not supported — mirror or rebuild infra-tools instead.

Can I make a component run somewhere its rules do not already allow?

Sometimes. A component with an if input exposes its trigger; the tofu-* components, goreleaser, zensical-pages and hugo-pages do not, and their triggers cannot be overridden through inputs at all. The trigger matrix lists which is which and why.

Two hard limits apply even where the trigger is overridable:

  • Nothing you set can make a component run on a scheduled pipeline except the three Renovate components and hugo-pages. The when: never schedule guard is the first rule and is not interpolated from any input.
  • A wider if does not create a pipeline. If your workflow: rules never create a pipeline for that ref, no component rule can run there.

Can I add a path to a component's changes filter without repeating the default?

No. There is no extend syntax — GitLab component inputs replace, they do not merge. Overriding changes discards the component's default entirely, so copy the documented default from the component's reference page and append your path to it.

This is the single most common way to create a false negative: an override that drops .gitlab-ci.yml, or a project's own tool config, produces a gate that stops running exactly when its configuration changes. The recipe is Add change-detection to a gate.

Can I turn change-detection on for the security components?

No. go-security, rust-security, svelte-security, tofu-security and skill-security have no changes input, and adding one is explicitly out of scope. A security scanner that runs only when "relevant" files changed misses the case that matters most — a vulnerability disclosed against a dependency you did not touch. The reasoning is Security, always-on.

They still obey the schedule guard. "Always-on" means every merge request, not every pipeline.

Can I fail a build on a macOS or Windows result?

No. rust-test's test-macos and test-windows jobs are allow_failure: true and there is no input to change that — a transient SaaS-runner quota or outage must not block a Linux-green merge.

They also need more than enable_cross_os: true. The jobs stay dormant until $RUN_CROSS_OS_TESTS is "true" as well, and they request the saas-macos-medium-m1 / saas-windows-medium-amd64 runner tags. Without eligible runners they would sit stuck-pending and block the test stage on every pipeline, which is why the second gate exists. Setting the input alone and seeing nothing happen is expected behaviour, not a bug.

Can I run the integration test jobs on a shared, unprivileged runner?

No. go-test's enable_integration job runs a docker:dind service and wires DOCKER_HOST, FF_NETWORK_PER_BUILD and TESTCONTAINERS_RYUK_DISABLED for testcontainers-go. That needs a runner in privileged mode. On a runner without it the job fails to reach the Docker daemon; there is no non-dind fallback.

Can I deploy a site somewhere other than GitLab Pages?

No. zensical-pages and hugo-pages produce a pages job with a public/ artifact — that is the GitLab Pages contract, and nothing else consumes it. Publishing to S3, Netlify or Cloudflare is out of scope for both.

Can tofu-stop stop a production environment?

No, and this is fail-closed rather than discouraged. tofu-stop's deployment_tier input declares options: of development and staging only, so a production or other value is rejected by GitLab at pipeline creation — it cannot be passed at all. tofu-deploy-generate enforces the same guard on its catalog: production and other targets can never be marked stoppable, and must additionally be manual and carry confirmation text.

A stop lane strips an environment to baseline via an overlay apply. There is deliberately no way to point that at production.

Can I pin one component to an older version than the rest?

Technically yes — each include: carries its own @vX.Y.Z — but the components are released as one monorepo under a single tag stream, so a version exists for every component whether or not that component changed in it. A bump to v0.34.4 on a component untouched since v0.20.0 is normal and means nothing changed for you.

Mixing versions across components in one pipeline is not tested. The self-tests run every component from the same commit. Where two components are a pair — tofu-plan with tofu-apply, svelte-build with goreleaser — pin them to the same tag.

Will a minor version bump break my pipeline?

It can, until 1.0. Pre-1.0 a minor bump may change input shape: rename an input, change a default, add a required one. That is the documented versioning policy, not an accident. Pin to an exact @vX.Y.Z tag — never @~latest and never a branch — and read the Renovate MR before merging it.

Is there a component for Python, PHP, Java, or building container images?

No. The tracks that exist are Terraform/OpenTofu, Go, Rust, Svelte, static sites, cross-track quality, release and dependency automation, and AI skill / instruction-file scanning — 32 components, listed in full on the Reference index. Nothing else is built, and nothing else is in progress.

Container images are built in phpboyscout/images, which is a separate project with its own pipeline, not a component here.

Do the components declare stages, variables, or defaults for me?

No, by authoring rule. A template declares no top-level stages:, default: or variables: — everything is per-job. Every component takes a stage input, and you must declare that stage in your own stages: list. A stage that is not declared is a pipeline configuration error.

One related trap: a component's default stage is never .pre or .post. GitLab does not create a pipeline whose jobs are all in a built-in stage, so a component defaulting into one would silently produce no pipeline where it is the only job — as tofu-module-publish is on a release tag. A repository check (scripts/lint-stage-defaults.sh) enforces this on every template change.

Can I include two components that define the same job?

Only go-security with svelte-security, today. GitLab merges same-named jobs across includes and the later include wins, with no warning, so two components sharing a job name leave you one job. svelte-security prefixes its svelte-osv-scanner and svelte-gitleaks for exactly that pairing; set its gitleaks: false input there so gitleaks runs once.

Two collisions remain between security components no project combines yet: gitleaks in go-, rust-, skill- and tofu-security, and trivy in go- and rust-security. Including two of those together silently drops one job. Prefixing them is cicd#61. pages is defined by both hugo-pages and zensical-pages and stays that way, because a site is built with one or the other. A repository check (scripts/lint-job-names.sh) fails on any new collision.

Do the components manage my credentials?

No. Every component that authenticates takes a string input defaulting to $CI_JOB_TOKEN and never names a consumer variable of its own. Where the job token is not enough — the jobs-artifacts API on GitLab Free, a cross-project state backend, a package-registry write — you create the token, choose its scope, name the CI variable whatever you like, mark it Masked, and pass it in. The component neither creates, rotates, validates nor stores anything. See the token-input convention.

What about the things this documentation cannot tell you

Some questions have no answer here and never will:

  • Who runs these components, and how their pipelines behave. Consumer projects outside the phpboyscout group are private to their owners. Adoption, failure rates and production usage are not published and are not something this documentation can speak to.
  • What a specific consumer's pipeline did. The components are stateless templates; the run lives in that project's pipeline history.

See also