Skip to content

Conversation

@kvaps
Copy link
Member

@kvaps kvaps commented Dec 24, 2025

Signed-off-by: Andrei Kvapil kvapss@gmail.com

What this PR does

Release note

[cozypkg] Add tool for managing Package and PackageSources

Summary by CodeRabbit

  • New Features
    • New cozy CLI with entrypoint and root command.
    • Interactive "add" command to install packages from args or files, with dependency resolution, topological install order, variant selection, and progress feedback.
    • "del" command to remove packages safely, including dependent analysis, confirmation prompts, and safe delete ordering.
    • "list" command to show available or installed packages, with optional per-component output and concise status lines.
    • "dependencies" command to emit Graphviz DOT graphs of package/component relationships.
    • Common flags: kubeconfig, file inputs, --installed and --components where applicable.

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

@dosubot dosubot bot added the size:XXL This PR changes 1000+ lines, ignoring generated files. label Dec 24, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 24, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

📝 Walkthrough

Walkthrough

Adds a new "cozypkg" CLI with subcommands: add (interactive install with dependency resolution and file input), del (safe delete respecting dependents), list (list PackageSource or installed Package), and dot (emit Graphviz DOT). Also adds root entrypoint and updates go.mod with a DOT library.

Changes

Cohort / File(s) Summary
CLI Entrypoint & Root
cmd/cozypkg/main.go, cmd/cozypkg/cmd/root.go
Adds program entrypoint and Cobra root command with Execute() orchestration and stderr error handling.
Package Installation (add)
cmd/cozypkg/cmd/add.go
New add command: reads positional args and -f files/dirs (single/multi-doc YAML), builds kube client, parses Package/PackageSource, constructs dependency trees, topologically sorts (cycle detection), supports interactive variant selection, attempts direct Package creation from file with interactive fallback, and reports progress.
Package Deletion (del)
cmd/cozypkg/cmd/del.go
New del command: reads names and -f inputs, builds kube client, lists installed Packages, computes dependents set, prompts confirmation, computes reverse topological delete order, and deletes packages with per-item error handling.
Listing (list)
cmd/cozypkg/cmd/list.go
New list command: lists PackageSource or installed Package resources (--installed), supports --components, formats columns, derives ready/status from conditions, truncates long fields, and emits component lines when requested.
Dependency Graph (dot)
cmd/cozypkg/cmd/dependencies.go
New dot command: builds cluster dependency graph from PackageSource/Package resources, supports --installed, --components, selection via args or -f, collects variant/component-level edges (handles local and external references and missing targets), annotates variant-specific edges, and emits Graphviz DOT using github.com/emicklei/dot.
Module Dependencies
go.mod
Adds github.com/emicklei/dot v1.10.0 for DOT graph generation.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant CLI as "cozypkg (add/del/dot/list)"
    participant FS as FileSystem
    participant K8s as "Kubernetes API"
    participant Resolver as "DependencyResolver"
    participant Interactive as "VariantSelector"

    User->>CLI: invoke command (e.g., add pkgA -f pkgs.yaml)
    CLI->>FS: read args & files (YAML docs)
    FS-->>CLI: package identifiers / YAML docs

    CLI->>K8s: build client & fetch PackageSource/Package resources
    K8s-->>CLI: resources

    rect rgb(220,235,255)
    Note over Resolver: Dependency analysis (buildDependencyTree, topologicalSort)
    CLI->>Resolver: build dependency graph & sort
    Resolver-->>CLI: install/delete order or cycle error
    end

    rect rgb(255,245,220)
    Note over Interactive: Interactive flow (add command)
    loop per item in order
        CLI->>Interactive: prompt for variant (if needed)
        Interactive-->>CLI: selected variant
        CLI->>K8s: create/delete Package resource
        K8s-->>CLI: result
        CLI-->>User: progress/status
    end
    end

    CLI-->>User: final summary / DOT output
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐇
I nibbled YAML leaves beneath the moon,
Sorted roots and branches, humming a tune.
Chose variants, planted each tidy row,
Watched graphs and packages quietly grow.
Hooray — the cozy trees all glow!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 45.45% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ 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 accurately summarizes the main changes—adding a new CLI tool (cozypkg) for managing Package and PackageSource resources with commands for add, delete, list, and dependency visualization.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch cozypkg-new

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8f89395 and d3f1b82.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (7)
  • cmd/cozypkg/cmd/add.go
  • cmd/cozypkg/cmd/del.go
  • cmd/cozypkg/cmd/dependencies.go
  • cmd/cozypkg/cmd/list.go
  • cmd/cozypkg/cmd/root.go
  • cmd/cozypkg/main.go
  • go.mod
🚧 Files skipped from review as they are similar to previous changes (2)
  • go.mod
  • cmd/cozypkg/cmd/root.go
🧰 Additional context used
📓 Path-based instructions (2)
cmd/**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

Follow controller-runtime patterns and kubebuilder style for Go code in cmd directory

Files:

  • cmd/cozypkg/main.go
  • cmd/cozypkg/cmd/dependencies.go
  • cmd/cozypkg/cmd/add.go
  • cmd/cozypkg/cmd/del.go
  • cmd/cozypkg/cmd/list.go
**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

Do NOT manually edit vendor/ directory or auto-generated files (zz_generated.*.go)

Files:

  • cmd/cozypkg/main.go
  • cmd/cozypkg/cmd/dependencies.go
  • cmd/cozypkg/cmd/add.go
  • cmd/cozypkg/cmd/del.go
  • cmd/cozypkg/cmd/list.go
🧠 Learnings (3)
📚 Learning: 2025-06-04T06:22:17.306Z
Learnt from: lllamnyp
Repo: cozystack/cozystack PR: 1025
File: packages/apps/kafka/charts/cozy-lib:1-1
Timestamp: 2025-06-04T06:22:17.306Z
Learning: Files in packages/apps/*/charts/cozy-lib that contain the path "../../../library/cozy-lib" are symbolic links, not regular files. Git diffs may display symlinks as regular files with their target path as content, which can be misleading in code review.

Applied to files:

  • cmd/cozypkg/cmd/dependencies.go
