mirror of
				https://github.com/gradle/gradle-build-action.git
				synced 2025-11-04 01:28:56 +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:
		
							
								
								
									
										202
									
								
								dist/main/index.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										202
									
								
								dist/main/index.js
									
									
									
									
										vendored
									
									
								
							@@ -64910,8 +64910,10 @@ class GradleStateCache {
 | 
			
		||||
        return __awaiter(this, void 0, void 0, function* () {
 | 
			
		||||
            const cacheKey = (0, cache_utils_1.generateCacheKey)(this.cacheName).key;
 | 
			
		||||
            const restoredCacheKey = core.getState(RESTORED_CACHE_KEY_KEY);
 | 
			
		||||
            const entryListener = listener.entry(this.cacheDescription);
 | 
			
		||||
            if (restoredCacheKey && cacheKey === restoredCacheKey) {
 | 
			
		||||
                core.info(`Cache hit occurred on the cache key ${cacheKey}, not saving cache.`);
 | 
			
		||||
                entryListener.markUnchanged('cache key not changed');
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            try {
 | 
			
		||||
@@ -64923,7 +64925,6 @@ class GradleStateCache {
 | 
			
		||||
            }
 | 
			
		||||
            core.info(`Caching ${this.cacheDescription} with cache key: ${cacheKey}`);
 | 
			
		||||
            const cachePath = this.getCachePath();
 | 
			
		||||
            const entryListener = listener.entry(this.cacheDescription);
 | 
			
		||||
            yield (0, cache_utils_1.saveCache)(cachePath, cacheKey, entryListener);
 | 
			
		||||
            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;
 | 
			
		||||
            if (previouslyRestoredKey === cacheKey) {
 | 
			
		||||
                (0, cache_utils_1.cacheDebug)(`No change to previously restored ${artifactType}. Not saving.`);
 | 
			
		||||
                entryListener.markUnchanged('contents unchanged');
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
                core.info(`Caching ${artifactType} with path '${pattern}' and cache key: ${cacheKey}`);
 | 
			
		||||
@@ -65334,6 +65336,8 @@ const core = __importStar(__nccwpck_require__(2186));
 | 
			
		||||
class CacheListener {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        this.cacheEntries = [];
 | 
			
		||||
        this.isCacheReadOnly = false;
 | 
			
		||||
        this.isCacheWriteOnly = false;
 | 
			
		||||
    }
 | 
			
		||||
    get fullyRestored() {
 | 
			
		||||
        return this.cacheEntries.every(x => !x.wasRequestedButNotRestored());
 | 
			
		||||
@@ -65392,38 +65396,89 @@ class CacheEntryListener {
 | 
			
		||||
        this.savedSize = 0;
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
    markUnchanged(message) {
 | 
			
		||||
        this.unchanged = message;
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
exports.CacheEntryListener = CacheEntryListener;
 | 
			
		||||
function logCachingReport(listener) {
 | 
			
		||||
    var _a, _b, _c;
 | 
			
		||||
    if (listener.cacheEntries.length === 0) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    core.info(`---------- Caching Summary -------------
 | 
			
		||||
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');
 | 
			
		||||
    for (const entry of listener.cacheEntries) {
 | 
			
		||||
        core.info(`Entry: ${entry.entryName}
 | 
			
		||||
    core.summary.addHeading('Gradle Home Caching Summary', 3);
 | 
			
		||||
    const entries = listener.cacheEntries
 | 
			
		||||
        .map(entry => {
 | 
			
		||||
        var _a, _b, _c;
 | 
			
		||||
        return `Entry: ${entry.entryName}
 | 
			
		||||
    Requested Key : ${(_a = entry.requestedKey) !== null && _a !== void 0 ? _a : ''}
 | 
			
		||||
    Restored  Key : ${(_b = entry.restoredKey) !== null && _b !== void 0 ? _b : ''}
 | 
			
		||||
              Size: ${formatSize(entry.restoredSize)}
 | 
			
		||||
              ${getRestoredMessage(entry, listener.isCacheWriteOnly)}
 | 
			
		||||
    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;
 | 
			
		||||
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) {
 | 
			
		||||
    return cacheEntries.filter(e => predicate(e) !== undefined).length;
 | 
			
		||||
}
 | 
			
		||||
function getSum(cacheEntries, predicate) {
 | 
			
		||||
    if (cacheEntries.length === 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 getBytes(cacheEntries, predicate) {
 | 
			
		||||
    return 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) {
 | 
			
		||||
    if (bytes === undefined) {
 | 
			
		||||
@@ -65696,11 +65751,9 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
 | 
			
		||||
exports.save = exports.restore = void 0;
 | 
			
		||||
const core = __importStar(__nccwpck_require__(2186));
 | 
			
		||||
const cache_utils_1 = __nccwpck_require__(1678);
 | 
			
		||||
const cache_reporting_1 = __nccwpck_require__(6674);
 | 
			
		||||
const cache_base_1 = __nccwpck_require__(7591);
 | 
			
		||||
const CACHE_RESTORED_VAR = 'GRADLE_BUILD_ACTION_CACHE_RESTORED';
 | 
			
		||||
const CACHE_LISTENER = 'CACHE_LISTENER';
 | 
			
		||||
function restore(gradleUserHome) {
 | 
			
		||||
function restore(gradleUserHome, cacheListener) {
 | 
			
		||||
    return __awaiter(this, void 0, void 0, function* () {
 | 
			
		||||
        if (process.env[CACHE_RESTORED_VAR]) {
 | 
			
		||||
            core.info('Cache only restored on first action step.');
 | 
			
		||||
@@ -65722,31 +65775,28 @@ function restore(gradleUserHome) {
 | 
			
		||||
        core.saveState(CACHE_RESTORED_VAR, true);
 | 
			
		||||
        if ((0, cache_utils_1.isCacheWriteOnly)()) {
 | 
			
		||||
            core.info('Cache is write-only: will not restore from cache.');
 | 
			
		||||
            cacheListener.isCacheWriteOnly = true;
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        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);
 | 
			
		||||
            core.saveState(CACHE_LISTENER, cacheListener.stringify());
 | 
			
		||||
        }));
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
exports.restore = restore;
 | 
			
		||||
function save(gradleUserHome) {
 | 
			
		||||
function save(gradleUserHome, cacheListener) {
 | 
			
		||||
    return __awaiter(this, void 0, void 0, function* () {
 | 
			
		||||
        if (!shouldSaveCaches()) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        const cacheListener = cache_reporting_1.CacheListener.rehydrate(core.getState(CACHE_LISTENER));
 | 
			
		||||
        if ((0, cache_utils_1.isCacheReadOnly)()) {
 | 
			
		||||
            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;
 | 
			
		||||
        }
 | 
			
		||||
        yield core.group('Caching Gradle state', () => __awaiter(this, void 0, void 0, function* () {
 | 
			
		||||
            return new cache_base_1.GradleStateCache(gradleUserHome).save(cacheListener);
 | 
			
		||||
        }));
 | 
			
		||||
        (0, cache_reporting_1.logCachingReport)(cacheListener);
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
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 `[](${result.buildScanUri})`;
 | 
			
		||||
    }
 | 
			
		||||
    return ``;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/***/ }),
 | 
			
		||||
 | 
			
		||||
/***/ 399:
 | 
			
		||||
@@ -66239,8 +66376,11 @@ const core = __importStar(__nccwpck_require__(2186));
 | 
			
		||||
const path = __importStar(__nccwpck_require__(1017));
 | 
			
		||||
const os = __importStar(__nccwpck_require__(2037));
 | 
			
		||||
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_USER_HOME = 'GRADLE_USER_HOME';
 | 
			
		||||
const CACHE_LISTENER = 'CACHE_LISTENER';
 | 
			
		||||
function setup(buildRootDirectory) {
 | 
			
		||||
    return __awaiter(this, void 0, void 0, function* () {
 | 
			
		||||
        const gradleUserHome = determineGradleUserHome(buildRootDirectory);
 | 
			
		||||
@@ -66251,18 +66391,24 @@ function setup(buildRootDirectory) {
 | 
			
		||||
        core.exportVariable(GRADLE_SETUP_VAR, true);
 | 
			
		||||
        core.saveState(GRADLE_SETUP_VAR, true);
 | 
			
		||||
        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;
 | 
			
		||||
function complete() {
 | 
			
		||||
    return __awaiter(this, void 0, void 0, function* () {
 | 
			
		||||
        core.info('Inside setupGradle.complete()');
 | 
			
		||||
        if (!core.getState(GRADLE_SETUP_VAR)) {
 | 
			
		||||
            core.info('Gradle setup post-action only performed for first gradle-build-action step in workflow.');
 | 
			
		||||
            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);
 | 
			
		||||
        yield caches.save(gradleUserHome);
 | 
			
		||||
        yield caches.save(gradleUserHome, cacheListener);
 | 
			
		||||
        (0, job_summary_1.writeJobSummary)(cacheListener);
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
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
											
										
									
								
							
							
								
								
									
										202
									
								
								dist/post/index.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										202
									
								
								dist/post/index.js
									
									
									
									
										vendored
									
									
								
							@@ -63961,8 +63961,10 @@ class GradleStateCache {
 | 
			
		||||
        return __awaiter(this, void 0, void 0, function* () {
 | 
			
		||||
            const cacheKey = (0, cache_utils_1.generateCacheKey)(this.cacheName).key;
 | 
			
		||||
            const restoredCacheKey = core.getState(RESTORED_CACHE_KEY_KEY);
 | 
			
		||||
            const entryListener = listener.entry(this.cacheDescription);
 | 
			
		||||
            if (restoredCacheKey && cacheKey === restoredCacheKey) {
 | 
			
		||||
                core.info(`Cache hit occurred on the cache key ${cacheKey}, not saving cache.`);
 | 
			
		||||
                entryListener.markUnchanged('cache key not changed');
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            try {
 | 
			
		||||
@@ -63974,7 +63976,6 @@ class GradleStateCache {
 | 
			
		||||
            }
 | 
			
		||||
            core.info(`Caching ${this.cacheDescription} with cache key: ${cacheKey}`);
 | 
			
		||||
            const cachePath = this.getCachePath();
 | 
			
		||||
            const entryListener = listener.entry(this.cacheDescription);
 | 
			
		||||
            yield (0, cache_utils_1.saveCache)(cachePath, cacheKey, entryListener);
 | 
			
		||||
            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;
 | 
			
		||||
            if (previouslyRestoredKey === cacheKey) {
 | 
			
		||||
                (0, cache_utils_1.cacheDebug)(`No change to previously restored ${artifactType}. Not saving.`);
 | 
			
		||||
                entryListener.markUnchanged('contents unchanged');
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
                core.info(`Caching ${artifactType} with path '${pattern}' and cache key: ${cacheKey}`);
 | 
			
		||||
@@ -64385,6 +64387,8 @@ const core = __importStar(__nccwpck_require__(2186));
 | 
			
		||||
class CacheListener {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        this.cacheEntries = [];
 | 
			
		||||
        this.isCacheReadOnly = false;
 | 
			
		||||
        this.isCacheWriteOnly = false;
 | 
			
		||||
    }
 | 
			
		||||
    get fullyRestored() {
 | 
			
		||||
        return this.cacheEntries.every(x => !x.wasRequestedButNotRestored());
 | 
			
		||||
@@ -64443,38 +64447,89 @@ class CacheEntryListener {
 | 
			
		||||
        this.savedSize = 0;
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
    markUnchanged(message) {
 | 
			
		||||
        this.unchanged = message;
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
exports.CacheEntryListener = CacheEntryListener;
 | 
			
		||||
function logCachingReport(listener) {
 | 
			
		||||
    var _a, _b, _c;
 | 
			
		||||
    if (listener.cacheEntries.length === 0) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    core.info(`---------- Caching Summary -------------
 | 
			
		||||
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');
 | 
			
		||||
    for (const entry of listener.cacheEntries) {
 | 
			
		||||
        core.info(`Entry: ${entry.entryName}
 | 
			
		||||
    core.summary.addHeading('Gradle Home Caching Summary', 3);
 | 
			
		||||
    const entries = listener.cacheEntries
 | 
			
		||||
        .map(entry => {
 | 
			
		||||
        var _a, _b, _c;
 | 
			
		||||
        return `Entry: ${entry.entryName}
 | 
			
		||||
    Requested Key : ${(_a = entry.requestedKey) !== null && _a !== void 0 ? _a : ''}
 | 
			
		||||
    Restored  Key : ${(_b = entry.restoredKey) !== null && _b !== void 0 ? _b : ''}
 | 
			
		||||
              Size: ${formatSize(entry.restoredSize)}
 | 
			
		||||
              ${getRestoredMessage(entry, listener.isCacheWriteOnly)}
 | 
			
		||||
    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;
 | 
			
		||||
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) {
 | 
			
		||||
    return cacheEntries.filter(e => predicate(e) !== undefined).length;
 | 
			
		||||
}
 | 
			
		||||
function getSum(cacheEntries, predicate) {
 | 
			
		||||
    if (cacheEntries.length === 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 getBytes(cacheEntries, predicate) {
 | 
			
		||||
    return 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) {
 | 
			
		||||
    if (bytes === undefined) {
 | 
			
		||||
@@ -64747,11 +64802,9 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
 | 
			
		||||
exports.save = exports.restore = void 0;
 | 
			
		||||
const core = __importStar(__nccwpck_require__(2186));
 | 
			
		||||
const cache_utils_1 = __nccwpck_require__(1678);
 | 
			
		||||
const cache_reporting_1 = __nccwpck_require__(6674);
 | 
			
		||||
const cache_base_1 = __nccwpck_require__(7591);
 | 
			
		||||
const CACHE_RESTORED_VAR = 'GRADLE_BUILD_ACTION_CACHE_RESTORED';
 | 
			
		||||
const CACHE_LISTENER = 'CACHE_LISTENER';
 | 
			
		||||
function restore(gradleUserHome) {
 | 
			
		||||
function restore(gradleUserHome, cacheListener) {
 | 
			
		||||
    return __awaiter(this, void 0, void 0, function* () {
 | 
			
		||||
        if (process.env[CACHE_RESTORED_VAR]) {
 | 
			
		||||
            core.info('Cache only restored on first action step.');
 | 
			
		||||
@@ -64773,31 +64826,28 @@ function restore(gradleUserHome) {
 | 
			
		||||
        core.saveState(CACHE_RESTORED_VAR, true);
 | 
			
		||||
        if ((0, cache_utils_1.isCacheWriteOnly)()) {
 | 
			
		||||
            core.info('Cache is write-only: will not restore from cache.');
 | 
			
		||||
            cacheListener.isCacheWriteOnly = true;
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        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);
 | 
			
		||||
            core.saveState(CACHE_LISTENER, cacheListener.stringify());
 | 
			
		||||
        }));
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
exports.restore = restore;
 | 
			
		||||
function save(gradleUserHome) {
 | 
			
		||||
function save(gradleUserHome, cacheListener) {
 | 
			
		||||
    return __awaiter(this, void 0, void 0, function* () {
 | 
			
		||||
        if (!shouldSaveCaches()) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        const cacheListener = cache_reporting_1.CacheListener.rehydrate(core.getState(CACHE_LISTENER));
 | 
			
		||||
        if ((0, cache_utils_1.isCacheReadOnly)()) {
 | 
			
		||||
            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;
 | 
			
		||||
        }
 | 
			
		||||
        yield core.group('Caching Gradle state', () => __awaiter(this, void 0, void 0, function* () {
 | 
			
		||||
            return new cache_base_1.GradleStateCache(gradleUserHome).save(cacheListener);
 | 
			
		||||
        }));
 | 
			
		||||
        (0, cache_reporting_1.logCachingReport)(cacheListener);
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
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 `[](${result.buildScanUri})`;
 | 
			
		||||
    }
 | 
			
		||||
    return ``;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/***/ }),
 | 
			
		||||
 | 
			
		||||
/***/ 7051:
 | 
			
		||||
@@ -64923,8 +65060,11 @@ const core = __importStar(__nccwpck_require__(2186));
 | 
			
		||||
const path = __importStar(__nccwpck_require__(1017));
 | 
			
		||||
const os = __importStar(__nccwpck_require__(2037));
 | 
			
		||||
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_USER_HOME = 'GRADLE_USER_HOME';
 | 
			
		||||
const CACHE_LISTENER = 'CACHE_LISTENER';
 | 
			
		||||
function setup(buildRootDirectory) {
 | 
			
		||||
    return __awaiter(this, void 0, void 0, function* () {
 | 
			
		||||
        const gradleUserHome = determineGradleUserHome(buildRootDirectory);
 | 
			
		||||
@@ -64935,18 +65075,24 @@ function setup(buildRootDirectory) {
 | 
			
		||||
        core.exportVariable(GRADLE_SETUP_VAR, true);
 | 
			
		||||
        core.saveState(GRADLE_SETUP_VAR, true);
 | 
			
		||||
        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;
 | 
			
		||||
function complete() {
 | 
			
		||||
    return __awaiter(this, void 0, void 0, function* () {
 | 
			
		||||
        core.info('Inside setupGradle.complete()');
 | 
			
		||||
        if (!core.getState(GRADLE_SETUP_VAR)) {
 | 
			
		||||
            core.info('Gradle setup post-action only performed for first gradle-build-action step in workflow.');
 | 
			
		||||
            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);
 | 
			
		||||
        yield caches.save(gradleUserHome);
 | 
			
		||||
        yield caches.save(gradleUserHome, cacheListener);
 | 
			
		||||
        (0, job_summary_1.writeJobSummary)(cacheListener);
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
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> {
 | 
			
		||||
        const cacheKey = generateCacheKey(this.cacheName).key
 | 
			
		||||
        const restoredCacheKey = core.getState(RESTORED_CACHE_KEY_KEY)
 | 
			
		||||
        const entryListener = listener.entry(this.cacheDescription)
 | 
			
		||||
 | 
			
		||||
        if (restoredCacheKey && cacheKey === restoredCacheKey) {
 | 
			
		||||
            core.info(`Cache hit occurred on the cache key ${cacheKey}, not saving cache.`)
 | 
			
		||||
            entryListener.markUnchanged('cache key not changed')
 | 
			
		||||
            return
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -110,7 +112,6 @@ export class GradleStateCache {
 | 
			
		||||
 | 
			
		||||
        core.info(`Caching ${this.cacheDescription} with cache key: ${cacheKey}`)
 | 
			
		||||
        const cachePath = this.getCachePath()
 | 
			
		||||
        const entryListener = listener.entry(this.cacheDescription)
 | 
			
		||||
        await saveCache(cachePath, cacheKey, entryListener)
 | 
			
		||||
 | 
			
		||||
        return
 | 
			
		||||
 
 | 
			
		||||
@@ -212,6 +212,7 @@ abstract class AbstractEntryExtractor {
 | 
			
		||||
 | 
			
		||||
        if (previouslyRestoredKey === cacheKey) {
 | 
			
		||||
            cacheDebug(`No change to previously restored ${artifactType}. Not saving.`)
 | 
			
		||||
            entryListener.markUnchanged('contents unchanged')
 | 
			
		||||
        } else {
 | 
			
		||||
            core.info(`Caching ${artifactType} with path '${pattern}' and cache key: ${cacheKey}`)
 | 
			
		||||
            await saveCache([pattern], cacheKey, entryListener)
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,8 @@ import * as core from '@actions/core'
 | 
			
		||||
 */
 | 
			
		||||
export class CacheListener {
 | 
			
		||||
    cacheEntries: CacheEntryListener[] = []
 | 
			
		||||
    isCacheReadOnly = false
 | 
			
		||||
    isCacheWriteOnly = false
 | 
			
		||||
 | 
			
		||||
    get fullyRestored(): boolean {
 | 
			
		||||
        return this.cacheEntries.every(x => !x.wasRequestedButNotRestored())
 | 
			
		||||
@@ -54,6 +56,8 @@ export class CacheEntryListener {
 | 
			
		||||
    savedKey: string | undefined
 | 
			
		||||
    savedSize: number | undefined
 | 
			
		||||
 | 
			
		||||
    unchanged: string | undefined
 | 
			
		||||
 | 
			
		||||
    constructor(entryName: string) {
 | 
			
		||||
        this.entryName = entryName
 | 
			
		||||
    }
 | 
			
		||||
@@ -85,6 +89,11 @@ export class CacheEntryListener {
 | 
			
		||||
        this.savedSize = 0
 | 
			
		||||
        return this
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    markUnchanged(message: string): CacheEntryListener {
 | 
			
		||||
        this.unchanged = message
 | 
			
		||||
        return this
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function logCachingReport(listener: CacheListener): void {
 | 
			
		||||
@@ -92,22 +101,85 @@ export function logCachingReport(listener: CacheListener): void {
 | 
			
		||||
        return
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    core.info(`---------- Caching Summary -------------
 | 
			
		||||
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.summary.addHeading('Gradle Home Caching Summary', 3)
 | 
			
		||||
 | 
			
		||||
    core.startGroup('Cache Entry details')
 | 
			
		||||
    for (const entry of listener.cacheEntries) {
 | 
			
		||||
        core.info(`Entry: ${entry.entryName}
 | 
			
		||||
    const entries = listener.cacheEntries
 | 
			
		||||
        .map(
 | 
			
		||||
            entry =>
 | 
			
		||||
                `Entry: ${entry.entryName}
 | 
			
		||||
    Requested Key : ${entry.requestedKey ?? ''}
 | 
			
		||||
    Restored  Key : ${entry.restoredKey ?? ''}
 | 
			
		||||
              Size: ${formatSize(entry.restoredSize)}
 | 
			
		||||
              ${getRestoredMessage(entry, listener.isCacheWriteOnly)}
 | 
			
		||||
    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(
 | 
			
		||||
@@ -117,14 +189,19 @@ function getCount(
 | 
			
		||||
    return cacheEntries.filter(e => predicate(e) !== undefined).length
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getSum(
 | 
			
		||||
function getBytes(
 | 
			
		||||
    cacheEntries: CacheEntryListener[],
 | 
			
		||||
    predicate: (value: CacheEntryListener) => number | undefined
 | 
			
		||||
): string {
 | 
			
		||||
    if (cacheEntries.length === 0) {
 | 
			
		||||
        return '0'
 | 
			
		||||
    }
 | 
			
		||||
    return formatSize(cacheEntries.map(e => predicate(e) ?? 0).reduce((p, v) => p + v, 0))
 | 
			
		||||
): number {
 | 
			
		||||
    return 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 {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,12 +1,11 @@
 | 
			
		||||
import * as core from '@actions/core'
 | 
			
		||||
import {isCacheDisabled, isCacheReadOnly, isCacheWriteOnly} from './cache-utils'
 | 
			
		||||
import {logCachingReport, CacheListener} from './cache-reporting'
 | 
			
		||||
import {CacheListener} from './cache-reporting'
 | 
			
		||||
import {GradleStateCache} from './cache-base'
 | 
			
		||||
 | 
			
		||||
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.
 | 
			
		||||
    if (process.env[CACHE_RESTORED_VAR]) {
 | 
			
		||||
        core.info('Cache only restored on first action step.')
 | 
			
		||||
@@ -36,35 +35,29 @@ export async function restore(gradleUserHome: string): Promise<void> {
 | 
			
		||||
 | 
			
		||||
    if (isCacheWriteOnly()) {
 | 
			
		||||
        core.info('Cache is write-only: will not restore from cache.')
 | 
			
		||||
        cacheListener.isCacheWriteOnly = true
 | 
			
		||||
        return
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    await core.group('Restore Gradle state from cache', async () => {
 | 
			
		||||
        const cacheListener = new 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()) {
 | 
			
		||||
        return
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const cacheListener: CacheListener = CacheListener.rehydrate(core.getState(CACHE_LISTENER))
 | 
			
		||||
 | 
			
		||||
    if (isCacheReadOnly()) {
 | 
			
		||||
        core.info('Cache is read-only: will not save state for use in subsequent builds.')
 | 
			
		||||
        logCachingReport(cacheListener)
 | 
			
		||||
        cacheListener.isCacheReadOnly = true
 | 
			
		||||
        return
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    await core.group('Caching Gradle state', async () => {
 | 
			
		||||
        return new GradleStateCache(gradleUserHome).save(cacheListener)
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    logCachingReport(cacheListener)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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 `[](${result.buildScanUri})`
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ``
 | 
			
		||||
}
 | 
			
		||||
@@ -33,17 +33,23 @@ def registerCallbacks(buildScanExtension, rootProjectName) {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        buildScanPublished { buildScan ->
 | 
			
		||||
            def gradleCommand = rootProjectName + " " + gradle.startParameter.taskNames.join(" ")
 | 
			
		||||
            def buildResultsDir = new File(System.getenv("RUNNER_TEMP"), ".build-results")
 | 
			
		||||
            buildResultsDir.mkdirs()
 | 
			
		||||
            
 | 
			
		||||
            def buildResultsFile = new File(buildResultsDir, System.getenv("GITHUB_ACTION") + System.currentTimeMillis() + ".json")
 | 
			
		||||
 | 
			
		||||
            def requestedTasks = gradle.startParameter.taskNames.join(" ")
 | 
			
		||||
            def gradleVersion = GradleVersion.current().version
 | 
			
		||||
            def buildScanUri = buildScan.buildScanUri.toASCIIString()
 | 
			
		||||
            def buildResults = [
 | 
			
		||||
                rootProject: rootProjectName, 
 | 
			
		||||
                requestedTasks: requestedTasks,
 | 
			
		||||
                gradleVersion: gradleVersion, 
 | 
			
		||||
                buildFailed: buildFailed, 
 | 
			
		||||
                buildScanUri: buildScanUri
 | 
			
		||||
            ]
 | 
			
		||||
            buildResultsFile << groovy.json.JsonOutput.toJson(buildResults)
 | 
			
		||||
 | 
			
		||||
            // Write job summary to magic file defined by GitHub Actions.
 | 
			
		||||
            def githubSummaryFile = new File(System.getenv("GITHUB_STEP_SUMMARY"))
 | 
			
		||||
            if (buildFailed) {
 | 
			
		||||
                githubSummaryFile << ":x: Gradle Build `${gradleCommand}` [](${buildScan.buildScanUri})"
 | 
			
		||||
            } else {
 | 
			
		||||
                githubSummaryFile << ":white_check_mark: Gradle Build `${gradleCommand}` [](${buildScan.buildScanUri})"
 | 
			
		||||
            }
 | 
			
		||||
         
 | 
			
		||||
            // Send 'set-output' command directly to GitHub Actions via STDOUT.
 | 
			
		||||
            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 os from 'os'
 | 
			
		||||
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_USER_HOME = 'GRADLE_USER_HOME'
 | 
			
		||||
const CACHE_LISTENER = 'CACHE_LISTENER'
 | 
			
		||||
 | 
			
		||||
export async function setup(buildRootDirectory: string): Promise<void> {
 | 
			
		||||
    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.
 | 
			
		||||
    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> {
 | 
			
		||||
    core.info('Inside setupGradle.complete()')
 | 
			
		||||
    if (!core.getState(GRADLE_SETUP_VAR)) {
 | 
			
		||||
        core.info('Gradle setup post-action only performed for first gradle-build-action step in workflow.')
 | 
			
		||||
        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)
 | 
			
		||||
    await caches.save(gradleUserHome)
 | 
			
		||||
    await caches.save(gradleUserHome, cacheListener)
 | 
			
		||||
 | 
			
		||||
    writeJobSummary(cacheListener)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function determineGradleUserHome(rootDir: string): string {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user