Cubes

The cubes section lists the minimum logical actions, i.e., cubes, to execute within a task.

Such a minimum action may be calling a script, starting a Docker container, or calling a script in a Docker container.

The following cube types are available:

  • Native: Runs directly on a worker.

    If a native cube, while running, changes the worker environment, such as installs a package, creates or deletes a file, etc., such environment will still be there for all other cubes running within a single task.

  • Docker cube: Runs within a Docker container started on a worker. Technically, it runs a custom script or a container script, if the container has an entry point.

    If a Docker cube, while running, changes the environment, such environment will be available to other cubes within the task only in case the changes were made within the /sourcecraft directory. All other changes will be removed along with the Docker container.

    When working from a container, the directories are mounted as follows:

    • The directory housing files associated with the task in progress is mounted to /sourcecraft.
    • The directory to clone the repository to and that is also the working directory (workdir) by default, is mounted to /sourcecraft/workspace.

    You can get the paths of these directories from the $SOURCECRAFT_ROOT_DIRECTORY and $SOURCECRAFT_WORKSPACE predefined environment variables, respectively.

    To configure a Docker cube, use the image property to specify the Docker image name and, optionally, username, password, entry point, and arguments.

In cubes, you can use environment variables and secrets. To provide environment variables from a certain cube to others as KEY=VALUE pairs, you can use the $SOURCECRAFT_ENV predefined variable.

By default, cubes within a single task are run one by one. To link cubes, use the needs property, where you can specify the list of cubes to execute before the current one. If you skip this property, the cube will depend on the one defined immediately before it.

The artifacts that may be created after the cube is run are saved for further use. They will be available for download from the cube in the CI/CD section of the repository for 14 days.

Supported properties:

  • action: GitHub Action name and version, e.g., docker/setup-buildx-action@v3.11.1. For more information, see Integration with GitHub Actions in SourceCraft.

  • allow_failure: Flag to control your CI/CD process behavior when errors occur in individual cubes. If true, the task will continue as if the cube has completed successfully, even if there is an error. The default value is false. For more information, see Example of a configuration where the task continues despite cube failures.

  • artifacts: List of paths to the files that will be created after the cube is run and saved for further use. The artifacts will be available for download from the cube in the CI/CD section of the repository for 14 days. For more information, see Example of a cube configuration using artifacts.

  • env: Environment variables that are only available in a specific cube. For more information, see Example of a cube configuration using variables, including predefined ones.

    Tip

    You can also set environment variables within the following sections:

    • workflows: Variables will be available to all cubes of all tasks within a specific workflow.
    • tasks: Variables will be available in all cubes of a certain task.
  • exported: Set this flag to true to allow reusing the cube in another repository. The default value is false. For more information, see Example of reusing cube parameters from a YAML file in another repository.

  • gitlab_workflow: Path to the GitLab pipeline configuration file. For more information, see GitLab pipelines in the SourceCraft CI/CD.

  • if: Cube execution condition. If the condition is not met, the cube is skipped and the job continues. Supports the following operators:

    • always(): Execute the cube regardless of whether or not the previous cubes were executed successfully, e.g., if you need to clean the environment.
    • contains(): Check the string for any content, e.g., contains(env.SOURCECRAFT_COMMIT_REF_NAME, "release") or env.SOURCECRAFT_COMMIT_REF_NAME.contains("release").
    • ==: Comparison, e.g., env.SOURCECRAFT_COMMIT_REF_NAME == "main".
    • !=: Negation, e.g., env.SOURCECRAFT_COMMIT_REF_NAME != "main".
    • &&: The "AND" operator, e.g., contains(env.SOURCECRAFT_COMMIT_REF_NAME, "release") && env.SOURCECRAFT_BASE_REF == "main".
    • ||: The "OR" operator, e.g., contains(env.SOURCECRAFT_COMMIT_REF_NAME, "qwerty") || env.SOURCECRAFT_COMMIT_REF_NAME == "non-existing-ref".

    For more information, see Example of a configuration with conditional cube execution.

  • image: Docker image used to execute the cube. For more information, see Docker images.

  • name: Cube name. This is a required setting.

  • needs: List of cubes to execute before the current one.

  • script: Command to execute in the cube.

  • uses: Enables reusing another cube’s parameters in the current cube. The syntax depends on the location of the cube to reuse:

    • uses: <cube_name>: For cubes defined in .sourcecraft/ci.yaml. For more information, see Example of reusing cube parameters.

    • uses: ./<repository_file_path>/cubes/<cube_name>: For cubes defined in a YAML file in the same the repository. For more information, see Example of reusing cube parameters from a YAML file in the same repository. The number of files with cubes and the number of cubes per file are unlimited.

      Warning

      The path must begin with ./. Make sure to specify /cubes/<cube_name> after the file path.

    • uses: <organization_slug>/<repository_slug>/<repository_file_path>/cubes/<cube_name>: For cubes defined in a YAML file in another repository. For more information, see Example of reusing cube parameters from a YAML file in another repository.

      Warning

      To reuse a cube from another repository, the cube must have the exported: true flag. If this flag is not set, an attempt to reuse the cube in another repository will fail with an error.

    You can redefine some of the current cube’s parameters. For more information, see Example of reusing cube parameters.

  • with: GitHub Action parameters. It can only be used together with action.

