Skip to content

[build] sign Java artifacts in-process with in-memory PGP keys instead of gpg-agent - #18130

Merged
titusfortner merged 1 commit into
trunkfrom
java-in-memory-pgp-signing
Oct 7, 2026
Merged

titusfortner merged 1 commit into
trunkfrom
java-in-memory-pgp-signing

Conversation

@titusfortner

Copy link
Copy Markdown
Member

💥 What does this PR do?

  • Signs Java artifacts in-process through rules_jvm_external's in-memory PGP path instead of shelling out to a gpg-agent populated by crazy-max/ghaction-import-gpg.
  • Signs nightly Java snapshots too, so the release signing path runs daily instead of only at release time.

This prevents the error we had during the 4.50.0 release where Java publish failed partway through with gpg: signing failed: Inappropriate ioctl for device after gpg-agent dropped the preset passphrase.

🔧 Implementation Notes

  • java.rake derives the publisher's PGP_SIGNING_KEY/PGP_SIGNING_PWD from the existing GPG_PRIVATE_KEY/GPG_PASSPHRASE secrets, base64-encoding the key when it is armored, the same way Sonatype.load_credentials maps SEL_M2_USER to MAVEN_USER; a gpg binary is no longer needed anywhere in the release path.
  • The two secrets join the other publishing secrets in the bazel.yml job env, so the gpg-sign input is gone; only the nightly and release workflows inherit secrets.
  • The publisher signs with the keyring's primary key, which is sign-capable and is the key that has signed every release so far, so no new secret is needed.
  • Verified locally by publishing selenium-json to a file: repo with a throwaway key: the publisher logs in-memory signing and verification per artifact and gpg --verify accepts each .asc.

🤖 AI assistance

  • AI assisted (complete below)
    • Tool(s): Claude Code (Fable 5.1)
    • What was generated: the rules_jvm_external source review, the release-key inspection, the rake and workflow changes, the local dry run, and this description
    • I reviewed all AI output and can explain the change

🔄 Types of changes

  • Bug fix (backwards compatible)

@qodo-code-review

Copy link
Copy Markdown
Contributor

PR Summary by Qodo

Sign Java releases and nightly snapshots without gpg-agent

🐞 Bug fix ⚙️ Configuration changes 🕐 20-40 Minutes

Grey Divider

AI Description

• Move Java artifact signing in-process to avoid gpg-agent passphrase failures during publishing.
• Sign nightly snapshots as well as releases, exercising the signing path daily.
• Pass existing GPG secrets to the publisher and remove the workflow's GPG import step.
Diagram

graph TD
  W["Release and nightly"] --> B["Shared Bazel job"] --> R["Java release task"] --> P["Maven publisher"] --> M[("Sonatype repositories")]
  S["GPG secrets"] --> B
Loading
High-Level Assessment

Use the publisher's existing in-memory PGP path. Retaining external GPG with agent or loopback configuration would preserve another process-level signing dependency and would not address the failure as directly.

Files changed (3) +16 / -21

Bug fix (1) +14 / -9
java.rakeConfigure in-memory PGP signing for Java publishing +14/-9

Configure in-memory PGP signing for Java publishing

• Maps the existing GPG secrets to publisher credentials, base64-encoding an armored key, and requires them for both releases and nightlies. Enables in-memory signing, disables the external GPG path, and removes the gpg-binary check.

rake_tasks/java.rake

Other (2) +2 / -12
bazel.ymlExpose signing secrets without importing a GPG key +2/-11

Expose signing secrets without importing a GPG key

• Adds the existing private key and passphrase secrets to the reusable Bazel job environment. Removes its optional gpg-sign input and GPG-import action.

.github/workflows/bazel.yml

release.ymlRemove release-only GPG import request +0/-1

Remove release-only GPG import request

• Stops requesting the removed gpg-sign workflow input for Java publishing. Release signing now uses the same secret-based path as nightly publishing.

.github/workflows/release.yml

@selenium-ci selenium-ci added the B-build Includes scripting, bazel and CI integrations label Oct 6, 2026
@qodo-code-review

qodo-code-review Bot commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Remediation recommended

1. Non-Java jobs receive the signing key ✗ Dismissed
Description
The reusable Bazel job places GPG_PRIVATE_KEY and GPG_PASSPHRASE in job-wide environment
variables instead of supplying them only to Java publishing. Release and nightly publishing both
call that workflow with inherited secrets across language matrices, so non-Java commands and their
setup steps receive the Java private key and passphrase even when they do not publish Java
artifacts.
Code

.github/workflows/bazel.yml[R103-104]

+      GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
+      GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
Evidence
The added variables are declared at the reusable job's scope. Both publishing workflows invoke that
job with secrets: inherit for matrices containing Java and other languages; the reusable job also
runs setup and publish steps within that scope.

.github/workflows/bazel.yml[90-105]
.github/workflows/bazel.yml[172-190]
.github/workflows/bazel.yml[241-255]
.github/workflows/release.yml[139-164]
.github/workflows/nightly.yml[76-92]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The reusable Bazel workflow exposes the Java signing key and passphrase to every publishing language job, expanding access beyond Java publishing.

## Fix Focus Areas
- .github/workflows/bazel.yml[100-104]
- .github/workflows/release.yml[150-164]
- .github/workflows/nightly.yml[79-92]

## Recommended Fix
Add an explicit Java-signing input to the reusable workflow and conditionally populate the signing environment variables only for Java publish invocations. Set that input for Java in both the release and nightly callers.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
✅ Web pages:
  +20 more
Review mode: Auto: ⚖️ Balanced: Security-sensitive signing workflow and credential handling require careful single-pass review.

Grey Divider

Tip of the day
💡 Did you know, you can route each severity your way: inline, summary, both, or drop

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread .github/workflows/bazel.yml
@titusfortner
titusfortner merged commit f832d36 into trunk Oct 7, 2026
43 checks passed
@titusfortner
titusfortner deleted the java-in-memory-pgp-signing branch October 7, 2026 17:15
This was referenced Oct 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

B-build Includes scripting, bazel and CI integrations

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants