2021-04-05 13:02:27 +03:00
import * as core from '@actions/core' ;
import * as tc from '@actions/tool-cache' ;
import fs from 'fs' ;
import path from 'path' ;
import semver from 'semver' ;
2023-03-09 14:49:35 +02:00
import { JavaBase } from '../base-installer' ;
import { IAdoptAvailableVersions } from './models' ;
import {
JavaDownloadRelease ,
JavaInstallerOptions ,
JavaInstallerResults
} from '../base-models' ;
import {
extractJdkFile ,
Implement pagination with link headers for Adoptium based apis (#1014)
* Use Link headers for Adoptium pagination
* Fix nullable pagination URL types and rebuild dist
* Add 1000-page safeguard for JetBrains pagination
* Adjust plan for pagination safeguard scope
* Move pagination safeguard to non-JetBrains installers
* Add 1000-page safeguard to Adopt Temurin and Semeru pagination
* Fix Prettier formatting in adopt, semeru, and temurin installer files
* Fix CI audit failure by updating vulnerable transitive deps
* Address PR review: RFC-compliant Link parsing, SSRF validation, centralized constant
- Make getNextPageUrlFromLinkHeader RFC 8288 compliant by splitting
link-values and checking for rel=next anywhere in the parameters,
not just as the first parameter after the semicolon.
- Add validatePaginationUrl utility to reject pagination URLs that
point to unexpected origins (SSRF mitigation).
- Centralize MAX_PAGINATION_PAGES in util.ts instead of duplicating
across Adopt, Semeru, and Temurin installers.
- Add tests for rel not being the first parameter, and for URL
origin validation.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address code review feedback on pagination implementation
- Tighten rel regex with word boundary to prevent false positives
(e.g., rel="nextsomething" no longer matches).
- Use parsed.origin comparison in validatePaginationUrl to correctly
handle explicit default ports (e.g., :443 for HTTPS).
- Fix pagination safeguard tests to use same-origin URLs so they
actually exercise the 1000-page limit instead of being rejected
by origin validation on the first request.
- Add test for rel="nextsomething" not matching.
- Add test for explicit default port acceptance.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix prettier formatting in util.test.ts
* Rebuild dist/ to fix check-dist CI failure
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-12 11:50:16 +01:00
getNextPageUrlFromLinkHeader ,
2023-03-09 14:49:35 +02:00
getDownloadArchiveExtension ,
2024-10-11 03:02:25 +05:30
isVersionSatisfies ,
Implement pagination with link headers for Adoptium based apis (#1014)
* Use Link headers for Adoptium pagination
* Fix nullable pagination URL types and rebuild dist
* Add 1000-page safeguard for JetBrains pagination
* Adjust plan for pagination safeguard scope
* Move pagination safeguard to non-JetBrains installers
* Add 1000-page safeguard to Adopt Temurin and Semeru pagination
* Fix Prettier formatting in adopt, semeru, and temurin installer files
* Fix CI audit failure by updating vulnerable transitive deps
* Address PR review: RFC-compliant Link parsing, SSRF validation, centralized constant
- Make getNextPageUrlFromLinkHeader RFC 8288 compliant by splitting
link-values and checking for rel=next anywhere in the parameters,
not just as the first parameter after the semicolon.
- Add validatePaginationUrl utility to reject pagination URLs that
point to unexpected origins (SSRF mitigation).
- Centralize MAX_PAGINATION_PAGES in util.ts instead of duplicating
across Adopt, Semeru, and Temurin installers.
- Add tests for rel not being the first parameter, and for URL
origin validation.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address code review feedback on pagination implementation
- Tighten rel regex with word boundary to prevent false positives
(e.g., rel="nextsomething" no longer matches).
- Use parsed.origin comparison in validatePaginationUrl to correctly
handle explicit default ports (e.g., :443 for HTTPS).
- Fix pagination safeguard tests to use same-origin URLs so they
actually exercise the 1000-page limit instead of being rejected
by origin validation on the first request.
- Add test for rel="nextsomething" not matching.
- Add test for explicit default port acceptance.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix prettier formatting in util.test.ts
* Rebuild dist/ to fix check-dist CI failure
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-12 11:50:16 +01:00
renameWinArchive ,
MAX_PAGINATION_PAGES ,
validatePaginationUrl
2023-03-09 14:49:35 +02:00
} from '../../util' ;
2026-06-12 16:30:59 +01:00
import { TemurinDistribution , TemurinImplementation } from '../temurin/installer' ;
2021-04-05 13:02:27 +03:00
2021-05-17 15:33:21 +02:00
export enum AdoptImplementation {
Hotspot = 'Hotspot' ,
OpenJ9 = 'OpenJ9'
}
2021-04-05 13:02:27 +03:00
export class AdoptDistribution extends JavaBase {
2026-06-12 16:30:59 +01:00
private readonly temurinDistribution : TemurinDistribution | null ;
2021-05-17 15:33:21 +02:00
constructor (
installerOptions : JavaInstallerOptions ,
2026-06-12 16:30:59 +01:00
private readonly jvmImpl : AdoptImplementation ,
temurinDistribution : TemurinDistribution | null = null
2021-05-17 15:33:21 +02:00
) {
super ( ` Adopt- ${ jvmImpl } ` , installerOptions ) ;
2026-06-12 16:30:59 +01:00
if (
temurinDistribution !== null &&
jvmImpl !== AdoptImplementation . Hotspot
) {
throw new Error ( 'Only Hotspot JVM is supported by Temurin.' ) ;
}
// Only use the temurin repo for Hotspot JVMs
this . temurinDistribution =
temurinDistribution ? ?
( jvmImpl === AdoptImplementation . Hotspot
? new TemurinDistribution (
installerOptions ,
TemurinImplementation . Hotspot
)
: null ) ;
2021-04-05 13:02:27 +03:00
}
2023-03-09 14:49:35 +02:00
protected async findPackageForDownload (
version : string
2026-06-12 16:30:59 +01:00
) : Promise < JavaDownloadRelease > {
if ( this . jvmImpl === AdoptImplementation . Hotspot ) {
core . notice (
"AdoptOpenJDK has moved to Eclipse Temurin https://github.com/actions/setup-java#supported-distributions please consider changing to the 'temurin' distribution type in your setup-java configuration."
) ;
}
if (
this . jvmImpl === AdoptImplementation . Hotspot &&
this . temurinDistribution !== null
) {
try {
return await this . temurinDistribution . findPackageForDownload ( version ) ;
} catch ( error ) {
// Log the failure but always fall back to legacy AdoptOpenJDK for resilience
const errorMessage =
error instanceof Error ? error.message : String ( error ) ;
if ( error instanceof Error && error . name === 'VersionNotFoundError' ) {
core . notice (
'The JVM you are looking for could not be found in the Temurin repository, this likely indicates ' +
'that you are using an out of date version of Java, consider updating and moving to using the Temurin distribution type in setup-java.'
) ;
} else {
// Log other errors for debugging but gracefully fall back
core . debug (
` Temurin lookup failed: ${ errorMessage } . Falling back to AdoptOpenJDK API. `
) ;
}
}
}
// failed to find a Temurin version, so fall back to AdoptOpenJDK
return this . findPackageForDownloadOldAdoptOpenJdk ( version ) ;
}
private async findPackageForDownloadOldAdoptOpenJdk (
version : string
2023-03-09 14:49:35 +02:00
) : Promise < JavaDownloadRelease > {
2021-04-05 13:02:27 +03:00
const availableVersionsRaw = await this . getAvailableVersions ( ) ;
const availableVersionsWithBinaries = availableVersionsRaw
. filter ( item = > item . binaries . length > 0 )
. map ( item = > {
return {
version : item.version_data.semver ,
url : item.binaries [ 0 ] . package . link
} as JavaDownloadRelease ;
} ) ;
const satisfiedVersions = availableVersionsWithBinaries
. filter ( item = > isVersionSatisfies ( version , item . version ) )
. sort ( ( a , b ) = > {
return - semver . compareBuild ( a . version , b . version ) ;
} ) ;
2023-03-09 14:49:35 +02:00
const resolvedFullVersion =
satisfiedVersions . length > 0 ? satisfiedVersions [ 0 ] : null ;
2021-04-05 13:02:27 +03:00
if ( ! resolvedFullVersion ) {
2026-04-13 23:14:45 +05:30
const availableVersionStrings = availableVersionsWithBinaries . map (
item = > item . version
2021-04-05 13:02:27 +03:00
) ;
2026-04-13 23:14:45 +05:30
throw this . createVersionNotFoundError ( version , availableVersionStrings ) ;
2021-04-05 13:02:27 +03:00
}
return resolvedFullVersion ;
}
2023-03-09 14:49:35 +02:00
protected async downloadTool (
javaRelease : JavaDownloadRelease
) : Promise < JavaInstallerResults > {
2021-04-05 13:02:27 +03:00
core . info (
` Downloading Java ${ javaRelease . version } ( ${ this . distribution } ) from ${ javaRelease . url } ... `
) ;
2024-10-11 03:02:25 +05:30
let javaArchivePath = await tc . downloadTool ( javaRelease . url ) ;
2021-04-05 13:02:27 +03:00
core . info ( ` Extracting Java archive... ` ) ;
2023-03-09 14:49:35 +02:00
const extension = getDownloadArchiveExtension ( ) ;
2024-10-11 03:02:25 +05:30
if ( process . platform === 'win32' ) {
javaArchivePath = renameWinArchive ( javaArchivePath ) ;
}
2023-03-09 14:49:35 +02:00
const extractedJavaPath = await extractJdkFile ( javaArchivePath , extension ) ;
2021-04-05 13:02:27 +03:00
const archiveName = fs . readdirSync ( extractedJavaPath ) [ 0 ] ;
const archivePath = path . join ( extractedJavaPath , archiveName ) ;
const version = this . getToolcacheVersionName ( javaRelease . version ) ;
2023-03-09 14:49:35 +02:00
const javaPath = await tc . cacheDir (
archivePath ,
this . toolcacheFolderName ,
version ,
this . architecture
) ;
2021-04-05 13:02:27 +03:00
2023-03-09 14:49:35 +02:00
return { version : javaRelease.version , path : javaPath } ;
2021-04-05 13:02:27 +03:00
}
2021-05-17 15:33:21 +02:00
protected get toolcacheFolderName ( ) : string {
if ( this . jvmImpl === AdoptImplementation . Hotspot ) {
// exclude Hotspot postfix from distribution name because Hosted runners have pre-cached Adopt OpenJDK under "Java_Adopt_jdk"
// for more information see: https://github.com/actions/setup-java/pull/155#discussion_r610451063
return ` Java_Adopt_ ${ this . packageType } ` ;
}
return super . toolcacheFolderName ;
}
2021-04-05 13:02:27 +03:00
private async getAvailableVersions ( ) : Promise < IAdoptAvailableVersions [ ] > {
const platform = this . getPlatformOption ( ) ;
2022-10-10 17:47:17 -06:00
const arch = this . distributionArchitecture ( ) ;
2021-04-05 13:02:27 +03:00
const imageType = this . packageType ;
const versionRange = encodeURI ( '[1.0,100.0]' ) ; // retrieve all available versions
const releaseType = this . stable ? 'ga' : 'ea' ;
2022-09-08 15:26:54 +02:00
if ( core . isDebug ( ) ) {
2023-03-09 14:49:35 +02:00
console . time ( 'Retrieving available versions for Adopt took' ) ; // eslint-disable-line no-console
2022-09-08 15:26:54 +02:00
}
2021-04-05 13:02:27 +03:00
const baseRequestArguments = [
` project=jdk ` ,
'vendor=adoptopenjdk' ,
` heap_size=normal ` ,
'sort_method=DEFAULT' ,
'sort_order=DESC' ,
` os= ${ platform } ` ,
` architecture= ${ arch } ` ,
` image_type= ${ imageType } ` ,
2021-05-17 15:33:21 +02:00
` release_type= ${ releaseType } ` ,
` jvm_impl= ${ this . jvmImpl . toLowerCase ( ) } `
2021-04-05 13:02:27 +03:00
] . join ( '&' ) ;
Implement pagination with link headers for Adoptium based apis (#1014)
* Use Link headers for Adoptium pagination
* Fix nullable pagination URL types and rebuild dist
* Add 1000-page safeguard for JetBrains pagination
* Adjust plan for pagination safeguard scope
* Move pagination safeguard to non-JetBrains installers
* Add 1000-page safeguard to Adopt Temurin and Semeru pagination
* Fix Prettier formatting in adopt, semeru, and temurin installer files
* Fix CI audit failure by updating vulnerable transitive deps
* Address PR review: RFC-compliant Link parsing, SSRF validation, centralized constant
- Make getNextPageUrlFromLinkHeader RFC 8288 compliant by splitting
link-values and checking for rel=next anywhere in the parameters,
not just as the first parameter after the semicolon.
- Add validatePaginationUrl utility to reject pagination URLs that
point to unexpected origins (SSRF mitigation).
- Centralize MAX_PAGINATION_PAGES in util.ts instead of duplicating
across Adopt, Semeru, and Temurin installers.
- Add tests for rel not being the first parameter, and for URL
origin validation.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address code review feedback on pagination implementation
- Tighten rel regex with word boundary to prevent false positives
(e.g., rel="nextsomething" no longer matches).
- Use parsed.origin comparison in validatePaginationUrl to correctly
handle explicit default ports (e.g., :443 for HTTPS).
- Fix pagination safeguard tests to use same-origin URLs so they
actually exercise the 1000-page limit instead of being rejected
by origin validation on the first request.
- Add test for rel="nextsomething" not matching.
- Add test for explicit default port acceptance.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix prettier formatting in util.test.ts
* Rebuild dist/ to fix check-dist CI failure
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-12 11:50:16 +01:00
const requestArguments = ` ${ baseRequestArguments } &page_size=20&page=0 ` ;
let availableVersionsUrl : string | null =
` https://api.adoptopenjdk.net/v3/assets/version/ ${ versionRange } ? ${ requestArguments } ` ;
2021-04-05 13:02:27 +03:00
const availableVersions : IAdoptAvailableVersions [ ] = [ ] ;
Implement pagination with link headers for Adoptium based apis (#1014)
* Use Link headers for Adoptium pagination
* Fix nullable pagination URL types and rebuild dist
* Add 1000-page safeguard for JetBrains pagination
* Adjust plan for pagination safeguard scope
* Move pagination safeguard to non-JetBrains installers
* Add 1000-page safeguard to Adopt Temurin and Semeru pagination
* Fix Prettier formatting in adopt, semeru, and temurin installer files
* Fix CI audit failure by updating vulnerable transitive deps
* Address PR review: RFC-compliant Link parsing, SSRF validation, centralized constant
- Make getNextPageUrlFromLinkHeader RFC 8288 compliant by splitting
link-values and checking for rel=next anywhere in the parameters,
not just as the first parameter after the semicolon.
- Add validatePaginationUrl utility to reject pagination URLs that
point to unexpected origins (SSRF mitigation).
- Centralize MAX_PAGINATION_PAGES in util.ts instead of duplicating
across Adopt, Semeru, and Temurin installers.
- Add tests for rel not being the first parameter, and for URL
origin validation.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address code review feedback on pagination implementation
- Tighten rel regex with word boundary to prevent false positives
(e.g., rel="nextsomething" no longer matches).
- Use parsed.origin comparison in validatePaginationUrl to correctly
handle explicit default ports (e.g., :443 for HTTPS).
- Fix pagination safeguard tests to use same-origin URLs so they
actually exercise the 1000-page limit instead of being rejected
by origin validation on the first request.
- Add test for rel="nextsomething" not matching.
- Add test for explicit default port acceptance.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix prettier formatting in util.test.ts
* Rebuild dist/ to fix check-dist CI failure
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-12 11:50:16 +01:00
let pageCount = 0 ;
if ( core . isDebug ( ) ) {
core . debug ( ` Gathering available versions from ' ${ availableVersionsUrl } ' ` ) ;
}
while ( availableVersionsUrl ) {
pageCount ++ ;
const response =
await this . http . getJson < IAdoptAvailableVersions [ ] > (
availableVersionsUrl
2023-03-09 14:49:35 +02:00
) ;
Implement pagination with link headers for Adoptium based apis (#1014)
* Use Link headers for Adoptium pagination
* Fix nullable pagination URL types and rebuild dist
* Add 1000-page safeguard for JetBrains pagination
* Adjust plan for pagination safeguard scope
* Move pagination safeguard to non-JetBrains installers
* Add 1000-page safeguard to Adopt Temurin and Semeru pagination
* Fix Prettier formatting in adopt, semeru, and temurin installer files
* Fix CI audit failure by updating vulnerable transitive deps
* Address PR review: RFC-compliant Link parsing, SSRF validation, centralized constant
- Make getNextPageUrlFromLinkHeader RFC 8288 compliant by splitting
link-values and checking for rel=next anywhere in the parameters,
not just as the first parameter after the semicolon.
- Add validatePaginationUrl utility to reject pagination URLs that
point to unexpected origins (SSRF mitigation).
- Centralize MAX_PAGINATION_PAGES in util.ts instead of duplicating
across Adopt, Semeru, and Temurin installers.
- Add tests for rel not being the first parameter, and for URL
origin validation.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address code review feedback on pagination implementation
- Tighten rel regex with word boundary to prevent false positives
(e.g., rel="nextsomething" no longer matches).
- Use parsed.origin comparison in validatePaginationUrl to correctly
handle explicit default ports (e.g., :443 for HTTPS).
- Fix pagination safeguard tests to use same-origin URLs so they
actually exercise the 1000-page limit instead of being rejected
by origin validation on the first request.
- Add test for rel="nextsomething" not matching.
- Add test for explicit default port acceptance.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix prettier formatting in util.test.ts
* Rebuild dist/ to fix check-dist CI failure
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-12 11:50:16 +01:00
const paginationPage = response . result ;
const nextUrl = getNextPageUrlFromLinkHeader ( response . headers ) ;
if (
nextUrl &&
! validatePaginationUrl ( nextUrl , 'https://api.adoptopenjdk.net' )
) {
core . warning (
` Ignoring pagination link with unexpected origin: ${ nextUrl } `
) ;
availableVersionsUrl = null ;
} else {
availableVersionsUrl = nextUrl ;
2021-04-05 13:02:27 +03:00
}
if ( paginationPage === null || paginationPage . length === 0 ) {
break ;
}
availableVersions . push ( . . . paginationPage ) ;
Implement pagination with link headers for Adoptium based apis (#1014)
* Use Link headers for Adoptium pagination
* Fix nullable pagination URL types and rebuild dist
* Add 1000-page safeguard for JetBrains pagination
* Adjust plan for pagination safeguard scope
* Move pagination safeguard to non-JetBrains installers
* Add 1000-page safeguard to Adopt Temurin and Semeru pagination
* Fix Prettier formatting in adopt, semeru, and temurin installer files
* Fix CI audit failure by updating vulnerable transitive deps
* Address PR review: RFC-compliant Link parsing, SSRF validation, centralized constant
- Make getNextPageUrlFromLinkHeader RFC 8288 compliant by splitting
link-values and checking for rel=next anywhere in the parameters,
not just as the first parameter after the semicolon.
- Add validatePaginationUrl utility to reject pagination URLs that
point to unexpected origins (SSRF mitigation).
- Centralize MAX_PAGINATION_PAGES in util.ts instead of duplicating
across Adopt, Semeru, and Temurin installers.
- Add tests for rel not being the first parameter, and for URL
origin validation.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address code review feedback on pagination implementation
- Tighten rel regex with word boundary to prevent false positives
(e.g., rel="nextsomething" no longer matches).
- Use parsed.origin comparison in validatePaginationUrl to correctly
handle explicit default ports (e.g., :443 for HTTPS).
- Fix pagination safeguard tests to use same-origin URLs so they
actually exercise the 1000-page limit instead of being rejected
by origin validation on the first request.
- Add test for rel="nextsomething" not matching.
- Add test for explicit default port acceptance.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix prettier formatting in util.test.ts
* Rebuild dist/ to fix check-dist CI failure
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-12 11:50:16 +01:00
if ( pageCount >= MAX_PAGINATION_PAGES ) {
core . warning (
` Reached pagination safeguard limit ( ${ MAX_PAGINATION_PAGES } pages) while listing Adopt releases. `
) ;
break ;
}
2021-04-05 13:02:27 +03:00
}
if ( core . isDebug ( ) ) {
core . startGroup ( 'Print information about available versions' ) ;
2023-03-09 14:49:35 +02:00
console . timeEnd ( 'Retrieving available versions for Adopt took' ) ; // eslint-disable-line no-console
core . debug ( ` Available versions: [ ${ availableVersions . length } ] ` ) ;
core . debug (
availableVersions . map ( item = > item . version_data . semver ) . join ( ', ' )
) ;
2021-04-05 13:02:27 +03:00
core . endGroup ( ) ;
}
return availableVersions ;
}
private getPlatformOption ( ) : string {
// Adopt has own platform names so need to map them
switch ( process . platform ) {
case 'darwin' :
return 'mac' ;
case 'win32' :
return 'windows' ;
default :
return process . platform ;
}
}
}