Skip to content
Open
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
1436e90
Add verify-signature plumbing and Temurin verification support
Copilot Jun 17, 2026
39460f2
Rebuild dist after signature verification changes
Copilot Jun 17, 2026
70770c9
Refine signature verification errors and regenerate dist
Copilot Jun 17, 2026
b2f4bcb
refactor: make gpg.ts generic, move Adoptium-specific constant to tem…
Copilot Jun 17, 2026
fc8acd0
fix: mock renameWinArchive in temurin tests and add signature e2e job
Copilot Jun 17, 2026
c607d20
Merge pull request #5 from johnoliver/copilot/fix-github-actions-job-…
johnoliver Jun 17, 2026
a3589a9
refactor: bundle Adoptium public key, replace keyserver lookup with l…
Copilot Jun 24, 2026
33264d6
feat: add verify-signature-public-key input to allow custom GPG key o…
Copilot Jun 24, 2026
40f7b5c
refactor: extract Adoptium public key to adoptium-key.ts; tighten gpg…
Copilot Jun 24, 2026
3f3ac23
Add verify-signature plumbing and Temurin verification support
johnoliver Jun 24, 2026
c2ac82f
Potential fix for pull request finding
johnoliver Jun 24, 2026
03daa99
Potential fix for pull request finding
johnoliver Jun 24, 2026
db1f1b8
Add Microsoft signature verification support
Copilot Jun 25, 2026
2b15efd
Regenerate dist bundles for Microsoft signature checks
Copilot Jun 25, 2026
5dab176
Harden Microsoft signature URL handling
Copilot Jun 25, 2026
2c76c5e
Merge branch 'copilot/include-signature-verification' into signature-4
johnoliver Jun 25, 2026
776fcf9
Add setup-java-microsoft-signature-verification e2e job
Copilot Jun 25, 2026
2aeafef
Merge remote-tracking branch 'origin/copilot/include-signature-verifi…
johnoliver Jun 25, 2026
45cdfed
chore: regenerate dist files
Copilot Jun 25, 2026
673ccf9
Fix e2e-versions: remove duplicate job, update signature jobs to chec…
Copilot Jun 25, 2026
e2b8899
Fix Prettier formatting in test files
Copilot Jun 25, 2026
730e373
fix: mock renameWinArchive in microsoft-installer tests to fix Window…
Copilot Jun 25, 2026
8012407
fix: use --homedir flag instead of GNUPGHOME env var for Windows GPG …
Copilot Jun 25, 2026
2c98690
fix: convert Windows paths to POSIX format for MSYS2 GPG on Windows
Copilot Jun 25, 2026
165ecdd
Fix gpg test formatting
Copilot Jun 25, 2026
118154c
Merge branch 'main' into signature-4
brunoborges Jun 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions .github/workflows/e2e-versions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,62 @@ jobs:
run: bash __tests__/verify-java.sh "$JAVA_VERSION" "$JAVA_PATH"
shell: bash

setup-java-temurin-signature-verification:
name: temurin ${{ matrix.version }} signature verification - ${{ matrix.os }}
needs: setup-java-major-minor-versions
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [macos-latest, windows-latest, ubuntu-latest]
version: ['21', '17']
steps:
- name: Checkout
uses: actions/checkout@v7
with:
persist-credentials: false
- name: setup-java with signature verification
uses: ./
id: setup-java
with:
java-version: ${{ matrix.version }}
distribution: temurin
verify-signature: true
- name: Verify Java
env:
JAVA_VERSION: ${{ matrix.version }}
JAVA_PATH: ${{ steps.setup-java.outputs.path }}
run: bash __tests__/verify-java.sh "$JAVA_VERSION" "$JAVA_PATH"
shell: bash

