Merge pull request #1026 from gradle/dd/java-toolchains

Use Maven toolchains.xml to register pre-installed JDKs as java toolchains
This commit is contained in:
Daz DeBoer 2024-01-04 05:34:34 +01:00 committed by GitHub
commit 6c7537229b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 195 additions and 120 deletions

View file

@ -21,6 +21,7 @@ jobs:
# Test that pre-installed runner JDKs are detected # Test that pre-installed runner JDKs are detected
pre-installed-toolchains: pre-installed-toolchains:
strategy: strategy:
fail-fast: false
matrix: matrix:
os: ${{fromJSON(inputs.runner-os)}} os: ${{fromJSON(inputs.runner-os)}}
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
@ -35,7 +36,7 @@ jobs:
shell: bash shell: bash
working-directory: .github/workflow-samples/groovy-dsl working-directory: .github/workflow-samples/groovy-dsl
run: | run: |
gradle -q javaToolchains > output.txt gradle --info javaToolchains > output.txt
cat output.txt cat output.txt
- name: Verify detected toolchains - name: Verify detected toolchains
shell: bash shell: bash
@ -44,10 +45,12 @@ jobs:
grep -q 'Eclipse Temurin JDK 1.8' output.txt || (echo "::error::Did not detect preinstalled JDK 1.8" && exit 1) grep -q 'Eclipse Temurin JDK 1.8' output.txt || (echo "::error::Did not detect preinstalled JDK 1.8" && exit 1)
grep -q 'Eclipse Temurin JDK 11' output.txt || (echo "::error::Did not detect preinstalled JDK 11" && exit 1) grep -q 'Eclipse Temurin JDK 11' output.txt || (echo "::error::Did not detect preinstalled JDK 11" && exit 1)
grep -q 'Eclipse Temurin JDK 17' output.txt || (echo "::error::Did not detect preinstalled JDK 17" && exit 1) grep -q 'Eclipse Temurin JDK 17' output.txt || (echo "::error::Did not detect preinstalled JDK 17" && exit 1)
grep -q 'Eclipse Temurin JDK 21' output.txt || (echo "::error::Did not detect preinstalled JDK 21" && exit 1)
# Test that JDKs provisioned by setup-java are detected # Test that JDKs provisioned by setup-java are detected
setup-java-installed-toolchain: setup-java-installed-toolchain:
strategy: strategy:
fail-fast: false
matrix: matrix:
os: ${{fromJSON(inputs.runner-os)}} os: ${{fromJSON(inputs.runner-os)}}
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
@ -72,42 +75,19 @@ jobs:
shell: bash shell: bash
working-directory: .github/workflow-samples/groovy-dsl working-directory: .github/workflow-samples/groovy-dsl
run: | run: |
gradle -q javaToolchains > output.txt gradle --info javaToolchains > output.txt
cat output.txt cat output.txt
- name: Verify detected toolchains - name: Verify setup JDKs are detected
shell: bash shell: bash
working-directory: .github/workflow-samples/groovy-dsl working-directory: .github/workflow-samples/groovy-dsl
run: | run: |
grep -q 'Eclipse Temurin JDK 16' output.txt || (echo "::error::Did not detect setup-java installed JDK 16" && exit 1) grep -q 'Eclipse Temurin JDK 16' output.txt || (echo "::error::Did not detect setup-java installed JDK 16" && exit 1)
grep -q 'Eclipse Temurin JDK 20' output.txt || (echo "::error::Did not detect setup-java installed JDK 20" && exit 1) grep -q 'Eclipse Temurin JDK 20' output.txt || (echo "::error::Did not detect setup-java installed JDK 20" && exit 1)
- name: Verify pre-installed toolchains are detected
# Test that predefined JDK detection property is not overwritten by action
check-no-overwrite:
strategy:
matrix:
os: ${{fromJSON(inputs.runner-os)}}
runs-on: ${{ matrix.os }}
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Download distribution if required
uses: ./.github/actions/download-dist
- name: Configure java installations env var in Gradle User Home
shell: bash shell: bash
working-directory: .github/workflow-samples/groovy-dsl
run: | run: |
mkdir -p ~/.gradle grep -q 'Eclipse Temurin JDK 1.8' output.txt || (echo "::error::Did not detect preinstalled JDK 1.8" && exit 1)
echo "org.gradle.java.installations.fromEnv=XXXXX" > ~/.gradle/gradle.properties grep -q 'Eclipse Temurin JDK 11' output.txt || (echo "::error::Did not detect preinstalled JDK 11" && exit 1)
- name: Setup Gradle grep -q 'Eclipse Temurin JDK 17' output.txt || (echo "::error::Did not detect preinstalled JDK 17" && exit 1)
uses: ./ grep -q 'Eclipse Temurin JDK 21' output.txt || (echo "::error::Did not detect preinstalled JDK 21" && exit 1)
- name: Check gradle.properties
shell: bash
run: |
cat ~/.gradle/gradle.properties
if grep -q 'org.gradle.java.installations.fromEnv=JAVA_HOME' ~/.gradle/gradle.properties ; then
echo 'Found overwritten fromEnv'
exit 1
fi
if ! grep -q 'org.gradle.java.installations.fromEnv=XXXXX' ~/.gradle/gradle.properties ; then
echo 'Did NOT find original fromEnv'
exit 1
fi