📚 Learning: 2025-12-25T09:45:26.511Z
Learnt from: CR
Repo: cozystack/cozystack PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-25T09:45:26.511Z
Learning: Applies to pkg/**/*.go : Follow controller-runtime patterns and kubebuilder style for Go code in pkg directory

Applied to files:

  • cmd/cozypkg/cmd/add.go
📚 Learning: 2025-12-25T09:45:26.511Z
Learnt from: CR
Repo: cozystack/cozystack PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-25T09:45:26.511Z
Learning: Applies to cmd/**/*.go : Follow controller-runtime patterns and kubebuilder style for Go code in cmd directory

Applied to files:

  • cmd/cozypkg/cmd/add.go
  • cmd/cozypkg/cmd/del.go
🧬 Code graph analysis (4)
cmd/cozypkg/main.go (1)
cmd/cozypkg/cmd/root.go (1)
  • Execute (38-44)
cmd/cozypkg/cmd/dependencies.go (5)
internal/sse/server.go (1)
  • Options (17-44)
pkg/apiserver/apiserver.go (1)
  • Scheme (53-53)
api/v1alpha1/package_types.go (1)
  • PackageList (43-47)
api/v1alpha1/packagesource_types.go (1)
  • PackageSourceList (42-46)
pkg/apis/apps/install/install.go (1)
  • Install (26-29)
cmd/cozypkg/cmd/add.go (4)
internal/sse/server.go (1)
  • Options (17-44)
pkg/apiserver/apiserver.go (1)
  • Scheme (53-53)
api/v1alpha1/packagesource_types.go (3)
  • PackageSource (31-37)
  • PackageSourceList (42-46)
  • Variant (65-82)
api/v1alpha1/package_types.go (3)
  • Package (32-38)
  • PackageList (43-47)
  • PackageSpec (54-69)
cmd/cozypkg/cmd/list.go (2)
api/v1alpha1/packagesource_types.go (3)
  • PackageSourceList (42-46)
  • PackageSource (31-37)
  • Variant (65-82)
api/v1alpha1/package_types.go (1)
  • PackageList (43-47)
⏰ 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). (1)
  • GitHub Check: Build
🔇 Additional comments (3)
cmd/cozypkg/main.go (1)

25-29: LGTM! Clean CLI entrypoint.

The implementation follows standard Go CLI patterns with appropriate error handling delegation to the cmd package.

cmd/cozypkg/cmd/del.go (1)

71-74: Good user experience with duplicate package warnings.

Warning users when a package is defined in multiple files helps prevent confusion and unexpected behavior.

cmd/cozypkg/cmd/dependencies.go (1)

443-461: Robust package detection logic.

The isPackage helper function uses the packageNames map for lookups rather than hardcoded prefixes, making it flexible and maintainable.


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.

@dosubot dosubot bot added the enhancement New feature or request label Dec 24, 2025
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @kvaps, 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 cozypkg, a new command-line tool designed to streamline the management of Cozystack Package and PackageSource custom resources within a Kubernetes environment. It provides essential functionalities for installing packages with interactive dependency resolution, deleting existing packages, listing available and installed packages, and visualizing package dependencies through Graphviz DOT output. This tool aims to enhance the developer and operator experience by simplifying package lifecycle management.

Highlights

  • New CLI Tool: Introduces cozypkg, a new command-line interface for managing Cozystack packages.
  • Package Installation (add command): Provides an add command to interactively install PackageSource resources and their dependencies, including variant selection. It also supports direct Package creation from files.
  • Package Deletion (del command): Adds a del command to remove Package resources from the cluster.
  • Package Listing (list command): Implements a list command to display PackageSource and Package resources in a tabular format, with options to show components.
  • Dependency Graph Visualization (dot command): Introduces a dot command to generate Graphviz DOT format output for package and component dependencies, useful for visualization.
  • Dependency Resolution: Includes logic for building and topologically sorting dependency trees for PackageSource resources.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

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 cozypkg, a new CLI tool for managing Cozystack packages. The implementation is well-structured, using cobra for commands and controller-runtime for Kubernetes interactions. The new commands add, del, list, and dot provide essential functionality for package management.

My review focuses on improving efficiency, maintainability, and robustness. Key suggestions include:

  • Fixing an N+1 query issue in the list command to improve performance.
  • Improving the robustness of file parsing and dependency resolution.
  • Enhancing code clarity and maintainability by reducing duplication and using more idiomatic Go for Kubernetes error handling.
  • Using standard library features like tabwriter for better table formatting.

Overall, this is a great addition. The feedback provided should help refine the tool before it's merged.

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

🧹 Nitpick comments (6)
cmd/cozypkg/cmd/del.go (1)

73-96: Consider extracting shared Kubernetes client setup.

This kubeconfig loading and scheme registration pattern is duplicated across add.go, del.go, list.go, and dependencies.go. Consider extracting to a shared helper function.

🔎 Example helper function
// In a shared file like client.go
func newK8sClient(kubeconfig string) (client.Client, error) {
    var config *rest.Config
    var err error

    if kubeconfig != "" {
        config, err = clientcmd.BuildConfigFromFlags("", kubeconfig)
    } else {
        config, err = ctrl.GetConfig()
    }
    if err != nil {
        return nil, fmt.Errorf("failed to get kubeconfig: %w", err)
    }

    scheme := runtime.NewScheme()
    utilruntime.Must(clientgoscheme.AddToScheme(scheme))
    utilruntime.Must(cozyv1alpha1.AddToScheme(scheme))

    return client.New(config, client.Options{Scheme: scheme})
}
cmd/cozypkg/cmd/dependencies.go (2)

110-125: Consider consolidating init() functions.

Having two init() functions in the same file is valid Go but can reduce readability. Consider merging them.

🔎 Proposed consolidation
 func init() {
 	rootCmd.AddCommand(dotCmd)
 	dotCmd.Flags().BoolVarP(&dotCmdFlags.installed, "installed", "i", false, "show dependencies only for installed Package resources")
 	dotCmd.Flags().BoolVar(&dotCmdFlags.components, "components", true, "show component-level dependencies (default: true)")
 	dotCmd.Flags().StringArrayVarP(&dotCmdFlags.files, "file", "f", []string{}, "Read packages from file or directory (can be specified multiple times)")
 	dotCmd.Flags().StringVar(&dotCmdFlags.kubeconfig, "kubeconfig", "", "Path to kubeconfig file (defaults to ~/.kube/config or KUBECONFIG env var)")
+
+	utilruntime.Must(clientgoscheme.AddToScheme(dependenciesScheme))
+	utilruntime.Must(cozyv1alpha1.AddToScheme(dependenciesScheme))
 }
 
 var (
 	dependenciesScheme = runtime.NewScheme()
 )
