Skip to content

fix: pre-start gpg-agent for headless CI integration tests#1058

Merged
annejan merged 12 commits into
mainfrom
fix/integration-tests-ci-gpg-agent
Apr 19, 2026
Merged

fix: pre-start gpg-agent for headless CI integration tests#1058
annejan merged 12 commits into
mainfrom
fix/integration-tests-ci-gpg-agent

Conversation

@annejan
Copy link
Copy Markdown
Member

@annejan annejan commented Apr 19, 2026

User description

Summary

  • Writes gpg-agent.conf (allow-loopback-pinentry) and gpg.conf (pinentry-mode loopback) to the temp GNUPGHOME before any key operations
  • Explicitly launches gpg-agent via gpgconf --launch so all subsequent GPG subprocesses connect immediately instead of hanging

Test plan

  • Verify Ubuntu CI passes all 6 ImitatePass tests (previously 90s timeout)
  • Verify macOS CI passes all 6 ImitatePass tests (same issue)
  • Verify local run still passes

🤖 Generated with Claude Code


CodeAnt-AI Description

Prevent GPG integration tests from hanging in headless CI

What Changed

  • Integration tests now prepare GPG for headless runs before any key work starts, so CI no longer waits on missing PIN prompts or a late-starting agent
  • Insert failures now report the actual GPG error instead of only saying the expected success signal never arrived
  • CI now installs the GPG and pass-related tools needed for these integration tests on Linux and macOS

Impact

✅ Fewer CI test timeouts
✅ Reliable headless GPG test runs
✅ Clearer integration test failures

🔄 Retrigger CodeAnt AI Review

Details

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

Summary by CodeRabbit

  • Tests

    • Improved GPG integration tests for CI: non‑interactive agent startup, automatic test key setup and trust import, cleared signing-key state between tests, and clearer failure diagnostics for insert flows.
  • Chores

    • CI: conditional OS-specific installation of pass/pinentry when builds run.
    • .gitignore: ignore generated test binary.
  • Documentation / Localization

    • Updated translation metadata to match moved source locations for encryption and overwrite messages.

On headless CI (Ubuntu, macOS) gpg subprocesses hang waiting for a
PIN dialog or for gpg-agent to start, causing all ImitatePass tests
to time out at 15 s each.

Fix by writing gpg-agent.conf / gpg.conf to the temp GNUPGHOME before
key generation and explicitly launching the agent via gpgconf:
- allow-loopback-pinentry / pinentry-mode loopback: prevents blocking
  on pinentry when no GUI is available
- gpgconf --launch gpg-agent: ensures the agent is running before
  any GPG subprocess is spawned

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@codeant-ai
Copy link
Copy Markdown
Contributor

codeant-ai Bot commented Apr 19, 2026

CodeAnt AI is reviewing your PR.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 19, 2026

📝 Walkthrough

Walkthrough

Tests and CI now prepare a headless, CI-friendly GPG environment: tests write gpg config into a temp GNUPGHOME, pre-launch gpg-agent via gpgconf, import ownertrust for generated keys, and capture Pass::processErrorExit for richer test diagnostics; CI installs pinentry/pass on runners when building.

Changes

Cohort / File(s) Summary
Integration test setup & insert diagnostics
tests/auto/integration/tst_integration.cpp
Added findGpgconf(), updated generateTestKey() to extract first fpr: fingerprint and import ownertrust (gpg --import-ownertrust fingerprint:6:) with error handling; initTestCase() writes gpg-agent.conf/gpg.conf into temp GNUPGHOME, optionally sets pinentry-program, pre-launches gpg-agent via gpgconf --homedir ... --launch gpg-agent, preserves/restores pass-signing-key setting; tests now add a QSignalSpy for Pass::processErrorExit, use gpgInsertErrorMsg() for assertion messages, and clear spies between sequential inserts.
CI workflow: pinentry / pass install
.github/workflows/ccpp.yml
Added conditional OS-specific install steps before qmake: on Linux apt-get installs pinentry-tty, pass, pass-extension-otp; on macOS Homebrew installs pass and pass-otp. Steps run only when a build is required.
Localization .ts metadata updates
localization/localization_*.ts (many files)
Updated <location> line-number metadata across many Qt .ts files to reflect shifted source-line locations in ../src/pass.cpp (four GPG error messages) and ../src/storemodel.cpp (two overwrite prompts). No source or translation text changes.
Git ignore
.gitignore
Added tests/auto/integration/tst_integration test binary path to ignore list.

Sequence Diagram(s)

