Skip to content

Conversation

@jeremylongshore
Copy link
Contributor

@jeremylongshore jeremylongshore commented Jan 10, 2026

Summary

Implements the Tarball Helper requested in #452, providing 4 key features:

  • analyze: Detect build system (CMake, Meson, Autotools, Python, Make) and parse dependencies from build files
  • install-deps: Install missing -dev packages via apt
  • track: Record manual installations with packages used
  • cleanup: Remove tracked installations and optionally packages

Features

  • Auto-detects 6 build systems (CMake, Meson, Autotools, Make, Python, Unknown)
  • Parses find_package(), pkg_check_modules(), dependency(), AC_CHECK_*
  • Maps headers and pkg-config names to apt packages (26 common packages)
  • Suggests packaged alternatives before building from source
  • Tracks installation history in ~/.cortex/manual_builds.json

Demo

asciicast

Test Coverage

  • 71 tests with 100% code coverage
  • Tests all build system detection, parsing, installation tracking, and CLI commands

Usage

# Analyze a source directory
cortex tarball analyze /path/to/source

# Install missing dependencies
cortex tarball install-deps /path/to/source

# Track a manual installation
cortex tarball track myapp /path/to/source --packages libssl-dev zlib1g-dev

# List tracked installations
cortex tarball list

# Clean up an installation
cortex tarball cleanup myapp

AI Disclosure

This implementation was developed with assistance from Claude (Anthropic). The AI helped with:

  • Code structure and implementation patterns
  • Test case design for comprehensive coverage
  • Documentation and docstrings

All code was reviewed and the tests verify correct functionality.

Fixes #452

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added a tarball CLI for managing source builds with subcommands: analyze, install-deps, track, list, cleanup
    • Automatic build-system detection (CMake, Autotools, Meson, Python, Make) with recommended build commands
    • Dependency suggestion and install support with dry-run and persistent manual-install history
  • Documentation

    • New user guide describing usage, workflows, supported systems, and troubleshooting
  • Tests

    • Comprehensive tests covering detection, analysis, install workflows, tracking, listing, and cleanup

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 10, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

📝 Walkthrough

Walkthrough

Adds a Tarball/Source Build Helper module and CLI integration: new cortex/tarball_helper.py implements build-system detection, dependency analysis, install/track/cleanup workflows with persistent history; cortex/cli.py gains a tarball command and subcommands; tests and docs added.

Changes

Cohort / File(s) Summary
CLI Integration
cortex/cli.py
Adds CortexCLI.tarball(self, args: argparse.Namespace) -> int, registers top-level tarball command and subcommands (analyze, install-deps, track, list, cleanup), updates help output and dispatches to cortex.tarball_helper handlers.
Tarball Helper Implementation
cortex/tarball_helper.py
New module introducing BuildSystem enum, Dependency, BuildAnalysis, ManualInstall dataclasses and TarballHelper class. Implements detection for CMake/Autotools/Meson/Make/Python/UNKNOWN, per-system analyzers, dependency checks (PATH/pkg-config/dpkg), build-command generation, apt-package suggestion, dependency installation (dry-run), and persistent history at ~/.cortex/manual_builds.json. Exposes CLI entry points: run_analyze_command, run_install_deps_command, run_list_command, run_cleanup_command, run_track_command.
Tests
tests/test_tarball_helper.py
New comprehensive test suite covering enums/dataclasses, build-system detection, analyzers, build command generation, install workflows (dry-run/success/failure), alternative lookup, history tracking/listing/cleanup, and edge cases.
Documentation
docs/TARBALL_HELPER.md
New documentation describing features, usage examples for tarball subcommands, supported systems, package mappings, storage format/location for history, and troubleshooting notes.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant CLI as cortex/cli.py
    participant Helper as TarballHelper
    participant FS as Source Files
    participant Sys as pkg-config/apt/dpkg

    User->>CLI: tarball analyze <source_dir>
    CLI->>Helper: run_analyze_command(source_dir)
    Helper->>FS: read manifests (CMakeLists.txt / configure.ac / meson.build / setup.py)
    FS-->>Helper: file contents
    Helper->>Helper: detect build system, parse dependencies
    Helper->>Sys: check_installed(dependencies)
    Sys-->>Helper: installed status
    Helper-->>CLI: analysis results
    CLI-->>User: display analysis