Warning

Only cloud workers support running GitHub Actions or GitLab pipelines in SourceCraft CI/CD.

Example of a cube configuration using variables, including predefined ones
# Defining global variables
# to provide to all cubes of all tasks in all workflows.
env:
  GLOBAL_VAR: global_var
  GLOBAL_SECRET: ${{ secrets.<secret_name> }}

workflows:
  my-workflow:
    # Here you define variables that will be available in all cubes 
    # of all my-workflow tasks
    env:
      WORKFLOW_VAR: workflow-var
    
    tasks:
      - name: my-task
        # Here you define variables that will be available in all cubes 
        # within my-task
        env:
          TASK_ENV_VAR: This variable is available in all cubes of this task.
          # Multi-line variable
          MULTILINE_VAR: |
            multi-var
            multi-var
            this is my multi-var
        
        cubes:
          - name: my-cube-1
            # Here you define variables that will only be available
            # within my-cube-1
            env:
              CUBE_ENV_VAR: This variable is available only in cube my-cube-1.
              # Variable with a value from a secret
              SECRET_VAR: ${{ secrets.<secret_name> }}
              # Reusing global variables, 
              # e.g., GLOBAL_VAR and GLOBAL_SECRET
              LOCAL_VAR: ${{ env.<global_variable_1> }}
              LOCAL_SECRET: ${{ env.<global_variable_2> }}
              # Reusing workflow variables,
              # e.g., WORKFLOW_VAR
              LOCAL_VAR2: ${{ env.<workflow_variable> }}

            script:
              - echo "$TASK_ENV_VAR"
              - echo "$MULTILINE_VAR"
              - echo "$CUBE_ENV_VAR"
              - echo "$SECRET_VAR"
              - echo "$WORKFLOW_VAR"
              - echo "$LOCAL_VAR"
              - echo "$LOCAL_VAR2"
              - echo "$LOCAL_SECRET"

          - name: my-cube-2
            # Here you define variables that will only be available 
            # within my-cube-2
            env:
              CUBE_ENV_VAR: This variable is available only in cube my-cube-2.
            script:
              - echo "$TASK_ENV_VAR"
              - echo "$CUBE_ENV_VAR"
              # Using a predefined variable
              - echo "$SOURCECRAFT_TASK"
              - echo "$WORKFLOW_VAR"
              - echo "$GLOBAL_VAR"

      - name: my-task-2
        cubes:
          - name: my-cube-3
            script:
              - echo "$WORKFLOW_VAR"
              - echo "$GLOBAL_VAR"

For more information, see Predefined environment variables and Processing environment variables in SourceCraft.

Example of a cube configuration using artifacts
workflows:
  my-workflow:
    tasks:
      - name: my-task
        cubes:
          - name: delete-git
            script:
              - env
              - rm -rfv ./git
            artifacts:
              paths:
                - ./test.cpp

See also an example of using artifacts for Java in Examples.

Example of a configuration with cube dependencies
workflows:
  my-workflow:
    tasks:
      - name: my-task
        cubes:
          - name: vendor
            script:
              - make vendor

          - name: build-client
            needs: [ "vendor" ]
            script:
              - go build -C cmd/client
            artifacts:
              paths:
                - cmd/client/client

          - name: build-server
            needs: [ "vendor" ]
            script:
              - go build -C cmd/server/server
            artifacts:
              paths:
                - cmd/server/server

          - name: run-tests
            needs: [ "build-client", "build-server" ]
            script:
              - go test ./...
Example of reusing cube parameters
cubes:
  - name: external-cube
    env:
      CUBE_VAR: hello
    script:
      - echo $CUBE_VAR

tasks:
  - name: first-task
    cubes:
      - name: first-cube
        uses: external-cube
      # Reusing a cube with a redefined parameter
      - name: second-cube
        env:
          CUBE_VAR: world
        uses: external-cube

workflows:
  first-workflow:
    tasks:
      - first-task
Example of reusing cube parameters from a YAML file in the same repository

The .ci-files/cubes/bash-lib.yaml file containing the cube to reuse:

cubes:
  - name: external-cube-1
    env:
      CUBE_VAR: hello
    script:
      - echo $CUBE_VAR
  - name: external-cube-2
    script:
      - echo "world"

.sourcecraft/ci.yaml file:

tasks:
  - name: first-task
    cubes:
      - name: first-cube
        uses: ./.ci-files/cubes/bash-lib.yaml/cubes/external-cube-1

workflows:
  first-workflow:
    tasks:
      - first-task
      - second-task:
        cubes:
          - name: second-cube
            uses: ./.ci-files/cubes/bash-lib.yaml/cubes/external-cube-2
Example of reusing cube parameters from a YAML file in another repository

The .ci-files/cubes/bash-lib.yaml file with the cube to reuse, stored in the myrepo repository of the myorg organization:

cubes:
  - name: external-cube-1
    env:
      CUBE_VAR: hello
    script:
      - echo $CUBE_VAR
    # Flag that enables using the cube in other repositories
    exported: true
  - name: external-cube-2
    script:
      - echo "world"
    exported: true

The repository’s .sourcecraft/ci.yaml file containing the CI configuration:

tasks:
  - name: first-task
    cubes:
      - name: first-cube
        uses: myorg/myrepo/.ci-files/cubes/bash-lib.yaml/cubes/external-cube-1

workflows:
  first-workflow:
    tasks:
      - first-task
      - second-task:
        cubes:
          - name: second-cube
            uses: myorg/myrepo/.ci-files/cubes/bash-lib.yaml/cubes/external-cube-2
Example of a configuration where the task continues despite cube failures
workflows:
  workflow-name:
    tasks:
      - name: task-name
        cubes:
          - name: failing-cube
            allow_failure: true
Example of a configuration with conditional cube execution
workflows:
  workflow-name:
    tasks:
      - name: task-name
        cubes:
          # The cube will be executed only if the workflow has been executed in the branch whose name 
          # contains "release", and the target branch in the pull request is "main"
          - name: condition-cube-1
            if: contains(env.SOURCECRAFT_COMMIT_REF_NAME, "release") && env.SOURCECRAFT_BASE_REF == "main"
            script:
              - echo 'The source branch name contains text "release" and the target branch is "main".'

          # The cube will be executed only if the workflow has been executed in the branch whose name
          # contains "feature", and the target branch in the pull request is not "main"
          - name: condition-cube-2
            if: env.SOURCECRAFT_COMMIT_REF_NAME.contains("feature") || env.SOURCECRAFT_BASE_REF != "main"
            script:
              - echo 'The source branch name contains text "feature" or the target branch is not "main".'

          # Executing a cube regardless of whether the previous cubes were successful 
          # or not
          - name: condition-cube-3
            if: always()
            script:
              - env -i bash

