Enable Gitea Actions Cache to Accelerate CI/CD

4 min read

Introduction

Caching is a vital aspect of modern computer science. Today, we will discuss enabling Gitea Actions(Gitea's built-in CI/CD) cache to speed up CI/CD.

Gitea Actions utilizes two types of caches. The first is the Runner Tool Cache, created when launching a runner. This runner creates a volume named act-toolcache, which is mounted to the local file system(usually /opt/hostedtoolcache). When an action like setup-go is used, it downloads and installs a version of Go, storing it in this special volume, thus preventing redundant downloads of dependencies.

The second type is more fine-grained. Originating from Github Actions but compatible with Gitea Actions, it's called action/cache. This action uses a hash key to retrieve the specific cache. For more specific information and detailed configuration about this action, refer to this Github Offical Doc. In this tutorial, we will enable both types of caches to accelerate CI/CD.

Use Runner Tool Cache

The process is straightforward. Just add an env variable called RUNNER_TOOL_CACHE in your Gitea action workflow, and the Gitea act runner will automatically detect this environment and store the download cache there.

Notice: For now, /toolcache is hardcoded in the upstream project nektos/act. So it cannot be changed.

An example configuration:

jobs:
  build:
    env:
      RUNNER_TOOL_CACHE: /toolcache
...

Alternatively, you can use Docker Volume to specifically mount the cache volume:

jobs:
  build:
    runs-on: ubuntu-latest
    container: 
      image: your_docker_image
      volumes:
        - your_docker_volumn:/opt/hostedtoolcache # this is where Runner store their cache default

download time before: download_before

download time after: download_after

Use Cache Action

The Runner uses a cache server to store the key/value pair cache. The cache server is enabled by default. So You can directly use the action/cache.

An example configuration:

name: Caching with Go
on: push
jobs:
  Cache-Go:
    name: Cache Go
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-go@v3
        with:
          go-version: '>=1.20.1'
      - uses: https://gitea.com/actions/go-hashfiles@v0.0.1
        id: hash-go
        with:
          patterns: |
            go.mod
            go.sum                                    
      - name: cache go
        id: cache-go
        uses: actions/cache@v3
        with: # Specify with your cache path
          path: |
            /your_cache_path                                    
          key: go_path-${{ steps.hash-go.outputs.hash }}
          restore-keys: |-
            go_cache-${{ steps.hash-go.outputs.hash }}

This example utilizes a go cache and go-hashfiles to generate a hash. You should specify your cache path according to your programming language and define the key in any form you like.

Notice

  1. If you are running the Runner with docker. You may encounter network issue with the cache server. You should change the cache server host and port in config.yaml for your Act Runner. The configuration is explained here in detail.
  2. The built-in function hashFiles in the workflow yaml is not supported in Gitea Actions right now. You can use go-hashfiles(maintained by Gitea maintainers) or other alternatives instead.

A Complete Example

Let's use an example to demonstrate how to utilize these two types of caches in a real development environment.

Assume we're going to build an app called Hello-Gitea using Go, and we enable the Gitea Actions workflow for every Push.

Here is the workflow yaml(this file is also available on Gitea website)

name: Test Cache

on: 
  push

jobs:
  TestCache:
    env: 
      RUNNER_TOOL_CACHE: /toolcache # Runner Tool Cache
    name: Cache Go
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - uses: actions/setup-go@v3
        with:
          go-version: '>=1.20.1'

      - name: Get go-hashfiles
        uses: https://gitea.com/actions/go-hashfiles@v0.0.1
        id: hash-go
        with:
          patterns: |-
            go.mod
            go.sum                                            

      - name: Echo hash
        run: echo ${{ steps.hash-go.outputs.hash }}
        
      - name: Cache go
        id: cache-go
        uses: https://github.com/actions/cache@v3 # Action cache
        with: # specify with your GOMODCACHE and GOCACHE
          path: |- 
            /root/go/pkg/mod
            /root/.cache/go-build
          key: go_cache-${{ steps.hash-go.outputs.hash }}  
          restore-keys: |-
            go_cache-${{ steps.hash-go.outputs.hash }}            

      - name: Build
        run: go build -v .

      - name: Test
        run: go test -v ./...

After setting everything up, we can see how these caches are utilized.

tool cache

action cache

FAQ

Q: Why should I specify RUNNER_TOOL_CACHE: /toolcache to make the Runner Tool Cache work? It seems like it should cache the file by default

A: It's an upstream issue of nektos/act. See the issue for more details.

Q: Can different act runners on the same host share the Runner Tool Cache?

A: Yes, they can. To do so, use a Docker volume to map the cache directory.