mirror of
https://github.com/actions/setup-java.git
synced 2026-10-16 19:33:09 +01:00
Support Maven mirrors in generated settings.xml
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 59df028a-0d1b-49cb-8126-ab26408663e4
This commit is contained in:
88
.github/workflows/e2e-publishing.yml
vendored
88
.github/workflows/e2e-publishing.yml
vendored
@@ -175,6 +175,94 @@ jobs:
|
|||||||
throw "settings.xml file is not found in expected location"
|
throw "settings.xml file is not found in expected location"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test-maven-mirrors:
|
||||||
|
name: Maven mirrors (${{ matrix.mirror-of }})
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
os: [macos-latest, windows-latest, ubuntu-latest]
|
||||||
|
mirror-of: ['*', 'external:*']
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v7
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
- name: Configure Maven mirrors without repository inputs
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
distribution: 'temurin'
|
||||||
|
java-version: '21'
|
||||||
|
settings-path: ${{ runner.temp }}/maven-mirror-test
|
||||||
|
mvn-server-credentials: |
|
||||||
|
private:PRIVATE_USERNAME:PRIVATE_TOKEN
|
||||||
|
mvn-mirrors: |
|
||||||
|
private:https://mirror.example.invalid/maven:${{ matrix.mirror-of }}
|
||||||
|
- name: Validate generated settings and Maven mirror selection
|
||||||
|
env:
|
||||||
|
MIRROR_OF: ${{ matrix.mirror-of }}
|
||||||
|
PRIVATE_USERNAME: mirror-test-user
|
||||||
|
PRIVATE_TOKEN: mirror-test-token
|
||||||
|
run: |
|
||||||
|
$directory = Join-Path $env:RUNNER_TEMP "maven-mirror-test"
|
||||||
|
$settingsPath = Join-Path $directory "settings.xml"
|
||||||
|
[xml]$settings = Get-Content -Path $settingsPath -Raw
|
||||||
|
$mirrors = @($settings.settings.mirrors.mirror)
|
||||||
|
if ($mirrors.Count -ne 1 -or $mirrors[0].id -ne "private" -or $mirrors[0].url -ne "https://mirror.example.invalid/maven" -or $mirrors[0].mirrorOf -ne $env:MIRROR_OF) {
|
||||||
|
throw "Incorrect generated mirror"
|
||||||
|
}
|
||||||
|
if ($settings.settings.profiles -or $settings.settings.activeProfiles) {
|
||||||
|
throw "Mirror-only settings must not add repository profiles"
|
||||||
|
}
|
||||||
|
$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 "Mirror credentials were not preserved"
|
||||||
|
}
|
||||||
|
|
||||||
|
$pomPath = Join-Path $directory "pom.xml"
|
||||||
|
@'
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<groupId>setup-java.test</groupId>
|
||||||
|
<artifactId>mirror-settings</artifactId>
|
||||||
|
<version>1.0</version>
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>pom-dependencies</id>
|
||||||
|
<url>https://dependencies.example.invalid/maven</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
<pluginRepositories>
|
||||||
|
<pluginRepository>
|
||||||
|
<id>pom-plugins</id>
|
||||||
|
<url>https://plugins.example.invalid/maven</url>
|
||||||
|
</pluginRepository>
|
||||||
|
</pluginRepositories>
|
||||||
|
</project>
|
||||||
|
'@ | Set-Content -Path $pomPath
|
||||||
|
|
||||||
|
# validate requires no plugins or dependencies, so mirror selection can
|
||||||
|
# be inspected offline without contacting the deliberately invalid URLs.
|
||||||
|
$output = & mvn --batch-mode --no-transfer-progress --offline --debug `
|
||||||
|
--settings $settingsPath --file $pomPath `
|
||||||
|
"-Dmaven.repo.local=$directory/repository" validate 2>&1
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
throw "Could not inspect Maven mirror selection: $output"
|
||||||
|
}
|
||||||
|
$log = $output -join "`n"
|
||||||
|
foreach ($id in @("central", "pom-dependencies")) {
|
||||||
|
$expected = "Using mirror private (https://mirror.example.invalid/maven) for $id ("
|
||||||
|
if (-not $log.Contains($expected)) {
|
||||||
|
throw "Maven did not select the mirror for ${id}: $log"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach ($type in @("dependencies", "plugins")) {
|
||||||
|
$pattern = 'Repositories \(' + $type + '\)\s*: \[private \(https://mirror\.example\.invalid/maven, [^\]]+\)\]'
|
||||||
|
if ($log -notmatch $pattern) {
|
||||||
|
throw "Maven did not redirect all $type repositories: $log"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
test-maven-repositories:
|
test-maven-repositories:
|
||||||
name: Maven ${{ matrix.repositories }} repositories
|
name: Maven ${{ matrix.repositories }} repositories
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
|||||||
@@ -171,6 +171,7 @@ steps:
|
|||||||
| `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-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` | Multiline Maven dependency repositories in the format `repository-id:repository-url:snapshots-enabled`. | |
|
||||||
| `mvn-plugin-repositories` | Multiline Maven plugin repositories in the format `repository-id:repository-url:snapshots-enabled`. Can be used independently of `mvn-repositories`. | |
|
| `mvn-plugin-repositories` | Multiline Maven plugin repositories in the format `repository-id:repository-url:snapshots-enabled`. Can be used independently of `mvn-repositories`. | |
|
||||||
|
| `mvn-mirrors` | Multiline Maven mirrors in the format `mirror-id:mirror-url:mirror-of`. Redirect matching dependency and plugin repositories; use a matching server ID for authentication. | |
|
||||||
| `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-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` |
|
| `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` |
|
| `settings-path` | Directory where `settings.xml` is written. | `~/.m2` |
|
||||||
@@ -490,6 +491,11 @@ 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)
|
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).
|
and [Resolving Maven plugins from custom repositories](docs/advanced-usage.md#resolving-maven-plugins-from-custom-repositories).
|
||||||
|
|
||||||
|
To redirect repositories, including Central and repositories declared in project
|
||||||
|
or parent POMs, use [`mvn-mirrors`](docs/advanced-usage.md#redirecting-maven-repositories-with-mirrors).
|
||||||
|
It works independently of the repository inputs; a `mirrorOf` pattern of `*`
|
||||||
|
routes all dependency and plugin repositories through the configured mirror.
|
||||||
|
|
||||||
> [!WARNING]
|
> [!WARNING]
|
||||||
> `mvn-repositories-include-central: false` now disables inherited Maven Central
|
> `mvn-repositories-include-central: false` now disables inherited Maven Central
|
||||||
> for **both dependencies and plugins**, even in existing workflows that only
|
> for **both dependencies and plugins**, even in existing workflows that only
|
||||||
|
|||||||
@@ -882,6 +882,162 @@ describe('auth tests', () => {
|
|||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it.each([
|
||||||
|
'*',
|
||||||
|
'central',
|
||||||
|
'external:*',
|
||||||
|
'external:http:*',
|
||||||
|
'*,!internal',
|
||||||
|
'external:*,!internal',
|
||||||
|
'!internal,external:http:*',
|
||||||
|
'external:*,!external:http:*'
|
||||||
|
])('preserves the mirror selector %s and URL colons', mirrorOf => {
|
||||||
|
expect(
|
||||||
|
auth.parseMavenMirrors([
|
||||||
|
'',
|
||||||
|
' \t ',
|
||||||
|
` private : https://[2001:db8::1]:8443/maven : ${mirrorOf} `,
|
||||||
|
'public:https://repo.example.com:443/releases:central'
|
||||||
|
])
|
||||||
|
).toEqual([
|
||||||
|
{
|
||||||
|
id: 'private',
|
||||||
|
url: 'https://[2001:db8::1]:8443/maven',
|
||||||
|
mirrorOf
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'public',
|
||||||
|
url: 'https://repo.example.com:443/releases',
|
||||||
|
mirrorOf: 'central'
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it.each([
|
||||||
|
'private',
|
||||||
|
'private:https://repo.example.com',
|
||||||
|
':https://repo.example.com:*',
|
||||||
|
'private::*',
|
||||||
|
'private:https://repo.example.com:',
|
||||||
|
'private: :*',
|
||||||
|
'private:https://repo.example.com: '
|
||||||
|
])('rejects malformed mirror entry %s with a line number', entry => {
|
||||||
|
expect(() => auth.parseMavenMirrors(['', entry])).toThrow(
|
||||||
|
'Invalid mvn-mirrors entry at line 2.'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('rejects duplicate mirror IDs after trimming', () => {
|
||||||
|
expect(() =>
|
||||||
|
auth.parseMavenMirrors([
|
||||||
|
'private:https://first.example.com:*',
|
||||||
|
' private :https://second.example.com:central'
|
||||||
|
])
|
||||||
|
).toThrow("Duplicate mirror-id 'private' in mvn-mirrors input at line 2");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('leaves settings unchanged for absent or blank mirrors', () => {
|
||||||
|
const servers = credentials('github', 'USERNAME', 'PASSWORD');
|
||||||
|
expect(auth.parseMavenMirrors(['', ' ', '\t'])).toEqual([]);
|
||||||
|
expect(auth.generate(servers, undefined, undefined, [])).toBe(
|
||||||
|
auth.generate(servers)
|
||||||
|
);
|
||||||
|
expect(auth.generate(servers)).not.toContain('<mirrors>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('generates public mirrors without credentials or repository profiles', () => {
|
||||||
|
const mirrors = auth.parseMavenMirrors([
|
||||||
|
'public:https://repo.example.com:external:*',
|
||||||
|
'fallback:https://other.example.com:central'
|
||||||
|
]);
|
||||||
|
const xml = auth.generate([], undefined, undefined, mirrors);
|
||||||
|
expect(parseXmlObject(xml)).toMatchObject({
|
||||||
|
settings: {mirrors: {mirror: mirrors}}
|
||||||
|
});
|
||||||
|
expect(xml).not.toContain('<profiles>');
|
||||||
|
expect(xml).not.toContain('<activeProfiles>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('escapes all mirror fields as XML text', () => {
|
||||||
|
const mirror = {
|
||||||
|
id: 'private<&>',
|
||||||
|
url: 'https://repo.example.com/maven?a=1&b=<value>',
|
||||||
|
mirrorOf: '*,!internal<&>'
|
||||||
|
};
|
||||||
|
const xml = auth.generate([], undefined, undefined, [mirror]);
|
||||||
|
expect(xml).toContain('<id>private<&></id>');
|
||||||
|
expect(xml).toContain('a=1&b=<value>');
|
||||||
|
expect(xml).toContain('<mirrorOf>*,!internal<&></mirrorOf>');
|
||||||
|
expect(parseXmlObject(xml)).toMatchObject({
|
||||||
|
settings: {mirrors: {mirror}}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it.each([
|
||||||
|
{combined: false, overwrite: true},
|
||||||
|
{combined: true, overwrite: true},
|
||||||
|
{combined: true, overwrite: false}
|
||||||
|
])(
|
||||||
|
'configures mirrors with combined=$combined and overwrite=$overwrite',
|
||||||
|
async ({combined, overwrite}) => {
|
||||||
|
const directory = path.join(m2Dir, 'mirrors');
|
||||||
|
const location = path.join(directory, MVN_SETTINGS_FILE);
|
||||||
|
fs.mkdirSync(directory, {recursive: true});
|
||||||
|
fs.writeFileSync(location, 'EXISTING SETTINGS');
|
||||||
|
const url = 'https://maven.example.com/releases';
|
||||||
|
const inputs: Record<string, string> = {
|
||||||
|
'settings-path': directory,
|
||||||
|
'overwrite-settings': String(overwrite),
|
||||||
|
'mvn-repositories-include-central': 'false',
|
||||||
|
...(combined ? {'gpg-passphrase-env-var': 'GPG_PASSPHRASE'} : {})
|
||||||
|
};
|
||||||
|
const multilineInputs: Record<string, string[]> = {
|
||||||
|
'mvn-server-credentials': ['private:PRIVATE_USERNAME:PRIVATE_TOKEN'],
|
||||||
|
'mvn-mirrors': [`private:${url}:*`],
|
||||||
|
...(combined
|
||||||
|
? {
|
||||||
|
'mvn-repositories': [`private:${url}:false`],
|
||||||
|
'mvn-plugin-repositories': [`private:${url}:false`]
|
||||||
|
}
|
||||||
|
: {})
|
||||||
|
};
|
||||||
|
jest.mocked(core.getInput).mockImplementation(name => inputs[name] ?? '');
|
||||||
|
jest
|
||||||
|
.mocked(core.getMultilineInput)
|
||||||
|
.mockImplementation(name => multilineInputs[name] ?? []);
|
||||||
|
|
||||||
|
await auth.configureAuthentication();
|
||||||
|
|
||||||
|
const xml = fs.readFileSync(location, 'utf8');
|
||||||
|
if (!overwrite) {
|
||||||
|
expect(xml).toBe('EXISTING SETTINGS');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
expect(parseXmlObject(xml)).toMatchObject({
|
||||||
|
settings: {
|
||||||
|
mirrors: {mirror: {id: 'private', url, mirrorOf: '*'}},
|
||||||
|
servers: {
|
||||||
|
server: {
|
||||||
|
id: 'private',
|
||||||
|
username: '${env.PRIVATE_USERNAME}',
|
||||||
|
password: '${env.PRIVATE_TOKEN}'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (combined) {
|
||||||
|
expect(xml).toContain('<repositories>');
|
||||||
|
expect(xml).toContain('<pluginRepositories>');
|
||||||
|
expect(xml).toContain('<gpg.passphraseEnvName>GPG_PASSPHRASE');
|
||||||
|
} else {
|
||||||
|
expect(xml).not.toContain('<profiles>');
|
||||||
|
expect(core.getInput).not.toHaveBeenCalledWith(
|
||||||
|
'mvn-repositories-include-central'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
it.each(repositoryInputs)(
|
it.each(repositoryInputs)(
|
||||||
'parses %s while preserving colons in URLs',
|
'parses %s while preserving colons in URLs',
|
||||||
inputName => {
|
inputName => {
|
||||||
|
|||||||
@@ -75,6 +75,9 @@ inputs:
|
|||||||
mvn-plugin-repositories:
|
mvn-plugin-repositories:
|
||||||
description: 'Multiline list of Maven plugin repositories in the format `repository-id:repository-url:snapshots-enabled`.'
|
description: 'Multiline list of Maven plugin repositories in the format `repository-id:repository-url:snapshots-enabled`.'
|
||||||
required: false
|
required: false
|
||||||
|
mvn-mirrors:
|
||||||
|
description: 'Multiline list of Maven mirrors in the format `mirror-id:mirror-url:mirror-of`. Use a matching server ID for authentication. Can be used independently of repository inputs.'
|
||||||
|
required: false
|
||||||
mvn-repositories-include-central:
|
mvn-repositories-include-central:
|
||||||
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.'
|
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
|
required: false
|
||||||
|
|||||||
3
dist/cleanup/index.js
vendored
3
dist/cleanup/index.js
vendored
@@ -31040,7 +31040,7 @@ module.exports = {
|
|||||||
/* harmony export */ gk: () => (/* binding */ INPUT_CACHE),
|
/* harmony export */ gk: () => (/* binding */ INPUT_CACHE),
|
||||||
/* harmony export */ wG: () => (/* binding */ INPUT_JOB_STATUS)
|
/* harmony export */ wG: () => (/* binding */ INPUT_JOB_STATUS)
|
||||||
/* harmony export */ });
|
/* 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_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 */
|
/* 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_MIRRORS, 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 MACOS_JAVA_CONTENT_POSTFIX = 'Contents/Home';
|
||||||
const INPUT_JAVA_VERSION = 'java-version';
|
const INPUT_JAVA_VERSION = 'java-version';
|
||||||
const INPUT_JAVA_VERSION_FILE = 'java-version-file';
|
const INPUT_JAVA_VERSION_FILE = 'java-version-file';
|
||||||
@@ -31061,6 +31061,7 @@ const INPUT_MVN_SERVER_CREDENTIALS = 'mvn-server-credentials';
|
|||||||
const INPUT_MVN_SERVER_REPOSITORY_ORIGINS = 'mvn-server-repository-origins';
|
const INPUT_MVN_SERVER_REPOSITORY_ORIGINS = 'mvn-server-repository-origins';
|
||||||
const INPUT_MVN_REPOSITORIES = 'mvn-repositories';
|
const INPUT_MVN_REPOSITORIES = 'mvn-repositories';
|
||||||
const INPUT_MVN_PLUGIN_REPOSITORIES = 'mvn-plugin-repositories';
|
const INPUT_MVN_PLUGIN_REPOSITORIES = 'mvn-plugin-repositories';
|
||||||
|
const INPUT_MVN_MIRRORS = 'mvn-mirrors';
|
||||||
const INPUT_MVN_REPOSITORIES_INCLUDE_CENTRAL = 'mvn-repositories-include-central';
|
const INPUT_MVN_REPOSITORIES_INCLUDE_CENTRAL = 'mvn-repositories-include-central';
|
||||||
const INPUT_MVN_REPOSITORIES_PRIORITIZE_CENTRAL = 'mvn-repositories-prioritize-central';
|
const INPUT_MVN_REPOSITORIES_PRIORITIZE_CENTRAL = 'mvn-repositories-prioritize-central';
|
||||||
const INPUT_SERVER_ID = 'server-id';
|
const INPUT_SERVER_ID = 'server-id';
|
||||||
|
|||||||
48
dist/setup/81.index.js
vendored
48
dist/setup/81.index.js
vendored
@@ -14,6 +14,7 @@ __webpack_require__.r(__webpack_exports__);
|
|||||||
/* harmony export */ getInputWithDeprecatedAlias: () => (/* binding */ getInputWithDeprecatedAlias),
|
/* harmony export */ getInputWithDeprecatedAlias: () => (/* binding */ getInputWithDeprecatedAlias),
|
||||||
/* harmony export */ getMavenRepositorySettings: () => (/* binding */ getMavenRepositorySettings),
|
/* harmony export */ getMavenRepositorySettings: () => (/* binding */ getMavenRepositorySettings),
|
||||||
/* harmony export */ getMavenServerSettings: () => (/* binding */ getMavenServerSettings),
|
/* harmony export */ getMavenServerSettings: () => (/* binding */ getMavenServerSettings),
|
||||||
|
/* harmony export */ parseMavenMirrors: () => (/* binding */ parseMavenMirrors),
|
||||||
/* harmony export */ parseMavenRepositories: () => (/* binding */ parseMavenRepositories),
|
/* harmony export */ parseMavenRepositories: () => (/* binding */ parseMavenRepositories),
|
||||||
/* harmony export */ parseMavenServerCredentials: () => (/* binding */ parseMavenServerCredentials)
|
/* harmony export */ parseMavenServerCredentials: () => (/* binding */ parseMavenServerCredentials)
|
||||||
/* harmony export */ });
|
/* harmony export */ });
|
||||||
@@ -42,6 +43,7 @@ const MAVEN_REPOSITORY_ORIGIN = /^[A-Za-z][A-Za-z0-9+.-]*:\/\/[^/?#@]+\/?$/;
|
|||||||
async function configureAuthentication() {
|
async function configureAuthentication() {
|
||||||
const servers = getMavenServerSettings();
|
const servers = getMavenServerSettings();
|
||||||
const repositorySettings = getMavenRepositorySettings();
|
const repositorySettings = getMavenRepositorySettings();
|
||||||
|
const mirrors = parseMavenMirrors(_actions_core__WEBPACK_IMPORTED_MODULE_1__/* .getMultilineInput */ .q3(_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_MVN_MIRRORS */ .K));
|
||||||
const settingsDirectory = _actions_core__WEBPACK_IMPORTED_MODULE_1__/* .getInput */ .V4(_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_SETTINGS_PATH */ .Xh) ||
|
const settingsDirectory = _actions_core__WEBPACK_IMPORTED_MODULE_1__/* .getInput */ .V4(_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_SETTINGS_PATH */ .Xh) ||
|
||||||
path__WEBPACK_IMPORTED_MODULE_0__.join(os__WEBPACK_IMPORTED_MODULE_4__.homedir(), _constants_js__WEBPACK_IMPORTED_MODULE_7__/* .M2_DIR */ .iT);
|
path__WEBPACK_IMPORTED_MODULE_0__.join(os__WEBPACK_IMPORTED_MODULE_4__.homedir(), _constants_js__WEBPACK_IMPORTED_MODULE_7__/* .M2_DIR */ .iT);
|
||||||
const overwriteSettings = (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .getBooleanInput */ .Vt)(_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_OVERWRITE_SETTINGS */ .TS, true);
|
const overwriteSettings = (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .getBooleanInput */ .Vt)(_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_OVERWRITE_SETTINGS */ .TS, true);
|
||||||
@@ -51,7 +53,7 @@ async function configureAuthentication() {
|
|||||||
if (gpgPrivateKey) {
|
if (gpgPrivateKey) {
|
||||||
_actions_core__WEBPACK_IMPORTED_MODULE_1__/* .setSecret */ .Pq(gpgPrivateKey);
|
_actions_core__WEBPACK_IMPORTED_MODULE_1__/* .setSecret */ .Pq(gpgPrivateKey);
|
||||||
}
|
}
|
||||||
await createAuthenticationSettings(servers, settingsDirectory, overwriteSettings, gpgPassphraseEnvVar, repositorySettings);
|
await createAuthenticationSettings(servers, settingsDirectory, overwriteSettings, gpgPassphraseEnvVar, repositorySettings, mirrors);
|
||||||
if (gpgPrivateKey) {
|
if (gpgPrivateKey) {
|
||||||
_actions_core__WEBPACK_IMPORTED_MODULE_1__/* .info */ .pq('Importing private gpg key');
|
_actions_core__WEBPACK_IMPORTED_MODULE_1__/* .info */ .pq('Importing private gpg key');
|
||||||
const gpgHome = await _gpg_js__WEBPACK_IMPORTED_MODULE_5__/* .importKey */ .Fh(gpgPrivateKey);
|
const gpgHome = await _gpg_js__WEBPACK_IMPORTED_MODULE_5__/* .importKey */ .Fh(gpgPrivateKey);
|
||||||
@@ -222,6 +224,37 @@ function parseMavenRepositories(entries, includeCentral, inputName = _constants_
|
|||||||
});
|
});
|
||||||
return repositories;
|
return repositories;
|
||||||
}
|
}
|
||||||
|
// only exported for testing purposes
|
||||||
|
function parseMavenMirrors(entries) {
|
||||||
|
const mirrors = [];
|
||||||
|
const mirrorIds = new Set();
|
||||||
|
entries.forEach((entry, index) => {
|
||||||
|
if (!entry.trim()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const separator = entry.indexOf(':');
|
||||||
|
const remainder = entry.slice(separator + 1).trim();
|
||||||
|
// Consume the URL scheme before looking for the selector delimiter. Selector
|
||||||
|
// tokens may themselves contain colons (external:* and external:http:*).
|
||||||
|
const scheme = /^[A-Za-z][A-Za-z0-9+.-]*:/.exec(remainder)?.[0] ?? '';
|
||||||
|
const fields = /^(.*?):((?:\s*!?external:(?:http:)?\*\s*|[^:,]*)(?:,(?:\s*!?external:(?:http:)?\*\s*|[^:,]*))*)$/.exec(remainder.slice(scheme.length));
|
||||||
|
if (separator < 0 || !fields) {
|
||||||
|
throw new Error(`Invalid mvn-mirrors entry at line ${index + 1}. Expected format: mirror-id:mirror-url:mirror-of`);
|
||||||
|
}
|
||||||
|
const id = entry.slice(0, separator).trim();
|
||||||
|
const url = `${scheme}${fields[1]}`.trim();
|
||||||
|
const mirrorOf = fields[2].trim();
|
||||||
|
if (!id || !url || !mirrorOf) {
|
||||||
|
throw new Error(`Invalid mvn-mirrors entry at line ${index + 1}. mirror-id, mirror URL, and mirror-of are required`);
|
||||||
|
}
|
||||||
|
if (mirrorIds.has(id)) {
|
||||||
|
throw new Error(`Duplicate mirror-id '${id}' in mvn-mirrors input at line ${index + 1}`);
|
||||||
|
}
|
||||||
|
mirrorIds.add(id);
|
||||||
|
mirrors.push({ id, url, mirrorOf });
|
||||||
|
});
|
||||||
|
return mirrors;
|
||||||
|
}
|
||||||
function generateRepositorySection(customRepositories, settings, element) {
|
function generateRepositorySection(customRepositories, settings, element) {
|
||||||
if (!customRepositories.length && settings.includeCentral) {
|
if (!customRepositories.length && settings.includeCentral) {
|
||||||
return [];
|
return [];
|
||||||
@@ -253,15 +286,15 @@ function generateRepositorySection(customRepositories, settings, element) {
|
|||||||
lines.push(` </${container}>`);
|
lines.push(` </${container}>`);
|
||||||
return lines;
|
return lines;
|
||||||
}
|
}
|
||||||
async function createAuthenticationSettings(servers, settingsDirectory, overwriteSettings, gpgPassphraseEnvVar = undefined, repositorySettings = undefined) {
|
async function createAuthenticationSettings(servers, settingsDirectory, overwriteSettings, gpgPassphraseEnvVar = undefined, repositorySettings = undefined, mirrors = []) {
|
||||||
_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(', ')}`);
|
_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)
|
// when an alternate m2 location is specified use only that location (no .m2 directory)
|
||||||
// otherwise use the home/.m2/ path
|
// otherwise use the home/.m2/ path
|
||||||
await _actions_io__WEBPACK_IMPORTED_MODULE_2__/* .mkdirP */ .U$(settingsDirectory);
|
await _actions_io__WEBPACK_IMPORTED_MODULE_2__/* .mkdirP */ .U$(settingsDirectory);
|
||||||
await write(settingsDirectory, generate(servers, gpgPassphraseEnvVar, repositorySettings), overwriteSettings);
|
await write(settingsDirectory, generate(servers, gpgPassphraseEnvVar, repositorySettings, mirrors), overwriteSettings);
|
||||||
}
|
}
|
||||||
// only exported for testing purposes
|
// only exported for testing purposes
|
||||||
function generate(servers, gpgPassphraseEnvVar, repositorySettings) {
|
function generate(servers, gpgPassphraseEnvVar, repositorySettings, mirrors = []) {
|
||||||
// The maven-gpg-plugin reads the passphrase from the environment variable
|
// The maven-gpg-plugin reads the passphrase from the environment variable
|
||||||
// named by the `gpg.passphraseEnvName` property (default MAVEN_GPG_PASSPHRASE).
|
// named by the `gpg.passphraseEnvName` property (default MAVEN_GPG_PASSPHRASE).
|
||||||
// Only configure it when the requested env var name differs from that default;
|
// Only configure it when the requested env var name differs from that default;
|
||||||
@@ -289,6 +322,13 @@ function generate(servers, gpgPassphraseEnvVar, repositorySettings) {
|
|||||||
lines.push(' </server>');
|
lines.push(' </server>');
|
||||||
}
|
}
|
||||||
lines.push(' </servers>');
|
lines.push(' </servers>');
|
||||||
|
if (mirrors.length) {
|
||||||
|
lines.push(' <mirrors>');
|
||||||
|
for (const mirror of mirrors) {
|
||||||
|
lines.push(' <mirror>', ` <id>${(0,_xml_js__WEBPACK_IMPORTED_MODULE_8__/* .escapeXmlText */ .I)(mirror.id)}</id>`, ` <url>${(0,_xml_js__WEBPACK_IMPORTED_MODULE_8__/* .escapeXmlText */ .I)(mirror.url)}</url>`, ` <mirrorOf>${(0,_xml_js__WEBPACK_IMPORTED_MODULE_8__/* .escapeXmlText */ .I)(mirror.mirrorOf)}</mirrorOf>`, ' </mirror>');
|
||||||
|
}
|
||||||
|
lines.push(' </mirrors>');
|
||||||
|
}
|
||||||
if (repositorySettings || includeGpgPassphraseProfile) {
|
if (repositorySettings || includeGpgPassphraseProfile) {
|
||||||
lines.push(' <profiles>');
|
lines.push(' <profiles>');
|
||||||
if (repositorySettings) {
|
if (repositorySettings) {
|
||||||
|
|||||||
2
dist/setup/index.js
vendored
2
dist/setup/index.js
vendored
@@ -31040,6 +31040,7 @@ module.exports = {
|
|||||||
/* harmony export */ GL: () => (/* binding */ INPUT_CACHE_JDK),
|
/* harmony export */ GL: () => (/* binding */ INPUT_CACHE_JDK),
|
||||||
/* harmony export */ H5: () => (/* binding */ INPUT_MVN_REPOSITORIES_INCLUDE_CENTRAL),
|
/* harmony export */ H5: () => (/* binding */ INPUT_MVN_REPOSITORIES_INCLUDE_CENTRAL),
|
||||||
/* harmony export */ I9: () => (/* binding */ INPUT_FORCE_DOWNLOAD),
|
/* harmony export */ I9: () => (/* binding */ INPUT_FORCE_DOWNLOAD),
|
||||||
|
/* harmony export */ K: () => (/* binding */ INPUT_MVN_MIRRORS),
|
||||||
/* harmony export */ K$: () => (/* binding */ GPG_PASSPHRASE_PROFILE_ID),
|
/* harmony export */ K$: () => (/* binding */ GPG_PASSPHRASE_PROFILE_ID),
|
||||||
/* harmony export */ LS: () => (/* binding */ INPUT_ARCHITECTURE),
|
/* harmony export */ LS: () => (/* binding */ INPUT_ARCHITECTURE),
|
||||||
/* harmony export */ MM: () => (/* binding */ INPUT_MVN_SERVER_CREDENTIALS),
|
/* harmony export */ MM: () => (/* binding */ INPUT_MVN_SERVER_CREDENTIALS),
|
||||||
@@ -31111,6 +31112,7 @@ const INPUT_MVN_SERVER_CREDENTIALS = 'mvn-server-credentials';
|
|||||||
const INPUT_MVN_SERVER_REPOSITORY_ORIGINS = 'mvn-server-repository-origins';
|
const INPUT_MVN_SERVER_REPOSITORY_ORIGINS = 'mvn-server-repository-origins';
|
||||||
const INPUT_MVN_REPOSITORIES = 'mvn-repositories';
|
const INPUT_MVN_REPOSITORIES = 'mvn-repositories';
|
||||||
const INPUT_MVN_PLUGIN_REPOSITORIES = 'mvn-plugin-repositories';
|
const INPUT_MVN_PLUGIN_REPOSITORIES = 'mvn-plugin-repositories';
|
||||||
|
const INPUT_MVN_MIRRORS = 'mvn-mirrors';
|
||||||
const INPUT_MVN_REPOSITORIES_INCLUDE_CENTRAL = 'mvn-repositories-include-central';
|
const INPUT_MVN_REPOSITORIES_INCLUDE_CENTRAL = 'mvn-repositories-include-central';
|
||||||
const INPUT_MVN_REPOSITORIES_PRIORITIZE_CENTRAL = 'mvn-repositories-prioritize-central';
|
const INPUT_MVN_REPOSITORIES_PRIORITIZE_CENTRAL = 'mvn-repositories-prioritize-central';
|
||||||
const INPUT_SERVER_ID = 'server-id';
|
const INPUT_SERVER_ID = 'server-id';
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
- [Testing against different platforms](#Testing-against-different-platforms)
|
- [Testing against different platforms](#Testing-against-different-platforms)
|
||||||
- [Publishing using Apache Maven](#Publishing-using-Apache-Maven)
|
- [Publishing using Apache Maven](#Publishing-using-Apache-Maven)
|
||||||
- [Publishing to multiple Maven servers](#publishing-to-multiple-maven-servers)
|
- [Publishing to multiple Maven servers](#publishing-to-multiple-maven-servers)
|
||||||
|
- [Redirecting Maven repositories with mirrors](#redirecting-maven-repositories-with-mirrors)
|
||||||
- [Apache Maven with a settings path](#apache-maven-with-a-settings-path)
|
- [Apache Maven with a settings path](#apache-maven-with-a-settings-path)
|
||||||
- [Maven transfer progress (download logs)](#Maven-transfer-progress-download-logs)
|
- [Maven transfer progress (download logs)](#Maven-transfer-progress-download-logs)
|
||||||
- [Java problem matcher (compiler annotations)](#java-problem-matcher-compiler-annotations)
|
- [Java problem matcher (compiler annotations)](#java-problem-matcher-compiler-annotations)
|
||||||
@@ -1090,6 +1091,72 @@ default; `mvn-repositories-prioritize-central: false` places it after them.
|
|||||||
All repository generation respects `settings-path` and `overwrite-settings`;
|
All repository generation respects `settings-path` and `overwrite-settings`;
|
||||||
an existing settings file is left untouched when `overwrite-settings: false`.
|
an existing settings file is left untouched when `overwrite-settings: false`.
|
||||||
|
|
||||||
|
### Redirecting Maven repositories with mirrors
|
||||||
|
|
||||||
|
Use `mvn-mirrors` to redirect matching dependency and plugin repositories,
|
||||||
|
including Maven Central and repositories declared in project or parent POMs.
|
||||||
|
Unlike repository profiles, mirrors replace the destination Maven contacts.
|
||||||
|
The Central controls described above do not redirect arbitrary POM repositories.
|
||||||
|
|
||||||
|
Each nonblank line has the format `mirror-id:mirror-url:mirror-of`. IDs must be
|
||||||
|
unique within this input. URL schemes and ports, and colons in `mirrorOf`
|
||||||
|
selectors, are preserved. For example:
|
||||||
|
|
||||||
|
```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-mirrors: |
|
||||||
|
private:https://maven.example.com/releases:*
|
||||||
|
- run: mvn --batch-mode verify
|
||||||
|
env:
|
||||||
|
PRIVATE_REPOSITORY_USERNAME: ${{ secrets.PRIVATE_REPOSITORY_USERNAME }}
|
||||||
|
PRIVATE_REPOSITORY_TOKEN: ${{ secrets.PRIVATE_REPOSITORY_TOKEN }}
|
||||||
|
```
|
||||||
|
|
||||||
|
This adds the following directly under `<settings>`, not inside a profile:
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<mirrors>
|
||||||
|
<mirror>
|
||||||
|
<id>private</id>
|
||||||
|
<url>https://maven.example.com/releases</url>
|
||||||
|
<mirrorOf>*</mirrorOf>
|
||||||
|
</mirror>
|
||||||
|
</mirrors>
|
||||||
|
```
|
||||||
|
|
||||||
|
For authentication, the mirror ID must match a server ID configured through
|
||||||
|
`mvn-server-credentials` or the single-server inputs. Public mirrors do not need
|
||||||
|
matching credentials. Credentials remain environment-variable references in the
|
||||||
|
generated settings; do not put credential values in `mvn-mirrors`.
|
||||||
|
|
||||||
|
Mirrors can be used alone, as above, or alongside `mvn-repositories` and
|
||||||
|
`mvn-plugin-repositories`. They do not change those inputs or the Central
|
||||||
|
controls. Omitting `mvn-mirrors`, or supplying only blank lines, adds no
|
||||||
|
`<mirrors>` section or repository profile.
|
||||||
|
|
||||||
|
Maven interprets `mirrorOf`: `*` matches every repository, `central` matches
|
||||||
|
only that repository ID, `external:*` matches external repositories, and
|
||||||
|
`external:http:*` matches external HTTP repositories. Comma-separated patterns
|
||||||
|
such as `external:*,!internal` exclude specific IDs. Selector text and mirror
|
||||||
|
order are retained; Maven applies its own matching and precedence rules.
|
||||||
|
For example, a public mirror needs no additional repository or credential input:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
mvn-mirrors: |
|
||||||
|
public:https://mirror.example.com:8443/maven:external:*,!internal
|
||||||
|
```
|
||||||
|
|
||||||
|
Mirror generation respects `settings-path` and `overwrite-settings`. An existing
|
||||||
|
settings file is left untouched when `overwrite-settings: false`; this input
|
||||||
|
does not merge mirrors into that file.
|
||||||
|
|
||||||
### GPG
|
### GPG
|
||||||
|
|
||||||
The example above uses the [Maven GPG Plugin](https://maven.apache.org/plugins/maven-gpg-plugin/)'s Bouncy Castle signer (`-Dgpg.signer=bc`, available since `maven-gpg-plugin` 3.2.0). It is a pure-Java signer that reads the key directly from the `MAVEN_GPG_KEY` environment variable, so it does **not** require the `gpg` executable, importing the key into a GPG keychain, or the `--pinentry-mode loopback` workaround in your `pom.xml`. The key must be an ASCII-armored secret key (transferable secret key format).
|
The example above uses the [Maven GPG Plugin](https://maven.apache.org/plugins/maven-gpg-plugin/)'s Bouncy Castle signer (`-Dgpg.signer=bc`, available since `maven-gpg-plugin` 3.2.0). It is a pure-Java signer that reads the key directly from the `MAVEN_GPG_KEY` environment variable, so it does **not** require the `gpg` executable, importing the key into a GPG keychain, or the `--pinentry-mode loopback` workaround in your `pom.xml`. The key must be an ASCII-armored secret key (transferable secret key format).
|
||||||
|
|||||||
80
src/auth.ts
80
src/auth.ts
@@ -30,11 +30,20 @@ export interface MavenRepositorySettings {
|
|||||||
prioritizeCentral: boolean;
|
prioritizeCentral: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface MavenMirror {
|
||||||
|
id: string;
|
||||||
|
url: string;
|
||||||
|
mirrorOf: string;
|
||||||
|
}
|
||||||
|
|
||||||
const MAVEN_REPOSITORY_ORIGIN = /^[A-Za-z][A-Za-z0-9+.-]*:\/\/[^/?#@]+\/?$/;
|
const MAVEN_REPOSITORY_ORIGIN = /^[A-Za-z][A-Za-z0-9+.-]*:\/\/[^/?#@]+\/?$/;
|
||||||
|
|
||||||
export async function configureAuthentication() {
|
export async function configureAuthentication() {
|
||||||
const servers = getMavenServerSettings();
|
const servers = getMavenServerSettings();
|
||||||
const repositorySettings = getMavenRepositorySettings();
|
const repositorySettings = getMavenRepositorySettings();
|
||||||
|
const mirrors = parseMavenMirrors(
|
||||||
|
core.getMultilineInput(constants.INPUT_MVN_MIRRORS)
|
||||||
|
);
|
||||||
const settingsDirectory =
|
const settingsDirectory =
|
||||||
core.getInput(constants.INPUT_SETTINGS_PATH) ||
|
core.getInput(constants.INPUT_SETTINGS_PATH) ||
|
||||||
path.join(os.homedir(), constants.M2_DIR);
|
path.join(os.homedir(), constants.M2_DIR);
|
||||||
@@ -60,7 +69,8 @@ export async function configureAuthentication() {
|
|||||||
settingsDirectory,
|
settingsDirectory,
|
||||||
overwriteSettings,
|
overwriteSettings,
|
||||||
gpgPassphraseEnvVar,
|
gpgPassphraseEnvVar,
|
||||||
repositorySettings
|
repositorySettings,
|
||||||
|
mirrors
|
||||||
);
|
);
|
||||||
|
|
||||||
if (gpgPrivateKey) {
|
if (gpgPrivateKey) {
|
||||||
@@ -333,6 +343,52 @@ export function parseMavenRepositories(
|
|||||||
return repositories;
|
return repositories;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// only exported for testing purposes
|
||||||
|
export function parseMavenMirrors(entries: string[]): MavenMirror[] {
|
||||||
|
const mirrors: MavenMirror[] = [];
|
||||||
|
const mirrorIds = new Set<string>();
|
||||||
|
|
||||||
|
entries.forEach((entry, index) => {
|
||||||
|
if (!entry.trim()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const separator = entry.indexOf(':');
|
||||||
|
const remainder = entry.slice(separator + 1).trim();
|
||||||
|
// Consume the URL scheme before looking for the selector delimiter. Selector
|
||||||
|
// tokens may themselves contain colons (external:* and external:http:*).
|
||||||
|
const scheme = /^[A-Za-z][A-Za-z0-9+.-]*:/.exec(remainder)?.[0] ?? '';
|
||||||
|
const fields =
|
||||||
|
/^(.*?):((?:\s*!?external:(?:http:)?\*\s*|[^:,]*)(?:,(?:\s*!?external:(?:http:)?\*\s*|[^:,]*))*)$/.exec(
|
||||||
|
remainder.slice(scheme.length)
|
||||||
|
);
|
||||||
|
if (separator < 0 || !fields) {
|
||||||
|
throw new Error(
|
||||||
|
`Invalid mvn-mirrors entry at line ${index + 1}. Expected format: mirror-id:mirror-url:mirror-of`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const id = entry.slice(0, separator).trim();
|
||||||
|
const url = `${scheme}${fields[1]}`.trim();
|
||||||
|
const mirrorOf = fields[2].trim();
|
||||||
|
if (!id || !url || !mirrorOf) {
|
||||||
|
throw new Error(
|
||||||
|
`Invalid mvn-mirrors entry at line ${index + 1}. mirror-id, mirror URL, and mirror-of are required`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (mirrorIds.has(id)) {
|
||||||
|
throw new Error(
|
||||||
|
`Duplicate mirror-id '${id}' in mvn-mirrors input at line ${index + 1}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
mirrorIds.add(id);
|
||||||
|
mirrors.push({id, url, mirrorOf});
|
||||||
|
});
|
||||||
|
|
||||||
|
return mirrors;
|
||||||
|
}
|
||||||
|
|
||||||
function generateRepositorySection(
|
function generateRepositorySection(
|
||||||
customRepositories: MavenRepository[],
|
customRepositories: MavenRepository[],
|
||||||
settings: MavenRepositorySettings,
|
settings: MavenRepositorySettings,
|
||||||
@@ -388,7 +444,8 @@ export async function createAuthenticationSettings(
|
|||||||
settingsDirectory: string,
|
settingsDirectory: string,
|
||||||
overwriteSettings: boolean,
|
overwriteSettings: boolean,
|
||||||
gpgPassphraseEnvVar: string | undefined = undefined,
|
gpgPassphraseEnvVar: string | undefined = undefined,
|
||||||
repositorySettings: MavenRepositorySettings | undefined = undefined
|
repositorySettings: MavenRepositorySettings | undefined = undefined,
|
||||||
|
mirrors: MavenMirror[] = []
|
||||||
) {
|
) {
|
||||||
core.info(
|
core.info(
|
||||||
`Creating ${constants.MVN_SETTINGS_FILE} with server-id: ${servers.map(server => server.id).join(', ')}`
|
`Creating ${constants.MVN_SETTINGS_FILE} with server-id: ${servers.map(server => server.id).join(', ')}`
|
||||||
@@ -398,7 +455,7 @@ export async function createAuthenticationSettings(
|
|||||||
await io.mkdirP(settingsDirectory);
|
await io.mkdirP(settingsDirectory);
|
||||||
await write(
|
await write(
|
||||||
settingsDirectory,
|
settingsDirectory,
|
||||||
generate(servers, gpgPassphraseEnvVar, repositorySettings),
|
generate(servers, gpgPassphraseEnvVar, repositorySettings, mirrors),
|
||||||
overwriteSettings
|
overwriteSettings
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -407,7 +464,8 @@ export async function createAuthenticationSettings(
|
|||||||
export function generate(
|
export function generate(
|
||||||
servers: MavenServerCredentials[],
|
servers: MavenServerCredentials[],
|
||||||
gpgPassphraseEnvVar?: string | undefined,
|
gpgPassphraseEnvVar?: string | undefined,
|
||||||
repositorySettings?: MavenRepositorySettings | undefined
|
repositorySettings?: MavenRepositorySettings | undefined,
|
||||||
|
mirrors: MavenMirror[] = []
|
||||||
) {
|
) {
|
||||||
// The maven-gpg-plugin reads the passphrase from the environment variable
|
// The maven-gpg-plugin reads the passphrase from the environment variable
|
||||||
// named by the `gpg.passphraseEnvName` property (default MAVEN_GPG_PASSPHRASE).
|
// named by the `gpg.passphraseEnvName` property (default MAVEN_GPG_PASSPHRASE).
|
||||||
@@ -447,6 +505,20 @@ export function generate(
|
|||||||
}
|
}
|
||||||
lines.push(' </servers>');
|
lines.push(' </servers>');
|
||||||
|
|
||||||
|
if (mirrors.length) {
|
||||||
|
lines.push(' <mirrors>');
|
||||||
|
for (const mirror of mirrors) {
|
||||||
|
lines.push(
|
||||||
|
' <mirror>',
|
||||||
|
` <id>${escapeXmlText(mirror.id)}</id>`,
|
||||||
|
` <url>${escapeXmlText(mirror.url)}</url>`,
|
||||||
|
` <mirrorOf>${escapeXmlText(mirror.mirrorOf)}</mirrorOf>`,
|
||||||
|
' </mirror>'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
lines.push(' </mirrors>');
|
||||||
|
}
|
||||||
|
|
||||||
if (repositorySettings || includeGpgPassphraseProfile) {
|
if (repositorySettings || includeGpgPassphraseProfile) {
|
||||||
lines.push(' <profiles>');
|
lines.push(' <profiles>');
|
||||||
if (repositorySettings) {
|
if (repositorySettings) {
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ export const INPUT_MVN_SERVER_REPOSITORY_ORIGINS =
|
|||||||
'mvn-server-repository-origins';
|
'mvn-server-repository-origins';
|
||||||
export const INPUT_MVN_REPOSITORIES = 'mvn-repositories';
|
export const INPUT_MVN_REPOSITORIES = 'mvn-repositories';
|
||||||
export const INPUT_MVN_PLUGIN_REPOSITORIES = 'mvn-plugin-repositories';
|
export const INPUT_MVN_PLUGIN_REPOSITORIES = 'mvn-plugin-repositories';
|
||||||
|
export const INPUT_MVN_MIRRORS = 'mvn-mirrors';
|
||||||
export const INPUT_MVN_REPOSITORIES_INCLUDE_CENTRAL =
|
export const INPUT_MVN_REPOSITORIES_INCLUDE_CENTRAL =
|
||||||
'mvn-repositories-include-central';
|
'mvn-repositories-include-central';
|
||||||
export const INPUT_MVN_REPOSITORIES_PRIORITIZE_CENTRAL =
|
export const INPUT_MVN_REPOSITORIES_PRIORITIZE_CENTRAL =
|
||||||
|
|||||||
Reference in New Issue
Block a user