正式なドキュメントは英語版であり、この日本語訳はAI支援翻訳により作成された参考用のものです。日本語訳の一部の内容は人間によるレビューがまだ行われていないため、翻訳のタイミングにより英語版との間に差異が生じることがあります。最新かつ正確な情報については、英語版をご参照ください。

Create a GitLab Function

  • Tier: Free, Premium, Ultimate
  • Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
  • Status: Experiment

A GitLab Function is a directory with a func.yml file that defines the function’s interface and implementation. Functions can run locally or be published to an OCI registry for reuse across jobs and projects.

For information on using functions in a CI/CD job, see GitLab Functions. For example functions, see GitLab Functions examples.

Function structure

A function is a directory that contains at a minimum a func.yml file, plus any supporting files the implementation needs:

my-function/
├── func.yml
└── my-script.sh

The func.yml file contains two YAML documents separated by ---: a spec that defines the function’s inputs and outputs, and a definition that describes what the function does.

# Document 1: spec
spec:
  inputs:
    message:
      type: string
  outputs:
    result:
      type: string
---
# Document 2: definition
exec:
  command: ["${{ func_dir }}/my-script.sh", "${{ inputs.message }}"]

Spec: Declare inputs and outputs

The spec describes the function’s interface.

Inputs

Each input requires a type. Inputs with a default value are optional. Inputs without a default value must be provided by the caller.

Input names must use alphanumeric characters and underscores, and cannot start with a number.

Inputs must be one of these types:

TypeExampleDescription
array["a","b"]A list of untyped items
booleantrueTrue or false
number56.7764-bit float
string"brown cow"Text
struct{"k1":"v1","k2":"v2"}Structured content

For example:

spec:
  inputs:
    # Required string input
    message:
      type: string

    # Optional input with a default
    count:
      type: number
      default: 1

    # Struct input for passing structured data
    config:
      type: struct
      default: {}

Outputs

Outputs define the values the function returns to subsequent steps. Each output requires a type. Outputs with a default value are optional. The default value is used when the function doesn’t write the output value.

Outputs use the same types and naming rules as inputs.

For example:

spec:
  outputs:
    # Required string output
    artifact_path:
      type: string

    # Optional output with a default
    compressed:
      type: boolean
      default: false

At runtime, the function writes output values to the path given by ${{ output_file }}. Each line must be a JSON object with name and value fields:

echo '{"name":"artifact_path","value":"/dist/app.tar.gz"}' >> "${{ output_file }}"
echo '{"name":"compressed","value":true}' >> "${{ output_file }}"

Delegate outputs

If a function has multiple steps and you want the function’s outputs to come from one specific step, use outputs: delegate in the spec and delegate: <step_name> in the definition:

spec:
  outputs: delegate
---
run:
  - name: build
    func: ./build
  - name: package
    func: ./package
delegate: package  # use the package step outputs as this function outputs

Definition: Implement the function

The second document in func.yml describes the implementation. You can implement a function in two ways.

exec

Use exec to run a single command or script. The command is passed directly to the OS without a shell, so it must be an array of strings.

spec:
  inputs:
    message:
      type: string
---
exec:
  command: ["./greet", "${{ inputs.message }}"]

The working directory defaults to CI_PROJECT_DIR. To override it, use work_dir. The work_dir keyword is valid only for exec definitions, not run: definitions.

Set work_dir to ${{ func_dir }} when the command needs to reference files in the same directory as func.yml:

exec:
  command: ["./build.sh"]
  work_dir: "${{ func_dir }}"

The function fails if the command exits with a non-zero exit code.

run

Use run for a function that calls other functions in sequence.

The function fails if any step in the sequence fails. Subsequent steps in the sequence do not run after a failure.

spec:
  inputs:
    environment:
      type: string
  outputs:
    url:
      type: string
---
run:
  - name: build
    func: ./build
  - name: push
    func: registry.example.com/my-org/push:1.0.0
    inputs:
      artifact: ${{ steps.build.outputs.artifact_path }}
  - name: deploy
    func: ./deploy
    inputs:
      env: ${{ inputs.environment }}
      image: ${{ steps.push.outputs.image_ref }}
outputs:
  url: ${{ steps.deploy.outputs.url }}

Set environment variables

Use env in the definition to set environment variables for the exec command or for all steps in a run: sequence. Values can use expressions:

spec:
---
run:
  - name: test
    func: ./run-tests
env:
  GOFLAGS: "-race"
  TARGET_ENV: "${{ inputs.environment }}"

Export environment variables

To make an environment variable available to all steps that run after your function for the remainder of the job, write it to ${{ export_file }}. Each line must be a JSON object with name and value fields:

echo '{"name":"INSTALL_PATH","value":"/opt/myapp"}' >> "${{ export_file }}"

Only string, number, and boolean values can be exported as environment variables.

For more information about how exported variables interact with env: and the wider environment, see environment variables.

Expressions

Expressions use the ${{ }} syntax and are evaluated just before the function runs. They can appear in inputs values, env values, exec command arguments, and work_dir.

The following context variables are available inside a function definition, in addition to those described in expressions:

VariableDescription
inputs.<name>The value of the named input passed to this function.
func_dirAbsolute path to the directory containing this func.yml. Use to reference bundled files.
output_filePath to the file for writing outputs.
export_filePath to the file for exporting environment variables.
steps.<step_name>.outputs.<output_name>Output from a named step (available in run: definitions only).

Complete example

The following function accepts a file path, compresses it with gzip, and returns the path to the compressed file.

Create the function

Directory layout:

compress/
├── func.yml
└── compress.sh

func.yml:

spec:
  inputs:
    input_path:
      type: string
  outputs:
    output_path:
      type: string
---
exec:
  command: ["${{ func_dir }}/compress.sh", "${{ inputs.input_path }}", "${{ output_file }}"]

compress.sh (must be executable):

#!/usr/bin/env sh
set -e

INPUT_PATH="$1"
OUTPUT_FILE="$2"

gzip --keep "$INPUT_PATH"

echo "{\"name\":\"output_path\",\"value\":\"${INPUT_PATH}.gz\"}" >> "$OUTPUT_FILE"

Use the function from a job

This function requires gzip in the job environment. This example assumes gzip is already available on the instance where the job runs. If it is not, you can install it first with a script: step, or invoke a function that handles the installation before calling compress.

my-job:
  run:
    - name: compress_artifact
      func: ./compress
      inputs:
        input_path: "dist/app.tar"
    - name: list_compressed
      script: ls -lh ${{ steps.compress_artifact.outputs.output_path }}

For more example functions, see GitLab Functions examples.

Build and release functions

Functions are distributed as OCI images. The step runner provides two built-in functions for building and publishing function images.

Build

The builtin://function/oci/build function builds a multi-architecture function OCI image from files in the project directory and archives it as function-image.tar in the CI_PROJECT_DIR.

common.files copies files shared across all platforms. platforms.<os/arch>.files copies files specific to that platform. In both cases, map keys are destination paths in the image and values are source paths relative to CI_PROJECT_DIR.

In the following example, function-image.tar is a function OCI image that supports two platforms: linux/amd64 and linux/arm64. Each platform image has three files: func.yml, my-script.sh, and bin/my-binary. Using the same filename for platform binaries keeps func.yml platform-independent.

build_function:
  artifacts:
    paths:
      - function-image.tar
  run:
    - name: build
      func: builtin://function/oci/build
      inputs:
        version: "1.2.3"
        common:
          files:
            func.yml: func.yml
            my-script.sh: my-script.sh
        platforms:
          linux/amd64:
            files:
              bin/my-binary: bin/linux-amd64/my-binary
          linux/arm64:
            files:
              bin/my-binary: bin/linux-arm64/my-binary

Release

The builtin://function/oci/publish function publishes the archive from function/oci/build to an OCI registry.

The publish function uses semantic versioning for function image tags: 1.0.0, 1.1.0, 2.0.0. The function extracts the version from the function-image.tar file. Publish updates the major, major.minor, major.minor.patch and latest tags where necessary.

Release candidates use a pre-release suffix such as 1.2.0-rc1. Publishing a release candidate creates only the exact major.minor.patch-prerelease tag. It does not update major, major.minor, or latest tags.

publish_function:
  needs: [build_function]
  run:
    - name: publish
      func: builtin://function/oci/publish
      inputs:
        archive: function-image.tar  # version is baked into the tar file
        to_repository: registry.example.com/my-org/my-function

Authenticate to a registry

To publish to a private registry, authenticate before running function/oci/publish. Use the Docker Auth function to generate and export DOCKER_AUTH_CONFIG as a step before you publish:

publish_function:
  needs: [build_function]
  run:
    - name: auth
      func: registry.gitlab.com/gitlab-org/ci-cd/runner-tools/gitlab-functions-examples/docker-auth:1
      inputs:
        registry: ${{ vars.CI_REGISTRY }}
        username: ${{ vars.CI_REGISTRY_USER }}
        password: ${{ vars.CI_REGISTRY_PASSWORD }}
    - name: publish
      func: builtin://function/oci/publish
      inputs:
        archive: function-image.tar
        to_repository: ${{ vars.CI_REGISTRY_IMAGE }}

docker-auth exports DOCKER_AUTH_CONFIG to all subsequent steps, so function/oci/publish picks it up automatically.

Once published, callers reference the function using the registry URL and a tag:

run:
  - name: run_my_function
    func: registry.example.com/my-org/my-function:1.2.3