mirror of
https://github.com/actions/setup-java.git
synced 2026-10-15 15:14:53 +00:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b843ebf9b9 | ||
|
|
2a69be27b0 |
@@ -174,3 +174,115 @@ jobs:
|
||||
if (-not (Test-Path $path)) {
|
||||
throw "settings.xml file is not found in expected location"
|
||||
}
|
||||
|
||||
test-maven-repositories:
|
||||
name: Maven ${{ matrix.repositories }} repositories
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-latest, windows-latest, ubuntu-latest]
|
||||
repositories: [dependencies, plugins, both]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Prepare Maven model inspection
|
||||
run: |
|
||||
$directory = Join-Path $env:RUNNER_TEMP "maven-repository-test"
|
||||
New-Item -Path $directory -ItemType Directory -Force | Out-Null
|
||||
$pomPath = Join-Path $directory "pom.xml"
|
||||
$warmSettingsPath = Join-Path $directory "warm-settings.xml"
|
||||
$cachePath = Join-Path $directory "repository"
|
||||
$outputPath = Join-Path $directory "warm-effective-pom.xml"
|
||||
|
||||
# This project repository keeps the inspection plugin available offline
|
||||
# after the generated settings disable inherited plugin Central.
|
||||
@'
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>setup-java.test</groupId>
|
||||
<artifactId>repository-settings</artifactId>
|
||||
<version>1.0</version>
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>inspection</id>
|
||||
<url>https://repo.maven.apache.org/maven2</url>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
</project>
|
||||
'@ | Set-Content -Path $pomPath
|
||||
'<settings />' | Set-Content -Path $warmSettingsPath
|
||||
|
||||
mvn --batch-mode --no-transfer-progress --settings $warmSettingsPath `
|
||||
"-Dmaven.repo.local=$cachePath" --file $pomPath `
|
||||
org.apache.maven.plugins:maven-help-plugin:3.5.1:effective-pom `
|
||||
"-Doutput=$outputPath"
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "Could not prepare the Maven Help Plugin"
|
||||
}
|
||||
- name: Configure dependency and plugin repositories
|
||||
uses: ./
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '21'
|
||||
settings-path: ${{ runner.temp }}/maven-repository-test/settings
|
||||
mvn-server-credentials: |
|
||||
private:PRIVATE_USERNAME:PRIVATE_TOKEN
|
||||
mvn-repositories: ${{ matrix.repositories != 'plugins' && 'private:https://repo.example.invalid/maven:false' || '' }}
|
||||
mvn-plugin-repositories: ${{ matrix.repositories != 'dependencies' && 'private:https://repo.example.invalid/maven:false' || '' }}
|
||||
mvn-repositories-include-central: false
|
||||
- name: Validate generated settings and effective Maven repositories
|
||||
env:
|
||||
REPOSITORY_CONFIGURATION: ${{ matrix.repositories }}
|
||||
run: |
|
||||
$directory = Join-Path $env:RUNNER_TEMP "maven-repository-test"
|
||||
$settingsPath = Join-Path $directory "settings/settings.xml"
|
||||
[xml]$settings = Get-Content -Path $settingsPath -Raw
|
||||
$profiles = @($settings.settings.profiles.profile)
|
||||
if ($profiles.Count -ne 1 -or $profiles[0].id -ne "setup-java-repositories") {
|
||||
throw "Expected one repository profile"
|
||||
}
|
||||
$activeProfiles = @($settings.settings.activeProfiles.activeProfile)
|
||||
if ($activeProfiles.Count -ne 1 -or $activeProfiles[0] -ne "setup-java-repositories") {
|
||||
throw "Expected one active repository profile"
|
||||
}
|
||||
$server = $settings.settings.servers.server
|
||||
if ($server.id -ne "private" -or $server.username -ne '${env.PRIVATE_USERNAME}' -or $server.password -ne '${env.PRIVATE_TOKEN}') {
|
||||
throw "Repository credentials were not preserved"
|
||||
}
|
||||
|
||||
function Assert-Repositories($repositories, $expectPrivate, $context) {
|
||||
$central = @($repositories | Where-Object { $_.id -eq "central" })
|
||||
if ($central.Count -ne 1 -or $central[0].releases.enabled -ne "false" -or $central[0].snapshots.enabled -ne "false") {
|
||||
throw "$context did not disable inherited Maven Central"
|
||||
}
|
||||
$private = @($repositories | Where-Object { $_.id -eq "private" })
|
||||
$expectedCount = if ($expectPrivate) { 1 } else { 0 }
|
||||
if ($private.Count -ne $expectedCount) {
|
||||
throw "$context has incorrect private repositories"
|
||||
}
|
||||
if ($expectPrivate -and ($private[0].url -ne "https://repo.example.invalid/maven" -or $private[0].snapshots.enabled -ne "false")) {
|
||||
throw "$context has incorrect private repository settings"
|
||||
}
|
||||
}
|
||||
|
||||
$expectDependencies = $env:REPOSITORY_CONFIGURATION -ne "plugins"
|
||||
$expectPlugins = $env:REPOSITORY_CONFIGURATION -ne "dependencies"
|
||||
Assert-Repositories @($profiles[0].repositories.repository) $expectDependencies "Settings dependency repositories"
|
||||
Assert-Repositories @($profiles[0].pluginRepositories.pluginRepository) $expectPlugins "Settings plugin repositories"
|
||||
|
||||
$pomPath = Join-Path $directory "pom.xml"
|
||||
$cachePath = Join-Path $directory "repository"
|
||||
$outputPath = Join-Path $directory "effective-pom.xml"
|
||||
mvn --batch-mode --no-transfer-progress --offline --settings $settingsPath `
|
||||
"-Dmaven.repo.local=$cachePath" --file $pomPath `
|
||||
org.apache.maven.plugins:maven-help-plugin:3.5.1:effective-pom `
|
||||
"-Doutput=$outputPath"
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "Could not inspect the effective Maven model"
|
||||
}
|
||||
[xml]$effectivePom = Get-Content -Path $outputPath -Raw
|
||||
Assert-Repositories @($effectivePom.project.repositories.repository) $expectDependencies "Effective dependency repositories"
|
||||
Assert-Repositories @($effectivePom.project.pluginRepositories.pluginRepository) $expectPlugins "Effective plugin repositories"
|
||||
|
||||
@@ -168,9 +168,11 @@ steps:
|
||||
| `server-username-env-var` | Environment variable name for Maven repository username. | `GITHUB_ACTOR` |
|
||||
| `server-password-env-var` | Environment variable name for Maven repository password or token. | `GITHUB_TOKEN` |
|
||||
| `mvn-server-credentials` | Multiline Maven server credentials in the format `server-id:USERNAME_ENV:PASSWORD_ENV`. Replaces the single server configured by the three inputs above when set. | |
|
||||
| `mvn-server-repository-origins` | Multiline Maven credential origins in the format `server-id:repository-origin`. Each origin must belong to a configured server ID. Requires Maven 3.10+. | |
|
||||
| `mvn-repositories` | Multiline Maven dependency repositories in the format `repository-id:repository-url:snapshots-enabled`. | |
|
||||
| `mvn-repositories-include-central` | Include Maven Central in the generated dependency repositories profile. When `false`, Central is disabled unless an explicit `central` repository is declared. | `true` |
|
||||
| `mvn-repositories-prioritize-central` | Place Maven Central before custom dependency repositories. Has no effect when Maven Central is excluded. | `true` |
|
||||
| `mvn-plugin-repositories` | Multiline Maven plugin repositories in the format `repository-id:repository-url:snapshots-enabled`. Can be used independently of `mvn-repositories`. | |
|
||||
| `mvn-repositories-include-central` | Include Maven Central for dependency and plugin repositories in the generated profile. When `false`, Central is disabled for both types unless that type explicitly declares `central`. Has no effect when neither repository list is configured. | `true` |
|
||||
| `mvn-repositories-prioritize-central` | Place Maven Central before custom dependency and plugin repositories. Has no effect when Central is excluded or neither repository list is configured. | `true` |
|
||||
| `settings-path` | Directory where `settings.xml` is written. | `~/.m2` |
|
||||
| `overwrite-settings` | Overwrite an existing `settings.xml`. | `true` |
|
||||
| `gpg-private-key` | GPG private key to import into an isolated temporary keyring. | |
|
||||
@@ -233,13 +235,10 @@ Additional distribution notes:
|
||||
| --- | --- |
|
||||
| Major version | `8`, `11`, `17`, `21`, `25` |
|
||||
| Specific feature or patch version | `11.0`, `11.0.4`, `17.0`, `8.0.282+8` |
|
||||
| Exact build, with optional `jdk-` prefix | `27+35`, `27.0+35`, `27.0.0+35`, `jdk-27+35` |
|
||||
| JEP 322 multi-field versions | `11.0.9.1`, `18.0.1.1`, `26.0.2.1+1` |
|
||||
| Early access | `15-ea`, `15.0.0-ea`, `27-ea` |
|
||||
| Latest stable GA release | `latest` |
|
||||
|
||||
Numeric Java versions can use a `jdk-` prefix. For example, `jdk-27+35`, `27+35`, and `27.0+35` all normalize to `27.0.0+35` and pin that exact build; `jdk-27` and `27` remain major-version ranges. The prefix does not select a distribution or package type. Release availability depends on the selected distribution and platform.
|
||||
|
||||
When `check-latest` is `false`, the action first tries the runner tool cache for the requested distribution, package type, architecture, and version range. It downloads Java only when no matching cached version is found. When `check-latest` is `true`, the action checks remote metadata first and downloads if the cached version is not current.
|
||||
|
||||
GitHub-hosted runners primarily pre-cache Eclipse Temurin JDKs. See the installed Java versions for [Ubuntu](https://github.com/actions/runner-images/blob/main/images/ubuntu/Ubuntu2404-Readme.md#java), [Windows](https://github.com/actions/runner-images/blob/main/images/windows/Windows2025-Readme.md#java), and [macOS](https://github.com/actions/runner-images/blob/main/images/macos/macos-15-Readme.md#java). On a fresh GitHub-hosted runner, requests for other distributions usually miss the tool cache and resolve from remote metadata. For broad version ranges such as a major version (`21`, `25`), this often behaves similarly to `check-latest: true` because the action downloads the latest available release that satisfies the range.
|
||||
@@ -484,10 +483,20 @@ steps:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
```
|
||||
|
||||
For dependencies hosted outside Maven Central, use `mvn-repositories` to add
|
||||
resolution repositories to an active profile in the generated `settings.xml`.
|
||||
Repository IDs can match `mvn-server-credentials` IDs when authentication is
|
||||
required. See [Resolving Maven dependencies from custom repositories](docs/advanced-usage.md#resolving-maven-dependencies-from-custom-repositories).
|
||||
For dependencies hosted outside Maven Central, use `mvn-repositories`; for build
|
||||
plugins, use `mvn-plugin-repositories`. Either input adds its own repository type
|
||||
to the same active profile in the generated `settings.xml`. Repository IDs can
|
||||
match `mvn-server-credentials` IDs when authentication is required.
|
||||
See [Resolving Maven dependencies from custom repositories](docs/advanced-usage.md#resolving-maven-dependencies-from-custom-repositories)
|
||||
and [Resolving Maven plugins from custom repositories](docs/advanced-usage.md#resolving-maven-plugins-from-custom-repositories).
|
||||
|
||||
> [!WARNING]
|
||||
> `mvn-repositories-include-central: false` now disables inherited Maven Central
|
||||
> for **both dependencies and plugins**, even in existing workflows that only
|
||||
> configure `mvn-repositories`. Builds relying on uncached plugins from Central
|
||||
> must configure `mvn-plugin-repositories` with an accessible plugin repository
|
||||
> or explicitly declare `central` there. Neither repository list configured
|
||||
> means the Central controls remain inactive.
|
||||
|
||||
### GPG signing
|
||||
|
||||
|
||||
+620
-65
@@ -63,12 +63,51 @@ const credentials = (id: string, username: string, password: string) => [
|
||||
const repositorySettings = (
|
||||
repositories: auth.MavenRepository[],
|
||||
includeCentral = true,
|
||||
prioritizeCentral = true
|
||||
prioritizeCentral = true,
|
||||
pluginRepositories: auth.MavenRepository[] = []
|
||||
): auth.MavenRepositorySettings => ({
|
||||
repositories,
|
||||
pluginRepositories,
|
||||
includeCentral,
|
||||
prioritizeCentral
|
||||
});
|
||||
const repositoryInputs = ['mvn-repositories', 'mvn-plugin-repositories'];
|
||||
const privateRepository = {
|
||||
id: 'private',
|
||||
url: 'https://repo.example.com/maven',
|
||||
snapshotsEnabled: true
|
||||
};
|
||||
const privateRepositoryXml = {
|
||||
id: privateRepository.id,
|
||||
url: privateRepository.url,
|
||||
snapshots: {enabled: 'true'}
|
||||
};
|
||||
const centralRepositoryXml = {
|
||||
id: 'central',
|
||||
url: 'https://repo.maven.apache.org/maven2',
|
||||
snapshots: {enabled: 'false'}
|
||||
};
|
||||
const disabledCentralRepositoryXml = {
|
||||
...centralRepositoryXml,
|
||||
releases: {enabled: 'false'}
|
||||
};
|
||||
const repositoryConfigurations = [
|
||||
{
|
||||
name: 'dependency-only',
|
||||
repositories: [privateRepository],
|
||||
pluginRepositories: []
|
||||
},
|
||||
{
|
||||
name: 'plugin-only',
|
||||
repositories: [],
|
||||
pluginRepositories: [privateRepository]
|
||||
},
|
||||
{
|
||||
name: 'combined',
|
||||
repositories: [privateRepository],
|
||||
pluginRepositories: [privateRepository]
|
||||
}
|
||||
];
|
||||
|
||||
describe('auth tests', () => {
|
||||
let spyOSHomedir: any;
|
||||
@@ -318,6 +357,21 @@ describe('auth tests', () => {
|
||||
).toEqual(expectedSettings);
|
||||
});
|
||||
|
||||
it('generates repository origins for a Maven server', () => {
|
||||
const settings = auth.generate([
|
||||
{
|
||||
id: 'central',
|
||||
usernameEnvVar: 'CENTRAL_USER',
|
||||
passwordEnvVar: 'CENTRAL_PASS',
|
||||
repositoryOrigins: ['https://central.sonatype.com']
|
||||
}
|
||||
]);
|
||||
|
||||
expect(settings).toContain(` <repositoryOrigins>
|
||||
<repositoryOrigin>https://central.sonatype.com</repositoryOrigin>
|
||||
</repositoryOrigins>`);
|
||||
});
|
||||
|
||||
it('does not add a gpg profile when the passphrase env var is the maven-gpg-plugin default', () => {
|
||||
const id = 'packages';
|
||||
const username = 'USER';
|
||||
@@ -460,6 +514,87 @@ describe('auth tests', () => {
|
||||
).toEqual(['first', 'second', 'central']);
|
||||
});
|
||||
|
||||
it.each([
|
||||
{
|
||||
name: 'Central first by default',
|
||||
prioritizeCentral: undefined,
|
||||
expectedRepositories: [
|
||||
{
|
||||
id: 'central',
|
||||
url: 'https://repo.maven.apache.org/maven2',
|
||||
snapshots: {enabled: 'false'}
|
||||
},
|
||||
{
|
||||
id: 'first',
|
||||
url: 'https://first.example.com/plugins',
|
||||
snapshots: {enabled: 'false'}
|
||||
},
|
||||
{
|
||||
id: 'second',
|
||||
url: 'https://second.example.com/plugins',
|
||||
snapshots: {enabled: 'true'}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'custom plugins before Central',
|
||||
prioritizeCentral: false,
|
||||
expectedRepositories: [
|
||||
{
|
||||
id: 'first',
|
||||
url: 'https://first.example.com/plugins',
|
||||
snapshots: {enabled: 'false'}
|
||||
},
|
||||
{
|
||||
id: 'second',
|
||||
url: 'https://second.example.com/plugins',
|
||||
snapshots: {enabled: 'true'}
|
||||
},
|
||||
{
|
||||
id: 'central',
|
||||
url: 'https://repo.maven.apache.org/maven2',
|
||||
snapshots: {enabled: 'false'}
|
||||
}
|
||||
]
|
||||
}
|
||||
])(
|
||||
'generates plugin-only settings with $name',
|
||||
({prioritizeCentral, expectedRepositories}) => {
|
||||
const xml = auth.generate(
|
||||
[],
|
||||
undefined,
|
||||
repositorySettings([], true, prioritizeCentral, [
|
||||
{
|
||||
id: 'first',
|
||||
url: 'https://first.example.com/plugins',
|
||||
snapshotsEnabled: false
|
||||
},
|
||||
{
|
||||
id: 'second',
|
||||
url: 'https://second.example.com/plugins',
|
||||
snapshotsEnabled: true
|
||||
}
|
||||
])
|
||||
);
|
||||
|
||||
expect(parseXmlObject(xml)).toEqual(
|
||||
expect.objectContaining({
|
||||
settings: expect.objectContaining({
|
||||
profiles: {
|
||||
profile: {
|
||||
id: 'setup-java-repositories',
|
||||
pluginRepositories: {
|
||||
pluginRepository: expectedRepositories
|
||||
}
|
||||
}
|
||||
},
|
||||
activeProfiles: {activeProfile: 'setup-java-repositories'}
|
||||
})
|
||||
})
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
it('excludes Central from the generated repository profile when configured', () => {
|
||||
const parsed = parseXmlObject(
|
||||
auth.generate(
|
||||
@@ -491,6 +626,9 @@ describe('auth tests', () => {
|
||||
snapshots: {enabled: 'false'}
|
||||
}
|
||||
]);
|
||||
expect(
|
||||
parsed.settings.profiles.profile.pluginRepositories.pluginRepository
|
||||
).toEqual(disabledCentralRepositoryXml);
|
||||
});
|
||||
|
||||
it('combines repository and GPG configuration in shared profile blocks', () => {
|
||||
@@ -528,6 +666,9 @@ describe('auth tests', () => {
|
||||
snapshots: {enabled: 'false'}
|
||||
}
|
||||
]
|
||||
},
|
||||
pluginRepositories: {
|
||||
pluginRepository: disabledCentralRepositoryXml
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -541,6 +682,161 @@ describe('auth tests', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it.each(
|
||||
repositoryConfigurations.flatMap(configuration =>
|
||||
[
|
||||
{includeCentral: true, prioritizeCentral: true},
|
||||
{includeCentral: true, prioritizeCentral: false},
|
||||
{includeCentral: false, prioritizeCentral: true},
|
||||
{includeCentral: false, prioritizeCentral: false}
|
||||
].map(controls => ({...configuration, ...controls}))
|
||||
)
|
||||
)(
|
||||
'generates $name repositories with includeCentral=$includeCentral and prioritizeCentral=$prioritizeCentral',
|
||||
({repositories, pluginRepositories, includeCentral, prioritizeCentral}) => {
|
||||
const xml = auth.generate(
|
||||
credentials('private', 'USERNAME', 'PASSWORD'),
|
||||
undefined,
|
||||
repositorySettings(
|
||||
repositories,
|
||||
includeCentral,
|
||||
prioritizeCentral,
|
||||
pluginRepositories
|
||||
)
|
||||
);
|
||||
const expectedEntries = (configured: boolean) => {
|
||||
const entries = includeCentral
|
||||
? configured
|
||||
? prioritizeCentral
|
||||
? [centralRepositoryXml, privateRepositoryXml]
|
||||
: [privateRepositoryXml, centralRepositoryXml]
|
||||
: []
|
||||
: configured
|
||||
? [privateRepositoryXml, disabledCentralRepositoryXml]
|
||||
: [disabledCentralRepositoryXml];
|
||||
return entries.length === 1 ? entries[0] : entries;
|
||||
};
|
||||
const includeRepositories = repositories.length > 0 || !includeCentral;
|
||||
const includePluginRepositories =
|
||||
pluginRepositories.length > 0 || !includeCentral;
|
||||
|
||||
expect(parseXmlObject(xml)).toMatchObject({
|
||||
settings: {
|
||||
profiles: {
|
||||
profile: {
|
||||
id: 'setup-java-repositories',
|
||||
...(includeRepositories
|
||||
? {
|
||||
repositories: {
|
||||
repository: expectedEntries(repositories.length > 0)
|
||||
}
|
||||
}
|
||||
: {}),
|
||||
...(includePluginRepositories
|
||||
? {
|
||||
pluginRepositories: {
|
||||
pluginRepository: expectedEntries(
|
||||
pluginRepositories.length > 0
|
||||
)
|
||||
}
|
||||
}
|
||||
: {})
|
||||
}
|
||||
},
|
||||
activeProfiles: {activeProfile: 'setup-java-repositories'}
|
||||
}
|
||||
});
|
||||
if (!includeRepositories) {
|
||||
expect(xml).not.toContain('<repositories>');
|
||||
}
|
||||
if (!includePluginRepositories) {
|
||||
expect(xml).not.toContain('<pluginRepositories>');
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
it.each(repositoryConfigurations)(
|
||||
'handles explicit Central independently for $name repositories',
|
||||
({repositories, pluginRepositories}) => {
|
||||
const central = {
|
||||
id: 'central',
|
||||
url: 'https://mirror.example.com/maven',
|
||||
snapshotsEnabled: true
|
||||
};
|
||||
const explicitCentralXml = {
|
||||
id: central.id,
|
||||
url: central.url,
|
||||
snapshots: {enabled: 'true'}
|
||||
};
|
||||
const xml = auth.generate(
|
||||
[],
|
||||
undefined,
|
||||
repositorySettings(
|
||||
repositories.length ? [central] : [],
|
||||
false,
|
||||
true,
|
||||
pluginRepositories.length ? [central] : []
|
||||
)
|
||||
);
|
||||
|
||||
expect(parseXmlObject(xml)).toMatchObject({
|
||||
settings: {
|
||||
profiles: {
|
||||
profile: {
|
||||
repositories: {
|
||||
repository: repositories.length
|
||||
? explicitCentralXml
|
||||
: disabledCentralRepositoryXml
|
||||
},
|
||||
pluginRepositories: {
|
||||
pluginRepository: pluginRepositories.length
|
||||
? explicitCentralXml
|
||||
: disabledCentralRepositoryXml
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
expect(xml.match(/<id>central<\/id>/g)).toHaveLength(2);
|
||||
}
|
||||
);
|
||||
|
||||
it('escapes plugin repository values while preserving parsed semantics', () => {
|
||||
const repository = {
|
||||
id: `private&<>"'é`,
|
||||
url: `https://repo.example.com:8443/a?x=1&y=<value>"'é`,
|
||||
snapshotsEnabled: false
|
||||
};
|
||||
const xml = auth.generate(
|
||||
credentials(repository.id, 'USERNAME', 'PASSWORD'),
|
||||
undefined,
|
||||
repositorySettings([], true, true, [repository])
|
||||
);
|
||||
|
||||
expect(parseXmlObject(xml)).toMatchObject({
|
||||
settings: {
|
||||
servers: {server: {id: repository.id}},
|
||||
profiles: {
|
||||
profile: {
|
||||
pluginRepositories: {
|
||||
pluginRepository: [
|
||||
centralRepositoryXml,
|
||||
{
|
||||
id: repository.id,
|
||||
url: repository.url,
|
||||
snapshots: {enabled: 'false'}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
expect(xml).toContain('private&<>');
|
||||
expect(xml).toContain('x=1&y=<value>');
|
||||
expect(xml).not.toContain('<repositories>');
|
||||
});
|
||||
|
||||
it('escapes repository values while preserving parsed semantics', () => {
|
||||
const repository = {
|
||||
id: `private&<>"'é`,
|
||||
@@ -586,81 +882,111 @@ describe('auth tests', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it('parses Maven repositories while preserving colons in URLs', () => {
|
||||
expect(
|
||||
auth.parseMavenRepositories(
|
||||
[
|
||||
'',
|
||||
' private : https://repo.example.com:8443/maven : true ',
|
||||
'releases:https://repo.example.com/releases:false'
|
||||
],
|
||||
true
|
||||
)
|
||||
).toEqual([
|
||||
it.each(repositoryInputs)(
|
||||
'parses %s while preserving colons in URLs',
|
||||
inputName => {
|
||||
expect(
|
||||
auth.parseMavenRepositories(
|
||||
[
|
||||
'',
|
||||
' private : https://repo.example.com:8443/maven : TRUE ',
|
||||
'releases:https://repo.example.com/releases:false'
|
||||
],
|
||||
true,
|
||||
inputName
|
||||
)
|
||||
).toEqual([
|
||||
{
|
||||
id: 'private',
|
||||
url: 'https://repo.example.com:8443/maven',
|
||||
snapshotsEnabled: true
|
||||
},
|
||||
{
|
||||
id: 'releases',
|
||||
url: 'https://repo.example.com/releases',
|
||||
snapshotsEnabled: false
|
||||
}
|
||||
]);
|
||||
}
|
||||
);
|
||||
|
||||
it.each(
|
||||
[
|
||||
{
|
||||
id: 'private',
|
||||
url: 'https://repo.example.com:8443/maven',
|
||||
snapshotsEnabled: true
|
||||
entries: ['private'],
|
||||
error:
|
||||
'Invalid mvn-repositories entry at line 1. Expected format: repository-id:repository-url:snapshots-enabled'
|
||||
},
|
||||
{
|
||||
id: 'releases',
|
||||
url: 'https://repo.example.com/releases',
|
||||
snapshotsEnabled: false
|
||||
entries: ['private:https://repo.example.com'],
|
||||
error:
|
||||
"Invalid snapshots-enabled value '//repo.example.com' in mvn-repositories entry at line 1. Expected true or false"
|
||||
},
|
||||
{
|
||||
entries: ['private::true'],
|
||||
error:
|
||||
'Invalid mvn-repositories entry at line 1. repository-id, repository URL, and snapshots-enabled are required'
|
||||
},
|
||||
{
|
||||
entries: ['private:https://repo.example.com:'],
|
||||
error:
|
||||
'Invalid mvn-repositories entry at line 1. repository-id, repository URL, and snapshots-enabled are required'
|
||||
},
|
||||
{
|
||||
entries: ['', 'private:https://repo.example.com:true', ' :url:false'],
|
||||
error:
|
||||
'Invalid mvn-repositories entry at line 3. repository-id, repository URL, and snapshots-enabled are required'
|
||||
},
|
||||
{
|
||||
entries: ['private:https://repo.example.com:sometimes'],
|
||||
error:
|
||||
"Invalid snapshots-enabled value 'sometimes' in mvn-repositories entry at line 1. Expected true or false"
|
||||
}
|
||||
]);
|
||||
].flatMap(testCase =>
|
||||
repositoryInputs.map(inputName => ({
|
||||
...testCase,
|
||||
inputName,
|
||||
error: testCase.error.replace('mvn-repositories', inputName)
|
||||
}))
|
||||
)
|
||||
)('rejects malformed $inputName: $entries', ({entries, error, inputName}) => {
|
||||
expect(() => auth.parseMavenRepositories(entries, true, inputName)).toThrow(
|
||||
error
|
||||
);
|
||||
});
|
||||
|
||||
it.each([
|
||||
{
|
||||
entries: ['private'],
|
||||
error:
|
||||
'Invalid mvn-repositories entry at line 1. Expected format: repository-id:repository-url:snapshots-enabled'
|
||||
},
|
||||
{
|
||||
entries: ['private:https://repo.example.com'],
|
||||
error:
|
||||
"Invalid snapshots-enabled value '//repo.example.com' in mvn-repositories entry at line 1. Expected true or false"
|
||||
},
|
||||
{
|
||||
entries: ['private::true'],
|
||||
error:
|
||||
'Invalid mvn-repositories entry at line 1. repository-id, repository URL, and snapshots-enabled are required'
|
||||
},
|
||||
{
|
||||
entries: ['private:https://repo.example.com:sometimes'],
|
||||
error:
|
||||
"Invalid snapshots-enabled value 'sometimes' in mvn-repositories entry at line 1. Expected true or false"
|
||||
}
|
||||
])('rejects malformed Maven repositories: $entries', ({entries, error}) => {
|
||||
expect(() => auth.parseMavenRepositories(entries, true)).toThrow(error);
|
||||
});
|
||||
|
||||
it('rejects duplicate Maven repository ids', () => {
|
||||
it.each(repositoryInputs)('rejects duplicate IDs in %s', inputName => {
|
||||
expect(() =>
|
||||
auth.parseMavenRepositories(
|
||||
[
|
||||
'private:https://first.example.com:false',
|
||||
'private:https://second.example.com:true'
|
||||
],
|
||||
true
|
||||
true,
|
||||
inputName
|
||||
)
|
||||
).toThrow("Duplicate repository-id 'private' in mvn-repositories input");
|
||||
).toThrow(`Duplicate repository-id 'private' in ${inputName} input`);
|
||||
});
|
||||
|
||||
it('reserves the Central repository id only when automatic Central inclusion is enabled', () => {
|
||||
const central = 'central:https://custom.example.com/maven:false';
|
||||
it.each(repositoryInputs)(
|
||||
'reserves the Central ID in %s only when automatic inclusion is enabled',
|
||||
inputName => {
|
||||
const central = 'central:https://custom.example.com/maven:false';
|
||||
|
||||
expect(() => auth.parseMavenRepositories([central], true)).toThrow(
|
||||
"Repository-id 'central' is reserved when mvn-repositories-include-central is enabled"
|
||||
);
|
||||
expect(auth.parseMavenRepositories([central], false)).toEqual([
|
||||
{
|
||||
id: 'central',
|
||||
url: 'https://custom.example.com/maven',
|
||||
snapshotsEnabled: false
|
||||
}
|
||||
]);
|
||||
});
|
||||
expect(() =>
|
||||
auth.parseMavenRepositories([central], true, inputName)
|
||||
).toThrow(
|
||||
"Repository-id 'central' is reserved when mvn-repositories-include-central is enabled"
|
||||
);
|
||||
expect(auth.parseMavenRepositories([central], false, inputName)).toEqual([
|
||||
{
|
||||
id: 'central',
|
||||
url: 'https://custom.example.com/maven',
|
||||
snapshotsEnabled: false
|
||||
}
|
||||
]);
|
||||
}
|
||||
);
|
||||
|
||||
it('uses an explicit Central repository instead of adding a disabled override', () => {
|
||||
const parsed = parseXmlObject(
|
||||
@@ -706,16 +1032,138 @@ describe('auth tests', () => {
|
||||
snapshotsEnabled: true
|
||||
}
|
||||
],
|
||||
pluginRepositories: [],
|
||||
includeCentral: false,
|
||||
prioritizeCentral: false
|
||||
});
|
||||
});
|
||||
|
||||
it('does not read repository controls when no repositories are configured', () => {
|
||||
(
|
||||
core.getInput as jest.MockedFunction<typeof core.getInput>
|
||||
).mockReturnValue('false');
|
||||
expect(auth.getMavenRepositorySettings()).toBeUndefined();
|
||||
expect(core.getInput).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('ignores blank dependency and plugin repository inputs', () => {
|
||||
(
|
||||
core.getMultilineInput as jest.MockedFunction<
|
||||
typeof core.getMultilineInput
|
||||
>
|
||||
).mockReturnValue(['', ' ', '\t']);
|
||||
|
||||
expect(auth.getMavenRepositorySettings()).toBeUndefined();
|
||||
expect(core.getInput).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it.each(repositoryConfigurations)(
|
||||
'reads $name inputs with default Central controls and shared IDs',
|
||||
({repositories, pluginRepositories}) => {
|
||||
(
|
||||
core.getInput as jest.MockedFunction<typeof core.getInput>
|
||||
).mockReturnValue('');
|
||||
(
|
||||
core.getMultilineInput as jest.MockedFunction<
|
||||
typeof core.getMultilineInput
|
||||
>
|
||||
).mockImplementation(name => {
|
||||
const configured =
|
||||
name === 'mvn-repositories' ? repositories : pluginRepositories;
|
||||
return configured.map(
|
||||
repository =>
|
||||
`${repository.id}:${repository.url}:${repository.snapshotsEnabled}`
|
||||
);
|
||||
});
|
||||
|
||||
expect(auth.getMavenRepositorySettings()).toEqual({
|
||||
repositories,
|
||||
pluginRepositories,
|
||||
includeCentral: true,
|
||||
prioritizeCentral: true
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
it.each([true, false])(
|
||||
'configures plugin repositories with credentials, GPG, a custom path, and overwrite=%s',
|
||||
async overwriteSettings => {
|
||||
const directory = path.join(m2Dir, 'custom');
|
||||
const location = path.join(directory, MVN_SETTINGS_FILE);
|
||||
fs.mkdirSync(directory, {recursive: true});
|
||||
fs.writeFileSync(location, 'EXISTING SETTINGS');
|
||||
(
|
||||
core.getInput as jest.MockedFunction<typeof core.getInput>
|
||||
).mockImplementation(name => {
|
||||
const inputs: Record<string, string> = {
|
||||
'settings-path': directory,
|
||||
'overwrite-settings': String(overwriteSettings),
|
||||
'gpg-passphrase-env-var': 'GPG_PASSPHRASE',
|
||||
'mvn-repositories-include-central': 'false'
|
||||
};
|
||||
return inputs[name] ?? '';
|
||||
});
|
||||
(
|
||||
core.getMultilineInput as jest.MockedFunction<
|
||||
typeof core.getMultilineInput
|
||||
>
|
||||
).mockImplementation(name => {
|
||||
const inputs: Record<string, string[]> = {
|
||||
'mvn-server-credentials': ['private:USERNAME:PASSWORD'],
|
||||
'mvn-server-repository-origins': ['private:https://repo.example.com'],
|
||||
'mvn-plugin-repositories': [
|
||||
'private:https://repo.example.com/maven:true'
|
||||
]
|
||||
};
|
||||
return inputs[name] ?? [];
|
||||
});
|
||||
|
||||
await auth.configureAuthentication();
|
||||
|
||||
const xml = fs.readFileSync(location, 'utf8');
|
||||
if (!overwriteSettings) {
|
||||
expect(xml).toBe('EXISTING SETTINGS');
|
||||
return;
|
||||
}
|
||||
expect(parseXmlObject(xml)).toMatchObject({
|
||||
settings: {
|
||||
servers: {
|
||||
server: {
|
||||
id: 'private',
|
||||
username: '${env.USERNAME}',
|
||||
password: '${env.PASSWORD}',
|
||||
repositoryOrigins: {
|
||||
repositoryOrigin: 'https://repo.example.com'
|
||||
}
|
||||
}
|
||||
},
|
||||
profiles: {
|
||||
profile: [
|
||||
{
|
||||
id: 'setup-java-repositories',
|
||||
repositories: {repository: disabledCentralRepositoryXml},
|
||||
pluginRepositories: {
|
||||
pluginRepository: [
|
||||
privateRepositoryXml,
|
||||
disabledCentralRepositoryXml
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'setup-java-gpg',
|
||||
properties: {'gpg.passphraseEnvName': 'GPG_PASSPHRASE'}
|
||||
}
|
||||
]
|
||||
},
|
||||
activeProfiles: {
|
||||
activeProfile: ['setup-java-repositories', 'setup-java-gpg']
|
||||
}
|
||||
}
|
||||
});
|
||||
expect(fs.existsSync(settingsFile)).toBe(false);
|
||||
}
|
||||
);
|
||||
|
||||
it.each([
|
||||
{
|
||||
entries: ['releases:RELEASES_USERNAME'],
|
||||
@@ -749,16 +1197,23 @@ describe('auth tests', () => {
|
||||
});
|
||||
|
||||
it('uses multiline Maven server credentials instead of single-server inputs', () => {
|
||||
(core.getMultilineInput as jest.Mock).mockReturnValue([
|
||||
'releases:RELEASES_USERNAME:RELEASES_PASSWORD',
|
||||
'snapshots:SNAPSHOTS_USERNAME:SNAPSHOTS_PASSWORD'
|
||||
]);
|
||||
(core.getMultilineInput as jest.Mock).mockImplementation((name: string) =>
|
||||
name === 'mvn-server-credentials'
|
||||
? [
|
||||
'releases:RELEASES_USERNAME:RELEASES_PASSWORD',
|
||||
'snapshots:SNAPSHOTS_USERNAME:SNAPSHOTS_PASSWORD'
|
||||
]
|
||||
: name === 'mvn-server-repository-origins'
|
||||
? ['releases:https://repo.example.com']
|
||||
: []
|
||||
);
|
||||
|
||||
expect(auth.getMavenServerSettings()).toEqual([
|
||||
{
|
||||
id: 'releases',
|
||||
usernameEnvVar: 'RELEASES_USERNAME',
|
||||
passwordEnvVar: 'RELEASES_PASSWORD'
|
||||
passwordEnvVar: 'RELEASES_PASSWORD',
|
||||
repositoryOrigins: ['https://repo.example.com']
|
||||
},
|
||||
{
|
||||
id: 'snapshots',
|
||||
@@ -803,6 +1258,106 @@ describe('auth tests', () => {
|
||||
expect(core.warning).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it('adds normalized repository origins to matching Maven servers', () => {
|
||||
expect(
|
||||
auth.addMavenServerRepositoryOrigins(
|
||||
[
|
||||
{
|
||||
id: 'central',
|
||||
usernameEnvVar: 'CENTRAL_USER',
|
||||
passwordEnvVar: 'CENTRAL_PASS'
|
||||
},
|
||||
{
|
||||
id: 'packages',
|
||||
usernameEnvVar: 'GITHUB_ACTOR',
|
||||
passwordEnvVar: 'GITHUB_TOKEN'
|
||||
}
|
||||
],
|
||||
[
|
||||
'central:https://central.sonatype.com/',
|
||||
'central:https://central.sonatype.com',
|
||||
'central:https://central.sonatype.com:443',
|
||||
'packages:https://maven.pkg.github.com',
|
||||
'packages:ssh://packages.example.com:22',
|
||||
'packages:ftp://packages.example.com:21'
|
||||
]
|
||||
)
|
||||
).toEqual([
|
||||
{
|
||||
id: 'central',
|
||||
usernameEnvVar: 'CENTRAL_USER',
|
||||
passwordEnvVar: 'CENTRAL_PASS',
|
||||
repositoryOrigins: ['https://central.sonatype.com']
|
||||
},
|
||||
{
|
||||
id: 'packages',
|
||||
usernameEnvVar: 'GITHUB_ACTOR',
|
||||
passwordEnvVar: 'GITHUB_TOKEN',
|
||||
repositoryOrigins: [
|
||||
'https://maven.pkg.github.com',
|
||||
'ssh://packages.example.com:22',
|
||||
'ftp://packages.example.com:21'
|
||||
]
|
||||
}
|
||||
]);
|
||||
});
|
||||
|
||||
it.each([
|
||||
{
|
||||
entries: ['central'],
|
||||
error:
|
||||
'Invalid mvn-server-repository-origins entry at line 1. Expected format: server-id:repository-origin'
|
||||
},
|
||||
{
|
||||
entries: ['other:https://repo.example.com'],
|
||||
error:
|
||||
"Unknown server-id 'other' in mvn-server-repository-origins at line 1"
|
||||
},
|
||||
{
|
||||
entries: ['central:https://repo.example.com/path'],
|
||||
error:
|
||||
"Invalid repository origin 'https://repo.example.com/path' in mvn-server-repository-origins at line 1"
|
||||
},
|
||||
{
|
||||
entries: ['central:https:repo.example.com'],
|
||||
error:
|
||||
"Invalid repository origin 'https:repo.example.com' in mvn-server-repository-origins at line 1"
|
||||
},
|
||||
{
|
||||
entries: ['central:https:/repo.example.com'],
|
||||
error:
|
||||
"Invalid repository origin 'https:/repo.example.com' in mvn-server-repository-origins at line 1"
|
||||
},
|
||||
{
|
||||
entries: ['central:https://repo.example.com?'],
|
||||
error:
|
||||
"Invalid repository origin 'https://repo.example.com?' in mvn-server-repository-origins at line 1"
|
||||
},
|
||||
{
|
||||
entries: ['central:https://repo.example.com#'],
|
||||
error:
|
||||
"Invalid repository origin 'https://repo.example.com#' in mvn-server-repository-origins at line 1"
|
||||
},
|
||||
{
|
||||
entries: ['central:https://@repo.example.com'],
|
||||
error:
|
||||
"Invalid repository origin 'https://@repo.example.com' in mvn-server-repository-origins at line 1"
|
||||
}
|
||||
])('rejects invalid Maven server repository origins', ({entries, error}) => {
|
||||
expect(() =>
|
||||
auth.addMavenServerRepositoryOrigins(
|
||||
[
|
||||
{
|
||||
id: 'central',
|
||||
usernameEnvVar: 'CENTRAL_USER',
|
||||
passwordEnvVar: 'CENTRAL_PASS'
|
||||
}
|
||||
],
|
||||
entries
|
||||
)
|
||||
).toThrow(error);
|
||||
});
|
||||
|
||||
function xmlElementText(xml: string, tagName: string): string {
|
||||
const match = new RegExp(`<${tagName}>([\\s\\S]*?)</${tagName}>`).exec(xml);
|
||||
expect(match).not.toBeNull();
|
||||
|
||||
@@ -374,49 +374,6 @@ describe('findInToolcache', () => {
|
||||
);
|
||||
});
|
||||
|
||||
describe('exact build requests in tool-cache', () => {
|
||||
afterEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
it.each(['jdk-27+35', '27+35', '27.0+35', '27.0.0+35'])(
|
||||
'only matches the requested build for %s',
|
||||
input => {
|
||||
const findAllVersions = jest.mocked(tc.findAllVersions);
|
||||
findAllVersions.mockReturnValue([
|
||||
'27.0.1-35',
|
||||
'27.0.0-36',
|
||||
'27.0.0-ea.35',
|
||||
'27.0.0-35'
|
||||
]);
|
||||
jest
|
||||
.mocked(util.getToolcachePath)
|
||||
.mockImplementation(
|
||||
(toolname, version, architecture) =>
|
||||
`/hostedtoolcache/${toolname}/${version}/${architecture}`
|
||||
);
|
||||
const distribution = new EmptyJavaBase({
|
||||
version: input,
|
||||
architecture: 'x64',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
});
|
||||
|
||||
expect(distribution['findInToolcache']()).toEqual({
|
||||
version: '27.0.0+35',
|
||||
path: '/hostedtoolcache/Java_Empty_jdk/27.0.0-35/x64'
|
||||
});
|
||||
|
||||
findAllVersions.mockReturnValue([
|
||||
'27.0.1-35',
|
||||
'27.0.0-36',
|
||||
'27.0.0-ea.35'
|
||||
]);
|
||||
expect(distribution['findInToolcache']()).toBeNull();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
describe('setupJava', () => {
|
||||
const actualJavaVersion = '11.0.9';
|
||||
const installedJavaVersion = '11.0.8';
|
||||
@@ -1792,15 +1749,6 @@ describe('normalizeVersion', () => {
|
||||
const DummyJavaBase = JavaBase as any;
|
||||
|
||||
it.each([
|
||||
['jdk-27+35', {version: '27.0.0+35', stable: true, latest: false}],
|
||||
['27+35', {version: '27.0.0+35', stable: true, latest: false}],
|
||||
['27.0+35', {version: '27.0.0+35', stable: true, latest: false}],
|
||||
['jdk-27', {version: '27', stable: true, latest: false}],
|
||||
['jdk-27.0', {version: '27.0', stable: true, latest: false}],
|
||||
['jdk-27-ea', {version: '27', stable: false, latest: false}],
|
||||
['jdk-27+35-ea', {version: '27.0.0+35', stable: false, latest: false}],
|
||||
['jdk-27-ea.35', {version: '27.0.0+35', stable: false, latest: false}],
|
||||
['jdk-26.0.2.1+1', {version: '26.0.2+1.1', stable: true, latest: false}],
|
||||
['11', {version: '11', stable: true, latest: false}],
|
||||
['11.0', {version: '11.0', stable: true, latest: false}],
|
||||
['11.0.10', {version: '11.0.10', stable: true, latest: false}],
|
||||
@@ -1830,24 +1778,6 @@ describe('normalizeVersion', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it.each([
|
||||
'jdk-',
|
||||
'jdk-latest',
|
||||
'jdk-27.x',
|
||||
'jdk->=27',
|
||||
'jdk8u442-b06',
|
||||
'temurin-27+35',
|
||||
'jdk-27-ea+35',
|
||||
'jdk-27+',
|
||||
'jdk-27+35..1',
|
||||
'27+35..1',
|
||||
'jdk-27..0+35'
|
||||
])('rejects malformed or unsupported release tags: %s', input => {
|
||||
expect(() =>
|
||||
DummyJavaBase.prototype.normalizeVersion.call(null, input)
|
||||
).toThrow(/is not valid SemVer notation for a Java version/);
|
||||
});
|
||||
|
||||
it.each(['latest-ea', 'latest.1', 'LATEST-EA', ' latest-ea '])(
|
||||
'normalizeVersion should throw a targeted error for latest combined with a qualifier (%s)',
|
||||
version => {
|
||||
|
||||
@@ -82,7 +82,7 @@ describe('getJavaDistribution', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it.each(['8', '23.x', '23.0.1.1', '23.0.1.1+1', '<24', 'jdk-23+35'])(
|
||||
it.each(['8', '23.x', '23.0.1.1', '23.0.1.1+1', '<24'])(
|
||||
"rejects Temurin java-package 'jdk+jmods' for version %s",
|
||||
async version => {
|
||||
await expect(
|
||||
@@ -96,15 +96,7 @@ describe('getJavaDistribution', () => {
|
||||
}
|
||||
);
|
||||
|
||||
it.each([
|
||||
'24',
|
||||
'24.0.1.1',
|
||||
'25.0.4.1+1',
|
||||
'25-ea',
|
||||
'>=21',
|
||||
'latest',
|
||||
'jdk-27+35'
|
||||
])(
|
||||
it.each(['24', '24.0.1.1', '25.0.4.1+1', '25-ea', '>=21', 'latest'])(
|
||||
"accepts Temurin java-package 'jdk+jmods' for version %s",
|
||||
async version => {
|
||||
expect(
|
||||
@@ -125,17 +117,6 @@ describe('getJavaDistribution', () => {
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
it('does not change the distribution or package for a jdk-prefixed version', async () => {
|
||||
const distribution = await getJavaDistribution(
|
||||
JavaDistribution.Zulu,
|
||||
installerOptions('jre', 'jdk-27+35')
|
||||
);
|
||||
|
||||
expect(distribution!['distribution']).toBe('Zulu');
|
||||
expect(distribution!['packageType']).toBe('jre');
|
||||
expect(distribution!['version']).toBe('27.0.0+35');
|
||||
});
|
||||
|
||||
it.each(['adopt', 'adopt-hotspot', 'adopt-openj9'])(
|
||||
'does not support legacy Adopt distribution %s',
|
||||
async distributionName => {
|
||||
|
||||
@@ -378,7 +378,7 @@ describe('findPackageForDownload', () => {
|
||||
expect(resolvedVersion.version).toBe('16.0.2+7');
|
||||
});
|
||||
|
||||
describe('OpenJDK versions and release tags', () => {
|
||||
describe('OpenJDK patch (respin) versions', () => {
|
||||
const makeRelease = (
|
||||
semverVersion: string,
|
||||
openjdkVersion: string,
|
||||
@@ -402,21 +402,6 @@ describe('findPackageForDownload', () => {
|
||||
});
|
||||
|
||||
const respinManifest = [
|
||||
makeRelease('27.0.1+35', '27.0.1+35', {
|
||||
major: 27,
|
||||
security: 1,
|
||||
build: 35
|
||||
}),
|
||||
makeRelease('27.0.0+36', '27+36', {
|
||||
major: 27,
|
||||
security: 0,
|
||||
build: 36
|
||||
}),
|
||||
makeRelease('27.0.0+35', '27+35', {
|
||||
major: 27,
|
||||
security: 0,
|
||||
build: 35
|
||||
}),
|
||||
makeRelease('26.0.2+101', '26.0.2.1+1', {
|
||||
major: 26,
|
||||
security: 2,
|
||||
@@ -442,13 +427,6 @@ describe('findPackageForDownload', () => {
|
||||
];
|
||||
|
||||
it.each([
|
||||
['jdk-27+35', '27.0.0+35'],
|
||||
['27+35', '27.0.0+35'],
|
||||
['27.0+35', '27.0.0+35'],
|
||||
['jdk-27.0.0+35', '27.0.0+35'],
|
||||
['jdk-27', '27.0.1+35'],
|
||||
['27', '27.0.1+35'],
|
||||
['jdk-26.0.2.1+1', '26.0.2+101'],
|
||||
['26.0.2.1+1', '26.0.2+101'],
|
||||
['26.0.2+10', '26.0.2+10'],
|
||||
['26', '26.0.2+101'],
|
||||
@@ -474,27 +452,21 @@ describe('findPackageForDownload', () => {
|
||||
expect(resolvedVersion).not.toHaveProperty('openjdkVersion');
|
||||
});
|
||||
|
||||
it.each(['26.0.2.2+1', 'jdk-27+34', '27+34'])(
|
||||
'does not match a non-existent build or respin: %s',
|
||||
async input => {
|
||||
const distribution = new TemurinDistribution(
|
||||
{
|
||||
version: input,
|
||||
architecture: 'x64',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
},
|
||||
TemurinImplementation.Hotspot
|
||||
);
|
||||
distribution['getAvailableVersions'] = async () =>
|
||||
respinManifest as any;
|
||||
await expect(
|
||||
distribution['findPackageForDownload'](distribution['version'])
|
||||
).rejects.toThrow(
|
||||
`No matching version found for SemVer '${distribution['version']}'`
|
||||
);
|
||||
}
|
||||
);
|
||||
it('does not match a non-existent respin', async () => {
|
||||
const distribution = new TemurinDistribution(
|
||||
{
|
||||
version: '26.0.2.2+1',
|
||||
architecture: 'x64',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
},
|
||||
TemurinImplementation.Hotspot
|
||||
);
|
||||
distribution['getAvailableVersions'] = async () => respinManifest as any;
|
||||
await expect(
|
||||
distribution['findPackageForDownload'](distribution['version'])
|
||||
).rejects.toThrow(/No matching version found for SemVer '26.0.2\+2.1'/);
|
||||
});
|
||||
});
|
||||
|
||||
it('version is found but binaries list is empty', async () => {
|
||||
|
||||
@@ -102,24 +102,6 @@ describe('Java platform capabilities', () => {
|
||||
}
|
||||
);
|
||||
|
||||
it.each(['jdk-27+35', '27+35', 'jdk-27-ea.35'])(
|
||||
'enforces version-dependent architecture restrictions for %s',
|
||||
version => {
|
||||
expect(() =>
|
||||
validateJavaPlatform('corretto', 'linux', 'x86', version)
|
||||
).toThrow(/x86 \(<12\)/);
|
||||
}
|
||||
);
|
||||
|
||||
it.each(['jdk-11+9', '11+9', 'jdk-11-ea.9'])(
|
||||
'accepts compatible numeric release tags: %s',
|
||||
version => {
|
||||
expect(validateJavaPlatform('corretto', 'linux', 'x86', version)).toBe(
|
||||
'x86'
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
it('allows local archives on any platform and architecture', () => {
|
||||
expect(validateJavaPlatform('jdkfile', 'aix', 'mips64', '21')).toBe(
|
||||
'mips64'
|
||||
|
||||
+1
-16
@@ -191,17 +191,6 @@ describe('convertVersionToSemver', () => {
|
||||
|
||||
describe('normalizeJavaVersionToSemver', () => {
|
||||
it.each([
|
||||
['jdk-27+35', '27.0.0+35'],
|
||||
['27+35', '27.0.0+35'],
|
||||
['27.0+35', '27.0.0+35'],
|
||||
['jdk-27.0+35', '27.0.0+35'],
|
||||
['jdk-27.0.0+35', '27.0.0+35'],
|
||||
['jdk-27', '27'],
|
||||
['jdk-27.0', '27.0'],
|
||||
['jdk-27.0.1', '27.0.1'],
|
||||
['27+35.0.LTS', '27.0.0+35.0.LTS'],
|
||||
['jdk-26.0.2.1+1', '26.0.2+1.1'],
|
||||
['jdk-11.0.9.1', '11.0.9+1'],
|
||||
['17', '17'],
|
||||
['17.0.8', '17.0.8'],
|
||||
['17.0.8+7', '17.0.8+7'],
|
||||
@@ -210,11 +199,7 @@ describe('normalizeJavaVersionToSemver', () => {
|
||||
['26.0.2.1+1', '26.0.2+1.1'],
|
||||
['17.0.8.1+1080.1', '17.0.8+1.1080.1'],
|
||||
['>=11.0.9.1', '>=11.0.9.1'],
|
||||
['17.x', '17.x'],
|
||||
['>=17 <28', '>=17 <28'],
|
||||
['jdk-27.x', 'jdk-27.x'],
|
||||
['jdk-latest', 'jdk-latest'],
|
||||
['temurin-27+35', 'temurin-27+35']
|
||||
['17.x', '17.x']
|
||||
])('%s -> %s', (input: string, expected: string) => {
|
||||
expect(normalizeJavaVersionToSemver(input)).toBe(expected);
|
||||
});
|
||||
|
||||
+8
-2
@@ -66,15 +66,21 @@ inputs:
|
||||
mvn-server-credentials:
|
||||
description: 'Multiline list of Maven server credentials in the format `server-id:USERNAME_ENV:PASSWORD_ENV`. When set, replaces the single server configured by server-id, server-username-env-var, and server-password-env-var.'
|
||||
required: false
|
||||
mvn-server-repository-origins:
|
||||
description: 'Multiline list of Maven credential origins in the format `server-id:repository-origin`. Each origin must belong to a configured server ID. Requires Maven 3.10+.'
|
||||
required: false
|
||||
mvn-repositories:
|
||||
description: 'Multiline list of Maven dependency repositories in the format `repository-id:repository-url:snapshots-enabled`.'
|
||||
required: false
|
||||
mvn-plugin-repositories:
|
||||
description: 'Multiline list of Maven plugin repositories in the format `repository-id:repository-url:snapshots-enabled`.'
|
||||
required: false
|
||||
mvn-repositories-include-central:
|
||||
description: 'Include Maven Central in the generated dependency repositories profile. When false, Central is disabled unless an explicit repository with ID `central` is declared.'
|
||||
description: 'Include Maven Central for dependency and plugin repositories in the generated profile. When false, Central is disabled for both types unless that type explicitly declares ID `central`. Has no effect when neither repository list is configured.'
|
||||
required: false
|
||||
default: true
|
||||
mvn-repositories-prioritize-central:
|
||||
description: 'Place Maven Central before custom dependency repositories. Has no effect when Maven Central is excluded.'
|
||||
description: 'Place Maven Central before custom dependency and plugin repositories. Has no effect when Maven Central is excluded or neither repository list is configured.'
|
||||
required: false
|
||||
default: true
|
||||
settings-path:
|
||||
|
||||
Vendored
+10
-16
@@ -31040,7 +31040,7 @@ module.exports = {
|
||||
/* harmony export */ gk: () => (/* binding */ INPUT_CACHE),
|
||||
/* harmony export */ wG: () => (/* binding */ INPUT_JOB_STATUS)
|
||||
/* harmony export */ });
|
||||
/* unused harmony exports MACOS_JAVA_CONTENT_POSTFIX, INPUT_JAVA_VERSION, INPUT_JAVA_VERSION_FILE, INPUT_ARCHITECTURE, INPUT_JAVA_PACKAGE, INPUT_DISTRIBUTION, INPUT_JDK_FILE, INPUT_JDK_FILE_DEPRECATED, INPUT_CHECK_LATEST, INPUT_FORCE_DOWNLOAD, INPUT_SET_DEFAULT, INPUT_PROBLEM_MATCHER, INPUT_VERIFY_SIGNATURE, INPUT_VERIFY_SIGNATURE_PUBLIC_KEY, SIGNATURE_VERIFICATION_DOCUMENTATION_URL, SIGNATURE_VERIFICATION_FAILURE_HELP, INPUT_MVN_SERVER_CREDENTIALS, INPUT_MVN_REPOSITORIES, INPUT_MVN_REPOSITORIES_INCLUDE_CENTRAL, INPUT_MVN_REPOSITORIES_PRIORITIZE_CENTRAL, INPUT_SERVER_ID, INPUT_SERVER_USERNAME_ENV_VAR, INPUT_SERVER_PASSWORD_ENV_VAR, INPUT_SERVER_USERNAME_DEPRECATED, INPUT_SERVER_PASSWORD_DEPRECATED, INPUT_SETTINGS_PATH, INPUT_OVERWRITE_SETTINGS, INPUT_GPG_PRIVATE_KEY, INPUT_GPG_PASSPHRASE_ENV_VAR, INPUT_GPG_PASSPHRASE_DEPRECATED, INPUT_DEFAULT_SERVER_USERNAME, INPUT_DEFAULT_SERVER_PASSWORD, INPUT_DEFAULT_GPG_PRIVATE_KEY, INPUT_DEFAULT_GPG_PASSPHRASE, MAVEN_GPG_PASSPHRASE_DEFAULT_ENV, GPG_PASSPHRASE_PROFILE_ID, MAVEN_REPOSITORIES_PROFILE_ID, MAVEN_CENTRAL_REPOSITORY_ID, MAVEN_CENTRAL_REPOSITORY_URL, INPUT_CACHE_DEPENDENCY_PATH, INPUT_CACHE_PATH, M2_DIR, MVN_SETTINGS_FILE, MVN_TOOLCHAINS_FILE, INPUT_MVN_TOOLCHAIN_ID, INPUT_MVN_TOOLCHAIN_VENDOR, INPUT_SHOW_DOWNLOAD_PROGRESS, MAVEN_ARGS_ENV, MAVEN_NO_TRANSFER_PROGRESS_FLAG, MAVEN_NO_TRANSFER_PROGRESS_LONG_FLAG, DISTRIBUTIONS_ONLY_MAJOR_VERSION */
|
||||
/* unused harmony exports MACOS_JAVA_CONTENT_POSTFIX, INPUT_JAVA_VERSION, INPUT_JAVA_VERSION_FILE, INPUT_ARCHITECTURE, INPUT_JAVA_PACKAGE, INPUT_DISTRIBUTION, INPUT_JDK_FILE, INPUT_JDK_FILE_DEPRECATED, INPUT_CHECK_LATEST, INPUT_FORCE_DOWNLOAD, INPUT_SET_DEFAULT, INPUT_PROBLEM_MATCHER, INPUT_VERIFY_SIGNATURE, INPUT_VERIFY_SIGNATURE_PUBLIC_KEY, SIGNATURE_VERIFICATION_DOCUMENTATION_URL, SIGNATURE_VERIFICATION_FAILURE_HELP, INPUT_MVN_SERVER_CREDENTIALS, INPUT_MVN_SERVER_REPOSITORY_ORIGINS, INPUT_MVN_REPOSITORIES, INPUT_MVN_PLUGIN_REPOSITORIES, INPUT_MVN_REPOSITORIES_INCLUDE_CENTRAL, INPUT_MVN_REPOSITORIES_PRIORITIZE_CENTRAL, INPUT_SERVER_ID, INPUT_SERVER_USERNAME_ENV_VAR, INPUT_SERVER_PASSWORD_ENV_VAR, INPUT_SERVER_USERNAME_DEPRECATED, INPUT_SERVER_PASSWORD_DEPRECATED, INPUT_SETTINGS_PATH, INPUT_OVERWRITE_SETTINGS, INPUT_GPG_PRIVATE_KEY, INPUT_GPG_PASSPHRASE_ENV_VAR, INPUT_GPG_PASSPHRASE_DEPRECATED, INPUT_DEFAULT_SERVER_USERNAME, INPUT_DEFAULT_SERVER_PASSWORD, INPUT_DEFAULT_GPG_PRIVATE_KEY, INPUT_DEFAULT_GPG_PASSPHRASE, MAVEN_GPG_PASSPHRASE_DEFAULT_ENV, GPG_PASSPHRASE_PROFILE_ID, MAVEN_REPOSITORIES_PROFILE_ID, MAVEN_CENTRAL_REPOSITORY_ID, MAVEN_CENTRAL_REPOSITORY_URL, INPUT_CACHE_DEPENDENCY_PATH, INPUT_CACHE_PATH, M2_DIR, MVN_SETTINGS_FILE, MVN_TOOLCHAINS_FILE, INPUT_MVN_TOOLCHAIN_ID, INPUT_MVN_TOOLCHAIN_VENDOR, INPUT_SHOW_DOWNLOAD_PROGRESS, MAVEN_ARGS_ENV, MAVEN_NO_TRANSFER_PROGRESS_FLAG, MAVEN_NO_TRANSFER_PROGRESS_LONG_FLAG, DISTRIBUTIONS_ONLY_MAJOR_VERSION */
|
||||
const MACOS_JAVA_CONTENT_POSTFIX = 'Contents/Home';
|
||||
const INPUT_JAVA_VERSION = 'java-version';
|
||||
const INPUT_JAVA_VERSION_FILE = 'java-version-file';
|
||||
@@ -31058,7 +31058,9 @@ const INPUT_VERIFY_SIGNATURE_PUBLIC_KEY = 'verify-signature-public-key';
|
||||
const SIGNATURE_VERIFICATION_DOCUMENTATION_URL = 'https://github.com/actions/setup-java#download-integrity-and-signatures';
|
||||
const SIGNATURE_VERIFICATION_FAILURE_HELP = (/* unused pure expression or super */ null && (`If this is a legitimate vendor signing-key rotation, see ${SIGNATURE_VERIFICATION_DOCUMENTATION_URL} for instructions to configure the updated public key or temporarily disable signature verification.`));
|
||||
const INPUT_MVN_SERVER_CREDENTIALS = 'mvn-server-credentials';
|
||||
const INPUT_MVN_SERVER_REPOSITORY_ORIGINS = 'mvn-server-repository-origins';
|
||||
const INPUT_MVN_REPOSITORIES = 'mvn-repositories';
|
||||
const INPUT_MVN_PLUGIN_REPOSITORIES = 'mvn-plugin-repositories';
|
||||
const INPUT_MVN_REPOSITORIES_INCLUDE_CENTRAL = 'mvn-repositories-include-central';
|
||||
const INPUT_MVN_REPOSITORIES_PRIORITIZE_CENTRAL = 'mvn-repositories-prioritize-central';
|
||||
const INPUT_SERVER_ID = 'server-id';
|
||||
@@ -31514,26 +31516,18 @@ function convertVersionToSemver(version) {
|
||||
return mainVersion;
|
||||
}
|
||||
/**
|
||||
* Normalize numeric Java versions, optionally prefixed with 'jdk-'. Pad
|
||||
* abbreviated build requests ('27+35' -> '27.0.0+35') to preserve exact
|
||||
* matching, and move extra JEP 322 fields into build metadata
|
||||
* ('26.0.2.1+1' -> '26.0.2+1.1'). Leave ranges unchanged.
|
||||
* Java versions (JEP 322) can contain more numeric fields than SemVer allows,
|
||||
* e.g. '11.0.9.1' or Temurin respins such as '26.0.2.1+1'. Move the extra
|
||||
* fields into SemVer build metadata ('11.0.9+1', '26.0.2+1.1'). Any other
|
||||
* input (ranges, regular SemVer versions) is returned unchanged.
|
||||
*/
|
||||
function normalizeJavaVersionToSemver(version) {
|
||||
const match = /^(?:jdk-)?(\d+(?:\.\d+)*)(?:\+([0-9A-Za-z.-]+))?$/.exec(version);
|
||||
const match = /^(\d+(?:\.\d+){3,})(?:\+([0-9A-Za-z.-]+))?$/.exec(version);
|
||||
if (!match) {
|
||||
return version;
|
||||
}
|
||||
const versionParts = match[1].split('.');
|
||||
if (match[2]) {
|
||||
while (versionParts.length < 3) {
|
||||
versionParts.push('0');
|
||||
}
|
||||
}
|
||||
const converted = convertVersionToSemver(versionParts.join('.'));
|
||||
return match[2]
|
||||
? `${converted}${versionParts.length > 3 ? '.' : '+'}${match[2]}`
|
||||
: converted;
|
||||
const converted = convertVersionToSemver(match[1]);
|
||||
return match[2] ? `${converted}.${match[2]}` : converted;
|
||||
}
|
||||
/**
|
||||
* Builds a validator for the bytes currently served by a URL from the response
|
||||
|
||||
Vendored
+4
-2
@@ -728,8 +728,10 @@ class JavaBase {
|
||||
version = version.replace('-ea.', '+');
|
||||
stable = false;
|
||||
}
|
||||
// Normalize Java release tags and JEP 322 versions without losing exact
|
||||
// build constraints ('jdk-27+35' -> '27.0.0+35'). Leave ranges unchanged.
|
||||
// Java uses a versioning scheme (JEP 322) that can contain more numeric
|
||||
// fields than SemVer allows, e.g. '18.0.1.1' or '11.0.9.1'. Convert such
|
||||
// exact versions to SemVer build notation ('18.0.1+1', or '26.0.2+1.1'
|
||||
// for '26.0.2.1+1') so they are accepted. Ranges are left untouched.
|
||||
version = (0,util/* normalizeJavaVersionToSemver */.zZ)(version);
|
||||
if (!semver_default().validRange(version)) {
|
||||
throw new Error(`The string '${version}' is not valid SemVer notation for a Java version. Please check README file for code snippets and more detailed information`);
|
||||
|
||||
Vendored
+117
-44
@@ -7,6 +7,7 @@ export const modules = {
|
||||
|
||||
__webpack_require__.r(__webpack_exports__);
|
||||
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
||||
/* harmony export */ addMavenServerRepositoryOrigins: () => (/* binding */ addMavenServerRepositoryOrigins),
|
||||
/* harmony export */ configureAuthentication: () => (/* binding */ configureAuthentication),
|
||||
/* harmony export */ createAuthenticationSettings: () => (/* binding */ createAuthenticationSettings),
|
||||
/* harmony export */ generate: () => (/* binding */ generate),
|
||||
@@ -37,6 +38,7 @@ __webpack_require__.r(__webpack_exports__);
|
||||
|
||||
|
||||
|
||||
const MAVEN_REPOSITORY_ORIGIN = /^[A-Za-z][A-Za-z0-9+.-]*:\/\/[^/?#@]+\/?$/;
|
||||
async function configureAuthentication() {
|
||||
const servers = getMavenServerSettings();
|
||||
const repositorySettings = getMavenRepositorySettings();
|
||||
@@ -74,16 +76,16 @@ function getInputWithDeprecatedAlias(inputName, deprecatedInputName, defaultValu
|
||||
// only exported for testing purposes
|
||||
function getMavenServerSettings() {
|
||||
const entries = _actions_core__WEBPACK_IMPORTED_MODULE_1__/* .getMultilineInput */ .q3(_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_MVN_SERVER_CREDENTIALS */ .MM);
|
||||
if (entries.some(entry => entry.trim())) {
|
||||
return parseMavenServerCredentials(entries);
|
||||
}
|
||||
return [
|
||||
{
|
||||
id: _actions_core__WEBPACK_IMPORTED_MODULE_1__/* .getInput */ .V4(_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_SERVER_ID */ .fd),
|
||||
usernameEnvVar: getInputWithDeprecatedAlias(_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_SERVER_USERNAME_ENV_VAR */ .sc, _constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_SERVER_USERNAME_DEPRECATED */ .sp, _constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_DEFAULT_SERVER_USERNAME */ .Wj),
|
||||
passwordEnvVar: getInputWithDeprecatedAlias(_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_SERVER_PASSWORD_ENV_VAR */ .r4, _constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_SERVER_PASSWORD_DEPRECATED */ .Vt, _constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_DEFAULT_SERVER_PASSWORD */ .xp)
|
||||
}
|
||||
];
|
||||
const servers = entries.some(entry => entry.trim())
|
||||
? parseMavenServerCredentials(entries)
|
||||
: [
|
||||
{
|
||||
id: _actions_core__WEBPACK_IMPORTED_MODULE_1__/* .getInput */ .V4(_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_SERVER_ID */ .fd),
|
||||
usernameEnvVar: getInputWithDeprecatedAlias(_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_SERVER_USERNAME_ENV_VAR */ .sc, _constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_SERVER_USERNAME_DEPRECATED */ .sp, _constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_DEFAULT_SERVER_USERNAME */ .Wj),
|
||||
passwordEnvVar: getInputWithDeprecatedAlias(_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_SERVER_PASSWORD_ENV_VAR */ .r4, _constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_SERVER_PASSWORD_DEPRECATED */ .Vt, _constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_DEFAULT_SERVER_PASSWORD */ .xp)
|
||||
}
|
||||
];
|
||||
return addMavenServerRepositoryOrigins(servers, _actions_core__WEBPACK_IMPORTED_MODULE_1__/* .getMultilineInput */ .q3(_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_MVN_SERVER_REPOSITORY_ORIGINS */ .Pt));
|
||||
}
|
||||
// only exported for testing purposes
|
||||
function parseMavenServerCredentials(entries) {
|
||||
@@ -110,20 +112,78 @@ function parseMavenServerCredentials(entries) {
|
||||
return servers;
|
||||
}
|
||||
// only exported for testing purposes
|
||||
function addMavenServerRepositoryOrigins(servers, entries) {
|
||||
const serverIds = new Set(servers.map(server => server.id));
|
||||
const originsByServer = new Map();
|
||||
entries.forEach((entry, index) => {
|
||||
if (!entry.trim()) {
|
||||
return;
|
||||
}
|
||||
const separator = entry.indexOf(':');
|
||||
if (separator <= 0 || separator === entry.length - 1) {
|
||||
throw new Error(`Invalid mvn-server-repository-origins entry at line ${index + 1}. Expected format: server-id:repository-origin`);
|
||||
}
|
||||
const id = entry.slice(0, separator).trim();
|
||||
const value = entry.slice(separator + 1).trim();
|
||||
if (!id || !value) {
|
||||
throw new Error(`Invalid mvn-server-repository-origins entry at line ${index + 1}. Server ID and repository origin are required`);
|
||||
}
|
||||
if (!serverIds.has(id)) {
|
||||
throw new Error(`Unknown server-id '${id}' in mvn-server-repository-origins at line ${index + 1}`);
|
||||
}
|
||||
let url;
|
||||
try {
|
||||
if (!MAVEN_REPOSITORY_ORIGIN.test(value)) {
|
||||
throw new Error();
|
||||
}
|
||||
url = new URL(value);
|
||||
}
|
||||
catch {
|
||||
throw new Error(`Invalid repository origin '${value}' in mvn-server-repository-origins at line ${index + 1}`);
|
||||
}
|
||||
if (!url.host ||
|
||||
url.username ||
|
||||
url.password ||
|
||||
(url.pathname !== '' && url.pathname !== '/') ||
|
||||
url.search ||
|
||||
url.hash) {
|
||||
throw new Error(`Invalid repository origin '${value}' in mvn-server-repository-origins at line ${index + 1}`);
|
||||
}
|
||||
const explicitPort = /:(\d+)\/?$/.exec(value)?.[1];
|
||||
const port = explicitPort ? Number.parseInt(explicitPort, 10) : undefined;
|
||||
const includePort = port !== undefined &&
|
||||
!((url.protocol === 'http:' && port === 80) ||
|
||||
(url.protocol === 'https:' && port === 443));
|
||||
const origin = `${url.protocol}//${url.hostname}${includePort ? `:${port}` : ''}`;
|
||||
const origins = originsByServer.get(id) || [];
|
||||
if (!origins.includes(origin)) {
|
||||
origins.push(origin);
|
||||
originsByServer.set(id, origins);
|
||||
}
|
||||
});
|
||||
return servers.map(server => {
|
||||
const repositoryOrigins = originsByServer.get(server.id);
|
||||
return repositoryOrigins ? { ...server, repositoryOrigins } : server;
|
||||
});
|
||||
}
|
||||
// only exported for testing purposes
|
||||
function getMavenRepositorySettings() {
|
||||
const entries = _actions_core__WEBPACK_IMPORTED_MODULE_1__/* .getMultilineInput */ .q3(_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_MVN_REPOSITORIES */ .W2);
|
||||
if (!entries.some(entry => entry.trim())) {
|
||||
const pluginEntries = _actions_core__WEBPACK_IMPORTED_MODULE_1__/* .getMultilineInput */ .q3(_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_MVN_PLUGIN_REPOSITORIES */ .gR);
|
||||
if (!entries.some(entry => entry.trim()) &&
|
||||
!pluginEntries.some(entry => entry.trim())) {
|
||||
return undefined;
|
||||
}
|
||||
const includeCentral = (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .getBooleanInput */ .Vt)(_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_MVN_REPOSITORIES_INCLUDE_CENTRAL */ .H5, true);
|
||||
return {
|
||||
repositories: parseMavenRepositories(entries, includeCentral),
|
||||
pluginRepositories: parseMavenRepositories(pluginEntries, includeCentral, _constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_MVN_PLUGIN_REPOSITORIES */ .gR),
|
||||
includeCentral,
|
||||
prioritizeCentral: (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .getBooleanInput */ .Vt)(_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_MVN_REPOSITORIES_PRIORITIZE_CENTRAL */ .OT, true)
|
||||
};
|
||||
}
|
||||
// only exported for testing purposes
|
||||
function parseMavenRepositories(entries, includeCentral) {
|
||||
function parseMavenRepositories(entries, includeCentral, inputName = _constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_MVN_REPOSITORIES */ .W2) {
|
||||
const repositories = [];
|
||||
const repositoryIds = new Set();
|
||||
entries.forEach((entry, index) => {
|
||||
@@ -133,7 +193,7 @@ function parseMavenRepositories(entries, includeCentral) {
|
||||
const firstSeparator = entry.indexOf(':');
|
||||
const lastSeparator = entry.lastIndexOf(':');
|
||||
if (firstSeparator <= 0 || lastSeparator <= firstSeparator) {
|
||||
throw new Error(`Invalid mvn-repositories entry at line ${index + 1}. Expected format: repository-id:repository-url:snapshots-enabled`);
|
||||
throw new Error(`Invalid ${inputName} entry at line ${index + 1}. Expected format: repository-id:repository-url:snapshots-enabled`);
|
||||
}
|
||||
const id = entry.slice(0, firstSeparator).trim();
|
||||
const url = entry.slice(firstSeparator + 1, lastSeparator).trim();
|
||||
@@ -142,13 +202,13 @@ function parseMavenRepositories(entries, includeCentral) {
|
||||
.trim()
|
||||
.toLowerCase();
|
||||
if (!id || !url || !snapshotsValue) {
|
||||
throw new Error(`Invalid mvn-repositories entry at line ${index + 1}. repository-id, repository URL, and snapshots-enabled are required`);
|
||||
throw new Error(`Invalid ${inputName} entry at line ${index + 1}. repository-id, repository URL, and snapshots-enabled are required`);
|
||||
}
|
||||
if (snapshotsValue !== 'true' && snapshotsValue !== 'false') {
|
||||
throw new Error(`Invalid snapshots-enabled value '${snapshotsValue}' in mvn-repositories entry at line ${index + 1}. Expected true or false`);
|
||||
throw new Error(`Invalid snapshots-enabled value '${snapshotsValue}' in ${inputName} entry at line ${index + 1}. Expected true or false`);
|
||||
}
|
||||
if (repositoryIds.has(id)) {
|
||||
throw new Error(`Duplicate repository-id '${id}' in mvn-repositories input`);
|
||||
throw new Error(`Duplicate repository-id '${id}' in ${inputName} input`);
|
||||
}
|
||||
if (includeCentral && id === _constants_js__WEBPACK_IMPORTED_MODULE_7__/* .MAVEN_CENTRAL_REPOSITORY_ID */ .xg) {
|
||||
throw new Error(`Repository-id '${_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .MAVEN_CENTRAL_REPOSITORY_ID */ .xg}' is reserved when ${_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_MVN_REPOSITORIES_INCLUDE_CENTRAL */ .H5} is enabled`);
|
||||
@@ -162,6 +222,37 @@ function parseMavenRepositories(entries, includeCentral) {
|
||||
});
|
||||
return repositories;
|
||||
}
|
||||
function generateRepositorySection(customRepositories, settings, element) {
|
||||
if (!customRepositories.length && settings.includeCentral) {
|
||||
return [];
|
||||
}
|
||||
const centralRepository = {
|
||||
id: _constants_js__WEBPACK_IMPORTED_MODULE_7__/* .MAVEN_CENTRAL_REPOSITORY_ID */ .xg,
|
||||
url: _constants_js__WEBPACK_IMPORTED_MODULE_7__/* .MAVEN_CENTRAL_REPOSITORY_URL */ .jv,
|
||||
snapshotsEnabled: false
|
||||
};
|
||||
const customCentralConfigured = customRepositories.some(repository => repository.id === _constants_js__WEBPACK_IMPORTED_MODULE_7__/* .MAVEN_CENTRAL_REPOSITORY_ID */ .xg);
|
||||
const repositories = settings.includeCentral
|
||||
? settings.prioritizeCentral
|
||||
? [centralRepository, ...customRepositories]
|
||||
: [...customRepositories, centralRepository]
|
||||
: customCentralConfigured
|
||||
? customRepositories
|
||||
: [...customRepositories, { ...centralRepository, releasesEnabled: false }];
|
||||
const container = element === 'repository' ? 'repositories' : 'pluginRepositories';
|
||||
const lines = [` <${container}>`];
|
||||
for (const repository of repositories) {
|
||||
lines.push(` <${element}>`, ` <id>${(0,_xml_js__WEBPACK_IMPORTED_MODULE_8__/* .escapeXmlText */ .I)(repository.id)}</id>`, ` <url>${(0,_xml_js__WEBPACK_IMPORTED_MODULE_8__/* .escapeXmlText */ .I)(repository.url)}</url>`, ...(repository.releasesEnabled === undefined
|
||||
? []
|
||||
: [
|
||||
' <releases>',
|
||||
` <enabled>${repository.releasesEnabled}</enabled>`,
|
||||
' </releases>'
|
||||
]), ' <snapshots>', ` <enabled>${repository.snapshotsEnabled}</enabled>`, ' </snapshots>', ` </${element}>`);
|
||||
}
|
||||
lines.push(` </${container}>`);
|
||||
return lines;
|
||||
}
|
||||
async function createAuthenticationSettings(servers, settingsDirectory, overwriteSettings, gpgPassphraseEnvVar = undefined, repositorySettings = undefined) {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_1__/* .info */ .pq(`Creating ${_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .MVN_SETTINGS_FILE */ .vO} with server-id: ${servers.map(server => server.id).join(', ')}`);
|
||||
// when an alternate m2 location is specified use only that location (no .m2 directory)
|
||||
@@ -187,39 +278,21 @@ function generate(servers, gpgPassphraseEnvVar, repositorySettings) {
|
||||
' <servers>'
|
||||
];
|
||||
for (const server of servers) {
|
||||
lines.push(' <server>', ` <id>${(0,_xml_js__WEBPACK_IMPORTED_MODULE_8__/* .escapeXmlText */ .I)(server.id)}</id>`, ` <username>${(0,_xml_js__WEBPACK_IMPORTED_MODULE_8__/* .escapeXmlText */ .I)(`\${env.${server.usernameEnvVar}}`)}</username>`, ` <password>${(0,_xml_js__WEBPACK_IMPORTED_MODULE_8__/* .escapeXmlText */ .I)(`\${env.${server.passwordEnvVar}}`)}</password>`, ' </server>');
|
||||
lines.push(' <server>', ` <id>${(0,_xml_js__WEBPACK_IMPORTED_MODULE_8__/* .escapeXmlText */ .I)(server.id)}</id>`, ` <username>${(0,_xml_js__WEBPACK_IMPORTED_MODULE_8__/* .escapeXmlText */ .I)(`\${env.${server.usernameEnvVar}}`)}</username>`, ` <password>${(0,_xml_js__WEBPACK_IMPORTED_MODULE_8__/* .escapeXmlText */ .I)(`\${env.${server.passwordEnvVar}}`)}</password>`);
|
||||
if (server.repositoryOrigins) {
|
||||
lines.push(' <repositoryOrigins>');
|
||||
for (const origin of server.repositoryOrigins) {
|
||||
lines.push(` <repositoryOrigin>${(0,_xml_js__WEBPACK_IMPORTED_MODULE_8__/* .escapeXmlText */ .I)(origin)}</repositoryOrigin>`);
|
||||
}
|
||||
lines.push(' </repositoryOrigins>');
|
||||
}
|
||||
lines.push(' </server>');
|
||||
}
|
||||
lines.push(' </servers>');
|
||||
if (repositorySettings || includeGpgPassphraseProfile) {
|
||||
lines.push(' <profiles>');
|
||||
if (repositorySettings) {
|
||||
const centralRepository = {
|
||||
id: _constants_js__WEBPACK_IMPORTED_MODULE_7__/* .MAVEN_CENTRAL_REPOSITORY_ID */ .xg,
|
||||
url: _constants_js__WEBPACK_IMPORTED_MODULE_7__/* .MAVEN_CENTRAL_REPOSITORY_URL */ .jv,
|
||||
snapshotsEnabled: false
|
||||
};
|
||||
const customCentralConfigured = repositorySettings.repositories.some(repository => repository.id === _constants_js__WEBPACK_IMPORTED_MODULE_7__/* .MAVEN_CENTRAL_REPOSITORY_ID */ .xg);
|
||||
const repositories = repositorySettings.includeCentral
|
||||
? repositorySettings.prioritizeCentral
|
||||
? [centralRepository, ...repositorySettings.repositories]
|
||||
: [...repositorySettings.repositories, centralRepository]
|
||||
: customCentralConfigured
|
||||
? repositorySettings.repositories
|
||||
: [
|
||||
...repositorySettings.repositories,
|
||||
{ ...centralRepository, releasesEnabled: false }
|
||||
];
|
||||
lines.push(' <profile>', ` <id>${_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .MAVEN_REPOSITORIES_PROFILE_ID */ .hq}</id>`, ' <repositories>');
|
||||
for (const repository of repositories) {
|
||||
lines.push(' <repository>', ` <id>${(0,_xml_js__WEBPACK_IMPORTED_MODULE_8__/* .escapeXmlText */ .I)(repository.id)}</id>`, ` <url>${(0,_xml_js__WEBPACK_IMPORTED_MODULE_8__/* .escapeXmlText */ .I)(repository.url)}</url>`, ...(repository.releasesEnabled === undefined
|
||||
? []
|
||||
: [
|
||||
' <releases>',
|
||||
` <enabled>${repository.releasesEnabled}</enabled>`,
|
||||
' </releases>'
|
||||
]), ' <snapshots>', ` <enabled>${repository.snapshotsEnabled}</enabled>`, ' </snapshots>', ' </repository>');
|
||||
}
|
||||
lines.push(' </repositories>', ' </profile>');
|
||||
lines.push(' <profile>', ` <id>${_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .MAVEN_REPOSITORIES_PROFILE_ID */ .hq}</id>`, ...generateRepositorySection(repositorySettings.repositories, repositorySettings, 'repository'), ...generateRepositorySection(repositorySettings.pluginRepositories ?? [], repositorySettings, 'pluginRepository'), ' </profile>');
|
||||
}
|
||||
if (includeGpgPassphraseProfile) {
|
||||
lines.push(' <profile>', ` <id>${_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .GPG_PASSPHRASE_PROFILE_ID */ .K$}</id>`, ' <properties>', ` <gpg.passphraseEnvName>${(0,_xml_js__WEBPACK_IMPORTED_MODULE_8__/* .escapeXmlText */ .I)(gpgPassphraseEnvVar)}</gpg.passphraseEnvName>`, ' </properties>', ' </profile>');
|
||||
|
||||
Vendored
+42
-37
@@ -31046,6 +31046,7 @@ module.exports = {
|
||||
/* harmony export */ OD: () => (/* binding */ INPUT_DEFAULT_GPG_PRIVATE_KEY),
|
||||
/* harmony export */ OT: () => (/* binding */ INPUT_MVN_REPOSITORIES_PRIORITIZE_CENTRAL),
|
||||
/* harmony export */ PG: () => (/* binding */ MACOS_JAVA_CONTENT_POSTFIX),
|
||||
/* harmony export */ Pt: () => (/* binding */ INPUT_MVN_SERVER_REPOSITORY_ORIGINS),
|
||||
/* harmony export */ QM: () => (/* binding */ INPUT_JAVA_VERSION),
|
||||
/* harmony export */ RX: () => (/* binding */ INPUT_DEFAULT_GPG_PASSPHRASE),
|
||||
/* harmony export */ TS: () => (/* binding */ INPUT_OVERWRITE_SETTINGS),
|
||||
@@ -31060,6 +31061,7 @@ module.exports = {
|
||||
/* harmony export */ af: () => (/* binding */ INPUT_JAVA_VERSION_FILE),
|
||||
/* harmony export */ db: () => (/* binding */ INPUT_GPG_PASSPHRASE_ENV_VAR),
|
||||
/* harmony export */ fd: () => (/* binding */ INPUT_SERVER_ID),
|
||||
/* harmony export */ gR: () => (/* binding */ INPUT_MVN_PLUGIN_REPOSITORIES),
|
||||
/* harmony export */ g_: () => (/* binding */ INPUT_DISTRIBUTION),
|
||||
/* harmony export */ gk: () => (/* binding */ INPUT_CACHE),
|
||||
/* harmony export */ hq: () => (/* binding */ MAVEN_REPOSITORIES_PROFILE_ID),
|
||||
@@ -31106,7 +31108,9 @@ const INPUT_VERIFY_SIGNATURE_PUBLIC_KEY = 'verify-signature-public-key';
|
||||
const SIGNATURE_VERIFICATION_DOCUMENTATION_URL = 'https://github.com/actions/setup-java#download-integrity-and-signatures';
|
||||
const SIGNATURE_VERIFICATION_FAILURE_HELP = `If this is a legitimate vendor signing-key rotation, see ${SIGNATURE_VERIFICATION_DOCUMENTATION_URL} for instructions to configure the updated public key or temporarily disable signature verification.`;
|
||||
const INPUT_MVN_SERVER_CREDENTIALS = 'mvn-server-credentials';
|
||||
const INPUT_MVN_SERVER_REPOSITORY_ORIGINS = 'mvn-server-repository-origins';
|
||||
const INPUT_MVN_REPOSITORIES = 'mvn-repositories';
|
||||
const INPUT_MVN_PLUGIN_REPOSITORIES = 'mvn-plugin-repositories';
|
||||
const INPUT_MVN_REPOSITORIES_INCLUDE_CENTRAL = 'mvn-repositories-include-central';
|
||||
const INPUT_MVN_REPOSITORIES_PRIORITIZE_CENTRAL = 'mvn-repositories-prioritize-central';
|
||||
const INPUT_SERVER_ID = 'server-id';
|
||||
@@ -31278,9 +31282,7 @@ function createUnsupportedPackageError(distributionName, packageType, supportedP
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__nccwpck_require__.n(fs__WEBPACK_IMPORTED_MODULE_0__);
|
||||
/* harmony import */ var semver__WEBPACK_IMPORTED_MODULE_1__ = __nccwpck_require__(2088);
|
||||
/* harmony import */ var semver__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__nccwpck_require__.n(semver__WEBPACK_IMPORTED_MODULE_1__);
|
||||
/* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_2__ = __nccwpck_require__(4527);
|
||||
/* harmony import */ var _package_types_js__WEBPACK_IMPORTED_MODULE_3__ = __nccwpck_require__(7835);
|
||||
|
||||
/* harmony import */ var _package_types_js__WEBPACK_IMPORTED_MODULE_2__ = __nccwpck_require__(7835);
|
||||
|
||||
|
||||
|
||||
@@ -31294,21 +31296,21 @@ const STANDARD_LINUX = [
|
||||
's390x'
|
||||
];
|
||||
const JAVA_PLATFORM_CAPABILITIES = {
|
||||
[_package_types_js__WEBPACK_IMPORTED_MODULE_3__/* .JavaDistribution */ .zS.Temurin]: {
|
||||
[_package_types_js__WEBPACK_IMPORTED_MODULE_2__/* .JavaDistribution */ .zS.Temurin]: {
|
||||
platforms: {
|
||||
linux: [...STANDARD_LINUX, { architecture: 'armv7', versionRange: '<18' }],
|
||||
macos: X64_ARM64,
|
||||
windows: ['x64', 'x86', 'aarch64']
|
||||
}
|
||||
},
|
||||
[_package_types_js__WEBPACK_IMPORTED_MODULE_3__/* .JavaDistribution */ .zS.Zulu]: {
|
||||
[_package_types_js__WEBPACK_IMPORTED_MODULE_2__/* .JavaDistribution */ .zS.Zulu]: {
|
||||
platforms: {
|
||||
linux: ['x64', 'x86', 'armv7', 'aarch64'],
|
||||
macos: X64_ARM64,
|
||||
windows: ['x64', 'x86', 'aarch64']
|
||||
}
|
||||
},
|
||||
[_package_types_js__WEBPACK_IMPORTED_MODULE_3__/* .JavaDistribution */ .zS.Liberica]: {
|
||||
[_package_types_js__WEBPACK_IMPORTED_MODULE_2__/* .JavaDistribution */ .zS.Liberica]: {
|
||||
platforms: {
|
||||
linux: ['x64', 'x86', 'armv7', 'aarch64', 'ppc64le'],
|
||||
macos: X64_ARM64,
|
||||
@@ -31316,31 +31318,31 @@ const JAVA_PLATFORM_CAPABILITIES = {
|
||||
solaris: ['x64']
|
||||
}
|
||||
},
|
||||
[_package_types_js__WEBPACK_IMPORTED_MODULE_3__/* .JavaDistribution */ .zS.LibericaNik]: {
|
||||
[_package_types_js__WEBPACK_IMPORTED_MODULE_2__/* .JavaDistribution */ .zS.LibericaNik]: {
|
||||
platforms: {
|
||||
linux: X64_ARM64,
|
||||
macos: X64_ARM64,
|
||||
windows: X64_ARM64
|
||||
}
|
||||
},
|
||||
[_package_types_js__WEBPACK_IMPORTED_MODULE_3__/* .JavaDistribution */ .zS.JdkFile]: {
|
||||
[_package_types_js__WEBPACK_IMPORTED_MODULE_2__/* .JavaDistribution */ .zS.JdkFile]: {
|
||||
unrestricted: true
|
||||
},
|
||||
[_package_types_js__WEBPACK_IMPORTED_MODULE_3__/* .JavaDistribution */ .zS.Microsoft]: {
|
||||
[_package_types_js__WEBPACK_IMPORTED_MODULE_2__/* .JavaDistribution */ .zS.Microsoft]: {
|
||||
platforms: {
|
||||
linux: X64_ARM64,
|
||||
macos: X64_ARM64,
|
||||
windows: X64_ARM64
|
||||
}
|
||||
},
|
||||
[_package_types_js__WEBPACK_IMPORTED_MODULE_3__/* .JavaDistribution */ .zS.Semeru]: {
|
||||
[_package_types_js__WEBPACK_IMPORTED_MODULE_2__/* .JavaDistribution */ .zS.Semeru]: {
|
||||
platforms: {
|
||||
linux: ['x64', 'x86', 'ppc64le', 'ppc64', 's390x', 'aarch64'],
|
||||
macos: X64_ARM64,
|
||||
windows: ['x64', 'aarch64']
|
||||
}
|
||||
},
|
||||
[_package_types_js__WEBPACK_IMPORTED_MODULE_3__/* .JavaDistribution */ .zS.Corretto]: {
|
||||
[_package_types_js__WEBPACK_IMPORTED_MODULE_2__/* .JavaDistribution */ .zS.Corretto]: {
|
||||
platforms: {
|
||||
linux: [
|
||||
'x64',
|
||||
@@ -31352,62 +31354,62 @@ const JAVA_PLATFORM_CAPABILITIES = {
|
||||
windows: ['x64', { architecture: 'x86', versionRange: '<12' }]
|
||||
}
|
||||
},
|
||||
[_package_types_js__WEBPACK_IMPORTED_MODULE_3__/* .JavaDistribution */ .zS.Oracle]: {
|
||||
[_package_types_js__WEBPACK_IMPORTED_MODULE_2__/* .JavaDistribution */ .zS.Oracle]: {
|
||||
platforms: {
|
||||
linux: X64_ARM64,
|
||||
macos: X64_ARM64,
|
||||
windows: ['x64']
|
||||
}
|
||||
},
|
||||
[_package_types_js__WEBPACK_IMPORTED_MODULE_3__/* .JavaDistribution */ .zS.Dragonwell]: {
|
||||
[_package_types_js__WEBPACK_IMPORTED_MODULE_2__/* .JavaDistribution */ .zS.Dragonwell]: {
|
||||
platforms: {
|
||||
linux: X64_ARM64,
|
||||
windows: ['x64']
|
||||
}
|
||||
},
|
||||
[_package_types_js__WEBPACK_IMPORTED_MODULE_3__/* .JavaDistribution */ .zS.SapMachine]: {
|
||||
[_package_types_js__WEBPACK_IMPORTED_MODULE_2__/* .JavaDistribution */ .zS.SapMachine]: {
|
||||
platforms: {
|
||||
linux: ['x64', 'aarch64', 'ppc64le'],
|
||||
macos: X64_ARM64,
|
||||
windows: X64_ARM64
|
||||
}
|
||||
},
|
||||
[_package_types_js__WEBPACK_IMPORTED_MODULE_3__/* .JavaDistribution */ .zS.GraalVM]: {
|
||||
[_package_types_js__WEBPACK_IMPORTED_MODULE_2__/* .JavaDistribution */ .zS.GraalVM]: {
|
||||
platforms: {
|
||||
linux: X64_ARM64,
|
||||
macos: X64_ARM64,
|
||||
windows: ['x64']
|
||||
}
|
||||
},
|
||||
[_package_types_js__WEBPACK_IMPORTED_MODULE_3__/* .JavaDistribution */ .zS.GraalVMCommunity]: {
|
||||
[_package_types_js__WEBPACK_IMPORTED_MODULE_2__/* .JavaDistribution */ .zS.GraalVMCommunity]: {
|
||||
platforms: {
|
||||
linux: X64_ARM64,
|
||||
macos: X64_ARM64,
|
||||
windows: ['x64']
|
||||
}
|
||||
},
|
||||
[_package_types_js__WEBPACK_IMPORTED_MODULE_3__/* .JavaDistribution */ .zS.JetBrains]: {
|
||||
[_package_types_js__WEBPACK_IMPORTED_MODULE_2__/* .JavaDistribution */ .zS.JetBrains]: {
|
||||
platforms: {
|
||||
linux: X64_ARM64,
|
||||
macos: X64_ARM64,
|
||||
windows: X64_ARM64
|
||||
}
|
||||
},
|
||||
[_package_types_js__WEBPACK_IMPORTED_MODULE_3__/* .JavaDistribution */ .zS.Kona]: {
|
||||
[_package_types_js__WEBPACK_IMPORTED_MODULE_2__/* .JavaDistribution */ .zS.Kona]: {
|
||||
platforms: {
|
||||
linux: X64_ARM64,
|
||||
macos: X64_ARM64,
|
||||
windows: ['x64']
|
||||
}
|
||||
},
|
||||
[_package_types_js__WEBPACK_IMPORTED_MODULE_3__/* .JavaDistribution */ .zS.OracleOpenJdk]: {
|
||||
[_package_types_js__WEBPACK_IMPORTED_MODULE_2__/* .JavaDistribution */ .zS.OracleOpenJdk]: {
|
||||
platforms: {
|
||||
linux: X64_ARM64,
|
||||
macos: X64_ARM64,
|
||||
windows: ['x64']
|
||||
}
|
||||
},
|
||||
[_package_types_js__WEBPACK_IMPORTED_MODULE_3__/* .JavaDistribution */ .zS.RedHat]: {
|
||||
[_package_types_js__WEBPACK_IMPORTED_MODULE_2__/* .JavaDistribution */ .zS.RedHat]: {
|
||||
platforms: {
|
||||
linux: [
|
||||
'x64',
|
||||
@@ -31494,15 +31496,26 @@ function isJavaDistribution(value) {
|
||||
return Object.prototype.hasOwnProperty.call(JAVA_PLATFORM_CAPABILITIES, value);
|
||||
}
|
||||
function isVersionCompatible(version, supportedRange) {
|
||||
const normalizedVersion = version.trim().toLowerCase();
|
||||
let normalizedVersion = version.trim().toLowerCase();
|
||||
if (normalizedVersion === 'latest') {
|
||||
return true;
|
||||
}
|
||||
const requestedRange = semver__WEBPACK_IMPORTED_MODULE_1___default().validRange((0,_util_js__WEBPACK_IMPORTED_MODULE_2__/* .normalizeJavaVersionToSemver */ .zZ)(normalizedVersion.replace(/-ea$/, '').replace('-ea.', '+')));
|
||||
if (/^\d+(\.\d+){3,}$/.test(normalizedVersion)) {
|
||||
normalizedVersion = normalizeExtendedVersionToSemver(normalizedVersion);
|
||||
}
|
||||
const requestedRange = semver__WEBPACK_IMPORTED_MODULE_1___default().validRange(normalizedVersion.replace(/-ea$/, ''));
|
||||
const capabilityRange = semver__WEBPACK_IMPORTED_MODULE_1___default().validRange(supportedRange);
|
||||
if (!requestedRange || !capabilityRange) {
|
||||
return true;
|
||||
}
|
||||
function normalizeExtendedVersionToSemver(version) {
|
||||
const versionParts = version.split('.');
|
||||
const mainVersion = versionParts.slice(0, 3).join('.');
|
||||
if (versionParts.length > 3) {
|
||||
return `${mainVersion}+${versionParts.slice(3).join('.')}`;
|
||||
}
|
||||
return version;
|
||||
}
|
||||
return semver__WEBPACK_IMPORTED_MODULE_1___default().intersects(requestedRange, capabilityRange, {
|
||||
includePrerelease: true
|
||||
});
|
||||
@@ -31966,26 +31979,18 @@ function convertVersionToSemver(version) {
|
||||
return mainVersion;
|
||||
}
|
||||
/**
|
||||
* Normalize numeric Java versions, optionally prefixed with 'jdk-'. Pad
|
||||
* abbreviated build requests ('27+35' -> '27.0.0+35') to preserve exact
|
||||
* matching, and move extra JEP 322 fields into build metadata
|
||||
* ('26.0.2.1+1' -> '26.0.2+1.1'). Leave ranges unchanged.
|
||||
* Java versions (JEP 322) can contain more numeric fields than SemVer allows,
|
||||
* e.g. '11.0.9.1' or Temurin respins such as '26.0.2.1+1'. Move the extra
|
||||
* fields into SemVer build metadata ('11.0.9+1', '26.0.2+1.1'). Any other
|
||||
* input (ranges, regular SemVer versions) is returned unchanged.
|
||||
*/
|
||||
function normalizeJavaVersionToSemver(version) {
|
||||
const match = /^(?:jdk-)?(\d+(?:\.\d+)*)(?:\+([0-9A-Za-z.-]+))?$/.exec(version);
|
||||
const match = /^(\d+(?:\.\d+){3,})(?:\+([0-9A-Za-z.-]+))?$/.exec(version);
|
||||
if (!match) {
|
||||
return version;
|
||||
}
|
||||
const versionParts = match[1].split('.');
|
||||
if (match[2]) {
|
||||
while (versionParts.length < 3) {
|
||||
versionParts.push('0');
|
||||
}
|
||||
}
|
||||
const converted = convertVersionToSemver(versionParts.join('.'));
|
||||
return match[2]
|
||||
? `${converted}${versionParts.length > 3 ? '.' : '+'}${match[2]}`
|
||||
: converted;
|
||||
const converted = convertVersionToSemver(match[1]);
|
||||
return match[2] ? `${converted}.${match[2]}` : converted;
|
||||
}
|
||||
/**
|
||||
* Builds a validator for the bytes currently served by a URL from the response
|
||||
|
||||
+100
-8
@@ -885,6 +885,11 @@ Use `mvn-server-credentials` to add more than one credential entry to the genera
|
||||
|
||||
When this input is set, it replaces the single server configured by `server-id`, `server-username-env-var`, and `server-password-env-var`.
|
||||
|
||||
Use `mvn-server-repository-origins` when a Maven server credential must be allowed for an explicit repository origin. Each line has the format `server-id:repository-origin`; a server can have multiple origins.
|
||||
|
||||
> [!NOTE]
|
||||
> `mvn-server-repository-origins` only works with Maven 3.10 and later. Earlier Maven versions ignore the generated `repositoryOrigins` element and log an `Unrecognised tag: 'repositoryOrigins'` warning. GitHub-hosted runners currently ship Maven 3.9.x, so use the [Maven Wrapper](https://maven.apache.org/tools/wrapper/) or install Maven 3.10+ yourself to use this feature.
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
@@ -896,6 +901,9 @@ steps:
|
||||
mvn-server-credentials: |
|
||||
releases:RELEASES_USERNAME:RELEASES_PASSWORD
|
||||
snapshots:SNAPSHOTS_USERNAME:SNAPSHOTS_PASSWORD
|
||||
mvn-server-repository-origins: |
|
||||
releases:https://central.sonatype.com
|
||||
snapshots:https://central.sonatype.com
|
||||
- name: Publish with Maven
|
||||
run: mvn deploy
|
||||
env:
|
||||
@@ -913,11 +921,17 @@ This configuration produces the following server entries:
|
||||
<id>releases</id>
|
||||
<username>${env.RELEASES_USERNAME}</username>
|
||||
<password>${env.RELEASES_PASSWORD}</password>
|
||||
<repositoryOrigins>
|
||||
<repositoryOrigin>https://central.sonatype.com</repositoryOrigin>
|
||||
</repositoryOrigins>
|
||||
</server>
|
||||
<server>
|
||||
<id>snapshots</id>
|
||||
<username>${env.SNAPSHOTS_USERNAME}</username>
|
||||
<password>${env.SNAPSHOTS_PASSWORD}</password>
|
||||
<repositoryOrigins>
|
||||
<repositoryOrigin>https://central.sonatype.com</repositoryOrigin>
|
||||
</repositoryOrigins>
|
||||
</server>
|
||||
</servers>
|
||||
```
|
||||
@@ -989,14 +1003,92 @@ This configuration adds the following active profile to `settings.xml`:
|
||||
</activeProfiles>
|
||||
```
|
||||
|
||||
Maven Central is included first by default. Set
|
||||
`mvn-repositories-prioritize-central: false` to place custom repositories
|
||||
first, or set `mvn-repositories-include-central: false` to disable Central. The
|
||||
generated profile overrides the Central repository inherited from Maven's Super
|
||||
POM with releases and snapshots disabled. When automatic Central inclusion is
|
||||
off, the ID `central` may instead be declared explicitly in `mvn-repositories`
|
||||
to replace it with a user-specified repository; otherwise that ID is reserved
|
||||
to prevent duplicate entries.
|
||||
Maven Central is included first by default. The Central controls apply to both
|
||||
dependency and plugin repositories. Set
|
||||
`mvn-repositories-prioritize-central: false` to place custom repositories first
|
||||
within each configured list, or set `mvn-repositories-include-central: false` to
|
||||
disable Central for both types. The generated profile overrides the dependency
|
||||
and plugin Central repositories inherited from Maven's Super POM with releases
|
||||
and snapshots disabled, even if only one custom repository list is supplied.
|
||||
These controls have no effect when neither list contains a nonblank entry.
|
||||
|
||||
When automatic Central inclusion is off, the ID `central` may instead be
|
||||
declared explicitly in `mvn-repositories` or `mvn-plugin-repositories` to replace
|
||||
it with a user-specified repository for that type. Declaring it in one list
|
||||
does not enable Central in the other. Otherwise that ID is reserved to prevent
|
||||
duplicate entries. Other repositories declared in your project's POM are not
|
||||
disabled by these controls.
|
||||
|
||||
### Resolving Maven plugins from custom repositories
|
||||
|
||||
Maven resolves build plugins through `<pluginRepositories>`, separately from
|
||||
dependency `<repositories>`. Use `mvn-plugin-repositories` to configure plugin
|
||||
resolution with the same multiline `repository-id:repository-url:snapshots-enabled`
|
||||
format. It can be supplied without `mvn-repositories`; dependency repositories
|
||||
are not automatically used as plugin repositories.
|
||||
|
||||
For example, configure the same private repository for dependencies and plugins
|
||||
and disable inherited Maven Central for both:
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/setup-java@v6
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '21'
|
||||
mvn-server-credentials: |
|
||||
private:PRIVATE_REPOSITORY_USERNAME:PRIVATE_REPOSITORY_TOKEN
|
||||
mvn-repositories: |
|
||||
private:https://maven.example.com/releases:false
|
||||
mvn-plugin-repositories: |
|
||||
private:https://maven.example.com/releases:false
|
||||
mvn-repositories-include-central: false
|
||||
- run: mvn --batch-mode verify
|
||||
env:
|
||||
PRIVATE_REPOSITORY_USERNAME: ${{ secrets.PRIVATE_REPOSITORY_USERNAME }}
|
||||
PRIVATE_REPOSITORY_TOKEN: ${{ secrets.PRIVATE_REPOSITORY_TOKEN }}
|
||||
```
|
||||
|
||||
The matching ID `private` selects the same server credentials for both types.
|
||||
IDs must be unique within each list, but can be shared across the two lists.
|
||||
Public repositories do not require a matching credential entry.
|
||||
|
||||
Alongside dependency repositories, the active `setup-java-repositories` profile
|
||||
contains:
|
||||
|
||||
```xml
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>private</id>
|
||||
<url>https://maven.example.com/releases</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</pluginRepository>
|
||||
<pluginRepository>
|
||||
<id>central</id>
|
||||
<url>https://repo.maven.apache.org/maven2</url>
|
||||
<releases>
|
||||
<enabled>false</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
```
|
||||
|
||||
Omitting a Central override would leave the Super POM's plugin repository
|
||||
enabled. In particular, `mvn-repositories-include-central: false` now disables
|
||||
inherited plugin Central even for existing workflows that only configure
|
||||
`mvn-repositories`. To download plugins in such workflows, configure a plugin
|
||||
repository or explicitly declare `central` in `mvn-plugin-repositories`.
|
||||
|
||||
With Central included, it is placed before custom plugin repositories by
|
||||
default; `mvn-repositories-prioritize-central: false` places it after them.
|
||||
All repository generation respects `settings-path` and `overwrite-settings`;
|
||||
an existing settings file is left untouched when `overwrite-settings: false`.
|
||||
|
||||
### GPG
|
||||
|
||||
|
||||
Generated
+4
-4
@@ -4320,13 +4320,13 @@
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/handlebars": {
|
||||
"version": "4.7.9",
|
||||
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.9.tgz",
|
||||
"integrity": "sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ==",
|
||||
"version": "4.7.10",
|
||||
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.10.tgz",
|
||||
"integrity": "sha512-P5VJMVM7qgBn6vjXMw8WG9uVI+ncf2pi72j4de4yz5ZULLj2RGqLYaKOYGsgyrViQ0tePOVlN1tDCCXXtFqXKg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"minimist": "^1.2.5",
|
||||
"minimist": "^1.2.8",
|
||||
"neo-async": "^2.6.2",
|
||||
"source-map": "^0.6.1",
|
||||
"wordwrap": "^1.0.0"
|
||||
|
||||
+194
-67
@@ -13,6 +13,7 @@ export interface MavenServerCredentials {
|
||||
id: string;
|
||||
usernameEnvVar: string;
|
||||
passwordEnvVar: string;
|
||||
repositoryOrigins?: string[];
|
||||
}
|
||||
|
||||
export interface MavenRepository {
|
||||
@@ -24,10 +25,13 @@ export interface MavenRepository {
|
||||
|
||||
export interface MavenRepositorySettings {
|
||||
repositories: MavenRepository[];
|
||||
pluginRepositories?: MavenRepository[];
|
||||
includeCentral: boolean;
|
||||
prioritizeCentral: boolean;
|
||||
}
|
||||
|
||||
const MAVEN_REPOSITORY_ORIGIN = /^[A-Za-z][A-Za-z0-9+.-]*:\/\/[^/?#@]+\/?$/;
|
||||
|
||||
export async function configureAuthentication() {
|
||||
const servers = getMavenServerSettings();
|
||||
const repositorySettings = getMavenRepositorySettings();
|
||||
@@ -95,25 +99,28 @@ export function getMavenServerSettings(): MavenServerCredentials[] {
|
||||
constants.INPUT_MVN_SERVER_CREDENTIALS
|
||||
);
|
||||
|
||||
if (entries.some(entry => entry.trim())) {
|
||||
return parseMavenServerCredentials(entries);
|
||||
}
|
||||
const servers = entries.some(entry => entry.trim())
|
||||
? parseMavenServerCredentials(entries)
|
||||
: [
|
||||
{
|
||||
id: core.getInput(constants.INPUT_SERVER_ID),
|
||||
usernameEnvVar: getInputWithDeprecatedAlias(
|
||||
constants.INPUT_SERVER_USERNAME_ENV_VAR,
|
||||
constants.INPUT_SERVER_USERNAME_DEPRECATED,
|
||||
constants.INPUT_DEFAULT_SERVER_USERNAME
|
||||
),
|
||||
passwordEnvVar: getInputWithDeprecatedAlias(
|
||||
constants.INPUT_SERVER_PASSWORD_ENV_VAR,
|
||||
constants.INPUT_SERVER_PASSWORD_DEPRECATED,
|
||||
constants.INPUT_DEFAULT_SERVER_PASSWORD
|
||||
)
|
||||
}
|
||||
];
|
||||
|
||||
return [
|
||||
{
|
||||
id: core.getInput(constants.INPUT_SERVER_ID),
|
||||
usernameEnvVar: getInputWithDeprecatedAlias(
|
||||
constants.INPUT_SERVER_USERNAME_ENV_VAR,
|
||||
constants.INPUT_SERVER_USERNAME_DEPRECATED,
|
||||
constants.INPUT_DEFAULT_SERVER_USERNAME
|
||||
),
|
||||
passwordEnvVar: getInputWithDeprecatedAlias(
|
||||
constants.INPUT_SERVER_PASSWORD_ENV_VAR,
|
||||
constants.INPUT_SERVER_PASSWORD_DEPRECATED,
|
||||
constants.INPUT_DEFAULT_SERVER_PASSWORD
|
||||
)
|
||||
}
|
||||
];
|
||||
return addMavenServerRepositoryOrigins(
|
||||
servers,
|
||||
core.getMultilineInput(constants.INPUT_MVN_SERVER_REPOSITORY_ORIGINS)
|
||||
);
|
||||
}
|
||||
|
||||
// only exported for testing purposes
|
||||
@@ -156,11 +163,96 @@ export function parseMavenServerCredentials(
|
||||
return servers;
|
||||
}
|
||||
|
||||
// only exported for testing purposes
|
||||
export function addMavenServerRepositoryOrigins(
|
||||
servers: MavenServerCredentials[],
|
||||
entries: string[]
|
||||
): MavenServerCredentials[] {
|
||||
const serverIds = new Set(servers.map(server => server.id));
|
||||
const originsByServer = new Map<string, string[]>();
|
||||
|
||||
entries.forEach((entry, index) => {
|
||||
if (!entry.trim()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const separator = entry.indexOf(':');
|
||||
if (separator <= 0 || separator === entry.length - 1) {
|
||||
throw new Error(
|
||||
`Invalid mvn-server-repository-origins entry at line ${index + 1}. Expected format: server-id:repository-origin`
|
||||
);
|
||||
}
|
||||
|
||||
const id = entry.slice(0, separator).trim();
|
||||
const value = entry.slice(separator + 1).trim();
|
||||
if (!id || !value) {
|
||||
throw new Error(
|
||||
`Invalid mvn-server-repository-origins entry at line ${index + 1}. Server ID and repository origin are required`
|
||||
);
|
||||
}
|
||||
if (!serverIds.has(id)) {
|
||||
throw new Error(
|
||||
`Unknown server-id '${id}' in mvn-server-repository-origins at line ${index + 1}`
|
||||
);
|
||||
}
|
||||
|
||||
let url: URL;
|
||||
try {
|
||||
if (!MAVEN_REPOSITORY_ORIGIN.test(value)) {
|
||||
throw new Error();
|
||||
}
|
||||
url = new URL(value);
|
||||
} catch {
|
||||
throw new Error(
|
||||
`Invalid repository origin '${value}' in mvn-server-repository-origins at line ${index + 1}`
|
||||
);
|
||||
}
|
||||
if (
|
||||
!url.host ||
|
||||
url.username ||
|
||||
url.password ||
|
||||
(url.pathname !== '' && url.pathname !== '/') ||
|
||||
url.search ||
|
||||
url.hash
|
||||
) {
|
||||
throw new Error(
|
||||
`Invalid repository origin '${value}' in mvn-server-repository-origins at line ${index + 1}`
|
||||
);
|
||||
}
|
||||
|
||||
const explicitPort = /:(\d+)\/?$/.exec(value)?.[1];
|
||||
const port = explicitPort ? Number.parseInt(explicitPort, 10) : undefined;
|
||||
const includePort =
|
||||
port !== undefined &&
|
||||
!(
|
||||
(url.protocol === 'http:' && port === 80) ||
|
||||
(url.protocol === 'https:' && port === 443)
|
||||
);
|
||||
const origin = `${url.protocol}//${url.hostname}${includePort ? `:${port}` : ''}`;
|
||||
const origins = originsByServer.get(id) || [];
|
||||
if (!origins.includes(origin)) {
|
||||
origins.push(origin);
|
||||
originsByServer.set(id, origins);
|
||||
}
|
||||
});
|
||||
|
||||
return servers.map(server => {
|
||||
const repositoryOrigins = originsByServer.get(server.id);
|
||||
return repositoryOrigins ? {...server, repositoryOrigins} : server;
|
||||
});
|
||||
}
|
||||
|
||||
// only exported for testing purposes
|
||||
export function getMavenRepositorySettings():
|
||||
MavenRepositorySettings | undefined {
|
||||
const entries = core.getMultilineInput(constants.INPUT_MVN_REPOSITORIES);
|
||||
if (!entries.some(entry => entry.trim())) {
|
||||
const pluginEntries = core.getMultilineInput(
|
||||
constants.INPUT_MVN_PLUGIN_REPOSITORIES
|
||||
);
|
||||
if (
|
||||
!entries.some(entry => entry.trim()) &&
|
||||
!pluginEntries.some(entry => entry.trim())
|
||||
) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -170,6 +262,11 @@ export function getMavenRepositorySettings():
|
||||
);
|
||||
return {
|
||||
repositories: parseMavenRepositories(entries, includeCentral),
|
||||
pluginRepositories: parseMavenRepositories(
|
||||
pluginEntries,
|
||||
includeCentral,
|
||||
constants.INPUT_MVN_PLUGIN_REPOSITORIES
|
||||
),
|
||||
includeCentral,
|
||||
prioritizeCentral: getBooleanInput(
|
||||
constants.INPUT_MVN_REPOSITORIES_PRIORITIZE_CENTRAL,
|
||||
@@ -181,7 +278,8 @@ export function getMavenRepositorySettings():
|
||||
// only exported for testing purposes
|
||||
export function parseMavenRepositories(
|
||||
entries: string[],
|
||||
includeCentral: boolean
|
||||
includeCentral: boolean,
|
||||
inputName = constants.INPUT_MVN_REPOSITORIES
|
||||
): MavenRepository[] {
|
||||
const repositories: MavenRepository[] = [];
|
||||
const repositoryIds = new Set<string>();
|
||||
@@ -195,7 +293,7 @@ export function parseMavenRepositories(
|
||||
const lastSeparator = entry.lastIndexOf(':');
|
||||
if (firstSeparator <= 0 || lastSeparator <= firstSeparator) {
|
||||
throw new Error(
|
||||
`Invalid mvn-repositories entry at line ${index + 1}. Expected format: repository-id:repository-url:snapshots-enabled`
|
||||
`Invalid ${inputName} entry at line ${index + 1}. Expected format: repository-id:repository-url:snapshots-enabled`
|
||||
);
|
||||
}
|
||||
|
||||
@@ -207,18 +305,16 @@ export function parseMavenRepositories(
|
||||
.toLowerCase();
|
||||
if (!id || !url || !snapshotsValue) {
|
||||
throw new Error(
|
||||
`Invalid mvn-repositories entry at line ${index + 1}. repository-id, repository URL, and snapshots-enabled are required`
|
||||
`Invalid ${inputName} entry at line ${index + 1}. repository-id, repository URL, and snapshots-enabled are required`
|
||||
);
|
||||
}
|
||||
if (snapshotsValue !== 'true' && snapshotsValue !== 'false') {
|
||||
throw new Error(
|
||||
`Invalid snapshots-enabled value '${snapshotsValue}' in mvn-repositories entry at line ${index + 1}. Expected true or false`
|
||||
`Invalid snapshots-enabled value '${snapshotsValue}' in ${inputName} entry at line ${index + 1}. Expected true or false`
|
||||
);
|
||||
}
|
||||
if (repositoryIds.has(id)) {
|
||||
throw new Error(
|
||||
`Duplicate repository-id '${id}' in mvn-repositories input`
|
||||
);
|
||||
throw new Error(`Duplicate repository-id '${id}' in ${inputName} input`);
|
||||
}
|
||||
if (includeCentral && id === constants.MAVEN_CENTRAL_REPOSITORY_ID) {
|
||||
throw new Error(
|
||||
@@ -237,6 +333,56 @@ export function parseMavenRepositories(
|
||||
return repositories;
|
||||
}
|
||||
|
||||
function generateRepositorySection(
|
||||
customRepositories: MavenRepository[],
|
||||
settings: MavenRepositorySettings,
|
||||
element: 'repository' | 'pluginRepository'
|
||||
): string[] {
|
||||
if (!customRepositories.length && settings.includeCentral) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const centralRepository: MavenRepository = {
|
||||
id: constants.MAVEN_CENTRAL_REPOSITORY_ID,
|
||||
url: constants.MAVEN_CENTRAL_REPOSITORY_URL,
|
||||
snapshotsEnabled: false
|
||||
};
|
||||
const customCentralConfigured = customRepositories.some(
|
||||
repository => repository.id === constants.MAVEN_CENTRAL_REPOSITORY_ID
|
||||
);
|
||||
const repositories = settings.includeCentral
|
||||
? settings.prioritizeCentral
|
||||
? [centralRepository, ...customRepositories]
|
||||
: [...customRepositories, centralRepository]
|
||||
: customCentralConfigured
|
||||
? customRepositories
|
||||
: [...customRepositories, {...centralRepository, releasesEnabled: false}];
|
||||
const container =
|
||||
element === 'repository' ? 'repositories' : 'pluginRepositories';
|
||||
const lines = [` <${container}>`];
|
||||
|
||||
for (const repository of repositories) {
|
||||
lines.push(
|
||||
` <${element}>`,
|
||||
` <id>${escapeXmlText(repository.id)}</id>`,
|
||||
` <url>${escapeXmlText(repository.url)}</url>`,
|
||||
...(repository.releasesEnabled === undefined
|
||||
? []
|
||||
: [
|
||||
' <releases>',
|
||||
` <enabled>${repository.releasesEnabled}</enabled>`,
|
||||
' </releases>'
|
||||
]),
|
||||
' <snapshots>',
|
||||
` <enabled>${repository.snapshotsEnabled}</enabled>`,
|
||||
' </snapshots>',
|
||||
` </${element}>`
|
||||
);
|
||||
}
|
||||
lines.push(` </${container}>`);
|
||||
return lines;
|
||||
}
|
||||
|
||||
export async function createAuthenticationSettings(
|
||||
servers: MavenServerCredentials[],
|
||||
settingsDirectory: string,
|
||||
@@ -286,58 +432,39 @@ export function generate(
|
||||
' <server>',
|
||||
` <id>${escapeXmlText(server.id)}</id>`,
|
||||
` <username>${escapeXmlText(`\${env.${server.usernameEnvVar}}`)}</username>`,
|
||||
` <password>${escapeXmlText(`\${env.${server.passwordEnvVar}}`)}</password>`,
|
||||
' </server>'
|
||||
` <password>${escapeXmlText(`\${env.${server.passwordEnvVar}}`)}</password>`
|
||||
);
|
||||
if (server.repositoryOrigins) {
|
||||
lines.push(' <repositoryOrigins>');
|
||||
for (const origin of server.repositoryOrigins) {
|
||||
lines.push(
|
||||
` <repositoryOrigin>${escapeXmlText(origin)}</repositoryOrigin>`
|
||||
);
|
||||
}
|
||||
lines.push(' </repositoryOrigins>');
|
||||
}
|
||||
lines.push(' </server>');
|
||||
}
|
||||
lines.push(' </servers>');
|
||||
|
||||
if (repositorySettings || includeGpgPassphraseProfile) {
|
||||
lines.push(' <profiles>');
|
||||
if (repositorySettings) {
|
||||
const centralRepository: MavenRepository = {
|
||||
id: constants.MAVEN_CENTRAL_REPOSITORY_ID,
|
||||
url: constants.MAVEN_CENTRAL_REPOSITORY_URL,
|
||||
snapshotsEnabled: false
|
||||
};
|
||||
const customCentralConfigured = repositorySettings.repositories.some(
|
||||
repository => repository.id === constants.MAVEN_CENTRAL_REPOSITORY_ID
|
||||
);
|
||||
const repositories = repositorySettings.includeCentral
|
||||
? repositorySettings.prioritizeCentral
|
||||
? [centralRepository, ...repositorySettings.repositories]
|
||||
: [...repositorySettings.repositories, centralRepository]
|
||||
: customCentralConfigured
|
||||
? repositorySettings.repositories
|
||||
: [
|
||||
...repositorySettings.repositories,
|
||||
{...centralRepository, releasesEnabled: false}
|
||||
];
|
||||
|
||||
lines.push(
|
||||
' <profile>',
|
||||
` <id>${constants.MAVEN_REPOSITORIES_PROFILE_ID}</id>`,
|
||||
' <repositories>'
|
||||
...generateRepositorySection(
|
||||
repositorySettings.repositories,
|
||||
repositorySettings,
|
||||
'repository'
|
||||
),
|
||||
...generateRepositorySection(
|
||||
repositorySettings.pluginRepositories ?? [],
|
||||
repositorySettings,
|
||||
'pluginRepository'
|
||||
),
|
||||
' </profile>'
|
||||
);
|
||||
for (const repository of repositories) {
|
||||
lines.push(
|
||||
' <repository>',
|
||||
` <id>${escapeXmlText(repository.id)}</id>`,
|
||||
` <url>${escapeXmlText(repository.url)}</url>`,
|
||||
...(repository.releasesEnabled === undefined
|
||||
? []
|
||||
: [
|
||||
' <releases>',
|
||||
` <enabled>${repository.releasesEnabled}</enabled>`,
|
||||
' </releases>'
|
||||
]),
|
||||
' <snapshots>',
|
||||
` <enabled>${repository.snapshotsEnabled}</enabled>`,
|
||||
' </snapshots>',
|
||||
' </repository>'
|
||||
);
|
||||
}
|
||||
lines.push(' </repositories>', ' </profile>');
|
||||
}
|
||||
if (includeGpgPassphraseProfile) {
|
||||
lines.push(
|
||||
|
||||
@@ -16,7 +16,10 @@ export const SIGNATURE_VERIFICATION_DOCUMENTATION_URL =
|
||||
'https://github.com/actions/setup-java#download-integrity-and-signatures';
|
||||
export const SIGNATURE_VERIFICATION_FAILURE_HELP = `If this is a legitimate vendor signing-key rotation, see ${SIGNATURE_VERIFICATION_DOCUMENTATION_URL} for instructions to configure the updated public key or temporarily disable signature verification.`;
|
||||
export const INPUT_MVN_SERVER_CREDENTIALS = 'mvn-server-credentials';
|
||||
export const INPUT_MVN_SERVER_REPOSITORY_ORIGINS =
|
||||
'mvn-server-repository-origins';
|
||||
export const INPUT_MVN_REPOSITORIES = 'mvn-repositories';
|
||||
export const INPUT_MVN_PLUGIN_REPOSITORIES = 'mvn-plugin-repositories';
|
||||
export const INPUT_MVN_REPOSITORIES_INCLUDE_CENTRAL =
|
||||
'mvn-repositories-include-central';
|
||||
export const INPUT_MVN_REPOSITORIES_PRIORITIZE_CENTRAL =
|
||||
|
||||
@@ -673,8 +673,10 @@ export abstract class JavaBase {
|
||||
stable = false;
|
||||
}
|
||||
|
||||
// Normalize Java release tags and JEP 322 versions without losing exact
|
||||
// build constraints ('jdk-27+35' -> '27.0.0+35'). Leave ranges unchanged.
|
||||
// Java uses a versioning scheme (JEP 322) that can contain more numeric
|
||||
// fields than SemVer allows, e.g. '18.0.1.1' or '11.0.9.1'. Convert such
|
||||
// exact versions to SemVer build notation ('18.0.1+1', or '26.0.2+1.1'
|
||||
// for '26.0.2.1+1') so they are accepted. Ranges are left untouched.
|
||||
version = normalizeJavaVersionToSemver(version);
|
||||
|
||||
if (!semver.validRange(version)) {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import fs from 'fs';
|
||||
import semver from 'semver';
|
||||
import {normalizeJavaVersionToSemver} from '../util.js';
|
||||
import {JavaDistribution} from './package-types.js';
|
||||
|
||||
export type JavaPlatform = 'linux' | 'macos' | 'windows' | 'solaris';
|
||||
@@ -290,20 +289,31 @@ function isJavaDistribution(value: string): value is JavaDistribution {
|
||||
}
|
||||
|
||||
function isVersionCompatible(version: string, supportedRange: string): boolean {
|
||||
const normalizedVersion = version.trim().toLowerCase();
|
||||
let normalizedVersion = version.trim().toLowerCase();
|
||||
if (normalizedVersion === 'latest') {
|
||||
return true;
|
||||
}
|
||||
if (/^\d+(\.\d+){3,}$/.test(normalizedVersion)) {
|
||||
normalizedVersion = normalizeExtendedVersionToSemver(normalizedVersion);
|
||||
}
|
||||
|
||||
const requestedRange = semver.validRange(
|
||||
normalizeJavaVersionToSemver(
|
||||
normalizedVersion.replace(/-ea$/, '').replace('-ea.', '+')
|
||||
)
|
||||
normalizedVersion.replace(/-ea$/, '')
|
||||
);
|
||||
const capabilityRange = semver.validRange(supportedRange);
|
||||
if (!requestedRange || !capabilityRange) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function normalizeExtendedVersionToSemver(version: string): string {
|
||||
const versionParts = version.split('.');
|
||||
const mainVersion = versionParts.slice(0, 3).join('.');
|
||||
if (versionParts.length > 3) {
|
||||
return `${mainVersion}+${versionParts.slice(3).join('.')}`;
|
||||
}
|
||||
return version;
|
||||
}
|
||||
|
||||
return semver.intersects(requestedRange, capabilityRange, {
|
||||
includePrerelease: true
|
||||
});
|
||||
|
||||
+7
-17
@@ -511,28 +511,18 @@ export function convertVersionToSemver(version: number[] | string) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize numeric Java versions, optionally prefixed with 'jdk-'. Pad
|
||||
* abbreviated build requests ('27+35' -> '27.0.0+35') to preserve exact
|
||||
* matching, and move extra JEP 322 fields into build metadata
|
||||
* ('26.0.2.1+1' -> '26.0.2+1.1'). Leave ranges unchanged.
|
||||
* Java versions (JEP 322) can contain more numeric fields than SemVer allows,
|
||||
* e.g. '11.0.9.1' or Temurin respins such as '26.0.2.1+1'. Move the extra
|
||||
* fields into SemVer build metadata ('11.0.9+1', '26.0.2+1.1'). Any other
|
||||
* input (ranges, regular SemVer versions) is returned unchanged.
|
||||
*/
|
||||
export function normalizeJavaVersionToSemver(version: string): string {
|
||||
const match = /^(?:jdk-)?(\d+(?:\.\d+)*)(?:\+([0-9A-Za-z.-]+))?$/.exec(
|
||||
version
|
||||
);
|
||||
const match = /^(\d+(?:\.\d+){3,})(?:\+([0-9A-Za-z.-]+))?$/.exec(version);
|
||||
if (!match) {
|
||||
return version;
|
||||
}
|
||||
const versionParts = match[1].split('.');
|
||||
if (match[2]) {
|
||||
while (versionParts.length < 3) {
|
||||
versionParts.push('0');
|
||||
}
|
||||
}
|
||||
const converted = convertVersionToSemver(versionParts.join('.'));
|
||||
return match[2]
|
||||
? `${converted}${versionParts.length > 3 ? '.' : '+'}${match[2]}`
|
||||
: converted;
|
||||
const converted = convertVersionToSemver(match[1]);
|
||||
return match[2] ? `${converted}.${match[2]}` : converted;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user