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_WORKSPACEpredefined 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.
Devcontainer cube: Runs in the environment defined in the Development Container specification. This cube builds a container based on the configuration stored in the repository and runs a custom script in that container.
A devcontainer cube is specified in the devcontainer property which contains the path to the directory with the devcontainer.json or Dockerfile specification.
Cube with AI skill: Runs an AI skill available in the repository. You set such a cube using the skill parameter, which gives the service name of the skill. For more information, see Running a skill in CI/CD.
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_ENVpredefined 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.
allow_failure: Flag to control your CI/CD workflow 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.
if: Cube execution condition. If the condition is not met, the cube is skipped and the job continues.
If the condition does not contain calls to success(), failure(), or always(), the system automatically adds a success() check: success() && (<other_condition>). Therefore, if the previous cube in the same job fails, the current cube is skipped even if the specified condition is met. Failures of cubes with allow_failure: true do not prevent subsequent cubes from running.
If the condition already contains a call to at least one of these functions, no additional success() check is added.
Supported functions, expressions, and 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(): Checking the string for any content, e.g., contains(env.SOURCECRAFT_COMMIT_REF_NAME, "release") or env.SOURCECRAFT_COMMIT_REF_NAME.contains("release").
cubes.<cube_name>.status: Checking the status of any previous cube.
failure() and success(): Checking the summary status of all cubes that have completed their work before the current one in the same job.
skill: Service name of the AI skill to run in the cube. Provide it without /. For more information, see Running a skill in CI/CD.
uses: Parameter that allows the current cube to reuse parameters from another cube defined in the same .sourcecraft/ci.yaml file, any YAML file in the same repository, or any YAML file in another repository. For more information, see Reusing cube parameters.
with: GitHub Action or AI skill parameters; used together with action or skill.
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_varGLOBAL_SECRET:${{secrets.<secret_name>}}workflows:my-workflow:# Here you define variables that will be available in all cubes # of all my-workflow tasksenv:WORKFLOW_VAR:workflow-vartasks:-name:my-task# Here you define variables that will be available in all cubes # within my-taskenv:TASK_ENV_VAR:Thisvariableisavailableinallcubesofthistask.# Multi-line variableMULTILINE_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-1env:CUBE_ENV_VAR:Thisvariableisavailableonlyincubemy-cube-1.# Variable with a value from a secretSECRET_VAR:${{secrets.<secret_name>}}# Reusing global variables, # e.g., GLOBAL_VAR and GLOBAL_SECRETLOCAL_VAR:${{env.<global_variable_1>}}LOCAL_SECRET:${{env.<global_variable_2>}}# Reusing workflow variables,# e.g., WORKFLOW_VARLOCAL_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-2env:CUBE_ENV_VAR:Thisvariableisavailableonlyincubemy-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-2cubes:-name:my-cube-3script:-echo"$WORKFLOW_VAR"-echo"$GLOBAL_VAR"
Example of a configuration with conditional cube execution
workflows:workflow-name:tasks:-name:task-namecubes:# The cube will be executed if success() returns _true_, the source branch name# contains "release", and the target branch in the pool request is "main"-name:condition-cube-1if: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 if success() returns _true_ and at least one of the following conditions is met:# the source branch name contains "feature", and the target branch is not "main"-name:condition-cube-2if: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-3if:always()script:-env-ibash
To check the condition regardless of errors in previous cubes, add a call to always(). For example, the following condition checks only the branch name:
Example of a cube configuration that runs an AI skill
This example uses the issue-summary skill that creates an issue summary. Import the skill from the catalog before running it. In the issue_link parameter, specify the link to the issue.
You can use multiple AI skill cubes in a single task and add regular cubes to them.
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.
Tip
Instead of image, you can use the devcontainer section to run a cube in the environment defined in the Development Container specification. The image and devcontainer sections are mutually exclusive.
If neither the image nor the devcontainer section is specified, the commands will run in the 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
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.:
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.:
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:
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:
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.
Development Container (devcontainer) environment
The devcontainer section allows you to run a cube in the environment defined in the Development Container specification. When you start a cube, the system uses configuration from the repository to build a container and use it to run the command from the script section.
Tip
Instead of devcontainer, you can use the image section to run a cube in the environment of a specific Docker image. The image and devcontainer sections are mutually exclusive.
If neither the image nor the devcontainer section is specified, the commands will run in the Linux environment.
The devcontainer section must include the workspace_folder parameter which specifies the path to the repository's working directory. You can land the environment configuration file either at .devcontainer.json or .devcontainer/devcontainer.json relative to this directory. The directory may also contain files used in the environment configuration, such as Dockerfile.
Example of a cube configuration with devcontainer
devcontainer_tests/simple/.devcontainer.json:
{"name":"Rust Dev Container","build":{"dockerfile":"Dockerfile"},"customizations":{"vscode":{"extensions":["rust-lang.rust-analyzer"]}},"postCreateCommand":"cargo fetch"}
devcontainer_tests/simple/Dockerfile:
FROM rust:1.95-alpine
RUN cargo versionWORKDIR /workspace
The example below uses the simple-devcontainer cube to build an environment based on the configuration from the devcontainer_tests/simple directory and run the cargo version command.
Reusing cube parameters
You can use the uses parameter in the current cube to reuse the parameters of another cube. The syntax depends on the location of the cube to reuse:
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.
Example of reusing cube parameters within a single .sourcecraft/ci.yaml file
cubes:-name:external-cubeenv:CUBE_VAR:helloscript:-echo$CUBE_VARtasks:-name:first-taskcubes:-name:first-cubeuses:external-cube# Reusing a cube with a redefined parameter-name:second-cubeenv:CUBE_VAR:worlduses:external-cubeworkflows: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:
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-1env:CUBE_VAR:helloscript:-echo$CUBE_VAR# Flag that enables using the cube in other repositoriesexported:true-name:external-cube-2script:-echo"world"exported:true
The repository’s .sourcecraft/ci.yaml file containing the CI configuration:
max: Maximum number of retries. After the initial start, the cube will be restarted a maximum of three times.
on_error_types: Restart conditions:
timeout: Restart on timeout.
Checking the status of previous cubes
The following statuses are possible:
success: Success.
failure: Failure due to an error.
ignored_failure: Formal success. Ignored error transformed from failure with allow_failure=true enabled.
timeout: Failure. Execution interrupted by timeout.
ignored_timeout: Formal success. Ignored timeout transformed from timeout with allow_failure=true enabled.
skipped: Cube skipped. Not executed because the if condition returned false.
cancelled: Cube canceled. Entire workflow canceled by the user.
Checking the status of any previous cube
To check the status of any previous cube, use the cubes.<cube_name>.status == <status> expression format in the if condition.
Checking the status with cubes.<cube_name>.status does not disable automatic addition of success(). To execute a cube after a specific cube fails, add a call to failure() or always(), such as follows:
if:failure()&&cubes.failed-cube.status=="failure"
Example
cubes:# Cube 1: Successful cube-name:success-cubescript:-echo"This cube must succeed"# Cube 2: Checking the success status of the previous cube-name:if-success-cubeif:cubes.success-cube.status=="success"needs:-success-cubescript:-echo"success-cube succeeded (expected)!"
Checking the summary status of all previous cubes
To check the summary status of all cubes that have completed their work before the current one in the same job, use the following functions in the if condition:
success(): Returns true if all previous cubes completed successfully, were skipped, or failed with errors allowed by allow_failure: true.
Statuses that meet the condition:
success
skipped
ignored_failure
ignored_timeout
failure(): returns true if at least one of the previous cubes failed.
Statuses that meet the condition:
failure
timeout
cancelled
Failures of cubes with allow_failure: true do not trigger failure().
always(): Returns true regardless of the status of previous cubes. Use this function to execute a cube even after an error, e.g., to clean up the environment.
If the if condition contains no calls to success(), failure(), or always(), a success() check is added automatically. Calling any of these functions allows you to explicitly define how the results of previous cubes affect whether the current one runs.
Example
cubes:# Cube 1: Successful cube-name:success-cubescript:-echo"This cube must succeed"# Cube 2a: Checking the success status of the previous cube-name:if-success-cube# if-condition for checking the status of any previous cubeif:cubes.success-cube.status=="success"needs:-success-cubescript:-echo"success-cube succeeded (expected)!"# Cube 2b: Checking the failure status of the previous cube-name:if-failure-cube# if-condition for checking the summary status of all cubes that have completed their work before this cubeif:failure()||!success()needs:-success-cubescript:-echo"success-cube failed (not expected)!"-exit1# Cube 3: Cube with an error-name:failed-cubeallow_failure:trueneeds:-if-success-cube-if-failure-cubescript:-echo"This cube must fail"-exit1# Cube 4a: Checking the failure status of the previous cube-name:if-success-cube-2if:cubes.failed-cube.status=="success"needs:-failed-cubescript:-echo"failed-cube succeeded (not expected)!"-exit1# Cube 4b: Checking the failure status of the previous cube-name:if-failure-cube-2if:cubes.failed-cube.status=="ignored_failure"needs:-failed-cubescript:-echo"failed-cube failed (expected)!"
You can also check the execution status of previous cubes in scripts by using the following syntax for outputs: ${{ cubes.<cube-name>.status }}.
Example
if [ "${{ cubes.retrycube.status }}" == "success" ]; then
echo "Retry cube succeeded!"
else
echo "Retry cube failed!"
fi