name: 'Cache Julia artifacts, packages and registry' description: 'Cache Julia using actions/cache' author: 'Sascha Mann, Rik Huijzer, and contributors' branding: icon: 'archive' color: 'purple' inputs: cache-name: description: >- The cache key prefix. The key body automatically includes the OS and, unless disabled, the matrix vars. Include any other parameters/details in this prefix to ensure one unique cache key per concurrent job type. default: julia-cache;workflow=${{ github.workflow }};job=${{ github.job }} include-matrix: description: Whether to include the matrix values when constructing the cache key. default: 'true' depot: description: Path to a Julia depot directory where cached data will be saved to and restored from. default: '' cache-artifacts: description: Whether to cache the depot's `artifacts` directory. default: 'true' cache-packages: description: Whether to cache the depot's `packages` directory. default: 'true' cache-registries: description: Whether to cache the depot's `registries` directory. default: 'true' cache-compiled: description: Whether to cache the depot's `compiled` directory. default: 'true' cache-scratchspaces: description: Whether to cache the depot's `scratchspaces` directory. default: 'true' cache-logs: description: Whether to cache the depot's `logs` directory. This helps automatic `Pkg.gc()` keep the cache size down. default: 'true' delete-old-caches: description: Whether to delete old caches for the given key. default: 'true' token: description: A GitHub PAT. Requires `repo` scope to enable the deletion of old caches. default: ${{ github.token }} outputs: cache-hit: description: A boolean value to indicate an exact match was found for the primary key. Returns "" when the key is new. Forwarded from actions/cache. value: ${{ steps.hit.outputs.cache-hit }} runs: using: 'composite' steps: - name: Install jq # Skip installation on GitHub-hosted runners: # https://github.com/orgs/community/discussions/48359#discussioncomment-5323864 if: ${{ !startsWith(runner.name, 'GitHub Actions') }} uses: dcarbone/install-jq-action@v2.1.0 with: force: false # Skip install when an existing `jq` is present - id: paths run: | if [ -n "${{ inputs.depot }}" ]; then depot="${{ inputs.depot }}" elif [ -n "$JULIA_DEPOT_PATH" ]; then # Use the first depot path depot=$(echo $JULIA_DEPOT_PATH | cut -d$PATH_DELIMITER -f1) else depot="~/.julia" fi echo "depot=$depot" >> $GITHUB_OUTPUT [ "${{ inputs.cache-artifacts }}" = "true" ] && A_PATH="${depot}/artifacts" echo "artifacts-path=$A_PATH" >> $GITHUB_OUTPUT [ "${{ inputs.cache-packages }}" = "true" ] && P_PATH="${depot}/packages" echo "packages-path=$P_PATH" >> $GITHUB_OUTPUT [ "${{ inputs.cache-registries }}" = "true" ] && R_PATH="${depot}/registries" echo "registries-path=$R_PATH" >> $GITHUB_OUTPUT [ "${{ inputs.cache-compiled }}" = "true" ] && PCC_PATH="${depot}/compiled" echo "compiled-path=$PCC_PATH" >> $GITHUB_OUTPUT [ "${{ inputs.cache-scratchspaces }}" = "true" ] && S_PATH="${depot}/scratchspaces" echo "scratchspaces-path=$S_PATH" >> $GITHUB_OUTPUT [ "${{ inputs.cache-logs }}" = "true" ] && L_PATH="${depot}/logs" echo "logs-path=$L_PATH" >> $GITHUB_OUTPUT shell: bash env: PATH_DELIMITER: ${{ runner.OS == 'Windows' && ';' || ':' }} - name: Generate Keys id: keys run: | # `matrix_key` joins all of matrix keys/values (including nested objects) to ensure that concurrent runs each use a unique cache key. # When `matrix` isn't set for the job then `MATRIX_JSON=null`. if [ "${{ inputs.include-matrix }}" == "true" ] && [ "$MATRIX_JSON" != "null" ]; then matrix_key=$(echo "$MATRIX_JSON" | jq 'paths(type != "object") as $p | ($p | join("-")) + "=" + (getpath($p) | tostring)' | jq -rs 'join(";") | . + ";"') fi restore_key="${{ inputs.cache-name }};os=${{ runner.os }};${matrix_key}" # URL encode any restricted characters: # https://github.com/actions/toolkit/blob/5430c5d84832076372990c7c27f900878ff66dc9/packages/cache/src/cache.ts#L38-L43 restore_key=$(sed 's/,/%2C/g' <<<"${restore_key}") key="${restore_key}run_id=${{ github.run_id }};run_attempt=${{ github.run_attempt }}" echo "restore-key=${restore_key}" >> $GITHUB_OUTPUT echo "key=${key}" >> $GITHUB_OUTPUT shell: bash env: MATRIX_JSON: ${{ toJSON(matrix) }} - uses: actions/cache@4d4ae6ae148a43d0fd1eda1800170683e9882738 id: cache with: path: | ${{ steps.paths.outputs.artifacts-path }} ${{ steps.paths.outputs.packages-path }} ${{ steps.paths.outputs.registries-path }} ${{ steps.paths.outputs.scratchspaces-path }} ${{ steps.paths.outputs.compiled-path }} ${{ steps.paths.outputs.logs-path }} key: ${{ steps.keys.outputs.key }} restore-keys: ${{ steps.keys.outputs.restore-key }} enableCrossOsArchive: false - name: list restored depot directory sizes if: ${{ steps.cache.outputs.cache-hit == 'true' }} run: du -shc ${{ steps.paths.outputs.depot }}/* || true shell: bash # github and actions/cache doesn't provide a way to update a cache at a given key, so we delete any # that match the restore key just before saving the new cache # Not windows - uses: pyTooling/Actions/with-post-step@adef08d3bdef092282614f3b683897cefae82ee3 if: ${{ inputs.delete-old-caches != 'false' && runner.OS != 'Windows' }} with: # seems like there has to be a `main` step in this action. Could list caches for info if we wanted # main: julia ${{ github.action_path }}/handle_caches.jl "${{ github.repository }}" "list" main: echo "" post: julia $GITHUB_ACTION_PATH/handle_caches.jl rm "${{ github.repository }}" "${{ steps.keys.outputs.restore-key }}" "${{ github.ref }}" "${{ inputs.delete-old-caches != 'required' }}" env: GH_TOKEN: ${{ inputs.token }} # Windows (because this action uses command prompt on windows) - uses: pyTooling/Actions/with-post-step@adef08d3bdef092282614f3b683897cefae82ee3 if: ${{ inputs.delete-old-caches != 'false' && runner.OS == 'Windows' }} with: main: echo "" post: cd %GITHUB_ACTION_PATH% && julia handle_caches.jl rm "${{ github.repository }}" "${{ steps.keys.outputs.restore-key }}" "${{ github.ref }}" "${{ inputs.delete-old-caches != 'required' }}" env: GH_TOKEN: ${{ inputs.token }} - id: hit run: echo "cache-hit=$CACHE_HIT" >> $GITHUB_OUTPUT env: CACHE_HIT: ${{ steps.cache.outputs.cache-hit }} shell: bash