actions/cache: the key, and the restore-keys that save you

An exact key miss with no restore keys means starting from nothing, which for a node_modules cache is the difference between four seconds and ninety.

- uses: actions/cache@v2
  with:
    path: ~/.npm
    key: npm-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
    restore-keys: |
      npm-${{ runner.os }}-

# exact key hits  → restored, and not saved again
# exact key miss  → the newest matching prefix is restored,
#                   and the new cache IS saved at the end

The restore key is a prefix match against the most recently created cache, so a lock file change starts from the previous install rather than from empty. Caches are immutable once written, which is why the key must contain the hash — reusing a fixed key means the first run of the week populates it and nothing ever updates it. The scoping rules are the other surprise: a cache written on a branch is visible to that branch and to the default branch, and not to sibling branches.