setup-java-microsoft-signature-verification:
name: microsoft ${{ matrix.version }} signature verification - ${{ matrix.os }}
needs: setup-java-major-minor-versions
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [macos-latest, windows-latest, ubuntu-latest]
version: ['21', '17']
steps:
- name: Checkout
uses: actions/checkout@v7
with:
persist-credentials: false
- name: setup-java with signature verification
uses: ./
id: setup-java
with:
java-version: ${{ matrix.version }}
distribution: microsoft
verify-signature: true
- name: Verify Java
env:
JAVA_VERSION: ${{ matrix.version }}
JAVA_PATH: ${{ steps.setup-java.outputs.path }}
run: bash __tests__/verify-java.sh "$JAVA_VERSION" "$JAVA_PATH"
shell: bash

setup-java-ea-versions-sapmachine:
name: sapmachine ${{ matrix.version }} (jdk-x64) - ${{ matrix.os }}
needs: setup-java-major-minor-versions
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ For more details, see the full release notes on the [releases page](https://git

- `check-latest`: Setting this option makes the action to check for the latest available version for the version spec.

- `verify-signature`: Verifies downloaded Java package signatures when supported by the selected distribution. Currently supported for `temurin` and `microsoft`. If set to `true` for unsupported distributions, the action fails.

- `verify-signature-public-key`: ASCII-armored GPG public key used to verify the downloaded package signature. Overrides the default bundled key for the selected distribution.

- `cache`: Quick [setup caching](#caching-packages-dependencies) for the dependencies managed through one of the predefined package managers. It can be one of "maven", "gradle" or "sbt".

- `cache-dependency-path`: The path to a dependency file: pom.xml, build.gradle, build.sbt, etc. This option can be used with the `cache` option. If this option is omitted, the action searches for the dependency file in the entire repository. This option supports wildcards and a list of file names for caching multiple dependencies.
Expand Down
297 changes: 198 additions & 99 deletions __tests__/data/temurin.json

Large diffs are not rendered by default.

18 changes: 18 additions & 0 deletions __tests__/distributors/base-installer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,24 @@ describe('setupJava', () => {
}
);

it('should fail when verify-signature is enabled for unsupported distributions', async () => {
mockJavaBase = new EmptyJavaBase({
version: '11',
architecture: 'x86',
packageType: 'jdk',
checkLatest: false,
verifySignature: true
});

await expect(mockJavaBase.setupJava()).rejects.toThrow(
"Input 'verify-signature' is not supported for distribution 'Empty'."
);
expect(spyTcFindAllVersions).not.toHaveBeenCalled();
expect(spyCoreAddPath).not.toHaveBeenCalled();
expect(spyCoreExportVariable).not.toHaveBeenCalled();
expect(spyCoreSetOutput).not.toHaveBeenCalled();
});

it.each([
[
{
Expand Down
159 changes: 158 additions & 1 deletion __tests__/distributors/microsoft-installer.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
import {MicrosoftDistributions} from '../../src/distributions/microsoft/installer';
import {
MicrosoftDistributions,
MICROSOFT_PUBLIC_KEY
} from '../../src/distributions/microsoft/installer';
import os from 'os';
import data from '../data/microsoft.json';
import * as httpm from '@actions/http-client';
import * as core from '@actions/core';
import * as tc from '@actions/tool-cache';
import * as gpg from '../../src/gpg';
import * as util from '../../src/util';
import fs from 'fs';

describe('findPackageForDownload', () => {
let distribution: MicrosoftDistributions;
Expand Down Expand Up @@ -102,6 +109,7 @@ describe('findPackageForDownload', () => {
.replace('{{OS_TYPE}}', os)
.replace('{{ARCHIVE_TYPE}}', archive);
expect(result.url).toBe(url);
expect(result.signatureUrl).toBe(`${url}.sig`);
});

it.each([
Expand Down Expand Up @@ -187,4 +195,153 @@ describe('findPackageForDownload', () => {
/No matching version found for SemVer */
);
});

it('uses manifest-provided signature URL when available', async () => {
spyGetManifestFromRepo.mockReturnValue({
result: [
{
version: '17.0.10',
stable: true,
release_url: 'https://example.test',
files: [
{
filename: 'microsoft-jdk-17.0.10-linux-x64.tar.gz',
arch: 'x64',
platform: 'linux',
download_url: 'https://example.test/jdk.tar.gz',
signature_url: 'https://example.test/jdk.tar.gz.custom.sig'
}
]
}
],
statusCode: 200,
headers: {}
});
jest.spyOn(os, 'platform').mockReturnValue('linux');

const result = await distribution['findPackageForDownload']('17.0.10');

expect(result.signatureUrl).toBe(
'https://example.test/jdk.tar.gz.custom.sig'
);
});
});

describe('downloadTool', () => {
let spyDownloadTool: jest.SpyInstance;
let spyExtractJdkFile: jest.SpyInstance;
let spyCacheDir: jest.SpyInstance;
let spyVerifySignature: jest.SpyInstance;
let distribution: MicrosoftDistributions;

beforeEach(() => {
jest
.spyOn(os, 'platform')
.mockReturnValue(process.platform as ReturnType<typeof os.platform>);

distribution = new MicrosoftDistributions({
version: '17',
architecture: 'x64',
packageType: 'jdk',
checkLatest: false
});

spyDownloadTool = jest.spyOn(tc, 'downloadTool');
spyDownloadTool.mockImplementation(async () => {
return '/tmp/jdk.tar.gz';
});

spyExtractJdkFile = jest.spyOn(util, 'extractJdkFile');
spyExtractJdkFile.mockImplementation(async () => {
return '/tmp/unpacked';
});

jest.spyOn(fs, 'readdirSync').mockReturnValue(['jdk'] as any);
spyCacheDir = jest.spyOn(tc, 'cacheDir');
spyCacheDir.mockImplementation(async () => {
return '/tmp/cached';
});

jest
.spyOn(util, 'renameWinArchive')
.mockImplementation((archivePath: string) => `${archivePath}.zip`);

spyVerifySignature = jest.spyOn(gpg, 'verifyPackageSignature');
spyVerifySignature.mockImplementation(async () => {});
});

afterEach(() => {
jest.restoreAllMocks();
});

it('verifies signature when enabled', async () => {
const signedDistribution = new MicrosoftDistributions({
version: '17',
architecture: 'x64',
packageType: 'jdk',
checkLatest: false,
verifySignature: true
});

await signedDistribution['downloadTool']({
version: '17.0.14+7',
url: 'https://example.com/jdk.tar.gz',
signatureUrl: 'https://example.com/jdk.tar.gz.sig'
});

expect(spyVerifySignature).toHaveBeenCalledWith(
'/tmp/jdk.tar.gz',
'https://example.com/jdk.tar.gz.sig',
MICROSOFT_PUBLIC_KEY
);
});

it('uses custom public key when verifySignaturePublicKey is provided', async () => {
const customKey =
'-----BEGIN PGP PUBLIC KEY BLOCK-----\ncustom\n-----END PGP PUBLIC KEY BLOCK-----';
const signedDistribution = new MicrosoftDistributions({
version: '17',
architecture: 'x64',
packageType: 'jdk',
checkLatest: false,
verifySignature: true,
verifySignaturePublicKey: customKey
});

await signedDistribution['downloadTool']({
version: '17.0.14+7',
url: 'https://example.com/jdk.tar.gz',
signatureUrl: 'https://example.com/jdk.tar.gz.sig'
});

expect(spyVerifySignature).toHaveBeenCalledWith(
'/tmp/jdk.tar.gz',
'https://example.com/jdk.tar.gz.sig',
customKey
);
});

it('fails when signature is missing and verification is enabled', async () => {
const signedDistribution = new MicrosoftDistributions({
version: '17',
architecture: 'x64',
packageType: 'jdk',
checkLatest: false,
verifySignature: true
});

await expect(
signedDistribution['downloadTool']({
version: '17.0.14+7',
url: 'https://example.com/jdk.tar.gz'
})
).rejects.toThrow(
"Input 'verify-signature' is enabled, but no signature URL was found for Microsoft Build of OpenJDK version 17.0.14+7."
);
expect(spyVerifySignature).not.toHaveBeenCalled();
});

it('supports signature verification', () => {
expect(distribution['supportsSignatureVerification']()).toBe(true);
});
});
Loading
Loading