nektos/act

Case of cache keys are not preserved

BytewaveMLP opened this issue ยท 0 comments

Bug report info

act version:            0.2.67
GOOS:                   linux
GOARCH:                 amd64
NumCPU:                 16
Docker host:            DOCKER_HOST environment variable is not set
Sockets found:
        /var/run/docker.sock
Config files:
        /home/bw81/.config/act/actrc:
                -P ubuntu-latest=catthehacker/ubuntu:act-latest
                -P ubuntu-22.04=catthehacker/ubuntu:act-22.04
                -P ubuntu-20.04=catthehacker/ubuntu:act-20.04
                -P ubuntu-18.04=catthehacker/ubuntu:act-18.04
Build info:
        Go version:            go1.21.13
        Module path:           github.com/nektos/act
        Main version:          (devel)
        Main path:             github.com/nektos/act
        Main checksum:
        Build settings:
                -buildmode:           exe
                -compiler:            gc
                -trimpath:            true
                CGO_ENABLED:          0
                GOARCH:               amd64
                GOOS:                 linux
                GOAMD64:              v1
                vcs:                  git
                vcs.revision:         3f5d34d38dec16a3c4cec1e8aab00d5f123727b2
                vcs.time:             2024-09-07T22:56:04Z
                vcs.modified:         true
Docker Engine:
        Engine version:        27.1.1
        Engine runtime:        runc
        Cgroup version:        1
        Cgroup driver:         cgroupfs
        Storage driver:        overlay2
        Registry URI:          https://index.docker.io/v1/
        OS:                    Docker Desktop
        OS type:               linux
        OS version:
        OS arch:               x86_64
        OS kernel:             5.15.153.1-microsoft-standard-WSL2
        OS CPU:                16
        OS memory:             7898 MB
        Security options:
                name=seccomp,profile=unconfined

Command used with act

gh act -W .github/workflows/api-ci.yml -j 'lint'

Describe issue

The case of keys for cache artifacts being committed to the cache are forcibly normalized to lowercase. This causes the result of cache.restoreCache to return an all-lowercase key, even if the original key was submitted with uppercase characters. This deviates from the behavior of GitHub Actions, as while restore operations ignore case, the returned key's case is preserved. This causes issues for workflows which rely on using partial-matching keys to determine whether they need to update the cache, as seen in setup-ruby.

More specifically, setup-ruby uses the result of cache.restoreCache to determine whether the cache that was just restored is a partial hit (same runner/Ruby version, but different dependencies), or if it's a complete miss. It does this by directly comparing the result of cache.restoreCache with the expected result of the current cache key, and if the two are different, it will repopulate the cache. However, because the Bundler lockfile is case-sensitive (Gemfile.lock), the returned cache key and the expected cache key differ in case, so this comparison fails (see log output).

Link to GitHub repository

No response

Workflow content

name: API CI

on:
  pull_request:
    paths:
      - 'api/**'
      - '.github/workflows/api-ci.yml'
  push:
    branches: [main]
    paths:
      - 'api/**'
      - '.github/workflows/api-ci.yml'

defaults:
  run:
    working-directory: ./api

jobs:
  lint:
    name: Rubocop

    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up Ruby
        uses: ruby/setup-ruby@v1
        with:
          working-directory: ./api
          ruby-version: .ruby-version
          bundler-cache: true

      - name: Lint code for consistent style
        run: bin/rubocop -f github

Relevant log output

