-
Notifications
You must be signed in to change notification settings - Fork 13
HYPERFLEET-474 - Spike: Evaluate Maestro REST vs gRPC API for HyperFleet integration #77
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
HYPERFLEET-474 - Spike: Evaluate Maestro REST vs gRPC API for HyperFleet integration #77
Conversation
WalkthroughAdds three new HyperFleet Maestro documents: an integration strategy prescribing a job-based maestro-cli approach (gRPC broker for resource operations + HTTP polling for status), ManifestWork-per-adapter-per-cluster naming and three granularity patterns (A/B/C), race-condition analyses, security and deployment requirements, and a roadmap; an architecture deep dive describing Maestro Server/Agent, PostgreSQL, brokers, deployment modes, communication protocols, resource/ManifestWork model, observability and troubleshooting; and a maestro-cli implementation guide specifying commands (apply/get/list/describe/delete/validate/wait/watch/diff/build), ManifestWork-centric workflows, status/result formats, build/merge strategies for nodepools, error-handling, scaling considerations, and migration guidance. Sequence Diagram(s)sequenceDiagram
participant CLI as "maestro-cli (Job)"
participant Maestro as "Maestro Server / Controller"
participant Broker as "Broker (gRPC)"
participant Cluster as "Managed Cluster (ManifestWork)"
participant Status as "Status Store (HTTP RESULTS_PATH)"
CLI->>Maestro: submit job (apply/delete/update)
activate Maestro
Maestro->>Broker: enqueue resource operation (gRPC)
Broker->>Cluster: deliver ManifestWork
Cluster-->>Maestro: ManifestWork status updates (k8s status / HTTP)
Maestro->>Status: write StatusResult to RESULTS_PATH (HTTP)
deactivate Maestro
CLI->>Status: poll/read StatusResult (wait/watch)
Status-->>CLI: return status/result
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 🧹 Recent nitpick comments
📜 Recent review detailsConfiguration used: Organization UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (3)
🧰 Additional context used🪛 LanguageToolhyperfleet/components/adapter/maestro-cli/maestro-adapter-integration-strategy.md[style] ~547-~547: This phrase is redundant. Consider writing “eliminate”. (COMPLETELY_ANNIHILATE) [style] ~560-~560: This phrase is redundant. Consider writing “eliminates”. (COMPLETELY_ANNIHILATE) [uncategorized] ~651-~651: If this is a compound adjective that modifies the following noun, use a hyphen. (EN_COMPOUND_ADJECTIVE_INTERNAL) 🪛 markdownlint-cli2 (0.18.1)hyperfleet/components/adapter/maestro-cli/maestro-cli-implementation.md103-103: Fenced code blocks should have a language specified (MD040, fenced-code-language) 691-691: Fenced code blocks should have a language specified (MD040, fenced-code-language) hyperfleet/components/adapter/maestro-cli/maestro-architecture.md39-39: Fenced code blocks should have a language specified (MD040, fenced-code-language) 58-58: Fenced code blocks should have a language specified (MD040, fenced-code-language) 76-76: Fenced code blocks should have a language specified (MD040, fenced-code-language) 95-95: Fenced code blocks should have a language specified (MD040, fenced-code-language) 🔇 Additional comments (7)
✏️ Tip: You can disable this entire section by setting Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In `@hyperfleet/components/adapter/maestro-cli/maestro-cli-implementation.md`:
- Around line 1208-1219: Change manifestKey to return (string, error) and
surface JSON unmarshal failures instead of returning an empty string: when
unstructured.Unstructured.UnmarshalJSON fails return a wrapped error; on success
return the formatted key via fmt.Sprintf and nil error. Update all callers that
use manifestKey(...) to handle the returned error (e.g., key, err :=
manifestKey(manifest); if err != nil { return fmt.Errorf("failed to generate
manifest key: %w", err) }) so failures are propagated instead of being silently
ignored.
- Around line 1153-1180: mergeManifestWork currently dereferences out-of-scope
flags.Name and flags.Consumer when existingWork is nil; update the function to
either accept explicit name and namespace parameters (e.g., add name, namespace
args to mergeManifestWork) or return an error when existingWork is nil, then
create the new work using those provided name/namespace values instead of flags.
Also validate the strategy when existingWork is nil (ensure only supported
strategies are allowed) and keep calling mergeStrategy or replaceStrategy on a
non-nil mergedWork; remove any references to flags.Name/flags.Consumer and use
the new parameters or explicit error paths.
🧹 Nitpick comments (9)
hyperfleet/components/adapter/maestro-cli/maestro-adapter-integration-strategy.md (4)
9-9: Format bare URL as a proper markdown link.The bare URL should be formatted as a markdown link for better readability and to comply with markdown best practices.
📝 Proposed fix
-| **Repository** | https://github.com/openshift-online/maestro | +| **Repository** | [openshift-online/maestro](https://github.com/openshift-online/maestro) |
431-431: Format bare URL as a proper markdown link.The bare URL should be formatted as a markdown link for better readability.
📝 Proposed fix
-See: https://github.com/openshift-hyperfleet/status-reporter +See: [HyperFleet status-reporter](https://github.com/openshift-hyperfleet/status-reporter)
481-481: Add language specifiers to fenced code blocks.Code blocks should specify the language type for proper syntax highlighting and better readability.
📝 Proposed fixes
For line 481:
-``` +```text maestro-cli (writes RESULTS_PATH) → status-reporter (reads RESULTS_PATH) → HyperFleet status updatesFor line 502: ```diff -``` +```text Each Adapter → K8s Job (maestro-cli apply) → Maestro → Creates ManifestWork with semantic name → Stored in Adapter's status data</details> Also applies to: 502-502 --- `619-673`: **Clarify the recommended pattern selection criteria.** The document presents Pattern A and Pattern B but the recommendation logic could be clearer. Lines 654-658 say "Use Pattern A" when each adapter manages single resources, but lines 659-668 warn that Pattern A "still requires fetching" for multiple resources, which seems contradictory. Consider restructuring the recommendation as: ```markdown ### Recommended Approach **Default: Pattern A (One ManifestWork Per Adapter Per Cluster)** - ✅ Use when each adapter type manages a single logical component - ✅ Simpler tracking and ownership model - ⚠️ Requires fetch-merge-apply for adapters managing multiple resources (e.g., multiple nodepools) **When to use Pattern B (One ManifestWork Per Resource Per Cluster)** - ✅ Adapter manages multiple independent resources (e.g., 5+ nodepools) - ✅ High-frequency parallel operations on resources - ✅ Independent lifecycle for each resource is critical - ⚠️ Accept higher operational overhead of tracking many ManifestWorksThis makes the decision criteria more actionable.
hyperfleet/components/adapter/maestro-cli/maestro-architecture.md (3)
39-39: Add language specifiers to deployment mode diagrams.The deployment mode diagrams in code blocks should have a language specifier for better rendering and clarity.
📝 Proposed fix
-``` +```text Components: - Maestro Server (with integrated gRPC broker)Apply similar changes to lines 57, 75, and 94. </details> Also applies to: 57-57, 75-75, 94-94 --- `165-189`: **Clarify the API endpoint support matrix.** The API endpoint support matrix at lines 170-174 shows that `/api/maestro/v1/resource-bundles` supports POST: ❌, but the "HTTP API Use Cases" section (lines 184-188) doesn't clarify what operations can be performed via HTTP on resource-bundles. Consider adding a note in the matrix: ```markdown | API Endpoint | GET | POST | PATCH | DELETE | Purpose | |--------------|-----|------|-------|--------|---------| | `/api/maestro/v1/consumers` | ✅ | ✅ | ❌ | ✅ | Consumer metadata management | | `/api/maestro/v1/resource-bundles` | ✅ Read-only | ❌ Use gRPC | ❌ Use gRPC | ✅ | ManifestWork status/monitoring | **Note**: ManifestWork creation and updates require gRPC CloudEvents. HTTP DELETE is supported for cleanup operations only.This makes the API capabilities more explicit.
263-267: Add guidance for log level recommendations.The logging strategy section mentions
KLOG_Vbut doesn't provide recommendations for appropriate verbosity levels for different scenarios.Consider adding:
# Configurable log levels - name: KLOG_V value: "2" # Production: 0-2, Debug: 3-5, Trace: 6+And document:
- Level 0-1: Errors and warnings only (production)
- Level 2: Important info messages (default production)
- Level 3-4: Debug information (troubleshooting)
- Level 5+: Verbose trace (development only)
hyperfleet/components/adapter/maestro-cli/maestro-cli-implementation.md (2)
103-103: Add language specifiers to code blocks.Code blocks should have language specifiers for proper rendering.
📝 Proposed fixes
Line 103:
-``` +```text Each ManifestWork = One Resource-BundleLine 115: ```diff -``` +```text cluster-west-1 (consumer):Line 917: ```diff -``` +```text maestro-cli (writes RESULTS_PATH) → status-reporter (reads RESULTS_PATH) → HyperFleet status updates</details> Also applies to: 115-115, 917-917 --- `1182-1206`: **Consider idempotency guarantees in mergeStrategy.** The `mergeStrategy` function replaces resources with the same kind/name/namespace but doesn't validate that the merge is idempotent. If called multiple times with the same input, it should produce the same result. Consider adding: 1. **Deterministic ordering** of manifests after merge 2. **Validation** that merged manifests don't contain duplicates 3. **Documentation** of merge behavior when manifests only differ in spec ```go func mergeStrategy(work *workv1.ManifestWork, newManifests []workv1.Manifest) (*workv1.ManifestWork, error) { existingManifests := work.Spec.Workload.Manifests // Build index of existing resources by kind/name/namespace existingIndex := make(map[string]int) for i, manifest := range existingManifests { key := manifestKey(manifest) if key == "" { return nil, fmt.Errorf("invalid manifest at index %d: cannot extract key", i) } existingIndex[key] = i } // Merge new manifests for _, newManifest := range newManifests { key := manifestKey(newManifest) if key == "" { return nil, fmt.Errorf("invalid manifest in new manifests: cannot extract key") } if existingIdx, exists := existingIndex[key]; exists { // Replace existing resource existingManifests[existingIdx] = newManifest } else { // Add new resource existingManifests = append(existingManifests, newManifest) } } work.Spec.Workload.Manifests = existingManifests return work, nil }
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
hyperfleet/components/adapter/maestro-cli/maestro-adapter-integration-strategy.mdhyperfleet/components/adapter/maestro-cli/maestro-architecture.mdhyperfleet/components/adapter/maestro-cli/maestro-cli-implementation.md
🧰 Additional context used
🪛 LanguageTool
hyperfleet/components/adapter/maestro-cli/maestro-adapter-integration-strategy.md
[style] ~594-~594: This phrase is redundant. Consider writing “eliminate”.
Context: ...ifestWork Per Resource Per Cluster** to completely eliminate race conditions: ```bash # Each resour...
(COMPLETELY_ANNIHILATE)
[style] ~607-~607: This phrase is redundant. Consider writing “eliminates”.
Context: ...age-cluster123 ``` Benefits: - ✅ Completely eliminates race conditions - no shared state any...
(COMPLETELY_ANNIHILATE)
🪛 markdownlint-cli2 (0.18.1)
hyperfleet/components/adapter/maestro-cli/maestro-adapter-integration-strategy.md
9-9: Bare URL used
(MD034, no-bare-urls)
431-431: Bare URL used
(MD034, no-bare-urls)
481-481: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
502-502: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
hyperfleet/components/adapter/maestro-cli/maestro-cli-implementation.md
103-103: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
115-115: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
917-917: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
hyperfleet/components/adapter/maestro-cli/maestro-architecture.md
39-39: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
57-57: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
75-75: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
94-94: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🔇 Additional comments (6)
hyperfleet/components/adapter/maestro-cli/maestro-adapter-integration-strategy.md (3)
10-10: Consider documenting image version maintenance strategy.The container image reference uses a specific SHA digest that may become outdated. Consider adding a note about version maintenance or using a tagged version reference.
Do you have a process for keeping this SHA updated, or would it be better to reference a stable tag (e.g.,
latestor version tag) with a note about verifying the digest?
153-170: Verify CronJob schedule syntax and resource requests.The CronJob example uses
"*/2 * * * *"(every 2 minutes) which may be too frequent for production scenarios. Additionally, the imagehyperfleet/maestro-sync:latestappears to be a placeholder.Consider documenting:
- Recommended sync intervals for different environments (dev/staging/prod)
- Whether the
hyperfleet/maestro-syncimage exists or is planned- Appropriate resource requests/limits for the sync controller
466-477: Verify the priority logic for RESULTS_PATH resolution.The
getResultsPathfunction checksflags.ResultsPathfirst, thenRESULTS_PATHenv var, then defaults to"/shared/results.json". However, line 394 shows--results-pathflag being passed which would override the env var from line 399. Ensure the documented priority order matches the actual implementation.Confirm that:
- The flag priority (flag > env > default) is correctly implemented
- The default path
/shared/results.jsonis appropriate for all execution contexts- The emptyDir volume mount at line 417 supports the default path
hyperfleet/components/adapter/maestro-cli/maestro-cli-implementation.md (2)
214-235: Verify error handling for version conflicts in applyManifestWork.The
applyManifestWorkfunction usesPatchto update existing ManifestWork but doesn't handle version conflicts explicitly. Given the race condition concerns discussed in the integration strategy doc, this should handle optimistic locking failures.Consider adding retry logic for version conflicts:
func applyManifestWork(ctx context.Context, workClient workv1client.WorkV1Interface, consumer string, manifestwork *workv1.ManifestWork) error { // Try to get existing work existingWork, err := workClient.ManifestWorks(consumer).Get(ctx, manifestwork.Name, metav1.GetOptions{}) if apierrors.IsNotFound(err) { _, err := workClient.ManifestWorks(consumer).Create(ctx, manifestwork, metav1.CreateOptions{}) return err } if err != nil { return fmt.Errorf("failed to get existing work: %w", err) } // Update ResourceVersion to ensure optimistic locking manifestwork.ResourceVersion = existingWork.ResourceVersion // Work exists, update with merge patch patchData, err := grpcsource.ToWorkPatch(existingWork, manifestwork) if err != nil { return fmt.Errorf("failed to create patch: %w", err) } _, err = workClient.ManifestWorks(consumer).Patch(ctx, manifestwork.Name, types.MergePatchType, patchData, metav1.PatchOptions{}) if apierrors.IsConflict(err) { return fmt.Errorf("version conflict - resource modified: %w", err) } return err }Should the CLI handle retries for conflicts, or is that the adapter's responsibility?
1243-1276: Excellent documentation of performance trade-offs.The performance considerations section clearly articulates the design rationale for prioritizing simplicity over optimization in the job-based CLI approach. The comparison table between maestro-cli and future adapter framework is particularly helpful for understanding when these trade-offs matter.
This kind of explicit documentation of trade-off decisions is valuable for future maintainers and helps prevent premature optimization.
hyperfleet/components/adapter/maestro-cli/maestro-architecture.md (1)
196-197: The claim and explanation are accurate. Maestro correctly uses Open Cluster Management APIs (specifically the ManifestWork resource definition) without requiring the ACM operator, because it implements its own control plane with custom CloudEvents transport and PostgreSQL storage. The existing documentation already adequately explains this relationship. No changes needed.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
hyperfleet/components/adapter/maestro-cli/maestro-adapter-integration-strategy.md
Show resolved
Hide resolved
hyperfleet/components/adapter/maestro-cli/maestro-architecture.md
Outdated
Show resolved
Hide resolved
hyperfleet/components/adapter/maestro-cli/maestro-adapter-integration-strategy.md
Outdated
Show resolved
Hide resolved
hyperfleet/components/adapter/maestro-cli/maestro-cli-implementation.md
Outdated
Show resolved
Hide resolved
hyperfleet/components/adapter/maestro-cli/maestro-adapter-integration-strategy.md
Outdated
Show resolved
Hide resolved
hyperfleet/components/adapter/maestro-cli/maestro-adapter-integration-strategy.md
Show resolved
Hide resolved
hyperfleet/components/adapter/maestro-cli/maestro-adapter-integration-strategy.md
Show resolved
Hide resolved
hyperfleet/components/adapter/maestro-cli/maestro-adapter-integration-strategy.md
Show resolved
Hide resolved
hyperfleet/components/adapter/maestro-cli/maestro-architecture.md
Outdated
Show resolved
Hide resolved
hyperfleet/components/adapter/maestro-cli/maestro-cli-implementation.md
Outdated
Show resolved
Hide resolved
hyperfleet/components/adapter/maestro-cli/maestro-cli-implementation.md
Outdated
Show resolved
Hide resolved
hyperfleet/components/adapter/maestro-cli/maestro-cli-implementation.md
Outdated
Show resolved
Hide resolved
d84b354 to
fa4a039
Compare
There was a problem hiding this 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 `@hyperfleet/components/adapter/maestro-cli/maestro-cli-implementation.md`:
- Around line 636-685: The docs are inconsistent about a default RESULTS_PATH;
reconcile by making the code follow the integration strategy: change
getResultsPath (used by writeStatusResult and referencing MaestroCLIFlags and
RESULTS_PATH env) to return the default "/shared/results.json" when both
flags.ResultsPath and os.Getenv("RESULTS_PATH") are empty, update the inline
comment/documentation in this file to reflect that default, and ensure
writeStatusResult still writes to that path when returned.
- Line 454: Correct the spelling of "benifits" to "benefits" in the sentence
under the "No state persistence needed" paragraph; locate the line containing
the phrase "**No state persistence needed** - Subscribe-based approach requires
a "database" to record status from CloudEvents, otherwise duplicating what
Maestro Server already does; HTTP polling leverages Maestro's existing status
storage. We can use RESULT_PATH file to record the status with gRPC, but not
enough benifits from the complexity." and replace "benifits" with "benefits".
♻️ Duplicate comments (2)
hyperfleet/components/adapter/maestro-cli/maestro-adapter-integration-strategy.md (2)
317-340: Security context and certificate mounts are missing from Job template.The Job template lacks security hardening and TLS certificate volume mounts required for mTLS authentication (referenced in lines 361-369 and 373-389).
🔒 Security enhancements needed
Add security context and certificate volume mounts:
containers: - name: maestro-cli image: hyperfleet/maestro-cli:latest command: ["maestro-cli", "apply"] args: - --manifest-file=/config/manifest.yaml - --consumer=${target-cluster} - --watch - --timeout=5m - --grpc-endpoint=maestro-grpc:8090 + - --grpc-server-ca-file=/certs/ca.crt + - --grpc-client-cert-file=/certs/client.crt + - --grpc-client-key-file=/certs/client.key + securityContext: + runAsNonRoot: true + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + capabilities: + drop: + - ALL volumeMounts: - name: manifest-config mountPath: /config + - name: tls-certs + mountPath: /certs + readOnly: true restartPolicy: Never + volumes: + - name: manifest-config + configMap: + name: ${manifest-config-name} + - name: tls-certs + secret: + secretName: maestro-client-certs
411-466: Apply security hardening to this Job template as well.This Job template (like the earlier one at lines 317-340) should include security context and TLS certificate volume mounts for production readiness.
🔒 Add security context
containers: - name: maestro-cli image: hyperfleet/maestro-cli:latest command: ["maestro-cli", "apply"] args: - --manifest-file=/config/manifest.yaml - --consumer=${target-cluster} - --watch - --timeout=5m - --grpc-endpoint=maestro-grpc:8090 - --http-endpoint=maestro-http:8000 - --results-path=/shared/results.json + - --grpc-server-ca-file=/certs/ca.crt + - --grpc-client-cert-file=/certs/client.crt + - --grpc-client-key-file=/certs/client.key + securityContext: + runAsNonRoot: true + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + capabilities: + drop: + - ALL env: - name: EVENT_ID value: "${sentinel-event-id}" - name: RESULTS_PATH value: "/shared/results.json" volumeMounts: - name: shared-status mountPath: /shared - name: manifest-config mountPath: /config + - name: tls-certs + mountPath: /certs + readOnly: trueAnd add the certificate secret volume:
volumes: - name: shared-status emptyDir: {} - name: manifest-config configMap: name: ${manifest-config-name} + - name: tls-certs + secret: + secretName: maestro-client-certs
🧹 Nitpick comments (6)
hyperfleet/components/adapter/maestro-cli/maestro-adapter-integration-strategy.md (4)
10-10: Consider adding a note about container image versioning.The hardcoded SHA256 digest may become outdated as Maestro evolves. For production deployment, consider documenting a version update strategy or using tagged releases.
507-518: Consider whether a default RESULTS_PATH is appropriate.The default path
/shared/results.jsonassumes a specific volume mount exists. If the volume is not configured, writes will fail silently. Consider either:
- No default (return empty string) to make configuration explicit
- Document the requirement for the
/sharedvolume mount
704-726: Clarify Pattern A vs Pattern B recommendation.Lines 706-709 recommend Pattern A for "each adapter manages single resources" but lines 711-714 immediately list limitations where Pattern A still requires fetching and has race conditions. Consider restructuring to:
- Start with Pattern B as the default recommendation
- Note Pattern A as acceptable only when truly single-resource per adapter and no concurrency
The current flow seems contradictory.
729-786: Framework integration discussion may create confusion about Pattern C.Line 756 suggests shared ManifestWork patterns (Pattern C) "may become viable with proper in-process coordination" in framework mode. However, earlier sections (lines 79-110) strongly warn against Pattern C due to resource loss risks. Clarify that:
- Pattern C would require significant architectural changes
- Even with framework integration, the fetch-merge-apply complexity remains
- Pattern B (per-resource) may still be preferable for true parallelism
hyperfleet/components/adapter/maestro-cli/maestro-architecture.md (2)
56-110: Add status update flows to broker-based deployment mode diagrams.The gRPC mode diagram (line 46) shows bidirectional communication, but MQTT, GCP Pub/Sub, and AWS IoT diagrams only show one direction. Based on past review discussions, the server subscribes to status updates from agents via the broker. Consider adding status update flows:
# MQTT Mode Server ──Publish──▶ MQTT Broker ──Subscribe──▶ Agents ◀──Subscribe─ MQTT Broker ◀──Publish──── Agents (status) # GCP Pub/Sub Mode Server ──Publish──▶ GCP Pub/Sub ──Subscribe──▶ Agents ◀──Subscribe─ GCP Pub/Sub ◀──Publish──── Agents (status)This clarifies the complete resource lifecycle mentioned in maestro-cli-implementation.md.
222-246: Security architecture provides good overview.The three-layer authentication model is well documented. However, "Certificate rotation strategy" (line 239) is mentioned without details. Consider adding a reference to operational procedures or noting this as a deployment consideration.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
hyperfleet/components/adapter/maestro-cli/maestro-adapter-integration-strategy.mdhyperfleet/components/adapter/maestro-cli/maestro-architecture.mdhyperfleet/components/adapter/maestro-cli/maestro-cli-implementation.md
🧰 Additional context used
🪛 LanguageTool
hyperfleet/components/adapter/maestro-cli/maestro-cli-implementation.md
[grammar] ~454-~454: Ensure spelling is correct
Context: ...rd the status with gRPC, but not enough benifits from the complexity. **Trade-offs Acce...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
hyperfleet/components/adapter/maestro-cli/maestro-adapter-integration-strategy.md
[style] ~635-~635: This phrase is redundant. Consider writing “eliminate”.
Context: ...er Resource Per Cluster(pattern B)** to completely eliminate race conditions: ```bash # Each resour...
(COMPLETELY_ANNIHILATE)
[style] ~648-~648: This phrase is redundant. Consider writing “eliminates”.
Context: ...depool-storage ``` Benefits: - ✅ Completely eliminates race conditions - no shared state any...
(COMPLETELY_ANNIHILATE)
[uncategorized] ~739-~739: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ...Operation Frequency** | Low to medium | High frequency operations | | Latency Requirements...
(EN_COMPOUND_ADJECTIVE_INTERNAL)
🪛 markdownlint-cli2 (0.18.1)
hyperfleet/components/adapter/maestro-cli/maestro-cli-implementation.md
103-103: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
691-691: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
hyperfleet/components/adapter/maestro-cli/maestro-architecture.md
39-39: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
57-57: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
75-75: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
94-94: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
hyperfleet/components/adapter/maestro-cli/maestro-adapter-integration-strategy.md
9-9: Bare URL used
(MD034, no-bare-urls)
39-39: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
472-472: Bare URL used
(MD034, no-bare-urls)
522-522: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
543-543: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🔇 Additional comments (9)
hyperfleet/components/adapter/maestro-cli/maestro-adapter-integration-strategy.md (2)
183-187: Verify operational overhead rating for Hybrid approach.The table shows Hybrid has "High" resource usage but only "Medium" operational overhead. Given that Hybrid requires managing both push and pull mechanisms, consider whether "High" operational overhead would be more accurate.
554-631: Excellent explanation of race conditions and Maestro's version control.The distinction between version conflicts (handled by Maestro) and resource loss (not prevented) is clearly explained with concrete timing examples. This effectively justifies the "One ManifestWork Per Adapter Per Cluster" pattern.
hyperfleet/components/adapter/maestro-cli/maestro-architecture.md (3)
142-161: Well-documented event consumption risks.The distinction between queue-based (MQTT/AWS IoT) and broadcast (gRPC) consumption patterns is clearly explained. This helps justify the gRPC recommendation in the integration strategy document.
164-188: API capabilities clearly documented.The distinction between HTTP (read-only) and gRPC (lifecycle operations) is well explained, supporting the hybrid communication pattern recommended in the integration strategy.
250-317: Comprehensive monitoring and troubleshooting guidance.The observability section provides practical metrics, logging configuration, and troubleshooting steps. This will be valuable for operational teams.
hyperfleet/components/adapter/maestro-cli/maestro-cli-implementation.md (4)
88-384: Excellent analysis of implementation approaches.The comparison between ManifestWork Client and CloudEvents implementations is thorough and well-reasoned. The detailed table (lines 361-370) and problem analysis (lines 372-377) provide strong justification for the chosen approach.
697-732: Clear documentation of complete manifest update requirement.The explanation that ManifestWork always requires complete state (not partial updates) is well documented with examples showing both correct and incorrect usage.
735-985: Build command provides valuable automation for nodepool management.The build command design addresses the fetch-merge-apply workflow complexity effectively. The merge strategies (merge vs replace) and nodepool configuration format are well documented.
988-1020: Pragmatic performance assessment for job-based approach.The acknowledgment that job startup overhead dominates CLI execution time (lines 1016-1017) justifies the "simplicity over performance" trade-off. The forward-looking comparison with framework integration provides valuable context for future optimization decisions.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
| - **No broker dependency** - Works even if gRPC broker has issues | ||
| - **Configurable intervals** - Balance between latency and server load | ||
| - **No broker-specific setup** - Subscribe requires additional preparation for non-gRPC brokers (e.g., GCP Pub/Sub requires creating a separate subscription, AWS IoT requires topic configuration) | ||
| - **No state persistence needed** - Subscribe-based approach requires a "database" to record status from CloudEvents, otherwise duplicating what Maestro Server already does; HTTP polling leverages Maestro's existing status storage. We can use RESULT_PATH file to record the status with gRPC, but not enough benifits from the complexity. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix spelling error.
Line 454: "benifits" should be "benefits"
-- **No state persistence needed** - Subscribe-based approach requires a "database" to record status from CloudEvents, otherwise duplicating what Maestro Server already does; HTTP polling leverages Maestro's existing status storage. We can use RESULT_PATH file to record the status with gRPC, but not enough benifits from the complexity.
+- **No state persistence needed** - Subscribe-based approach requires a "database" to record status from CloudEvents, otherwise duplicating what Maestro Server already does; HTTP polling leverages Maestro's existing status storage. We can use RESULT_PATH file to record the status with gRPC, but not enough benefits from the complexity.📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - **No state persistence needed** - Subscribe-based approach requires a "database" to record status from CloudEvents, otherwise duplicating what Maestro Server already does; HTTP polling leverages Maestro's existing status storage. We can use RESULT_PATH file to record the status with gRPC, but not enough benifits from the complexity. | |
| - **No state persistence needed** - Subscribe-based approach requires a "database" to record status from CloudEvents, otherwise duplicating what Maestro Server already does; HTTP polling leverages Maestro's existing status storage. We can use RESULT_PATH file to record the status with gRPC, but not enough benefits from the complexity. |
🧰 Tools
🪛 LanguageTool
[grammar] ~454-~454: Ensure spelling is correct
Context: ...rd the status with gRPC, but not enough benifits from the complexity. **Trade-offs Acce...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
🤖 Prompt for AI Agents
In `@hyperfleet/components/adapter/maestro-cli/maestro-cli-implementation.md` at
line 454, Correct the spelling of "benifits" to "benefits" in the sentence under
the "No state persistence needed" paragraph; locate the line containing the
phrase "**No state persistence needed** - Subscribe-based approach requires a
"database" to record status from CloudEvents, otherwise duplicating what Maestro
Server already does; HTTP polling leverages Maestro's existing status storage.
We can use RESULT_PATH file to record the status with gRPC, but not enough
benifits from the complexity." and replace "benifits" with "benefits".
042afca to
6a681a0
Compare
There was a problem hiding this 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
🤖 Fix all issues with AI agents
In `@hyperfleet/components/adapter/maestro-cli/maestro-cli-implementation.md`:
- Around line 636-685: The documentation and implementation disagree on
RESULTS_PATH default: getResultsPath (used by writeStatusResult) currently
returns an empty string (no default) while
maestro-adapter-integration-strategy.md declares "/shared/results.json" as the
default; pick one approach and make both docs and code consistent. If you choose
"no default" (recommended) keep getResultsPath and writeStatusResult as-is and
update maestro-adapter-integration-strategy.md to remove the default path; if
you choose the default path approach, change getResultsPath to return
"/shared/results.json" when neither flags.ResultsPath nor RESULTS_PATH env var
are set and update the comment and the Status Output "Default" line to reflect
that default; ensure references to MaestroCLIFlags, ResultsPath flag, and
environment variable RESULTS_PATH are updated in both documents.
♻️ Duplicate comments (1)
hyperfleet/components/adapter/maestro-cli/maestro-cli-implementation.md (1)
454-454: Fix spelling error."benifits" should be "benefits".
✏️ Proposed fix
-- **No state persistence needed** - Subscribe-based approach requires a "database" to record status from CloudEvents, otherwise duplicating what Maestro Server already does; HTTP polling leverages Maestro's existing status storage. We can use RESULT_PATH file to record the status with gRPC, but not enough benifits from the complexity. +- **No state persistence needed** - Subscribe-based approach requires a "database" to record status from CloudEvents, otherwise duplicating what Maestro Server already does; HTTP polling leverages Maestro's existing status storage. We can use RESULT_PATH file to record the status with gRPC, but not enough benefits from the complexity.
🧹 Nitpick comments (2)
hyperfleet/components/adapter/maestro-cli/maestro-architecture.md (1)
39-110: Consider adding language identifiers to architecture diagrams.The static analysis tool flags these fenced code blocks as missing language specifiers. While adding
textorplaintextidentifiers wouldn't change rendering, it would silence linter warnings and make the intent explicit.📝 Optional: Add language identifiers
For example, line 39:
-``` +```text Components: - Maestro Server (with integrated gRPC broker)Apply similar changes to lines 57, 75, and 94.
hyperfleet/components/adapter/maestro-cli/maestro-adapter-integration-strategy.md (1)
103-103: Consider adding language identifier to code block.While this appears to be pseudo-text showing a timeline scenario, adding a language identifier like
textorbashwould silence linter warnings.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
hyperfleet/components/adapter/maestro-cli/maestro-adapter-integration-strategy.mdhyperfleet/components/adapter/maestro-cli/maestro-architecture.mdhyperfleet/components/adapter/maestro-cli/maestro-cli-implementation.md
🧰 Additional context used
🪛 LanguageTool
hyperfleet/components/adapter/maestro-cli/maestro-cli-implementation.md
[grammar] ~454-~454: Ensure spelling is correct
Context: ...rd the status with gRPC, but not enough benifits from the complexity. **Trade-offs Acce...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
hyperfleet/components/adapter/maestro-cli/maestro-adapter-integration-strategy.md
[style] ~554-~554: This phrase is redundant. Consider writing “eliminate”.
Context: ...er Resource Per Cluster(pattern B)** to completely eliminate race conditions: ```bash # Each resour...
(COMPLETELY_ANNIHILATE)
[style] ~567-~567: This phrase is redundant. Consider writing “eliminates”.
Context: ...depool-storage ``` Benefits: - ✅ Completely eliminates race conditions - no shared state any...
(COMPLETELY_ANNIHILATE)
[uncategorized] ~658-~658: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ...Operation Frequency** | Low to medium | High frequency operations | | Latency Requirements...
(EN_COMPOUND_ADJECTIVE_INTERNAL)
🪛 markdownlint-cli2 (0.18.1)
hyperfleet/components/adapter/maestro-cli/maestro-architecture.md
39-39: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
57-57: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
75-75: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
94-94: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
hyperfleet/components/adapter/maestro-cli/maestro-adapter-integration-strategy.md
103-103: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
691-691: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🔇 Additional comments (3)
hyperfleet/components/adapter/maestro-cli/maestro-architecture.md (1)
1-317: Comprehensive architecture documentation.This document provides excellent coverage of Maestro's architecture, deployment modes, security considerations, and operational guidance. The structured approach with tables, code examples, and troubleshooting sections makes it highly valuable for integration planning.
hyperfleet/components/adapter/maestro-cli/maestro-adapter-integration-strategy.md (1)
1-716: Well-structured integration strategy with thorough race condition analysis.The document effectively covers:
- Job-based maestro-CLI approach with clear rationale
- One ManifestWork per adapter per cluster pattern to avoid race conditions
- Detailed comparison of resource-manifest strategies (Patterns A, B, C)
- Security considerations and future framework integration path
The race condition scenarios (lines 86-105, 504-543) are particularly valuable, clearly demonstrating why the chosen pattern eliminates resource loss issues.
hyperfleet/components/adapter/maestro-cli/maestro-cli-implementation.md (1)
1-1023: Comprehensive CLI implementation guide with clear workflow examples.This document excels at:
- Detailed command specifications with multi-cluster examples
- Clear rationale for ManifestWork client over CloudEvents approach (lines 88-385)
- Thorough build command workflow for nodepool merging (lines 735-985)
- Explicit performance trade-off discussions for job-based vs framework integration
The decision to use HTTP polling for status monitoring (lines 443-464) is well-justified given the job-based architecture, and the performance considerations section (lines 988-1020) appropriately scopes optimization concerns to future framework integration.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
6a681a0 to
b481b9c
Compare
There was a problem hiding this 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
`@hyperfleet/components/adapter/maestro-cli/maestro-adapter-integration-strategy.md`:
- Line 429: The two docs disagree on the default RESULTS_PATH; change the
implementation in maestro-adapter-integration-strategy.md so the
function/constant that currently returns "/shared/results.json" instead returns
"" and update its inline comment to indicate "Default: None" (no default),
ensuring it matches maestro-cli-implementation.md which currently returns an
empty string; confirm both documents now consistently state no default for
RESULTS_PATH.
- Line 274: The table row "PostgreSQL Database | ✅ | 17.2+" in
maestro-adapter-integration-strategy.md conflicts with the integration tests
that use postgres:15; either change that table entry to "PostgreSQL Database | ✅
| 15+" to match the tested version or add a short justification next to the
17.2+ entry explaining why 17.2+ is required (mentioning the specific
feature/behavior and linking to the tests that use postgres:15 and/or update the
test matrix to use 17.2 if you truly require it); update any related
documentation notes so the specification and the test configuration are
consistent.
♻️ Duplicate comments (1)
hyperfleet/components/adapter/maestro-cli/maestro-cli-implementation.md (1)
640-685: RESULTS_PATH configuration is correctly documented here.This document correctly specifies:
- Priority: flag > env var > no default
- Default: None (line 646)
- Returns empty string when not configured (line 683)
However, this conflicts with
maestro-adapter-integration-strategy.mdline 429 which returns"/shared/results.json"as the default. This inconsistency was flagged in the review of that file.The approach in this document (no default) is safer as it makes configuration explicit. Ensure the integration strategy document is updated to match.
🧹 Nitpick comments (1)
hyperfleet/components/adapter/maestro-cli/maestro-architecture.md (1)
39-47: Communication flow diagram for gRPC mode is simplified.The communication flow shows a single line "Server ──gRPC Stream──▶ Agents ──Status Updates──▶ Server", but this doesn't clearly convey that gRPC is bidirectional. The server publishes resource events, and agents publish status events back, both over the gRPC broker.
Consider clarifying the bidirectional nature:
Communication Flow: - Server ──gRPC Stream──▶ Agents ──Status Updates──▶ Server + Server ←──gRPC Stream (bidirectional)──▶ Agents + (Resources: Server → Agents, Status: Agents → Server)Based on learnings from past review, this flow includes both resource delivery and status updates through the gRPC broker.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
hyperfleet/components/adapter/maestro-cli/maestro-adapter-integration-strategy.mdhyperfleet/components/adapter/maestro-cli/maestro-architecture.mdhyperfleet/components/adapter/maestro-cli/maestro-cli-implementation.md
🧰 Additional context used
🪛 LanguageTool
hyperfleet/components/adapter/maestro-cli/maestro-adapter-integration-strategy.md
[style] ~547-~547: This phrase is redundant. Consider writing “eliminate”.
Context: ...er Resource Per Cluster(pattern B)** to completely eliminate race conditions: ```bash # Each resour...
(COMPLETELY_ANNIHILATE)
[style] ~560-~560: This phrase is redundant. Consider writing “eliminates”.
Context: ...depool-storage ``` Benefits: - ✅ Completely eliminates race conditions - no shared state any...
(COMPLETELY_ANNIHILATE)
[uncategorized] ~651-~651: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ...Operation Frequency** | Low to medium | High frequency operations | | Latency Requirements...
(EN_COMPOUND_ADJECTIVE_INTERNAL)
🪛 markdownlint-cli2 (0.18.1)
hyperfleet/components/adapter/maestro-cli/maestro-architecture.md
39-39: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
57-57: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
75-75: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
94-94: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
hyperfleet/components/adapter/maestro-cli/maestro-cli-implementation.md
103-103: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
691-691: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
hyperfleet/components/adapter/maestro-cli/maestro-adapter-integration-strategy.md
9-9: Bare URL used
(MD034, no-bare-urls)
39-39: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
391-391: Bare URL used
(MD034, no-bare-urls)
434-434: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
455-455: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🔇 Additional comments (12)
hyperfleet/components/adapter/maestro-cli/maestro-adapter-integration-strategy.md (3)
10-10: Container image reference uses SHA256 digest.The container image is pinned to a specific SHA256 digest, which is a security best practice for ensuring immutable deployments. However, this may complicate version tracking and updates.
Consider documenting the version mapping for this SHA or using tagged releases for easier maintenance:
#!/bin/bash # Verify the image digest and check for newer versions echo "Current pinned image:" echo "quay.io/redhat-user-workloads/maestro-rhtap-tenant/maestro/maestro@sha256:062efc1b4a78e45c714f1925528443d49201acd0c7ce447c20e60706138550ec" echo -e "\nChecking if this digest is still valid and what version it represents..." # Note: This requires authentication to the registry
262-262: Verify status-reporter repository URL.The document references an external GitHub repository for the status-reporter component. Ensure this repository exists and is accessible to implementers.
#!/bin/bash # Verify the status-reporter repository exists and is accessible echo "Checking if status-reporter repository exists..." curl -s -o /dev/null -w "%{http_code}" https://github.com/openshift-hyperfleet/status-reporter | grep -q "200" && echo "✅ Repository exists" || echo "❌ Repository not found or not accessible"
700-709: LGTM! Clear conclusion aligns with spike objectives.The conclusion effectively summarizes the recommended approach:
- gRPC mode for broker communication
- HTTP API for read-only monitoring
- gRPC required for ManifestWork lifecycle
- Job-based maestro-cli for simplicity
- Hybrid communication pattern for reliability
The key takeaways are actionable and align with the spike evaluation goals.
hyperfleet/components/adapter/maestro-cli/maestro-architecture.md (3)
135-138: Subscription requirements are clearly documented.The document correctly identifies that:
- gRPC has dynamic subscriptions (no pre-setup)
- MQTT requires topic structure configuration
- GCP Pub/Sub requires topics/subscriptions created beforehand
- AWS IoT requires Things, certificates, and policies
This is important operational information for deployment planning.
250-317: LGTM! Comprehensive monitoring and troubleshooting guidance.The monitoring section covers key metrics, logging strategy, and alerting scenarios. The troubleshooting guide is well-organized by problem domain (connection, resource delivery, database, permissions) and provides actionable debugging steps.
17-17: Verify the 200,000+ clusters scalability claim against Maestro's official documentation.The document attributes this scalability figure to Maestro (an external system). While Maestro's repository is public (github.com/openshift-online/maestro), the specific 200,000+ clusters claim lacks supporting evidence in publicly accessible documentation. Consider either linking to official Maestro benchmarks/docs that validate this figure, or softening the claim to reflect the current state of validation (e.g., "Designed to scale" vs "Scalable to").
hyperfleet/components/adapter/maestro-cli/maestro-cli-implementation.md (6)
361-378: LGTM! Clear comparison justifies ManifestWork over CloudEvents.The comparison table effectively demonstrates why the ManifestWork client is superior:
- No bundle ID management needed (semantic names)
- Built-in apply logic (handles create/update)
- Strong typing and type safety
- Simpler API (kubectl-like operations)
- Real-time watch support
The "Key Problems with CloudEvents Approach" section provides concrete reasons for the architectural choice.
419-419: Verify Maestro example reference URL.The document references the official Maestro ManifestWork client example. Ensure this path exists in the Maestro repository and is accessible to implementers.
#!/bin/bash # Verify the Maestro example file exists echo "Checking Maestro ManifestWork client example..." curl -s -o /dev/null -w "%{http_code}" https://github.com/openshift-online/maestro/blob/main/examples/manifestwork/client.go | grep -q "200" && echo "✅ Example file exists" || echo "❌ File not found"
442-464: LGTM! Well-reasoned decision to use HTTP polling for status monitoring.The rationale for HTTP polling over gRPC subscription is solid:
- No event consumption conflicts
- Simpler implementation
- Works regardless of broker type
- No state persistence needed
The trade-offs (higher latency, more requests) are acceptable for job-based operations where startup time dominates. This aligns with the "simplicity and reliability over performance" principle stated in the document.
699-731: Important constraint: Always provide complete ManifestWork.The document correctly emphasizes that maestro-cli requires complete ManifestWork resources, not partial updates. The rationale is sound:
- ManifestWork spec represents complete desired state
- Missing manifests will be deleted by the agent
- Ensures atomic operations and consistency
The warning at line 730 is crucial for preventing accidental resource deletion.
735-985: LGTM! Build command design addresses nodepool merging use case.The Build command provides a valuable abstraction for complex merge scenarios:
- Fetches existing ManifestWork
- Merges nodepool configuration
- Supports merge vs replace strategies
- Can apply directly or output for review
The implementation examples show the pattern clearly. The merge strategy comparison helps users choose the right approach.
Note: Based on learnings from past review, code issues in the examples (like scope problems in line 903-904) are acceptable since this is documentation/example code.
988-1023: LGTM! Realistic performance expectations for job-based approach.The document honestly acknowledges that performance optimization is not a primary concern for the short-lived CLI tool, since job startup overhead dominates. The comparison with future adapter framework integration is valuable for understanding when optimization becomes important.
The trade-off decisions are well-articulated:
- Simplicity over performance
- Job isolation over efficiency
- Reliability over speed
- Maintainability over optimization
This pragmatic approach aligns with the spike's goal of finding the optimal balance.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
hyperfleet/components/adapter/maestro-cli/maestro-adapter-integration-strategy.md
Show resolved
Hide resolved
hyperfleet/components/adapter/maestro-cli/maestro-adapter-integration-strategy.md
Outdated
Show resolved
Hide resolved
b481b9c to
061b84b
Compare
061b84b to
6fdd7f0
Compare
ciaranRoche
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/lgtm
Lets merge this to unblock the effort and we will iterate on it during implementation over the next 2 weeks
hyperfleet/components/adapter/maestro-cli/maestro-adapter-integration-strategy.md
Show resolved
Hide resolved
hyperfleet/components/adapter/maestro-cli/maestro-adapter-integration-strategy.md
Show resolved
Hide resolved
hyperfleet/components/adapter/maestro-cli/maestro-adapter-integration-strategy.md
Show resolved
Hide resolved
hyperfleet/components/adapter/maestro-cli/maestro-adapter-integration-strategy.md
Show resolved
Hide resolved
hyperfleet/components/adapter/maestro-cli/maestro-adapter-integration-strategy.md
Show resolved
Hide resolved
|
merge it. |
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.