Loading
sequenceDiagram
    participant User
    participant CLI as cortex/cli.py
    participant Helper as TarballHelper
    participant PkgMgr as apt / apt-cache
    participant History as ~/.cortex/manual_builds.json

    User->>CLI: tarball install-deps <source_dir> [--dry-run]
    CLI->>Helper: run_install_deps_command(source_dir, dry_run)
    Helper->>Helper: determine missing packages
    Helper->>PkgMgr: apt-get install (or simulate)
    PkgMgr-->>Helper: result
    Helper-->>CLI: report install outcome

    User->>CLI: tarball track <name> <source_dir> [--packages ...]
    CLI->>Helper: run_track_command(name, source_dir, packages)
    Helper->>History: _load_history()
    Helper->>History: _save_history(updated)
    Helper-->>CLI: confirm tracked

    User->>CLI: tarball cleanup <name> [--dry-run]
    CLI->>Helper: run_cleanup_command(name, dry_run)
    Helper->>History: _load_history()
    Helper->>PkgMgr: remove packages (or simulate)
    Helper->>History: _save_history(updated)
    Helper-->>CLI: cleanup result
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Suggested reviewers

  • mikejmorgan-ai
  • Anshgrover23

Poem

🐰 I sniff the tarball, find the clues inside,
I map the headers, where dev-packages hide.
I track each install, then tidy the trail—
Hop, build, and clean: a rabbit-approved tale.

🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 23.76% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title 'feat(tarball): Add tarball/source build helper (Issue #452)' is clear, specific, and directly describes the main change—adding a tarball helper feature.
Description check ✅ Passed The PR description is comprehensive, covering summary, features, usage, test coverage, and AI disclosure. However, the 'Related Issue' section (required by template) is not explicitly included as a separate field.
Linked Issues check ✅ Passed All coding objectives from Issue #452 are met: build system detection and parsing implemented [cortex/tarball_helper.py], missing -dev package installation [cortex/tarball_helper.py], manual installation tracking [cortex/tarball_helper.py], and package alternative suggestions [cortex/tarball_helper.py].
Out of Scope Changes check ✅ Passed All changes are within scope of Issue #452 requirements. The new tarball helper feature, CLI integration, comprehensive tests, and documentation are directly aligned with the stated objectives.

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


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.

@github-actions
Copy link

github-actions bot commented Jan 10, 2026

CLA Verification Passed

All contributors have signed the CLA.

Contributor Signed As
@jeremylongshore @jeremylongshore
@Anshgrover23 @Anshgrover23

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @jeremylongshore, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a powerful new cortex tarball command-line utility designed to simplify the often complex process of building software from source code. It provides intelligent analysis of various build systems to identify dependencies, automates the installation of missing development packages, and offers robust tracking and cleanup mechanisms for manual installations. This feature aims to significantly reduce the friction and manual effort involved in managing custom-built software.

Highlights

  • New cortex tarball command: Introduces a new top-level command cortex tarball with subcommands to assist with building software from source.
  • Automated Dependency Analysis: The analyze subcommand automatically detects build systems (CMake, Meson, Autotools, Python, Make) and parses dependencies from their respective build files.
  • Missing Dependency Installation: The install-deps subcommand identifies and installs missing development packages via apt, streamlining the setup process for source builds.
  • Manual Installation Tracking & Cleanup: Provides track and cleanup subcommands to record manual installations and their associated packages, enabling easy removal later.
  • Packaged Alternative Suggestions: The tool suggests official apt packaged alternatives when available, encouraging the use of system packages over manual builds.
  • Comprehensive Test Coverage: The new functionality is thoroughly tested with 71 unit tests, achieving 100% code coverage to ensure reliability.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
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 introduces a powerful tarball helper to analyze and manage dependencies for source builds. The implementation is well-structured with a dedicated tarball_helper module and comprehensive test coverage. The code is clear and the feature is a great addition to the CLI.

My review focuses on improving the robustness of the implementation. I've identified some areas for improvement:

  • The dependency parsing logic in tarball_helper.py uses regular expressions that are too simple for complex, real-world build files, which could lead to missed dependencies.
  • The test suite for this parsing logic could be expanded to cover these more complex cases.
  • In cli.py, the exception handling is overly broad, and a minor logic improvement can make package name parsing more robust.

Overall, this is a very strong contribution. Addressing these points will make the new feature even more reliable.

content = cmake_file.read_text(encoding="utf-8", errors="ignore")

# Find find_package() calls
for match in re.finditer(r"find_package\s*\(\s*(\w+)", content, re.IGNORECASE):
Copy link
Contributor

Choose a reason for hiding this comment

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

high

