Skip to content

Commit 7d48588

Browse files
brunoborgesCopilot
andauthored
Use gpg.passphraseEnvName instead of the deprecated gpg.passphrase server (#1123)
* Use gpg.passphraseEnvName instead of gpg.passphrase server The maven-gpg-plugin's `gpg.passphrase`/`passphraseServerId` mechanism is deprecated and fails when the plugin's `bestPractices` mode is enabled. Stop writing the `gpg.passphrase` server to settings.xml and instead set `gpg.passphraseEnvName` via an active profile when the configured passphrase env var name differs from the plugin default (MAVEN_GPG_PASSPHRASE). The default `gpg-passphrase` input value (GPG_PASSPHRASE) is unchanged, so the plugin reads the same environment variable as before. Fixes #760 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * Fix settings.xml publishing validation Update the publishing e2e check to assert the settings.xml generated when gpg-passphrase is MAVEN_GPG_PASSPHRASE. In that default case the action no longer writes a gpg.passphrase server entry. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 7d0a510e-aebf-4ec4-a667-efeb3e4edeb1 * Default gpg-passphrase to MAVEN_GPG_PASSPHRASE Align the default `gpg-passphrase` input value with the maven-gpg-plugin default environment variable name (MAVEN_GPG_PASSPHRASE). With this default, setup-java writes no extra GPG configuration to settings.xml and the plugin reads the passphrase from MAVEN_GPG_PASSPHRASE out of the box. Also document that reading the passphrase from an environment variable via `gpg.passphraseEnvName` requires maven-gpg-plugin 3.2.0 or newer. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 7d0a510e-aebf-4ec4-a667-efeb3e4edeb1 * Document gpg-passphrase breaking change in V6 Add a "Breaking changes in V6" section to the README covering the switch to gpg.passphraseEnvName, the new MAVEN_GPG_PASSPHRASE default, and the maven-gpg-plugin 3.2.0+ requirement. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 7d0a510e-aebf-4ec4-a667-efeb3e4edeb1 * Keep GPG_PASSPHRASE default for v5 compatibility Revert the gpg-passphrase input default back to GPG_PASSPHRASE so existing v5 workflows that set the GPG_PASSPHRASE environment variable keep working without changes. setup-java writes gpg.passphraseEnvName=GPG_PASSPHRASE into an active profile, so the maven-gpg-plugin reads the same variable as before. The only remaining compatibility requirement is maven-gpg-plugin 3.2.0+, which is documented in the README and advanced usage guide. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 7d0a510e-aebf-4ec4-a667-efeb3e4edeb1 * Clarify GPG passphrase profile compatibility Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 7d0a510e-aebf-4ec4-a667-efeb3e4edeb1 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
1 parent c3568cc commit 7d48588

8 files changed

Lines changed: 138 additions & 25 deletions

File tree

.github/workflows/e2e-publishing.yml

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,25 @@ jobs:
4646
$xmlPath = Join-Path $HOME ".m2" "settings.xml"
4747
Get-Content $xmlPath | ForEach-Object { Write-Host $_ }
4848
49-
[xml]$xml = Get-Content $xmlPath
50-
$servers = $xml.settings.servers.server
51-
if (($servers[0].id -ne 'maven') -or ($servers[0].username -ne '${env.MAVEN_USERNAME}') -or ($servers[0].password -ne '${env.MAVEN_CENTRAL_TOKEN}')) {
52-
throw "Generated XML file is incorrect"
53-
}
49+
$content = [System.IO.File]::ReadAllText($xmlPath)
50+
$expected = @(
51+
'<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"'
52+
' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"'
53+
' xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd">'
54+
' <interactiveMode>false</interactiveMode>'
55+
' <servers>'
56+
' <server>'
57+
' <id>maven</id>'
58+
' <username>${env.MAVEN_USERNAME}</username>'
59+
' <password>${env.MAVEN_CENTRAL_TOKEN}</password>'
60+
' </server>'
61+
' </servers>'
62+
'</settings>'
63+
) -join "`n"
5464
55-
if (($servers[1].id -ne 'gpg.passphrase') -or ($servers[1].passphrase -ne '${env.MAVEN_GPG_PASSPHRASE}')) {
65+
if ($content -ne $expected) {
66+
Write-Host "Expected settings.xml:"
67+
$expected -split "`n" | ForEach-Object { Write-Host $_ }
5668
throw "Generated XML file is incorrect"
5769
}
5870

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ This action allows you to work with Java and Scala projects.
2222

2323
- **Migrated to ESM** to enable support for the latest `@actions/*` package versions. This is an internal implementation change only. No changes are required to your workflow configuration, and the action's behavior is unchanged. Existing workflows continue to work as before.
2424

25+
## Breaking changes in V6
26+
27+
- **The GPG passphrase is now passed to the Maven GPG Plugin through an environment variable (`gpg.passphraseEnvName`) instead of the deprecated `gpg.passphrase` server in `settings.xml`.** The `gpg-passphrase` input and its default (`GPG_PASSPHRASE`) are unchanged, so if you already set that environment variable in your build step your workflow keeps working. However, this now requires `maven-gpg-plugin` **3.2.0 or newer**; older versions do not honor `gpg.passphraseEnvName` and, because the `gpg.passphrase` server is no longer written, will not pick up the passphrase. Upgrade the plugin to 3.2.0+.
28+
29+
See [GPG](docs/advanced-usage.md#gpg) for details.
30+
2531
## Breaking changes in V5
2632

2733
- Upgraded action from node20 to node24

__tests__/auth.test.ts

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -228,9 +228,40 @@ describe('auth tests', () => {
228228
<username>\${env.${username}}</username>
229229
<password>\${env.&amp;&lt;&gt;"''"&gt;&lt;&amp;}</password>
230230
</server>
231+
</servers>
232+
<profiles>
233+
<profile>
234+
<id>setup-java-gpg</id>
235+
<properties>
236+
<gpg.passphraseEnvName>${gpgPassphrase}</gpg.passphraseEnvName>
237+
</properties>
238+
</profile>
239+
</profiles>
240+
<activeProfiles>
241+
<activeProfile>setup-java-gpg</activeProfile>
242+
</activeProfiles>
243+
</settings>`;
244+
245+
expect(auth.generate(id, username, password, gpgPassphrase)).toEqual(
246+
expectedSettings
247+
);
248+
});
249+
250+
it('does not add a gpg profile when the passphrase env var is the maven-gpg-plugin default', () => {
251+
const id = 'packages';
252+
const username = 'USER';
253+
const password = '&<>"\'\'"><&';
254+
const gpgPassphrase = 'MAVEN_GPG_PASSPHRASE';
255+
256+
const expectedSettings = `<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
257+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
258+
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd">
259+
<interactiveMode>false</interactiveMode>
260+
<servers>
231261
<server>
232-
<id>gpg.passphrase</id>
233-
<passphrase>\${env.${gpgPassphrase}}</passphrase>
262+
<id>${id}</id>
263+
<username>\${env.${username}}</username>
264+
<password>\${env.&amp;&lt;&gt;"''"&gt;&lt;&amp;}</password>
234265
</server>
235266
</servers>
236267
</settings>`;

dist/cleanup/index.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95849,6 +95849,12 @@ const INPUT_GPG_PRIVATE_KEY = 'gpg-private-key';
9584995849
const INPUT_GPG_PASSPHRASE = 'gpg-passphrase';
9585095850
const INPUT_DEFAULT_GPG_PRIVATE_KEY = (/* unused pure expression or super */ null && (undefined));
9585195851
const INPUT_DEFAULT_GPG_PASSPHRASE = 'GPG_PASSPHRASE';
95852+
// The default name of the environment variable the maven-gpg-plugin reads the
95853+
// passphrase from (property `gpg.passphraseEnvName`). When the configured
95854+
// passphrase env var name matches this, no extra configuration is required.
95855+
const MAVEN_GPG_PASSPHRASE_DEFAULT_ENV = 'MAVEN_GPG_PASSPHRASE';
95856+
// Id of the settings.xml profile used to set `gpg.passphraseEnvName`.
95857+
const GPG_PASSPHRASE_PROFILE_ID = 'setup-java-gpg';
9585295858
const INPUT_CACHE = 'cache';
9585395859
const INPUT_CACHE_DEPENDENCY_PATH = 'cache-dependency-path';
9585495860
const INPUT_JOB_STATUS = 'job-status';

dist/setup/index.js

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73294,6 +73294,12 @@ const INPUT_GPG_PRIVATE_KEY = 'gpg-private-key';
7329473294
const INPUT_GPG_PASSPHRASE = 'gpg-passphrase';
7329573295
const INPUT_DEFAULT_GPG_PRIVATE_KEY = undefined;
7329673296
const INPUT_DEFAULT_GPG_PASSPHRASE = 'GPG_PASSPHRASE';
73297+
// The default name of the environment variable the maven-gpg-plugin reads the
73298+
// passphrase from (property `gpg.passphraseEnvName`). When the configured
73299+
// passphrase env var name matches this, no extra configuration is required.
73300+
const MAVEN_GPG_PASSPHRASE_DEFAULT_ENV = 'MAVEN_GPG_PASSPHRASE';
73301+
// Id of the settings.xml profile used to set `gpg.passphraseEnvName`.
73302+
const GPG_PASSPHRASE_PROFILE_ID = 'setup-java-gpg';
7329773303
const INPUT_CACHE = 'cache';
7329873304
const INPUT_CACHE_DEPENDENCY_PATH = 'cache-dependency-path';
7329973305
const constants_INPUT_JOB_STATUS = 'job-status';
@@ -127311,12 +127317,25 @@ function generate(id, username, password, gpgPassphrase) {
127311127317
}
127312127318
}
127313127319
};
127314-
if (gpgPassphrase) {
127315-
const gpgServer = {
127316-
id: 'gpg.passphrase',
127317-
passphrase: `\${env.${gpgPassphrase}}`
127320+
// The maven-gpg-plugin reads the passphrase from the environment variable
127321+
// named by the `gpg.passphraseEnvName` property (default MAVEN_GPG_PASSPHRASE).
127322+
// Only configure it when the requested env var name differs from that default;
127323+
// otherwise the plugin already reads the right variable and no extra settings
127324+
// are needed. Writing `gpg.passphrase` to settings.xml is deprecated and fails
127325+
// when the plugin's `bestPractices` mode is enabled.
127326+
if (gpgPassphrase &&
127327+
gpgPassphrase !== MAVEN_GPG_PASSPHRASE_DEFAULT_ENV) {
127328+
xmlObj.settings.profiles = {
127329+
profile: {
127330+
id: GPG_PASSPHRASE_PROFILE_ID,
127331+
properties: {
127332+
'gpg.passphraseEnvName': gpgPassphrase
127333+
}
127334+
}
127335+
};
127336+
xmlObj.settings.activeProfiles = {
127337+
activeProfile: GPG_PASSPHRASE_PROFILE_ID
127318127338
};
127319-
xmlObj.settings.servers.server.push(gpgServer);
127320127339
}
127321127340
return (0,lib/* create */.vt)(xmlObj).end({
127322127341
headless: true,

docs/advanced-usage.md

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -660,7 +660,9 @@ See the help docs on [Publishing a Package](https://help.github.com/en/github/ma
660660

661661
#### Legacy / alternative: let setup-java import the key
662662

663-
If you use `maven-gpg-plugin` older than 3.2.0, or you prefer signing with the `gpg` executable, you can let setup-java import the key instead by providing the `gpg-private-key` and `gpg-passphrase` inputs. The private key is written to a file in the runner's temp directory, imported into the GPG keychain, and the file is promptly removed before proceeding with the rest of the setup process. A cleanup step removes the imported private key from the GPG keychain after the job completes regardless of the job status. This ensures that the private key is no longer accessible on self-hosted runners and cannot "leak" between jobs (hosted runners are always clean instances).
663+
If you prefer signing with the `gpg` executable (for example because you are using `maven-gpg-plugin` older than 3.2.0), you can let setup-java import the key instead by providing the `gpg-private-key` and `gpg-passphrase` inputs. The private key is written to a file in the runner's temp directory, imported into the GPG keychain, and the file is promptly removed before proceeding with the rest of the setup process. A cleanup step removes the imported private key from the GPG keychain after the job completes regardless of the job status. This ensures that the private key is no longer accessible on self-hosted runners and cannot "leak" between jobs (hosted runners are always clean instances).
664+
665+
setup-java imports the key independently of the plugin version, but the generated passphrase profile described below uses `gpg.passphraseEnvName`, which requires `maven-gpg-plugin` 3.2.0 or newer. Since `gpg-passphrase` defaults to `GPG_PASSPHRASE`, setup-java writes that profile unless you override the input to `MAVEN_GPG_PASSPHRASE`.
664666

665667
```yaml
666668
- name: Set up Apache Maven Central
@@ -682,15 +684,29 @@ If you use `maven-gpg-plugin` older than 3.2.0, or you prefer signing with the `
682684
MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}
683685
```
684686

685-
With these inputs, setup-java adds a `gpg.passphrase` server to the generated `settings.xml`:
687+
The `gpg-passphrase` input is the **name of the environment variable** that holds the passphrase (not the passphrase itself). It defaults to `GPG_PASSPHRASE`. The [Maven GPG Plugin](https://maven.apache.org/plugins/maven-gpg-plugin/) reads the passphrase from the environment variable named by its `gpg.passphraseEnvName` property, whose own default is `MAVEN_GPG_PASSPHRASE`.
688+
689+
- If `gpg-passphrase` is `MAVEN_GPG_PASSPHRASE`, the plugin already reads that variable by default, so setup-java writes nothing extra to `settings.xml`.
690+
- Otherwise (including the default `GPG_PASSPHRASE`), setup-java configures `gpg.passphraseEnvName` through an active profile in the generated `settings.xml` so the plugin reads the passphrase from that variable. For the default `gpg-passphrase: GPG_PASSPHRASE`:
686691

687692
```xml
688-
<server>
689-
<id>gpg.passphrase</id>
690-
<passphrase>${env.MAVEN_GPG_PASSPHRASE}</passphrase>
691-
</server>
693+
<profiles>
694+
<profile>
695+
<id>setup-java-gpg</id>
696+
<properties>
697+
<gpg.passphraseEnvName>GPG_PASSPHRASE</gpg.passphraseEnvName>
698+
</properties>
699+
</profile>
700+
</profiles>
701+
<activeProfiles>
702+
<activeProfile>setup-java-gpg</activeProfile>
703+
</activeProfiles>
692704
```
693705

706+
> **Note:** Earlier versions of setup-java wrote a `gpg.passphrase` server to `settings.xml`. That mechanism is deprecated by the Maven GPG Plugin and fails when its `bestPractices` mode is enabled, so setup-java now relies on `gpg.passphraseEnvName` instead. The `gpg-passphrase` input and its `GPG_PASSPHRASE` default are unchanged, so existing workflows that set the `GPG_PASSPHRASE` environment variable keep working.
707+
708+
> **Compatibility note:** Reading the passphrase from an environment variable (`gpg.passphraseEnvName`) requires `maven-gpg-plugin` 3.2.0 or newer. Older versions do not honor this property and will not pick up the passphrase, because setup-java no longer writes the deprecated `gpg.passphrase` server to `settings.xml`. If you are pinned to `maven-gpg-plugin` older than 3.2.0, upgrade to 3.2.0+.
709+
694710
When signing with the `gpg` executable, the Maven GPG Plugin configuration in your `pom.xml` should contain the following structure to avoid possible issues like `Inappropriate ioctl for device` or `gpg: signing failed: No such file or directory`:
695711

696712
```xml
@@ -703,7 +719,7 @@ When signing with the `gpg` executable, the Maven GPG Plugin configuration in yo
703719
</configuration>
704720
```
705721

706-
GPG 2.1 requires `--pinentry-mode` to be set to `loopback` in order to pick up the `gpg.passphrase` value defined in Maven `settings.xml`.
722+
GPG 2.1 requires `--pinentry-mode` to be set to `loopback` in order to read the passphrase non-interactively.
707723

708724
***NOTE***: If, when using the default `gpg` signer, the error `gpg: Sorry, no terminal at all requested - can't get input` [is encountered](https://github.com/actions/setup-java/issues/554), please update the version of `maven-gpg-plugin` to 1.6 or higher.
709725

src/auth.ts

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,12 +93,27 @@ export function generate(
9393
}
9494
};
9595

96-
if (gpgPassphrase) {
97-
const gpgServer = {
98-
id: 'gpg.passphrase',
99-
passphrase: `\${env.${gpgPassphrase}}`
96+
// The maven-gpg-plugin reads the passphrase from the environment variable
97+
// named by the `gpg.passphraseEnvName` property (default MAVEN_GPG_PASSPHRASE).
98+
// Only configure it when the requested env var name differs from that default;
99+
// otherwise the plugin already reads the right variable and no extra settings
100+
// are needed. Writing `gpg.passphrase` to settings.xml is deprecated and fails
101+
// when the plugin's `bestPractices` mode is enabled.
102+
if (
103+
gpgPassphrase &&
104+
gpgPassphrase !== constants.MAVEN_GPG_PASSPHRASE_DEFAULT_ENV
105+
) {
106+
xmlObj.settings.profiles = {
107+
profile: {
108+
id: constants.GPG_PASSPHRASE_PROFILE_ID,
109+
properties: {
110+
'gpg.passphraseEnvName': gpgPassphrase
111+
}
112+
}
113+
};
114+
xmlObj.settings.activeProfiles = {
115+
activeProfile: constants.GPG_PASSPHRASE_PROFILE_ID
100116
};
101-
xmlObj.settings.servers.server.push(gpgServer);
102117
}
103118

104119
return xmlCreate(xmlObj).end({

src/constants.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,14 @@ export const INPUT_GPG_PASSPHRASE = 'gpg-passphrase';
2121
export const INPUT_DEFAULT_GPG_PRIVATE_KEY = undefined;
2222
export const INPUT_DEFAULT_GPG_PASSPHRASE = 'GPG_PASSPHRASE';
2323

24+
// The default name of the environment variable the maven-gpg-plugin reads the
25+
// passphrase from (property `gpg.passphraseEnvName`). When the configured
26+
// passphrase env var name matches this, no extra configuration is required.
27+
export const MAVEN_GPG_PASSPHRASE_DEFAULT_ENV = 'MAVEN_GPG_PASSPHRASE';
28+
29+
// Id of the settings.xml profile used to set `gpg.passphraseEnvName`.
30+
export const GPG_PASSPHRASE_PROFILE_ID = 'setup-java-gpg';
31+
2432
export const INPUT_CACHE = 'cache';
2533
export const INPUT_CACHE_DEPENDENCY_PATH = 'cache-dependency-path';
2634
export const INPUT_JOB_STATUS = 'job-status';

0 commit comments

Comments
 (0)