68
dist/main/index.js vendored
View file

@ -138599,17 +138599,14 @@ const cache_extract_entries_1 = __nccwpck_require__(76161);
const RESTORED_CACHE_KEY_KEY = 'restored-cache-key'; const RESTORED_CACHE_KEY_KEY = 'restored-cache-key';
exports.META_FILE_DIR = '.gradle-build-action'; exports.META_FILE_DIR = '.gradle-build-action';
class GradleStateCache { class GradleStateCache {
constructor(gradleUserHome) { constructor(userHome, gradleUserHome) {
this.userHome = userHome;
this.gradleUserHome = gradleUserHome; this.gradleUserHome = gradleUserHome;
this.cacheName = 'gradle'; this.cacheName = 'gradle';
this.cacheDescription = 'Gradle User Home'; this.cacheDescription = 'Gradle User Home';
} }
init() { init() {
const actionCacheDir = path_1.default.resolve(this.gradleUserHome, '.gradle-build-action'); this.initializeGradleUserHome();
fs_1.default.mkdirSync(actionCacheDir, { recursive: true });
const initScriptsDir = path_1.default.resolve(this.gradleUserHome, 'init.d');
fs_1.default.mkdirSync(initScriptsDir, { recursive: true });
this.initializeGradleUserHome(this.gradleUserHome, initScriptsDir);
const encryptionKey = params.getCacheEncryptionKey(); const encryptionKey = params.getCacheEncryptionKey();
if (encryptionKey) { if (encryptionKey) {
core.exportVariable('GRADLE_ENCRYPTION_KEY', encryptionKey); core.exportVariable('GRADLE_ENCRYPTION_KEY', encryptionKey);
@ -138725,17 +138722,15 @@ class GradleStateCache {
} }
return path_1.default.resolve(this.gradleUserHome, rawPath); return path_1.default.resolve(this.gradleUserHome, rawPath);
} }
initializeGradleUserHome(gradleUserHome, initScriptsDir) { initializeGradleUserHome() {
const gradleProperties = path_1.default.resolve(gradleUserHome, 'gradle.properties'); const actionCacheDir = path_1.default.resolve(this.gradleUserHome, '.gradle-build-action');
const existingGradleProperties = fs_1.default.existsSync(gradleProperties) fs_1.default.mkdirSync(actionCacheDir, { recursive: true });
? fs_1.default.readFileSync(gradleProperties, 'utf8') this.copyInitScripts();
: ''; this.registerToolchains();
if (!existingGradleProperties.includes('org.gradle.java.installations.fromEnv=')) { }
fs_1.default.appendFileSync(gradleProperties, ` copyInitScripts() {
# Auto-detect pre-installed JDKs const initScriptsDir = path_1.default.resolve(this.gradleUserHome, 'init.d');
org.gradle.java.installations.fromEnv=JAVA_HOME_8_X64,JAVA_HOME_11_X64,JAVA_HOME_17_X64 fs_1.default.mkdirSync(initScriptsDir, { recursive: true });
`);
}
const initScriptFilenames = [ const initScriptFilenames = [
'gradle-build-action.build-result-capture.init.gradle', 'gradle-build-action.build-result-capture.init.gradle',
'gradle-build-action.build-result-capture-service.plugin.groovy', 'gradle-build-action.build-result-capture-service.plugin.groovy',
@ -138744,13 +138739,30 @@ org.gradle.java.installations.fromEnv=JAVA_HOME_8_X64,JAVA_HOME_11_X64,JAVA_HOME
'gradle-build-action.inject-gradle-enterprise.init.gradle' 'gradle-build-action.inject-gradle-enterprise.init.gradle'
]; ];
for (const initScriptFilename of initScriptFilenames) { for (const initScriptFilename of initScriptFilenames) {
const initScriptContent = this.readInitScriptAsString(initScriptFilename); const initScriptContent = this.readResourceFileAsString('init-scripts', initScriptFilename);
const initScriptPath = path_1.default.resolve(initScriptsDir, initScriptFilename); const initScriptPath = path_1.default.resolve(initScriptsDir, initScriptFilename);
fs_1.default.writeFileSync(initScriptPath, initScriptContent); fs_1.default.writeFileSync(initScriptPath, initScriptContent);
} }
} }
readInitScriptAsString(resource) { registerToolchains() {
const absolutePath = path_1.default.resolve(__dirname, '..', '..', 'src', 'resources', 'init-scripts', resource); const preInstalledToolchains = this.readResourceFileAsString('toolchains.xml');
const m2dir = path_1.default.resolve(this.userHome, '.m2');
const toolchainXmlTarget = path_1.default.resolve(m2dir, 'toolchains.xml');
if (!fs_1.default.existsSync(toolchainXmlTarget)) {
fs_1.default.mkdirSync(m2dir, { recursive: true });
fs_1.default.writeFileSync(toolchainXmlTarget, preInstalledToolchains);
core.info(`Wrote default JDK locations to ${toolchainXmlTarget}`);
}
else {
const existingToolchainContent = fs_1.default.readFileSync(toolchainXmlTarget, 'utf8');
const appendedContent = preInstalledToolchains.split('<toolchains>').pop();
const mergedContent = existingToolchainContent.replace('</toolchains>', appendedContent);
fs_1.default.writeFileSync(toolchainXmlTarget, mergedContent);
core.info(`Merged default JDK locations into ${toolchainXmlTarget}`);
}
}
readResourceFileAsString(...paths) {
const absolutePath = path_1.default.resolve(__dirname, '..', '..', 'src', 'resources', ...paths);
return fs_1.default.readFileSync(absolutePath, 'utf8'); return fs_1.default.readFileSync(absolutePath, 'utf8');
} }
debugReportGradleUserHomeSize(label) { debugReportGradleUserHomeSize(label) {
@ -139758,14 +139770,14 @@ const cache_utils_1 = __nccwpck_require__(41678);
const cache_base_1 = __nccwpck_require__(47591); const cache_base_1 = __nccwpck_require__(47591);
const cache_cleaner_1 = __nccwpck_require__(57); const cache_cleaner_1 = __nccwpck_require__(57);
const CACHE_RESTORED_VAR = 'GRADLE_BUILD_ACTION_CACHE_RESTORED'; const CACHE_RESTORED_VAR = 'GRADLE_BUILD_ACTION_CACHE_RESTORED';
function restore(gradleUserHome, cacheListener) { function restore(userHome, gradleUserHome, cacheListener) {
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.');
return; return;
} }
core.exportVariable(CACHE_RESTORED_VAR, true); core.exportVariable(CACHE_RESTORED_VAR, true);
const gradleStateCache = new cache_base_1.GradleStateCache(gradleUserHome); const gradleStateCache = new cache_base_1.GradleStateCache(userHome, gradleUserHome);
if ((0, cache_utils_1.isCacheDisabled)()) { if ((0, cache_utils_1.isCacheDisabled)()) {
core.info('Cache is disabled: will not restore state from previous builds.'); core.info('Cache is disabled: will not restore state from previous builds.');
gradleStateCache.init(); gradleStateCache.init();
@ -139800,7 +139812,7 @@ function restore(gradleUserHome, cacheListener) {
}); });
} }
exports.restore = restore; exports.restore = restore;
function save(gradleUserHome, cacheListener, daemonController) { function save(userHome, gradleUserHome, cacheListener, daemonController) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
if ((0, cache_utils_1.isCacheDisabled)()) { if ((0, cache_utils_1.isCacheDisabled)()) {
core.info('Cache is disabled: will not save state for later builds.'); core.info('Cache is disabled: will not save state for later builds.');
@ -139827,7 +139839,7 @@ function save(gradleUserHome, cacheListener, daemonController) {
} }
} }
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(userHome, gradleUserHome).save(cacheListener);
})); }));
}); });
} }
@ -141052,10 +141064,12 @@ const build_results_1 = __nccwpck_require__(82107);
const cache_reporting_1 = __nccwpck_require__(66674); const cache_reporting_1 = __nccwpck_require__(66674);
const daemon_controller_1 = __nccwpck_require__(85146); const daemon_controller_1 = __nccwpck_require__(85146);
const GRADLE_SETUP_VAR = 'GRADLE_BUILD_ACTION_SETUP_COMPLETED'; const GRADLE_SETUP_VAR = 'GRADLE_BUILD_ACTION_SETUP_COMPLETED';
const USER_HOME = 'USER_HOME';
const GRADLE_USER_HOME = 'GRADLE_USER_HOME'; const GRADLE_USER_HOME = 'GRADLE_USER_HOME';
const CACHE_LISTENER = 'CACHE_LISTENER'; const CACHE_LISTENER = 'CACHE_LISTENER';
function setup() { function setup() {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
const userHome = yield determineUserHome();
const gradleUserHome = yield determineGradleUserHome(); const gradleUserHome = yield determineGradleUserHome();
if (process.env[GRADLE_SETUP_VAR]) { if (process.env[GRADLE_SETUP_VAR]) {
core.info('Gradle setup only performed on first gradle-build-action step in workflow.'); core.info('Gradle setup only performed on first gradle-build-action step in workflow.');
@ -141063,9 +141077,10 @@ function setup() {
} }
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(USER_HOME, userHome);
core.saveState(GRADLE_USER_HOME, gradleUserHome); core.saveState(GRADLE_USER_HOME, gradleUserHome);
const cacheListener = new cache_reporting_1.CacheListener(); const cacheListener = new cache_reporting_1.CacheListener();
yield caches.restore(gradleUserHome, cacheListener); yield caches.restore(userHome, gradleUserHome, cacheListener);
core.saveState(CACHE_LISTENER, cacheListener.stringify()); core.saveState(CACHE_LISTENER, cacheListener.stringify());
yield dependencyGraph.setup(params.getDependencyGraphOption()); yield dependencyGraph.setup(params.getDependencyGraphOption());
}); });
@ -141079,10 +141094,11 @@ function complete() {
} }
core.info('In post-action step'); core.info('In post-action step');
const buildResults = (0, build_results_1.loadBuildResults)(); const buildResults = (0, build_results_1.loadBuildResults)();
const userHome = core.getState(USER_HOME);
const gradleUserHome = core.getState(GRADLE_USER_HOME); const gradleUserHome = core.getState(GRADLE_USER_HOME);
const cacheListener = cache_reporting_1.CacheListener.rehydrate(core.getState(CACHE_LISTENER)); const cacheListener = cache_reporting_1.CacheListener.rehydrate(core.getState(CACHE_LISTENER));
const daemonController = new daemon_controller_1.DaemonController(buildResults); const daemonController = new daemon_controller_1.DaemonController(buildResults);
yield caches.save(gradleUserHome, cacheListener, daemonController); yield caches.save(userHome, gradleUserHome, cacheListener, daemonController);
yield jobSummary.generateJobSummary(buildResults, cacheListener); yield jobSummary.generateJobSummary(buildResults, cacheListener);
yield dependencyGraph.complete(params.getDependencyGraphOption()); yield dependencyGraph.complete(params.getDependencyGraphOption());
core.info('Completed post-action step'); core.info('Completed post-action step');

