GitLab Functions supports multiple operating systems
## Goal Steps should run on different operating systems and architectures. Only the code specific to the os/arch should be downloaded and run. This epic changes the step-runner to use step images, which are OCI images that conform to a known layout defined in the CI Steps step-runner. ## Success criteria - Users can run steps on Linux, on AMD_64 and ARM_64 - Steps references can point to an OCI image. Step runner downloads the appropriate step for the given operating system and architecture - Step authors can use a canonical step for packaging a steps OCI image - Step authors can use a canonical step for publishing a steps OCI image - Step OCI images is the default way of loading a step, fetching steps from Git is no longer supported (https://gitlab.com/groups/gitlab-org/-/epics/19829) ## Example step author workflow Similar to a Docker workflow, where a Docker image author has to build and push, the steps author workflow uses two new builtin steps (`builtin://step/oci/build` and `builtin://step/oci/promote`) that handle OCI image creation and publishing: 1. The step OCI image is packaged - Users specify the version of the step OCI image that is being created - Users specify which files should be included for all operating systems - Users specify which files should be included for specific operating systems/architectures - Produces a step OCI image as a tar file. The tar file will be an artifact on the CI job 2. Step authors may run tests on the step OCI image to verify correctness 3. Step authors publish/release the step OCI image to an OCI registry (e.g. GitLab Container Registry) - Input to the publish step is the tar file produced when the step OCI image was packaged - Users can authenticate to the OCI registry where the step OCI image is published <details> <summary>Example YAML of package and release</summary> **My app step.yml** ```yaml spec: inputs: msg: type: string --- exec: work_dir: ${{ job.CI_PROJECT_DIR }} command: ["${{step_dir}}/run", "--msg=${{inputs.msg}}"] ``` **CI pipeline** ```yaml stages: - build - release # build platform specific binaries # produces binaries out/my-app-linux-amd64, out/my-app-linux-arm64 binaries: stage: build image: golang:1.24 script: - apk add make - BUILD_OS_ARCH="linux/amd64 linux/arm64" make build artifacts: paths: - out/my-app-* # package the step OCI image # produces the image for two platforms: linux/amd64, linux/arm64 # The version specified here (1.0.3) is embedded in the step-image.tar metadata package step: stage: build image: alpine:latest needs: ["binaries"] run: - name: build_image step: builtin://step/oci/build inputs: version: 1.0.3 common: # these files are included on all built os/arch images files: ${{ job.CI_PROJECT_DIR }}/step.yml: step.yml platforms: # these files are included on specific os/arch images linux/amd64: files: ${{ job.CI_PROJECT_DIR }}/out/my-app-linux-amd64: run # renames file to run on the resulting image linux/arm64: files: ${{ job.CI_PROJECT_DIR }}/out/my-app-linux-arm64: run # renames file to run on the resulting image artifacts: paths: [step-image.tar] # step OCI image file created by builtin://step/oci/build # manually triggered release job # this pushes the step-image.tar file to the remote registry so other users can run the step # the version released is determined from the step-image.tar metadata release step: stage: release image: alpine:latest needs: ["package step"] run: # note: auth setup shown here is verbose and can be simplified in future iterations - name: auth_to_registry script: echo "{\"name\":\"DOCKER_AUTH_CONFIG\",\"value\":\"{\\\"auths\\\":{\\\"registry.gitlab.com\\\":{\\\"auth\\\":\\\"$(echo -n ${{ job.CI_REGISTRY_USER }}:${{ job.CI_REGISTRY_PASSWORD }} | base64)\\\"} } }\" }" >${{ export_file }} - name: release step: builtin://step/oci/promote inputs: archive: ${{ job.CI_PROJECT_DIR }}/step-image.tar to_repository: registry.gitlab.com/my-group/my-app-step when: manual allow_failure: false rules: - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH ``` </details> For simple use-cases, step authors could use a CI template to hide much of this complexity. ## Example user of step workflow Step OCI images can be referenced from `step:` using `step: <registry/repository@version>`. Loading steps using a step OCI image will be the default way to load. The current default fetches steps from a Git repository. Fetching steps from Git will no longer be possible. <details> <summary>Example YAML of package and release</summary> ```yaml run my-app: stage: build image: alpine:latest # no need for golang image here - step image contains binary specific to running os/arch run: - name: my_app_step step: registry.gitlab.com/my-group/my-app-step@1.0.0 inputs: msg: "Hi there!" ``` </details>
epic