How to: define a job for creating and pushing a merged manifest
merge-manifests:
  stage: container-build
  # all containers must be build before merging them
  # alternatively the job may be configured to run in a later stage
  needs:
    - job: container-build
      artifacts: false
  tags:
    # may run on any architecture supported by manifest-tool image
    - runner-xyz
  image:
    name: mplatform/manifest-tool:alpine
    entrypoint: [""]
  script:
    - >-
      manifest-tool # authorize against your container registry
      --username=${CI_REGISTRY_USER} --password=${CI_REGISTRY_PASSWORD} push
      from-args # define the architectures you want to merge --platforms
      linux/amd64,linux/arm64 # "ARCH" will be automatically replaced by
      manifest-tool # with the appropriate arch from the platform definitions
      --template ${CI_REGISTRY_IMAGE}:ARCH # The name of the final, combined
      image which will be pushed to your registry --target ${CI_REGISTRY_IMAGE}
```

#### On the Note of Adding Versioned Tags

For simplicity's sake we deliberately refrained from using versioned tagged
images (all builds will be tagged as "latest") in the previous examples, as we
feel like this adds to much platform and workflow specific code.

Nethertheless, for anyone interested in how we handle (dynamic) versioning in
GitLab, here is a short rundown:

- If you are only interested in building tagged releases, you can simply use the
  [GitLab predefined](https://docs.gitlab.com/ee/ci/variables/predefined_variables.html)
  `CI_COMMIT_TAG` variable when running a tag pipeline.
- When you (like us) want to additionally build container images outside of
  releases, things get a bit messier. In our case, we added a additional job
  which runs before the build and merge jobs (don't forget to extend the `needs`
  section of the build and merge jobs accordingly), which will set the tag to
  `latest` when running on the default branch, to the commit hash when run on
  other branches and to the release tag when run on a tag pipeline.

gitlab-ci.yml:

```yaml
container-get-tag:
  stage: pre-container-build-stage
  tags:
    - runner-xyz
  image: busybox
  script:
    # All other branches are tagged with the currently built commit SHA hash
    - |
      # If pipeline runs on the default branch: Set tag to "latest"
      if test "$CI_COMMIT_BRANCH" == "$CI_DEFAULT_BRANCH"; then
        tag="latest"
      # If pipeline is a tag pipeline, set tag to the git commit tag
      elif test -n "$CI_COMMIT_TAG"; then
        tag="$CI_COMMIT_TAG"
      # Else set the tag to the git commit sha
      else
        tag="$CI_COMMIT_SHA"
      fi
    - echo "tag=$tag" > build.env
  # parse tag to the build and merge jobs.
  # See: https://docs.gitlab.com/ee/ci/variables/#pass-an-environment-variable-to-another-job
  artifacts:
    reports:
      dotenv: build.env
```