Skip to content

feat(gemini): A Docker utility to prune unused images, stopped containers, and dangling volumes, keeping your digital garden tidy.#3635

Open
polsala wants to merge 1 commit intomainfrom
ai/gemini-20260306-0835
Open

feat(gemini): A Docker utility to prune unused images, stopped containers, and dangling volumes, keeping your digital garden tidy.#3635
polsala wants to merge 1 commit intomainfrom
ai/gemini-20260306-0835

Conversation

@polsala
Copy link
Owner

@polsala polsala commented Mar 6, 2026

Implementation Summary

  • Utility: nightly-container-garden-tidy
  • Provider: gemini
  • Location: docker-tools/nightly-nightly-container-garden-tid
  • Files Created: 4
  • Description: A Docker utility to prune unused images, stopped containers, and dangling volumes, keeping your digital garden tidy.

Rationale

  • Automated proposal from the Gemini generator delivering a fresh community utility.
  • This utility was generated using the gemini AI provider.

Why safe to merge

  • Utility is isolated to docker-tools/nightly-nightly-container-garden-tid.
  • README + tests ship together (see folder contents).
  • No secrets or credentials touched.
  • All changes are additive and self-contained.

Test Plan

  • Follow the instructions in the generated README at docker-tools/nightly-nightly-container-garden-tid/README.md
  • Run tests located in docker-tools/nightly-nightly-container-garden-tid/tests/

Links

  • Generated docs and examples committed alongside this change.

Mock Justification

  • Not applicable; generator did not introduce new mocks.

…ners, and dangling volumes, keeping your digital garden tidy.
@polsala
Copy link
Owner Author

polsala commented Mar 6, 2026

🤖 Review by GROQ Agent

✅ What's solid

  • Self‑contained utility – The new nightly-container-garden-tidy lives under its own directory, with its own Dockerfile, script, README and tests. This isolation makes it easy to version and ship independently.
  • Clear user story – The README explains the problem (Docker “weeds”) and the two usage modes (dry‑run vs --prune) in a friendly, step‑by‑step way.
  • Test harness – The Bash test suite spins up a temporary mock docker binary, keeping CI fast and deterministic without needing a real Docker daemon.
  • Dockerfile simplicity – The image is built from the official docker:latest base, copies the script, makes it executable and sets it as the entry‑point – a minimal, functional container.

🧪 Tests

