integrate the cache logic to entry points

This commit is contained in:
Kengo TODA 2021-07-13 09:04:54 +08:00
parent fef7d5836a
commit 4a7bf9903c
8 changed files with 116152 additions and 578 deletions

88
.github/workflows/e2e-cache.yml vendored Normal file
View file

@ -0,0 +1,88 @@
name: Validate cache
on:
push:
branches:
- main
- releases/*
paths-ignore:
- '**.md'
pull_request:
paths-ignore:
- '**.md'
defaults:
run:
shell: bash
jobs:
save:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [macos-latest, windows-latest, ubuntu-latest]
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Run setup-java with the cache for gradle
uses: ./
id: setup-java
with:
distribution: 'adopt'
java-version: '11'
cache: gradle
- name: Create files to cache
run: |
cat <<EOF > build.gradle
plugins { id 'java' }
repositories { mavenCentral() }
dependencies { implementation 'org.codehaus.groovy:groovy:1.8.6' }
tasks.register('downloadDependencies') { doLast {
def total = configurations.compileClasspath.inject (0) { sum, file ->
sum + file.length()
}
println total
}}
EOF
gradle downloadDependencies
if [ ! -d ~/.gradle/caches ]; then
echo "::error::The ~/.gradle/caches directory does not exist unexpectedly"
exit 1
fi
restore:
runs-on: ubuntu-latest
needs: save
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Create build.gradle
run: |
cat <<EOF > build.gradle
plugins { id 'java' }
repositories { mavenCentral() }
dependencies { implementation 'org.codehaus.groovy:groovy:1.8.6' }
tasks.register('downloadDependencies') { doLast {
def total = configurations.compileClasspath.inject (0) { sum, file ->
sum + file.length()
}
println total
}}
EOF
if [ -d ~/.gradle/caches ]; then
echo "::error::The ~/.gradle/caches directory exists unexpectedly"
exit 1
fi
- name: Run setup-java with the cache for gradle
uses: ./
id: setup-java
with:
distribution: 'adopt'
java-version: '11'
cache: gradle
- name: Confirm that ~/.gradle/caches directory has been made
run: |
if [ ! -d ~/.gradle/caches ]; then
echo "::error::The ~/.gradle/caches directory does not exist unexpectedly"
exit 1
fi
ls ~/.gradle/caches/

View file

@ -0,0 +1,51 @@
import { mkdtempSync } from 'fs';
import { tmpdir } from 'os';
import { join } from 'path';
import { restore, save } from '../src/cache';
import { run as cleanup } from '../src/cleanup-java';
import * as fs from 'fs';
import * as os from 'os';
import * as core from '@actions/core';
import * as cache from '@actions/cache';
describe('cleanup', () => {
let spyInfo: jest.SpyInstance<void, Parameters<typeof core.info>>;
let spyWarning: jest.SpyInstance<void, Parameters<typeof core.warning>>;
let spyCacheSave: jest.SpyInstance<
ReturnType<typeof cache.saveCache>,
Parameters<typeof cache.saveCache>
>;
beforeEach(() => {
spyInfo = jest.spyOn(core, 'info');
spyWarning = jest.spyOn(core, 'warning');
spyCacheSave = jest.spyOn(cache, 'saveCache');
});
it('does not fail nor warn even when the save provess throws a ReserveCacheError', async () => {
spyCacheSave.mockImplementation((paths: string[], key: string) =>
Promise.reject(
new cache.ReserveCacheError(
'Unable to reserve cache with key, another job may be creating this cache.'
)
)
);
jest.spyOn(core, 'getInput').mockImplementation((name: string) => {
return name === 'cache' ? 'gradle' : '';
});
await cleanup();
expect(spyCacheSave).toBeCalled();
expect(spyWarning).not.toBeCalled();
});
it('does not fail even though the save process throws error', async () => {
spyCacheSave.mockImplementation((paths: string[], key: string) =>
Promise.reject(new Error('Unexpected error'))
);
jest.spyOn(core, 'getInput').mockImplementation((name: string) => {
return name === 'cache' ? 'gradle' : '';
});
await cleanup();
expect(spyCacheSave).toBeCalled();
});
});

View file

@ -53,6 +53,9 @@ inputs:
description: 'Environment variable name for the GPG private key passphrase. Default is
$GPG_PASSPHRASE.'
required: false
cache:
description: 'Name of the build platform to cache dependencies. It can be "maven" or "gradle".'
required: false
outputs:
distribution:
description: 'Distribution of Java that has been installed'

58368
dist/cleanup/index.js vendored

File diff suppressed because one or more lines are too long

58159
dist/setup/index.js vendored

File diff suppressed because one or more lines are too long

View file

@ -1,8 +1,9 @@
import * as core from '@actions/core';
import * as gpg from './gpg';
import * as constants from './constants';
import { save } from './cache';
async function run() {
async function removePrivateKeyFromKeychain() {
if (core.getInput(constants.INPUT_GPG_PRIVATE_KEY, { required: false })) {
core.info('Removing private key from keychain');
try {
@ -14,4 +15,39 @@ async function run() {
}
}
run();
/**
* Check given input and run a save process for the specified package manager
* @returns Promise that will be resolved when the save process finishes
*/
async function saveCache() {
const cache = core.getInput(constants.INPUT_CACHE);
return cache ? save(cache) : Promise.resolve();
}
/**
* The save process is best-effort, and it should not make the workflow failed
* even though this process throws an error.
* @param promise the promise to ignore error from
* @returns Promise that will ignore error reported by the given promise
*/
async function ignoreError(promise: Promise<void>) {
return new Promise(resolve => {
promise
.catch(error => {
core.warning(error);
resolve(void 0);
})
.then(resolve);
});
}
export async function run() {
await Promise.all([removePrivateKeyFromKeychain(), ignoreError(saveCache())]);
}
if (require.main === module) {
run();
} else {
// https://nodejs.org/api/modules.html#modules_accessing_the_main_module
core.info('the script is loaded as a module, so skipping the execution');
}

