How to Add Additional Script Commands in GitLab Components


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:

  1. Defining an input array for extra commands
  2. 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!