Artifacts in GitHub Actions pass data to a subsequent job or store data or compiled binaries once the workflow is completed. Persisted data in one job can be passed to another subsequent job, which may be running on a different operating system. This is an advantage of using artifacts. The retention period of artifacts in GitHub Actions workflows in 90 days by default; however, you have the option to change these settings, which is discussed later in this chapter.
Reusable files can be cached, which considerably reduces the execution time of a GitHub Actions workflow. However, any secrets or files containing secrets should not be added to the cache because the cache can be pulled from a forked repo.
This chapters explains how to use artifacts and caches.
Storing Content in Artifacts
When you execute a build or test run in a GitHub Actions workflow, it generates binaries and test results as the output of the workflow. These items may be stored for the next jobs in the same workflow. GitHub storage is utilized to store artifacts. Usage is free for public repos and self-hosted runners (discussed in Chapter 6). Private repos have limitations on storage and the number of minutes to run actions.
You can download artifacts from a workflow once it is completed (see Figure 5-1).
Figure 5-1
Artifacts
Using artifacts from another workflow is ideal for implementing a better CI/CD experience. However, sharing artifacts between workflows is not a built-in feature (as of writing this book). One of the GitHub Actions issues (in the community where GitHub issues are discussed) mentioned that sharing artifacts between workflows would be implemented sooner, and if such sharing of artifacts between workflows is implmented that would be ideal for implementing proper CI CD workflows in GitHub Actions.
To upload an artifact, use the “Upload a Build Artifact” action in GitHub. You can also download artifacts and delete artifact tasks in a workflow (see Figure 5-2).
Figure 5-2
Artifact actions
The code for uploading an artifact action is shown in the following example. Artifacts and log files can remain in a workflow for a maximum of 90 days and a minimum of one day. The default retention period is 90 days.
- name: Upload a Build Artifact
uses: actions/upload-artifact@v2.2.0
with:
# Artifact name
name: myartifact2 # optional, default is artifact
# A file, directory or wildcard pattern that describes what to upload
# The desired behavior if no files are found using the provided path.
#Available Options:
# warn: Output a warning but do not fail the action
# error: Fail the action with an error message
# ignore: Do not output any warnings or errors, the action does not fail
if-no-files-found: error # optional, default is warn
# Duration after which artifact will expire in days. 0 means using default retention.
# Minimum 1 day. Maximum 90 days unless changed from the repository settings page.
retention-days: 90 # optional
If you want to change the retention period to more than 90 days for private, internal or GitHub enterprise you can set the value to maximum of 400 days.
Let’s look at an example scenario where artifacts must be passed to another job in the workflow. Android build steps are done on a macOS runner. The build APK is deployed to the Microsoft App Center using a Windows runner for distribution purposes. Once you complete the build, you can upload the APK as an artifact in the workflow, and then download it to the Windows runner job, and deploy it to the app center. Note the following example pipeline.
Then, the artifact is downloaded in the next job, using the artifact name.
- uses: actions/download-artifact@v2
with:
name: my-artifact
The download artifact action has the following options. You can provide the name of the artifact and optionally a path to download artifacts. Artifact content is extracted from the specified path.
- name: Download a Build Artifact
uses: actions/download-artifact@v2.0.5
with:
# Artifact name
name: myartifact # optional
# Destination path
path: artifacts # optional
5.02: Cashing Workflow Dependencies
When jobs are executed in GitHub-hosted runners, they always run in a fresh and clean virtual environment. A clean environment demands downloading all required dependencies in each job run, causing longer runtimes for jobs, higher utilization of network bandwidth, and increased costs. Dependencies may include files utilized by package and dependency management tools such as npm, Gradle, yarn.
As a solution, you can use GitHub’s capabilities to cache dependencies. However, you should avoid caching sensitive values in public repositories because forked repos can obtain cached information.
File storing is a common capability of both artifacts and caches; however, each purpose is different, and the use of artifacts and caches are not interchangeable. Caching should store files when they do not change jobs or when the next workflow runs. Artifacts should share files between jobs and when you want to view files after a job run.
The following is a template for the latest version of a cache action.
- name: Cache
uses: actions/cache@v2.1.3
with:
# A list of files, directories, and wildcard patterns to cache and restore
path:
# An explicit key for restoring and saving the cache
key:
# An ordered list of keys to use for restoring the cache if no cache hit occurred for key
restore-keys: # optional
# The chunk size used to split up large files during upload, in bytes
upload-chunk-size: # optional
You can define a list of files, directories or wild card patterns in the cache action which are used to put in cache or restore from cache. Explicit key can be specified to use as the key for restoring or saving the cache. Additionally, a list of keys can be specified to use for restoration of cache items in a case where the cache items cannot be found with the explicit key. The chunk size can be used to define the size of chunks to use, when breaking down a large file to chunks, which is uploading to cache.
An example of caching a node module is shown next.
- name: Cache node modules
uses: actions/cache@v2
env:
cache-name: cache-node-modules
with:
# npm cache files are stored in `~/.npm` on Linux/macOS
The path is ~/.npm. It is the path for Linux and macOS npm cache files. If you use this in a pipeline implemented to build a node project, the build steps with caching are similar to the following.
name: Node.js CI
on: [workflow_dispatch]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Cache node modules
uses: actions/cache@v2
env:
cache-name: cache-node-modules
with:
# npm cache files are stored in `~/.npm` on Linux/macOS
When you execute the workflow for the first time, there is no cache available in the repo, so the files are stored in the cache (see Figure 5-3).
Figure 5-3
Cache node modules
In subsequent runs, the cached files are used, and since the cache is available, the pipeline does not save the cache again (see Figure 5-4).
Figure 5-4
Using cache
GitHub’s policy is to remove cached files not accessed for seven days. You can create many caches; however, there is a 5 GB size limit for all caches in the repository. If you add more than 5 GB, GitHub removes caches to bring down the cached file size to under 5 GB.
Summary
This chapter discussed using artifacts in GitHub Actions to share files between workflow jobs and to view or download file output in a workflow. It also explored caching files for workflow execution.
The next chapter discusses self-hosted runner setups in GitHub Actions so to execute workflows on your machines or virtual machines.