[RAILS] GitHub Actions/Cache: Cache bundle installed gems on Docker container

When I run rspec/rubocop of Rails project on GitHub Acitons, I want to cache the gem with bundle install, but I get aPermission denied error and the cache cannot be created properly, and the cache key is polluted [ ^ 1] It was sometimes done.

error example


Post job cleanup.
/bin/tar --posix --use-compress-program zstd -T0 -cf cache.tzst -P -C /home/runner/work/project/project --files-from manifest.txt
/bin/tar: ../../../../../tmp/cache/bundle/gems/puma-5.1.1/ext/puma_http11/.gem.20201227-1-wtkvl5: Cannot open: Permission denied
/bin/tar: ../../../../../tmp/cache/bundle/gems/mini_racer-0.3.1/ext/mini_racer_extension/.gem.
[Omission]
/bin/tar: ../../../../../tmp/cache/bundle/gems/sassc-2.4.0/ext/.gem.20201227-1-1ompol5: Cannot open: Permission denied
/bin/tar: Exiting with failure status due to previous errors
Warning: Tar failed with error: The process '/bin/tar' failed with exit code 2

The above error is that the local / var/cache/bundle directory is mounted on the container's/bundle and BUNDLE_PATH =/bundle bundle install is executed, and/var/cache/bundle is . Occurs when caching with Actions/Cache

docker-compose and workflow yaml looks like this

docker-compose.yaml


version: '3.7'

services:
  app:
    ...

    volumes:
      - ./:/app:cached
      - /var/cache/bundle:/bundle

yaml:.github/workflows/ci.yml


jobs:
  ...
  rspec:
    ...
    env:
      GEMS_CACHE_DIR: /tmp/cache/bundle

    steps:
    ...

    - name: Cache bundle gems
      id: cache-bundle-gems
      uses: actions/cache@v2
      with:
        path: ${{env.GEMS_CACHE_DIR}}
        key: ${{ runner.os }}-${{ matrix.ruby }}-${{ env.GEM_CACHE_TAG }}-${{ hashFiles('Gemfile.lock') }}
        restore-keys: |
          ${{ runner.os }}-${{ matrix.ruby }}-${{ env.GEM_CACHE_TAG }}-

Solution 1 Rewrite access privileges

Since it is a problem of access authority, how to rewrite the access authority roughly.

It would be nice if sudo could be added with the tar command when creating the cache, but since there is no such option, insert it at the end of the action steps as shown below.

yaml:.github/workflows/ci.yml


  - name: Fix permissions of bundle
    id: fix-permissions-of-bundle
    run: sudo chmod -R a+rwx ${{env.GEMS_CACHE_DIR}}

Maybe this way is okay.

However, since the access authority will be rewritten, I can not confirm the operation around that (I think that there is almost no problem ...

Solution 2 Create a tar on the container and cache it

The permissions issue occurs because you're doing bundler install on the container but you're creating the tar locally.

There is no problem if you create a tar of / bundle on the container and cache the tar with Actions/Cache.

With the settings below, we are creating a tar by launching only the minimum required lightweight container (this time we are using a container named standalone).

yaml:.github/workflows/ci.yml


  env:
    GEMS_ARCHIVE_DIR: /tmp/cache/bundle-gem-archive
  ...
  # $GEMS_ARCHIVE_Cache DIR directory
  - name: Cache bundle gems
    id: cache-bundle-gems
    uses: actions/cache@v2
    with:
      path: ${{ env.GEMS_ARCHIVE_DIR }}
      key: ${{ runner.os }}-${{ matrix.ruby }}-${{ env.GEM_CACHE_TAG }}-${{ hashFiles('Gemfile.lock') }}
      restore-keys: |
        ${{ runner.os }}-${{ matrix.ruby }}-${{ env.GEM_CACHE_TAG }}-
    
  # $GEMS_ARCHIVE_On a lightweight container with DIR mounted/archive/bundle.Extract files from tar
  - name: Unarchive bundle gems cache
    id: unarchive-bundle-gems-cache
    run: test -f ${{env.GEMS_ARCHIVE_DIR}}/bundle.tar
      && docker-compose run --rm -v ${{ env.GEMS_ARCHIVE_DIR }}:/archive:cached standalone
        tar -xf /archive/bundle.tar -C /
      || echo "bundle gem cache does not exist."
    
  ...

  #On a lightweight container$GEM_Harden the contents of HOME with tar,/archive/bundle.Save as tar
  - name: Create bundle gems archive
    id: create-bundle-gems-archive
    if: steps.cache-bundle-gems.outputs.cache-hit != 'true'
    run: docker-compose run --rm -v ${{ env.GEMS_ARCHIVE_DIR }}:/archive:cached
        standalone tar -cf /archive/bundle.tar -C / bundle

In the case of this method, tar is executed on the container, so it seems to be a little slow, but in my environment, the error (a few seconds) changed (I think it depends on the amount of gem etc.).

[^ 1]: GitHub Actions/Cache "Unable to reserve cache with key \ {KEY }, another job may be creating this cache ." Error -Qiita

Recommended Posts

GitHub Actions/Cache: Cache bundle installed gems on Docker container
Run React on a Docker container
Run GUI application on Docker container
Run PureScript on a Docker container
Enable Docker build cache on GitHub Action and deploy to Amazon ECS
Publish Docker Image on GitHub Package Registry
Docker push to GitHub Container Registry (ghcr.io)
Launch docker container on EC2 (personal memorandum)
Run NordVPN on Docker (Windows) Ubuntu container
I installed Docker on my Raspberry Pi 3
Run GUI application on Docker container (Japanese input)
I installed Docker on EC2 and started it
Send emails using Docker container on Raspberry Pi 3
Update container image with KUSANAGI Runs on Docker
I tried running Ansible on a Docker container