sequenceDiagram
  participant Test as TestHarness
  participant FS as Filesystem
  participant GConf as gpgconf
  participant GAgent as gpg-agent
  participant GPG as gpg CLI
  participant App as PassApp

  Test->>FS: write gpg-agent.conf, gpg.conf into GNUPGHOME
  Test->>GConf: gpgconf --homedir <GNUPGHOME> --launch gpg-agent
  GAgent-->>Test: started / ready (exit code)
  Test->>GPG: generate key / read status (captures `fpr:` line)
  GPG-->>Test: emits `fpr:` fingerprint
  Test->>GPG: gpg --import-ownertrust <fingerprint>:6:
  GPG-->>Test: import exit status
  Test->>App: run insert flows (ImitatePass / RealPass)
  App-->>Test: emits finishedInsert or Pass::processErrorExit
  Test->>Test: QSignalSpy reads processErrorExit and includes message in assertions
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

size:M

Suggested reviewers

  • nogeenhenk

Poem

🐰 I hopped into GNUPGHOME at first light,
I wrote confs and launched agents out of sight.
I trusted keys and cued their fate,
I listened for errors, patient and late,
Tests pass — the rabbit twirls with delight!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly and concisely summarizes the main change: fixing GPG agent pre-start for headless CI integration tests. It accurately reflects the primary objective of preventing test hangs in CI environments.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/integration-tests-ci-gpg-agent

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codeant-ai codeant-ai Bot added the size:S This PR changes 10-29 lines, ignoring generated files label Apr 19, 2026
@codeant-ai
Copy link
Copy Markdown
Contributor

codeant-ai Bot commented Apr 19, 2026