The regular expression used for find_package is a bit too simple and may fail on common CMake syntax, leading to missed dependencies. For example, it won't match package names containing hyphens or numbers if not at the end (e.g., Qt5-Core), and it doesn't correctly handle arguments that follow the package name.

A more robust regex that captures the first argument would handle more cases. A similar issue exists with the pkg_check_modules regex on line 261, which can fail to find all packages if multiple are listed.

Suggested change
for match in re.finditer(r"find_package\s*\(\s*(\w+)", content, re.IGNORECASE):
for match in re.finditer(r"find_package\s*\(\s*([^\s\)]+)", content, re.IGNORECASE):

Comment on lines +623 to +671
if action == "analyze":
try:
run_analyze_command(args.source_dir)
return 0
except Exception as e:
console.print(f"[red]Error: {e}[/red]")
return 1

elif action == "install-deps":
try:
run_install_deps_command(
args.source_dir,
dry_run=getattr(args, "dry_run", False),
)
return 0
except Exception as e:
console.print(f"[red]Error: {e}[/red]")
return 1

elif action == "track":
try:
packages = []
if hasattr(args, "packages") and args.packages:
packages = args.packages.split(",")
run_track_command(args.name, args.source_dir, packages)
return 0
except Exception as e:
console.print(f"[red]Error: {e}[/red]")
return 1

elif action == "list":
try:
run_list_command()
return 0
except Exception as e:
console.print(f"[red]Error: {e}[/red]")
return 1

elif action == "cleanup":
try:
run_cleanup_command(
args.name,
dry_run=getattr(args, "dry_run", False),
)
return 0
except Exception as e:
console.print(f"[red]Error: {e}[/red]")
return 1

Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The repeated use of except Exception as e is too broad. It can catch and hide unexpected errors, including SystemExit or KeyboardInterrupt, making debugging difficult. It's better to catch more specific exceptions that you expect from the tarball_helper functions (like ValueError or FileNotFoundError) and let other exceptions propagate to a higher-level handler. If you must catch a broad exception, consider logging the full traceback when in verbose mode to aid debugging.

try:
packages = []
if hasattr(args, "packages") and args.packages:
packages = args.packages.split(",")
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

When splitting the packages string, it's a good practice to strip whitespace from each package name. This makes the input more robust against variations like "pkg1, pkg2" (with a space).

Suggested change
packages = args.packages.split(",")
packages = [p.strip() for p in args.packages.split(",")]

Comment on lines +133 to +166
class TestAnalyzeCMake:
"""Test CMake analysis."""

def test_analyze_cmake_find_package(self, tmp_path):
cmake_content = """
cmake_minimum_required(VERSION 3.10)
project(MyProject)
find_package(OpenSSL REQUIRED)
find_package(ZLIB)
"""
(tmp_path / "CMakeLists.txt").write_text(cmake_content)

helper = TarballHelper()
with patch.object(helper, "_check_installed"):
analysis = helper.analyze(tmp_path)

assert analysis.build_system == BuildSystem.CMAKE
pkg_names = [d.name for d in analysis.dependencies]
assert "openssl" in pkg_names
assert "zlib" in pkg_names

def test_analyze_cmake_pkg_check_modules(self, tmp_path):
cmake_content = """
pkg_check_modules(GLIB REQUIRED glib-2.0)
"""
(tmp_path / "CMakeLists.txt").write_text(cmake_content)

helper = TarballHelper()
with patch.object(helper, "_check_installed"):
analysis = helper.analyze(tmp_path)

pkg_names = [d.name for d in analysis.dependencies]
assert "glib-2.0" in pkg_names

Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The tests for _analyze_cmake are good, but they only cover simple cases that the current regular expressions can handle. To make the test suite more robust and catch the fragility of the regex-based parsing, consider adding test cases with more complex, real-world CMakeLists.txt syntax.

Examples of valuable test cases to add:

  • find_package with package names containing numbers and hyphens (e.g., find_package(Qt5-Core)).
  • pkg_check_modules with multiple packages listed (e.g., pkg_check_modules(GSTREAMER gstreamer-1.0 gstreamer-video-1.0)).
  • find_package with version numbers and components (e.g., find_package(Boost 1.71.0 REQUIRED COMPONENTS program_options)).

Adding these would help ensure the dependency analysis is reliable across a wider range of projects.

Copy link
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: 0

🧹 Nitpick comments (7)
tests/test_tarball_helper.py (2)

264-277: Consider adding assertion for the subprocess command.

