Skip to content

GitLab 18.2.0 - Cannot pull job cache when using file in a subdirectory as key

Summary

Since the update of our GitLab Dedicated Premium runners from 18.1.1 to 18.2.0, we are no longer able to use job cache with a file key, when this file key contains slash (which occurs when the file used as key sits in a subdirectory).

Steps to reproduce

I was able to reproduce the bug by using this .gitlab-ci.yml file, but any job with a cache.key.files with a / in it and a pull or pull-push policy should encounter this issue :

Folded for readability
---
.cache: &cache
  key:
    files:
      - project/dependencies.json
  paths:
    - project/vendor

install:
  stage: .pre
  image: alpine:latest
  script:
    - mkdir -p project/vendor
    - mv project/dependencies.json project/vendor
  cache:
    - <<: *cache
      when: on_success
      policy: push

build:
  stage: build
  image: alpine:latest
  script:
    - cat project/vendor/dependencies.json
  needs:
    - job: install
      artifacts: false
  cache:
    - <<: *cache
      policy: pull

Example Project

I put my code on this repository : yanbuatois/cache-key-test>, in it the job works as intended, but I see the gitlab-runner is not 18.2.0 but 18.2.0~pre.109.ga17adc6a (a17adc6a), which seems to be an older version.

What is the current bug behavior?

When trying to use a file as cache key with a / in its path, we are able to push our cache without any problem, but then it cannot be pulled anymore. When trying to pull the cache, we got the following error at the runtime:

cache key "0_project/dependencies-7ab1ff8ddd4179468d07100f16b6f19f91b645a8-non_protected" must not contain '/' or its URL-encoded equivalent

Then the job runs, but without any cache.

What is the expected correct behavior?

We should be able to pull our cache the same way we pushed it, using our subdirectory file as cache key.

Relevant logs and/or screenshots

For the job pushing our cache, the output is:

Running with gitlab-runner 18.2.0 (c24769e8)
  on stg-gitlab-runner-size-s-gitlab-runner-97564b6c5-c6ljg m4YqdxRS5, system ID: r_EYFjtTAzYxrd
  feature flags: FF_USE_FASTZIP:true, FF_WAIT_FOR_POD_TO_BE_REACHABLE:true
Resolving secrets
Preparing the "kubernetes" executor
00:00
Using Kubernetes namespace: gitlab
Using Kubernetes executor with image alpine:latest ...
Using attach strategy to execute scripts...
Using effective pull policy of [Always IfNotPresent] for container build
Using effective pull policy of [Always IfNotPresent] for container helper
Using effective pull policy of [Always IfNotPresent] for container init-permissions
Preparing environment
00:07
Using FF_USE_POD_ACTIVE_DEADLINE_SECONDS, the Pod activeDeadlineSeconds will be set to the job timeout: 1h0m0s...
Waiting for pod gitlab/runner-m4yqdxrs5-project-56-concurrent-0-1skanx9q to be running, status is Pending
Running on runner-m4yqdxrs5-project-56-concurrent-0-1skanx9q via stg-gitlab-runner-size-s-gitlab-runner-97564b6c5-c6ljg...
Getting source from Git repository
00:03
Gitaly correlation ID: 01K0F2ABA9WWAN9QRWF6AGM6T6
Fetching changes with git depth set to 20...
Initialized empty Git repository in /builds/ybuatois/test-ci/.git/
Created fresh repository.
Checking out 33d99fd4 as detached HEAD (ref is main)...
Skipping Git submodules setup
Restoring cache
00:01
Not downloading cache 0_project/dependencies-7ab1ff8ddd4179468d07100f16b6f19f91b645a8-non_protected due to policy
Executing "step_script" stage of the job script
00:01
$ mkdir -p project/vendor
$ mv project/dependencies.json project/vendor
Saving cache for successful job
00:01
Creating cache 0_project/dependencies-7ab1ff8ddd4179468d07100f16b6f19f91b645a8-non_protected...
project/vendor: found 2 matching artifact files and directories 
Uploading cache.zip to https://<bucket>/project/56/0_project/dependencies-7ab1ff8ddd4179468d07100f16b6f19f91b645a8-non_protected 
Created cache
Cleaning up project directory and file based variables
00:01
Job succeeded

Then for the job pulling our cache, the output is:

Running with gitlab-runner 18.2.0 (c24769e8)
  on stg-gitlab-runner-size-s-gitlab-runner-97564b6c5-c6ljg m4YqdxRS5, system ID: r_EYFjtTAzYxrd
  feature flags: FF_USE_FASTZIP:true, FF_WAIT_FOR_POD_TO_BE_REACHABLE:true
Resolving secrets
Preparing the "kubernetes" executor
00:00
Using Kubernetes namespace: gitlab
Using Kubernetes executor with image alpine:latest ...
Using attach strategy to execute scripts...
Using effective pull policy of [Always IfNotPresent] for container build
Using effective pull policy of [Always IfNotPresent] for container helper
Using effective pull policy of [Always IfNotPresent] for container init-permissions
Preparing environment
00:06
Using FF_USE_POD_ACTIVE_DEADLINE_SECONDS, the Pod activeDeadlineSeconds will be set to the job timeout: 1h0m0s...
Waiting for pod gitlab/runner-m4yqdxrs5-project-56-concurrent-0-aibh31y3 to be running, status is Pending
Running on runner-m4yqdxrs5-project-56-concurrent-0-aibh31y3 via stg-gitlab-runner-size-s-gitlab-runner-97564b6c5-c6ljg...
Getting source from Git repository
00:02
Gitaly correlation ID: 01K0F2AZS25P7V4WB797D6FRPX
Fetching changes with git depth set to 20...
Initialized empty Git repository in /builds/ybuatois/test-ci/.git/
Created fresh repository.
Checking out 33d99fd4 as detached HEAD (ref is main)...
Skipping Git submodules setup
Restoring cache
00:01
cache key "0_project/dependencies-7ab1ff8ddd4179468d07100f16b6f19f91b645a8-non_protected" must not contain '/' or its URL-encoded equivalent
Executing "step_script" stage of the job script
00:01
$ cat project/vendor/dependencies.json
cat: can't open 'project/vendor/dependencies.json': No such file or directory
Cleaning up project directory and file based variables
00:01
ERROR: Job failed: command terminated with exit code 1

Output of checks

Results of GitLab environment info

We run GitLab in Kubernetes.

Expand for output related to GitLab environment info

 (For installations with omnibus-gitlab package run and paste the output of: \`sudo gitlab-rake gitlab:env:info\`)  (For installations from source run and paste the output of: \`sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production\`)  

Results of GitLab application Check

Expand for output related to the GitLab application check

(For installations with omnibus-gitlab package run and paste the output of:
`sudo gitlab-rake gitlab:check SANITIZE=true`)

(For installations from source run and paste the output of:
`sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production SANITIZE=true`)

(we will only investigate if the tests are passing)

Possible fixes

I think the problem comes from this line : https://gitlab.com/gitlab-org/gitlab-runner/-/blob/main/shells/abstract.go?ref_type=heads#L277

But I don't know how it can be properly fixed while keeping secure the cache system.

Edited by 🤖 GitLab Bot 🤖