mirror of
https://github.com/gradle/gradle-build-action.git
synced 2024-12-25 14:56:18 +08:00
Merge pull request #298 from gradle/job-summary-table
Add improved Job Summary with build results and caching report
This commit is contained in:
commit
d3a78eb55f
200
dist/main/index.js
vendored
200
dist/main/index.js
vendored
@ -64910,8 +64910,10 @@ class GradleStateCache {
|
|||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
const cacheKey = (0, cache_utils_1.generateCacheKey)(this.cacheName).key;
|
const cacheKey = (0, cache_utils_1.generateCacheKey)(this.cacheName).key;
|
||||||
const restoredCacheKey = core.getState(RESTORED_CACHE_KEY_KEY);
|
const restoredCacheKey = core.getState(RESTORED_CACHE_KEY_KEY);
|
||||||
|
const entryListener = listener.entry(this.cacheDescription);
|
||||||
if (restoredCacheKey && cacheKey === restoredCacheKey) {
|
if (restoredCacheKey && cacheKey === restoredCacheKey) {
|
||||||
core.info(`Cache hit occurred on the cache key ${cacheKey}, not saving cache.`);
|
core.info(`Cache hit occurred on the cache key ${cacheKey}, not saving cache.`);
|
||||||
|
entryListener.markUnchanged('cache key not changed');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
@ -64923,7 +64925,6 @@ class GradleStateCache {
|
|||||||
}
|
}
|
||||||
core.info(`Caching ${this.cacheDescription} with cache key: ${cacheKey}`);
|
core.info(`Caching ${this.cacheDescription} with cache key: ${cacheKey}`);
|
||||||
const cachePath = this.getCachePath();
|
const cachePath = this.getCachePath();
|
||||||
const entryListener = listener.entry(this.cacheDescription);
|
|
||||||
yield (0, cache_utils_1.saveCache)(cachePath, cacheKey, entryListener);
|
yield (0, cache_utils_1.saveCache)(cachePath, cacheKey, entryListener);
|
||||||
return;
|
return;
|
||||||
});
|
});
|
||||||
@ -65155,6 +65156,7 @@ class AbstractEntryExtractor {
|
|||||||
const previouslyRestoredKey = (_a = previouslyRestoredEntries.find(x => x.artifactType === artifactType && x.pattern === pattern)) === null || _a === void 0 ? void 0 : _a.cacheKey;
|
const previouslyRestoredKey = (_a = previouslyRestoredEntries.find(x => x.artifactType === artifactType && x.pattern === pattern)) === null || _a === void 0 ? void 0 : _a.cacheKey;
|
||||||
if (previouslyRestoredKey === cacheKey) {
|
if (previouslyRestoredKey === cacheKey) {
|
||||||
(0, cache_utils_1.cacheDebug)(`No change to previously restored ${artifactType}. Not saving.`);
|
(0, cache_utils_1.cacheDebug)(`No change to previously restored ${artifactType}. Not saving.`);
|
||||||
|
entryListener.markUnchanged('contents unchanged');
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
core.info(`Caching ${artifactType} with path '${pattern}' and cache key: ${cacheKey}`);
|
core.info(`Caching ${artifactType} with path '${pattern}' and cache key: ${cacheKey}`);
|
||||||
@ -65334,6 +65336,8 @@ const core = __importStar(__nccwpck_require__(2186));
|
|||||||
class CacheListener {
|
class CacheListener {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.cacheEntries = [];
|
this.cacheEntries = [];
|
||||||
|
this.isCacheReadOnly = false;
|
||||||
|
this.isCacheWriteOnly = false;
|
||||||
}
|
}
|
||||||
get fullyRestored() {
|
get fullyRestored() {
|
||||||
return this.cacheEntries.every(x => !x.wasRequestedButNotRestored());
|
return this.cacheEntries.every(x => !x.wasRequestedButNotRestored());
|
||||||
@ -65392,38 +65396,89 @@ class CacheEntryListener {
|
|||||||
this.savedSize = 0;
|
this.savedSize = 0;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
markUnchanged(message) {
|
||||||
|
this.unchanged = message;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
exports.CacheEntryListener = CacheEntryListener;
|
exports.CacheEntryListener = CacheEntryListener;
|
||||||
function logCachingReport(listener) {
|
function logCachingReport(listener) {
|
||||||
var _a, _b, _c;
|
|
||||||
if (listener.cacheEntries.length === 0) {
|
if (listener.cacheEntries.length === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
core.info(`---------- Caching Summary -------------
|
core.summary.addHeading('Gradle Home Caching Summary', 3);
|
||||||
Restored Entries Count: ${getCount(listener.cacheEntries, e => e.restoredSize)}
|
const entries = listener.cacheEntries
|
||||||
Size: ${getSum(listener.cacheEntries, e => e.restoredSize)}
|
.map(entry => {
|
||||||
Saved Entries Count: ${getCount(listener.cacheEntries, e => e.savedSize)}
|
var _a, _b, _c;
|
||||||
Size: ${getSum(listener.cacheEntries, e => e.savedSize)}`);
|
return `Entry: ${entry.entryName}
|
||||||
core.startGroup('Cache Entry details');
|
|
||||||
for (const entry of listener.cacheEntries) {
|
|
||||||
core.info(`Entry: ${entry.entryName}
|
|
||||||
Requested Key : ${(_a = entry.requestedKey) !== null && _a !== void 0 ? _a : ''}
|
Requested Key : ${(_a = entry.requestedKey) !== null && _a !== void 0 ? _a : ''}
|
||||||
Restored Key : ${(_b = entry.restoredKey) !== null && _b !== void 0 ? _b : ''}
|
Restored Key : ${(_b = entry.restoredKey) !== null && _b !== void 0 ? _b : ''}
|
||||||
Size: ${formatSize(entry.restoredSize)}
|
Size: ${formatSize(entry.restoredSize)}
|
||||||
|
${getRestoredMessage(entry, listener.isCacheWriteOnly)}
|
||||||
Saved Key : ${(_c = entry.savedKey) !== null && _c !== void 0 ? _c : ''}
|
Saved Key : ${(_c = entry.savedKey) !== null && _c !== void 0 ? _c : ''}
|
||||||
Size: ${formatSize(entry.savedSize)}`);
|
Size: ${formatSize(entry.savedSize)}
|
||||||
|
${getSavedMessage(entry, listener.isCacheReadOnly)}
|
||||||
|
---`;
|
||||||
|
})
|
||||||
|
.join('\n');
|
||||||
|
core.summary.addRaw(`
|
||||||
|
|
||||||
|
| | Count | Size (Mb) | Size (B) |
|
||||||
|
| - | -: | -: | -: |
|
||||||
|
| Restored | ${getCount(listener.cacheEntries, e => e.restoredSize)} | ${getMegaBytes(listener.cacheEntries, e => e.restoredSize)} | ${getBytes(listener.cacheEntries, e => e.restoredSize)} |
|
||||||
|
| Saved | ${getCount(listener.cacheEntries, e => e.savedSize)} | ${getMegaBytes(listener.cacheEntries, e => e.savedSize)} | ${getBytes(listener.cacheEntries, e => e.savedSize)} |
|
||||||
|
|
||||||
|
`);
|
||||||
|
if (listener.isCacheReadOnly) {
|
||||||
|
core.summary.addRaw('- **Cache is read-only**\n');
|
||||||
}
|
}
|
||||||
core.endGroup();
|
if (listener.isCacheWriteOnly) {
|
||||||
|
core.summary.addRaw('- **Cache is write-only**\n');
|
||||||
|
}
|
||||||
|
core.summary.addDetails('Cache Entry Details', `
|
||||||
|
<pre>
|
||||||
|
${entries}
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
`);
|
||||||
}
|
}
|
||||||
exports.logCachingReport = logCachingReport;
|
exports.logCachingReport = logCachingReport;
|
||||||
|
function getRestoredMessage(entry, isCacheWriteOnly) {
|
||||||
|
if (isCacheWriteOnly) {
|
||||||
|
return '(Entry not restored: cache is write-only)';
|
||||||
|
}
|
||||||
|
if (entry.restoredKey === undefined) {
|
||||||
|
return '(Entry not restored: no match found)';
|
||||||
|
}
|
||||||
|
if (entry.restoredKey === entry.requestedKey) {
|
||||||
|
return '(Entry restored: exact match found)';
|
||||||
|
}
|
||||||
|
return '(Entry restored: partial match found)';
|
||||||
|
}
|
||||||
|
function getSavedMessage(entry, isCacheReadOnly) {
|
||||||
|
if (entry.unchanged) {
|
||||||
|
return `(Entry not saved: ${entry.unchanged})`;
|
||||||
|
}
|
||||||
|
if (entry.savedKey === undefined) {
|
||||||
|
if (isCacheReadOnly) {
|
||||||
|
return '(Entry not saved: cache is read-only)';
|
||||||
|
}
|
||||||
|
return '(Entry not saved: reason unknown)';
|
||||||
|
}
|
||||||
|
if (entry.savedSize === 0) {
|
||||||
|
return '(Entry not saved: entry with key already exists)';
|
||||||
|
}
|
||||||
|
return '(Entry saved)';
|
||||||
|
}
|
||||||
function getCount(cacheEntries, predicate) {
|
function getCount(cacheEntries, predicate) {
|
||||||
return cacheEntries.filter(e => predicate(e) !== undefined).length;
|
return cacheEntries.filter(e => predicate(e) !== undefined).length;
|
||||||
}
|
}
|
||||||
function getSum(cacheEntries, predicate) {
|
function getBytes(cacheEntries, predicate) {
|
||||||
if (cacheEntries.length === 0) {
|
return cacheEntries.map(e => { var _a; return (_a = predicate(e)) !== null && _a !== void 0 ? _a : 0; }).reduce((p, v) => p + v, 0);
|
||||||
return '0';
|
|
||||||
}
|
}
|
||||||
return formatSize(cacheEntries.map(e => { var _a; return (_a = predicate(e)) !== null && _a !== void 0 ? _a : 0; }).reduce((p, v) => p + v, 0));
|
function getMegaBytes(cacheEntries, predicate) {
|
||||||
|
const bytes = getBytes(cacheEntries, predicate);
|
||||||
|
return Math.round(bytes / (1024 * 1024));
|
||||||
}
|
}
|
||||||
function formatSize(bytes) {
|
function formatSize(bytes) {
|
||||||
if (bytes === undefined) {
|
if (bytes === undefined) {
|
||||||
@ -65696,11 +65751,9 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|||||||
exports.save = exports.restore = void 0;
|
exports.save = exports.restore = void 0;
|
||||||
const core = __importStar(__nccwpck_require__(2186));
|
const core = __importStar(__nccwpck_require__(2186));
|
||||||
const cache_utils_1 = __nccwpck_require__(1678);
|
const cache_utils_1 = __nccwpck_require__(1678);
|
||||||
const cache_reporting_1 = __nccwpck_require__(6674);
|
|
||||||
const cache_base_1 = __nccwpck_require__(7591);
|
const cache_base_1 = __nccwpck_require__(7591);
|
||||||
const CACHE_RESTORED_VAR = 'GRADLE_BUILD_ACTION_CACHE_RESTORED';
|
const CACHE_RESTORED_VAR = 'GRADLE_BUILD_ACTION_CACHE_RESTORED';
|
||||||
const CACHE_LISTENER = 'CACHE_LISTENER';
|
function restore(gradleUserHome, cacheListener) {
|
||||||
function restore(gradleUserHome) {
|
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
if (process.env[CACHE_RESTORED_VAR]) {
|
if (process.env[CACHE_RESTORED_VAR]) {
|
||||||
core.info('Cache only restored on first action step.');
|
core.info('Cache only restored on first action step.');
|
||||||
@ -65722,31 +65775,28 @@ function restore(gradleUserHome) {
|
|||||||
core.saveState(CACHE_RESTORED_VAR, true);
|
core.saveState(CACHE_RESTORED_VAR, true);
|
||||||
if ((0, cache_utils_1.isCacheWriteOnly)()) {
|
if ((0, cache_utils_1.isCacheWriteOnly)()) {
|
||||||
core.info('Cache is write-only: will not restore from cache.');
|
core.info('Cache is write-only: will not restore from cache.');
|
||||||
|
cacheListener.isCacheWriteOnly = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
yield core.group('Restore Gradle state from cache', () => __awaiter(this, void 0, void 0, function* () {
|
yield core.group('Restore Gradle state from cache', () => __awaiter(this, void 0, void 0, function* () {
|
||||||
const cacheListener = new cache_reporting_1.CacheListener();
|
|
||||||
yield gradleStateCache.restore(cacheListener);
|
yield gradleStateCache.restore(cacheListener);
|
||||||
core.saveState(CACHE_LISTENER, cacheListener.stringify());
|
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
exports.restore = restore;
|
exports.restore = restore;
|
||||||
function save(gradleUserHome) {
|
function save(gradleUserHome, cacheListener) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
if (!shouldSaveCaches()) {
|
if (!shouldSaveCaches()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const cacheListener = cache_reporting_1.CacheListener.rehydrate(core.getState(CACHE_LISTENER));
|
|
||||||
if ((0, cache_utils_1.isCacheReadOnly)()) {
|
if ((0, cache_utils_1.isCacheReadOnly)()) {
|
||||||
core.info('Cache is read-only: will not save state for use in subsequent builds.');
|
core.info('Cache is read-only: will not save state for use in subsequent builds.');
|
||||||
(0, cache_reporting_1.logCachingReport)(cacheListener);
|
cacheListener.isCacheReadOnly = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
yield core.group('Caching Gradle state', () => __awaiter(this, void 0, void 0, function* () {
|
yield core.group('Caching Gradle state', () => __awaiter(this, void 0, void 0, function* () {
|
||||||
return new cache_base_1.GradleStateCache(gradleUserHome).save(cacheListener);
|
return new cache_base_1.GradleStateCache(gradleUserHome).save(cacheListener);
|
||||||
}));
|
}));
|
||||||
(0, cache_reporting_1.logCachingReport)(cacheListener);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
exports.save = save;
|
exports.save = save;
|
||||||
@ -65894,6 +65944,93 @@ function validateGradleWrapper(buildRootDirectory) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ 7345:
|
||||||
|
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||||
|
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||||
|
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||||
|
}
|
||||||
|
Object.defineProperty(o, k2, desc);
|
||||||
|
}) : (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
o[k2] = m[k];
|
||||||
|
}));
|
||||||
|
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||||
|
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||||
|
}) : function(o, v) {
|
||||||
|
o["default"] = v;
|
||||||
|
});
|
||||||
|
var __importStar = (this && this.__importStar) || function (mod) {
|
||||||
|
if (mod && mod.__esModule) return mod;
|
||||||
|
var result = {};
|
||||||
|
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||||
|
__setModuleDefault(result, mod);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||||
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||||
|
exports.writeJobSummary = void 0;
|
||||||
|
const core = __importStar(__nccwpck_require__(2186));
|
||||||
|
const fs_1 = __importDefault(__nccwpck_require__(7147));
|
||||||
|
const path_1 = __importDefault(__nccwpck_require__(1017));
|
||||||
|
const cache_reporting_1 = __nccwpck_require__(6674);
|
||||||
|
function writeJobSummary(cacheListener) {
|
||||||
|
core.info('Writing job summary...');
|
||||||
|
const buildResults = loadBuildResults();
|
||||||
|
if (buildResults.length === 0) {
|
||||||
|
core.debug('No Gradle build results found. Summary table will not be generated.');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
core.info('Writing summary table');
|
||||||
|
writeSummaryTable(buildResults);
|
||||||
|
}
|
||||||
|
core.info('Writing cache report...');
|
||||||
|
(0, cache_reporting_1.logCachingReport)(cacheListener);
|
||||||
|
core.summary.write();
|
||||||
|
}
|
||||||
|
exports.writeJobSummary = writeJobSummary;
|
||||||
|
function loadBuildResults() {
|
||||||
|
const buildResultsDir = path_1.default.resolve(process.env['RUNNER_TEMP'], '.build-results');
|
||||||
|
if (!fs_1.default.existsSync(buildResultsDir)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return fs_1.default.readdirSync(buildResultsDir).map(file => {
|
||||||
|
const filePath = path_1.default.join(buildResultsDir, file);
|
||||||
|
const content = fs_1.default.readFileSync(filePath, 'utf8');
|
||||||
|
return JSON.parse(content);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function writeSummaryTable(results) {
|
||||||
|
core.summary.addRaw('\n');
|
||||||
|
core.summary.addHeading('Gradle Builds', 3);
|
||||||
|
core.summary.addRaw('\n| Root Project | Tasks | Gradle Version | Outcome |\n| - | - | - | - |\n');
|
||||||
|
for (const result of results) {
|
||||||
|
const tableRow = `| ${result.rootProject} \
|
||||||
|
| ${result.requestedTasks} \
|
||||||
|
| ${result.gradleVersion} \
|
||||||
|
| ${renderOutcome(result)} \
|
||||||
|
|\n`;
|
||||||
|
core.summary.addRaw(tableRow);
|
||||||
|
}
|
||||||
|
core.summary.addRaw('\n');
|
||||||
|
}
|
||||||
|
function renderOutcome(result) {
|
||||||
|
if (result.buildScanUri) {
|
||||||
|
return `[![Gradle Build](https://img.shields.io/badge/Build%20Scan%E2%84%A2-${result.buildFailed ? 'FAILED-red' : 'SUCCESS-brightgreen'}?logo=Gradle)](${result.buildScanUri})`;
|
||||||
|
}
|
||||||
|
return `![Gradle Build](https://img.shields.io/badge/${result.buildFailed ? 'FAILED-red' : 'SUCCESS-brightgreen'}?logo=Gradle)`;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
|
|
||||||
/***/ 399:
|
/***/ 399:
|
||||||
@ -66239,8 +66376,11 @@ const core = __importStar(__nccwpck_require__(2186));
|
|||||||
const path = __importStar(__nccwpck_require__(1017));
|
const path = __importStar(__nccwpck_require__(1017));
|
||||||
const os = __importStar(__nccwpck_require__(2037));
|
const os = __importStar(__nccwpck_require__(2037));
|
||||||
const caches = __importStar(__nccwpck_require__(3800));
|
const caches = __importStar(__nccwpck_require__(3800));
|
||||||
|
const cache_reporting_1 = __nccwpck_require__(6674);
|
||||||
|
const job_summary_1 = __nccwpck_require__(7345);
|
||||||
const GRADLE_SETUP_VAR = 'GRADLE_BUILD_ACTION_SETUP_COMPLETED';
|
const GRADLE_SETUP_VAR = 'GRADLE_BUILD_ACTION_SETUP_COMPLETED';
|
||||||
const GRADLE_USER_HOME = 'GRADLE_USER_HOME';
|
const GRADLE_USER_HOME = 'GRADLE_USER_HOME';
|
||||||
|
const CACHE_LISTENER = 'CACHE_LISTENER';
|
||||||
function setup(buildRootDirectory) {
|
function setup(buildRootDirectory) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
const gradleUserHome = determineGradleUserHome(buildRootDirectory);
|
const gradleUserHome = determineGradleUserHome(buildRootDirectory);
|
||||||
@ -66251,18 +66391,24 @@ function setup(buildRootDirectory) {
|
|||||||
core.exportVariable(GRADLE_SETUP_VAR, true);
|
core.exportVariable(GRADLE_SETUP_VAR, true);
|
||||||
core.saveState(GRADLE_SETUP_VAR, true);
|
core.saveState(GRADLE_SETUP_VAR, true);
|
||||||
core.saveState(GRADLE_USER_HOME, gradleUserHome);
|
core.saveState(GRADLE_USER_HOME, gradleUserHome);
|
||||||
yield caches.restore(gradleUserHome);
|
const cacheListener = new cache_reporting_1.CacheListener();
|
||||||
|
yield caches.restore(gradleUserHome, cacheListener);
|
||||||
|
core.saveState(CACHE_LISTENER, cacheListener.stringify());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
exports.setup = setup;
|
exports.setup = setup;
|
||||||
function complete() {
|
function complete() {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
core.info('Inside setupGradle.complete()');
|
||||||
if (!core.getState(GRADLE_SETUP_VAR)) {
|
if (!core.getState(GRADLE_SETUP_VAR)) {
|
||||||
core.info('Gradle setup post-action only performed for first gradle-build-action step in workflow.');
|
core.info('Gradle setup post-action only performed for first gradle-build-action step in workflow.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
core.info('In final post-action step, saving state and writing summary');
|
||||||
|
const cacheListener = cache_reporting_1.CacheListener.rehydrate(core.getState(CACHE_LISTENER));
|
||||||
const gradleUserHome = core.getState(GRADLE_USER_HOME);
|
const gradleUserHome = core.getState(GRADLE_USER_HOME);
|
||||||
yield caches.save(gradleUserHome);
|
yield caches.save(gradleUserHome, cacheListener);
|
||||||
|
(0, job_summary_1.writeJobSummary)(cacheListener);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
exports.complete = complete;
|
exports.complete = complete;
|
||||||
|
2
dist/main/index.js.map
vendored
2
dist/main/index.js.map
vendored
File diff suppressed because one or more lines are too long
200
dist/post/index.js
vendored
200
dist/post/index.js
vendored
@ -63961,8 +63961,10 @@ class GradleStateCache {
|
|||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
const cacheKey = (0, cache_utils_1.generateCacheKey)(this.cacheName).key;
|
const cacheKey = (0, cache_utils_1.generateCacheKey)(this.cacheName).key;
|
||||||
const restoredCacheKey = core.getState(RESTORED_CACHE_KEY_KEY);
|
const restoredCacheKey = core.getState(RESTORED_CACHE_KEY_KEY);
|
||||||
|
const entryListener = listener.entry(this.cacheDescription);
|
||||||
if (restoredCacheKey && cacheKey === restoredCacheKey) {
|
if (restoredCacheKey && cacheKey === restoredCacheKey) {
|
||||||
core.info(`Cache hit occurred on the cache key ${cacheKey}, not saving cache.`);
|
core.info(`Cache hit occurred on the cache key ${cacheKey}, not saving cache.`);
|
||||||
|
entryListener.markUnchanged('cache key not changed');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
@ -63974,7 +63976,6 @@ class GradleStateCache {
|
|||||||
}
|
}
|
||||||
core.info(`Caching ${this.cacheDescription} with cache key: ${cacheKey}`);
|
core.info(`Caching ${this.cacheDescription} with cache key: ${cacheKey}`);
|
||||||
const cachePath = this.getCachePath();
|
const cachePath = this.getCachePath();
|
||||||
const entryListener = listener.entry(this.cacheDescription);
|
|
||||||
yield (0, cache_utils_1.saveCache)(cachePath, cacheKey, entryListener);
|
yield (0, cache_utils_1.saveCache)(cachePath, cacheKey, entryListener);
|
||||||
return;
|
return;
|
||||||
});
|
});
|
||||||
@ -64206,6 +64207,7 @@ class AbstractEntryExtractor {
|
|||||||
const previouslyRestoredKey = (_a = previouslyRestoredEntries.find(x => x.artifactType === artifactType && x.pattern === pattern)) === null || _a === void 0 ? void 0 : _a.cacheKey;
|
const previouslyRestoredKey = (_a = previouslyRestoredEntries.find(x => x.artifactType === artifactType && x.pattern === pattern)) === null || _a === void 0 ? void 0 : _a.cacheKey;
|
||||||
if (previouslyRestoredKey === cacheKey) {
|
if (previouslyRestoredKey === cacheKey) {
|
||||||
(0, cache_utils_1.cacheDebug)(`No change to previously restored ${artifactType}. Not saving.`);
|
(0, cache_utils_1.cacheDebug)(`No change to previously restored ${artifactType}. Not saving.`);
|
||||||
|
entryListener.markUnchanged('contents unchanged');
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
core.info(`Caching ${artifactType} with path '${pattern}' and cache key: ${cacheKey}`);
|
core.info(`Caching ${artifactType} with path '${pattern}' and cache key: ${cacheKey}`);
|
||||||
@ -64385,6 +64387,8 @@ const core = __importStar(__nccwpck_require__(2186));
|
|||||||
class CacheListener {
|
class CacheListener {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.cacheEntries = [];
|
this.cacheEntries = [];
|
||||||
|
this.isCacheReadOnly = false;
|
||||||
|
this.isCacheWriteOnly = false;
|
||||||
}
|
}
|
||||||
get fullyRestored() {
|
get fullyRestored() {
|
||||||
return this.cacheEntries.every(x => !x.wasRequestedButNotRestored());
|
return this.cacheEntries.every(x => !x.wasRequestedButNotRestored());
|
||||||
@ -64443,38 +64447,89 @@ class CacheEntryListener {
|
|||||||
this.savedSize = 0;
|
this.savedSize = 0;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
markUnchanged(message) {
|
||||||
|
this.unchanged = message;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
exports.CacheEntryListener = CacheEntryListener;
|
exports.CacheEntryListener = CacheEntryListener;
|
||||||
function logCachingReport(listener) {
|
function logCachingReport(listener) {
|
||||||
var _a, _b, _c;
|
|
||||||
if (listener.cacheEntries.length === 0) {
|
if (listener.cacheEntries.length === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
core.info(`---------- Caching Summary -------------
|
core.summary.addHeading('Gradle Home Caching Summary', 3);
|
||||||
Restored Entries Count: ${getCount(listener.cacheEntries, e => e.restoredSize)}
|
const entries = listener.cacheEntries
|
||||||
Size: ${getSum(listener.cacheEntries, e => e.restoredSize)}
|
.map(entry => {
|
||||||
Saved Entries Count: ${getCount(listener.cacheEntries, e => e.savedSize)}
|
var _a, _b, _c;
|
||||||
Size: ${getSum(listener.cacheEntries, e => e.savedSize)}`);
|
return `Entry: ${entry.entryName}
|
||||||
core.startGroup('Cache Entry details');
|
|
||||||
for (const entry of listener.cacheEntries) {
|
|
||||||
core.info(`Entry: ${entry.entryName}
|
|
||||||
Requested Key : ${(_a = entry.requestedKey) !== null && _a !== void 0 ? _a : ''}
|
Requested Key : ${(_a = entry.requestedKey) !== null && _a !== void 0 ? _a : ''}
|
||||||
Restored Key : ${(_b = entry.restoredKey) !== null && _b !== void 0 ? _b : ''}
|
Restored Key : ${(_b = entry.restoredKey) !== null && _b !== void 0 ? _b : ''}
|
||||||
Size: ${formatSize(entry.restoredSize)}
|
Size: ${formatSize(entry.restoredSize)}
|
||||||
|
${getRestoredMessage(entry, listener.isCacheWriteOnly)}
|
||||||
Saved Key : ${(_c = entry.savedKey) !== null && _c !== void 0 ? _c : ''}
|
Saved Key : ${(_c = entry.savedKey) !== null && _c !== void 0 ? _c : ''}
|
||||||
Size: ${formatSize(entry.savedSize)}`);
|
Size: ${formatSize(entry.savedSize)}
|
||||||
|
${getSavedMessage(entry, listener.isCacheReadOnly)}
|
||||||
|
---`;
|
||||||
|
})
|
||||||
|
.join('\n');
|
||||||
|
core.summary.addRaw(`
|
||||||
|
|
||||||
|
| | Count | Size (Mb) | Size (B) |
|
||||||
|
| - | -: | -: | -: |
|
||||||
|
| Restored | ${getCount(listener.cacheEntries, e => e.restoredSize)} | ${getMegaBytes(listener.cacheEntries, e => e.restoredSize)} | ${getBytes(listener.cacheEntries, e => e.restoredSize)} |
|
||||||
|
| Saved | ${getCount(listener.cacheEntries, e => e.savedSize)} | ${getMegaBytes(listener.cacheEntries, e => e.savedSize)} | ${getBytes(listener.cacheEntries, e => e.savedSize)} |
|
||||||
|
|
||||||
|
`);
|
||||||
|
if (listener.isCacheReadOnly) {
|
||||||
|
core.summary.addRaw('- **Cache is read-only**\n');
|
||||||
}
|
}
|
||||||
core.endGroup();
|
if (listener.isCacheWriteOnly) {
|
||||||
|
core.summary.addRaw('- **Cache is write-only**\n');
|
||||||
|
}
|
||||||
|
core.summary.addDetails('Cache Entry Details', `
|
||||||
|
<pre>
|
||||||
|
${entries}
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
`);
|
||||||
}
|
}
|
||||||
exports.logCachingReport = logCachingReport;
|
exports.logCachingReport = logCachingReport;
|
||||||
|
function getRestoredMessage(entry, isCacheWriteOnly) {
|
||||||
|
if (isCacheWriteOnly) {
|
||||||
|
return '(Entry not restored: cache is write-only)';
|
||||||
|
}
|
||||||
|
if (entry.restoredKey === undefined) {
|
||||||
|
return '(Entry not restored: no match found)';
|
||||||
|
}
|
||||||
|
if (entry.restoredKey === entry.requestedKey) {
|
||||||
|
return '(Entry restored: exact match found)';
|
||||||
|
}
|
||||||
|
return '(Entry restored: partial match found)';
|
||||||
|
}
|
||||||
|
function getSavedMessage(entry, isCacheReadOnly) {
|
||||||
|
if (entry.unchanged) {
|
||||||
|
return `(Entry not saved: ${entry.unchanged})`;
|
||||||
|
}
|
||||||
|
if (entry.savedKey === undefined) {
|
||||||
|
if (isCacheReadOnly) {
|
||||||
|
return '(Entry not saved: cache is read-only)';
|
||||||
|
}
|
||||||
|
return '(Entry not saved: reason unknown)';
|
||||||
|
}
|
||||||
|
if (entry.savedSize === 0) {
|
||||||
|
return '(Entry not saved: entry with key already exists)';
|
||||||
|
}
|
||||||
|
return '(Entry saved)';
|
||||||
|
}
|
||||||
function getCount(cacheEntries, predicate) {
|
function getCount(cacheEntries, predicate) {
|
||||||
return cacheEntries.filter(e => predicate(e) !== undefined).length;
|
return cacheEntries.filter(e => predicate(e) !== undefined).length;
|
||||||
}
|
}
|
||||||
function getSum(cacheEntries, predicate) {
|
function getBytes(cacheEntries, predicate) {
|
||||||
if (cacheEntries.length === 0) {
|
return cacheEntries.map(e => { var _a; return (_a = predicate(e)) !== null && _a !== void 0 ? _a : 0; }).reduce((p, v) => p + v, 0);
|
||||||
return '0';
|
|
||||||
}
|
}
|
||||||
return formatSize(cacheEntries.map(e => { var _a; return (_a = predicate(e)) !== null && _a !== void 0 ? _a : 0; }).reduce((p, v) => p + v, 0));
|
function getMegaBytes(cacheEntries, predicate) {
|
||||||
|
const bytes = getBytes(cacheEntries, predicate);
|
||||||
|
return Math.round(bytes / (1024 * 1024));
|
||||||
}
|
}
|
||||||
function formatSize(bytes) {
|
function formatSize(bytes) {
|
||||||
if (bytes === undefined) {
|
if (bytes === undefined) {
|
||||||
@ -64747,11 +64802,9 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|||||||
exports.save = exports.restore = void 0;
|
exports.save = exports.restore = void 0;
|
||||||
const core = __importStar(__nccwpck_require__(2186));
|
const core = __importStar(__nccwpck_require__(2186));
|
||||||
const cache_utils_1 = __nccwpck_require__(1678);
|
const cache_utils_1 = __nccwpck_require__(1678);
|
||||||
const cache_reporting_1 = __nccwpck_require__(6674);
|
|
||||||
const cache_base_1 = __nccwpck_require__(7591);
|
const cache_base_1 = __nccwpck_require__(7591);
|
||||||
const CACHE_RESTORED_VAR = 'GRADLE_BUILD_ACTION_CACHE_RESTORED';
|
const CACHE_RESTORED_VAR = 'GRADLE_BUILD_ACTION_CACHE_RESTORED';
|
||||||
const CACHE_LISTENER = 'CACHE_LISTENER';
|
function restore(gradleUserHome, cacheListener) {
|
||||||
function restore(gradleUserHome) {
|
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
if (process.env[CACHE_RESTORED_VAR]) {
|
if (process.env[CACHE_RESTORED_VAR]) {
|
||||||
core.info('Cache only restored on first action step.');
|
core.info('Cache only restored on first action step.');
|
||||||
@ -64773,31 +64826,28 @@ function restore(gradleUserHome) {
|
|||||||
core.saveState(CACHE_RESTORED_VAR, true);
|
core.saveState(CACHE_RESTORED_VAR, true);
|
||||||
if ((0, cache_utils_1.isCacheWriteOnly)()) {
|
if ((0, cache_utils_1.isCacheWriteOnly)()) {
|
||||||
core.info('Cache is write-only: will not restore from cache.');
|
core.info('Cache is write-only: will not restore from cache.');
|
||||||
|
cacheListener.isCacheWriteOnly = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
yield core.group('Restore Gradle state from cache', () => __awaiter(this, void 0, void 0, function* () {
|
yield core.group('Restore Gradle state from cache', () => __awaiter(this, void 0, void 0, function* () {
|
||||||
const cacheListener = new cache_reporting_1.CacheListener();
|
|
||||||
yield gradleStateCache.restore(cacheListener);
|
yield gradleStateCache.restore(cacheListener);
|
||||||
core.saveState(CACHE_LISTENER, cacheListener.stringify());
|
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
exports.restore = restore;
|
exports.restore = restore;
|
||||||
function save(gradleUserHome) {
|
function save(gradleUserHome, cacheListener) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
if (!shouldSaveCaches()) {
|
if (!shouldSaveCaches()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const cacheListener = cache_reporting_1.CacheListener.rehydrate(core.getState(CACHE_LISTENER));
|
|
||||||
if ((0, cache_utils_1.isCacheReadOnly)()) {
|
if ((0, cache_utils_1.isCacheReadOnly)()) {
|
||||||
core.info('Cache is read-only: will not save state for use in subsequent builds.');
|
core.info('Cache is read-only: will not save state for use in subsequent builds.');
|
||||||
(0, cache_reporting_1.logCachingReport)(cacheListener);
|
cacheListener.isCacheReadOnly = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
yield core.group('Caching Gradle state', () => __awaiter(this, void 0, void 0, function* () {
|
yield core.group('Caching Gradle state', () => __awaiter(this, void 0, void 0, function* () {
|
||||||
return new cache_base_1.GradleStateCache(gradleUserHome).save(cacheListener);
|
return new cache_base_1.GradleStateCache(gradleUserHome).save(cacheListener);
|
||||||
}));
|
}));
|
||||||
(0, cache_reporting_1.logCachingReport)(cacheListener);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
exports.save = save;
|
exports.save = save;
|
||||||
@ -64814,6 +64864,93 @@ function shouldSaveCaches() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ 7345:
|
||||||
|
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||||
|
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||||
|
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||||
|
}
|
||||||
|
Object.defineProperty(o, k2, desc);
|
||||||
|
}) : (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
o[k2] = m[k];
|
||||||
|
}));
|
||||||
|
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||||
|
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||||
|
}) : function(o, v) {
|
||||||
|
o["default"] = v;
|
||||||
|
});
|
||||||
|
var __importStar = (this && this.__importStar) || function (mod) {
|
||||||
|
if (mod && mod.__esModule) return mod;
|
||||||
|
var result = {};
|
||||||
|
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||||
|
__setModuleDefault(result, mod);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||||
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||||
|
exports.writeJobSummary = void 0;
|
||||||
|
const core = __importStar(__nccwpck_require__(2186));
|
||||||
|
const fs_1 = __importDefault(__nccwpck_require__(7147));
|
||||||
|
const path_1 = __importDefault(__nccwpck_require__(1017));
|
||||||
|
const cache_reporting_1 = __nccwpck_require__(6674);
|
||||||
|
function writeJobSummary(cacheListener) {
|
||||||
|
core.info('Writing job summary...');
|
||||||
|
const buildResults = loadBuildResults();
|
||||||
|
if (buildResults.length === 0) {
|
||||||
|
core.debug('No Gradle build results found. Summary table will not be generated.');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
core.info('Writing summary table');
|
||||||
|
writeSummaryTable(buildResults);
|
||||||
|
}
|
||||||
|
core.info('Writing cache report...');
|
||||||
|
(0, cache_reporting_1.logCachingReport)(cacheListener);
|
||||||
|
core.summary.write();
|
||||||
|
}
|
||||||
|
exports.writeJobSummary = writeJobSummary;
|
||||||
|
function loadBuildResults() {
|
||||||
|
const buildResultsDir = path_1.default.resolve(process.env['RUNNER_TEMP'], '.build-results');
|
||||||
|
if (!fs_1.default.existsSync(buildResultsDir)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return fs_1.default.readdirSync(buildResultsDir).map(file => {
|
||||||
|
const filePath = path_1.default.join(buildResultsDir, file);
|
||||||
|
const content = fs_1.default.readFileSync(filePath, 'utf8');
|
||||||
|
return JSON.parse(content);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function writeSummaryTable(results) {
|
||||||
|
core.summary.addRaw('\n');
|
||||||
|
core.summary.addHeading('Gradle Builds', 3);
|
||||||
|
core.summary.addRaw('\n| Root Project | Tasks | Gradle Version | Outcome |\n| - | - | - | - |\n');
|
||||||
|
for (const result of results) {
|
||||||
|
const tableRow = `| ${result.rootProject} \
|
||||||
|
| ${result.requestedTasks} \
|
||||||
|
| ${result.gradleVersion} \
|
||||||
|
| ${renderOutcome(result)} \
|
||||||
|
|\n`;
|
||||||
|
core.summary.addRaw(tableRow);
|
||||||
|
}
|
||||||
|
core.summary.addRaw('\n');
|
||||||
|
}
|
||||||
|
function renderOutcome(result) {
|
||||||
|
if (result.buildScanUri) {
|
||||||
|
return `[![Gradle Build](https://img.shields.io/badge/Build%20Scan%E2%84%A2-${result.buildFailed ? 'FAILED-red' : 'SUCCESS-brightgreen'}?logo=Gradle)](${result.buildScanUri})`;
|
||||||
|
}
|
||||||
|
return `![Gradle Build](https://img.shields.io/badge/${result.buildFailed ? 'FAILED-red' : 'SUCCESS-brightgreen'}?logo=Gradle)`;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
|
|
||||||
/***/ 7051:
|
/***/ 7051:
|
||||||
@ -64923,8 +65060,11 @@ const core = __importStar(__nccwpck_require__(2186));
|
|||||||
const path = __importStar(__nccwpck_require__(1017));
|
const path = __importStar(__nccwpck_require__(1017));
|
||||||
const os = __importStar(__nccwpck_require__(2037));
|
const os = __importStar(__nccwpck_require__(2037));
|
||||||
const caches = __importStar(__nccwpck_require__(3800));
|
const caches = __importStar(__nccwpck_require__(3800));
|
||||||
|
const cache_reporting_1 = __nccwpck_require__(6674);
|
||||||
|
const job_summary_1 = __nccwpck_require__(7345);
|
||||||
const GRADLE_SETUP_VAR = 'GRADLE_BUILD_ACTION_SETUP_COMPLETED';
|
const GRADLE_SETUP_VAR = 'GRADLE_BUILD_ACTION_SETUP_COMPLETED';
|
||||||
const GRADLE_USER_HOME = 'GRADLE_USER_HOME';
|
const GRADLE_USER_HOME = 'GRADLE_USER_HOME';
|
||||||
|
const CACHE_LISTENER = 'CACHE_LISTENER';
|
||||||
function setup(buildRootDirectory) {
|
function setup(buildRootDirectory) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
const gradleUserHome = determineGradleUserHome(buildRootDirectory);
|
const gradleUserHome = determineGradleUserHome(buildRootDirectory);
|
||||||
@ -64935,18 +65075,24 @@ function setup(buildRootDirectory) {
|
|||||||
core.exportVariable(GRADLE_SETUP_VAR, true);
|
core.exportVariable(GRADLE_SETUP_VAR, true);
|
||||||
core.saveState(GRADLE_SETUP_VAR, true);
|
core.saveState(GRADLE_SETUP_VAR, true);
|
||||||
core.saveState(GRADLE_USER_HOME, gradleUserHome);
|
core.saveState(GRADLE_USER_HOME, gradleUserHome);
|
||||||
yield caches.restore(gradleUserHome);
|
const cacheListener = new cache_reporting_1.CacheListener();
|
||||||
|
yield caches.restore(gradleUserHome, cacheListener);
|
||||||
|
core.saveState(CACHE_LISTENER, cacheListener.stringify());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
exports.setup = setup;
|
exports.setup = setup;
|
||||||
function complete() {
|
function complete() {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
core.info('Inside setupGradle.complete()');
|
||||||
if (!core.getState(GRADLE_SETUP_VAR)) {
|
if (!core.getState(GRADLE_SETUP_VAR)) {
|
||||||
core.info('Gradle setup post-action only performed for first gradle-build-action step in workflow.');
|
core.info('Gradle setup post-action only performed for first gradle-build-action step in workflow.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
core.info('In final post-action step, saving state and writing summary');
|
||||||
|
const cacheListener = cache_reporting_1.CacheListener.rehydrate(core.getState(CACHE_LISTENER));
|
||||||
const gradleUserHome = core.getState(GRADLE_USER_HOME);
|
const gradleUserHome = core.getState(GRADLE_USER_HOME);
|
||||||
yield caches.save(gradleUserHome);
|
yield caches.save(gradleUserHome, cacheListener);
|
||||||
|
(0, job_summary_1.writeJobSummary)(cacheListener);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
exports.complete = complete;
|
exports.complete = complete;
|
||||||
|
2
dist/post/index.js.map
vendored
2
dist/post/index.js.map
vendored
File diff suppressed because one or more lines are too long
@ -95,9 +95,11 @@ export class GradleStateCache {
|
|||||||
async save(listener: CacheListener): Promise<void> {
|
async save(listener: CacheListener): Promise<void> {
|
||||||
const cacheKey = generateCacheKey(this.cacheName).key
|
const cacheKey = generateCacheKey(this.cacheName).key
|
||||||
const restoredCacheKey = core.getState(RESTORED_CACHE_KEY_KEY)
|
const restoredCacheKey = core.getState(RESTORED_CACHE_KEY_KEY)
|
||||||
|
const entryListener = listener.entry(this.cacheDescription)
|
||||||
|
|
||||||
if (restoredCacheKey && cacheKey === restoredCacheKey) {
|
if (restoredCacheKey && cacheKey === restoredCacheKey) {
|
||||||
core.info(`Cache hit occurred on the cache key ${cacheKey}, not saving cache.`)
|
core.info(`Cache hit occurred on the cache key ${cacheKey}, not saving cache.`)
|
||||||
|
entryListener.markUnchanged('cache key not changed')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,7 +112,6 @@ export class GradleStateCache {
|
|||||||
|
|
||||||
core.info(`Caching ${this.cacheDescription} with cache key: ${cacheKey}`)
|
core.info(`Caching ${this.cacheDescription} with cache key: ${cacheKey}`)
|
||||||
const cachePath = this.getCachePath()
|
const cachePath = this.getCachePath()
|
||||||
const entryListener = listener.entry(this.cacheDescription)
|
|
||||||
await saveCache(cachePath, cacheKey, entryListener)
|
await saveCache(cachePath, cacheKey, entryListener)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -212,6 +212,7 @@ abstract class AbstractEntryExtractor {
|
|||||||
|
|
||||||
if (previouslyRestoredKey === cacheKey) {
|
if (previouslyRestoredKey === cacheKey) {
|
||||||
cacheDebug(`No change to previously restored ${artifactType}. Not saving.`)
|
cacheDebug(`No change to previously restored ${artifactType}. Not saving.`)
|
||||||
|
entryListener.markUnchanged('contents unchanged')
|
||||||
} else {
|
} else {
|
||||||
core.info(`Caching ${artifactType} with path '${pattern}' and cache key: ${cacheKey}`)
|
core.info(`Caching ${artifactType} with path '${pattern}' and cache key: ${cacheKey}`)
|
||||||
await saveCache([pattern], cacheKey, entryListener)
|
await saveCache([pattern], cacheKey, entryListener)
|
||||||
|
@ -6,6 +6,8 @@ import * as core from '@actions/core'
|
|||||||
*/
|
*/
|
||||||
export class CacheListener {
|
export class CacheListener {
|
||||||
cacheEntries: CacheEntryListener[] = []
|
cacheEntries: CacheEntryListener[] = []
|
||||||
|
isCacheReadOnly = false
|
||||||
|
isCacheWriteOnly = false
|
||||||
|
|
||||||
get fullyRestored(): boolean {
|
get fullyRestored(): boolean {
|
||||||
return this.cacheEntries.every(x => !x.wasRequestedButNotRestored())
|
return this.cacheEntries.every(x => !x.wasRequestedButNotRestored())
|
||||||
@ -54,6 +56,8 @@ export class CacheEntryListener {
|
|||||||
savedKey: string | undefined
|
savedKey: string | undefined
|
||||||
savedSize: number | undefined
|
savedSize: number | undefined
|
||||||
|
|
||||||
|
unchanged: string | undefined
|
||||||
|
|
||||||
constructor(entryName: string) {
|
constructor(entryName: string) {
|
||||||
this.entryName = entryName
|
this.entryName = entryName
|
||||||
}
|
}
|
||||||
@ -85,6 +89,11 @@ export class CacheEntryListener {
|
|||||||
this.savedSize = 0
|
this.savedSize = 0
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
markUnchanged(message: string): CacheEntryListener {
|
||||||
|
this.unchanged = message
|
||||||
|
return this
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function logCachingReport(listener: CacheListener): void {
|
export function logCachingReport(listener: CacheListener): void {
|
||||||
@ -92,22 +101,85 @@ export function logCachingReport(listener: CacheListener): void {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
core.info(`---------- Caching Summary -------------
|
core.summary.addHeading('Gradle Home Caching Summary', 3)
|
||||||
Restored Entries Count: ${getCount(listener.cacheEntries, e => e.restoredSize)}
|
|
||||||
Size: ${getSum(listener.cacheEntries, e => e.restoredSize)}
|
|
||||||
Saved Entries Count: ${getCount(listener.cacheEntries, e => e.savedSize)}
|
|
||||||
Size: ${getSum(listener.cacheEntries, e => e.savedSize)}`)
|
|
||||||
|
|
||||||
core.startGroup('Cache Entry details')
|
const entries = listener.cacheEntries
|
||||||
for (const entry of listener.cacheEntries) {
|
.map(
|
||||||
core.info(`Entry: ${entry.entryName}
|
entry =>
|
||||||
|
`Entry: ${entry.entryName}
|
||||||
Requested Key : ${entry.requestedKey ?? ''}
|
Requested Key : ${entry.requestedKey ?? ''}
|
||||||
Restored Key : ${entry.restoredKey ?? ''}
|
Restored Key : ${entry.restoredKey ?? ''}
|
||||||
Size: ${formatSize(entry.restoredSize)}
|
Size: ${formatSize(entry.restoredSize)}
|
||||||
|
${getRestoredMessage(entry, listener.isCacheWriteOnly)}
|
||||||
Saved Key : ${entry.savedKey ?? ''}
|
Saved Key : ${entry.savedKey ?? ''}
|
||||||
Size: ${formatSize(entry.savedSize)}`)
|
Size: ${formatSize(entry.savedSize)}
|
||||||
|
${getSavedMessage(entry, listener.isCacheReadOnly)}
|
||||||
|
---`
|
||||||
|
)
|
||||||
|
.join('\n')
|
||||||
|
|
||||||
|
core.summary.addRaw(
|
||||||
|
`
|
||||||
|
|
||||||
|
| | Count | Size (Mb) | Size (B) |
|
||||||
|
| - | -: | -: | -: |
|
||||||
|
| Restored | ${getCount(listener.cacheEntries, e => e.restoredSize)} | ${getMegaBytes(
|
||||||
|
listener.cacheEntries,
|
||||||
|
e => e.restoredSize
|
||||||
|
)} | ${getBytes(listener.cacheEntries, e => e.restoredSize)} |
|
||||||
|
| Saved | ${getCount(listener.cacheEntries, e => e.savedSize)} | ${getMegaBytes(
|
||||||
|
listener.cacheEntries,
|
||||||
|
e => e.savedSize
|
||||||
|
)} | ${getBytes(listener.cacheEntries, e => e.savedSize)} |
|
||||||
|
|
||||||
|
`
|
||||||
|
)
|
||||||
|
|
||||||
|
if (listener.isCacheReadOnly) {
|
||||||
|
core.summary.addRaw('- **Cache is read-only**\n')
|
||||||
}
|
}
|
||||||
core.endGroup()
|
if (listener.isCacheWriteOnly) {
|
||||||
|
core.summary.addRaw('- **Cache is write-only**\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
core.summary.addDetails(
|
||||||
|
'Cache Entry Details',
|
||||||
|
`
|
||||||
|
<pre>
|
||||||
|
${entries}
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRestoredMessage(entry: CacheEntryListener, isCacheWriteOnly: boolean): string {
|
||||||
|
if (isCacheWriteOnly) {
|
||||||
|
return '(Entry not restored: cache is write-only)'
|
||||||
|
}
|
||||||
|
if (entry.restoredKey === undefined) {
|
||||||
|
return '(Entry not restored: no match found)'
|
||||||
|
}
|
||||||
|
if (entry.restoredKey === entry.requestedKey) {
|
||||||
|
return '(Entry restored: exact match found)'
|
||||||
|
}
|
||||||
|
return '(Entry restored: partial match found)'
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSavedMessage(entry: CacheEntryListener, isCacheReadOnly: boolean): string {
|
||||||
|
if (entry.unchanged) {
|
||||||
|
return `(Entry not saved: ${entry.unchanged})`
|
||||||
|
}
|
||||||
|
if (entry.savedKey === undefined) {
|
||||||
|
if (isCacheReadOnly) {
|
||||||
|
return '(Entry not saved: cache is read-only)'
|
||||||
|
}
|
||||||
|
return '(Entry not saved: reason unknown)'
|
||||||
|
}
|
||||||
|
if (entry.savedSize === 0) {
|
||||||
|
return '(Entry not saved: entry with key already exists)'
|
||||||
|
}
|
||||||
|
return '(Entry saved)'
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCount(
|
function getCount(
|
||||||
@ -117,14 +189,19 @@ function getCount(
|
|||||||
return cacheEntries.filter(e => predicate(e) !== undefined).length
|
return cacheEntries.filter(e => predicate(e) !== undefined).length
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSum(
|
function getBytes(
|
||||||
cacheEntries: CacheEntryListener[],
|
cacheEntries: CacheEntryListener[],
|
||||||
predicate: (value: CacheEntryListener) => number | undefined
|
predicate: (value: CacheEntryListener) => number | undefined
|
||||||
): string {
|
): number {
|
||||||
if (cacheEntries.length === 0) {
|
return cacheEntries.map(e => predicate(e) ?? 0).reduce((p, v) => p + v, 0)
|
||||||
return '0'
|
|
||||||
}
|
}
|
||||||
return formatSize(cacheEntries.map(e => predicate(e) ?? 0).reduce((p, v) => p + v, 0))
|
|
||||||
|
function getMegaBytes(
|
||||||
|
cacheEntries: CacheEntryListener[],
|
||||||
|
predicate: (value: CacheEntryListener) => number | undefined
|
||||||
|
): number {
|
||||||
|
const bytes = getBytes(cacheEntries, predicate)
|
||||||
|
return Math.round(bytes / (1024 * 1024))
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatSize(bytes: number | undefined): string {
|
function formatSize(bytes: number | undefined): string {
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
import * as core from '@actions/core'
|
import * as core from '@actions/core'
|
||||||
import {isCacheDisabled, isCacheReadOnly, isCacheWriteOnly} from './cache-utils'
|
import {isCacheDisabled, isCacheReadOnly, isCacheWriteOnly} from './cache-utils'
|
||||||
import {logCachingReport, CacheListener} from './cache-reporting'
|
import {CacheListener} from './cache-reporting'
|
||||||
import {GradleStateCache} from './cache-base'
|
import {GradleStateCache} from './cache-base'
|
||||||
|
|
||||||
const CACHE_RESTORED_VAR = 'GRADLE_BUILD_ACTION_CACHE_RESTORED'
|
const CACHE_RESTORED_VAR = 'GRADLE_BUILD_ACTION_CACHE_RESTORED'
|
||||||
const CACHE_LISTENER = 'CACHE_LISTENER'
|
|
||||||
|
|
||||||
export async function restore(gradleUserHome: string): Promise<void> {
|
export async function restore(gradleUserHome: string, cacheListener: CacheListener): Promise<void> {
|
||||||
// Bypass restore cache on all but first action step in workflow.
|
// Bypass restore cache on all but first action step in workflow.
|
||||||
if (process.env[CACHE_RESTORED_VAR]) {
|
if (process.env[CACHE_RESTORED_VAR]) {
|
||||||
core.info('Cache only restored on first action step.')
|
core.info('Cache only restored on first action step.')
|
||||||
@ -36,35 +35,29 @@ export async function restore(gradleUserHome: string): Promise<void> {
|
|||||||
|
|
||||||
if (isCacheWriteOnly()) {
|
if (isCacheWriteOnly()) {
|
||||||
core.info('Cache is write-only: will not restore from cache.')
|
core.info('Cache is write-only: will not restore from cache.')
|
||||||
|
cacheListener.isCacheWriteOnly = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
await core.group('Restore Gradle state from cache', async () => {
|
await core.group('Restore Gradle state from cache', async () => {
|
||||||
const cacheListener = new CacheListener()
|
|
||||||
await gradleStateCache.restore(cacheListener)
|
await gradleStateCache.restore(cacheListener)
|
||||||
|
|
||||||
core.saveState(CACHE_LISTENER, cacheListener.stringify())
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function save(gradleUserHome: string): Promise<void> {
|
export async function save(gradleUserHome: string, cacheListener: CacheListener): Promise<void> {
|
||||||
if (!shouldSaveCaches()) {
|
if (!shouldSaveCaches()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const cacheListener: CacheListener = CacheListener.rehydrate(core.getState(CACHE_LISTENER))
|
|
||||||
|
|
||||||
if (isCacheReadOnly()) {
|
if (isCacheReadOnly()) {
|
||||||
core.info('Cache is read-only: will not save state for use in subsequent builds.')
|
core.info('Cache is read-only: will not save state for use in subsequent builds.')
|
||||||
logCachingReport(cacheListener)
|
cacheListener.isCacheReadOnly = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
await core.group('Caching Gradle state', async () => {
|
await core.group('Caching Gradle state', async () => {
|
||||||
return new GradleStateCache(gradleUserHome).save(cacheListener)
|
return new GradleStateCache(gradleUserHome).save(cacheListener)
|
||||||
})
|
})
|
||||||
|
|
||||||
logCachingReport(cacheListener)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function shouldSaveCaches(): boolean {
|
function shouldSaveCaches(): boolean {
|
||||||
|
70
src/job-summary.ts
Normal file
70
src/job-summary.ts
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
import * as core from '@actions/core'
|
||||||
|
import fs from 'fs'
|
||||||
|
import path from 'path'
|
||||||
|
import {logCachingReport, CacheListener} from './cache-reporting'
|
||||||
|
|
||||||
|
interface BuildResult {
|
||||||
|
get rootProject(): string
|
||||||
|
get requestedTasks(): string
|
||||||
|
get gradleVersion(): string
|
||||||
|
get buildFailed(): boolean
|
||||||
|
get buildScanUri(): string
|
||||||
|
}
|
||||||
|
|
||||||
|
export function writeJobSummary(cacheListener: CacheListener): void {
|
||||||
|
core.info('Writing job summary...')
|
||||||
|
|
||||||
|
const buildResults = loadBuildResults()
|
||||||
|
if (buildResults.length === 0) {
|
||||||
|
core.debug('No Gradle build results found. Summary table will not be generated.')
|
||||||
|
} else {
|
||||||
|
core.info('Writing summary table')
|
||||||
|
writeSummaryTable(buildResults)
|
||||||
|
}
|
||||||
|
|
||||||
|
core.info('Writing cache report...')
|
||||||
|
logCachingReport(cacheListener)
|
||||||
|
|
||||||
|
core.summary.write()
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadBuildResults(): BuildResult[] {
|
||||||
|
const buildResultsDir = path.resolve(process.env['RUNNER_TEMP']!, '.build-results')
|
||||||
|
if (!fs.existsSync(buildResultsDir)) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
return fs.readdirSync(buildResultsDir).map(file => {
|
||||||
|
// Every file in the .build-results dir should be a BuildResults JSON
|
||||||
|
const filePath = path.join(buildResultsDir, file)
|
||||||
|
const content = fs.readFileSync(filePath, 'utf8')
|
||||||
|
return JSON.parse(content) as BuildResult
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeSummaryTable(results: BuildResult[]): void {
|
||||||
|
core.summary.addRaw('\n')
|
||||||
|
core.summary.addHeading('Gradle Builds', 3)
|
||||||
|
core.summary.addRaw('\n| Root Project | Tasks | Gradle Version | Outcome |\n| - | - | - | - |\n')
|
||||||
|
for (const result of results) {
|
||||||
|
const tableRow = `| ${result.rootProject} \
|
||||||
|
| ${result.requestedTasks} \
|
||||||
|
| ${result.gradleVersion} \
|
||||||
|
| ${renderOutcome(result)} \
|
||||||
|
|\n`
|
||||||
|
core.summary.addRaw(tableRow)
|
||||||
|
}
|
||||||
|
core.summary.addRaw('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderOutcome(result: BuildResult): string {
|
||||||
|
if (result.buildScanUri) {
|
||||||
|
return `[![Gradle Build](https://img.shields.io/badge/Build%20Scan%E2%84%A2-${
|
||||||
|
result.buildFailed ? 'FAILED-red' : 'SUCCESS-brightgreen'
|
||||||
|
}?logo=Gradle)](${result.buildScanUri})`
|
||||||
|
}
|
||||||
|
|
||||||
|
return `![Gradle Build](https://img.shields.io/badge/${
|
||||||
|
result.buildFailed ? 'FAILED-red' : 'SUCCESS-brightgreen'
|
||||||
|
}?logo=Gradle)`
|
||||||
|
}
|
@ -33,17 +33,23 @@ def registerCallbacks(buildScanExtension, rootProjectName) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
buildScanPublished { buildScan ->
|
buildScanPublished { buildScan ->
|
||||||
def gradleCommand = rootProjectName + " " + gradle.startParameter.taskNames.join(" ")
|
def buildResultsDir = new File(System.getenv("RUNNER_TEMP"), ".build-results")
|
||||||
|
buildResultsDir.mkdirs()
|
||||||
|
|
||||||
// Write job summary to magic file defined by GitHub Actions.
|
def buildResultsFile = new File(buildResultsDir, System.getenv("GITHUB_ACTION") + System.currentTimeMillis() + ".json")
|
||||||
def githubSummaryFile = new File(System.getenv("GITHUB_STEP_SUMMARY"))
|
|
||||||
if (buildFailed) {
|
def requestedTasks = gradle.startParameter.taskNames.join(" ")
|
||||||
githubSummaryFile << ":x: Gradle Build `${gradleCommand}` [![Gradle Enterprise Build Scan](https://img.shields.io/badge/Gradle%20Enterprise%20Build%20Scan%E2%84%A2-FAILED-red?logo=Gradle)](${buildScan.buildScanUri})"
|
def gradleVersion = GradleVersion.current().version
|
||||||
} else {
|
def buildScanUri = buildScan.buildScanUri.toASCIIString()
|
||||||
githubSummaryFile << ":white_check_mark: Gradle Build `${gradleCommand}` [![Gradle Enterprise Build Scan](https://img.shields.io/badge/Gradle%20Enterprise%20Build%20Scan%E2%84%A2-SUCCESS-brightgreen?logo=Gradle)](${buildScan.buildScanUri})"
|
def buildResults = [
|
||||||
}
|
rootProject: rootProjectName,
|
||||||
|
requestedTasks: requestedTasks,
|
||||||
|
gradleVersion: gradleVersion,
|
||||||
|
buildFailed: buildFailed,
|
||||||
|
buildScanUri: buildScanUri
|
||||||
|
]
|
||||||
|
buildResultsFile << groovy.json.JsonOutput.toJson(buildResults)
|
||||||
|
|
||||||
// Send 'set-output' command directly to GitHub Actions via STDOUT.
|
|
||||||
println("::set-output name=build-scan-url::${buildScan.buildScanUri}")
|
println("::set-output name=build-scan-url::${buildScan.buildScanUri}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,12 @@ import * as core from '@actions/core'
|
|||||||
import * as path from 'path'
|
import * as path from 'path'
|
||||||
import * as os from 'os'
|
import * as os from 'os'
|
||||||
import * as caches from './caches'
|
import * as caches from './caches'
|
||||||
|
import {CacheListener} from './cache-reporting'
|
||||||
|
import {writeJobSummary} from './job-summary'
|
||||||
|
|
||||||
const GRADLE_SETUP_VAR = 'GRADLE_BUILD_ACTION_SETUP_COMPLETED'
|
const GRADLE_SETUP_VAR = 'GRADLE_BUILD_ACTION_SETUP_COMPLETED'
|
||||||
const GRADLE_USER_HOME = 'GRADLE_USER_HOME'
|
const GRADLE_USER_HOME = 'GRADLE_USER_HOME'
|
||||||
|
const CACHE_LISTENER = 'CACHE_LISTENER'
|
||||||
|
|
||||||
export async function setup(buildRootDirectory: string): Promise<void> {
|
export async function setup(buildRootDirectory: string): Promise<void> {
|
||||||
const gradleUserHome = determineGradleUserHome(buildRootDirectory)
|
const gradleUserHome = determineGradleUserHome(buildRootDirectory)
|
||||||
@ -22,17 +25,26 @@ export async function setup(buildRootDirectory: string): Promise<void> {
|
|||||||
// Save the Gradle User Home for use in the post-action step.
|
// Save the Gradle User Home for use in the post-action step.
|
||||||
core.saveState(GRADLE_USER_HOME, gradleUserHome)
|
core.saveState(GRADLE_USER_HOME, gradleUserHome)
|
||||||
|
|
||||||
await caches.restore(gradleUserHome)
|
const cacheListener = new CacheListener()
|
||||||
|
await caches.restore(gradleUserHome, cacheListener)
|
||||||
|
|
||||||
|
core.saveState(CACHE_LISTENER, cacheListener.stringify())
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function complete(): Promise<void> {
|
export async function complete(): Promise<void> {
|
||||||
|
core.info('Inside setupGradle.complete()')
|
||||||
if (!core.getState(GRADLE_SETUP_VAR)) {
|
if (!core.getState(GRADLE_SETUP_VAR)) {
|
||||||
core.info('Gradle setup post-action only performed for first gradle-build-action step in workflow.')
|
core.info('Gradle setup post-action only performed for first gradle-build-action step in workflow.')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
core.info('In final post-action step, saving state and writing summary')
|
||||||
|
const cacheListener: CacheListener = CacheListener.rehydrate(core.getState(CACHE_LISTENER))
|
||||||
|
|
||||||
const gradleUserHome = core.getState(GRADLE_USER_HOME)
|
const gradleUserHome = core.getState(GRADLE_USER_HOME)
|
||||||
await caches.save(gradleUserHome)
|
await caches.save(gradleUserHome, cacheListener)
|
||||||
|
|
||||||
|
writeJobSummary(cacheListener)
|
||||||
}
|
}
|
||||||
|
|
||||||
function determineGradleUserHome(rootDir: string): string {
|
function determineGradleUserHome(rootDir: string): string {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user