How to concatenate strings inside hashFiles

I want to use an input variable, like from a matrix or outputs of a previous step, concatenate it with a glob pattern like /** and use it inside the hashFiles expression in the actions/cache@v2 step.
For example, here is my example simple workflow yaml:

name: Matrix test
on:
  workflow_dispatch:
  push:
    branches:
      - tom-plat-matrix
    paths:
      - '.github/workflows/matrix_test.yml'
jobs:
  build-gulp-apps:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        apps: [
          {
            name: 'static',
            path: './src/servers/static'
          },
        ]
    steps:
      - uses: actions/checkout@v2
      - uses: actions/cache@v2
        with:
          key: ${{ hashFiles(matrix.apps.path/**) }}
          path: ${{ matrix.apps.path }}/js/dist
      - if: steps.cache.outputs.cache-hit != 'true'
        run: npx gulp ${{ matrix.apps.name }}-scripts

However, the workflow doesn’t run due to the following error:

The workflow is not valid. .github/workflows/matrix_test.yml (Line: 24, Col: 16): Unexpected symbol: ‘path/**’. Located at position 23 within expression: hashFiles(matrix.apps.path/**)

That makes sense since there is no path/** inside the matrix’ apps object.
I tried using join and format expressions, but that’s not possible inside the hashFiles expression.
Eventually I solved it by generating this string in a previous step to the cache step:

name: output ${{ matrix.apps.name }} glob
id: glob
run: |
  echo "::set-output name=glob::${{ matrix.apps.path }}/**"

and using the steps.glob.outputs.glob in the cache key instead.
However, that seems weird to me that it’s no solvable in a single cache step. This is just a simple example of a much more complex matrix, jobs and steps. If every time I need to add something to a matrix/input string I will need to create another step before, it would make my workflow file a lot longer and complicated.
So, what did I miss here?

We do something similar for caching our C# nuget packages. Since we use a mono-repo we need the hashFiles key to be based off the project sub-directory. You can use the format helper to build the path strings - Try hashFiles(format('{0}/**', matrix.apps.path)).

Here’s our cache action for reference.

    - name: Cache NuGet packages
      uses: actions/cache@v2
      with:
        path: ~/.nuget/packages
        key: ${{ runner.os }}-nuget-${{ hashFiles(format('{0}/**/*.csproj', env.PROJECT_DIR), format('{0}/*.props', env.PROJECT_DIR)) }}
        restore-keys: ${{ runner.os }}-nuget
1 Like

wow that works! I swear I tried the format option as I wrote in the original question, but I guess I was dreaming? :thinking: weird that join doesn’t work as well, both are similar expressions. But format will do! Thanks!