Skip to content

Import Maven signing keys into an isolated GPG home - #1214

Merged
brunoborges merged 5 commits into
actions:mainfrom
jdubois:jdubois-fix-isolated-gpg-home
Aug 5, 2026
Merged

Import Maven signing keys into an isolated GPG home#1214
brunoborges merged 5 commits into
actions:mainfrom
jdubois:jdubois-fix-isolated-gpg-home

Conversation

@jdubois

@jdubois jdubois commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Summary

  • create a restrictive, action-owned temporary GPG home for Maven signing keys and export it through GNUPGHOME
  • remove unique restricted key files on every import path and delete only the owned GPG-home directory in the post action
  • cover import failures, pre-existing key material, multi-key input, repeated invocations, missing state, and Windows/MSYS path conversion
  • document isolated key handling and regenerate the setup and cleanup bundles

Validation

Closes #1211

jdubois and others added 3 commits August 5, 2026 15:14
Import signing keys into an action-owned temporary GPG home, export GNUPGHOME, and remove the owned directory in the post action. Cover import failure, multiple keys and invocations, unrelated keyrings, missing state, and Windows path conversion.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Account for isolated GPG-home cleanup when cache saving is disabled.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Apply repository formatting and commit the setup and cleanup bundles produced by the validated Node 24 build.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI lite review requested due to automatic review settings August 5, 2026 13:19
@jdubois
jdubois requested a review from a team as a code owner August 5, 2026 13:19

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates actions/setup-java to import Maven signing keys into an action-owned, isolated temporary GPG home (exported via GNUPGHOME) and to clean up by deleting the owned GPG home directory instead of deleting fingerprints from the runner’s default keyring.

Changes:

  • Create a per-invocation temporary GPG home with restrictive permissions and import gpg-private-key into that isolated keyring.
  • Persist the owned GPG home path as post-action state and remove the directory during cleanup with ownership/safety checks.
  • Expand test coverage and update docs/action metadata to reflect isolated key handling; regenerate dist/ bundles.
Show a summary per file
File Description
src/gpg.ts Adds isolated GPG home creation, key import into that home, and safe removal of action-owned homes.
src/constants.ts Switches cleanup state from fingerprint-based to gpg-home.
src/cleanup-java.ts Cleans up by removing the persisted isolated GPG home directory instead of deleting keys by fingerprint.
src/auth.ts Imports key into isolated home, saves gpg-home state, exports GNUPGHOME.
README.md Updates input description to reflect isolated temporary keyring behavior.
docs/advanced-usage.md Updates advanced docs to describe isolated keyring import and cleanup behavior.
action.yml Updates gpg-private-key input description to mention isolated temporary keyring.
tests/gpg.test.ts Adds coverage for isolated home creation, import failure cleanup, multi-key input, and safe home removal.
tests/distributors/temurin-installer.test.ts Updates GPG mock API to match new cleanup function name.
tests/distributors/microsoft-installer.test.ts Updates GPG mock API to match new cleanup function name.
tests/cleanup-java.test.ts Adds coverage for isolated home cleanup, idempotency, and missing state behavior.
tests/auth.test.ts Adds coverage for persisting/exporting isolated home and cleanup on export failure.
dist/setup/index.js Regenerated bundle reflecting new state constant and GPG isolation changes.
dist/setup/81.index.js Regenerated setup bundle chunk reflecting new GPG home handling and exports.
dist/setup/463.index.js Regenerated setup bundle chunk reflecting new GPG home handling and exports.
dist/setup/220.index.js Regenerated setup bundle chunk reflecting new GPG home handling and exports.
dist/cleanup/index.js Regenerated cleanup bundle reflecting new state constant and cleanup behavior.

Review details

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 12/17 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment thread src/auth.ts
@brunoborges

Copy link
Copy Markdown
Contributor

Nice work — this matches how I'd approach #1211 almost exactly (isolated home, 0600 key file with wx, no fingerprint parsing, state-driven cleanup, saveState before exportVariable with rollback). Two things I ran into implementing the same fix that might be worth folding in:

1. gpg-agent outlives the home

removeGpgHome goes straight to io.rmRF. Importing a secret key starts a gpg-agent bound to that --homedir. Two consequences:

  • the agent can outlive the job with key material still cached, which is the exact leak class the issue is about on persistent self-hosted runners;
  • on Windows the agent holds open handles under the home, so rmRF can fail — and since removeGpgHome failure calls setFailed, that turns into a red job at the end of an otherwise green run.

Best-effort kill before removal handles both:

try {
  await exec.exec(
    'gpgconf',
    ['--homedir', toGpgPath(resolvedGpgHome), '--kill', 'gpg-agent'],
    {silent: true, ignoreReturnCode: true}
  );
} catch {
  // gpgconf may not be present; removal is still attempted
}

await io.rmRF(resolvedGpgHome);

2. GNUPGHOME value on Windows

auth.ts exports the native path, while the action's own gpg invocations use toGpgPath(gpgHome) for --homedir. That asymmetry may be deliberate, but it's worth pinning down: GNUPGHOME is read by whichever gpg the user's Maven ends up invoking, and the MSYS2/Git-bundled gpg on the Windows runners and native Gpg4win don't interpret /d/a/_temp/... vs D:\a\_temp\... the same way. I don't think either choice is safe to assume without an actual Windows run exercising a real signing step against both — has that been tested end to end on windows-latest?

The removeGpgHome ownership guard (dirname === temp && basename.startsWith(prefix)) is a good call — I'd adopted the same idea after noticing that cleanup otherwise rmRFs whatever the state value happens to contain.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@brunoborges

Copy link
Copy Markdown
Contributor

Addressed both cleanup follow-ups in 53f7386: removeGpgHome now best-effort kills the isolated home’s gpg-agent via gpgconf before deletion (while still deleting if gpgconf is unavailable), and Windows exports a POSIX-compatible GNUPGHOME while preserving the native path in action state. Added regression coverage and regenerated the action bundles.

@brunoborges
brunoborges merged commit 634b0f0 into actions:main Aug 5, 2026
84 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Import Maven signing keys into an isolated temporary GPG home

3 participants