The success and failure tests mock subprocess.run but don't verify the command arguments. Consider adding an assertion to confirm the correct apt-get command is constructed.

💡 Optional enhancement
     def test_install_deps_success(self):
         helper = TarballHelper()
         mock_result = MagicMock(returncode=0)
-        with patch("subprocess.run", return_value=mock_result):
+        with patch("subprocess.run", return_value=mock_result) as mock_run:
             result = helper.install_dependencies(["zlib1g-dev"])
+        mock_run.assert_called_once()
+        assert "apt-get" in mock_run.call_args[0][0]
         assert result is True

375-410: Run command tests verify no exceptions are raised but lack output assertions.

These tests confirm the commands execute without error, which is valuable. For higher confidence, consider capturing console output and verifying expected content is printed.

cortex/tarball_helper.py (5)

317-324: AC_CHECK_LIB mapping may not always find apt packages.

The code tries to find apt package as lib{lib_name} in PKGCONFIG_PACKAGES, but many libraries (e.g., zzlib, cryptolibssl-dev) don't follow this pattern. The mapping may miss some packages.

This is a minor limitation since the tool still identifies the dependency; apt package suggestion just won't always work.

Consider expanding the library-to-package mapping for common cases like zzlib1g-dev, cryptolibssl-dev.


374-386: Consider adding timeout to subprocess calls.

The subprocess.run calls for pkg-config and dpkg-query don't specify a timeout. While these are typically fast, in edge cases (broken dpkg, stale locks) they could hang indefinitely.

💡 Add timeout to prevent potential hangs
             elif dep.dep_type == "pkg-config" and dep.apt_package:
                 # Check via pkg-config
                 result = subprocess.run(
                     ["pkg-config", "--exists", dep.name],
                     capture_output=True,
+                    timeout=5,
                 )
                 dep.found = result.returncode == 0
             elif dep.apt_package:
                 # Check if apt package is installed
                 result = subprocess.run(
                     ["dpkg-query", "-W", "-f=${Status}", dep.apt_package],
                     capture_output=True,
                     text=True,
+                    timeout=5,
                 )

448-451: Consider providing error feedback on installation failure.

When apt-get install fails, the method returns False but doesn't provide any feedback to the user about what went wrong. The apt output would have been shown, but a follow-up message might help.

💡 Optional: Add failure message
     result = subprocess.run(cmd)
-    return result.returncode == 0
+    if result.returncode != 0:
+        console.print("[red]Package installation failed. Check the output above for details.[/red]")
+        return False
+    return True

552-565: History removal happens before package removal confirmation.

The installation is removed from history (line 553-554) before the package removal prompt. If the user declines package removal or if it fails, the history is still lost.

Consider: Should the tracking entry be preserved if the user declines to remove packages?

💡 Optional: Delay history removal
-        # Remove from history
-        del history[name]
-        self._save_history(history)
-
-        console.print(f"[green]Removed '{name}' from tracking.[/green]")
-
         if packages:
             remove_pkgs = Confirm.ask(
                 f"Remove {len(packages)} packages that were installed for this build?"
             )
             if remove_pkgs:
                 cmd = ["sudo", "apt-get", "remove", "-y"] + packages
                 subprocess.run(cmd)

+        # Remove from history after user decisions
+        del history[name]
+        self._save_history(history)
+        console.print(f"[green]Removed '{name}' from tracking.[/green]")
+
         return True

577-580: Consider specifying encoding for write_text.

_load_history doesn't specify encoding for read_text(), and _save_history doesn't specify encoding for write_text(). While Python 3 defaults to UTF-8 on most systems, explicit encoding ensures consistency.

💡 Optional: Explicit encoding
     def _load_history(self) -> dict:
         """Load installation history from file."""
         if not self.history_file.exists():
             return {}
         try:
-            return json.loads(self.history_file.read_text())
+            return json.loads(self.history_file.read_text(encoding="utf-8"))
         except (json.JSONDecodeError, OSError):
             return {}

     def _save_history(self, history: dict) -> None:
         """Save installation history to file."""
-        self.history_file.write_text(json.dumps(history, indent=2))
+        self.history_file.write_text(json.dumps(history, indent=2), encoding="utf-8")
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8676bb2 and f301d08.

📒 Files selected for processing (3)
  • cortex/cli.py
  • cortex/tarball_helper.py
  • tests/test_tarball_helper.py
🧰 Additional context used
📓 Path-based instructions (2)
**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

**/*.py: Follow PEP 8 style guide
Type hints required in Python code
Docstrings required for all public APIs

Files:

  • cortex/cli.py
  • tests/test_tarball_helper.py
  • cortex/tarball_helper.py
tests/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Maintain >80% test coverage for pull requests

Files:

  • tests/test_tarball_helper.py
🧬 Code graph analysis (2)
cortex/cli.py (1)
cortex/tarball_helper.py (5)
  • run_analyze_command (582-647)
  • run_cleanup_command (699-707)
  • run_install_deps_command (650-670)
  • run_list_command (673-696)
  • run_track_command (710-726)
cortex/tarball_helper.py (1)
cortex/branding.py (1)
  • cx_header (82-88)
🔇 Additional comments (18)
cortex/cli.py (3)

604-685: LGTM! Clean implementation following existing patterns.

The tarball() method correctly:

  • Uses lazy imports to avoid loading tarball_helper unless needed
  • Handles each subcommand with try/except for error resilience
  • Returns appropriate exit codes (0 for success, 1 for error)
  • Provides helpful usage info when no action is specified

The structure is consistent with existing command handlers like sandbox() and notify().


2357-2399: Argument parser definitions are well-structured.

The tarball subcommands are defined consistently with other CLI subcommands. The --packages argument for track uses comma-separated values which is handled in the tarball() method via args.packages.split(",").


2662-2663: Command routing is correct.

tests/test_tarball_helper.py (6)

1-25: Well-organized test file with comprehensive imports.

The test file follows good practices:

  • Clear module docstring explaining purpose
  • All necessary imports from the module under test
  • Proper use of pytest and unittest.mock

27-74: Good dataclass and enum tests.

These tests verify the basic data structures work correctly with default values and full initialization.


85-131: Comprehensive build system detection tests.

All six build system types are tested, plus the error case for invalid paths. The tests correctly use tmp_path for isolation.


133-218: Analysis tests cover the main parsing patterns well.

The tests mock _check_installed appropriately to avoid external tool calls during testing, while still verifying the parsing logic extracts dependencies correctly.


451-827: Excellent edge case coverage.

The advanced test classes thoroughly cover:

  • Empty build files
  • Missing configuration files
  • Corrupt JSON history
  • Command-line scenarios with missing directories
  • Various fallback behaviors

This provides good confidence in error handling paths.


829-830: Good test entry point.

cortex/tarball_helper.py (9)

1-24: Well-structured module with clear imports and organization.

The module docstring explains the purpose, and imports are organized logically. Using rich for console output aligns with the rest of the codebase.


26-94: Well-designed data models with proper type hints and docstrings.

The dataclasses correctly:

  • Use field(default_factory=list) for mutable default arguments
  • Include comprehensive docstrings as required by the coding guidelines
  • Use Optional[str] for nullable fields

96-171: Good class design with comprehensive package mappings.

The class follows good patterns:

  • Clear docstring explaining purpose
  • Class-level constants for mappings (26 common packages)
  • Safe directory creation in __init__

172-199: Clean build system detection with sensible priority order.

The detection order prioritizes more specific build systems (CMake, Meson) before generic ones (Makefile), which is correct since a project might have both.


200-243: Well-structured analysis orchestration.

The analyze method cleanly:

  • Resolves paths to absolute
  • Delegates to specific analyzers
  • Checks installation status
  • Collects missing packages (with deduplication)
  • Generates appropriate build commands

244-282: Good CMake parsing for common patterns.

The regex patterns correctly handle:

  • find_package(OpenSSL REQUIRED)
  • pkg_check_modules(GLIB REQUIRED glib-2.0)
  • CHECK_INCLUDE_FILE("zlib.h" HAVE_ZLIB)

Using errors="ignore" is appropriate for potentially mixed-encoding build files.


453-488: Good alternative package detection with sensible fallbacks.

The method:

  1. First tries exact name match
  2. Falls back to lib{name} prefix
  3. Prefers -dev packages for build dependencies

This covers common scenarios well.


582-648: Well-formatted analysis output with rich components.

The run_analyze_command function provides excellent user experience:

  • Shows build system detected
  • Suggests packaged alternatives when available
  • Displays dependencies in a formatted table
  • Shows missing packages with install command
  • Lists build commands

650-726: Clean command functions delegating to TarballHelper.

All run_* functions follow a consistent pattern:

  • Validate inputs
  • Create TarballHelper instance
  • Delegate to appropriate method
  • Handle output/feedback

Copy link
Collaborator

@Anshgrover23 Anshgrover23 left a comment

Choose a reason for hiding this comment

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

@jeremylongshore Documentation missing, also Kindly address bot comments.

@jeremylongshore
Copy link
Contributor Author

Thanks for the review! I've addressed all the feedback:

Bot comment fixes:

  • ✅ Added 5s timeouts to pkg-config and dpkg-query subprocess calls
  • ✅ Added error feedback message when apt-get install fails
  • ✅ Fixed history removal timing - now happens after user confirms/declines package removal
  • ✅ Added explicit UTF-8 encoding to history file read/write operations

Documentation:

  • ✅ Added comprehensive docs/TARBALL_HELPER.md covering all commands, build system detection, dependency mappings, and workflow examples

All 71 tests passing with 99% code coverage. Ready for re-review.

Copy link
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: 0

🧹 Nitpick comments (1)
docs/TARBALL_HELPER.md (1)

120-120: Consider using lowercase for CMake function names.

While CMake is case-insensitive, the convention is to use lowercase for function names. check_include_file() is more commonly seen in CMake documentation than CHECK_INCLUDE_FILE().

📝 Minor documentation improvement
-| CMake | `CMakeLists.txt` | `find_package()`, `pkg_check_modules()`, `CHECK_INCLUDE_FILE()` |
+| CMake | `CMakeLists.txt` | `find_package()`, `pkg_check_modules()`, `check_include_file()` |
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f301d08 and bc6159c.

📒 Files selected for processing (2)
  • cortex/tarball_helper.py
  • docs/TARBALL_HELPER.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • cortex/tarball_helper.py
🔇 Additional comments (6)
docs/TARBALL_HELPER.md (6)

1-52: Excellent introduction and quick start section.

The overview clearly communicates the tool's purpose and key features. The quick start example is comprehensive, showing the complete workflow from analysis through cleanup with realistic output. The progression is logical and immediately demonstrates value to users.


54-115: Clear and comprehensive command documentation.

All five commands are well documented with usage examples and options. The structure is consistent, making it easy for users to find the information they need.


126-161: Build commands are accurate and helpful.

The build commands for each system follow standard practices and include helpful notes (like the autoreconf step for Autotools). This will guide users effectively through the build process.


162-200: Dependency mappings are accurate and comprehensive.

The header-to-package, pkg-config-to-package, and build-tool mappings are correct for Debian/Ubuntu systems. This will be very helpful for users trying to resolve build dependencies.


201-246: Storage format and workflow example are well documented.

The JSON storage format is clearly documented with all fields explained. The nginx workflow example is particularly valuable—it walks through a complete real-world scenario from download to cleanup, including the helpful reminder about considering packaged alternatives.


248-283: Limitations and troubleshooting sections add valuable context.

The documentation honestly acknowledges the tool's limitations, which helps set appropriate user expectations. The troubleshooting section addresses likely pain points with practical solutions, including correct apt-cache commands for manual investigation.

jeremylongshore added a commit to jeremylongshore/cortex that referenced this pull request Jan 12, 2026
Adding myself to enable CLA checks on PRs cortexlinux#557 and cortexlinux#558.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@jeremylongshore
Copy link
Contributor Author

@Anshgrover23 I've addressed all feedback:

Once #568 is merged, the CLA check will pass. Ready for re-review!

Copy link
Collaborator

@Anshgrover23 Anshgrover23 left a comment

Choose a reason for hiding this comment

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

@jeremylongshore CI is failing.

Anshgrover23 pushed a commit that referenced this pull request Jan 12, 2026
Adding myself to enable CLA checks on PRs #557 and #558.

Co-authored-by: jeremylongshore <jeremylongshore@users.noreply.github.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Copy link
Collaborator

@Anshgrover23 Anshgrover23 left a comment

Choose a reason for hiding this comment

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

@jeremylongshore Address coderabbit comments.

@jeremylongshore
Copy link
Contributor Author

CLA PR #568 has been merged. Could you please re-run the CLA check? Thanks!

@jeremylongshore
Copy link
Contributor Author

recheck

@jeremylongshore
Copy link
Contributor Author

Same issue as #557 - the CLA failure is due to Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> in commits. Claude is an AI assistant.

Could noreply@anthropic.com be added to the bot allowlist, or should I rebase to remove the Co-Authored-By trailers?

ShreeJejurikar pushed a commit to ShreeJejurikar/cortex that referenced this pull request Jan 12, 2026
Adding myself to enable CLA checks on PRs cortexlinux#557 and cortexlinux#558.

Co-authored-by: jeremylongshore <jeremylongshore@users.noreply.github.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Implements issue cortexlinux#452 - Tarball Helper with 4 key features:

1. analyze: Detect build system (CMake, Meson, Autotools, Python, Make)
   and parse dependencies from build files
2. install-deps: Install missing -dev packages via apt
3. track: Record manual installations with packages used
4. cleanup: Remove tracked installations and optionally packages

Features:
- Auto-detects 6 build systems (CMake, Meson, Autotools, Make, Python, Unknown)
- Parses find_package(), pkg_check_modules(), dependency(), AC_CHECK_*
- Maps headers and pkg-config names to apt packages
- Suggests packaged alternatives before building from source
- Tracks installation history in ~/.cortex/manual_builds.json

Demo: https://asciinema.org/a/rFzQXtU4HqmrRscL
- Add timeouts (5s) to pkg-config and dpkg-query subprocess calls
- Add error feedback message when apt-get install fails
- Fix history removal timing: move deletion after user interactions
- Add explicit UTF-8 encoding to history file read/write operations
- Add comprehensive documentation in docs/TARBALL_HELPER.md
@jeremylongshore
Copy link
Contributor Author

Rebased and removed the Co-Authored-By trailers. CLA check is now passing. Ready for review!

Copy link
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

🤖 Fix all issues with AI agents
In @cortex/tarball_helper.py:
- Around line 51-53: Change the type annotation for the variable apt_package
from Optional[str] to the PEP 604 union style str | None, and then remove the
now-unused Optional import from the top-level imports as well as the other
unused Optional import elsewhere in the module (the remaining import that was
only used for Optional). Ensure no other references to Optional remain before
committing.
- Around line 466-500: The return type annotation for find_alternative should
use the PEP 604 union syntax instead of Optional: change the signature from def
find_alternative(self, name: str) -> Optional[str]: to def
find_alternative(self, name: str) -> str | None: and update imports/usages
accordingly (remove or replace typing.Optional import and any other references
to Optional in this file) so the linter stops flagging the annotation.
🧹 Nitpick comments (4)
cortex/tarball_helper.py (4)

366-394: Consider handling missing pkg-config or dpkg-query commands.

If pkg-config or dpkg-query are not installed, subprocess.run will raise FileNotFoundError. This could cause the entire analysis to fail on minimal systems.

♻️ Proposed fix to handle missing commands gracefully
             elif dep.dep_type == "pkg-config" and dep.apt_package:
                 # Check via pkg-config
                 try:
                     result = subprocess.run(
                         ["pkg-config", "--exists", dep.name],
                         capture_output=True,
                         timeout=5,
                     )
                     dep.found = result.returncode == 0
-                except subprocess.TimeoutExpired:
+                except (subprocess.TimeoutExpired, FileNotFoundError):
                     dep.found = False
             elif dep.apt_package:
                 # Check if apt package is installed
                 try:
                     result = subprocess.run(
                         ["dpkg-query", "-W", "-f=${Status}", dep.apt_package],
                         capture_output=True,
                         text=True,
                         timeout=5,
                     )
                     dep.found = "install ok installed" in result.stdout
-                except subprocess.TimeoutExpired:
+                except (subprocess.TimeoutExpired, FileNotFoundError):
                     dep.found = False

565-580: Consider checking the result of package removal.

The apt-get remove command result is not checked. If removal fails, the user won't get feedback, yet the installation is still removed from history.

♻️ Proposed improvement
         if packages:
             remove_pkgs = Confirm.ask(
                 f"Remove {len(packages)} packages that were installed for this build?"
             )
             if remove_pkgs:
                 cmd = ["sudo", "apt-get", "remove", "-y"] + packages
-                subprocess.run(cmd)
+                result = subprocess.run(cmd)
+                if result.returncode != 0:
+                    console.print("[yellow]Warning: Package removal may have failed.[/yellow]")

         # Remove from history after all user interactions
         del history[name]
         self._save_history(history)

591-593: Consider handling write errors in _save_history.

If the write fails (disk full, permission denied), the exception will propagate up and could leave the system in an inconsistent state where packages were removed but history wasn't updated.

♻️ Suggested improvement
     def _save_history(self, history: dict) -> None:
         """Save installation history to file."""
-        self.history_file.write_text(json.dumps(history, indent=2), encoding="utf-8")
+        try:
+            self.history_file.write_text(json.dumps(history, indent=2), encoding="utf-8")
+        except OSError as e:
+            console.print(f"[red]Warning: Failed to save history: {e}[/red]")

617-619: Name extraction may be inaccurate for hyphenated software names.

The logic path.name.split("-")[0] assumes the pattern name-version, but software like nginx-1.25.3 works while my-cool-app-1.0 would extract just my instead of my-cool-app.

This is a heuristic and may not always work perfectly. Consider documenting this limitation or using a more sophisticated version-detection regex if accuracy is important.

# Alternative approach - split on version-like patterns
import re
dir_name = re.split(r'-\d', path.name)[0]  # Split on hyphen followed by digit
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bc6159c and 2b20c2a.

📒 Files selected for processing (4)
  • cortex/cli.py
  • cortex/tarball_helper.py
  • docs/TARBALL_HELPER.md
  • tests/test_tarball_helper.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/test_tarball_helper.py
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

**/*.py: Follow PEP 8 style guide
Type hints required in Python code
Docstrings required for all public APIs

Files:

  • cortex/tarball_helper.py
  • cortex/cli.py
🧬 Code graph analysis (2)
cortex/tarball_helper.py (1)
cortex/branding.py (1)
  • cx_header (82-88)
cortex/cli.py (1)
cortex/tarball_helper.py (5)
  • run_analyze_command (596-661)
  • run_cleanup_command (713-721)
  • run_install_deps_command (664-684)
  • run_list_command (687-710)
  • run_track_command (724-740)
🪛 GitHub Actions: CI
cortex/tarball_helper.py

[error] 51-51: ruff check failed: UP045 Use X | None for type annotations.

🪛 GitHub Check: lint
cortex/tarball_helper.py

[failure] 466-466: Ruff (UP045)
cortex/tarball_helper.py:466:46: UP045 Use X | None for type annotations


[failure] 51-51: Ruff (UP045)
cortex/tarball_helper.py:51:18: UP045 Use X | None for type annotations

🪛 GitHub Check: Lint
cortex/tarball_helper.py

[failure] 466-466: Ruff (UP045)
cortex/tarball_helper.py:466:46: UP045 Use X | None for type annotations


[failure] 51-51: Ruff (UP045)
cortex/tarball_helper.py:51:18: UP045 Use X | None for type annotations

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: test (3.10)
  • GitHub Check: test (3.11)
  • GitHub Check: test (3.12)