CodeAnt AI finished reviewing your PR.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/auto/integration/tst_integration.cpp`:
- Around line 176-178: The call to agentLaunch.start("gpgconf", {"--homedir",
m_gnupgHome.path(), "--launch", "gpg-agent"}) and the subsequent
agentLaunch.waitForFinished(10000) is not being validated, so failures silently
proceed into generateTestKey(); update the test to assert success by first
checking agentLaunch.waitForStarted(...) returned true, then that
waitForFinished(10000) returned true, and verify the QProcess::exitStatus() is
Normal and exitCode() == 0 before calling generateTestKey(); use QVERIFY2() (or
similar) and include the process output
(readAllStandardOutput()/readAllStandardError()) in the failure message to aid
debugging, referencing agentLaunch, waitForStarted, waitForFinished, exitStatus,
exitCode, and generateTestKey().
- Around line 162-167: The test currently ignores failures when creating/writing
GPG config files (QFile agentConf/gpgConf), so update the block that opens and
writes to agentConf and gpgConf to fail fast: check the result of
agentConf.open(...) and agentConf.write(...), and likewise gpgConf.open(...) and
gpgConf.write(...); if any of those return false or a negative/zero write
length, report the error and abort the test (e.g., QFAIL or throw) with a clear
message mentioning which file failed and the QFile::errorString(), so the test
does not continue silently without loopback pinentry configured.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: d3d04294-1e29-4df0-8777-17b0a1d78ad2

📥 Commits

Reviewing files that changed from the base of the PR and between 486a7fb and 2b61bae.

📒 Files selected for processing (1)
  • tests/auto/integration/tst_integration.cpp

Comment thread tests/auto/integration/tst_integration.cpp Outdated
Comment thread tests/auto/integration/tst_integration.cpp Outdated
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 19, 2026

❌ 6 Tests Failed:

Tests completed Failed Passed Skipped
352 6 346 8
View the top 3 failed test(s) by shortest run time
tst_integration::imitatePass_insertAndShow
Stack Traces | 14.3s run time
'waitForSignal(insertSpy)' returned FALSE. (finishedInsert not emitted (GPG may have hung or failed to start))
tst_integration::imitatePass_insertAndRemove
Stack Traces | 15s run time
'waitForSignal(insertSpy)' returned FALSE. (finishedInsert not emitted (GPG may have hung or failed to start))
tst_integration::imitatePass_insertAndGrep
Stack Traces | 15s run time
'waitForSignal(insertSpy)' returned FALSE. (finishedInsert not emitted (GPG may have hung or failed to start))
tst_integration::imitatePass_insertCopyAndShow
Stack Traces | 15s run time
'waitForSignal(insertSpy)' returned FALSE. (finishedInsert not emitted (GPG may have hung or failed to start))
tst_integration::imitatePass_nestedDirectoryInsertAndShow
Stack Traces | 15s run time
'waitForSignal(insertSpy)' returned FALSE. (finishedInsert not emitted (GPG may have hung or failed to start))
tst_integration::imitatePass_insertMoveAndShow
Stack Traces | 15s run time
'waitForSignal(insertSpy)' returned FALSE. (finishedInsert not emitted (GPG may have hung or failed to start))

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

- QVERIFY2 on QFile::open/write for gpg-agent.conf and gpg.conf so a
  permission or path failure surfaces immediately with errorString()
- QVERIFY2 on waitForStarted, waitForFinished, and exit code for the
  gpgconf --launch gpg-agent step, including stderr in the failure message

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (1)
tests/auto/integration/tst_integration.cpp (1)

161-176: ⚠️ Potential issue | 🟡 Minor

write() > 0 accepts short writes — prefer comparing against the payload size.

QIODevice::write() returns -1 on error or the number of bytes actually written, so > 0 correctly catches hard errors but silently accepts a truncated config (e.g. 1 byte written out of 40). If only a prefix like "a" lands in gpg-agent.conf, the test proceeds without allow-loopback-pinentry and reintroduces the exact hang this PR fixes — only harder to diagnose. Payloads here are tiny and buffered, so in practice this is very unlikely to bite, but the assertion should encode the invariant you actually want.

Same concern applies to both agentConf.write(...) and gpgConf.write(...).

♻️ Proposed fix
-    QFile agentConf(m_gnupgHome.path() + "/gpg-agent.conf");
-    QVERIFY2(agentConf.open(QIODevice::WriteOnly | QIODevice::Text),
+    const QByteArray agentConfig("allow-loopback-pinentry\ndefault-cache-ttl 300\n");
+    QFile agentConf(m_gnupgHome.path() + "/gpg-agent.conf");
+    QVERIFY2(agentConf.open(QIODevice::WriteOnly | QIODevice::Text |
+                            QIODevice::Truncate),
              qPrintable("Cannot open gpg-agent.conf: " +
                         agentConf.errorString()));
-    QVERIFY2(
-        agentConf.write("allow-loopback-pinentry\ndefault-cache-ttl 300\n") >
-            0,
-        qPrintable("Cannot write gpg-agent.conf: " + agentConf.errorString()));
-    QFile gpgConf(m_gnupgHome.path() + "/gpg.conf");
-    QVERIFY2(gpgConf.open(QIODevice::WriteOnly | QIODevice::Text),
+    QVERIFY2(agentConf.write(agentConfig) == agentConfig.size(),
+             qPrintable("Cannot write gpg-agent.conf: " + agentConf.errorString()));
+
+    const QByteArray gpgConfig("pinentry-mode loopback\nbatch\nno-tty\n");
+    QFile gpgConf(m_gnupgHome.path() + "/gpg.conf");
+    QVERIFY2(gpgConf.open(QIODevice::WriteOnly | QIODevice::Text |
+                          QIODevice::Truncate),
              qPrintable("Cannot open gpg.conf: " + gpgConf.errorString()));
-    QVERIFY2(
-        gpgConf.write("pinentry-mode loopback\nbatch\nno-tty\n") > 0,
-        qPrintable("Cannot write gpg.conf: " + gpgConf.errorString()));
+    QVERIFY2(gpgConf.write(gpgConfig) == gpgConfig.size(),
+             qPrintable("Cannot write gpg.conf: " + gpgConf.errorString()));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/auto/integration/tst_integration.cpp` around lines 161 - 176, The tests
currently assert agentConf.write(...) > 0 and gpgConf.write(...) > 0 which
allows truncated writes to pass; instead capture each payload into a variable
(e.g. QByteArray/QString payloadAgent and payloadGpg) and assert that the return
value of agentConf.write(payloadAgent) and gpgConf.write(payloadGpg) equals
payloadAgent.size()/payloadGpg.size() respectively (i.e. full write), failing
the test on any short write or error; update the two write call sites around
QFile agentConf and QFile gpgConf to use payload variables and compare against
payload.size().
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@tests/auto/integration/tst_integration.cpp`:
- Around line 161-176: The tests currently assert agentConf.write(...) > 0 and
gpgConf.write(...) > 0 which allows truncated writes to pass; instead capture
each payload into a variable (e.g. QByteArray/QString payloadAgent and
payloadGpg) and assert that the return value of agentConf.write(payloadAgent)
and gpgConf.write(payloadGpg) equals payloadAgent.size()/payloadGpg.size()
respectively (i.e. full write), failing the test on any short write or error;
update the two write call sites around QFile agentConf and QFile gpgConf to use
payload variables and compare against payload.size().

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: c533d5e5-68a4-4fe9-a224-5979a43defda

📥 Commits

Reviewing files that changed from the base of the PR and between 2b61bae and 6e829dc.

📒 Files selected for processing (1)
  • tests/auto/integration/tst_integration.cpp

- generateTestKey: explicitly set ownertrust to ultimate (level 6) via
  --import-ownertrust; some GPG versions don't auto-assign it from
  --gen-key --batch, causing encryption to refuse the key silently
- initTestCase: capture config payloads into QByteArray variables and
  assert write() == payload.size() for full-write verification
- All ImitatePass Insert tests: add processErrorExit spy alongside
  insertSpy so failures report the actual GPG error instead of just
  "finishedInsert not emitted"

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/auto/integration/tst_integration.cpp`:
- Around line 106-110: The ownertrust import call in generateTestKey ignores
runGpg()'s exit code so it may return a fingerprint even when trust import
failed; modify generateTestKey to capture the result/exit code of
runGpg(gnupgHome, {"--batch", "--import-ownertrust"}, fingerprint + ":6:\n") and
if it indicates failure, fail the setup immediately (e.g., return an error/empty
fingerprint or throw), and log a clear error mentioning the fingerprint and that
ownertrust import failed so downstream tests don't proceed with an untrusted
key.
- Around line 137-144: The function gpgInsertErrorMsg should use a trailing
return type to satisfy the Clang rule: change its signature from "static
QByteArray gpgInsertErrorMsg(const QSignalSpy &errorSpy)" to use "auto
gpgInsertErrorMsg(const QSignalSpy &errorSpy) -> QByteArray" and leave the
function body unchanged (keep the static specifier and the const QSignalSpy&
parameter and the current return logic).
- Around line 183-191: The new QFile constructions use string concatenation with
m_gnupgHome.path() which can produce non-normalized paths; normalize the paths
before creating QFile by calling QDir::cleanPath() on the combined path (e.g.,
for the gpg-agent.conf and gpg.conf paths used to construct agentConf and
gpgConf), ensuring you build the filename string with m_gnupgHome.path() +
"/gpg-agent.conf" and m_gnupgHome.path() + "/gpg.conf" then pass those cleaned
results into QFile so the tests are cross-platform consistent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9c9df591-4019-4500-b143-945b655289d4