Observation Recommendation
The mock docker script matches commands by concatenating the first three positional arguments ("$1 $2 $3"). This works for the current test cases but will break if the script under test adds extra flags (e.g., docker images -f dangling=true --format "{{.Repository}}"). Make the mock more flexible – use a loop to inspect $@ or pattern‑match with case "$*" in. Example:
bash\ncase "$*" in\n "images -f dangling=true"* ) … ;;\n "ps -a -f status=exited"* ) … ;;\n # …\nesac\n
The test suite checks for exact substrings in the output using a single regex per test. This is fine, but the regex for “Dry run – With items to prune” is long and brittle. Add helper assertions – capture sections of output into variables (e.g., dangling=$(grep -A1 "Dangling Images" <<<"$OUTPUT")) and assert on each piece separately. This makes failures easier to diagnose.
The “No Docker client available” test temporarily strips the mock directory from $PATH. It restores $PATH afterwards, but if the test fails early the restoration never runs. Wrap the PATH manipulation in a trap to guarantee cleanup:
```bash\nORIGINAL_PATH=$PATH\ntrap 'export PATH=$ORIGINAL_PATH' EXIT\nexport PATH=$(echo "$PATH"
No test covers the error handling when Docker returns a non‑zero exit code for a real command (e.g., permission denied on the socket). Add a negative test that forces the mock to exit with a non‑zero status for docker system prune -f and verify the script surfaces a helpful error message.
The script is invoked via bash "$SCRIPT_TO_TEST" in the tests, which bypasses the executable bit. This is fine, but the script’s shebang (#!/bin/bash) is never exercised. Add a test that runs the script directly ("$SCRIPT_TO_TEST") after chmod +x to ensure the shebang works on all platforms.

🔒 Security

  • Docker socket exposure – The utility requires -v /var/run/docker.sock:/var/run/docker.sock to function. Running any container with socket access gives it full control over the host Docker daemon, which is a privilege escalation vector.
    • Action: Document the security implication prominently in the README (e.g., “⚠️ This container runs with full Docker daemon access; only use on trusted hosts.”) and consider providing a non‑privileged mode that only reports (dry‑run) without needing socket access (e.g., by reading /var/lib/docker metadata if available).
  • Base image choicedocker:latest pulls a fairly large image that includes many tools. If the utility only needs Bash and the Docker CLI, a slimmer variant such as docker:stable-dind-alpine or docker:cli-alpine would reduce the attack surface.
    • Action: Switch the Dockerfile to an Alpine‑based Docker CLI image:
      Dockerfile\nFROM docker:cli-alpine\n...\n |
  • Script robustness – The script does not enable strict Bash modes (set -euo pipefail). Without them, a typo or unexpected empty variable could cause silent failures.
    • Action: Add at the top of tidy_garden.sh:
      bash\nset -euo pipefail\nIFS=$'\\n\\t'\n |
  • Output sanitisation – The script prints raw Docker command output directly to the console. While this is generally safe, if a malicious Docker daemon were attached it could inject control characters.
    • Action: Pipe outputs through sed -e 's/[\x00-\x1F\x7F]//g' or use printf '%s\n' "$output" to strip non‑printable characters before echoing.

🧩 Docs / Developer Experience

  • Folder naming inconsistency – The directory is called nightly-nightly-container-garden-tid (note the duplicated “nightly” and truncated “tid”). The README and usage examples refer to nightly-container-garden-tidy. This mismatch can confuse users and CI scripts.
    • Action: Rename the folder to nightly-container-garden-tidy and update any references in the PR description.
  • README build instructions – The “Build the Docker Image (Optional)” section suggests running docker build -t nightly-container-garden-tidy . from the utility’s directory. It would be helpful to include the exact command for the CI pipeline, e.g., docker build -t ghcr.io/yourorg/nightly-container-garden-tidy:latest ..
  • Dry‑run vs prune flag – The script accepts both --prune and --force (treated the same). The README only mentions --prune.
    • Action: Either document --force as an alias or remove the alias to avoid confusion.
  • Example output formatting – The README uses literal newline characters (\n) inside echo strings in the script, which may not render as intended on all shells. Consider using printf with \n or separate echo statements.
  • Contribution guidelines – Since this utility is generated by an AI provider, it would be nice to add a short note in the repo’s CONTRIBUTING file about reviewing AI‑generated code for security and style.

🧱 Mocks / Fakes

  • Mock Docker binary location – The test creates a temporary directory and prepends it to $PATH. This works, but the mock binary is left on the host filesystem until the end of the test suite. If a test crashes early, the temporary directory may linger.
    • Action: Use trap 'rm -rf "$MOCK_BIN_DIR"' EXIT right after creation to guarantee cleanup even on failure.
  • Mock command coverage – The mock only implements a subset of Docker sub‑commands (images, ps, volume, network, system prune, volume prune). If future enhancements add more Docker interactions (e.g., docker builder prune), the mock will need to be extended.
    • Action: Consider extracting the mock logic into a reusable helper script (tests/mock_docker.sh) that can be sourced by multiple test suites, making it easier to maintain.
  • Exit‑code semantics – The mock returns exit 1 when there are “no items” for docker images, ps, etc. In reality, Docker returns zero with an empty output. The script’s || echo "<none>" works because the command exits with a non‑zero status only when there is an error, not when the list is empty. This discrepancy could mask bugs.
    • Action: Change the mock to output nothing and exit 0 for the “no items” case, then adjust the script to test for empty output rather than relying on a non‑zero exit status. Example mock snippet:
      bash\nif [ -s "$MOCK_BIN_DIR/mock_dangling_images" ]; then\n cat "$MOCK_BIN_DIR/mock_dangling_images"\nelse\n # No dangling images – print nothing and exit 0\n exit 0\nfi\n |
  • Portability of the mock – The mock uses Bash‑specific features ([[ ]], [[ -f ... ]]). If the test environment runs under sh (e.g., on a minimal CI runner), the mock could fail.
    • Action: Add a shebang #!/usr/bin/env bash and ensure the CI image includes Bash, or rewrite the mock to be POSIX‑sh compatible.

Overall, the utility is a valuable addition that brings automated Docker cleanup to the nightly toolbox. Addressing the points above—especially the folder naming, Docker socket security note, and tightening the test mock—will make the contribution more robust, maintainable, and safer for downstream users. Happy gardening!

@polsala
Copy link
Owner Author

polsala commented Mar 8, 2026

🤖 Review by OPENROUTER Agent

Code Review: Nightly Container Garden Tidy-Upper

✅ What's solid

  • Well-isolated utility: The tool is contained within its own directory with clear separation of concerns
  • Clear value proposition: Addresses a common Docker maintenance pain point with a user-friendly interface
  • Comprehensive testing approach: Includes mocked Docker commands for deterministic offline testing
  • Safe defaults: Dry-run mode as default prevents accidental data loss

🧪 Tests

  • Good test coverage: Tests cover dry-run scenarios, pruning mode, and error conditions
  • Effective mocking strategy: Mock Docker binary allows for controlled test environments
  • Actionable improvements needed:
    • Add test cases for unknown argument handling
    • Consider testing both --prune and --force flags separately since they're treated equivalently
    • Add edge case tests for malformed Docker outputs
    • Include tests for partial failure scenarios (e.g., some Docker commands fail but others succeed)

🔒 Security

  • Proper container isolation: Runs in its own container with minimal dependencies
  • No hardcoded credentials: Clean implementation without secret exposure
  • Actionable improvements needed:
    • Add explicit user directive in Dockerfile to avoid running as root:
      # Add after FROM line
      RUN adduser -D tidy-user
      USER tidy-user
    • Consider adding security scanning to the pipeline for the generated image
    • Document the security implications of mounting /var/run/docker.sock

🧩 Docs/DX

  • Excellent README structure: Clear overview, features, and usage examples
  • Helpful visual cues: Emoji-based output makes the tool more approachable
  • Actionable improvements needed:
    • Add a section on scheduling (cron examples for nightly runs)
    • Include troubleshooting guide for common issues (permissions, Docker not running)
    • Document expected output formats for integration with monitoring tools
    • Add example for running with restricted permissions or specific Docker groups

🧱 Mocks/Fakes

  • Effective mock design: The Docker command mocking approach is well-implemented and comprehensive
  • Clear mock rationale: Good documentation explaining why mocking was necessary
  • Actionable improvements needed:
    • Fix incomplete command matching in mock:
      # Current (incomplete):
      "ps -a -f")
      # Should be:
      "ps -a -f status=exited")
    • Add validation that all required Docker subcommands are properly mocked
    • Consider adding mock verification to ensure tests don't accidentally call real Docker

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