</>

Technology

GitHub Actions

Difficulty

Intermediate

Interview Question

How do you cache dependencies in GitHub Actions to speed up builds?

Answer

Caching Dependencies in GitHub Actions

Without caching, every run downloads all dependencies fresh — slow and wasteful. Caching saves them between runs.

Cache a Maven Project (~/.m2)

YAML
jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Set up JDK 17
        uses: actions/setup-java@v4
        with:
          java-version: '17'
          distribution: 'temurin'

      - name: Cache Maven dependencies
        uses: actions/cache@v4
        with:
          path: ~/.m2/repository
          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
          restore-keys: |
            ${{ runner.os }}-maven-
        # key:          exact match (pom.xml unchanged → cache hit)
        # restore-keys: partial match fallback (pom.xml changed → use old cache, update after)

      - name: Build and test
        run: mvn clean verify

Built-in Cache via setup-java (Simpler)

YAML
- name: Set up JDK 17 with Maven cache
  uses: actions/setup-java@v4
  with:
    java-version: '17'
    distribution: 'temurin'
    cache: 'maven'   # ← handles caching automatically!
    # also supports: 'gradle', 'sbt'

Cache npm / Node.js (Cypress, Playwright)

YAML
- name: Set up Node.js with npm cache
  uses: actions/setup-node@v4
  with:
    node-version: '20'
    cache: 'npm'       # ← built-in cache for npm
    # cache: 'yarn' or 'pnpm' also supported

- run: npm ci          # use ci (not install) for reproducible installs

# Or manual cache:
- name: Cache node_modules
  uses: actions/cache@v4
  with:
    path: ~/.npm
    key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
    restore-keys: |
      ${{ runner.os }}-node-

Cache Gradle

YAML
- name: Cache Gradle packages
  uses: actions/cache@v4
  with:
    path: |
      ~/.gradle/caches
      ~/.gradle/wrapper
    key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
    restore-keys: |
      ${{ runner.os }}-gradle-

Cache Python (pip)

YAML
- uses: actions/setup-python@v5
  with:
    python-version: '3.11'
    cache: 'pip'       # built-in pip cache

- run: pip install -r requirements.txt

How Cache Keys Work

CODE
key: ubuntu-latest-maven-abc123   ← exact match → CACHE HIT (fastest)

restore-keys:
  ubuntu-latest-maven-           ← prefix match → CACHE MISS but partial restore
  ubuntu-latest-                  ← broader fallback

On CACHE HIT:  restores files, skips download
On CACHE MISS: downloads normally, saves new cache after job

Cache Limits

  • Max cache size per entry: 10 GB
  • Cache evicted after 7 days of no use
  • Per-repo cache limit: 10 GB (then oldest evicted)

Measuring Cache Impact

YAML
- name: Cache Maven
  id: cache-maven
  uses: actions/cache@v4
  with:
    path: ~/.m2/repository
    key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}

- name: Check cache status
  run: |
    if [ "${{ steps.cache-maven.outputs.cache-hit }}" == "true" ]; then
      echo "Cache HIT — dependencies restored from cache"
    else
      echo "Cache MISS — downloading dependencies"
    fi

Typical Time Savings

ProjectWithout CacheWith Cache
Maven (200 deps)3–5 min20–30 sec
npm (node_modules)2–4 min15–25 sec
pip (ML packages)5–10 min30–60 sec

Follow AutomateQA

Related Topics