-
-func init() {
-	utilruntime.Must(clientgoscheme.AddToScheme(dependenciesScheme))
-	utilruntime.Must(cozyv1alpha1.AddToScheme(dependenciesScheme))
-}

263-275: Avoid redundant string splitting.

Line 268 splits the node string twice. Consider splitting once and reusing.

🔎 Proposed fix
 		// Style nodes based on type
 		if strings.Contains(node, ".") && !strings.HasPrefix(node, "cozystack.") {
 			// Component node
+			parts := strings.Split(node, ".")
 			n.Attr("shape", "box")
 			n.Attr("style", "rounded,filled")
 			n.Attr("fillcolor", "lightyellow")
-			n.Attr("label", strings.Split(node, ".")[len(strings.Split(node, "."))-1])
+			n.Attr("label", parts[len(parts)-1])
 		} else {
cmd/cozypkg/cmd/add.go (3)

111-118: Silent fallback may hide legitimate errors.

When createPackageFromFile fails, the code silently falls back to interactive installation. This could hide issues like YAML parse errors or permission problems. Consider logging when falling back.

🔎 Proposed improvement
 			// Check if package comes from a file
 			if filePath, fromFile := packagesFromFiles[packageName]; fromFile {
 				// Try to create Package directly from file
-				if err := createPackageFromFile(ctx, k8sClient, filePath, packageName); err == nil {
+				err := createPackageFromFile(ctx, k8sClient, filePath, packageName)
+				if err == nil {
 					fmt.Fprintf(os.Stderr, "✓ Added Package %s\n", packageName)
 					continue
 				}
-				// If failed, fall back to interactive installation
+				// If failed, fall back to interactive installation
+				fmt.Fprintf(os.Stderr, "ℹ Package definition not found in %s, using interactive mode for %s\n", filePath, packageName)
 			}

286-296: Dependency requester tracking overwrites previous requesters.

If multiple packages depend on the same package (e.g., A→X and B→X), only the last requester is stored. The error message at line 470 will only show one requester. This is acceptable but could be enhanced to show all requesters.


536-557: Consider adding an exit option for interactive variant selection.

The infinite loop requires Ctrl+C to abort. Consider accepting 'q' or empty input (when multiple variants) to cancel gracefully.

🔎 Example enhancement
 	for {
 		fmt.Fprintf(os.Stderr, prompt)
 		input, err := reader.ReadString('\n')
 		if err != nil {
 			return "", fmt.Errorf("failed to read input: %w", err)
 		}

 		input = strings.TrimSpace(input)

+		// Allow user to quit
+		if input == "q" || input == "quit" {
+			return "", fmt.Errorf("installation cancelled by user")
+		}
+
 		// If input is empty and there's a default variant, use it
 		if input == "" && len(ps.Spec.Variants) == 1 {
 			return defaultVariant, nil
 		}
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 59f62b7 and 4e1938c.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (7)
  • cmd/cozypkg/cmd/add.go
  • cmd/cozypkg/cmd/del.go
  • cmd/cozypkg/cmd/dependencies.go
  • cmd/cozypkg/cmd/list.go
  • cmd/cozypkg/cmd/root.go
  • cmd/cozypkg/main.go
  • go.mod
🧰 Additional context used
📓 Path-based instructions (2)
**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

Use Controller-runtime patterns and kubebuilder style for Go code

Files:

  • cmd/cozypkg/cmd/del.go
  • cmd/cozypkg/cmd/root.go
  • cmd/cozypkg/cmd/add.go
  • cmd/cozypkg/cmd/list.go
  • cmd/cozypkg/main.go
  • cmd/cozypkg/cmd/dependencies.go
{go.mod,go.sum}

📄 CodeRabbit inference engine (AGENTS.md)

Do not manually modify go.mod and go.sum files; use go get command instead

Files:

  • go.mod
🧠 Learnings (1)
📓 Common learnings
Learnt from: NickVolynkin
Repo: cozystack/cozystack PR: 1117
File: packages/apps/mysql/Makefile:8-8
Timestamp: 2025-06-26T04:29:24.830Z
Learning: The cozystack project uses yq v4+ on their CI runner, so yq v4 syntax (-o json --indent 4) is compatible and version checks are not needed.
🧬 Code graph analysis (3)
cmd/cozypkg/cmd/del.go (2)
pkg/apiserver/apiserver.go (1)
  • Scheme (53-53)
api/v1alpha1/package_types.go (1)
  • Package (32-38)
cmd/cozypkg/cmd/list.go (2)
api/v1alpha1/packagesource_types.go (3)
  • PackageSourceList (42-46)
  • Variant (65-82)
  • PackageSource (31-37)
api/v1alpha1/package_types.go (1)
  • PackageList (43-47)
cmd/cozypkg/main.go (1)
cmd/cozypkg/cmd/root.go (1)
  • Execute (38-44)
⏰ 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). (1)
  • GitHub Check: Build
🔇 Additional comments (8)
cmd/cozypkg/main.go (1)

25-29: LGTM!

Clean entry point. Error handling is correctly delegated to cmd.Execute() which prints to stderr, and the exit code 1 signals failure appropriately.

cmd/cozypkg/cmd/root.go (1)

26-44: LGTM!

Standard Cobra root command setup. SilenceErrors and SilenceUsage are correctly paired with manual error printing in Execute() for controlled error output.

cmd/cozypkg/cmd/del.go (1)

99-110: LGTM on delete logic.

The delete loop correctly handles not-found resources gracefully by logging and continuing, which is appropriate for a batch delete operation.

cmd/cozypkg/cmd/list.go (1)

173-188: Silently ignoring PackageSource fetch errors is acceptable here.

The err == nil check silently skips component display when the PackageSource cannot be fetched. This is reasonable since component display is an optional enhancement and the Package list itself is still shown.

cmd/cozypkg/cmd/dependencies.go (1)

180-197: Filtering logic is correct but could be simplified.

The packageName and selectedPackages filters are mutually exclusive based on the calling logic (lines 88-94). The code works correctly, though a comment clarifying this invariant would help maintainability.

cmd/cozypkg/cmd/add.go (2)

253-307: Dependency tree building logic is sound.

The recursive buildDependencyTree correctly handles cycles via the visited map and collects dependencies from all variants. The approach of aggregating dependencies across variants is appropriate for determining what might need to be installed.


309-362: Topological sort implementation is correct.

Kahn's algorithm is properly implemented with cycle detection. The result ordering (dependencies first) aligns with the installation order requirement.

go.mod (1)

8-8: This change follows proper dependency management practices.

The emicklei/dot v1.10.0 dependency is valid (published 2025-12-03T12:57:45Z) and is actively used in cmd/cozypkg/cmd/dependencies.go as part of the cozypkg tool addition. The go.mod file header states "This is a generated file. Do not edit directly," confirming that dependencies were added via go get (not manual editing), which is exactly what the coding guideline requires.

Likely an incorrect or invalid review comment.

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: 1

🧹 Nitpick comments (9)
cmd/cozypkg/cmd/del.go (2)

101-109: Consider reusing the installed packages list.

The installed packages are listed here (lines 102-109) and then listed again in findPackagesToDelete (lines 161-169). Consider passing installedMap to findPackagesToDelete to avoid the redundant API call.

🔎 Proposed refactor
-		// Find all packages to delete (including dependents)
-		packagesToDelete, err := findPackagesToDelete(ctx, k8sClient, packageNames)
+		// Find all packages to delete (including dependents)
+		packagesToDelete, err := findPackagesToDelete(ctx, k8sClient, packageNames, installedMap)

Then update the function signature and remove the duplicate listing inside findPackagesToDelete.


246-260: Consider sorting package lists for consistent output.

Map iteration order is non-deterministic in Go. Sorting the requested and dependents slices before printing would provide consistent, reproducible output across runs.

🔎 Proposed fix

Add import for sort and sort the slices:

+import "sort"
...
+	sort.Strings(requested)
+	sort.Strings(dependents)
+
 	fmt.Fprintf(os.Stderr, "\nThe following packages will be deleted:\n\n")
cmd/cozypkg/cmd/dependencies.go (3)

110-125: Consider consolidating init() functions.

Having two init() functions in the same file is valid Go but can reduce readability. Consider combining them or adding a comment explaining why they're separate.

🔎 Proposed fix
 func init() {
 	rootCmd.AddCommand(dotCmd)
 	dotCmd.Flags().BoolVarP(&dotCmdFlags.installed, "installed", "i", false, "show dependencies only for installed Package resources")
 	dotCmd.Flags().BoolVar(&dotCmdFlags.components, "components", true, "show component-level dependencies (default: true)")
 	dotCmd.Flags().StringArrayVarP(&dotCmdFlags.files, "file", "f", []string{}, "Read packages from file or directory (can be specified multiple times)")
 	dotCmd.Flags().StringVar(&dotCmdFlags.kubeconfig, "kubeconfig", "", "Path to kubeconfig file (defaults to ~/.kube/config or KUBECONFIG env var)")
-}
-
-var (
-	dependenciesScheme = runtime.NewScheme()
-)
-
-func init() {
+
+	// Initialize scheme for Kubernetes client
 	utilruntime.Must(clientgoscheme.AddToScheme(dependenciesScheme))
 	utilruntime.Must(cozyv1alpha1.AddToScheme(dependenciesScheme))
 }
+
+var (
+	dependenciesScheme = runtime.NewScheme()
+)

180-197: Redundant filter logic when single package is specified.

When exactly one package is specified, both packageName (line 181-183) and selectedPackages (line 186-197) filters are applied, which is redundant. This works correctly but could be simplified.

🔎 Proposed simplification

Consider using only selectedPackages for filtering and removing the packageName parameter:

-func buildGraphFromCluster(ctx context.Context, kubeconfig string, packagesOnly bool, installedOnly bool, packageName string, selectedPackages []string) (map[string][]string, map[string]bool, error) {
+func buildGraphFromCluster(ctx context.Context, kubeconfig string, packagesOnly bool, installedOnly bool, selectedPackages []string) (map[string][]string, map[string]bool, error) {
 ...
-		// Filter by package name if specified
-		if packageName != "" && psName != packageName {
-			continue
-		}
-
 		// Filter by selected packages if specified
 		if len(selectedPackages) > 0 {

Then update the caller to always use selectedPackages.


272-272: Avoid duplicate strings.Split call.

The node string is split twice on the same line. Extract to a variable for efficiency.

🔎 Proposed fix
-			n.Attr("label", strings.Split(node, ".")[len(strings.Split(node, "."))-1])
+			parts := strings.Split(node, ".")
+			n.Attr("label", parts[len(parts)-1])
cmd/cozypkg/cmd/add.go (4)

114-121: Silent fallback may hide important errors.

When createPackageFromFile fails, the code silently falls back to interactive installation without logging the error. This could hide issues like permission errors or malformed YAML. Consider logging the error before falling back.

🔎 Proposed fix
 			// Check if package comes from a file
 			if filePath, fromFile := packagesFromFiles[packageName]; fromFile {
 				// Try to create Package directly from file
-				if err := createPackageFromFile(ctx, k8sClient, filePath, packageName); err == nil {
+				err := createPackageFromFile(ctx, k8sClient, filePath, packageName)
+				if err == nil {
 					fmt.Fprintf(os.Stderr, "✓ Added Package %s\n", packageName)
 					continue
 				}
-				// If failed, fall back to interactive installation
+				// Log the error and fall back to interactive installation
+				fmt.Fprintf(os.Stderr, "⚠ Could not create Package %s from file (%v), falling back to interactive installation\n", packageName, err)
 			}

274-276: Dependency requester may be overwritten.

If multiple packages depend on the same dependency, dependencyRequesters[dep] will only store the last requester. This affects error messages only, but could be misleading when debugging missing dependencies.

🔎 Proposed fix

Consider storing all requesters or the first one:

 		for dep := range deps {
 			if _, exists := tree[pkgName]; !exists {
 				tree[pkgName] = []string{}
 			}
 			tree[pkgName] = append(tree[pkgName], dep)
 			// Track who requested this dependency
-			dependencyRequesters[dep] = pkgName
+			if _, exists := dependencyRequesters[dep]; !exists {
+				dependencyRequesters[dep] = pkgName
+			}

520-541: Consider adding a maximum retry limit.

The infinite loop for variant selection will retry indefinitely on invalid input. While this is intentional, consider adding a retry limit to prevent user frustration or issues when stdin is unexpectedly non-interactive.


380-383: Handle "already exists" case explicitly.

If the Package already exists in the cluster, k8sClient.Create will return an error. This bubbles up and causes a fallback to interactive installation, which will then report "already installed". Consider checking for apierrors.IsAlreadyExists and returning success in that case.

🔎 Proposed fix
+			apierrors "k8s.io/apimachinery/pkg/api/errors"
...
 			// Create Package
 			if err := k8sClient.Create(ctx, &pkg); err != nil {
+				if apierrors.IsAlreadyExists(err) {
+					return nil // Already exists is not an error
+				}
 				return fmt.Errorf("failed to create Package: %w", err)
 			}
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4e1938c and 06c31a9.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (7)
  • cmd/cozypkg/cmd/add.go
  • cmd/cozypkg/cmd/del.go
  • cmd/cozypkg/cmd/dependencies.go
  • cmd/cozypkg/cmd/list.go
  • cmd/cozypkg/cmd/root.go
  • cmd/cozypkg/main.go
  • go.mod
🚧 Files skipped from review as they are similar to previous changes (2)
  • go.mod
  • cmd/cozypkg/cmd/list.go
🧰 Additional context used
📓 Path-based instructions (2)
cmd/**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

Follow controller-runtime patterns and kubebuilder style for Go code in cmd directory

Files:

  • cmd/cozypkg/cmd/root.go
  • cmd/cozypkg/cmd/del.go
  • cmd/cozypkg/cmd/add.go
  • cmd/cozypkg/cmd/dependencies.go
  • cmd/cozypkg/main.go
**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

Do NOT manually edit vendor/ directory or auto-generated files (zz_generated.*.go)

Files:

  • cmd/cozypkg/cmd/root.go
  • cmd/cozypkg/cmd/del.go
  • cmd/cozypkg/cmd/add.go
  • cmd/cozypkg/cmd/dependencies.go
  • cmd/cozypkg/main.go
🧠 Learnings (3)
📚 Learning: 2025-12-25T09:45:26.511Z
Learnt from: CR
Repo: cozystack/cozystack PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-25T09:45:26.511Z
Learning: Applies to cmd/**/*.go : Follow controller-runtime patterns and kubebuilder style for Go code in cmd directory

Applied to files:

  • cmd/cozypkg/cmd/del.go
  • cmd/cozypkg/cmd/add.go
  • cmd/cozypkg/cmd/dependencies.go
  • cmd/cozypkg/main.go
📚 Learning: 2025-12-25T09:45:26.511Z
Learnt from: CR
Repo: cozystack/cozystack PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-25T09:45:26.511Z
Learning: Applies to pkg/**/*.go : Follow controller-runtime patterns and kubebuilder style for Go code in pkg directory

Applied to files:

  • cmd/cozypkg/cmd/add.go
📚 Learning: 2025-06-04T06:22:17.306Z
Learnt from: lllamnyp
Repo: cozystack/cozystack PR: 1025
File: packages/apps/kafka/charts/cozy-lib:1-1
Timestamp: 2025-06-04T06:22:17.306Z
Learning: Files in packages/apps/*/charts/cozy-lib that contain the path "../../../library/cozy-lib" are symbolic links, not regular files. Git diffs may display symlinks as regular files with their target path as content, which can be misleading in code review.

Applied to files:

  • cmd/cozypkg/cmd/dependencies.go
🧬 Code graph analysis (3)
cmd/cozypkg/cmd/del.go (2)
api/v1alpha1/package_types.go (2)
  • PackageList (43-47)
  • Package (32-38)
api/v1alpha1/packagesource_types.go (1)
  • PackageSourceList (42-46)
cmd/cozypkg/cmd/add.go (3)
pkg/apiserver/apiserver.go (1)
  • Scheme (53-53)
api/v1alpha1/packagesource_types.go (3)
  • PackageSource (31-37)
  • PackageSourceList (42-46)
  • Variant (65-82)
api/v1alpha1/package_types.go (3)
  • Package (32-38)
  • PackageList (43-47)
  • PackageSpec (54-69)
cmd/cozypkg/cmd/dependencies.go (5)
internal/sse/server.go (1)
  • Options (17-44)
pkg/apiserver/apiserver.go (1)
  • Scheme (53-53)
api/v1alpha1/package_types.go (1)
  • PackageList (43-47)
api/v1alpha1/packagesource_types.go (1)
  • PackageSourceList (42-46)
pkg/apis/apps/install/install.go (1)
  • Install (26-29)
⏰ 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). (1)
  • GitHub Check: Build
🔇 Additional comments (3)
cmd/cozypkg/main.go (1)

25-29: LGTM!

Clean and minimal CLI entrypoint that properly delegates to cmd.Execute() and exits with status code 1 on error. This follows standard Go CLI patterns.

cmd/cozypkg/cmd/root.go (1)

26-44: LGTM!

Well-structured root command setup. The SilenceErrors and SilenceUsage flags combined with custom error printing in Execute() provide clean error handling. The DisableAutoGenTag is a nice touch for generated documentation.

cmd/cozypkg/cmd/add.go (1)

293-346: LGTM!

Well-implemented topological sort using Kahn's algorithm with proper cycle detection at lines 340-343.

@kvaps kvaps force-pushed the cozypkg-new branch 2 times, most recently from dbe129a to 6e9277b Compare December 25, 2025 11:04
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

♻️ Duplicate comments (1)
cmd/cozypkg/cmd/del.go (1)

346-366: Add cycle detection to prevent incomplete deletions.

The topological sort using Kahn's algorithm will terminate early if cycles exist, returning an incomplete list without any error. This could lead to some packages not being deleted silently.

🔎 Proposed fix
 	var result []string
 	for len(queue) > 0 {
 		node := queue[0]
 		queue = queue[1:]
 		result = append(result, node)

 		// Process dependents
 		for _, dependent := range reverseGraph[node] {
 			inDegree[dependent]--
 			if inDegree[dependent] == 0 {
 				queue = append(queue, dependent)
 			}
 		}
 	}

+	// Check for cycles - if not all nodes were processed, a cycle exists
+	if len(result) != len(allNodes) {
+		return nil, fmt.Errorf("dependency cycle detected, cannot determine safe delete order")
+	}
+
 	// Reverse the result to get dependents first, then dependencies
 	for i, j := 0, len(result)-1; i < j; i, j = i+1, j-1 {
 		result[i], result[j] = result[j], result[i]
 	}

 	return result, nil
🧹 Nitpick comments (1)
cmd/cozypkg/cmd/dependencies.go (1)

170-402: Consider extracting helper functions to reduce complexity.

The buildGraphFromCluster function is quite long (~270 lines) with deeply nested loops. While the logic is correct, extracting helper functions for component dependency processing (lines 300-348) and edge variant tracking (lines 351-399) would improve readability and testability.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 06c31a9 and dbe129a.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (7)
  • cmd/cozypkg/cmd/add.go
  • cmd/cozypkg/cmd/del.go
  • cmd/cozypkg/cmd/dependencies.go
  • cmd/cozypkg/cmd/list.go
  • cmd/cozypkg/cmd/root.go
  • cmd/cozypkg/main.go
  • go.mod
🚧 Files skipped from review as they are similar to previous changes (3)
  • cmd/cozypkg/cmd/list.go
  • cmd/cozypkg/main.go
  • cmd/cozypkg/cmd/root.go
🧰 Additional context used
📓 Path-based instructions (3)
cmd/**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

Follow controller-runtime patterns and kubebuilder style for Go code in cmd directory

Files:

  • cmd/cozypkg/cmd/del.go
  • cmd/cozypkg/cmd/dependencies.go
  • cmd/cozypkg/cmd/add.go
**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

Do NOT manually edit vendor/ directory or auto-generated files (zz_generated.*.go)

Files:

  • cmd/cozypkg/cmd/del.go
  • cmd/cozypkg/cmd/dependencies.go
  • cmd/cozypkg/cmd/add.go
go.mod

📄 CodeRabbit inference engine (AGENTS.md)

Do NOT modify go.mod manually; use go get command instead

Files:

  • go.mod
🧠 Learnings (3)
📚 Learning: 2025-12-25T09:45:26.511Z
Learnt from: CR
Repo: cozystack/cozystack PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-25T09:45:26.511Z
Learning: Applies to cmd/**/*.go : Follow controller-runtime patterns and kubebuilder style for Go code in cmd directory

Applied to files:

  • cmd/cozypkg/cmd/del.go
  • cmd/cozypkg/cmd/add.go
📚 Learning: 2025-06-04T06:22:17.306Z
Learnt from: lllamnyp
Repo: cozystack/cozystack PR: 1025
File: packages/apps/kafka/charts/cozy-lib:1-1
Timestamp: 2025-06-04T06:22:17.306Z
Learning: Files in packages/apps/*/charts/cozy-lib that contain the path "../../../library/cozy-lib" are symbolic links, not regular files. Git diffs may display symlinks as regular files with their target path as content, which can be misleading in code review.

Applied to files:

  • cmd/cozypkg/cmd/dependencies.go
📚 Learning: 2025-12-25T09:45:26.511Z
Learnt from: CR
Repo: cozystack/cozystack PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-25T09:45:26.511Z
Learning: Applies to pkg/**/*.go : Follow controller-runtime patterns and kubebuilder style for Go code in pkg directory

Applied to files:

  • cmd/cozypkg/cmd/add.go
🧬 Code graph analysis (3)
cmd/cozypkg/cmd/del.go (3)
pkg/apiserver/apiserver.go (1)
  • Scheme (53-53)
api/v1alpha1/package_types.go (2)
  • PackageList (43-47)
  • Package (32-38)
api/v1alpha1/packagesource_types.go (1)
  • PackageSourceList (42-46)
cmd/cozypkg/cmd/dependencies.go (2)
api/v1alpha1/package_types.go (1)
  • PackageList (43-47)
api/v1alpha1/packagesource_types.go (2)
  • PackageSourceList (42-46)
  • PackageSource (31-37)
cmd/cozypkg/cmd/add.go (2)
api/v1alpha1/packagesource_types.go (3)
  • PackageSource (31-37)
  • PackageSourceList (42-46)
  • Variant (65-82)
api/v1alpha1/package_types.go (3)
  • Package (32-38)
  • PackageList (43-47)
  • PackageSpec (54-69)
🔇 Additional comments (16)
cmd/cozypkg/cmd/del.go (5)

19-42: LGTM!

Imports are properly organized and the use of apierrors for checking IsNotFound is idiomatic. The flag structure follows Cobra conventions.


44-156: LGTM!

The command implementation follows controller-runtime patterns correctly. Error handling is thorough, with proper use of apierrors.IsNotFound for handling already-deleted packages. The flow from dependency analysis to confirmation to ordered deletion is well-structured.


158-228: LGTM!

The function correctly builds a reverse dependency graph and recursively finds all dependents. The visited map properly handles potential cycles in the dependency graph during traversal.


230-277: LGTM!

Good UX design separating requested packages from dependents in the confirmation prompt. The input validation correctly handles both "y" and "yes" responses.


369-373: LGTM!

Command registration and flag definitions follow Cobra conventions.

cmd/cozypkg/cmd/dependencies.go (3)

45-108: LGTM!

The command definition is well-documented with clear usage examples for piping to graphviz. The flag definitions are appropriate for the use cases.


132-168: LGTM!

The Kubernetes client setup follows controller-runtime patterns. The conditional fetching of installed packages only when installedOnly is true addresses efficiency concerns about unnecessary API calls.


404-503: LGTM!

The DOT graph generation is well-implemented with clear visual distinction between node types (packages vs components) and proper handling of missing dependencies (red/dashed). The isPackage helper correctly uses the packageNames map for determination rather than relying on naming conventions.

cmd/cozypkg/cmd/add.go (8)

48-131: LGTM!

The command implementation properly handles both file-based and interactive installation paths. The duplicate package warning (lines 75-77) provides clear feedback to users about conflicting definitions across files.


133-235: LGTM!

File and YAML parsing is well-implemented. The consolidated handling of PackageList and PackageSourceList (lines 214-229) reduces code duplication. Returning an empty list for files without packages is the correct user-friendly behavior.


237-291: LGTM!

The dependency tree building correctly handles cycles via the visited map. The dependencyRequesters map provides helpful context for error messages when dependencies are missing.


293-346: LGTM!

Correct implementation of Kahn's algorithm with proper cycle detection (lines 340-343). This is the pattern that getDeleteOrder in del.go should follow.


348-390: LGTM!

The function correctly parses YAML, finds the matching Package by name, and creates it via the Kubernetes client with proper error handling.


392-495: LGTM!

The installation flow is well-structured: build dependency tree → topological sort → collect variant selections → create packages. The handling of already-installed packages with their existing variants ensures consistency.


497-542: LGTM!

Good UX design with automatic default selection for single-variant packages. Using stderr for interactive prompts keeps stdout clean for potential piped output.


544-548: LGTM!

Command registration and flag definitions follow Cobra conventions consistently with other commands in this package.

@kvaps kvaps force-pushed the cozypkg-new branch 2 times, most recently from 8f89395 to 9fb0a39 Compare December 25, 2025 13:57
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)
cmd/cozypkg/cmd/dependencies.go (1)

110-116: Consider consolidating init functions.

While valid Go, having two separate init() functions in the same file is unusual. You could merge them into a single init() for clarity.

🔎 Consolidation example
-var dotCmd = &cobra.Command{
-	// ...
-}
-
-func init() {
-	rootCmd.AddCommand(dotCmd)
-	dotCmd.Flags().BoolVarP(&dotCmdFlags.installed, "installed", "i", false, "show dependencies only for installed Package resources")
-	dotCmd.Flags().BoolVar(&dotCmdFlags.components, "components", false, "show component-level dependencies")
-	dotCmd.Flags().StringArrayVarP(&dotCmdFlags.files, "file", "f", []string{}, "Read packages from file or directory (can be specified multiple times)")
-	dotCmd.Flags().StringVar(&dotCmdFlags.kubeconfig, "kubeconfig", "", "Path to kubeconfig file (defaults to ~/.kube/config or KUBECONFIG env var)")
-}
-
-var (
-	dependenciesScheme = runtime.NewScheme()
-)
-
 func init() {
+	// Initialize scheme
 	utilruntime.Must(clientgoscheme.AddToScheme(dependenciesScheme))
 	utilruntime.Must(cozyv1alpha1.AddToScheme(dependenciesScheme))
+	
+	// Register command
+	rootCmd.AddCommand(dotCmd)
+	dotCmd.Flags().BoolVarP(&dotCmdFlags.installed, "installed", "i", false, "show dependencies only for installed Package resources")
+	dotCmd.Flags().BoolVar(&dotCmdFlags.components, "components", false, "show component-level dependencies")
+	dotCmd.Flags().StringArrayVarP(&dotCmdFlags.files, "file", "f", []string{}, "Read packages from file or directory (can be specified multiple times)")
+	dotCmd.Flags().StringVar(&dotCmdFlags.kubeconfig, "kubeconfig", "", "Path to kubeconfig file (defaults to ~/.kube/config or KUBECONFIG env var)")
 }

Also applies to: 122-125

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dbe129a and 8f89395.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (7)
  • cmd/cozypkg/cmd/add.go
  • cmd/cozypkg/cmd/del.go
  • cmd/cozypkg/cmd/dependencies.go
  • cmd/cozypkg/cmd/list.go
  • cmd/cozypkg/cmd/root.go
  • cmd/cozypkg/main.go
  • go.mod
🚧 Files skipped from review as they are similar to previous changes (3)
  • cmd/cozypkg/main.go
  • go.mod
  • cmd/cozypkg/cmd/root.go
🧰 Additional context used
📓 Path-based instructions (2)
cmd/**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

Follow controller-runtime patterns and kubebuilder style for Go code in cmd directory

Files:

  • cmd/cozypkg/cmd/list.go
  • cmd/cozypkg/cmd/del.go
  • cmd/cozypkg/cmd/add.go
  • cmd/cozypkg/cmd/dependencies.go
**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

Do NOT manually edit vendor/ directory or auto-generated files (zz_generated.*.go)

Files:

  • cmd/cozypkg/cmd/list.go
  • cmd/cozypkg/cmd/del.go
  • cmd/cozypkg/cmd/add.go
  • cmd/cozypkg/cmd/dependencies.go
🧠 Learnings (3)
📚 Learning: 2025-12-25T09:45:26.511Z
Learnt from: CR
Repo: cozystack/cozystack PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-25T09:45:26.511Z
Learning: Applies to cmd/**/*.go : Follow controller-runtime patterns and kubebuilder style for Go code in cmd directory

Applied to files:

  • cmd/cozypkg/cmd/del.go
  • cmd/cozypkg/cmd/add.go
📚 Learning: 2025-12-25T09:45:26.511Z
Learnt from: CR
Repo: cozystack/cozystack PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-25T09:45:26.511Z
Learning: Applies to pkg/**/*.go : Follow controller-runtime patterns and kubebuilder style for Go code in pkg directory

Applied to files:

  • cmd/cozypkg/cmd/add.go
📚 Learning: 2025-06-04T06:22:17.306Z
Learnt from: lllamnyp
Repo: cozystack/cozystack PR: 1025
File: packages/apps/kafka/charts/cozy-lib:1-1
Timestamp: 2025-06-04T06:22:17.306Z
Learning: Files in packages/apps/*/charts/cozy-lib that contain the path "../../../library/cozy-lib" are symbolic links, not regular files. Git diffs may display symlinks as regular files with their target path as content, which can be misleading in code review.

Applied to files:

  • cmd/cozypkg/cmd/dependencies.go
🧬 Code graph analysis (4)
cmd/cozypkg/cmd/list.go (3)
pkg/apiserver/apiserver.go (1)
  • Scheme (53-53)
api/v1alpha1/packagesource_types.go (3)
  • PackageSourceList (42-46)
  • PackageSource (31-37)
  • Variant (65-82)
api/v1alpha1/package_types.go (1)
  • PackageList (43-47)
cmd/cozypkg/cmd/del.go (2)
api/v1alpha1/package_types.go (2)
  • PackageList (43-47)
  • Package (32-38)
api/v1alpha1/packagesource_types.go (1)
  • PackageSourceList (42-46)
cmd/cozypkg/cmd/add.go (2)
api/v1alpha1/packagesource_types.go (3)
  • PackageSource (31-37)
  • PackageSourceList (42-46)
  • Variant (65-82)
api/v1alpha1/package_types.go (3)
  • Package (32-38)
  • PackageList (43-47)
  • PackageSpec (54-69)
cmd/cozypkg/cmd/dependencies.go (3)
api/v1alpha1/package_types.go (1)
  • PackageList (43-47)
api/v1alpha1/packagesource_types.go (2)
  • PackageSourceList (42-46)
  • PackageSource (31-37)
pkg/apis/apps/install/install.go (1)
  • Install (26-29)
⏰ 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). (1)
  • GitHub Check: Build
🔇 Additional comments (10)
cmd/cozypkg/cmd/list.go (2)

149-160: LGTM: N+1 query issue resolved.

The code now fetches all PackageSource resources once upfront and stores them in a map for lookup, eliminating the N+1 query problem flagged in previous reviews.


93-95: LGTM: tabwriter properly adopted.

The code now uses text/tabwriter for column alignment, making the table formatting robust and maintainable. This addresses the previous concern about hardcoded padding.

Also applies to: 162-164

cmd/cozypkg/cmd/del.go (3)

151-151: LGTM: Idiomatic error checking.

The code now uses apierrors.IsNotFound(err) for NotFound error detection, which is more idiomatic and readable than the previous approach.


367-381: LGTM: Cycle detection implemented.

The function now properly detects dependency cycles by comparing processed nodes against total nodes, returning a clear error with the list of unprocessed packages. This prevents incomplete deletions and provides actionable feedback.


285-389: Well-structured topological sort.

The reverse topological sort correctly ensures dependents are deleted before their dependencies, using Kahn's algorithm with proper cycle detection. The implementation is clear and handles edge cases appropriately.

cmd/cozypkg/cmd/dependencies.go (1)

160-160: LGTM: Condition correctly guards API call.

The installed packages list is now fetched only when installedOnly is true, eliminating the unnecessary API call mentioned in previous reviews.

cmd/cozypkg/cmd/add.go (4)

75-77: LGTM: Duplicate package warning added.

The code now warns users when a package is defined in multiple files, preventing silent overwrites and making the behavior transparent.


214-229: LGTM: Parsing consolidated.

The code now handles both PackageList and PackageSourceList in a single conditional block, eliminating duplication and improving maintainability.


232-234: LGTM: Returns empty list gracefully.

The function no longer errors when no packages are found in a file, allowing users to provide files with other Kubernetes resources or empty files without failure. The actual validation happens later in RunE.


392-495: Well-structured dependency installation.

The installPackage function handles dependency resolution, variant selection, and package creation in a clear, sequential flow. The two-phase approach (collect variants, then create resources) ensures all user interactions happen upfront before any API calls.

Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
@dosubot dosubot bot added the lgtm This PR has been approved by a maintainer label Dec 30, 2025
@kvaps kvaps merged commit c200a45 into main Dec 30, 2025
13 of 24 checks passed
@kvaps kvaps deleted the cozypkg-new branch December 30, 2025 10:56
kvaps added a commit that referenced this pull request Jan 8, 2026
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>

<!-- Thank you for making a contribution! Here are some tips for you:
- Start the PR title with the [label] of Cozystack component:
- For system components: [platform], [system], [linstor], [cilium],
[kube-ovn], [dashboard], [cluster-api], etc.
- For managed apps: [apps], [tenant], [kubernetes], [postgres],
[virtual-machine] etc.
- For development and maintenance: [tests], [ci], [docs], [maintenance].
- If it's a work in progress, consider creating this PR as a draft.
- Don't hesistate to ask for opinion and review in the community chats,
even if it's still a draft.
- Add the label `backport` if it's a bugfix that needs to be backported
to a previous version.
-->

## What this PR does


### Release note

<!--  Write a release note:
- Explain what has changed internally and for users.
- Start with the same [label] as in the PR title
- Follow the guidelines at
https://github.com/kubernetes/community/blob/master/contributors/guide/release-notes.md.
-->

```release-note
[cozypkg] Add tool for managing Package and PackageSources
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
  * New cozy CLI with entrypoint and root command.
* Interactive "add" command to install packages from args or files, with
dependency resolution, topological install order, variant selection, and
progress feedback.
* "del" command to remove packages safely, including dependent analysis,
confirmation prompts, and safe delete ordering.
* "list" command to show available or installed packages, with optional
per-component output and concise status lines.
* "dependencies" command to emit Graphviz DOT graphs of
package/component relationships.
* Common flags: kubeconfig, file inputs, --installed and --components
where applicable.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
kvaps added a commit that referenced this pull request Jan 16, 2026
…d backup system (#1867)

## What this PR does

Update changelog for v1.0.0-alpha.1 to include missing features:
- **Cozystack Operator**: New operator for Package and PackageSource
management (#1740, #1741, #1755, #1756, #1760, #1761)
- **Backup System**: Comprehensive backup functionality with Velero
integration (#1640, #1685, #1687, #1708, #1719, #1720, #1737, #1762)
- Add @androndo to contributors
- Update Full Changelog link to v0.38.0...v1.0.0-alpha.1

### Release note

```release-note
[docs] Update changelog for v1.0.0-alpha.1: add cozystack-operator and backup system
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request lgtm This PR has been approved by a maintainer size:XXL This PR changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants