Cache: Configurable save cache on failure

Created on 13 Nov 2019  路  19Comments  路  Source: actions/cache

Currently this cache action will only save caches if all tests succeed. In many cases this is desirable behavior. However I have some projects with long build times and flakey test suites. It would be very helpful if I could configure the cache to be saved regardless of the test suite success or failure.

I have created a fork of this project action to set the post-if to always().

Is it possible to make the cache policy configurable? Or to pass post-if as an argument from the cache configuration?

feature request

Most helpful comment

Next fork with latest upstream changes (including the new 5GB cache limit): https://github.com/marketplace/actions/always-upload-cache

All 19 comments

I also desperately need this. For my use cases (grading of student assignments), it is expected that at least some of the tests will fail most of the time, so having a completely successful run is rare. This means caching is basically useless, as the cache will never actually be persisted.

@gerbal I've tried your fork, but it also doesn't seem to work. The post-action simply never runs (it stays a grey square in the log UI), same as with the original cache action.

Bump. I have some caches that take a long time to rebuild, and sometimes they may need to be rebuilt due to external events right in the middle of other changes that may cause subsequent steps to fail. So it's a big waste of time to have to then disable and reenable all of the following steps to be able to save the cache. A totally configurable 'pass-if' option would be a great solution, but if for some reason that's difficult to implement, maybe we could have a 'save-after' option where you could pass the id of the step that builds the thing that needs to be cached ? Then instead of running the post cache step after all other steps, it could run right after the 'save-after' step, and then that would make it succeed regardless of any subsequent steps that might fail ?

Next fork with latest upstream changes (including the new 5GB cache limit): https://github.com/marketplace/actions/always-upload-cache

For anyone interested, you are welcome to try out my advanced cache action built on top of this repo. Simply specify your cache targets in a config file, and finishes restoration, build, and save as many caches as you want in one step:

steps:
- uses: actions/checkout@v2
- uses: ktmud/cached-dependencies@v1
  with:
    run: |
      cache-restore npm
      npm install
      cache-save npm

      cache-restore pip
      pip install -r requirements.txt
      cache-save pip

https://github.com/ktmud/cached-dependencies#speficy-when-to-restore-and-save

@ktmud thanks for the link it seems like a better solution.

Seems like it would make a lot of sense in some circumstances.

Say I have following steps:

  • install dependencies (success)
  • check code style (fail)
  • post cache (skip)

It would make sense if post cache could happen conditionally on success of dependencies install, code style step is irrelevant to it.

+1, this would be very good to have, for example for Bazel.

This is very much needed. Even another action which only uploads would be fine.

Something like:

- name: Upload cache because failure
  if: failed()
  uses: actions/upload-cache
  with:
    path: dependencies/
    key: 123

+1, this would be very good to have

+1 yes please! Seems like a fairly minor addition that would make a bit difference

+1
I agree, having this as an option to cache even on a failure. Would be nice, because in docker build workflow this woud allow to get the working layers out of the cache and reduce much build time if the build fails somewhere.

@sidey79 @ben-spiller @ollydev @glau2 Is it possible to add post-if to the CI? Like this: post-if: always().

I'm not sure if that is available to users of the action or only available to the developer in action.yml.

@eyal0 that was not possible to override at the time I tried.

@Rarst yes, that's what I suspect. post-if is not documented in the user action guide as part of the spec.

You could fork it yourself and change it to always().

FYI: such fork already exists: https://github.com/pat-s/always-upload-cache

You can also reference env vars in the post-if condition:

post-if: success() || env.ALWAYS_SAVE_CACHE == 'true'

(I would love to replace the env var with an input here, but that wasn't supported when I last tested.)

@dhadka Inputs and env vars are basically the same thing:

From: https://raw.githubusercontent.com/actions/cache/main/dist/save/index.js

/**
 * Gets the value of an input.  The value is also trimmed.
 *
 * @param     name     name of the input to get
 * @param     options  optional. See InputOptions.
 * @returns   string
 */
function getInput(name, options) {
    const val = process.env[`INPUT_${name.replace(/ /g, '_').toUpperCase()}`] || '';
    if (options && options.required && !val) {
        throw new Error(`Input required and not supplied: ${name}`);
    }
    return val.trim();
}
exports.getInput = getInput;

Why would you rather use an input instead of an environment variable? The input would be static but an environment variable you can change whenever you want.

@eyal0 馃憤 true. This is getting off topic 馃槃 but I prefer inputs because:

  1. This keeps all the inputs to the action defined in one spot instead of split across inputs and env vars, especially when it changes the functionality of the action.

  2. If you need or want to use an env var, you can always pass the env var to the input:

    with:
       always-save: ${{ env.ALWAYS_SAVE_CACHE }}
    
  3. Probably most importantly, inputs are well-defined for an action. You can provide a description, make inputs required or optional, and set default values in action.yml. If you had a typo, for example, an input would show a warning or error whereas an env var would silently ignore the typo. This also lets us auto-generate documentation for each action when using the workflow editor.

But for this issue since we can't use inputs in the post-if condition, this is a moot point.

Yeah. If you want, you could use my fork and just change the "success()" to "always()".

https://github.com/actions/cache/pull/498#issuecomment-753804797

It lets you control the behavior of the post action with an environment variable. So you could "always" run the post action and then have an environment variable that is set to true or false to control whether or not to update the cache. There are likely dozens of solutions similar to mine.

The authors of actions/cache ought to look at what the common forks of this repo are trying to do and incorporate the features.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jwt27 picture jwt27  路  3Comments

evandrocoan picture evandrocoan  路  3Comments

binhxn picture binhxn  路  3Comments

jcornaz picture jcornaz  路  4Comments

Lyeeedar picture Lyeeedar  路  5Comments