Search code examples
cachinggithub-actions

How to output cache key to GITHUB_OUTPUT in Github Cache action?


In my Github workflow, I am using cache across two jobs. The cache key is generated with the help of ${{ hashFiles(...) }} function. In the second job I need this cache key name in order to skip repeated action for retrieving arguments for hashFiles, and go straight to downloading the cache. But I can't do it, why doesn't this action output a cache key name?


Solution

  • why doesn't this action output a cache key name?

    This question is well-suited for that action. You may create an issue on its repo (if there isn't one already) to ask this or maybe suggest it as a feature.


    Apart from that, apparently hashFiles seems to work only in certain contexts i.e. it cannot be used in a separate step to calculate it once and then shared across jobs via an output parameter.

    However, you may calculate it manually in a separate step without hashFiles as described in the docs:

    This function calculates an individual SHA-256 hash for each matched file, and then uses those hashes to calculate a final SHA-256 hash for the set of files. If the path pattern does not match any files, this returns an empty string. For more information about SHA-256, see "SHA-2."

    For example, in Bash you can do something like this using find and sha256sum utilities and then share the output between jobs:

    FILENAME="<FILENAME>"
    COMBINED_HASHES=$(echo $(find . -type f -name "$FILENAME" -exec bash -c "sha256sum {} | cut -d ' ' -f1" \;) | tr -d '\n')
    HASH=$(sha256sum <<< "$COMBINED_HASHES" | cut -d ' ' -f1)
    
    echo "HASH=$HASH" >> "$GITHUB_OUTPUT"
    

    Depending on your use case, you may further refine it accordingly.


    UPDATE (May 10th, 2023)

    Another solution could be to use https://github.com/actions/github-script with glob which provides an implementation for hashFiles also.

    Here's a working example:

    name: github_script_hash_files_test
    
    on: workflow_dispatch
    
    jobs:
      hash:
        runs-on: ubuntu-latest
    
        outputs:
          result: '${{ steps.hash.outputs.result }}'
    
        steps:
          - name: Checkout
            uses: actions/checkout@v3
    
          - name: Hash
            id: hash
            uses: actions/github-script@v6
            with:
              result-encoding: string
              script: |
                return glob.hashFiles('**/README.md');
    
      check:
        runs-on: ubuntu-latest
        needs: [hash]
    
        steps:
          - name: Check
            env:
              HASH: '${{ needs.hash.outputs.result }}'
            run: |
              echo "HASH: [$HASH]"