Skip to content

Commit

Permalink
Create toolchains.xml dynamically based on envs (#150)
Browse files Browse the repository at this point in the history
Different runners have different JDKs installed, so using a hard-coded
list for
`toolchains.xml` doesn't work. With this change, the file is generated
based on the available `JAVA_HOME_*` environment variables.

Fixes #89 

Thanks @hfhbd for the contribution!

Co-authored-by: hfhbd <22521688+hfhbd@users.noreply.github.com>
  • Loading branch information
bigdaz and hfhbd committed Apr 10, 2024
1 parent 6832731 commit e21decc
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 54 deletions.
16 changes: 6 additions & 10 deletions sources/src/caching/gradle-user-home-cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ import fs from 'fs'
import {generateCacheKey} from './cache-key'
import {CacheListener} from './cache-reporting'
import {saveCache, restoreCache, cacheDebug, isCacheDebuggingEnabled, tryDelete} from './cache-utils'
import {GradleHomeEntryExtractor, ConfigurationCacheEntryExtractor} from './gradle-home-extry-extractor'
import {CacheConfig} from '../configuration'
import {GradleHomeEntryExtractor, ConfigurationCacheEntryExtractor} from './gradle-home-extry-extractor'
import {getPredefinedToolchains, readResourceFileAsString} from './gradle-user-home-utils'

const RESTORED_CACHE_KEY_KEY = 'restored-cache-key'

Expand Down Expand Up @@ -211,14 +212,16 @@ export class GradleUserHomeCache {
'gradle-actions.inject-develocity.init.gradle'
]
for (const initScriptFilename of initScriptFilenames) {
const initScriptContent = this.readResourceFileAsString('init-scripts', initScriptFilename)
const initScriptContent = readResourceFileAsString('init-scripts', initScriptFilename)
const initScriptPath = path.resolve(initScriptsDir, initScriptFilename)
fs.writeFileSync(initScriptPath, initScriptContent)
}
}

private registerToolchains(): void {
const preInstalledToolchains = this.readResourceFileAsString('toolchains.xml')
const preInstalledToolchains: string | null = getPredefinedToolchains()
if (preInstalledToolchains == null) return

const m2dir = path.resolve(this.userHome, '.m2')
const toolchainXmlTarget = path.resolve(m2dir, 'toolchains.xml')
if (!fs.existsSync(toolchainXmlTarget)) {
Expand All @@ -238,13 +241,6 @@ export class GradleUserHomeCache {
}
}

// TODO:DAZ Move this to a utility class
private readResourceFileAsString(...paths: string[]): string {
// Resolving relative to __dirname will allow node to find the resource at runtime
const absolutePath = path.resolve(__dirname, '..', '..', '..', 'sources', 'src', 'resources', ...paths)
return fs.readFileSync(absolutePath, 'utf8')
}

/**
* When the GitHub environment ACTIONS_RUNNER_DEBUG is true, run Gradle with --info and --stacktrace.
* see https://docs.github.com/en/actions/monitoring-and-troubleshooting-workflows/enabling-debug-logging
Expand Down
44 changes: 44 additions & 0 deletions sources/src/caching/gradle-user-home-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import path from 'path'
import fs from 'fs'

export function readResourceFileAsString(...paths: string[]): string {
// Resolving relative to __dirname will allow node to find the resource at runtime
const absolutePath = path.resolve(__dirname, '..', '..', '..', 'sources', 'src', 'resources', ...paths)
return fs.readFileSync(absolutePath, 'utf8')
}

/**
* Iterate over all `JAVA_HOME_{version}_{arch}` envs and construct the toolchain.xml.
*
* @VisibleForTesting
*/
export function getPredefinedToolchains(): string | null {
const javaHomeEnvs: string[] = []
for (const javaHomeEnvsKey in process.env) {
if (javaHomeEnvsKey.startsWith('JAVA_HOME_')) {
javaHomeEnvs.push(javaHomeEnvsKey)
}
}
if (javaHomeEnvs.length === 0) {
return null
}
// language=XML
let toolchainsXml = `<?xml version="1.0" encoding="UTF-8"?>
<toolchains>
<!-- JDK Toolchains installed by default on GitHub-hosted runners -->
`
for (const javaHomeEnv of javaHomeEnvs) {
const version = javaHomeEnv.match(/JAVA_HOME_(\d+)_/)?.[1]!
toolchainsXml += ` <toolchain>
<type>jdk</type>
<provides>
<version>${version}</version>
</provides>
<configuration>
<jdkHome>\${env.${javaHomeEnv}}</jdkHome>
</configuration>
</toolchain>\n`
}
toolchainsXml += `</toolchains>\n`
return toolchainsXml
}
44 changes: 0 additions & 44 deletions sources/src/resources/toolchains.xml

This file was deleted.

65 changes: 65 additions & 0 deletions sources/test/jest/predefined-toolchains.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import {getPredefinedToolchains} from "../../src/caching/gradle-user-home-utils";

describe('predefined-toolchains', () => {
const OLD_ENV = process.env
afterAll(() => {
process.env = OLD_ENV
});

describe('returns', () => {
it('null if no JAVA_HOME_ envs are set', async () => {
jest.resetModules()
process.env = {
"JAVA_HOME": "/jdks/foo_8"
}

const predefinedToolchains = getPredefinedToolchains()
expect(predefinedToolchains).toBe(null)
})
it('valid toolchains.xml if JAVA_HOME_ envs are set', async () => {
jest.resetModules()
process.env = {
"JAVA_HOME": "/jdks/foo_8",
"JAVA_HOME_8_X64": "/jdks/foo_8",
"JAVA_HOME_11_X64": "/jdks/foo_11",
"JAVA_HOME_21_ARM64": "/jdks/foo_21",
}

const predefinedToolchains = getPredefinedToolchains()
expect(predefinedToolchains).toBe(
// language=XML
`<?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>
</provides>
<configuration>
<jdkHome>\${env.JAVA_HOME_8_X64}</jdkHome>
</configuration>
</toolchain>
<toolchain>
<type>jdk</type>
<provides>
<version>11</version>
</provides>
<configuration>
<jdkHome>\${env.JAVA_HOME_11_X64}</jdkHome>
</configuration>
</toolchain>
<toolchain>
<type>jdk</type>
<provides>
<version>21</version>
</provides>
<configuration>
<jdkHome>\${env.JAVA_HOME_21_ARM64}</jdkHome>
</configuration>
</toolchain>
</toolchains>
`)
})
})
})

0 comments on commit e21decc

Please sign in to comment.