File diff suppressed because one or more lines are too long

68
dist/post/index.js vendored
View file

@ -136052,17 +136052,14 @@ const cache_extract_entries_1 = __nccwpck_require__(76161);
const RESTORED_CACHE_KEY_KEY = 'restored-cache-key'; const RESTORED_CACHE_KEY_KEY = 'restored-cache-key';
exports.META_FILE_DIR = '.gradle-build-action'; exports.META_FILE_DIR = '.gradle-build-action';
class GradleStateCache { class GradleStateCache {
constructor(gradleUserHome) { constructor(userHome, gradleUserHome) {
this.userHome = userHome;
this.gradleUserHome = gradleUserHome; this.gradleUserHome = gradleUserHome;
this.cacheName = 'gradle'; this.cacheName = 'gradle';
this.cacheDescription = 'Gradle User Home'; this.cacheDescription = 'Gradle User Home';
} }
init() { init() {
const actionCacheDir = path_1.default.resolve(this.gradleUserHome, '.gradle-build-action'); this.initializeGradleUserHome();
fs_1.default.mkdirSync(actionCacheDir, { recursive: true });
const initScriptsDir = path_1.default.resolve(this.gradleUserHome, 'init.d');
fs_1.default.mkdirSync(initScriptsDir, { recursive: true });
this.initializeGradleUserHome(this.gradleUserHome, initScriptsDir);
const encryptionKey = params.getCacheEncryptionKey(); const encryptionKey = params.getCacheEncryptionKey();
if (encryptionKey) { if (encryptionKey) {
core.exportVariable('GRADLE_ENCRYPTION_KEY', encryptionKey); core.exportVariable('GRADLE_ENCRYPTION_KEY', encryptionKey);
@ -136178,17 +136175,15 @@ class GradleStateCache {
} }
return path_1.default.resolve(this.gradleUserHome, rawPath); return path_1.default.resolve(this.gradleUserHome, rawPath);
} }
initializeGradleUserHome(gradleUserHome, initScriptsDir) { initializeGradleUserHome() {
const gradleProperties = path_1.default.resolve(gradleUserHome, 'gradle.properties'); const actionCacheDir = path_1.default.resolve(this.gradleUserHome, '.gradle-build-action');
const existingGradleProperties = fs_1.default.existsSync(gradleProperties) fs_1.default.mkdirSync(actionCacheDir, { recursive: true });
? fs_1.default.readFileSync(gradleProperties, 'utf8') this.copyInitScripts();
: ''; this.registerToolchains();
if (!existingGradleProperties.includes('org.gradle.java.installations.fromEnv=')) { }
fs_1.default.appendFileSync(gradleProperties, ` copyInitScripts() {
# Auto-detect pre-installed JDKs const initScriptsDir = path_1.default.resolve(this.gradleUserHome, 'init.d');
org.gradle.java.installations.fromEnv=JAVA_HOME_8_X64,JAVA_HOME_11_X64,JAVA_HOME_17_X64 fs_1.default.mkdirSync(initScriptsDir, { recursive: true });
`);
}
const initScriptFilenames = [ const initScriptFilenames = [
'gradle-build-action.build-result-capture.init.gradle', 'gradle-build-action.build-result-capture.init.gradle',
'gradle-build-action.build-result-capture-service.plugin.groovy', 'gradle-build-action.build-result-capture-service.plugin.groovy',
@ -136197,13 +136192,30 @@ org.gradle.java.installations.fromEnv=JAVA_HOME_8_X64,JAVA_HOME_11_X64,JAVA_HOME
'gradle-build-action.inject-gradle-enterprise.init.gradle' 'gradle-build-action.inject-gradle-enterprise.init.gradle'
]; ];
for (const initScriptFilename of initScriptFilenames) { for (const initScriptFilename of initScriptFilenames) {
const initScriptContent = this.readInitScriptAsString(initScriptFilename); const initScriptContent = this.readResourceFileAsString('init-scripts', initScriptFilename);
const initScriptPath = path_1.default.resolve(initScriptsDir, initScriptFilename); const initScriptPath = path_1.default.resolve(initScriptsDir, initScriptFilename);
fs_1.default.writeFileSync(initScriptPath, initScriptContent); fs_1.default.writeFileSync(initScriptPath, initScriptContent);
} }
} }
readInitScriptAsString(resource) { registerToolchains() {
const absolutePath = path_1.default.resolve(__dirname, '..', '..', 'src', 'resources', 'init-scripts', resource); const preInstalledToolchains = this.readResourceFileAsString('toolchains.xml');
const m2dir = path_1.default.resolve(this.userHome, '.m2');
const toolchainXmlTarget = path_1.default.resolve(m2dir, 'toolchains.xml');
if (!fs_1.default.existsSync(toolchainXmlTarget)) {
fs_1.default.mkdirSync(m2dir, { recursive: true });
fs_1.default.writeFileSync(toolchainXmlTarget, preInstalledToolchains);
core.info(`Wrote default JDK locations to ${toolchainXmlTarget}`);
}
else {
const existingToolchainContent = fs_1.default.readFileSync(toolchainXmlTarget, 'utf8');
const appendedContent = preInstalledToolchains.split('<toolchains>').pop();
const mergedContent = existingToolchainContent.replace('</toolchains>', appendedContent);
fs_1.default.writeFileSync(toolchainXmlTarget, mergedContent);
core.info(`Merged default JDK locations into ${toolchainXmlTarget}`);
}
}
readResourceFileAsString(...paths) {
const absolutePath = path_1.default.resolve(__dirname, '..', '..', 'src', 'resources', ...paths);
return fs_1.default.readFileSync(absolutePath, 'utf8'); return fs_1.default.readFileSync(absolutePath, 'utf8');
} }
debugReportGradleUserHomeSize(label) { debugReportGradleUserHomeSize(label) {
@ -137211,14 +137223,14 @@ const cache_utils_1 = __nccwpck_require__(41678);
const cache_base_1 = __nccwpck_require__(47591); const cache_base_1 = __nccwpck_require__(47591);
const cache_cleaner_1 = __nccwpck_require__(57); const cache_cleaner_1 = __nccwpck_require__(57);
const CACHE_RESTORED_VAR = 'GRADLE_BUILD_ACTION_CACHE_RESTORED'; const CACHE_RESTORED_VAR = 'GRADLE_BUILD_ACTION_CACHE_RESTORED';
function restore(gradleUserHome, cacheListener) { function restore(userHome, gradleUserHome, cacheListener) {
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.');
return; return;
} }
core.exportVariable(CACHE_RESTORED_VAR, true); core.exportVariable(CACHE_RESTORED_VAR, true);
const gradleStateCache = new cache_base_1.GradleStateCache(gradleUserHome); const gradleStateCache = new cache_base_1.GradleStateCache(userHome, gradleUserHome);
if ((0, cache_utils_1.isCacheDisabled)()) { if ((0, cache_utils_1.isCacheDisabled)()) {
core.info('Cache is disabled: will not restore state from previous builds.'); core.info('Cache is disabled: will not restore state from previous builds.');
gradleStateCache.init(); gradleStateCache.init();
@ -137253,7 +137265,7 @@ function restore(gradleUserHome, cacheListener) {
}); });
} }
exports.restore = restore; exports.restore = restore;
function save(gradleUserHome, cacheListener, daemonController) { function save(userHome, gradleUserHome, cacheListener, daemonController) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
if ((0, cache_utils_1.isCacheDisabled)()) { if ((0, cache_utils_1.isCacheDisabled)()) {
core.info('Cache is disabled: will not save state for later builds.'); core.info('Cache is disabled: will not save state for later builds.');
@ -137280,7 +137292,7 @@ function save(gradleUserHome, cacheListener, daemonController) {
} }
} }
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(userHome, gradleUserHome).save(cacheListener);
})); }));
}); });
} }
@ -138137,10 +138149,12 @@ const build_results_1 = __nccwpck_require__(82107);
const cache_reporting_1 = __nccwpck_require__(66674); const cache_reporting_1 = __nccwpck_require__(66674);
const daemon_controller_1 = __nccwpck_require__(85146); const daemon_controller_1 = __nccwpck_require__(85146);
const GRADLE_SETUP_VAR = 'GRADLE_BUILD_ACTION_SETUP_COMPLETED'; const GRADLE_SETUP_VAR = 'GRADLE_BUILD_ACTION_SETUP_COMPLETED';
const USER_HOME = 'USER_HOME';
const GRADLE_USER_HOME = 'GRADLE_USER_HOME'; const GRADLE_USER_HOME = 'GRADLE_USER_HOME';
const CACHE_LISTENER = 'CACHE_LISTENER'; const CACHE_LISTENER = 'CACHE_LISTENER';
function setup() { function setup() {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
const userHome = yield determineUserHome();
const gradleUserHome = yield determineGradleUserHome(); const gradleUserHome = yield determineGradleUserHome();
if (process.env[GRADLE_SETUP_VAR]) { if (process.env[GRADLE_SETUP_VAR]) {
core.info('Gradle setup only performed on first gradle-build-action step in workflow.'); core.info('Gradle setup only performed on first gradle-build-action step in workflow.');
@ -138148,9 +138162,10 @@ function setup() {
} }
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(USER_HOME, userHome);
core.saveState(GRADLE_USER_HOME, gradleUserHome); core.saveState(GRADLE_USER_HOME, gradleUserHome);
const cacheListener = new cache_reporting_1.CacheListener(); const cacheListener = new cache_reporting_1.CacheListener();
yield caches.restore(gradleUserHome, cacheListener); yield caches.restore(userHome, gradleUserHome, cacheListener);
core.saveState(CACHE_LISTENER, cacheListener.stringify()); core.saveState(CACHE_LISTENER, cacheListener.stringify());
yield dependencyGraph.setup(params.getDependencyGraphOption()); yield dependencyGraph.setup(params.getDependencyGraphOption());
}); });
@ -138164,10 +138179,11 @@ function complete() {
} }
core.info('In post-action step'); core.info('In post-action step');
const buildResults = (0, build_results_1.loadBuildResults)(); const buildResults = (0, build_results_1.loadBuildResults)();
const userHome = core.getState(USER_HOME);
const gradleUserHome = core.getState(GRADLE_USER_HOME); const gradleUserHome = core.getState(GRADLE_USER_HOME);
const cacheListener = cache_reporting_1.CacheListener.rehydrate(core.getState(CACHE_LISTENER)); const cacheListener = cache_reporting_1.CacheListener.rehydrate(core.getState(CACHE_LISTENER));
const daemonController = new daemon_controller_1.DaemonController(buildResults); const daemonController = new daemon_controller_1.DaemonController(buildResults);
yield caches.save(gradleUserHome, cacheListener, daemonController); yield caches.save(userHome, gradleUserHome, cacheListener, daemonController);
yield jobSummary.generateJobSummary(buildResults, cacheListener); yield jobSummary.generateJobSummary(buildResults, cacheListener);
yield dependencyGraph.complete(params.getDependencyGraphOption()); yield dependencyGraph.complete(params.getDependencyGraphOption());
core.info('Completed post-action step'); core.info('Completed post-action step');