Docker images

The image section contains parameters of the Docker image used to execute the cube.

You can specify a standard Docker image name or a path in a particular registry.

If the image section is not specified, the commands will be executed in Linux environment.

Supported optional properties:

  • args: Arguments to provide as input to a starting container. You cannot use this property in a cube where the script property is specified.

  • entrypoint: Redefining the container entry point. Same as the --entrypoint flag for the docker run command.

    To learn more about using the entry point and arguments, see the relevant section.

  • name: Path to the Docker image in the registry.

  • password: Password to access the registry. You may want to use secrets to store your passwords.

  • username: Username to access the registry.

Example of a Docker image configuration with a standard name
workflows:
  my-workflow:
    tasks:
      - name: my-task
        cubes:
          - name: my-cube
            image: ubuntu:22.04
            script: echo "hello world!"
Example of a Docker image configuration specifying a path in a particular registry
workflows:
  my-workflow:
    tasks:
      - name: my-task
        cubes:
          - name: my-cube
            image: cr.yandex/mirror/ubuntu:22.04
            script: echo "hello world!"
Example of a Docker image configuration with authentication

If authentication is required to access the registry, you can use the docker login command in your task or configure authentication in the image section and use a secret, e.g.:

workflows:
  my-workflow:
    tasks:
      - name: my-task
        cubes:
          - name: my-cube
            image:
              name: some-docker-registry.com/account-name/ubuntu:22.04
              username: username 
              password: ${{ secrets.<secret_name> }}

For more information about working with secrets, see Managing secrets in a SourceCraft repository.

Entry point and arguments

Running commands in a Docker container

To run commands in the container context, specify the Docker image path in the registry using the image or image:name property, and provide the commands in the script property, e.g.:

cubes:
  - name: greet
    env:
      GREETING: "Hello"
    image: docker.io/library/node
    script:
      - echo $GREETING

If the container has a redefined entry point, you will need to reset the latter before running a command from script. You can do this by specifying "" in the entrypoint property. For example, you can use a container that has the ENTRYPOINT ["/usr/bin/docker"] entry point set by default:

cubes:
  - name: greet
    env:
      GREETING: "Hello"
    image:
      name: some-docker-registry.com/cloud-builders/docker
      entrypoint: ""
    script:
      - echo $GREETING

Providing command-line arguments to a Docker container

To provide arguments, which you need to run a container, to a container with a redefined entry point, use the args property. For example, this may be the case for a container used to create a new Docker image:

cubes:
  - name: build-and-greet
    image:
      name: some-docker-registry.com/cloud-builders/docker
      args: ["build", "-t", "hello-world", "."]

Alternative configuration:

cubes:
  - name: build-and-greet
    image:
      name: some-docker-registry.com/cloud-builders/docker
      args:
        - 'build'
        - '-t'
        - 'hello-world'
        - '.'

Tip

To flexibly solve your CI/CD tasks using Docker containers, you can use entrypoint and args properties together.

Example of using entrypoint and args together:

cubes:
  - name: test
    image:
      name: docker.io/library/python:3.13-slim
      entrypoint: "/bin/bash"
      args: ["-c", "'pip install flask && python test_app.py -v'"]

Alternative configuration using script:

cubes:
  - name: test
    image: docker.io/library/python:3.13-slim
    script:
      - pip install flask
      - python test_app.py -v

The script: [commands] property is an alternative to entrypoint: "default shell" and args: ["-c", 'command_1 && … && command_N'].

Warning

You cannot specify both image:args and script at the same time in the same cube.

See also