Skip to content

Image Policy

Resolution order

The executor resolves the requested image in this order:

  1. the job's image: field, if JEBALLTO_ALLOW_JOB_IMAGE_OVERRIDE=true
  2. CUSTOM_ENV_CI_JOB_IMAGE
  3. JEBALLTO_DEFAULT_IMAGE

If nothing resolves to an image, prepare fails.

Required image contents

The image must boot a macOS VM that provides these tools in PATH:

  • bash
  • git
  • gitlab-runner

Before running job commands, the executor prepends common macOS tool locations to the remote shell PATH:

/opt/homebrew/bin:/usr/local/bin

That means tools installed by Homebrew or local admin scripts can be found even when the SSH login shell starts with a minimal PATH. The tools still need to exist in the image.

Allowing job-level overrides safely

Job-level image selection is flexible, but it can also widen your blast radius. A good production baseline is:

  • keep JEBALLTO_ALLOW_JOB_IMAGE_OVERRIDE=true
  • define JEBALLTO_IMAGE_ALLOWLIST
  • restrict allowed images to your registry namespace

Example:

export JEBALLTO_IMAGE_ALLOWLIST='ghcr.io/myorg/*,registry.internal/ci/*'

When to prefer a default image

Use JEBALLTO_DEFAULT_IMAGE when:

  • most jobs should land on the same image
  • you want a stable first rollout
  • your runners are operated by a central team

Use per-job images when:

  • different pipelines need materially different Xcode or SDK stacks
  • the image catalog is curated and guarded by an allowlist

Common image problems

  • image typo: fails during resolution or pull
  • image exists but lacks gitlab-runner: toolchain probe fails
  • image boots but SSH credentials do not match executor settings: prepare fails late
  • image requests too many resources for the host: provisioning slows or fails under load