Compare commits

..

1 Commits

Author SHA1 Message Date
Mosè Giordano
dc533cbb67 Avoid evaluation of command substitution in input
In the body of the bash script, `${{ inputs }}` parameters are often quoted with double quotes, which allow command substitution.  This replaces double quotes with single quotes to prevent that and avoid command substitution.
2024-10-31 18:28:50 +00:00
4 changed files with 46 additions and 86 deletions

View File

@@ -59,7 +59,7 @@ jobs:
env: env:
JULIA_DEPOT_PATH: /tmp/julia-depot JULIA_DEPOT_PATH: /tmp/julia-depot
steps: steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
- name: Set cache-name - name: Set cache-name
id: cache-name id: cache-name
shell: bash shell: bash
@@ -117,7 +117,7 @@ jobs:
env: env:
JULIA_DEPOT_PATH: /tmp/julia-depot JULIA_DEPOT_PATH: /tmp/julia-depot
steps: steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
- uses: julia-actions/setup-julia@v2 - uses: julia-actions/setup-julia@v2
with: with:
version: ${{ matrix.version }} version: ${{ matrix.version }}
@@ -161,7 +161,7 @@ jobs:
outputs: outputs:
cache-name: ${{ steps.cache-name.outputs.cache-name }} cache-name: ${{ steps.cache-name.outputs.cache-name }}
steps: steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
- name: Set cache-name - name: Set cache-name
id: cache-name id: cache-name
run: | run: |
@@ -193,7 +193,7 @@ jobs:
needs: test-save-nomatrix needs: test-save-nomatrix
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
- name: Restore cache - name: Restore cache
id: cache id: cache
uses: ./ uses: ./
@@ -233,7 +233,7 @@ jobs:
outputs: outputs:
cache-name: ${{ steps.cache-name.outputs.cache-name }} cache-name: ${{ steps.cache-name.outputs.cache-name }}
steps: steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
- name: Set cache-name - name: Set cache-name
id: cache-name id: cache-name
run: | run: |
@@ -259,7 +259,7 @@ jobs:
needs: test-save-cloned-registry needs: test-save-cloned-registry
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
- name: Add General registry clone - name: Add General registry clone
shell: julia --color=yes {0} shell: julia --color=yes {0}
run: | run: |

View File