File diff suppressed because one or more lines are too long

View file

@ -17,23 +17,18 @@ export class GradleStateCache {
private cacheName: string private cacheName: string
private cacheDescription: string private cacheDescription: string
protected readonly userHome: string
protected readonly gradleUserHome: string protected readonly gradleUserHome: string
constructor(gradleUserHome: string) { constructor(userHome: string, gradleUserHome: string) {
this.userHome = userHome
this.gradleUserHome = gradleUserHome this.gradleUserHome = gradleUserHome
this.cacheName = 'gradle' this.cacheName = 'gradle'
this.cacheDescription = 'Gradle User Home' this.cacheDescription = 'Gradle User Home'
} }
init(): void { init(): void {
// Copy init-scripts to Gradle User Home this.initializeGradleUserHome()
const actionCacheDir = path.resolve(this.gradleUserHome, '.gradle-build-action')
fs.mkdirSync(actionCacheDir, {recursive: true})
const initScriptsDir = path.resolve(this.gradleUserHome, 'init.d')
fs.mkdirSync(initScriptsDir, {recursive: true})
this.initializeGradleUserHome(this.gradleUserHome, initScriptsDir)
// Export the GRADLE_ENCRYPTION_KEY variable if provided // Export the GRADLE_ENCRYPTION_KEY variable if provided
const encryptionKey = params.getCacheEncryptionKey() const encryptionKey = params.getCacheEncryptionKey()
@ -188,23 +183,21 @@ export class GradleStateCache {
return path.resolve(this.gradleUserHome, rawPath) return path.resolve(this.gradleUserHome, rawPath)
} }
private initializeGradleUserHome(gradleUserHome: string, initScriptsDir: string): void { private initializeGradleUserHome(): void {
// Ensure that pre-installed java versions are detected. Only add property if it isn't already defined. // Create a directory for storing action metadata
const gradleProperties = path.resolve(gradleUserHome, 'gradle.properties') const actionCacheDir = path.resolve(this.gradleUserHome, '.gradle-build-action')
const existingGradleProperties = fs.existsSync(gradleProperties) fs.mkdirSync(actionCacheDir, {recursive: true})
? fs.readFileSync(gradleProperties, 'utf8')
: ''
if (!existingGradleProperties.includes('org.gradle.java.installations.fromEnv=')) {
fs.appendFileSync(
gradleProperties,
`
# Auto-detect pre-installed JDKs
org.gradle.java.installations.fromEnv=JAVA_HOME_8_X64,JAVA_HOME_11_X64,JAVA_HOME_17_X64
`
)
}
// Copy init scripts from src/resources this.copyInitScripts()
// Copy the default toolchain definitions to `~/.m2/toolchains.xml`
this.registerToolchains()
}
private copyInitScripts(): void {
// Copy init scripts from src/resources to Gradle UserHome
const initScriptsDir = path.resolve(this.gradleUserHome, 'init.d')
fs.mkdirSync(initScriptsDir, {recursive: true})
const initScriptFilenames = [ const initScriptFilenames = [
'gradle-build-action.build-result-capture.init.gradle', 'gradle-build-action.build-result-capture.init.gradle',
'gradle-build-action.build-result-capture-service.plugin.groovy', 'gradle-build-action.build-result-capture-service.plugin.groovy',
@ -213,15 +206,36 @@ org.gradle.java.installations.fromEnv=JAVA_HOME_8_X64,JAVA_HOME_11_X64,JAVA_HOME
'gradle-build-action.inject-gradle-enterprise.init.gradle' 'gradle-build-action.inject-gradle-enterprise.init.gradle'
] ]
for (const initScriptFilename of initScriptFilenames) { for (const initScriptFilename of initScriptFilenames) {
const initScriptContent = this.readInitScriptAsString(initScriptFilename) const initScriptContent = this.readResourceFileAsString('init-scripts', initScriptFilename)
const initScriptPath = path.resolve(initScriptsDir, initScriptFilename) const initScriptPath = path.resolve(initScriptsDir, initScriptFilename)
fs.writeFileSync(initScriptPath, initScriptContent) fs.writeFileSync(initScriptPath, initScriptContent)
} }
} }
private readInitScriptAsString(resource: string): string { private registerToolchains(): void {
const preInstalledToolchains = this.readResourceFileAsString('toolchains.xml')
const m2dir = path.resolve(this.userHome, '.m2')
const toolchainXmlTarget = path.resolve(m2dir, 'toolchains.xml')
if (!fs.existsSync(toolchainXmlTarget)) {
// Write a new toolchains.xml file if it doesn't exist
fs.mkdirSync(m2dir, {recursive: true})
fs.writeFileSync(toolchainXmlTarget, preInstalledToolchains)
core.info(`Wrote default JDK locations to ${toolchainXmlTarget}`)
} else {
// Merge into an existing toolchains.xml file
const existingToolchainContent = fs.readFileSync(toolchainXmlTarget, 'utf8')
const appendedContent = preInstalledToolchains.split('<toolchains>').pop()!
const mergedContent = existingToolchainContent.replace('</toolchains>', appendedContent)
fs.writeFileSync(toolchainXmlTarget, mergedContent)
core.info(`Merged default JDK locations into ${toolchainXmlTarget}`)
}
}
private readResourceFileAsString(...paths: string[]): string {
// Resolving relative to __dirname will allow node to find the resource at runtime // Resolving relative to __dirname will allow node to find the resource at runtime
const absolutePath = path.resolve(__dirname, '..', '..', 'src', 'resources', 'init-scripts', resource) const absolutePath = path.resolve(__dirname, '..', '..', 'src', 'resources', ...paths)
return fs.readFileSync(absolutePath, 'utf8') return fs.readFileSync(absolutePath, 'utf8')
} }

View file

@ -13,7 +13,7 @@ import {CacheCleaner} from './cache-cleaner'
const CACHE_RESTORED_VAR = 'GRADLE_BUILD_ACTION_CACHE_RESTORED' const CACHE_RESTORED_VAR = 'GRADLE_BUILD_ACTION_CACHE_RESTORED'
export async function restore(gradleUserHome: string, cacheListener: CacheListener): Promise<void> { export async function restore(userHome: string, 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.')
@ -21,7 +21,7 @@ export async function restore(gradleUserHome: string, cacheListener: CacheListen
} }
core.exportVariable(CACHE_RESTORED_VAR, true) core.exportVariable(CACHE_RESTORED_VAR, true)
const gradleStateCache = new GradleStateCache(gradleUserHome) const gradleStateCache = new GradleStateCache(userHome, gradleUserHome)
if (isCacheDisabled()) { if (isCacheDisabled()) {
core.info('Cache is disabled: will not restore state from previous builds.') core.info('Cache is disabled: will not restore state from previous builds.')
@ -65,6 +65,7 @@ export async function restore(gradleUserHome: string, cacheListener: CacheListen
} }
export async function save( export async function save(
userHome: string,
gradleUserHome: string, gradleUserHome: string,
cacheListener: CacheListener, cacheListener: CacheListener,
daemonController: DaemonController daemonController: DaemonController
@ -98,6 +99,6 @@ export async function save(
} }
await core.group('Caching Gradle state', async () => { await core.group('Caching Gradle state', async () => {
return new GradleStateCache(gradleUserHome).save(cacheListener) return new GradleStateCache(userHome, gradleUserHome).save(cacheListener)
}) })
} }

View file

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<toolchains>
<!-- JDK Toolchains installed by default on GitHub-hosted runners -->
<toolchain>
<type>jdk</type>
<provides>
<version>8</version>
<vendor>Eclipse Temurin</vendor>
</provides>
<configuration>
<jdkHome>${env.JAVA_HOME_8_X64}</jdkHome>
</configuration>
</toolchain>
<toolchain>
<type>jdk</type>
<provides>
<version>11</version>
<vendor>Eclipse Temurin</vendor>
</provides>
<configuration>
<jdkHome>${env.JAVA_HOME_11_X64}</jdkHome>
</configuration>
</toolchain>
<toolchain>
<type>jdk</type>
<provides>
<version>17</version>
<vendor>Eclipse Temurin</vendor>
</provides>
<configuration>
<jdkHome>${env.JAVA_HOME_17_X64}</jdkHome>
</configuration>
</toolchain>
<toolchain>
<type>jdk</type>
<provides>
<version>21</version>
<vendor>Eclipse Temurin</vendor>
</provides>
<configuration>
<jdkHome>${env.JAVA_HOME_21_X64}</jdkHome>
</configuration>
</toolchain>
</toolchains>

View file

@ -13,10 +13,12 @@ import {CacheListener} from './cache-reporting'
import {DaemonController} from './daemon-controller' import {DaemonController} from './daemon-controller'
const GRADLE_SETUP_VAR = 'GRADLE_BUILD_ACTION_SETUP_COMPLETED' const GRADLE_SETUP_VAR = 'GRADLE_BUILD_ACTION_SETUP_COMPLETED'
const USER_HOME = 'USER_HOME'
const GRADLE_USER_HOME = 'GRADLE_USER_HOME' const GRADLE_USER_HOME = 'GRADLE_USER_HOME'
const CACHE_LISTENER = 'CACHE_LISTENER' const CACHE_LISTENER = 'CACHE_LISTENER'
export async function setup(): Promise<void> { export async function setup(): Promise<void> {
const userHome = await determineUserHome()
const gradleUserHome = await determineGradleUserHome() const gradleUserHome = await determineGradleUserHome()
// Bypass setup on all but first action step in workflow. // Bypass setup on all but first action step in workflow.
@ -29,11 +31,12 @@ export async function setup(): Promise<void> {
// Record setup complete: visible in post-action, to control action completion // Record setup complete: visible in post-action, to control action completion
core.saveState(GRADLE_SETUP_VAR, true) core.saveState(GRADLE_SETUP_VAR, true)
// Save the Gradle User Home for use in the post-action step. // Save the User Home and Gradle User Home for use in the post-action step.
core.saveState(USER_HOME, userHome)
core.saveState(GRADLE_USER_HOME, gradleUserHome) core.saveState(GRADLE_USER_HOME, gradleUserHome)
const cacheListener = new CacheListener() const cacheListener = new CacheListener()
await caches.restore(gradleUserHome, cacheListener) await caches.restore(userHome, gradleUserHome, cacheListener)
core.saveState(CACHE_LISTENER, cacheListener.stringify()) core.saveState(CACHE_LISTENER, cacheListener.stringify())
@ -49,11 +52,12 @@ export async function complete(): Promise<void> {
const buildResults = loadBuildResults() const buildResults = loadBuildResults()
const userHome = core.getState(USER_HOME)
const gradleUserHome = core.getState(GRADLE_USER_HOME) const gradleUserHome = core.getState(GRADLE_USER_HOME)
const cacheListener: CacheListener = CacheListener.rehydrate(core.getState(CACHE_LISTENER)) const cacheListener: CacheListener = CacheListener.rehydrate(core.getState(CACHE_LISTENER))
const daemonController = new DaemonController(buildResults) const daemonController = new DaemonController(buildResults)
await caches.save(gradleUserHome, cacheListener, daemonController) await caches.save(userHome, gradleUserHome, cacheListener, daemonController)
await jobSummary.generateJobSummary(buildResults, cacheListener) await jobSummary.generateJobSummary(buildResults, cacheListener)