Skip to content

PullPolicy:local-on-fail

What does this MR do?

The always/never pull-policies are mostly useful for administrators that want some (security) control over the pipelines.

However the if-not-present policy does something interesting, it tries to use a local container first, and pulls it if it does not exist.

This flow is very useful for 'build pipeline container' scenarios, where a pipeline could do a 'docker build -t $CI_PIPELINE_ID' container for the duration of a pipeline.

The downside of this flag is, that any existing container never gets updated without outside input. This means for example that a shellcheck container, is never updated unless the admin wipes the docker caches.

This commit introduces a fourth option: LocalOnFail

What this means, is that we first try to pull the image (similar to always for non-pipeline containers) and if that fails (will always happen for pipeline containers) tries to use a local container instead.

In essence, we get both scenario's 'always-if-not-present'.

Why was this MR needed?

The current available pull-policies are not adequate, especially when doing both remote images (the most common scenario) mixed with containers-per-pipeline (interesting for non-web-apps).

What's the best way to test this MR?

Test cases where added, but the best way is to create a simple pipeline, that does both linting, building a container, and see that the updated container (for the linter) gets used after cache expiry.

stages:
  - lint
  - build
  - test

lint:
  stage: lint
  image: "shellcheck-alpine:stable"
  script:
    - shellcheck testscript.sh

build:
  stage: build
  image: "docker:stable"
  script:
    - docker build --pull --rm --tag "${CI_COMMIT_SHORT_SHA}:${CI_PIPELINE_ID}" "./"

test:
  stage: test
  image: "${CI_COMMIT_SHORT_SHA}:${CI_PIPELINE_ID}"
  script:
     - ./testscript.sh
FROM alpine:latest

COPY testscript.sh
#!/bin/sh

echo "Hello World"

exit 0

(the above is pseudo-code all written from head without actually testing or running it ;) sorry)

With the 'always' runner, the test stage will always fail, as we can't pull the pipeline container With the 'never' runner, the linter will fail With the 'if-not-present' everything works, but the linter image gets outdated quickly (as does the alpine:latest from the container)

With the new 'local-on-fail' policy, everything should work as expected; the linter is always up-to-date and the test can run the container created with build (internally the pull fails, but I don't think we'll see it).

What are the relevant issue numbers?

#26558 (closed)

Edited by Elliot Rushton

Merge request reports