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?¶
No. The Tofu deployment components are AWS-only by construction. They take
role_arn, aws_region and an aud defaulting to sts.amazonaws.com,
they export AWS_ROLE_ARN / AWS_WEB_IDENTITY_TOKEN_FILE / AWS_REGION,
and they rely on the AWS SDK's web-identity credential chain to complete
the exchange. Nothing in them is cloud-agnostic, and there are no
equivalent Azure or GCP components.
The three Tofu gates are 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*-securitycomponents are the same idea split per scanner:trivy_image,gitleaks_image,semgrep_imageand so on.image_version— a tag only; the registry path is baked into the template. The eighttofu-*components,zensical-pagesandrenovate-mergeare pinned toregistry.gitlab.com/phpboyscout/images/infra-tools;renovate-selfandrenovate-grouptorenovate/renovate;releaser-pleasertoghcr.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. Thewhen: neverschedule guard is the first rule and is not interpolated from any input. - A wider
ifdoes not create a pipeline. If yourworkflow: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.
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
phpboyscoutgroup 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¶
- Which pipelines each component runs on — the trigger matrix.
- How-to: diagnose a failing job — symptom-first troubleshooting.
- Explanation: security, always-on.
- Explanation: the token-input convention.