📥 Commits

Reviewing files that changed from the base of the PR and between 6e829dc and 0560ba5.

📒 Files selected for processing (1)
  • tests/auto/integration/tst_integration.cpp

Comment thread tests/auto/integration/tst_integration.cpp
Comment thread tests/auto/integration/tst_integration.cpp Outdated
Comment thread tests/auto/integration/tst_integration.cpp Outdated
- Add pinentry-tty to CI workflow for GPG in headless environments
- Check ownertrust import exit code in generateTestKey
- Use trailing return type for gpgInsertErrorMsg
- Use QDir::cleanPath() for GPG config file paths
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/ccpp.yml:
- Around line 96-101: The "Install dependencies (Linux)" step currently only
checks runner.os == 'Linux' and should also be gated on the build decision to
avoid unnecessary apt runs; update the step (named "Install dependencies
(Linux)") to add the run_build condition so its if becomes something like
runner.os == 'Linux' && steps.need_build.outputs.run_build == 'true', ensuring
the apt-get update/install only runs when steps.need_build indicates a build.

In `@tests/auto/integration/tst_integration.cpp`:
- Around line 141-148: Replace the generic "finishedInsert not emitted" messages
in the RealPass tests with the new helper gpgInsertErrorMsg(const QSignalSpy
&errorSpy) -> QByteArray so you get the same detailed diagnostics as
ImitatePass; specifically, update realPass_insertAndShow and
realPass_insertAndGrep to call gpgInsertErrorMsg(errorSpy) when the
finished-insert signal isn't observed and use its returned QByteArray in the
test failure/assert message (the helper matches the trailing-return signature
and expects a QSignalSpy, and the emitted Pass::processErrorExit comes from the
same code path).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: a935f964-c85f-47b4-91e4-747d66e13d2f

📥 Commits

Reviewing files that changed from the base of the PR and between 0560ba5 and 21994f7.

📒 Files selected for processing (2)
  • .github/workflows/ccpp.yml
  • tests/auto/integration/tst_integration.cpp

Comment thread .github/workflows/ccpp.yml
Comment thread tests/auto/integration/tst_integration.cpp
…r RealPass

- Add QtPassSettings::setPassSigningKey(QString()) in initTestCase to clear the signing key
- Configure gpg-agent to use pinentry-tty for headless passphrase
- Update CI to only install dependencies when build is needed
- Use gpgInsertErrorMsg in RealPass tests for consistent error diagnostics
@coveralls
Copy link
Copy Markdown

coveralls commented Apr 19, 2026

Coverage Status

Coverage is 26.937%fix/integration-tests-ci-gpg-agent into main. No base build found for main.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@nogeenharrie nogeenharrie left a comment

Choose a reason for hiding this comment

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

All tests pass (183 passed). The integration tests now work in headless CI environments. Great work!

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
tests/auto/integration/tst_integration.cpp (1)

539-543: 🧹 Nitpick | 🔵 Trivial

Use the captured RealPass error for the second insert too.

Line 540 clears insertErrorSpy, but Line 543 still reports only "insert 2 not emitted", so the second RealPass insert loses the GPG stderr/return-code diagnostics this PR added elsewhere.

Proposed fix
   insertErrorSpy.clear();
   pass.Insert(QStringLiteral("email/outlook"),
               QStringLiteral("outlookpass\nurl: outlook.com\n"), false);
-  QVERIFY2(waitForSignal(insertSpy, 20000), "insert 2 not emitted");
+  QVERIFY2(waitForSignal(insertSpy, 20000), gpgInsertErrorMsg(insertErrorSpy));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/auto/integration/tst_integration.cpp` around lines 539 - 543, The
second RealPass insert is losing diagnostic info because insertErrorSpy is
cleared before the insert but the QVERIFY2 check only uses the static message
"insert 2 not emitted"; instead keep or capture the insertErrorSpy output for
the second insert and include it in the QVERIFY2 failure message (i.e., don't
clear insertErrorSpy immediately before calling pass.Insert(...) or read its
last/error output after the insert) so the waitForSignal(insertSpy, 20000)
assertion can report the RealPass stderr/return-code details from insertErrorSpy
if the signal isn't emitted; update the assertion to reference insertErrorSpy's
captured value when constructing the failure string.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/auto/integration/tst_integration.cpp`:
- Around line 185-187: The test currently hardcodes "/usr/bin/pinentry-tty" into
the agent config via the agentPayload string in tst_integration.cpp which breaks
macOS CI; update the agentPayload generation to avoid a hardcoded
pinentry-program (either omit the "pinentry-program" line entirely and rely on
loopback or detect the correct pinentry binary at runtime and insert its path)
so gpg-agent.conf no longer includes a platform-specific path and tests run on
macOS and Linux.

---

Duplicate comments:
In `@tests/auto/integration/tst_integration.cpp`:
- Around line 539-543: The second RealPass insert is losing diagnostic info
because insertErrorSpy is cleared before the insert but the QVERIFY2 check only
uses the static message "insert 2 not emitted"; instead keep or capture the
insertErrorSpy output for the second insert and include it in the QVERIFY2
failure message (i.e., don't clear insertErrorSpy immediately before calling
pass.Insert(...) or read its last/error output after the insert) so the
waitForSignal(insertSpy, 20000) assertion can report the RealPass
stderr/return-code details from insertErrorSpy if the signal isn't emitted;
update the assertion to reference insertErrorSpy's captured value when
constructing the failure string.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: aee77018-c030-462a-b4db-c2864edcc76d

📥 Commits

Reviewing files that changed from the base of the PR and between 21994f7 and b2cd820.

📒 Files selected for processing (52)
  • .github/workflows/ccpp.yml
  • localization/localization_af_ZA.ts
  • localization/localization_ar_MA.ts
  • localization/localization_bg_BG.ts
  • localization/localization_ca_ES.ts
  • localization/localization_cs_CZ.ts
  • localization/localization_cy_GB.ts
  • localization/localization_da_DK.ts
  • localization/localization_de_DE.ts
  • localization/localization_de_LU.ts
  • localization/localization_el_GR.ts
  • localization/localization_en_GB.ts
  • localization/localization_en_US.ts
  • localization/localization_es_AR.ts
  • localization/localization_es_EC.ts
  • localization/localization_es_ES.ts
  • localization/localization_es_MX.ts
  • localization/localization_es_UY.ts
  • localization/localization_et_EE.ts
  • localization/localization_fi_FI.ts
  • localization/localization_fr_BE.ts
  • localization/localization_fr_FR.ts
  • localization/localization_fr_LU.ts
  • localization/localization_gl_ES.ts
  • localization/localization_he_IL.ts
  • localization/localization_hr_HR.ts
  • localization/localization_hu_HU.ts
  • localization/localization_it_IT.ts
  • localization/localization_ja_JP.ts
  • localization/localization_ko_KR.ts
  • localization/localization_lb_LU.ts
  • localization/localization_nb_NO.ts
  • localization/localization_nl_BE.ts
  • localization/localization_nl_NL.ts
  • localization/localization_pl_PL.ts
  • localization/localization_pt_BR.ts
  • localization/localization_pt_PT.ts
  • localization/localization_ro_RO.ts
  • localization/localization_ru_RU.ts
  • localization/localization_si_LK.ts
  • localization/localization_sk_SK.ts
  • localization/localization_sq_AL.ts
  • localization/localization_sr_Cyrl.ts
  • localization/localization_sr_RS.ts
  • localization/localization_sv_SE.ts
  • localization/localization_ta_IN.ts
  • localization/localization_tr_TR.ts
  • localization/localization_uk_UA.ts
  • localization/localization_zh_CN.ts
  • localization/localization_zh_Hant.ts
  • tests/auto/integration/tst_integration
  • tests/auto/integration/tst_integration.cpp

Comment thread tests/auto/integration/tst_integration.cpp Outdated
- Only add pinentry-program for Linux, not macOS
- Keep insertErrorSpy for second RealPass insert to capture diagnostics
@codeant-ai
Copy link
Copy Markdown
Contributor

codeant-ai Bot commented Apr 19, 2026

CodeAnt AI is running the review.

@codeant-ai codeant-ai Bot added size:XL This PR changes 500-999 lines, ignoring generated files and removed size:S This PR changes 10-29 lines, ignoring generated files labels Apr 19, 2026
@codeant-ai
Copy link
Copy Markdown
Contributor

codeant-ai Bot commented Apr 19, 2026

Sequence Diagram

This PR changes the integration tests to configure a temporary GPG home for headless CI, pre-start the GPG agent, and use that environment so pass-style backends can encrypt secrets without hanging.

sequenceDiagram
    participant CI
    participant IntegrationTests
    participant GPGAgent
    participant GPG
    participant PassBackend

    CI->>IntegrationTests: Run GPG integration test suite
    IntegrationTests->>GPGAgent: Write gpg-agent and gpg config with loopback pinentry
    IntegrationTests->>GPGAgent: Launch agent via gpgconf in temp GNUPGHOME
    IntegrationTests->>GPG: Generate test key and set owner trust in temp keyring
    IntegrationTests->>PassBackend: Configure pass with test GNUPGHOME and key fingerprint
    PassBackend->>GPG: Encrypt secret during Insert
    GPG-->>PassBackend: Return encryption result
    PassBackend-->>IntegrationTests: Emit finishedInsert signal for the test
Loading

Generated by CodeAnt AI

Comment thread tests/auto/integration/tst_integration.cpp Outdated
@codeant-ai
Copy link
Copy Markdown
Contributor

codeant-ai Bot commented Apr 19, 2026

CodeAnt AI finished running the review.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/auto/integration/tst_integration.cpp`:
- Around line 535-544: The insertErrorSpy (QSignalSpy insertErrorSpy) is not
cleared between the two pass.Insert calls so a stale error from the first insert
can be reported by gpgInsertErrorMsg() on the second timeout; before performing
the second pass.Insert call, clear insertErrorSpy (similar to insertSpy.clear())
so that waitForSignal(insertSpy, ...) and gpgInsertErrorMsg(insertErrorSpy)
reflect only signals from the second operation.
- Line 234: The test currently calls
QtPassSettings::setPassSigningKey(QString()) which overwrites the user's
persisted signing key; to fix, capture the original key at test setup by calling
QtPassSettings::getPassSigningKey() and store it in a test-scoped variable, then
in cleanupTestCase() restore it by calling
QtPassSettings::setPassSigningKey(originalKey); ensure the stored variable is
accessible to cleanupTestCase() and that restore happens unconditionally even if
the test fails.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: 27675a61-336f-4f4e-82cd-f6ec36728c4b

📥 Commits

Reviewing files that changed from the base of the PR and between 21994f7 and ab18586.

📒 Files selected for processing (53)
  • .github/workflows/ccpp.yml
  • .gitignore
  • localization/localization_af_ZA.ts
  • localization/localization_ar_MA.ts
  • localization/localization_bg_BG.ts
  • localization/localization_ca_ES.ts
  • localization/localization_cs_CZ.ts
  • localization/localization_cy_GB.ts
  • localization/localization_da_DK.ts
  • localization/localization_de_DE.ts
  • localization/localization_de_LU.ts
  • localization/localization_el_GR.ts
  • localization/localization_en_GB.ts
  • localization/localization_en_US.ts
  • localization/localization_es_AR.ts
  • localization/localization_es_EC.ts
  • localization/localization_es_ES.ts
  • localization/localization_es_MX.ts
  • localization/localization_es_UY.ts
  • localization/localization_et_EE.ts
  • localization/localization_fi_FI.ts
  • localization/localization_fr_BE.ts
  • localization/localization_fr_FR.ts
  • localization/localization_fr_LU.ts
  • localization/localization_gl_ES.ts
  • localization/localization_he_IL.ts
  • localization/localization_hr_HR.ts
  • localization/localization_hu_HU.ts
  • localization/localization_it_IT.ts
  • localization/localization_ja_JP.ts
  • localization/localization_ko_KR.ts
  • localization/localization_lb_LU.ts
  • localization/localization_nb_NO.ts
  • localization/localization_nl_BE.ts
  • localization/localization_nl_NL.ts
  • localization/localization_pl_PL.ts
  • localization/localization_pt_BR.ts
  • localization/localization_pt_PT.ts
  • localization/localization_ro_RO.ts
  • localization/localization_ru_RU.ts
  • localization/localization_si_LK.ts
  • localization/localization_sk_SK.ts
  • localization/localization_sq_AL.ts
  • localization/localization_sr_Cyrl.ts
  • localization/localization_sr_RS.ts
  • localization/localization_sv_SE.ts
  • localization/localization_ta_IN.ts
  • localization/localization_tr_TR.ts
  • localization/localization_uk_UA.ts
  • localization/localization_zh_CN.ts
  • localization/localization_zh_Hant.ts
  • tests/auto/integration/tst_integration
  • tests/auto/integration/tst_integration.cpp

Comment thread tests/auto/integration/tst_integration.cpp
Comment thread tests/auto/integration/tst_integration.cpp
- Add findGpgconf() and skip tests if gpgconf not found
- Store original passSigningKey and restore in cleanupTestCase
- Clear insertErrorSpy before second RealPass insert
@codeant-ai
Copy link
Copy Markdown
Contributor

codeant-ai Bot commented Apr 19, 2026

CodeAnt AI is running Incremental review

@codeant-ai codeant-ai Bot added size:XL This PR changes 500-999 lines, ignoring generated files and removed size:XL This PR changes 500-999 lines, ignoring generated files labels Apr 19, 2026
Comment thread tests/auto/integration/tst_integration.cpp
@codeant-ai
Copy link
Copy Markdown
Contributor

codeant-ai Bot commented Apr 19, 2026

CodeAnt AI Incremental review completed.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 9

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@localization/localization_de_DE.ts`:
- Around line 1318-1337: You committed manual edits into
localization/localization_de_DE.ts (e.g. translation entries for "Encryption
failed: GPG key has expired." / "Encryption failed: GPG key has been revoked." /
"Encryption failed: recipient GPG key not found or invalid..."), which violates
the guideline to not edit .ts files by hand; revert those manual changes, update
translations via the project translation flow (Weblate) for those source
strings, then regenerate the .ts file using the project's sync step (run qmake6
as required) so the .ts entries and <location> tags are produced automatically.

