Skip to content

v0.1.7: APT Clean dry-run safety + docker test exit-code propagation#67

Merged
bluet merged 6 commits into
mainfrom
worktree-hotfix+v0.1.7-clean-dryrun
May 9, 2026
Merged

v0.1.7: APT Clean dry-run safety + docker test exit-code propagation#67
bluet merged 6 commits into
mainfrom
worktree-hotfix+v0.1.7-clean-dryrun

Conversation

@bluet
Copy link
Copy Markdown
Owner

@bluet bluet commented May 9, 2026

Summary

Three atomic commits prepping a v0.1.7 hotfix release:

  1. fix(apt): honor DryRun in Clean() — APT's Clean() was running apt autoclean regardless of the DryRun option, defeating the safety guarantee users expect from dry-run mode. The YUM/Snap/Flatpak Clean implementations on main already honored DryRun; APT now matches. Includes 3 regression tests with a TDD red-green-restore cycle verified locally.

  2. ci(docker): make test failures propagate + harden test-all service — The compose entrypoints used bash -c with && chains and trailing || true. Due to bash operator precedence, the || true caught failures from earlier in the chain (including go test), letting failed tests pass CI silently. Switched to bash -ec with ; separators so test failures abort immediately while fixture-generation steps remain individually allowed to fail. Added read_only: true and no-new-privileges:true to the test-all aggregator service.

  3. docs(changelog): add v0.1.7 entry — Documents all of the above plus the @aijanai contribution merged in add json tags to PackageInfo struct and tests #40.

Security relevance

The DryRun fix is security-relevant: a user testing destructive operations with --dry-run on shared / production hosts could trigger cache cleanup unexpectedly. The CI exit-code fix is also security-adjacent: tests can no longer pass silently when they should fail.

Test plan

  • TDD red-green-restore cycle locally proven (TestCleanRespectsDryRun FAILs without fix, PASSes with fix)
  • go build ./... exit 0
  • go vet ./... exit 0
  • gofmt -l ./ clean
  • go test ./manager/apt/ — 3 new tests PASS; pre-existing env-coupled FAILs identical to baseline (no regressions)
  • make test-docker-ubuntu exit 0 — confirms fix works on real Ubuntu APT, plus new bash -ec format is functional
  • make test-docker-rocky exit 0 — confirms new bash -ec format works for YUM
  • docker compose -f testing/docker/docker-compose.test.yml config parses cleanly
  • Reviewer: confirm CI stays green
  • Maintainer (post-merge): tag v0.1.7

Notes

  • Branch name has + from the worktree tooling; rename if you'd like before merge.
  • The CHANGELOG commit also picks up pre-commit-mandated whitespace cleanup (pre-existing trailing spaces) on lines we already touched.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • APT package manager's clean operation now respects dry-run setting
    • Fixed Go toolchain version declaration
  • Improvements

    • JSON output now uses consistent snake_case field naming
    • Enhanced test infrastructure reliability and security measures
  • Documentation

    • Updated changelog documenting version 0.1.7 release

Review Change Stack

bluet and others added 3 commits May 10, 2026 01:27
Previously, Clean() executed `apt autoclean` regardless of the DryRun
option, silently defeating the safety mechanism users expect from
dry-run mode. The YUM/Snap/Flatpak Clean implementations on main
already honored DryRun; APT now matches that behavior.

Add the early-return guard immediately after nil-opts defaulting
(matching the pattern at yum/yum.go:467, snap/snap.go:295,
flatpak/flatpak.go:300). Move context creation below the guard so the
DryRun path doesn't allocate an unused context.

Regression tests cover three contracts:
- Clean(DryRun=true) makes zero underlying command calls
- Clean(DryRun=false) does invoke `apt autoclean` (guards against
  the fix being implemented as a blanket no-op)
- Clean(nil) preserves the existing nil-opts default behavior