@@ -51,8 +51,6 @@ By default all depot directories called out below are cached.
### Outputs ### Outputs
- `cache-hit` - A boolean value to indicate an exact match was found for the primary key. Returns \"\" when the key is new. Forwarded from actions/cache. - `cache-hit` - A boolean value to indicate an exact match was found for the primary key. Returns \"\" when the key is new. Forwarded from actions/cache.
- `cache-paths` - A list of paths (as a newline-separated string) that were cached.
- `cache-key` - The cache key that was used for this run.
## How It Works ## How It Works
@@ -66,9 +64,6 @@ By default, this action removes caches that were previously made by jobs on the
GitHub automatically removes old caches after a certain period or when the repository cache allocation is full. GitHub automatically removes old caches after a certain period or when the repository cache allocation is full.
It is, however, more efficient to explicitly remove old caches to improve caching for less frequently run jobs. It is, however, more efficient to explicitly remove old caches to improve caching for less frequently run jobs.
For more information about GitHub caching generically, for example how to manually delete caches, see
[this GitHub documentation page](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/caching-dependencies-to-speed-up-workflows#managing-caches).
### Cache keys ### Cache keys
The cache key that the cache will be saved as is based on: The cache key that the cache will be saved as is based on:
@@ -106,35 +101,6 @@ Which means your caches files will not grow needlessly. GitHub also deletes cach
To disable deletion set input `delete-old-caches: 'false'`. To disable deletion set input `delete-old-caches: 'false'`.
### Caching even if an intermediate job fails
Just like [the basic actions/cache workflow](https://github.com/actions/cache), this action has a cache restore step, and also a save step which runs after the workflow completes.
By default, if any job in the workflow fails, the entire workflow will be stopped, and the cache will not be saved.
Due to current limitations in GitHub Actions syntax, there is no built-in option for this action to save the cache even if the job fails.
However, it does output information which you can feed into `actions/cache` yourself to achieve the same effect.
For example, this workflow will ensure that the cache is saved if a step fails (but skipping it if the cache was hit, i.e. there's no need to cache it again).
```yaml
steps:
- uses: actions/checkout@v4
- name: Load Julia packages from cache
id: julia-cache
uses: julia-actions/cache@v2
# do whatever you want here (that might fail)
- name: Save Julia depot cache on cancel or failure
id: julia-cache-save
if: cancelled() || failure()
uses: actions/cache/save@v4
with:
path: |
${{ steps.julia-cache.outputs.cache-paths }}
key: ${{ steps.julia-cache.outputs.cache-key }}
```
### Cache Garbage Collection ### Cache Garbage Collection
Caches are restored and re-saved after every run, retaining the state of the depot throughout runs. Caches are restored and re-saved after every run, retaining the state of the depot throughout runs.

View File

@@ -47,25 +47,19 @@ outputs:
cache-hit: 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. 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 }} value: ${{ steps.hit.outputs.cache-hit }}
cache-paths:
description: The paths that were cached
value: ${{ steps.paths.outputs.cache-paths }}
cache-key:
description: The full cache key used
value: ${{ steps.keys.outputs.key }}
runs: runs:
using: 'composite' using: 'composite'
steps: steps:
- name: Install jq - name: Install jq
uses: dcarbone/install-jq-action@b7ef57d46ece78760b4019dbc4080a1ba2a40b45 # v3.2.0 uses: dcarbone/install-jq-action@8867ddb4788346d7c22b72ea2e2ffe4d514c7bcb
with: with:
force: false # Skip install when an existing `jq` is present force: false # Skip install when an existing `jq` is present
- id: paths - id: paths
run: | run: |
if [ -n "${{ inputs.depot }}" ]; then if [ -n '${{ inputs.depot }}' ]; then
depot="${{ inputs.depot }}" depot='${{ inputs.depot }}'
elif [ -n "$JULIA_DEPOT_PATH" ]; then elif [ -n "$JULIA_DEPOT_PATH" ]; then
# Use the first depot path # Use the first depot path
depot=$(echo $JULIA_DEPOT_PATH | cut -d$PATH_DELIMITER -f1) depot=$(echo $JULIA_DEPOT_PATH | cut -d$PATH_DELIMITER -f1)
@@ -74,7 +68,6 @@ runs:
fi fi
if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "cygwin" ]]; then if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "cygwin" ]]; then
depot="${depot/#\~/$USERPROFILE}" # Windows paths depot="${depot/#\~/$USERPROFILE}" # Windows paths
depot="${depot//\\//}" # Replace backslashes with forward slashes
else else
depot="${depot/#\~/$HOME}" # Unix-like paths depot="${depot/#\~/$HOME}" # Unix-like paths
fi fi
@@ -82,11 +75,11 @@ runs:
cache_paths=() cache_paths=()
artifacts_path="${depot}/artifacts" artifacts_path="${depot}/artifacts"
[ "${{ inputs.cache-artifacts }}" = "true" ] && cache_paths+=("$artifacts_path") [ '${{ inputs.cache-artifacts }}' = "true" ] && cache_paths+=("$artifacts_path")
packages_path="${depot}/packages" packages_path="${depot}/packages"
[ "${{ inputs.cache-packages }}" = "true" ] && cache_paths+=("$packages_path") [ '${{ inputs.cache-packages }}' = "true" ] && cache_paths+=("$packages_path")
registries_path="${depot}/registries" registries_path="${depot}/registries"
if [ "${{ inputs.cache-registries }}" = "true" ]; then if [ '${{ inputs.cache-registries }}' = "true" ]; then
if [ ! -d "${registries_path}" ]; then if [ ! -d "${registries_path}" ]; then
cache_paths+=("$registries_path") cache_paths+=("$registries_path")
else else
@@ -94,11 +87,11 @@ runs:
fi fi
fi fi
compiled_path="${depot}/compiled" compiled_path="${depot}/compiled"
[ "${{ inputs.cache-compiled }}" = "true" ] && cache_paths+=("$compiled_path") [ '${{ inputs.cache-compiled }}' = "true" ] && cache_paths+=("$compiled_path")
scratchspaces_path="${depot}/scratchspaces" scratchspaces_path="${depot}/scratchspaces"
[ "${{ inputs.cache-scratchspaces }}" = "true" ] && cache_paths+=("$scratchspaces_path") [ '${{ inputs.cache-scratchspaces }}' = "true" ] && cache_paths+=("$scratchspaces_path")
logs_path="${depot}/logs" logs_path="${depot}/logs"
[ "${{ inputs.cache-logs }}" = "true" ] && cache_paths+=("$logs_path") [ '${{ inputs.cache-logs }}' = "true" ] && cache_paths+=("$logs_path")
{ {
echo "cache-paths<<EOF" echo "cache-paths<<EOF"
printf "%s\n" "${cache_paths[@]}" printf "%s\n" "${cache_paths[@]}"
@@ -113,10 +106,10 @@ runs:
run: | run: |
# `matrix_key` joins all of matrix keys/values (including nested objects) to ensure that concurrent runs each use a unique cache key. # `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`. # When `matrix` isn't set for the job then `MATRIX_JSON=null`.
if [ "${{ inputs.include-matrix }}" == "true" ] && [ "$MATRIX_JSON" != "null" ]; then 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(";") | . + ";"') matrix_key=$(echo "$MATRIX_JSON" | jq 'paths(type != "object") as $p | ($p | join("-")) + "=" + (getpath($p) | tostring)' | jq -rs 'join(";") | . + ";"')
fi fi
restore_key="${{ inputs.cache-name }};os=${{ runner.os }};${matrix_key}" restore_key='${{ inputs.cache-name }};os=${{ runner.os }};${matrix_key}'
# URL encode any restricted characters: # URL encode any restricted characters:
# https://github.com/actions/toolkit/blob/5430c5d84832076372990c7c27f900878ff66dc9/packages/cache/src/cache.ts#L38-L43 # https://github.com/actions/toolkit/blob/5430c5d84832076372990c7c27f900878ff66dc9/packages/cache/src/cache.ts#L38-L43
restore_key=$(sed 's/,/%2C/g' <<<"${restore_key}") restore_key=$(sed 's/,/%2C/g' <<<"${restore_key}")
@@ -127,7 +120,7 @@ runs:
env: env:
MATRIX_JSON: ${{ toJSON(matrix) }} MATRIX_JSON: ${{ toJSON(matrix) }}
- uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
id: cache id: cache
with: with:
path: | path: |
@@ -178,7 +171,7 @@ runs:
# - https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#usage-limits-and-eviction-policy # - https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#usage-limits-and-eviction-policy
# Not windows # Not windows
- uses: pyTooling/Actions/with-post-step@d6342484cd335d4c9c63d4f52f267c54d5bc3b19 # v5.4.0 - uses: pyTooling/Actions/with-post-step@e9d0dc3dba9fda45f195946858708f60c0240caf # v1.0.5
if: ${{ inputs.delete-old-caches != 'false' && if: ${{ inputs.delete-old-caches != 'false' &&
github.ref != format('refs/heads/{0}', github.event.repository.default_branch) && github.ref != format('refs/heads/{0}', github.event.repository.default_branch) &&
runner.OS != 'Windows' }} runner.OS != 'Windows' }}
@@ -186,18 +179,18 @@ runs:
# seems like there has to be a `main` step in this action. Could list caches for info if we wanted # 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: julia ${{ github.action_path }}/handle_caches.jl "${{ github.repository }}" "list"
main: echo "" 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' }}" post: julia $GITHUB_ACTION_PATH/handle_caches.jl rm '${{ github.repository }}' '${{ steps.keys.outputs.restore-key }}' '${{ github.ref }}' "${{ inputs.delete-old-caches != 'required' }}"
env: env:
GH_TOKEN: ${{ inputs.token }} GH_TOKEN: ${{ inputs.token }}
# Windows (because this action uses command prompt on windows) # Windows (because this action uses command prompt on windows)
- uses: pyTooling/Actions/with-post-step@d6342484cd335d4c9c63d4f52f267c54d5bc3b19 # v5.4.0 - uses: pyTooling/Actions/with-post-step@e9d0dc3dba9fda45f195946858708f60c0240caf # v1.0.5
if: ${{ inputs.delete-old-caches != 'false' && if: ${{ inputs.delete-old-caches != 'false' &&
github.ref != format('refs/heads/{0}', github.event.repository.default_branch) && github.ref != format('refs/heads/{0}', github.event.repository.default_branch) &&
runner.OS == 'Windows' }} runner.OS == 'Windows' }}
with: with:
main: echo "" 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' }}" 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: env:
GH_TOKEN: ${{ inputs.token }} GH_TOKEN: ${{ inputs.token }}

View File

@@ -4,52 +4,53 @@ In this guide, as an example, `v2.2.0` refers to the version number of the new r
## Part 1: Use the Git CLI to create and push the Git tags ## Part 1: Use the Git CLI to create and push the Git tags
Step 1: Clone the repository: Step 1: Create a new lightweight tag of the form `vMAJOR.MINOR.PATCH`.
```bash ```bash
git clone git@github.com:julia-actions/cache.git git clone git@github.com:julia-actions/cache.git
cd cache cd cache
``` git fetch --all --tags
Step 2: Create a new lightweight tag of the form `vMAJOR.MINOR.PATCH`. git checkout main
```bash git --no-pager log -1
# Get the commit SHA of the latest pushed commit on the default branch # Take note of the commit hash here.
git fetch origin --tags --force
commit_sha="$(git rev-parse origin/HEAD)"
# Validate this commit is the one you intend to release
git --no-pager log -1 "${commit_sha:?}"
# Now, create a new lightweight tag of the form `vMAJOR.MINOR.PATCH`. # Now, create a new lightweight tag of the form `vMAJOR.MINOR.PATCH`.
#
# Replace `commit_hash` with the commit hash that you obtained from the
# `git log -1` step.
#
# Replace `v2.2.0` with the actual version number that you want to use. # Replace `v2.2.0` with the actual version number that you want to use.
tag=v2.2.0 git tag v2.2.0 commit_hash
git tag "${tag:?}" "${commit_sha:?}"
``` ```
Step 3: Once you've created the new release, you need to update the major tag to point to the new release. For example, suppose that the previous release was `v2.1.0`, and suppose that you just created the new release `v2.2.0`. You need to update the major tag `v2` so that it points to `v2.2.0`. Here are the commands: Step 2: Once you've created the new release, you need to update the `v2` tag to point to the new release. For example, suppose that the previous release was `v2.1.0`, and suppose that you just created the new release `v2.2.0`. You need to update the `v2` tag so that it points to `v2.2.0`. Here are the commands:
```bash ```bash
# Create/update the new major tag locally, where the new major tag will point to the # Create/update the new v2 tag locally, where the new v2 tag will point to the
# release that you created in the previous step. # release that you created in the previous step.
# #
# The `-f` flag forcibly overwrites the old major tag (if it exists). # Make sure to change `v2.2.0` to the actual value for the tag that you just
major_tag="$(echo ${tag:?} | grep -o '^v[0-9]*')" # created in the previous step.
git tag --force "${major_tag:?}" "${tag:?}" #
# The `-f` flag forcibly overwrites the old
# `v2` tag (if it exists).
git tag -f v2 v2.2.0
``` ```
Step 4: Now you need to push the tags: Step 3: Now you need to push the tags:
```bash ```bash
# Regular-push the new tag: # Regular-push the new `v2.2.0` tag:
git push origin tag "${tag:?}" git push origin tag v2.2.0
# Force-push the new major tag: # Force-push the new v2 tag:
git push origin tag "${major_tag:?}" --force git push origin tag v2 --force
``` ```
## Part 2: Create the GitHub Release ## Part 2: Create the GitHub Release
Go to the [Releases](https://github.com/julia-actions/cache/releases) section of this repo and create a new release (using the GitHub web interface). Go to the [Releases](https://github.com/julia-actions/cache/releases) section of this repo and create a new release (using the GitHub web interface).
For the "choose a tag" drop-down field, select the new tag (e.g. `v2.2.0`) that you created and pushed in Part 1 of this guide. For the "choose a tag" drop-down field, select the `v2.2.0` tag that you created and pushed in Part 1 of this guide.