Managing CI/CD pipelines efficiently is essential for scalable and maintainable development workflows. GitLab’s new CI/CD components feature makes it easier to reuse pipeline logic across projects. But one common challenge developers face is:
“How can I allow projects using a component to inject or add their own custom script commands?”
In this blog, we’ll show you exactly how to support additional script commands in a reusable GitLab component using the inputs
feature. This lets teams customize behavior without modifying the shared component itself.
What Are GitLab Components?
GitLab CI/CD components are reusable chunks of pipeline configuration stored in a separate project. Projects can include and use these components via the include:
keyword, similar to templates, but with better structure and inputs.
For example, a component might define how to build a Docker image, and other projects can use it with custom settings.
But what if one project wants to run extra commands before or after the main steps in the component?
The Problem
Let’s say you have a GitLab component that defines a job like this:
my-component-job:
script:
- echo "Starting build"
- echo "Doing main work"
- echo "Finishing up"
You want to let other projects add extra script commands, like this:
inputs:
extra_script:
- echo "Custom step 1"
- echo "Custom step 2"
But YAML doesn’t allow dynamic merging of arrays like script:
. So how do you do this?
The Solution: Use Inputs and a Wrapper Script
We can solve this by:
- Defining an input array for extra commands
- Using a shell loop inside the
script:
to run them
Here’s how to do it in your component project.
Step-by-Step: Create the Component
1. .gitlab-ci-component.yml
This file tells GitLab what inputs your component supports.
spec:
inputs:
extra_script:
type: array
default: []
Save this at the root of your component project as .gitlab-ci-component.yml
.
2. Define the Component Job
Next, define your component job (e.g., build.yml
) like this:
custom:build:
stage: build
script:
- echo "=== Predefined step ==="
- for cmd in "${!INPUT_EXTRA_SCRIPT[@]}"; do
echo "Running: ${INPUT_EXTRA_SCRIPT[$cmd]}";
eval "${INPUT_EXTRA_SCRIPT[$cmd]}";
done
- echo "=== Done ==="
Note: GitLab will inject INPUT_EXTRA_SCRIPT
as an environment variable array when the component is used.
Step-by-Step: Use the Component
In the project that wants to use this component, write your .gitlab-ci.yml
like this:
include:
- component: gitlab.example.com/group/components/build.yml
custom:build:
inputs:
extra_script:
- echo "Custom logic A"
- echo "Custom logic B"
Now, when your pipeline runs, it will execute:
echo "=== Predefined step ==="
echo "Custom logic A"
echo "Custom logic B"
echo "=== Done ==="
Boom! You just added dynamic script injection into a shared GitLab component — cleanly and safely.
Why This Works
GitLab CI inputs allow component users to pass parameters like strings, arrays, and booleans. While you can’t directly splice an array into the script:
section (YAML limitation), you can use shell loops to simulate this behavior inside the script
itself.
This approach:
- Keeps the component reusable
- Avoids hardcoding custom logic
- Empowers each project to customize behavior safely
Bonus Tips
- You can define additional inputs like
before_script
,env_vars
, etc., and handle them similarly. - Always sanitize inputs if you’re using
eval
for security. - Don’t try to inject array data directly into
script:
— GitLab doesn’t support that. - For longer logic, allow users to provide paths to custom scripts.
References
This article is based on CI/CD best practices and guidance shared in:
- askfullstack — a growing hub for full-stack DevOps solutions
- wwebhub — providing practical guides for cloud-native engineering
Conclusion
With GitLab CI/CD components and input arrays, you can build powerful, reusable pipelines that are still flexible for specific use cases. This pattern — using inputs
and looping in script:
— is a safe and scalable way to add custom commands to shared jobs.
Give it a try in your next GitLab pipeline and take your CI game to the next level!