View file

@ -16,4 +16,6 @@ export const INPUT_GPG_PASSPHRASE = 'gpg-passphrase';
export const INPUT_DEFAULT_GPG_PRIVATE_KEY = undefined;
export const INPUT_DEFAULT_GPG_PASSPHRASE = 'GPG_PASSPHRASE';
export const INPUT_CACHE = 'cache';
export const STATE_GPG_PRIVATE_KEY_FINGERPRINT = 'gpg-private-key-fingerprint';

View file

@ -2,6 +2,7 @@ import * as core from '@actions/core';
import * as auth from './auth';
import { getBooleanInput } from './util';
import * as constants from './constants';
import { restore } from './cache';
import * as path from 'path';
import { getJavaDistribution } from './distributions/distribution-factory';
import { JavaInstallerOptions } from './distributions/base-models';
@ -13,6 +14,7 @@ async function run() {
const architecture = core.getInput(constants.INPUT_ARCHITECTURE);
const packageType = core.getInput(constants.INPUT_JAVA_PACKAGE);
const jdkFile = core.getInput(constants.INPUT_JDK_FILE);
const cache = core.getInput(constants.INPUT_CACHE);
const checkLatest = getBooleanInput(constants.INPUT_CHECK_LATEST, false);
const installerOptions: JavaInstallerOptions = {
@ -27,6 +29,7 @@ async function run() {
throw new Error(`No supported distribution was found for input ${distributionName}`);
}
const restoreResult = cache ? restore(cache) : Promise.resolve();
const result = await distribution.setupJava();
core.info('');
@ -39,7 +42,7 @@ async function run() {
const matchersPath = path.join(__dirname, '..', '..', '.github');
core.info(`##[add-matcher]${path.join(matchersPath, 'java.json')}`);
await auth.configureAuthentication();
await Promise.all([restoreResult, auth.configureAuthentication()]);
} catch (error) {
core.setFailed(error.message);
}