Skip to main content
Glama
264-gitops-tool-argocd.md17.3 kB
# PRD: GitOps Tool with Argo CD Support **Issue**: [#264](https://github.com/vfarcic/dot-ai/issues/264) **Status**: Draft **Priority**: High **Created**: 2025-12-10 --- ## Problem Statement Users working with GitOps workflows need to generate Argo CD Application CRs for their Kubernetes manifests. Currently: 1. **No Standalone GitOps Tool**: Users must manually create Argo CD Applications for existing packages 2. **No Project Detection**: Tools don't analyze the project to find existing Helm charts, Kustomize overlays, or manifest directories 3. **Manual Process**: Creating Application CRs requires knowing the exact schema and options 4. **Disconnected from AI Assistance**: No AI-powered guidance for GitOps configuration This PRD introduces a new `gitops` MCP tool that operates in **standalone mode** - working with any existing manifests, not just those generated by the `recommend` tool. --- ## Solution Overview Create a new `gitops` MCP tool that: 1. **Analyzes the Project**: Scans the working directory to detect package types (Helm, Kustomize, raw manifests) 2. **Confirms with User**: "Is this the package? [detected path]" or asks for path if not detected 3. **Selects GitOps Provider**: Ask which GitOps tool to use (Argo CD now, Flux in #265) 4. **Collects GitOps Configuration**: Repository URL, sync policy, namespaces, etc. 5. **Generates GitOps Resources**: Provider-specific manifests (Argo CD Application, Flux HelmRelease, etc.) ### Key Design Principles - **Standalone First**: Works independently with any existing packages - **Smart Detection**: Analyzes project structure to find packages automatically - **User Confirmation**: Always confirms detected paths before proceeding - **Pluggable Providers**: Architecture designed for multiple GitOps tools (Argo CD, Flux, future tools) - **Shared Infrastructure**: Detection, session management, and question framework are reusable across providers --- ## User Journeys ### Journey 1: Auto-Detected Helm Chart ``` User: [invokes gitops tool with intent "deploy my app"] → Tool scans project, finds ./charts/my-app/Chart.yaml → "I found a Helm chart at ./charts/my-app/. Is this the package you want to deploy?" → User confirms: Yes → "Which GitOps tool would you like to use?" - Argo CD (only option in this PRD) → Additional questions: - Git repository URL? (e.g., https://github.com/org/repo.git) - Path within repository? (default: charts/my-app) - Target namespace for deployment? - Argo CD Application namespace? (default: argocd) - Sync policy? (Manual / Automatic / Automatic with Pruning) → Tool generates Argo CD Application CR → "Where should I save the Application manifest?" (default: ./argocd-application.yaml) ``` ### Journey 2: Auto-Detected Kustomize ``` User: [invokes gitops tool] → Tool scans project, finds ./deploy/kustomization.yaml → "I found a Kustomize overlay at ./deploy/. Is this the package you want to deploy?" → User confirms: Yes → Tool collects GitOps configuration → Generates Application CR with Kustomize source type ``` ### Journey 3: Multiple Packages Detected ``` User: [invokes gitops tool] → Tool scans project, finds: - ./charts/frontend/Chart.yaml - ./charts/backend/Chart.yaml - ./deploy/kustomization.yaml → "I found multiple packages. Which one would you like to deploy?" Option 1: ./charts/frontend (Helm) Option 2: ./charts/backend (Helm) Option 3: ./deploy (Kustomize) Option 4: Specify a different path → User selects option → Continues with GitOps configuration ``` ### Journey 4: No Package Detected ``` User: [invokes gitops tool] → Tool scans project, finds no recognizable packages → "I couldn't detect a Helm chart, Kustomize overlay, or manifest directory. Where is your package located?" → User provides path: ./kubernetes/ → Tool analyzes the path: - If contains Chart.yaml → Helm - If contains kustomization.yaml → Kustomize - If contains .yaml/.yml files → Raw manifests → Continues with GitOps configuration ``` ### Journey 5: Raw Manifests Directory ``` User: [invokes gitops tool] → Tool detects ./manifests/ directory with .yaml files (no Chart.yaml or kustomization.yaml) → "I found raw Kubernetes manifests at ./manifests/. Is this what you want to deploy?" → User confirms → Tool generates Application CR with directory source type ``` --- ## Technical Design ### Tool Interface ```typescript // New MCP tool: gitops interface GitOpsToolParams { // Stage control stage?: 'detect' | 'selectPackage' | 'selectProvider' | 'configure' | 'generate'; // Session management sessionId?: string; // User inputs packagePath?: string; // Manual path override selectedPackage?: number; // Index when multiple packages found provider?: 'argocd' | 'flux'; // GitOps provider selection answers?: Record<string, any>; // Answers to configuration questions } ``` ### Workflow Stages ``` [detect] → [selectPackage] → [selectProvider] → [configure] → [generate] ↓ ↓ ↓ ↓ ↓ Scan for Confirm/select Argo CD or Provider- Output packages package path Flux specific manifests questions ``` ### Shared Infrastructure (Reusable by Flux and Future Providers) The following components are designed to be **provider-agnostic** and reusable: 1. **Package Detection** (`detection.ts`): Scans for Helm, Kustomize, raw manifests 2. **Session Management** (`session.ts`): Tracks workflow state across stages 3. **Question Framework** (`questions.ts`): Handles user prompts, validation, defaults 4. **Output Handling**: File writing, YAML formatting, multi-document output Only the **generator** and **provider-specific questions** vary by provider. ### Package Detection Logic ```typescript interface DetectedPackage { path: string; type: 'helm' | 'kustomize' | 'raw-manifests'; name: string; // Derived from Chart.yaml name or directory confidence: 'high' | 'medium' | 'low'; } async function detectPackages(workingDir: string): Promise<DetectedPackage[]> { const packages: DetectedPackage[] = []; // 1. Find Helm charts (Chart.yaml) const helmCharts = await glob('**/Chart.yaml', { cwd: workingDir }); for (const chartPath of helmCharts) { const chartDir = path.dirname(chartPath); const chartYaml = await readYaml(path.join(workingDir, chartPath)); packages.push({ path: chartDir, type: 'helm', name: chartYaml.name || path.basename(chartDir), confidence: 'high' }); } // 2. Find Kustomize overlays (kustomization.yaml) const kustomizations = await glob('**/kustomization.yaml', { cwd: workingDir }); for (const kustomizePath of kustomizations) { const kustomizeDir = path.dirname(kustomizePath); packages.push({ path: kustomizeDir, type: 'kustomize', name: path.basename(kustomizeDir), confidence: 'high' }); } // 3. Find raw manifest directories (directories with .yaml files) const manifestDirs = await findManifestDirectories(workingDir); for (const dir of manifestDirs) { // Only add if not already detected as Helm or Kustomize if (!packages.some(p => p.path === dir)) { packages.push({ path: dir, type: 'raw-manifests', name: path.basename(dir), confidence: 'medium' }); } } return packages; } ``` ### Provider Selection After package confirmation, the user selects their GitOps provider: ```typescript const providerQuestion = { id: 'gitopsProvider', question: 'Which GitOps tool would you like to use?', type: 'select', options: [ { value: 'argocd', label: 'Argo CD', description: 'Generate Argo CD Application' }, { value: 'flux', label: 'Flux', description: 'Generate Flux GitRepository + HelmRelease/Kustomization' } ], default: 'argocd' }; ``` **Note**: Flux option will show "coming soon" until PRD #265 is implemented. ### Configuration Questions Questions are split into **shared** (common to all providers) and **provider-specific**: #### Shared Questions (Used by All Providers) ```typescript const sharedQuestions = [ { id: 'gitRepoUrl', question: 'Git repository URL where the package is stored?', type: 'text', required: true, placeholder: 'https://github.com/org/repo.git' }, { id: 'gitRepoPath', question: 'Path within the repository?', type: 'text', default: '<detected-package-path>', required: true }, { id: 'targetRevision', question: 'Git branch or tag to track?', type: 'text', default: 'HEAD' }, { id: 'destinationNamespace', question: 'Target namespace for deployment?', type: 'text', required: true, placeholder: 'default' }, { id: 'outputPath', question: 'Where to save the GitOps manifest?', type: 'text', default: './<provider>-application.yaml' // e.g., ./argocd-application.yaml } ]; ``` #### Argo CD-Specific Questions ```typescript const argocdQuestions = [ { id: 'applicationNamespace', question: 'Namespace for the Argo CD Application CR?', type: 'text', default: 'argocd' }, { id: 'project', question: 'Argo CD project?', type: 'text', default: 'default' }, { id: 'syncPolicy', question: 'Sync policy?', type: 'select', options: [ { value: 'manual', label: 'Manual', description: 'Sync only when triggered' }, { value: 'auto', label: 'Automatic', description: 'Sync automatically on changes' }, { value: 'auto-prune', label: 'Automatic with Pruning', description: 'Auto-sync and remove orphaned resources' } ], default: 'manual' } ]; ``` ### Application CR Generation #### Helm Chart Source ```yaml apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: <package-name> namespace: argocd spec: project: default source: repoURL: https://github.com/org/repo.git path: charts/my-app targetRevision: HEAD helm: valueFiles: - values.yaml destination: server: https://kubernetes.default.svc namespace: my-app syncPolicy: automated: prune: true selfHeal: true ``` #### Kustomize Source ```yaml apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: <package-name> namespace: argocd spec: project: default source: repoURL: https://github.com/org/repo.git path: deploy/overlays/production targetRevision: HEAD destination: server: https://kubernetes.default.svc namespace: my-app syncPolicy: automated: prune: true selfHeal: true ``` #### Raw Manifests (Directory) ```yaml apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: <package-name> namespace: argocd spec: project: default source: repoURL: https://github.com/org/repo.git path: manifests targetRevision: HEAD directory: recurse: true destination: server: https://kubernetes.default.svc namespace: my-app syncPolicy: automated: prune: true selfHeal: true ``` ### Pluggable Generator Interface The generator interface allows adding new providers without modifying core logic: ```typescript // src/core/gitops/types.ts interface DetectedPackage { path: string; type: 'helm' | 'kustomize' | 'raw-manifests'; name: string; confidence: 'high' | 'medium' | 'low'; } interface GitOpsConfig { // From detection package: DetectedPackage; // From shared questions gitRepoUrl: string; gitRepoPath: string; targetRevision: string; destinationNamespace: string; outputPath: string; // Provider-specific (passed through) providerConfig: Record<string, any>; } interface GitOpsGenerator { /** Provider identifier */ readonly providerId: string; /** Human-readable name */ readonly providerName: string; /** Provider-specific questions (added to shared questions) */ getQuestions(): Question[]; /** Generate GitOps manifests */ generate(config: GitOpsConfig): GeneratedOutput; } interface GeneratedOutput { manifests: string; // YAML content (may be multi-document) filename: string; // Suggested filename description: string; // Human-readable summary } // Registry for providers const providers: Map<string, GitOpsGenerator> = new Map(); function registerProvider(generator: GitOpsGenerator) { providers.set(generator.providerId, generator); } // Argo CD provider registered by default registerProvider(new ArgoCDGenerator()); // Flux provider will be registered by PRD #265 // registerProvider(new FluxGenerator()); ``` ### File Structure ``` src/ ├── tools/ │ └── gitops/ │ ├── index.ts # Tool entry point │ ├── detection.ts # Package detection logic (SHARED) │ ├── questions.ts # Question framework (SHARED) │ ├── session.ts # Session management (SHARED) │ └── generators/ │ ├── index.ts # Generator registry (SHARED) │ ├── types.ts # Generator interface (SHARED) │ ├── argocd.ts # Argo CD generator │ └── flux.ts # Flux generator (PRD #265) ├── core/ │ └── gitops/ │ └── types.ts # Shared types prompts/ └── gitops/ ├── detect-package.md # Detection prompt (SHARED) ├── shared-questions.md # Common questions (SHARED) └── argocd-questions.md # Argo CD-specific prompts ``` Files marked **(SHARED)** are provider-agnostic and will be reused by Flux (PRD #265). --- ## Success Criteria ### Shared Infrastructure (Reusable) 1. **Package Detection**: Tool correctly detects Helm charts, Kustomize overlays, and raw manifest directories 2. **User Confirmation**: Always confirms detected package before proceeding 3. **Multiple Package Handling**: Presents clear selection when multiple packages found 4. **Manual Override**: Users can specify custom paths when detection fails or is wrong 5. **Provider Selection**: Users can choose GitOps provider (Argo CD now, Flux shows "coming soon") 6. **Pluggable Architecture**: New providers can be added by implementing `GitOpsGenerator` interface 7. **File Output**: Saves manifest to user-specified path ### Argo CD-Specific 8. **Valid Application CR**: Generated Application CRs pass `kubectl apply --dry-run=client` validation 9. **All Source Types**: Correctly generates Helm, Kustomize, and directory source configurations 10. **Sync Policies**: Supports manual, auto, and auto-prune sync policies --- ## Out of Scope 1. **Flux Support**: Covered by PRD #265 2. **Recommend Integration**: Covered by PRD #266 3. **Git Push**: Actually pushing generated files to Git 4. **Argo CD Detection**: Auto-detecting if Argo CD is installed 5. **ApplicationSet**: Multi-environment patterns 6. **App of Apps**: Nested Application structures 7. **Private Repos**: Credential configuration for private repositories 8. **Third-Party Helm Repos**: External HelmRepository references (future enhancement) --- ## Dependencies | Dependency | Relationship | |------------|--------------| | PRD #248 | Optional - packages generated by recommend can be used, but not required | --- ## Supersedes This PRD, along with #265 and #266, supersedes: - **#254** (Argo CD Integration for Third-Party Helm Charts) - **#255** (Argo CD Integration for Packaged Recommendations) - **#256** (Flux Integration for GitOps Deployments) The new architecture separates concerns: - **#264** (this): Standalone gitops tool + Argo CD - **#265**: Adds Flux support to gitops tool - **#266**: Integrates gitops into recommend workflow --- ## Risks and Mitigations | Risk | Impact | Mitigation | |------|--------|------------| | False positive detection | Wrong package selected | Always confirm with user; allow manual override | | Complex project structures | Detection misses packages | Support manual path input; improve detection heuristics | | Invalid Application generated | Deployment fails | Validate against Argo CD schema; include dry-run option | | Path format differences | Git path doesn't match local | Let user specify exact repository path | --- ## Milestones ### Shared Infrastructure - [ ] **M1**: Package detection logic (Helm, Kustomize, raw manifests) - [ ] **M2**: User confirmation flow with multiple package handling - [ ] **M3**: Provider selection and pluggable generator interface - [ ] **M4**: Shared question framework and session management - [ ] **M5**: File output with user-specified path ### Argo CD Provider - [ ] **M6**: Argo CD-specific questions (namespace, project, sync policy) - [ ] **M7**: Application CR generation for all source types (Helm, Kustomize, directory) - [ ] **M8**: Integration tests for detection and Argo CD generation - [ ] **M9**: Documentation with examples --- ## Progress Log | Date | Update | |------|--------| | 2025-12-10 | PRD created as part of GitOps architecture restructuring | | 2025-12-10 | Supersedes #254, #255, #256 (with #265 and #266) |

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/vfarcic/dot-ai'

If you have feedback or need assistance with the MCP directory API, please join our Discord server