🔇 Additional comments (8)
docs/TARBALL_HELPER.md (1)

1-283: LGTM! Comprehensive and well-structured documentation.

The documentation thoroughly covers the Tarball Helper feature including usage examples, supported build systems, dependency mappings, and troubleshooting guidance. The content aligns with the implementation in cortex/tarball_helper.py.

cortex/cli.py (3)

604-685: LGTM! Well-structured command handler following existing patterns.

The tarball() method:

  • Uses lazy imports for cortex.tarball_helper to avoid impacting CLI startup time
  • Follows the same dispatch pattern as sandbox() and other handlers
  • Includes proper docstring with type hints
  • Provides helpful fallback help text when no action is specified

2357-2399: LGTM! Argument parser configuration is complete and consistent.

The tarball subcommand parser follows the established patterns used for sandbox and other command groups. All five subcommands (analyze, install-deps, track, list, cleanup) are properly configured with appropriate arguments.


2662-2663: LGTM! Command routing correctly wired.

The tarball command is properly routed to cli.tarball(args) in the main dispatch block.

cortex/tarball_helper.py (4)

56-93: LGTM! Dataclasses are well-defined.

Proper use of field(default_factory=list) for mutable default values, and comprehensive docstrings for all attributes.


167-198: LGTM! Initialization and build system detection are sound.

The __init__ safely creates the config directory, and detect_build_system properly validates the input and checks build files in a sensible priority order.


200-242: LGTM! Analysis flow is well-structured.

The analyze method properly dispatches to build-system-specific analyzers. Note that BuildSystem.MAKE intentionally has no specialized analyzer since Makefiles don't have standardized dependency declarations.


724-740: LGTM! Track command is straightforward and correct.

Properly creates a ManualInstall record with current timestamp and delegates to track_installation.

@Anshgrover23 Anshgrover23 marked this pull request as draft January 12, 2026 07:40
@sonarqubecloud
Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
11 Security Hotspots

See analysis details on SonarQube Cloud

Copy link
Collaborator

@Anshgrover23 Anshgrover23 left a comment

Choose a reason for hiding this comment

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

@jeremylongshore Your SonarQubeCloud Quality Gate is failing kindly address that issues. Also address coderabbit comments that are still open.

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.

Tarball/Manual Build Helper

2 participants