2026-07-08 14:45:00 +05:30
import { JavaBase } from '../base-installer.js' ;
2023-03-09 14:49:35 +02:00
import {
JavaDownloadRelease ,
JavaInstallerOptions ,
JavaInstallerResults
2026-07-08 14:45:00 +05:30
} from '../base-models.js' ;
2023-09-20 19:22:11 +08:00
import {
2026-08-04 23:05:06 -04:00
cacheJdkDir ,
2023-09-20 19:22:11 +08:00
extractJdkFile ,
getDownloadArchiveExtension ,
2024-10-11 03:02:25 +05:30
getGitHubHttpHeaders ,
renameWinArchive
2026-07-08 14:45:00 +05:30
} from '../../util.js' ;
import * as gpg from '../../gpg.js' ;
import { MICROSOFT_PUBLIC_KEY } from './microsoft-key.js' ;
2021-12-08 10:50:14 -08:00
import * as core from '@actions/core' ;
import * as tc from '@actions/tool-cache' ;
import fs from 'fs' ;
import path from 'path' ;
2023-11-29 19:41:46 +05:30
import { TypedResponse } from '@actions/http-client/lib/interfaces' ;
2021-12-08 10:50:14 -08:00
2026-07-08 14:45:00 +05:30
export { MICROSOFT_PUBLIC_KEY } from './microsoft-key.js' ;
2026-06-29 13:19:49 +01:00
2021-12-08 10:50:14 -08:00
export class MicrosoftDistributions extends JavaBase {
constructor ( installerOptions : JavaInstallerOptions ) {
super ( 'Microsoft' , installerOptions );
}
2023-03-09 14:49:35 +02:00
protected async downloadTool (
javaRelease : JavaDownloadRelease
) : Promise < JavaInstallerResults > {
2021-12-08 10:50:14 -08:00
core . info (
`Downloading Java ${ javaRelease . version } ( ${ this . distribution } ) from ${ javaRelease . url } ...`
);
2026-07-29 04:43:56 -04:00
let javaArchivePath = await this . downloadAndVerify ( javaRelease );
2021-12-08 10:50:14 -08:00
2026-06-29 13:19:49 +01:00
if ( this . verifySignature ) {
if ( ! javaRelease . signatureUrl ) {
throw new Error (
`Input 'verify-signature' is enabled, but no signature URL was found for Microsoft Build of OpenJDK version ${ javaRelease . version } .`
);
}
core . info ( `Verifying Java package signature...` );
try {
await gpg . verifyPackageSignature (
javaArchivePath ,
javaRelease . signatureUrl ,
this . verifySignaturePublicKey ?? MICROSOFT_PUBLIC_KEY
);
} catch ( error ) {
throw new Error (
2026-07-08 14:45:00 +05:30
`Failed to verify signature for Microsoft Build of OpenJDK version ${ javaRelease . version } . Signature URL: ${ javaRelease . signatureUrl } . Error: ${ ( error as Error ). message } ` ,
{ cause : error }
2026-06-29 13:19:49 +01:00
);
}
}
2021-12-08 10:50:14 -08:00
core . info ( `Extracting Java archive...` );
const extension = getDownloadArchiveExtension ();
2024-10-11 03:02:25 +05:30
if ( process . platform === 'win32' ) {
javaArchivePath = renameWinArchive ( javaArchivePath );
}
2021-12-08 10:50:14 -08:00
const extractedJavaPath = await extractJdkFile ( javaArchivePath , extension );
const archiveName = fs . readdirSync ( extractedJavaPath )[ 0 ];
const archivePath = path . join ( extractedJavaPath , archiveName );
2026-08-04 23:05:06 -04:00
const javaPath = await cacheJdkDir (
2021-12-08 10:50:14 -08:00
archivePath ,
this . toolcacheFolderName ,
this . getToolcacheVersionName ( javaRelease . version ),
this . architecture
);
2023-03-09 14:49:35 +02:00
return { version : javaRelease.version , path : javaPath };
2021-12-08 10:50:14 -08:00
}
2023-03-09 14:49:35 +02:00
protected async findPackageForDownload (
range : string
) : Promise < JavaDownloadRelease > {
2022-10-10 17:47:17 -06:00
const arch = this . distributionArchitecture ();
if ( arch !== 'x64' && arch !== 'aarch64' ) {
2021-12-08 10:50:14 -08:00
throw new Error ( `Unsupported architecture: ${ this . architecture } ` );
}
2021-12-15 18:23:49 +03:00
if ( ! this . stable ) {
throw new Error ( 'Early access versions are not supported' );
}
2021-12-21 13:29:16 +03:00
if ( this . packageType !== 'jdk' ) {
2023-03-09 14:49:35 +02:00
throw new Error (
'Microsoft Build of OpenJDK provides only the `jdk` package type'
);
2021-12-21 13:29:16 +03:00
}
2022-09-23 14:47:30 +02:00
const manifest = await this . getAvailableVersions ();
2021-12-08 10:50:14 -08:00
2022-09-23 14:47:30 +02:00
if ( ! manifest ) {
throw new Error ( 'Could not load manifest for Microsoft Build of OpenJDK' );
}
2021-12-08 10:50:14 -08:00
2022-10-10 17:47:17 -06:00
const foundRelease = await tc . findFromManifest ( range , true , manifest , arch );
2021-12-08 10:50:14 -08:00
2022-09-23 14:47:30 +02:00
if ( ! foundRelease ) {
2026-04-13 23:14:45 +05:30
const availableVersionStrings = manifest . map ( item => item . version );
throw this . createVersionNotFoundError ( range , availableVersionStrings );
2021-12-08 10:50:14 -08:00
}
2026-06-29 13:19:49 +01:00
const file = foundRelease . files [ 0 ] as {
download_url : string ;
signature_url? : string ;
};
const signatureUrl = file . signature_url ?? ` ${ file . download_url } .sig` ;
2023-03-09 14:49:35 +02:00
return {
2026-06-29 13:19:49 +01:00
url : file.download_url ,
signatureUrl ,
2026-07-29 04:43:56 -04:00
version : foundRelease.version ,
checksum : await this . fetchChecksum (
` ${ file . download_url } .sha256sum.txt` ,
'sha256'
)
2023-03-09 14:49:35 +02:00
};
2021-12-08 10:50:14 -08:00
}
2026-06-29 13:19:49 +01:00
protected supportsSignatureVerification () : boolean {
return true ;
}
2022-09-23 14:47:30 +02:00
private async getAvailableVersions () : Promise < tc.IToolRelease [] | null > {
2021-12-08 10:50:14 -08:00
// TODO get these dynamically!
// We will need Microsoft to add an endpoint where we can query for versions.
2022-09-23 14:47:30 +02:00
const owner = 'actions' ;
const repository = 'setup-java' ;
const branch = 'main' ;
2023-03-09 14:49:35 +02:00
const filePath =
'src/distributions/microsoft/microsoft-openjdk-versions.json' ;
2022-09-23 14:47:30 +02:00
let releases : tc.IToolRelease [] | null = null ;
const fileUrl = `https://api.github.com/repos/ ${ owner } / ${ repository } /contents/ ${ filePath } ?ref= ${ branch } ` ;
2023-09-20 19:22:11 +08:00
const headers = getGitHubHttpHeaders ();
2022-09-23 14:47:30 +02:00
2023-11-29 19:41:46 +05:30
let response : TypedResponse < tc.IToolRelease [] > | null = null ;
2022-09-23 14:47:30 +02:00
2023-03-09 14:49:35 +02:00
if ( core . isDebug ()) {
console . time ( 'Retrieving available versions for Microsoft took' ); // eslint-disable-line no-console
}
2022-09-23 14:47:30 +02:00
try {
response = await this . http . getJson < tc.IToolRelease [] >( fileUrl , headers );
if ( ! response . result ) {
return null ;
2021-12-08 10:50:14 -08:00
}
2022-09-23 14:47:30 +02:00
} catch ( err ) {
core . debug (
2025-07-07 13:51:25 -05:00
`Http request for microsoft-openjdk-versions.json failed with status code: ${ response ? . statusCode } . Error: ${ err } `
2022-09-23 14:47:30 +02:00
);
return null ;
2021-12-08 10:50:14 -08:00
}
2022-09-23 14:47:30 +02:00
if ( response . result ) {
releases = response . result ;
2021-12-08 10:50:14 -08:00
}
2023-03-09 14:49:35 +02:00
if ( core . isDebug () && releases ) {
core . startGroup ( 'Print information about available versions' );
console . timeEnd ( 'Retrieving available versions for Microsoft took' ); // eslint-disable-line no-console
core . debug ( `Available versions: [ ${ releases . length } ]` );
core . debug ( releases . map ( item => item . version ). join ( ', ' ));
core . endGroup ();
}
2022-09-23 14:47:30 +02:00
return releases ;
2021-12-08 10:50:14 -08:00
}
}