This is security-relevant: a user testing with `--dry-run` on shared
or production hosts could trigger cache cleanup unexpectedly.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The compose test entrypoints used `bash -c` with `&&` chains and
trailing `|| true` on fixture-generation steps. Due to bash operator
precedence, the trailing `|| true` caught failures from earlier in
the chain — including `go test` itself — letting failed tests pass
CI silently while only the (allowed-to-fail) fixture-generation step
appeared to succeed.

Switch to `bash -ec` with explicit `;` separators for required steps:
- Required commands (go test, apt update) abort the script on
  non-zero exit (set -e via -e flag)
- Fixture-generation lines retain `|| true` so they remain
  individually allowed to fail
- Statements use `;` instead of `&&` so set -e can actually trigger
  on intermediate failures (set -e doesn't apply to commands inside
  `&&` lists except the final command)

Applied to ubuntu-apt-test, rockylinux-yum-test, almalinux-yum-test.

Defense-in-depth on the test-all aggregator service:
- read_only: true (it only runs an echo, no writes needed)
- security_opt: [no-new-privileges:true]

The required services (apt/yum tests) need write access for fixture
generation and don't get these constraints.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Document the APT Clean DryRun safety fix, the docker-compose exit
code propagation fix, the test-all defense-in-depth hardening, the
PackageInfo JSON tags change (#40), and the go.mod toolchain version
fix (#40).

Also picks up pre-commit-mandated cleanup of pre-existing trailing
whitespace and missing trailing newline.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 9, 2026

Warning

Rate limit exceeded

@bluet has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 15 minutes and 37 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5690bad5-74f7-4cfe-8424-7f3e694ec40b

📥 Commits

Reviewing files that changed from the base of the PR and between 3dd42ce and 0b84517.

📒 Files selected for processing (2)
  • Makefile
  • testing/docker/docker-compose.test.yml
📝 Walkthrough

Walkthrough

This PR introduces security enhancements and test reliability improvements for version 0.1.7. The APT package manager's Clean() method now respects the DryRun flag, Docker test runners use stricter bash semantics to detect failures, and the test-all service receives security hardening. All changes are documented in the changelog.

Changes

APT Dry-Run Security & Docker Test Hardening Release 0.1.7

Layer / File(s) Summary
APT Clean() Dry-Run Implementation
manager/apt/apt.go
Clean() initializes default opts when nil and returns early with a log message when DryRun is true, preventing command execution.
APT Clean() Dry-Run Tests
manager/apt/apt_clean_dryrun_test.go
Three tests verify dry-run behavior: DryRun=true skips execution, DryRun=false invokes apt autoclean, and nil opts defaults to non-dry-run.
Docker Test Runner Failure Detection
testing/docker/docker-compose.test.yml
Ubuntu, Rocky, and Alma test services switch from bash -c with && to bash -ec with ; separators, enabling immediate exit on test failures while allowing fixture steps to fail gracefully.
Test-All Service Security Hardening
testing/docker/docker-compose.test.yml
test-all service adds read_only: true and security_opt: no-new-privileges:true for defense-in-depth protection.
Release Documentation
CHANGELOG.md
0.1.7 release entry documents APT dry-run security, docker test improvements, test-all hardening, PackageInfo JSON snake_case fields, and go.mod toolchain fix; formatting adjustments to platform status sections.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 A dry-run hops without a care,
Docker tests now truly declare,
Security hardened, tests stay true,
The changelog sings of v0.1.7's new brew! 🎉

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and specifically summarizes the two main changes: APT Clean dry-run safety and docker test exit-code propagation, matching the core PR objectives.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch worktree-hotfix+v0.1.7-clean-dryrun

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.

@fossabot
Copy link
Copy Markdown

fossabot Bot commented May 9, 2026

No Issues

No security issues were detected in the SAST scan. The code changes appear to follow secure coding practices.


fossabot analyzed this PR using SAST security analysis (changed files only).

Copy link
Copy Markdown

@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

🧹 Nitpick comments (1)
testing/docker/docker-compose.test.yml (1)

146-153: ⚡ Quick win

Harden test-all further by making the /workspace bind mount read-only.

test-all now has read_only root FS and no-new-privileges, but the bind mount remains writable. Since this service only echoes status, :ro would better match the hardening goal.

Suggested diff
   test-all:
@@
     volumes:
-      - ../..:/workspace
+      - ../..:/workspace:ro
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@testing/docker/docker-compose.test.yml` around lines 146 - 153, The bind
mount for the test-all service is still writable; update the volumes entry that
currently maps "../..:/workspace" to be read-only by appending ":ro" (i.e.,
change the volumes line in the test-all service from ../..:/workspace to
../..:/workspace:ro) so /workspace is mounted read-only while keeping the
service's read_only and security_opt settings intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@manager/apt/apt_clean_dryrun_test.go`:
- Around line 1-8: This test file (package apt_test in apt_clean_dryrun_test.go)
needs Go build tags for selective test execution; add a top-of-file build
constraint such as a modern //go:build line combining the desired selectors (for
example unit and apt) and the corresponding legacy // +build line, placed before
the package declaration so the test runs only when those tags are specified.

---

Nitpick comments:
In `@testing/docker/docker-compose.test.yml`:
- Around line 146-153: The bind mount for the test-all service is still
writable; update the volumes entry that currently maps "../..:/workspace" to be
read-only by appending ":ro" (i.e., change the volumes line in the test-all
service from ../..:/workspace to ../..:/workspace:ro) so /workspace is mounted
read-only while keeping the service's read_only and security_opt settings
intact.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 10870b6a-434c-460d-a473-f090514e4772

📥 Commits

Reviewing files that changed from the base of the PR and between 738e5ab and 3dd42ce.

📒 Files selected for processing (4)
  • CHANGELOG.md
  • manager/apt/apt.go
  • manager/apt/apt_clean_dryrun_test.go
  • testing/docker/docker-compose.test.yml

Comment thread manager/apt/apt_clean_dryrun_test.go
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request fixes a security issue where the APT Clean() method ignored the DryRun option and updates Docker test runners to ensure test failures are correctly reported by using bash -ec. It also updates PackageInfo JSON fields to snake_case and hardens the Docker aggregator service. Feedback suggests improving the Docker Compose configuration by using the long form of depends_on to properly propagate failures, simplifying redundant option initializations in the APT manager, and correcting the syntax for the no-new-privileges security option.

Comment thread testing/docker/docker-compose.test.yml Outdated
Comment thread manager/apt/apt.go
Comment thread testing/docker/docker-compose.test.yml Outdated
Three small follow-ups to the test-all aggregator service from PR #67
review:

- depends_on switched to long-form with `condition: service_completed_successfully`
  for each dependent service. The short form only waited for dependents
  to *start*, so test-all's `echo` could finish in milliseconds and abort
  the compose run (--abort-on-container-exit) before the real tests
  reported failure. Same class of CI-honesty bug the bash -ec change in
  this same release fixes one layer up. (gemini-code-assist HIGH)

- /workspace bind mount made read-only (`:ro`). test-all only runs an
  echo, so the mount doesn't need write access. Defense-in-depth
  consistent with the existing read_only and security_opt. (CodeRabbit)

- Quoted "no-new-privileges:true" to eliminate YAML-parser ambiguity
  around `key:value` parsing while preserving Docker's documented form.
  (gemini-code-assist SECURITY-MEDIUM)

Verified via `docker compose config`: depends_on shows long-form with
condition: service_completed_successfully; read_only: true on the bind
mount; security_opt preserves the documented form.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@bluet
Copy link
Copy Markdown
Owner Author

bluet commented May 9, 2026

Review feedback applied in 1e42e97. Three test-all hardening items accepted, two declined with reasoning on their respective threads.

Accepted (commit 1e42e97):

  • depends_on long-form with condition: service_completed_successfully (gemini HIGH) — real CI-honesty bug, same theme as the bash -ec change in this PR
  • /workspace bind mount made read-only (CodeRabbit) — defense-in-depth consistent with the existing read_only/security_opt
  • Quoted "no-new-privileges:true" (gemini SECURITY-MEDIUM) — eliminates YAML ambiguity while preserving Docker's documented form

Declined:

  • Build tags on the new unit test file (CodeRabbit) — verified against the codebase: existing unit tests in manager/apt/ (apt_test.go, apt_commandrunner_test.go, behavior_test.go, utils_test.go) don't use build tags. The convention in this project is that only files like yum_integration_test.go (which touches a real system) get the //go:build integration tag. Adding tags here would be inconsistent with every existing unit test in the package.
  • Simplify &manager.Options{...} to &manager.Options{} (gemini MEDIUM) — technically correct but the same boilerplate exists in 6+ APT functions plus all the equivalents in yum.go, snap.go, flatpak.go. Simplifying only Clean() creates inconsistency. Worth a separate refactor PR; out of scope for a hotfix.

Note on the failing "Quality Gate" check: the SonarQube workflow has been failing on every recent PR and on main itself — the scan-action setup never starts, looks like a SONAR_TOKEN configuration issue. SonarCloud (different service) passed with 0 issues. Not a v0.1.7 blocker; tracked separately.

@fossabot
Copy link
Copy Markdown

fossabot Bot commented May 9, 2026

No Issues

No security issues were detected in the SAST scan. The code changes appear to follow secure coding practices.


fossabot analyzed this PR using SAST security analysis (changed files only).

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1e42e97549

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread testing/docker/docker-compose.test.yml
…ow tests

`--abort-on-container-exit` aborts the compose run when ANY container
exits — success or failure. With multi-service runs (`make test-docker`,
`make test-docker-all`), the FASTEST test container's success would
kill the slower siblings mid-test, masking failures and skipping most
of the matrix. Long-form depends_on on `test-all` from the prior
commit only addressed the test-all → dependents race; the test
containers race against each other was still there.

Switch to `--abort-on-container-failure` (Docker Compose v2.12+) which
aborts only when a container exits non-zero. Now multi-service runs
wait for all test containers to finish, fail fast on actual failure,
and surface real CI signal.

Applied uniformly across test-docker, test-docker-{ubuntu,rocky,alma},
test-fixtures, and the commented-out future targets.

Catch from chatgpt-codex-connector P1 review on PR #67.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@fossabot
Copy link
Copy Markdown

fossabot Bot commented May 9, 2026

No Issues

No security issues were detected in the SAST scan. The code changes appear to follow secure coding practices.


fossabot analyzed this PR using SAST security analysis (changed files only).

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5594581084

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread Makefile Outdated
Docker Compose v1 (`docker-compose`, the standalone Python binary)
was EOL'd June 2023 and does not support `--abort-on-container-failure`
introduced in the prior commit. With the Makefile invoking the legacy
hyphenated form, environments still using v1 would have all the
`make test-docker*` targets fail before any tests run.

Switch all 8 invocations from `docker-compose ...` to `docker compose ...`
(v2 plugin / standalone v2 binary). Filenames containing `docker-compose`
(e.g. `docker-compose.test.yml`) are unchanged.

Verified locally: `make test-docker-ubuntu` exits 0 with the v2 command.

Catch from chatgpt-codex-connector P2 review on PR #67.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented May 9, 2026

@fossabot
Copy link
Copy Markdown

fossabot Bot commented May 9, 2026

No Issues

No security issues were detected in the SAST scan. The code changes appear to follow secure coding practices.


fossabot analyzed this PR using SAST security analysis (changed files only).

@bluet bluet merged commit d8b97fe into main May 9, 2026
22 of 23 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.

1 participant