Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds opt-in caching #23

Merged
merged 4 commits into from May 19, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
22 changes: 22 additions & 0 deletions README.md
Expand Up @@ -56,6 +56,28 @@ jobs:
arch: x86-64
```

### Caching

This action can use [actions/cache](https://github.com/actions/cache) under the hood. Caching needs to be enabled explicitly and only works for specific tags.

```yaml
# ...
jobs:
my_job:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Github token scoped to job
steps:
- name: Install tf2pulumi
uses: jaxxstorm/action-install-gh-release@v1.5.0
with: # Grab a specific tag with caching
repo: pulumi/tf2pulumi
tag: v0.7.0
cache: enable
```

Caching helps avoid
[Rate limiting](https://docs.github.com/en/rest/overview/resources-in-the-rest-api#requests-from-github-actions), since this action does not need to scan tags and releases on a cache hit. Caching currently is not expected to speed up installation.

## Finding a release

By default, this action will lookup the Platform and Architecture of the runner and use those values to interpolate and match a release package. **The release package name is first converted to lowercase**. The match pattern is:
Expand Down
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -19,6 +19,7 @@
"@actions/github": "^5.0.1",
"@actions/tool-cache": "^1.7.1",
"@octokit/plugin-throttling": "^3.6.2",
"cache": "github:actions/cache",
"minimist": "^1.2.6",
"mkdirp-promise": "^5.0.1",
"node-fetch": "^2.6.7"
Expand Down
70 changes: 66 additions & 4 deletions src/main.ts
@@ -1,11 +1,22 @@
import * as os from "os";
import * as path from "path";

import * as cache from "@actions/cache";
import * as core from "@actions/core";
import * as tc from "@actions/tool-cache";
import { GitHub, getOctokitOptions} from "@actions/github/lib/utils";
import * as os from "os";
import { throttling } from "@octokit/plugin-throttling";

const ThrottlingOctokit = GitHub.plugin(throttling);

interface ToolInfo {
owner: string;
project: string;
tag: string;
osPlatform: string;
osArch: string;
}

async function run() {
try {

Expand Down Expand Up @@ -50,6 +61,10 @@ async function run() {
)
}

const cacheEnabled = (core.getInput("cache") === "enable")
&& tag !== "latest"
&& tag !== "";

const [owner, project] = repo.split("/")

let osMatch : string[] = []
Expand Down Expand Up @@ -94,6 +109,26 @@ async function run() {
core.info(`==> System reported arch: ${os.arch()}`)
core.info(`==> Using arch: ${osArch}`)

let toolInfo: ToolInfo = {
owner: owner,
project: project,
tag: tag,
osArch: osArch,
osPlatform: osPlatform
};
let dest = toolPath(toolInfo);

// Look in the cache first.
let cacheKey = cachePrimaryKey(toolInfo);
if (cacheEnabled && cacheKey !== undefined) {
let ok = await cache.restoreCache([dest], cacheKey);
if (ok !== undefined) {
core.info(`Found ${project} in the cache: ${dest}`)
core.addPath(dest);
return;
}
}

let getReleaseUrl;
if (tag === "latest") {
getReleaseUrl = await octokit.rest.repos.getLatestRelease({
Expand Down Expand Up @@ -129,10 +164,14 @@ async function run() {

core.info(`Downloading ${project} from ${url}`)
const binPath = await tc.downloadTool(url);
const extractedPath = await extractFn(binPath);
core.info(`Successfully extracted ${project} to ${extractedPath}`)
await extractFn(binPath, dest);

core.addPath(extractedPath);
if (cacheEnabled && cacheKey !== undefined) {
await cache.saveCache([dest], cacheKey);
}

core.addPath(dest);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a change here even when not opting into the cache, the path where the tool is installed is changing from a random UUID path to a path under hostedtoolcache (RUNNER_TOOL_CACHE) based on owner, repo, version, architecture (dest var). I think this should be ok. hostedtoolcache is not preserved across GHA worker runs but may be preserved across self-hosted runs.

core.info(`Successfully extracted ${project} to ${dest}`)
} catch (error) {
if (error instanceof Error) {
core.setFailed(error.message);
Expand All @@ -142,6 +181,29 @@ async function run() {
}
}

function cachePrimaryKey(info: ToolInfo): string|undefined {
// Currently not caching "latest" verisons of the tool.
if (info.tag === "latest") {
return undefined;
}
return "action-install-gh-release/" +
`${info.owner}/${info.project}/${info.tag}/${info.osPlatform}-${info.osArch}`;
}

function toolPath(info: ToolInfo): string {
return path.join(getCacheDirectory(),
info.owner, info.project, info.tag,
`${info.osPlatform}-${info.osArch}`);
}

function getCacheDirectory() {
const cacheDirectory = process.env['RUNNER_TOOL_CACHE'] || '';
if (cacheDirectory === '') {
core.warning('Expected RUNNER_TOOL_CACHE to be defined');
}
return cacheDirectory;
}

function getExtractFn(assetName: any) {
if (assetName.endsWith('.tar.gz')) {
return tc.extractTar;
Expand Down