In `@localization/localization_es_EC.ts`:
- Around line 1308-1327: The localization_es_EC.ts file was edited directly
(including <location> metadata) — revert these manual edits and regenerate the
translation file using the Weblate/translation tooling, then run qmake6/qmake
sync to update .ts metadata; specifically restore changes around the messages
with source texts "Encryption failed: GPG key has expired. Please renew or
replace it.", "Encryption failed: GPG key has been revoked.", and "Encryption
failed: recipient GPG key not found or invalid. Check that the key ID in .gpg-id
is correct and imported." (also revert the similar edits noted at the other
block) so that translations and <location> entries are produced by the tooling
rather than edited by hand.

In `@localization/localization_fr_BE.ts`:
- Around line 1319-1338: Revert the manual edits made to the translation file
(undo any changes to the translation metadata and message entries such as the
"Encryption failed: recipient GPG key not found or invalid. Check that the key
ID in .gpg-id is correct and imported." entry and the nearby entries), then
update translations via the translation tooling/Weblate (do not hand-edit .ts
files) and synchronize the .ts from Weblate; after syncing, run qmake6 to
regenerate and update the .ts/.qm artifacts so the correct metadata and
translations are restored and no direct .ts edits remain in the PR.

In `@localization/localization_gl_ES.ts`:
- Around line 1316-1335: This change manually edited the .ts translation file
(localization_gl_ES.ts); revert the direct edits and instead add the
translations via the Weblate translation platform (or the project's translation
workflow), then regenerate the .ts metadata by running qmake6 so the .ts is
produced by the supported pipeline; ensure you update the same message keys (the
strings from src/pass.cpp such as the "Encryption failed: GPG key has
expired..." / "has been revoked." / "recipient GPG key not found or invalid..."
entries) through Weblate and not by committing manual edits to
localization_gl_ES.ts.

In `@localization/localization_it_IT.ts`:
- Around line 1402-1421: The changes in localization_it_IT.ts (the edited
<message> entries for strings coming from src/pass.cpp like "Encryption failed:
GPG key has expired..." / "GPG key has been revoked." / "recipient GPG key not
found...") were made directly in the .ts file; revert those manual edits and
instead add/update translations through Weblate for the Italian locale, then run
qmake6 to regenerate the .ts artifacts so the updated translations are produced
correctly from the source (src/pass.cpp) and included in the build.

In `@localization/localization_ta_IN.ts`:
- Around line 1391-1410: The .ts translation entries were edited directly
instead of using the localization pipeline; revert the manual edits to
localization_ta_IN.ts and instead add or update the corresponding source strings
via the project's translation workflow (push the source changes so Weblate can
ingest them), perform the translations in Weblate, then regenerate the
translation artifacts by running qmake6 to produce updated .ts/.qm files; ensure
the specific messages like "Encryption failed: GPG key has expired. Please renew
or replace it.", "Encryption failed: GPG key has been revoked.", and "Encryption
failed: recipient GPG key not found or invalid. Check that the key ID in .gpg-id
is correct and imported." are handled through Weblate rather than edited in-PR.

In `@localization/localization_zh_CN.ts`:
- Around line 1350-1369: The commit contains manual edits to the Chinese
translation file for the error messages like "Encryption failed: GPG key has
expired. Please renew or replace it.", "Encryption failed: GPG key has been
revoked.", and "Encryption failed: recipient GPG key not found or invalid. Check
that the key ID in .gpg-id is correct and imported." — revert those direct
changes in localization_zh_CN.ts, instead push translations through Weblate
(update the corresponding entries there) and then regenerate the .ts files by
running qmake6 so the location remaps from the source (pass.cpp) are applied
automatically.

In `@tests/auto/integration/tst_integration.cpp`:
- Around line 50-56: The function findGpgconf() uses a traditional return type
and should be rewritten with a trailing return type to satisfy the
modernize-use-trailing-return-type rule; change its signature from "QString
findGpgconf()" to "auto findGpgconf() -> QString" (leave the body unchanged) so
the function name findGpgconf and its returns (QFile::exists and
QStandardPaths::findExecutable) remain intact.
- Around line 247-256: The test captures the original signing key too late
(m_originalPassSigningKey = QtPassSettings::getPassSigningKey()) so
cleanupTestCase() may restore an empty key if init failed early; move the
capture to a guaranteed-executed point (e.g., the tst_integration constructor or
the very top of initTestCase() before any QSKIP/QVERIFY calls) and set a boolean
flag (e.g., m_hasOriginalPassSigningKey) when captured, then change
cleanupTestCase() to only call
QtPassSettings::setPassSigningKey(m_originalPassSigningKey) if that flag is
true; update member declarations to include the flag and initialize it
appropriately.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: 4a8dd04b-b8f5-40ff-8148-d372a53bfd1f

📥 Commits

Reviewing files that changed from the base of the PR and between 21994f7 and bbcd56e.

📒 Files selected for processing (53)
  • .github/workflows/ccpp.yml
  • .gitignore
  • localization/localization_af_ZA.ts
  • localization/localization_ar_MA.ts
  • localization/localization_bg_BG.ts
  • localization/localization_ca_ES.ts
  • localization/localization_cs_CZ.ts
  • localization/localization_cy_GB.ts
  • localization/localization_da_DK.ts
  • localization/localization_de_DE.ts
  • localization/localization_de_LU.ts
  • localization/localization_el_GR.ts
  • localization/localization_en_GB.ts
  • localization/localization_en_US.ts
  • localization/localization_es_AR.ts
  • localization/localization_es_EC.ts
  • localization/localization_es_ES.ts
  • localization/localization_es_MX.ts
  • localization/localization_es_UY.ts
  • localization/localization_et_EE.ts
  • localization/localization_fi_FI.ts
  • localization/localization_fr_BE.ts
  • localization/localization_fr_FR.ts
  • localization/localization_fr_LU.ts
  • localization/localization_gl_ES.ts
  • localization/localization_he_IL.ts
  • localization/localization_hr_HR.ts
  • localization/localization_hu_HU.ts
  • localization/localization_it_IT.ts
  • localization/localization_ja_JP.ts
  • localization/localization_ko_KR.ts
  • localization/localization_lb_LU.ts
  • localization/localization_nb_NO.ts
  • localization/localization_nl_BE.ts
  • localization/localization_nl_NL.ts
  • localization/localization_pl_PL.ts
  • localization/localization_pt_BR.ts
  • localization/localization_pt_PT.ts
  • localization/localization_ro_RO.ts
  • localization/localization_ru_RU.ts
  • localization/localization_si_LK.ts
  • localization/localization_sk_SK.ts
  • localization/localization_sq_AL.ts
  • localization/localization_sr_Cyrl.ts
  • localization/localization_sr_RS.ts
  • localization/localization_sv_SE.ts
  • localization/localization_ta_IN.ts
  • localization/localization_tr_TR.ts
  • localization/localization_uk_UA.ts
  • localization/localization_zh_CN.ts
  • localization/localization_zh_Hant.ts
  • tests/auto/integration/tst_integration
  • tests/auto/integration/tst_integration.cpp

Comment thread localization/localization_de_DE.ts
Comment thread localization/localization_es_EC.ts
Comment thread localization/localization_fr_BE.ts
Comment thread localization/localization_gl_ES.ts
Comment thread localization/localization_it_IT.ts
Comment thread localization/localization_ta_IN.ts
Comment thread localization/localization_zh_CN.ts
Comment thread tests/auto/integration/tst_integration.cpp
Comment thread tests/auto/integration/tst_integration.cpp
@annejan annejan merged commit a00c653 into main Apr 19, 2026
22 of 24 checks passed
@annejan annejan deleted the fix/integration-tests-ci-gpg-agent branch April 19, 2026 01:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XL This PR changes 500-999 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants