Interacting with the Cache

Scrutinizer allows you to directly interact with the cache via regular build commands. This is in particular needed on minimal nodes, but can be used on auto-setup nodes, too.

Commands

Storing files and directories in the cache

For storing, the command usage is as follows:

# Storing a compressed tar archive with the given files/directories
store-in-cache <Scope: repository|execution> <key> <file-or-dir> <...more-files-or-dirs-or-a-tar-option>

# Storing piped input from any command
tar cf - some-dir/ | gzip | store-in-cache <Scope: repository|execution> <key> "-"

In the first case, all arguments after <key> are passed to the tar command. So, you can freely use any other options like --exclude that tar supports to further customize what is cached.

Restoring files and directories from the cache

For restoring, the command usage is as follows:

# Restoring a compressed tar archive in the current directory
restore-from-cache <Scope: repository|execution> <key>

# Piping data to another process
restore-from-cache <Scope: repository|execution> <key> - | gunzip | tar xf

All files and directories are unpacked relative to the directory you are currently in. Typically you would want to run store-in-cache and the corresponding restore-from-cache from the same directory.

If a file does not yet exist in the cache, restoring will still exit successfully and print a message that the key was not found in storage. If you specifically would like to check if a file exists, please see below.

Checking if a key exists in the cache

For checking the existence of a cache entry, the command usage is as follows:

exists-in-cache <Scope: repository|execution> <key>

If a file exists, the command will exit with a zero exit code. If it does not exist, it will exit with a non-zero exit code instead.

Scope

There are two cache scopes repository and execution. A repository-scoped cache entry is visible to all builds of the repository. In contrast, a execution-scoped cache entry is only visible to nodes that run later in the same build. Execution-scoped entries for example allow you to share build artifacts that might be needed later on a node that deploy these artifacts.

Examples

build:
  nodes:
    # In this example, we are using a minimal node.
    some-node:
      commands:
        # Store folder vendor/ with key "dependencies". This means all nodes use the same
        # cache for dependencies across all branches.
        - store-in-cache repository "dependencies" vendor/
        - restore-from-cache repository "dependencies"
        - exists-in-cache repository "dependencies"

        # If you would like to use a different cache per branch, you can make the branch
        # name part of the cache key like this.
        - store-in-cache repository "dependencies-$SCRUTINIZER_BRANCH" vendor/
        - restore-from-cache repository "dependencies-$SCRUTINIZER_BRANCH"
        - exists-in-cache repository "dependencies-$SCRUTINIZER_BRANCH"

        # If you further would like to use a different cache per branch and per node, all
        # we need to do is to add the node name to the cache key, too.
        - store-in-cache repository "dependencies-$SCRUTINIZER_BRANCH-$SCRUTINIZER_NODE_NAME" vendor/
        - restore-from-cache repository "dependencies-$SCRUTINIZER_BRANCH-$SCRUTINIZER_NODE_NAME"
        - exists-in-cache repository "dependencies-$SCRUTINIZER_BRANCH-$SCRUTINIZER_NODE_NAME"

        # The storing command is a regular system command, so you can use any environment
        # variables or the output of other commands to make up the cache key. For example,
        # if you wanted to automatically invalidate the cache if a certain file like a lock file
        # changes, this could look like this:
        - store-in-cache repository "dependencies-$(sha1sum some.lock | awk '{print $1}')" vendor/
        - restore-from-cache repository "dependencies-$(sha1sum some.lock | awk '{print $1}')"
        - exists-in-cache repository "dependencies-$(sha1sum some.lock | awk '{print $1}')"