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*-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.
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
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.