From 2e73c8f8cdda42e27cf4a72a4ff643f5864e0cbf Mon Sep 17 00:00:00 2001 From: jmjaffe37 <111303274+jmjaffe37@users.noreply.github.com> Date: Thu, 2 Jul 2026 12:01:00 -0700 Subject: [PATCH 1/7] Updated jetbrains test: https.request() now catches errors. This fixes leaking tests as well (#1070) * Updated jetbrains https.request command to catch errors. This fixes leaking tests as well * Removed deprecated lines from pre-commit and pre-push * added suggestion from PR feedback --- .husky/pre-commit | 3 --- .husky/pre-push | 3 --- .../distributors/jetbrains-installer.test.ts | 24 +++++++++++++++---- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/.husky/pre-commit b/.husky/pre-commit index d24fdfc6..2312dc58 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,4 +1 @@ -#!/usr/bin/env sh -. "$(dirname -- "$0")/_/husky.sh" - npx lint-staged diff --git a/.husky/pre-push b/.husky/pre-push index 7d6707f9..192cb67e 100755 --- a/.husky/pre-push +++ b/.husky/pre-push @@ -1,4 +1 @@ -#!/usr/bin/env sh -. "$(dirname -- "$0")/_/husky.sh" - npm run build && npm test diff --git a/__tests__/distributors/jetbrains-installer.test.ts b/__tests__/distributors/jetbrains-installer.test.ts index bf1dc15d..2d32e7e6 100644 --- a/__tests__/distributors/jetbrains-installer.test.ts +++ b/__tests__/distributors/jetbrains-installer.test.ts @@ -87,10 +87,26 @@ describe('findPackageForDownload', () => { const url = resolvedVersion.url; const options = {method: 'HEAD'}; - https.request(url, options, res => { - // JetBrains uses 403 for inexistent packages - expect(res.statusCode).not.toBe(403); - res.resume(); + await new Promise((resolve, reject) => { + const request = https.request(url, options, res => { + let assertionError: unknown; + + try { + // JetBrains uses 403 for non-existent packages + expect(res.statusCode).not.toBe(403); + } catch (error) { + assertionError = error; + } + + res.resume(); + res.once('error', reject); + res.once('end', () => + assertionError ? reject(assertionError as Error) : resolve() + ); + }); + + request.on('error', reject); + request.end(); }); } ); From 324b33387d37f5aa8878ea44bd7144864a316dee Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Thu, 2 Jul 2026 15:30:53 -0400 Subject: [PATCH 2/7] Fix arm64 e2e workflow tests mislabeled as x64 (#1073) * Initial plan * Fix mislabeled arch in e2e workflow job names for Apple silicon runners --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Bruno Borges --- .github/workflows/e2e-versions.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/e2e-versions.yml b/.github/workflows/e2e-versions.yml index 4ea83d8b..2bcf4883 100644 --- a/.github/workflows/e2e-versions.yml +++ b/.github/workflows/e2e-versions.yml @@ -19,7 +19,7 @@ permissions: jobs: setup-java-major-versions: - name: ${{ matrix.distribution }} ${{ matrix.version }} (jdk-x64) - ${{ matrix.os }} + name: ${{ matrix.distribution }} ${{ matrix.version }} (jdk-${{ contains(matrix.os, 'macos') && !contains(matrix.os, 'intel') && 'arm64' || 'x64' }}) - ${{ matrix.os }} runs-on: ${{ matrix.os }} strategy: fail-fast: false @@ -96,7 +96,7 @@ jobs: shell: bash setup-java-alpine-linux: - name: ${{ matrix.distribution }} ${{ matrix.version }} (jdk-x64) - alpine-linux - ${{ matrix.os }} + name: ${{ matrix.distribution }} ${{ matrix.version }} (jdk-${{ contains(matrix.os, 'macos') && !contains(matrix.os, 'intel') && 'arm64' || 'x64' }}) - alpine-linux - ${{ matrix.os }} runs-on: ${{ matrix.os }} container: image: alpine:3.21 @@ -127,7 +127,7 @@ jobs: shell: bash setup-java-major-minor-versions: - name: ${{ matrix.distribution }} ${{ matrix.version }} (jdk-x64) - ${{ matrix.os }} + name: ${{ matrix.distribution }} ${{ matrix.version }} (jdk-${{ contains(matrix.os, 'macos') && !contains(matrix.os, 'intel') && 'arm64' || 'x64' }}) - ${{ matrix.os }} needs: setup-java-major-versions runs-on: ${{ matrix.os }} strategy: @@ -275,7 +275,7 @@ jobs: shell: bash setup-java-ea-versions-zulu: - name: zulu ${{ matrix.version }} (jdk-x64) - ${{ matrix.os }} + name: zulu ${{ matrix.version }} (jdk-${{ contains(matrix.os, 'macos') && !contains(matrix.os, 'intel') && 'arm64' || 'x64' }}) - ${{ matrix.os }} needs: setup-java-major-minor-versions runs-on: ${{ matrix.os }} strategy: @@ -302,7 +302,7 @@ jobs: shell: bash setup-java-ea-versions-temurin: - name: temurin ${{ matrix.version }} (jdk-x64) - ${{ matrix.os }} + name: temurin ${{ matrix.version }} (jdk-${{ contains(matrix.os, 'macos') && !contains(matrix.os, 'intel') && 'arm64' || 'x64' }}) - ${{ matrix.os }} needs: setup-java-major-minor-versions runs-on: ${{ matrix.os }} strategy: @@ -385,7 +385,7 @@ jobs: shell: bash setup-java-ea-versions-sapmachine: - name: sapmachine ${{ matrix.version }} (jdk-x64) - ${{ matrix.os }} + name: sapmachine ${{ matrix.version }} (jdk-${{ contains(matrix.os, 'macos') && !contains(matrix.os, 'intel') && 'arm64' || 'x64' }}) - ${{ matrix.os }} needs: setup-java-major-minor-versions runs-on: ${{ matrix.os }} strategy: From 6c4d4a5025dca6ad7cc86c839fadbcb66762ed3b Mon Sep 17 00:00:00 2001 From: Bruno Borges Date: Thu, 2 Jul 2026 17:12:50 -0400 Subject: [PATCH 3/7] feat: suppress Maven transfer progress via MAVEN_ARGS by default (add show-download-progress input) (#1053) * feat: suppress Maven transfer progress via MAVEN_ARGS by default Set MAVEN_ARGS to include -ntp (--no-transfer-progress) so Maven invocations in the job produce cleaner CI logs without download/transfer progress noise. Add a new optional 'show-download-progress' input (default false); set it to true to keep the progress output. The change preserves any existing MAVEN_ARGS value (the flag is appended, not overwritten) and is idempotent (it won't add the flag twice if -ntp or --no-transfer-progress is already present). Applies on all platforms; honored by Maven 3.9.0+ and the Maven Wrapper, and is a no-op for non-Maven builds. - action.yml: add show-download-progress input - src/constants.ts: add input + MAVEN_ARGS constants - src/maven-args.ts: new configureMavenArgs() - src/setup-java.ts: invoke configureMavenArgs() during setup - __tests__/maven-args.test.ts: unit tests - docs/advanced-usage.md: document the behavior and input - dist: rebuild bundled action Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Update generated dist for Maven args log change --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> --- __tests__/maven-args.test.ts | 104 +++++++++++++++++++++++++++++++++++ action.yml | 4 ++ dist/cleanup/index.js | 6 +- dist/setup/index.js | 89 +++++++++++++++++++++++++++++- docs/advanced-usage.md | 31 +++++++++++ src/constants.ts | 5 ++ src/maven-args.ts | 69 +++++++++++++++++++++++ src/setup-java.ts | 2 + 8 files changed, 308 insertions(+), 2 deletions(-) create mode 100644 __tests__/maven-args.test.ts create mode 100644 src/maven-args.ts diff --git a/__tests__/maven-args.test.ts b/__tests__/maven-args.test.ts new file mode 100644 index 00000000..8a45a0ea --- /dev/null +++ b/__tests__/maven-args.test.ts @@ -0,0 +1,104 @@ +import * as core from '@actions/core'; + +import {configureMavenArgs} from '../src/maven-args'; +import { + INPUT_SHOW_DOWNLOAD_PROGRESS, + MAVEN_ARGS_ENV, + MAVEN_NO_TRANSFER_PROGRESS_FLAG +} from '../src/constants'; + +describe('configureMavenArgs', () => { + let inputs: Record; + let spyGetInput: jest.SpyInstance; + let spyExportVariable: jest.SpyInstance; + let spyInfo: jest.SpyInstance; + let spyDebug: jest.SpyInstance; + const originalMavenArgs = process.env[MAVEN_ARGS_ENV]; + + beforeEach(() => { + inputs = {}; + + spyGetInput = jest.spyOn(core, 'getInput'); + spyGetInput.mockImplementation((name: string) => inputs[name] ?? ''); + + spyExportVariable = jest.spyOn(core, 'exportVariable'); + spyExportVariable.mockImplementation((name: string, value: string) => { + process.env[name] = value; + }); + + spyInfo = jest.spyOn(core, 'info'); + spyInfo.mockImplementation(() => undefined); + + spyDebug = jest.spyOn(core, 'debug'); + spyDebug.mockImplementation(() => undefined); + + delete process.env[MAVEN_ARGS_ENV]; + }); + + afterEach(() => { + jest.restoreAllMocks(); + if (originalMavenArgs === undefined) { + delete process.env[MAVEN_ARGS_ENV]; + } else { + process.env[MAVEN_ARGS_ENV] = originalMavenArgs; + } + }); + + it('sets MAVEN_ARGS with -ntp by default', () => { + configureMavenArgs(); + + expect(spyExportVariable).toHaveBeenCalledWith( + MAVEN_ARGS_ENV, + MAVEN_NO_TRANSFER_PROGRESS_FLAG + ); + expect(process.env[MAVEN_ARGS_ENV]).toBe(MAVEN_NO_TRANSFER_PROGRESS_FLAG); + }); + + it('does not modify MAVEN_ARGS when show-download-progress is true', () => { + inputs[INPUT_SHOW_DOWNLOAD_PROGRESS] = 'true'; + + configureMavenArgs(); + + expect(spyExportVariable).not.toHaveBeenCalled(); + expect(process.env[MAVEN_ARGS_ENV]).toBeUndefined(); + }); + + it('preserves an existing MAVEN_ARGS value and appends -ntp', () => { + process.env[MAVEN_ARGS_ENV] = '-B -Dstyle.color=always'; + + configureMavenArgs(); + + expect(spyExportVariable).toHaveBeenCalledWith( + MAVEN_ARGS_ENV, + `-B -Dstyle.color=always ${MAVEN_NO_TRANSFER_PROGRESS_FLAG}` + ); + }); + + it('does not duplicate the flag when -ntp is already present', () => { + process.env[MAVEN_ARGS_ENV] = '-B -ntp'; + + configureMavenArgs(); + + expect(spyExportVariable).not.toHaveBeenCalled(); + expect(process.env[MAVEN_ARGS_ENV]).toBe('-B -ntp'); + }); + + it('does not duplicate the flag when --no-transfer-progress is already present', () => { + process.env[MAVEN_ARGS_ENV] = '--no-transfer-progress -B'; + + configureMavenArgs(); + + expect(spyExportVariable).not.toHaveBeenCalled(); + expect(process.env[MAVEN_ARGS_ENV]).toBe('--no-transfer-progress -B'); + }); + + it('keeps the existing MAVEN_ARGS when show-download-progress is true', () => { + inputs[INPUT_SHOW_DOWNLOAD_PROGRESS] = 'true'; + process.env[MAVEN_ARGS_ENV] = '-B'; + + configureMavenArgs(); + + expect(spyExportVariable).not.toHaveBeenCalled(); + expect(process.env[MAVEN_ARGS_ENV]).toBe('-B'); + }); +}); diff --git a/action.yml b/action.yml index cc1a541b..a5b673a8 100644 --- a/action.yml +++ b/action.yml @@ -82,6 +82,10 @@ inputs: mvn-toolchain-vendor: description: 'Name of Maven Toolchain Vendor if the default name of "${distribution}" is not wanted. See examples of supported syntax in Advanced Usage file' required: false + show-download-progress: + description: 'Whether Maven should print artifact download/transfer progress to the build log. When "false" (default) the action sets "-ntp" (--no-transfer-progress) in MAVEN_ARGS to produce cleaner logs. Set to "true" to keep the progress output. Has no effect on non-Maven builds.' + required: false + default: false outputs: distribution: description: 'Distribution of Java that has been installed' diff --git a/dist/cleanup/index.js b/dist/cleanup/index.js index d962852b..ef4fed3b 100644 --- a/dist/cleanup/index.js +++ b/dist/cleanup/index.js @@ -52241,7 +52241,7 @@ else { "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.DISTRIBUTIONS_ONLY_MAJOR_VERSION = exports.INPUT_MVN_TOOLCHAIN_VENDOR = exports.INPUT_MVN_TOOLCHAIN_ID = exports.MVN_TOOLCHAINS_FILE = exports.MVN_SETTINGS_FILE = exports.M2_DIR = exports.STATE_GPG_PRIVATE_KEY_FINGERPRINT = exports.INPUT_JOB_STATUS = exports.INPUT_CACHE_DEPENDENCY_PATH = exports.INPUT_CACHE = exports.INPUT_DEFAULT_GPG_PASSPHRASE = exports.INPUT_DEFAULT_GPG_PRIVATE_KEY = exports.INPUT_GPG_PASSPHRASE = exports.INPUT_GPG_PRIVATE_KEY = exports.INPUT_OVERWRITE_SETTINGS = exports.INPUT_SETTINGS_PATH = exports.INPUT_SERVER_PASSWORD = exports.INPUT_SERVER_USERNAME = exports.INPUT_SERVER_ID = exports.INPUT_VERIFY_SIGNATURE_PUBLIC_KEY = exports.INPUT_VERIFY_SIGNATURE = exports.INPUT_CHECK_LATEST = exports.INPUT_JDK_FILE = exports.INPUT_DISTRIBUTION = exports.INPUT_JAVA_PACKAGE = exports.INPUT_ARCHITECTURE = exports.INPUT_JAVA_VERSION_FILE = exports.INPUT_JAVA_VERSION = exports.MACOS_JAVA_CONTENT_POSTFIX = void 0; +exports.DISTRIBUTIONS_ONLY_MAJOR_VERSION = exports.MAVEN_NO_TRANSFER_PROGRESS_LONG_FLAG = exports.MAVEN_NO_TRANSFER_PROGRESS_FLAG = exports.MAVEN_ARGS_ENV = exports.INPUT_SHOW_DOWNLOAD_PROGRESS = exports.INPUT_MVN_TOOLCHAIN_VENDOR = exports.INPUT_MVN_TOOLCHAIN_ID = exports.MVN_TOOLCHAINS_FILE = exports.MVN_SETTINGS_FILE = exports.M2_DIR = exports.STATE_GPG_PRIVATE_KEY_FINGERPRINT = exports.INPUT_JOB_STATUS = exports.INPUT_CACHE_DEPENDENCY_PATH = exports.INPUT_CACHE = exports.INPUT_DEFAULT_GPG_PASSPHRASE = exports.INPUT_DEFAULT_GPG_PRIVATE_KEY = exports.INPUT_GPG_PASSPHRASE = exports.INPUT_GPG_PRIVATE_KEY = exports.INPUT_OVERWRITE_SETTINGS = exports.INPUT_SETTINGS_PATH = exports.INPUT_SERVER_PASSWORD = exports.INPUT_SERVER_USERNAME = exports.INPUT_SERVER_ID = exports.INPUT_VERIFY_SIGNATURE_PUBLIC_KEY = exports.INPUT_VERIFY_SIGNATURE = exports.INPUT_CHECK_LATEST = exports.INPUT_JDK_FILE = exports.INPUT_DISTRIBUTION = exports.INPUT_JAVA_PACKAGE = exports.INPUT_ARCHITECTURE = exports.INPUT_JAVA_VERSION_FILE = exports.INPUT_JAVA_VERSION = exports.MACOS_JAVA_CONTENT_POSTFIX = void 0; exports.MACOS_JAVA_CONTENT_POSTFIX = 'Contents/Home'; exports.INPUT_JAVA_VERSION = 'java-version'; exports.INPUT_JAVA_VERSION_FILE = 'java-version-file'; @@ -52270,6 +52270,10 @@ exports.MVN_SETTINGS_FILE = 'settings.xml'; exports.MVN_TOOLCHAINS_FILE = 'toolchains.xml'; exports.INPUT_MVN_TOOLCHAIN_ID = 'mvn-toolchain-id'; exports.INPUT_MVN_TOOLCHAIN_VENDOR = 'mvn-toolchain-vendor'; +exports.INPUT_SHOW_DOWNLOAD_PROGRESS = 'show-download-progress'; +exports.MAVEN_ARGS_ENV = 'MAVEN_ARGS'; +exports.MAVEN_NO_TRANSFER_PROGRESS_FLAG = '-ntp'; +exports.MAVEN_NO_TRANSFER_PROGRESS_LONG_FLAG = '--no-transfer-progress'; exports.DISTRIBUTIONS_ONLY_MAJOR_VERSION = ['corretto']; diff --git a/dist/setup/index.js b/dist/setup/index.js index 54ced2b5..59116af7 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -78000,7 +78000,7 @@ function isProbablyGradleDaemonProblem(packageManager, error) { "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.DISTRIBUTIONS_ONLY_MAJOR_VERSION = exports.INPUT_MVN_TOOLCHAIN_VENDOR = exports.INPUT_MVN_TOOLCHAIN_ID = exports.MVN_TOOLCHAINS_FILE = exports.MVN_SETTINGS_FILE = exports.M2_DIR = exports.STATE_GPG_PRIVATE_KEY_FINGERPRINT = exports.INPUT_JOB_STATUS = exports.INPUT_CACHE_DEPENDENCY_PATH = exports.INPUT_CACHE = exports.INPUT_DEFAULT_GPG_PASSPHRASE = exports.INPUT_DEFAULT_GPG_PRIVATE_KEY = exports.INPUT_GPG_PASSPHRASE = exports.INPUT_GPG_PRIVATE_KEY = exports.INPUT_OVERWRITE_SETTINGS = exports.INPUT_SETTINGS_PATH = exports.INPUT_SERVER_PASSWORD = exports.INPUT_SERVER_USERNAME = exports.INPUT_SERVER_ID = exports.INPUT_VERIFY_SIGNATURE_PUBLIC_KEY = exports.INPUT_VERIFY_SIGNATURE = exports.INPUT_CHECK_LATEST = exports.INPUT_JDK_FILE = exports.INPUT_DISTRIBUTION = exports.INPUT_JAVA_PACKAGE = exports.INPUT_ARCHITECTURE = exports.INPUT_JAVA_VERSION_FILE = exports.INPUT_JAVA_VERSION = exports.MACOS_JAVA_CONTENT_POSTFIX = void 0; +exports.DISTRIBUTIONS_ONLY_MAJOR_VERSION = exports.MAVEN_NO_TRANSFER_PROGRESS_LONG_FLAG = exports.MAVEN_NO_TRANSFER_PROGRESS_FLAG = exports.MAVEN_ARGS_ENV = exports.INPUT_SHOW_DOWNLOAD_PROGRESS = exports.INPUT_MVN_TOOLCHAIN_VENDOR = exports.INPUT_MVN_TOOLCHAIN_ID = exports.MVN_TOOLCHAINS_FILE = exports.MVN_SETTINGS_FILE = exports.M2_DIR = exports.STATE_GPG_PRIVATE_KEY_FINGERPRINT = exports.INPUT_JOB_STATUS = exports.INPUT_CACHE_DEPENDENCY_PATH = exports.INPUT_CACHE = exports.INPUT_DEFAULT_GPG_PASSPHRASE = exports.INPUT_DEFAULT_GPG_PRIVATE_KEY = exports.INPUT_GPG_PASSPHRASE = exports.INPUT_GPG_PRIVATE_KEY = exports.INPUT_OVERWRITE_SETTINGS = exports.INPUT_SETTINGS_PATH = exports.INPUT_SERVER_PASSWORD = exports.INPUT_SERVER_USERNAME = exports.INPUT_SERVER_ID = exports.INPUT_VERIFY_SIGNATURE_PUBLIC_KEY = exports.INPUT_VERIFY_SIGNATURE = exports.INPUT_CHECK_LATEST = exports.INPUT_JDK_FILE = exports.INPUT_DISTRIBUTION = exports.INPUT_JAVA_PACKAGE = exports.INPUT_ARCHITECTURE = exports.INPUT_JAVA_VERSION_FILE = exports.INPUT_JAVA_VERSION = exports.MACOS_JAVA_CONTENT_POSTFIX = void 0; exports.MACOS_JAVA_CONTENT_POSTFIX = 'Contents/Home'; exports.INPUT_JAVA_VERSION = 'java-version'; exports.INPUT_JAVA_VERSION_FILE = 'java-version-file'; @@ -78029,6 +78029,10 @@ exports.MVN_SETTINGS_FILE = 'settings.xml'; exports.MVN_TOOLCHAINS_FILE = 'toolchains.xml'; exports.INPUT_MVN_TOOLCHAIN_ID = 'mvn-toolchain-id'; exports.INPUT_MVN_TOOLCHAIN_VENDOR = 'mvn-toolchain-vendor'; +exports.INPUT_SHOW_DOWNLOAD_PROGRESS = 'show-download-progress'; +exports.MAVEN_ARGS_ENV = 'MAVEN_ARGS'; +exports.MAVEN_NO_TRANSFER_PROGRESS_FLAG = '-ntp'; +exports.MAVEN_NO_TRANSFER_PROGRESS_LONG_FLAG = '--no-transfer-progress'; exports.DISTRIBUTIONS_ONLY_MAJOR_VERSION = ['corretto']; @@ -81195,6 +81199,87 @@ function verifyPackageSignature(archivePath, signatureUrl, publicKeyContent) { exports.verifyPackageSignature = verifyPackageSignature; +/***/ }), + +/***/ 38172: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.configureMavenArgs = void 0; +const core = __importStar(__nccwpck_require__(37484)); +const util_1 = __nccwpck_require__(54527); +const constants_1 = __nccwpck_require__(27242); +/** + * Configures the MAVEN_ARGS environment variable so that Maven suppresses + * artifact transfer/download progress output by default, producing cleaner + * CI logs. + * + * Behavior: + * - When `show-download-progress` is `false` (the default), `-ntp` + * (`--no-transfer-progress`) is appended to any existing MAVEN_ARGS value. + * - When `show-download-progress` is `true`, MAVEN_ARGS is left untouched so + * the user's own configuration (and Maven's default progress output) is + * preserved. + * + * The change is idempotent: if MAVEN_ARGS already disables transfer progress + * (via `-ntp` or `--no-transfer-progress`) nothing is added. Any pre-existing + * MAVEN_ARGS value is preserved. + * + * MAVEN_ARGS is honored by Maven 3.9.0+ and the Maven Wrapper; older Maven + * versions ignore it, so this is a no-op there. It has no effect on non-Maven + * builds such as Gradle or sbt. + */ +function configureMavenArgs() { + var _a; + const showDownloadProgress = (0, util_1.getBooleanInput)(constants_1.INPUT_SHOW_DOWNLOAD_PROGRESS, false); + if (showDownloadProgress) { + core.debug(`${constants_1.INPUT_SHOW_DOWNLOAD_PROGRESS} is true; leaving ${constants_1.MAVEN_ARGS_ENV} unchanged`); + return; + } + const existingArgs = ((_a = process.env[constants_1.MAVEN_ARGS_ENV]) !== null && _a !== void 0 ? _a : '').trim(); + const alreadyDisabled = existingArgs + .split(/\s+/) + .some(arg => arg === constants_1.MAVEN_NO_TRANSFER_PROGRESS_FLAG || + arg === constants_1.MAVEN_NO_TRANSFER_PROGRESS_LONG_FLAG); + if (alreadyDisabled) { + core.debug(`${constants_1.MAVEN_ARGS_ENV} already disables transfer progress; leaving it unchanged`); + return; + } + const updatedArgs = existingArgs + ? `${existingArgs} ${constants_1.MAVEN_NO_TRANSFER_PROGRESS_FLAG}` + : constants_1.MAVEN_NO_TRANSFER_PROGRESS_FLAG; + core.exportVariable(constants_1.MAVEN_ARGS_ENV, updatedArgs); + core.info(`Configured ${constants_1.MAVEN_ARGS_ENV} to include ${constants_1.MAVEN_NO_TRANSFER_PROGRESS_FLAG} to suppress Maven transfer progress logs. ` + + `Set '${constants_1.INPUT_SHOW_DOWNLOAD_PROGRESS}: true' to keep the download progress output.`); +} +exports.configureMavenArgs = configureMavenArgs; + + /***/ }), /***/ 90471: @@ -81247,6 +81332,7 @@ const constants = __importStar(__nccwpck_require__(27242)); const cache_1 = __nccwpck_require__(97377); const path = __importStar(__nccwpck_require__(16928)); const distribution_factory_1 = __nccwpck_require__(2970); +const maven_args_1 = __nccwpck_require__(38172); function run() { return __awaiter(this, void 0, void 0, function* () { try { @@ -81298,6 +81384,7 @@ function run() { const matchersPath = path.join(__dirname, '..', '..', '.github'); core.info(`##[add-matcher]${path.join(matchersPath, 'java.json')}`); yield auth.configureAuthentication(); + (0, maven_args_1.configureMavenArgs)(); if (cache && (0, util_1.isCacheFeatureAvailable)()) { yield (0, cache_1.restore)(cache, cacheDependencyPath); } diff --git a/docs/advanced-usage.md b/docs/advanced-usage.md index 58301be9..7e18a278 100644 --- a/docs/advanced-usage.md +++ b/docs/advanced-usage.md @@ -19,6 +19,7 @@ - [Testing against different Java distributions](#Testing-against-different-Java-distributions) - [Testing against different platforms](#Testing-against-different-platforms) - [Publishing using Apache Maven](#Publishing-using-Apache-Maven) +- [Maven transfer progress (download logs)](#Maven-transfer-progress-download-logs) - [Publishing using Gradle](#Publishing-using-Gradle) - [Hosted Tool Cache](#Hosted-Tool-Cache) - [Modifying Maven Toolchains](#Modifying-Maven-Toolchains) @@ -526,6 +527,36 @@ jobs: GITHUB_TOKEN: ${{ github.token }} ``` +## Maven transfer progress (download logs) + +By default, Maven prints a line for every artifact it downloads, which can add hundreds of noisy lines to CI logs. To keep logs clean, `setup-java` sets the [`MAVEN_ARGS`](https://maven.apache.org/configure.html#maven_args-environment-variable) environment variable to include `-ntp` (`--no-transfer-progress`) so that subsequent Maven invocations in the job suppress this transfer progress output. + +This is enabled by default. Any existing `MAVEN_ARGS` value is preserved (the flag is appended, not overwritten), and the flag is not added twice if you already set it yourself. + +If you want to keep the download/transfer progress in your logs, set `show-download-progress: true`: + +```yaml +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v6 + - uses: actions/setup-java@v5 + with: + distribution: '' + java-version: '21' + show-download-progress: true # keep Maven download/transfer progress in the logs + + - name: Build with Maven + run: mvn -B package --file pom.xml +``` + +***NOTES***: +- `MAVEN_ARGS` is honored by Maven 3.9.0+ and the Maven Wrapper (`mvnw`). Older Maven versions ignore it, so on those you can pass `--no-transfer-progress` on the command line instead. +- This setting only affects Maven. It has no effect on Gradle, sbt, or other build tools. +- `-ntp` only controls transfer/progress output; it does not change whether Maven runs in batch mode. Use `-B`/`--batch-mode` (or `false` in `settings.xml`) if you also want non-interactive runs. + ## Publishing using Gradle ```yaml jobs: diff --git a/src/constants.ts b/src/constants.ts index 5b018896..641714c4 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -30,5 +30,10 @@ export const MVN_SETTINGS_FILE = 'settings.xml'; export const MVN_TOOLCHAINS_FILE = 'toolchains.xml'; export const INPUT_MVN_TOOLCHAIN_ID = 'mvn-toolchain-id'; export const INPUT_MVN_TOOLCHAIN_VENDOR = 'mvn-toolchain-vendor'; +export const INPUT_SHOW_DOWNLOAD_PROGRESS = 'show-download-progress'; + +export const MAVEN_ARGS_ENV = 'MAVEN_ARGS'; +export const MAVEN_NO_TRANSFER_PROGRESS_FLAG = '-ntp'; +export const MAVEN_NO_TRANSFER_PROGRESS_LONG_FLAG = '--no-transfer-progress'; export const DISTRIBUTIONS_ONLY_MAJOR_VERSION = ['corretto']; diff --git a/src/maven-args.ts b/src/maven-args.ts new file mode 100644 index 00000000..654bed27 --- /dev/null +++ b/src/maven-args.ts @@ -0,0 +1,69 @@ +import * as core from '@actions/core'; +import {getBooleanInput} from './util'; +import { + INPUT_SHOW_DOWNLOAD_PROGRESS, + MAVEN_ARGS_ENV, + MAVEN_NO_TRANSFER_PROGRESS_FLAG, + MAVEN_NO_TRANSFER_PROGRESS_LONG_FLAG +} from './constants'; + +/** + * Configures the MAVEN_ARGS environment variable so that Maven suppresses + * artifact transfer/download progress output by default, producing cleaner + * CI logs. + * + * Behavior: + * - When `show-download-progress` is `false` (the default), `-ntp` + * (`--no-transfer-progress`) is appended to any existing MAVEN_ARGS value. + * - When `show-download-progress` is `true`, MAVEN_ARGS is left untouched so + * the user's own configuration (and Maven's default progress output) is + * preserved. + * + * The change is idempotent: if MAVEN_ARGS already disables transfer progress + * (via `-ntp` or `--no-transfer-progress`) nothing is added. Any pre-existing + * MAVEN_ARGS value is preserved. + * + * MAVEN_ARGS is honored by Maven 3.9.0+ and the Maven Wrapper; older Maven + * versions ignore it, so this is a no-op there. It has no effect on non-Maven + * builds such as Gradle or sbt. + */ +export function configureMavenArgs(): void { + const showDownloadProgress = getBooleanInput( + INPUT_SHOW_DOWNLOAD_PROGRESS, + false + ); + + if (showDownloadProgress) { + core.debug( + `${INPUT_SHOW_DOWNLOAD_PROGRESS} is true; leaving ${MAVEN_ARGS_ENV} unchanged` + ); + return; + } + + const existingArgs = (process.env[MAVEN_ARGS_ENV] ?? '').trim(); + + const alreadyDisabled = existingArgs + .split(/\s+/) + .some( + arg => + arg === MAVEN_NO_TRANSFER_PROGRESS_FLAG || + arg === MAVEN_NO_TRANSFER_PROGRESS_LONG_FLAG + ); + + if (alreadyDisabled) { + core.debug( + `${MAVEN_ARGS_ENV} already disables transfer progress; leaving it unchanged` + ); + return; + } + + const updatedArgs = existingArgs + ? `${existingArgs} ${MAVEN_NO_TRANSFER_PROGRESS_FLAG}` + : MAVEN_NO_TRANSFER_PROGRESS_FLAG; + + core.exportVariable(MAVEN_ARGS_ENV, updatedArgs); + core.info( + `Configured ${MAVEN_ARGS_ENV} to include ${MAVEN_NO_TRANSFER_PROGRESS_FLAG} to suppress Maven transfer progress logs. ` + + `Set '${INPUT_SHOW_DOWNLOAD_PROGRESS}: true' to keep the download progress output.` + ); +} diff --git a/src/setup-java.ts b/src/setup-java.ts index e4ec400b..d7a84fab 100644 --- a/src/setup-java.ts +++ b/src/setup-java.ts @@ -12,6 +12,7 @@ import {restore} from './cache'; import * as path from 'path'; import {getJavaDistribution} from './distributions/distribution-factory'; import {JavaInstallerOptions} from './distributions/base-models'; +import {configureMavenArgs} from './maven-args'; async function run() { try { @@ -87,6 +88,7 @@ async function run() { core.info(`##[add-matcher]${path.join(matchersPath, 'java.json')}`); await auth.configureAuthentication(); + configureMavenArgs(); if (cache && isCacheFeatureAvailable()) { await restore(cache, cacheDependencyPath); } From 733efaeaca653493004ffb895a11b2c6c316558e Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Thu, 2 Jul 2026 17:22:38 -0400 Subject: [PATCH 4/7] feat: Disable interactiveMode in generated Maven settings.xml (#1052) * Initial plan * Add interactiveMode false to generated maven settings.xml --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Bruno Borges --- __tests__/auth.test.ts | 2 ++ dist/setup/index.js | 1 + docs/advanced-usage.md | 2 ++ src/auth.ts | 1 + 4 files changed, 6 insertions(+) diff --git a/__tests__/auth.test.ts b/__tests__/auth.test.ts index 06591da7..eca837a5 100644 --- a/__tests__/auth.test.ts +++ b/__tests__/auth.test.ts @@ -160,6 +160,7 @@ describe('auth tests', () => { const expectedSettings = ` + false ${id} @@ -181,6 +182,7 @@ describe('auth tests', () => { const expectedSettings = ` + false ${id} diff --git a/dist/setup/index.js b/dist/setup/index.js index 59116af7..0e40385c 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -77727,6 +77727,7 @@ function generate(id, username, password, gpgPassphrase) { '@xmlns': 'http://maven.apache.org/SETTINGS/1.0.0', '@xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance', '@xsi:schemaLocation': 'http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd', + interactiveMode: false, servers: { server: [ { diff --git a/docs/advanced-usage.md b/docs/advanced-usage.md index 7e18a278..58a6ca5d 100644 --- a/docs/advanced-usage.md +++ b/docs/advanced-usage.md @@ -437,6 +437,7 @@ The two `settings.xml` files created from the above example look like the follow + false github @@ -456,6 +457,7 @@ The two `settings.xml` files created from the above example look like the follow + false maven diff --git a/src/auth.ts b/src/auth.ts index c8ea6291..52ee3ede 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -80,6 +80,7 @@ export function generate( '@xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance', '@xsi:schemaLocation': 'http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd', + interactiveMode: false, servers: { server: [ { From c712b2fb55a8deb2d59f204bd7aa86ac6f938c98 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Jul 2026 13:35:02 -0400 Subject: [PATCH 5/7] Bump prettier from 3.6.2 to 3.9.1 (#1066) * Bump prettier from 3.6.2 to 3.9.1 Bumps [prettier](https://github.com/prettier/prettier) from 3.6.2 to 3.9.1. - [Release notes](https://github.com/prettier/prettier/releases) - [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md) - [Commits](https://github.com/prettier/prettier/compare/3.6.2...3.9.1) --- updated-dependencies: - dependency-name: prettier dependency-version: 3.9.1 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Format files for Prettier 3.9.1 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Bruno Borges Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- package-lock.json | 8 ++++---- package.json | 2 +- src/distributions/corretto/installer.ts | 3 +-- src/distributions/liberica/models.ts | 6 +----- 4 files changed, 7 insertions(+), 12 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3c1577ba..aaae36b4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -34,7 +34,7 @@ "jest": "^30.4.2", "jest-circus": "^30.4.2", "lint-staged": "^17.0.8", - "prettier": "^3.6.2", + "prettier": "^3.9.1", "ts-jest": "^29.4.11", "typescript": "^5.3.3" }, @@ -6137,9 +6137,9 @@ } }, "node_modules/prettier": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", - "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.9.1.tgz", + "integrity": "sha512-ppiDo2CSwexck1eyZUwJHg/N3nf1+6IRCv7W/VJ5vaLnVCmB7+3CdRfMwoCHBBX6xTrREDTksZ4OZl5SSf4zXA==", "dev": true, "license": "MIT", "bin": { diff --git a/package.json b/package.json index 64f2bf53..88b11df5 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ "jest": "^30.4.2", "jest-circus": "^30.4.2", "lint-staged": "^17.0.8", - "prettier": "^3.6.2", + "prettier": "^3.9.1", "ts-jest": "^29.4.11", "typescript": "^5.3.3" }, diff --git a/src/distributions/corretto/installer.ts b/src/distributions/corretto/installer.ts index 52af2dd9..fd732899 100644 --- a/src/distributions/corretto/installer.ts +++ b/src/distributions/corretto/installer.ts @@ -127,8 +127,7 @@ export class CorrettoDistribution extends JavaBase { private getAvailableVersionsForPlatform( eligibleVersions: - | ICorrettoAllAvailableVersions['os']['arch']['imageType'] - | undefined + ICorrettoAllAvailableVersions['os']['arch']['imageType'] | undefined ): ICorrettoAvailableVersions[] { const availableVersions: ICorrettoAvailableVersions[] = []; diff --git a/src/distributions/liberica/models.ts b/src/distributions/liberica/models.ts index c9285fb7..6f5a1de1 100644 --- a/src/distributions/liberica/models.ts +++ b/src/distributions/liberica/models.ts @@ -4,11 +4,7 @@ export type Bitness = '32' | '64'; export type ArchType = 'arm' | 'ppc' | 'sparc' | 'x86'; export type OsVersions = - | 'linux' - | 'linux-musl' - | 'macos' - | 'solaris' - | 'windows'; + 'linux' | 'linux-musl' | 'macos' | 'solaris' | 'windows'; export interface ArchitectureOptions { bitness: Bitness; From 0765b158bfd14bd15c56facab447d138e1161193 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Jul 2026 13:45:36 -0400 Subject: [PATCH 6/7] chore(deps-dev): bump eslint-plugin-jest from 29.0.1 to 29.15.4 (#1074) Bumps [eslint-plugin-jest](https://github.com/jest-community/eslint-plugin-jest) from 29.0.1 to 29.15.4. - [Release notes](https://github.com/jest-community/eslint-plugin-jest/releases) - [Changelog](https://github.com/jest-community/eslint-plugin-jest/blob/main/CHANGELOG.md) - [Commits](https://github.com/jest-community/eslint-plugin-jest/compare/v29.0.1...v29.15.4) --- updated-dependencies: - dependency-name: eslint-plugin-jest dependency-version: 29.15.4 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 17 +++++++++++------ package.json | 2 +- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index aaae36b4..e94683d4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,7 +28,7 @@ "@vercel/ncc": "^0.44.0", "eslint": "^8.57.0", "eslint-config-prettier": "^10.1.8", - "eslint-plugin-jest": "^29.0.1", + "eslint-plugin-jest": "^29.15.4", "eslint-plugin-node": "^11.1.0", "husky": "^9.1.7", "jest": "^30.4.2", @@ -3620,10 +3620,11 @@ } }, "node_modules/eslint-plugin-jest": { - "version": "29.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-29.0.1.tgz", - "integrity": "sha512-EE44T0OSMCeXhDrrdsbKAhprobKkPtJTbQz5yEktysNpHeDZTAL1SfDTNKmcFfJkY6yrQLtTKZALrD3j/Gpmiw==", + "version": "29.15.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-29.15.4.tgz", + "integrity": "sha512-6ln5i9Nkrb27X4w91ZPt/xHDsVQnvxTS2ntgq6r32u+8gymdUrp88TdcBXSveZW0Dl+M5v2H6K75kJhMvUGhjg==", "dev": true, + "license": "MIT", "dependencies": { "@typescript-eslint/utils": "^8.0.0" }, @@ -3632,8 +3633,9 @@ }, "peerDependencies": { "@typescript-eslint/eslint-plugin": "^8.0.0", - "eslint": "^8.57.0 || ^9.0.0", - "jest": "*" + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "jest": "*", + "typescript": ">=4.8.4 <7.0.0" }, "peerDependenciesMeta": { "@typescript-eslint/eslint-plugin": { @@ -3641,6 +3643,9 @@ }, "jest": { "optional": true + }, + "typescript": { + "optional": true } } }, diff --git a/package.json b/package.json index 88b11df5..e235cb95 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,7 @@ "@vercel/ncc": "^0.44.0", "eslint": "^8.57.0", "eslint-config-prettier": "^10.1.8", - "eslint-plugin-jest": "^29.0.1", + "eslint-plugin-jest": "^29.15.4", "eslint-plugin-node": "^11.1.0", "husky": "^9.1.7", "jest": "^30.4.2", From 77ee41d00e246422933200d520a0334a299f26e4 Mon Sep 17 00:00:00 2001 From: Nikolas Grottendieck Date: Tue, 7 Jul 2026 06:01:31 +0200 Subject: [PATCH 7/7] fix: Maven Toolchains grows unexpectedly (#534) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: Maven Toolchains grows unexpectedly On self-hosted runners toolchains.xml may survive multiple runs and unexpectedly grow as a result of the toolchains setup simply appending the JDK definition even if one with the same `type` and `provides.id` already exists. Restructuring the parsing step and filtering the potentially existing list of toolchain definitions prevents this and also fixes toolchain.xml files that already contain duplicates. Fixes #530 * fix: guard toolchain dedup and preserve existing root attributes Address reviewer feedback on the Maven toolchains dedup logic: - Treat jdk toolchains without a string `provides.id` as non-deduplicatable and use optional access when comparing ids, so partially-formed or nonstandard toolchains.xml files no longer crash setup. - Preserve the existing `` root attributes (xmlns, schemaLocation, …) when present, falling back to the 1.1.0 defaults only for attributes the existing file is missing. This avoids silently rewriting user-managed metadata or changing the effective namespace. Adds tests covering custom root attributes and id-less jdk toolchains, and rebuilds dist/. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Bruno Borges Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- __tests__/toolchains.test.ts | 615 ++++++++++++++++++++++++++++++++++- dist/setup/index.js | 88 +++-- src/toolchains.ts | 128 +++++--- 3 files changed, 757 insertions(+), 74 deletions(-) diff --git a/__tests__/toolchains.test.ts b/__tests__/toolchains.test.ts index 483077dc..38cac18c 100644 --- a/__tests__/toolchains.test.ts +++ b/__tests__/toolchains.test.ts @@ -143,7 +143,20 @@ describe('toolchains tests', () => { `; const result = ` - + + + jdk + + 17 + Eclipse Temurin + temurin_17 + + + /opt/hostedtoolcache/Java_Temurin-Hotspot_jdk/17.0.1-12/x64 + + jdk @@ -155,6 +168,68 @@ describe('toolchains tests', () => { /opt/jdk/sun/1.6 +`; + + fs.mkdirSync(m2Dir, {recursive: true}); + fs.writeFileSync(toolchainsFile, originalFile); + expect(fs.existsSync(m2Dir)).toBe(true); + expect(fs.existsSync(toolchainsFile)).toBe(true); + + await toolchains.createToolchainsSettings({ + jdkInfo, + settingsDirectory: m2Dir, + overwriteSettings: true + }); + + expect(fs.existsSync(m2Dir)).toBe(true); + expect(fs.existsSync(toolchainsFile)).toBe(true); + expect(fs.readFileSync(toolchainsFile, 'utf-8')).toEqual( + toolchains.generateToolchainDefinition( + originalFile, + jdkInfo.version, + jdkInfo.vendor, + jdkInfo.id, + jdkInfo.jdkHome + ) + ); + expect( + toolchains.generateToolchainDefinition( + originalFile, + jdkInfo.version, + jdkInfo.vendor, + jdkInfo.id, + jdkInfo.jdkHome + ) + ).toEqual(result); + }, 100000); + + it('does not discard custom elements in existing toolchain definitions', async () => { + const jdkInfo = { + version: '17', + vendor: 'Eclipse Temurin', + id: 'temurin_17', + jdkHome: '/opt/hostedtoolcache/Java_Temurin-Hotspot_jdk/17.0.1-12/x64' + }; + + const originalFile = ` + + jdk + + 1.6 + Sun + sun_1.6 + foo + + + /opt/jdk/sun/1.6 + /usr/local/bin/bash + + + `; + const result = ` + jdk @@ -166,6 +241,544 @@ describe('toolchains tests', () => { /opt/hostedtoolcache/Java_Temurin-Hotspot_jdk/17.0.1-12/x64 + + jdk + + 1.6 + Sun + sun_1.6 + foo + + + /opt/jdk/sun/1.6 + /usr/local/bin/bash + + +`; + + fs.mkdirSync(m2Dir, {recursive: true}); + fs.writeFileSync(toolchainsFile, originalFile); + expect(fs.existsSync(m2Dir)).toBe(true); + expect(fs.existsSync(toolchainsFile)).toBe(true); + + await toolchains.createToolchainsSettings({ + jdkInfo, + settingsDirectory: m2Dir, + overwriteSettings: true + }); + + expect(fs.existsSync(m2Dir)).toBe(true); + expect(fs.existsSync(toolchainsFile)).toBe(true); + expect(fs.readFileSync(toolchainsFile, 'utf-8')).toEqual( + toolchains.generateToolchainDefinition( + originalFile, + jdkInfo.version, + jdkInfo.vendor, + jdkInfo.id, + jdkInfo.jdkHome + ) + ); + expect( + toolchains.generateToolchainDefinition( + originalFile, + jdkInfo.version, + jdkInfo.vendor, + jdkInfo.id, + jdkInfo.jdkHome + ) + ).toEqual(result); + }, 100000); + + it('does not discard existing, custom toolchain definitions', async () => { + const jdkInfo = { + version: '17', + vendor: 'Eclipse Temurin', + id: 'temurin_17', + jdkHome: '/opt/hostedtoolcache/Java_Temurin-Hotspot_jdk/17.0.1-12/x64' + }; + + const originalFile = ` + + foo + + baz + + + /usr/local/bin/foo + + + `; + const result = ` + + + jdk + + 17 + Eclipse Temurin + temurin_17 + + + /opt/hostedtoolcache/Java_Temurin-Hotspot_jdk/17.0.1-12/x64 + + + + foo + + baz + + + /usr/local/bin/foo + + +`; + + fs.mkdirSync(m2Dir, {recursive: true}); + fs.writeFileSync(toolchainsFile, originalFile); + expect(fs.existsSync(m2Dir)).toBe(true); + expect(fs.existsSync(toolchainsFile)).toBe(true); + + await toolchains.createToolchainsSettings({ + jdkInfo, + settingsDirectory: m2Dir, + overwriteSettings: true + }); + + expect(fs.existsSync(m2Dir)).toBe(true); + expect(fs.existsSync(toolchainsFile)).toBe(true); + expect(fs.readFileSync(toolchainsFile, 'utf-8')).toEqual( + toolchains.generateToolchainDefinition( + originalFile, + jdkInfo.version, + jdkInfo.vendor, + jdkInfo.id, + jdkInfo.jdkHome + ) + ); + expect( + toolchains.generateToolchainDefinition( + originalFile, + jdkInfo.version, + jdkInfo.vendor, + jdkInfo.id, + jdkInfo.jdkHome + ) + ).toEqual(result); + }, 100000); + + it('does not duplicate existing toolchain definitions', async () => { + const jdkInfo = { + version: '17', + vendor: 'Eclipse Temurin', + id: 'temurin_17', + jdkHome: '/opt/hostedtoolcache/Java_Temurin-Hotspot_jdk/17.0.1-12/x64' + }; + + const originalFile = ` + + jdk + + 17 + Eclipse Temurin + temurin_17 + + + /opt/hostedtoolcache/Java_Temurin-Hotspot_jdk/17.0.1-12/x64 + + + `; + const result = ` + + + jdk + + 17 + Eclipse Temurin + temurin_17 + + + /opt/hostedtoolcache/Java_Temurin-Hotspot_jdk/17.0.1-12/x64 + + +`; + + fs.mkdirSync(m2Dir, {recursive: true}); + fs.writeFileSync(toolchainsFile, originalFile); + expect(fs.existsSync(m2Dir)).toBe(true); + expect(fs.existsSync(toolchainsFile)).toBe(true); + + await toolchains.createToolchainsSettings({ + jdkInfo, + settingsDirectory: m2Dir, + overwriteSettings: true + }); + + expect(fs.existsSync(m2Dir)).toBe(true); + expect(fs.existsSync(toolchainsFile)).toBe(true); + expect(fs.readFileSync(toolchainsFile, 'utf-8')).toEqual( + toolchains.generateToolchainDefinition( + originalFile, + jdkInfo.version, + jdkInfo.vendor, + jdkInfo.id, + jdkInfo.jdkHome + ) + ); + expect( + toolchains.generateToolchainDefinition( + originalFile, + jdkInfo.version, + jdkInfo.vendor, + jdkInfo.id, + jdkInfo.jdkHome + ) + ).toEqual(result); + }, 100000); + + it('does not duplicate existing toolchain definitions if multiple exist', async () => { + const jdkInfo = { + version: '17', + vendor: 'Eclipse Temurin', + id: 'temurin_17', + jdkHome: '/opt/hostedtoolcache/Java_Temurin-Hotspot_jdk/17.0.1-12/x64' + }; + + const originalFile = ` + + jdk + + 1.6 + Sun + sun_1.6 + + + /opt/jdk/sun/1.6 + + + + jdk + + 17 + Eclipse Temurin + temurin_17 + + + /opt/hostedtoolcache/Java_Temurin-Hotspot_jdk/17.0.1-12/x64 + + + `; + const result = ` + + + jdk + + 17 + Eclipse Temurin + temurin_17 + + + /opt/hostedtoolcache/Java_Temurin-Hotspot_jdk/17.0.1-12/x64 + + + + jdk + + 1.6 + Sun + sun_1.6 + + + /opt/jdk/sun/1.6 + + +`; + + fs.mkdirSync(m2Dir, {recursive: true}); + fs.writeFileSync(toolchainsFile, originalFile); + expect(fs.existsSync(m2Dir)).toBe(true); + expect(fs.existsSync(toolchainsFile)).toBe(true); + + await toolchains.createToolchainsSettings({ + jdkInfo, + settingsDirectory: m2Dir, + overwriteSettings: true + }); + + expect(fs.existsSync(m2Dir)).toBe(true); + expect(fs.existsSync(toolchainsFile)).toBe(true); + expect(fs.readFileSync(toolchainsFile, 'utf-8')).toEqual( + toolchains.generateToolchainDefinition( + originalFile, + jdkInfo.version, + jdkInfo.vendor, + jdkInfo.id, + jdkInfo.jdkHome + ) + ); + expect( + toolchains.generateToolchainDefinition( + originalFile, + jdkInfo.version, + jdkInfo.vendor, + jdkInfo.id, + jdkInfo.jdkHome + ) + ).toEqual(result); + }, 100000); + + it('handles an empty list of existing toolchains correctly', async () => { + const jdkInfo = { + version: '17', + vendor: 'Eclipse Temurin', + id: 'temurin_17', + jdkHome: '/opt/hostedtoolcache/Java_Temurin-Hotspot_jdk/17.0.1-12/x64' + }; + + const originalFile = ` + `; + const result = ` + + + jdk + + 17 + Eclipse Temurin + temurin_17 + + + /opt/hostedtoolcache/Java_Temurin-Hotspot_jdk/17.0.1-12/x64 + + +`; + + fs.mkdirSync(m2Dir, {recursive: true}); + fs.writeFileSync(toolchainsFile, originalFile); + expect(fs.existsSync(m2Dir)).toBe(true); + expect(fs.existsSync(toolchainsFile)).toBe(true); + + await toolchains.createToolchainsSettings({ + jdkInfo, + settingsDirectory: m2Dir, + overwriteSettings: true + }); + + expect(fs.existsSync(m2Dir)).toBe(true); + expect(fs.existsSync(toolchainsFile)).toBe(true); + expect(fs.readFileSync(toolchainsFile, 'utf-8')).toEqual( + toolchains.generateToolchainDefinition( + originalFile, + jdkInfo.version, + jdkInfo.vendor, + jdkInfo.id, + jdkInfo.jdkHome + ) + ); + expect( + toolchains.generateToolchainDefinition( + originalFile, + jdkInfo.version, + jdkInfo.vendor, + jdkInfo.id, + jdkInfo.jdkHome + ) + ).toEqual(result); + }, 100000); + + it('handles an empty existing toolchains.xml correctly', async () => { + const jdkInfo = { + version: '17', + vendor: 'Eclipse Temurin', + id: 'temurin_17', + jdkHome: '/opt/hostedtoolcache/Java_Temurin-Hotspot_jdk/17.0.1-12/x64' + }; + + const originalFile = ``; + const result = ` + + + jdk + + 17 + Eclipse Temurin + temurin_17 + + + /opt/hostedtoolcache/Java_Temurin-Hotspot_jdk/17.0.1-12/x64 + + +`; + + fs.mkdirSync(m2Dir, {recursive: true}); + fs.writeFileSync(toolchainsFile, originalFile); + expect(fs.existsSync(m2Dir)).toBe(true); + expect(fs.existsSync(toolchainsFile)).toBe(true); + + await toolchains.createToolchainsSettings({ + jdkInfo, + settingsDirectory: m2Dir, + overwriteSettings: true + }); + + expect(fs.existsSync(m2Dir)).toBe(true); + expect(fs.existsSync(toolchainsFile)).toBe(true); + expect(fs.readFileSync(toolchainsFile, 'utf-8')).toEqual( + toolchains.generateToolchainDefinition( + originalFile, + jdkInfo.version, + jdkInfo.vendor, + jdkInfo.id, + jdkInfo.jdkHome + ) + ); + expect( + toolchains.generateToolchainDefinition( + originalFile, + jdkInfo.version, + jdkInfo.vendor, + jdkInfo.id, + jdkInfo.jdkHome + ) + ).toEqual(result); + }, 100000); + + it('preserves custom root attributes on existing toolchains.xml', async () => { + const jdkInfo = { + version: '17', + vendor: 'Eclipse Temurin', + id: 'temurin_17', + jdkHome: '/opt/hostedtoolcache/Java_Temurin-Hotspot_jdk/17.0.1-12/x64' + }; + + const originalFile = ` + + jdk + + 1.6 + Sun + sun_1.6 + + + /opt/jdk/sun/1.6 + + + `; + const result = ` + + + jdk + + 17 + Eclipse Temurin + temurin_17 + + + /opt/hostedtoolcache/Java_Temurin-Hotspot_jdk/17.0.1-12/x64 + + + + jdk + + 1.6 + Sun + sun_1.6 + + + /opt/jdk/sun/1.6 + + +`; + + fs.mkdirSync(m2Dir, {recursive: true}); + fs.writeFileSync(toolchainsFile, originalFile); + expect(fs.existsSync(m2Dir)).toBe(true); + expect(fs.existsSync(toolchainsFile)).toBe(true); + + await toolchains.createToolchainsSettings({ + jdkInfo, + settingsDirectory: m2Dir, + overwriteSettings: true + }); + + expect(fs.existsSync(m2Dir)).toBe(true); + expect(fs.existsSync(toolchainsFile)).toBe(true); + expect(fs.readFileSync(toolchainsFile, 'utf-8')).toEqual( + toolchains.generateToolchainDefinition( + originalFile, + jdkInfo.version, + jdkInfo.vendor, + jdkInfo.id, + jdkInfo.jdkHome + ) + ); + expect( + toolchains.generateToolchainDefinition( + originalFile, + jdkInfo.version, + jdkInfo.vendor, + jdkInfo.id, + jdkInfo.jdkHome + ) + ).toEqual(result); + }, 100000); + + it('keeps partially-formed jdk toolchains without an id instead of crashing', async () => { + const jdkInfo = { + version: '17', + vendor: 'Eclipse Temurin', + id: 'temurin_17', + jdkHome: '/opt/hostedtoolcache/Java_Temurin-Hotspot_jdk/17.0.1-12/x64' + }; + + const originalFile = ` + + jdk + + 1.6 + Sun + + + /opt/jdk/sun/1.6 + + + `; + const result = ` + + + jdk + + 17 + Eclipse Temurin + temurin_17 + + + /opt/hostedtoolcache/Java_Temurin-Hotspot_jdk/17.0.1-12/x64 + + + + jdk + + 1.6 + Sun + + + /opt/jdk/sun/1.6 + + `; fs.mkdirSync(m2Dir, {recursive: true}); diff --git a/dist/setup/index.js b/dist/setup/index.js index 0e40385c..af458191 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -81506,46 +81506,66 @@ function createToolchainsSettings({ jdkInfo, settingsDirectory, overwriteSetting exports.createToolchainsSettings = createToolchainsSettings; // only exported for testing purposes function generateToolchainDefinition(original, version, vendor, id, jdkHome) { - let xmlObj; + let jsToolchains = [ + { + type: 'jdk', + provides: { + version: `${version}`, + vendor: `${vendor}`, + id: `${id}` + }, + configuration: { + jdkHome: `${jdkHome}` + } + } + ]; + // default root attributes, used when the existing file does not declare its own + let rootAttributes = { + '@xmlns': 'http://maven.apache.org/TOOLCHAINS/1.1.0', + '@xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance', + '@xsi:schemaLocation': 'http://maven.apache.org/TOOLCHAINS/1.1.0 https://maven.apache.org/xsd/toolchains-1.1.0.xsd' + }; if (original === null || original === void 0 ? void 0 : original.length) { - xmlObj = (0, xmlbuilder2_1.create)(original) + // convert existing toolchains into TS native objects for better handling + // xmlbuilder2 will convert the document into a `{toolchains: { toolchain: [] | {} }}` structure + // instead of the desired `toolchains: [{}]` one or simply `[{}]` + const jsObj = (0, xmlbuilder2_1.create)(original) .root() - .ele({ - toolchain: { - type: 'jdk', - provides: { - version: `${version}`, - vendor: `${vendor}`, - id: `${id}` - }, - configuration: { - jdkHome: `${jdkHome}` + .toObject(); + if (jsObj.toolchains) { + // preserve the existing root attributes (xmlns, schemaLocation, …) so we don't + // silently rewrite user-managed metadata or change the effective XML namespace; + // xmlbuilder2 exposes attributes as `@`-prefixed keys on the element object + const existingAttributes = Object.fromEntries(Object.entries(jsObj.toolchains).filter(([key]) => key.startsWith('@'))); + // fall back to the defaults only for attributes the existing file is missing + rootAttributes = Object.assign(Object.assign({}, rootAttributes), existingAttributes); + if (jsObj.toolchains.toolchain) { + // in case only a single child exists xmlbuilder2 will not create an array and using verbose = true equally doesn't work here + // See https://oozcitak.github.io/xmlbuilder2/serialization.html#js-object-and-map-serializers for details + if (Array.isArray(jsObj.toolchains.toolchain)) { + jsToolchains.push(...jsObj.toolchains.toolchain); + } + else { + jsToolchains.push(jsObj.toolchains.toolchain); } } + } + // remove potential duplicates based on type & id (which should be a unique combination); + // self.findIndex will only return the first occurrence, ensuring duplicates are skipped + jsToolchains = jsToolchains.filter((value, index, self) => { + var _a; + // ensure non-jdk toolchains are kept in the results, we must not touch them because they belong to the user + return value.type !== 'jdk' || + // keep toolchains that lack a usable string id (e.g. partially-formed user files); + // we cannot safely deduplicate them and must not crash while reading them + typeof ((_a = value.provides) === null || _a === void 0 ? void 0 : _a.id) !== 'string' || + index === + self.findIndex(t => { var _a, _b; return t.type === value.type && ((_a = t.provides) === null || _a === void 0 ? void 0 : _a.id) === ((_b = value.provides) === null || _b === void 0 ? void 0 : _b.id); }); }); } - else - xmlObj = (0, xmlbuilder2_1.create)({ - toolchains: { - '@xmlns': 'http://maven.apache.org/TOOLCHAINS/1.1.0', - '@xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance', - '@xsi:schemaLocation': 'http://maven.apache.org/TOOLCHAINS/1.1.0 https://maven.apache.org/xsd/toolchains-1.1.0.xsd', - toolchain: [ - { - type: 'jdk', - provides: { - version: `${version}`, - vendor: `${vendor}`, - id: `${id}` - }, - configuration: { - jdkHome: `${jdkHome}` - } - } - ] - } - }); - return xmlObj.end({ + return (0, xmlbuilder2_1.create)({ + toolchains: Object.assign(Object.assign({}, rootAttributes), { toolchain: jsToolchains }) + }).end({ format: 'xml', wellFormed: false, headless: false, diff --git a/src/toolchains.ts b/src/toolchains.ts index 77cae83f..a94a5630 100644 --- a/src/toolchains.ts +++ b/src/toolchains.ts @@ -83,47 +83,76 @@ export function generateToolchainDefinition( id: string, jdkHome: string ) { - let xmlObj; - if (original?.length) { - xmlObj = xmlCreate(original) - .root() - .ele({ - toolchain: { - type: 'jdk', - provides: { - version: `${version}`, - vendor: `${vendor}`, - id: `${id}` - }, - configuration: { - jdkHome: `${jdkHome}` - } - } - }); - } else - xmlObj = xmlCreate({ - toolchains: { - '@xmlns': 'http://maven.apache.org/TOOLCHAINS/1.1.0', - '@xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance', - '@xsi:schemaLocation': - 'http://maven.apache.org/TOOLCHAINS/1.1.0 https://maven.apache.org/xsd/toolchains-1.1.0.xsd', - toolchain: [ - { - type: 'jdk', - provides: { - version: `${version}`, - vendor: `${vendor}`, - id: `${id}` - }, - configuration: { - jdkHome: `${jdkHome}` - } - } - ] + let jsToolchains: Toolchain[] = [ + { + type: 'jdk', + provides: { + version: `${version}`, + vendor: `${vendor}`, + id: `${id}` + }, + configuration: { + jdkHome: `${jdkHome}` } - }); + } + ]; + // default root attributes, used when the existing file does not declare its own + let rootAttributes: Record = { + '@xmlns': 'http://maven.apache.org/TOOLCHAINS/1.1.0', + '@xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance', + '@xsi:schemaLocation': + 'http://maven.apache.org/TOOLCHAINS/1.1.0 https://maven.apache.org/xsd/toolchains-1.1.0.xsd' + }; + if (original?.length) { + // convert existing toolchains into TS native objects for better handling + // xmlbuilder2 will convert the document into a `{toolchains: { toolchain: [] | {} }}` structure + // instead of the desired `toolchains: [{}]` one or simply `[{}]` + const jsObj = xmlCreate(original) + .root() + .toObject() as unknown as ExtractedToolchains; + if (jsObj.toolchains) { + // preserve the existing root attributes (xmlns, schemaLocation, …) so we don't + // silently rewrite user-managed metadata or change the effective XML namespace; + // xmlbuilder2 exposes attributes as `@`-prefixed keys on the element object + const existingAttributes = Object.fromEntries( + Object.entries(jsObj.toolchains).filter(([key]) => key.startsWith('@')) + ) as Record; + // fall back to the defaults only for attributes the existing file is missing + rootAttributes = {...rootAttributes, ...existingAttributes}; - return xmlObj.end({ + if (jsObj.toolchains.toolchain) { + // in case only a single child exists xmlbuilder2 will not create an array and using verbose = true equally doesn't work here + // See https://oozcitak.github.io/xmlbuilder2/serialization.html#js-object-and-map-serializers for details + if (Array.isArray(jsObj.toolchains.toolchain)) { + jsToolchains.push(...jsObj.toolchains.toolchain); + } else { + jsToolchains.push(jsObj.toolchains.toolchain); + } + } + } + + // remove potential duplicates based on type & id (which should be a unique combination); + // self.findIndex will only return the first occurrence, ensuring duplicates are skipped + jsToolchains = jsToolchains.filter( + (value, index, self) => + // ensure non-jdk toolchains are kept in the results, we must not touch them because they belong to the user + value.type !== 'jdk' || + // keep toolchains that lack a usable string id (e.g. partially-formed user files); + // we cannot safely deduplicate them and must not crash while reading them + typeof value.provides?.id !== 'string' || + index === + self.findIndex( + t => t.type === value.type && t.provides?.id === value.provides?.id + ) + ); + } + + return xmlCreate({ + toolchains: { + ...rootAttributes, + toolchain: jsToolchains + } + }).end({ format: 'xml', wellFormed: false, headless: false, @@ -166,3 +195,24 @@ async function writeToolchainsFileToDisk( flag: 'w' }); } + +interface ExtractedToolchains { + toolchains: { + // root attributes such as xmlns / schemaLocation are exposed as `@`-prefixed keys + [attribute: `@${string}`]: string; + toolchain?: Toolchain[] | Toolchain; + }; +} + +// Toolchain type definition according to Maven Toolchains XSD 1.1.0 +interface Toolchain { + type: string; + provides: + | { + version: string; + vendor: string; + id: string; + } + | any; + configuration: any; +}