| > bundle install
| [command]/opt/hostedtoolcache/Ruby/3.3.5/x64/bin/bundle config --local path /home/bw81/code/redacted/api/vendor/bundle
| [command]/opt/hostedtoolcache/Ruby/3.3.5/x64/bin/bundle config --local deployment true
| Cache key: setup-ruby-bundler-cache-v6-ubuntu-22.04-x64-ruby-3.3.5-wd-/home/bw81/code/redacted/api-with--without--only--Gemfile.lock-739163d6bb6d4fe1d6a1b548623765d25d19e28b2ffe053ad12a67982b00f759
[API CI/Rubocop]   ๐Ÿ’ฌ  ::debug::Resolved Keys:
[API CI/Rubocop]   ๐Ÿ’ฌ  ::debug::["setup-ruby-bundler-cache-v6-ubuntu-22.04-x64-ruby-3.3.5-wd-/home/bw81/code/redacted/api-with--without--only--Gemfile.lock-739163d6bb6d4fe1d6a1b548623765d25d19e28b2ffe053ad12a67982b00f759","setup-ruby-bundler-cache-v6-ubuntu-22.04-x64-ruby-3.3.5-wd-/home/bw81/code/redacted/api-with--without--only--Gemfile.lock-"]
[API CI/Rubocop]   ๐Ÿ’ฌ  ::debug::Checking zstd --quiet --version
[API CI/Rubocop]   ๐Ÿ’ฌ  ::debug::1.4.8
[API CI/Rubocop]   ๐Ÿ’ฌ  ::debug::zstd version: 1.4.8
[API CI/Rubocop]   ๐Ÿ’ฌ  ::debug::Resource Url: http://172.28.40.72:42931/_apis/artifactcache/cache?keys=setup-ruby-bundler-cache-v6-ubuntu-22.04-x64-ruby-3.3.5-wd-%252Fhome%252Fbw81%252Fcode%252Fredacted%252Fapi-with--without--only--Gemfile.lock-739163d6bb6d4fe1d6a1b548623765d25d19e28b2ffe053ad12a67982b00f759%252Csetup-ruby-bundler-cache-v6-ubuntu-22.04-x64-ruby-3.3.5-wd-%252Fhome%252Fbw81%252Fcode%252Fredacted%252Fapi-with--without--only--Gemfile.lock-&version=f3a190c975da8339aef2d723682c8fb06999ced0c1e8592447dabecbf40062e3
DEBU[0006] GET /_apis/artifactcache/cache?keys=setup-ruby-bundler-cache-v6-ubuntu-22.04-x64-ruby-3.3.5-wd-%2Fhome%2Fbw81%2Fcode%2Fredacted%2Fapi-with--without--only--Gemfile.lock-739163d6bb6d4fe1d6a1b548623765d25d19e28b2ffe053ad12a67982b00f759%2Csetup-ruby-bundler-cache-v6-ubuntu-22.04-x64-ruby-3.3.5-wd-%2Fhome%2Fbw81%2Fcode%2Fredacted%2Fapi-with--without--only--Gemfile.lock-&version=f3a190c975da8339aef2d723682c8fb06999ced0c1e8592447dabecbf40062e3  module=artifactcache
DEBU[0006] skip gc: 2024-10-20 17:22:06.991207882 -0400 EDT m=+0.010056442  module=artifactcache
[API CI/Rubocop]   โš™  ***
[API CI/Rubocop]   ๐Ÿ’ฌ  ::debug::Cache Result:
[API CI/Rubocop]   ๐Ÿ’ฌ  ::debug::{"archiveLocation":"***","cacheKey":"setup-ruby-bundler-cache-v6-ubuntu-22.04-x64-ruby-3.3.5-wd-/home/bw81/code/redacted/api-with--without--only--gemfile.lock-739163d6bb6d4fe1d6a1b548623765d25d19e28b2ffe053ad12a67982b00f759","result":"hit"}
[API CI/Rubocop]   ๐Ÿ’ฌ  ::debug::Archive Path: /tmp/005c0f38-ce32-4cd1-8208-4415c2e43f83/cache.tzst
[API CI/Rubocop]   ๐Ÿ’ฌ  ::debug::Use Azure SDK: false
[API CI/Rubocop]   ๐Ÿ’ฌ  ::debug::Download concurrency: 8
[API CI/Rubocop]   ๐Ÿ’ฌ  ::debug::Request timeout (ms): 30000
[API CI/Rubocop]   ๐Ÿ’ฌ  ::debug::Cache segment download timeout mins env var: undefined
[API CI/Rubocop]   ๐Ÿ’ฌ  ::debug::Segment download timeout (ms): 600000
[API CI/Rubocop]   ๐Ÿ’ฌ  ::debug::Lookup only: false
DEBU[0006] GET /_apis/artifactcache/artifacts/12         module=artifactcache
DEBU[0007] skip gc: 2024-10-20 17:22:06.991207882 -0400 EDT m=+0.010056442  module=artifactcache
| Cache Size: ~60 MB (62460171 B)
| [command]/usr/bin/tar -xf /tmp/005c0f38-ce32-4cd1-8208-4415c2e43f83/cache.tzst -P -C /home/bw81/code/redacted --use-compress-program unzstd
| Cache restored successfully
| Found cache for key: setup-ruby-bundler-cache-v6-ubuntu-22.04-x64-ruby-3.3.5-wd-/home/bw81/code/redacted/api-with--without--only--gemfile.lock-739163d6bb6d4fe1d6a1b548623765d25d19e28b2ffe053ad12a67982b00f759
| [command]/opt/hostedtoolcache/Ruby/3.3.5/x64/bin/bundle install --jobs 4
| Don't run Bundler as root. Installing your bundle as root will break this
| application for all non-root users on this machine.
| Bundle complete! 45 Gemfile dependencies, 154 gems now installed.
| Bundled gems are installed into `./vendor/bundle`
| 1 installed gem you directly depend on is looking for funding.
|   Run `bundle fund` for details
| [command]/opt/hostedtoolcache/Ruby/3.3.5/x64/bin/bundle clean
| Saving cache
[API CI/Rubocop]   ๐Ÿ’ฌ  ::debug::Checking zstd --quiet --version
[API CI/Rubocop]   ๐Ÿ’ฌ  ::debug::1.4.8
[API CI/Rubocop]   ๐Ÿ’ฌ  ::debug::zstd version: 1.4.8
[API CI/Rubocop]   ๐Ÿ’ฌ  ::debug::implicitDescendants 'false'
[API CI/Rubocop]   ๐Ÿ’ฌ  ::debug::followSymbolicLinks 'true'
[API CI/Rubocop]   ๐Ÿ’ฌ  ::debug::implicitDescendants 'false'
[API CI/Rubocop]   ๐Ÿ’ฌ  ::debug::omitBrokenSymbolicLinks 'true'
[API CI/Rubocop]   ๐Ÿ’ฌ  ::debug::Search path '/home/bw81/code/redacted/api/vendor/bundle'
[API CI/Rubocop]   ๐Ÿ’ฌ  ::debug::Matched: api/vendor/bundle
[API CI/Rubocop]   ๐Ÿ’ฌ  ::debug::Cache Paths:
[API CI/Rubocop]   ๐Ÿ’ฌ  ::debug::["api/vendor/bundle"]
[API CI/Rubocop]   ๐Ÿ’ฌ  ::debug::Archive Path: /tmp/1787f509-15c8-4e70-8ade-5884562e6f15/cache.tzst
| [command]/usr/bin/tar --posix -cf cache.tzst --exclude cache.tzst -P -C /home/bw81/code/redacted --files-from manifest.txt --use-compress-program zstdmt
[API CI/Rubocop]   ๐Ÿ’ฌ  ::debug::File Size: 62463553
[API CI/Rubocop]   ๐Ÿ’ฌ  ::debug::Reserving Cache
[API CI/Rubocop]   ๐Ÿ’ฌ  ::debug::Resource Url: http://172.28.40.72:42931/_apis/artifactcache/caches
DEBU[0010] POST /_apis/artifactcache/caches              module=artifactcache
DEBU[0010] skip gc: 2024-10-20 17:22:06.991207882 -0400 EDT m=+0.010056442  module=artifactcache
[API CI/Rubocop]   ๐Ÿ’ฌ  ::debug::Saving Cache (ID: 13)
[API CI/Rubocop]   ๐Ÿ’ฌ  ::debug::Upload cache
[API CI/Rubocop]   ๐Ÿ’ฌ  ::debug::Resource Url: http://172.28.40.72:42931/_apis/artifactcache/caches/13
[API CI/Rubocop]   ๐Ÿ’ฌ  ::debug::Upload concurrency: 4
[API CI/Rubocop]   ๐Ÿ’ฌ  ::debug::Upload chunk size: 33554432
[API CI/Rubocop]   ๐Ÿ’ฌ  ::debug::Awaiting all uploads
[API CI/Rubocop]   ๐Ÿ’ฌ  ::debug::Uploading chunk of size 33554432 bytes at offset 0 with content range: bytes 0-33554431/*
[API CI/Rubocop]   ๐Ÿ’ฌ  ::debug::Uploading chunk of size 28909121 bytes at offset 33554432 with content range: bytes 33554432-62463552/*
DEBU[0010] PATCH /_apis/artifactcache/caches/13          module=artifactcache
DEBU[0010] PATCH /_apis/artifactcache/caches/13          module=artifactcache
DEBU[0010] skip gc: 2024-10-20 17:22:06.991207882 -0400 EDT m=+0.010056442  module=artifactcache
DEBU[0011] skip gc: 2024-10-20 17:22:06.991207882 -0400 EDT m=+0.010056442  module=artifactcache
[API CI/Rubocop]   ๐Ÿ’ฌ  ::debug::Commiting cache
| Cache Size: ~60 MB (62463553 B)
[API CI/Rubocop]   ๐Ÿ’ฌ  ::debug::Resource Url: http://172.28.40.72:42931/_apis/artifactcache/caches/13
DEBU[0011] POST /_apis/artifactcache/caches/13           module=artifactcache
DEBU[0011] skip gc: 2024-10-20 17:22:06.991207882 -0400 EDT m=+0.010056442  module=artifactcache
| Cache saved successfully
| Took   4.57 seconds

Additional information

I've also reported this issue to ruby/setup-ruby, since GitHub Actions doesn't actually care about cache key case as far as I can tell (saving an all-uppercase key and restoring from an all-lowercase key works as expected). However, the behavior that cache keys are returned with the same case as they were saved may be important for some workflows, as evidenced by this issue.

ruby/setup-ruby#659