Skip to content

RHTAP-6521: Rename WithMCPImage to WithImage and defer validation#57

Merged
Roming22 merged 1 commit into
redhat-appstudio:mainfrom
otaviof:RHTAP-6521
May 4, 2026
Merged

RHTAP-6521: Rename WithMCPImage to WithImage and defer validation#57
Roming22 merged 1 commit into
redhat-appstudio:mainfrom
otaviof:RHTAP-6521

Conversation

@otaviof

@otaviof otaviof commented May 4, 2026

Copy link
Copy Markdown
Collaborator

Renames WithMCPImage() to WithImage() and moves the container image validation from framework initialization to MCPServer.Complete(). Previously, NewApp() and NewAppFromTarball() would fail if no image was provided, blocking all subcommands — even those that don't need one. Now only the mcp-server subcommand requires an image, validated at runtime. WithMCPImage() is retained as a deprecated alias so existing consumers continue to compile without changes.

Summary by CodeRabbit

  • New Features

    • Introduced WithImage() configuration option for specifying container images.
    • Image configuration is now validated at runtime.
  • Deprecations

    • WithMCPImage() is deprecated in favor of WithImage() (backward compatible).
  • Documentation

    • Updated getting started guides, CLI reference, and architecture documentation to reflect the new image configuration method.

Rename the `App.mcpImage` field to `App.image` and introduce
`WithImage()` as the primary functional option, keeping `WithMCPImage()`
as a deprecated alias for backward compatibility. Remove the hard
validation gate from `setupRootCmd()` so subcommands that don't require
a container image (`deploy`, `config`, `topology`, `integration`,
`template`, `installer`) work without one. Move the empty-image check
into `MCPServer.Complete()`, ensuring the mcp-server subcommand fails
clearly at runtime when no image is configured.

Update example, documentation (architecture, mcp, getting-started,
cli-reference, installer-structure), and add unit tests for the new
option, deprecated alias, and `MCPServer.Complete()` validation.

Assisted-by: Claude
@otaviof otaviof added the enhancement New feature or request label May 4, 2026
@coderabbitai

coderabbitai Bot commented May 4, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR unifies the MCP image configuration option from WithMCPImage() to WithImage(), renames the internal App field from mcpImage to image, shifts image validation from app setup to runtime in MCPServer.Complete(), and updates all documentation and examples accordingly.

Changes

Image Configuration Unification

Layer / File(s) Summary
Option API
framework/options.go
New WithImage() option introduced; WithMCPImage() marked deprecated and delegated to WithImage().
Core App Implementation
framework/app.go
Field mcpImage renamed to image in App struct; subcommand registration and doc comments updated; pre-setup MCP image validation removed.
Runtime Validation
internal/subcmd/mcpserver.go
MCPServer.Complete() now enforces non-empty image, returning error with guidance to use WithImage() or --image flag.
Framework Tests
framework/app_test.go
Added test helpers and three tests: TestNewApp_WithoutImage_Succeeds, TestWithImage_SetsImage, and TestWithMCPImage_DeprecatedAlias (verifying backward compatibility).
Subcommand Tests
internal/subcmd/mcpserver_test.go
Added four tests covering Complete() validation: empty image error, successful completion with image, flag override, and Validate() always succeeding.
Documentation
docs/architecture.md, docs/cli-reference.md, docs/getting-started.md, docs/installer-structure.md, docs/mcp.md
Option references and descriptions updated from WithMCPImage() to WithImage() throughout; MCP.md clarified that image validation occurs at runtime via Complete().
Example Code
example/helmet-ex/main.go
Updated app construction to use WithImage() and adjusted comments to refer to generic "image reference".

Sequence Diagram

sequenceDiagram
    actor User
    participant App as App (Framework)
    participant MCPServer as MCPServer<br/>(Subcommand)
    participant Complete as Complete()

    User->>App: NewAppFromTarball(WithImage("...") or no image)
    App->>App: Store image in a.image
    Note over App: No validation at setup time
    
    User->>MCPServer: Execute mcp-server command (--image flag optional)
    Note over MCPServer: Receives image from app.image<br/>or --image flag override
    MCPServer->>Complete: Complete(context)
    Complete->>Complete: Check if image is set
    alt Image is empty
        Complete-->>MCPServer: Error: "WithImage() required"
        MCPServer-->>User: Command fails
    else Image is set
        Complete-->>MCPServer: Success
        MCPServer->>User: Proceed with execution
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 With image renamed, the path grows clear,
No longer MCP, but unified here!
Validation moves late, where it should be—
At runtime Complete(), not setup decree.
Deprecated old ways, the future's bright! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main changes: renaming WithMCPImage to WithImage and deferring validation to runtime, which aligns with the core refactoring described in the pull request.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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
Review rate limit: 0/1 reviews remaining, refill in 60 minutes.

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (5)
framework/app_test.go (1)

23-32: ⚡ Quick win

TestNewApp_WithoutImage_Succeeds doesn't assert the default image is empty.

The test confirms NewApp succeeds without an image option, but doesn't assert app.image == "". This leaves a gap where a future change that defaulted image to a non-empty value would pass the test silently.

✏️ Suggested addition
 	if app == nil {
 		t.Fatal("expected non-nil App")
 	}
+	if app.image != "" {
+		t.Fatalf("expected empty image without WithImage option, got %q", app.image)
+	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@framework/app_test.go` around lines 23 - 32, TestNewApp_WithoutImage_Succeeds
currently verifies NewApp returns non-nil but doesn't assert the default image
is empty; add an assertion after creation that the App's image field (e.g.,
app.image or app.Image depending on visibility) equals the empty string and fail
the test (using t.Fatalf or t.Fatalf-like) if it's not, so the test explicitly
checks the default image behavior of NewApp.
internal/subcmd/mcpserver.go (1)

42-49: 💤 Low value

Consider moving the empty-image guard to Validate() instead of Complete().

Per the documented SubCommand lifecycle (and cli-reference.md in this PR), Complete is for loading external data/parsing args, while Validate is for "required fields are non-empty" checks. The image value is already fully resolved before PreRunE runs (Cobra applies the --image flag before PreRunE), so the guard would be equally correct in Validate() and would better match the lifecycle's stated intent.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/subcmd/mcpserver.go` around lines 42 - 49, Move the empty-image
guard out of Complete() and into Validate(): remove the fmt.Errorf check from
MCPServer.Complete and add the same check in MCPServer.Validate (returning the
same "container image not configured: use WithImage() option or --image flag"
error when m.image == ""), ensuring Complete() only handles loading/parsing and
Validate() enforces required-field checks for the MCPServer type.
docs/mcp.md (1)

108-108: 💤 Low value

Minor wording ambiguity in the WithImage() initialization note.

"WithImage() is no longer required at framework initialization" could be read as "no image is ever needed," since the next sentence mentions Complete() validation without explicitly stating that some image source is still mandatory. Consider tightening it, e.g.:

WithImage() no longer needs to be provided at framework initialization — image validation is deferred to mcp-server's Complete(). Either WithImage() or --image at runtime must supply a non-empty image.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/mcp.md` at line 108, Clarify the wording: update the note about
WithImage() so it states that WithImage() is optional at framework
initialization because image validation is deferred to mcp-server's Complete(),
but that an image source is still required at runtime — either provided via
WithImage() earlier or overridden/provided via the --image flag — and that one
of those must supply a non-empty image. Mention WithImage(), mcp-server,
Complete(), and --image to make the requirement explicit.
example/helmet-ex/main.go (1)

29-31: 💤 Low value

Minor naming inconsistency: buildMCPImage / mcpImage still carry the MCP prefix.

The call site and doc comment were updated to "image" terminology, but the local variable mcpImage and helper buildMCPImage still use the old MCP-specific prefix. Since this is an example/reference file, a rename would keep it fully consistent with the new naming.

✏️ Optional rename
-	// 3. Build image reference
-	mcpImage := buildMCPImage()
+	// 3. Build image reference
+	image := buildImage()

	// 4. Create application with framework options (GitHub URLs via CustomURLProvider; see framework/integrations.go)
	appIntegrations := framework.StandardIntegrations()
	appIntegrations = framework.WithURLProvider(appIntegrations, CustomURLProvider{})
	app, err := framework.NewAppFromTarball(
		appCtx,
		installer.InstallerTarball,
		cwd,
		framework.WithIntegrations(appIntegrations...),
-		framework.WithImage(mcpImage),
+		framework.WithImage(image),
	)
-// buildMCPImage constructs the container image reference for the installer.
+// buildImage constructs the container image reference for the installer.
// Uses the commit ID for versioning when available, falls back to 'latest'.
-func buildMCPImage() string {
+func buildImage() string {

Also applies to: 81-83

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@example/helmet-ex/main.go` around lines 29 - 31, Rename the MCP-specific
identifiers to the generic "image" naming: change function buildMCPImage to
buildImage and all local variable usages of mcpImage to image (also update any
related occurrences such as the later variables/uses around buildMCPImage and
mcpImage at the other occurrence). Update the function declaration, all calls,
and any comments/docstrings that reference buildMCPImage or mcpImage to use
buildImage and image so the example file is consistent with the new terminology.
framework/options.go (1)

27-30: 💤 Low value

WithMCPImage doc comment is missing a function-name lead.

The Go convention says to add a paragraph beginning with Deprecated: to the function's existing doc comment. The current comment has only the Deprecated: line with no preceding description starting with the function's name, which is the standard Go doc convention for exported identifiers.

✏️ Suggested wording
-// Deprecated: use WithImage instead.
+// WithMCPImage sets the container image for the installer.
+//
+// Deprecated: use WithImage instead.
func WithMCPImage(image string) Option {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@framework/options.go` around lines 27 - 30, Update the doc comment for
WithMCPImage to follow Go conventions by starting with the function name (e.g.,
"WithMCPImage returns an Option that sets the image.") and then include the
Deprecated paragraph "Deprecated: use WithImage instead." so the comment
contains a leading description followed by the deprecation note; ensure the
comment remains associated with the WithMCPImage function that currently
forwards to WithImage.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@docs/mcp.md`:
- Line 108: Clarify the wording: update the note about WithImage() so it states
that WithImage() is optional at framework initialization because image
validation is deferred to mcp-server's Complete(), but that an image source is
still required at runtime — either provided via WithImage() earlier or
overridden/provided via the --image flag — and that one of those must supply a
non-empty image. Mention WithImage(), mcp-server, Complete(), and --image to
make the requirement explicit.

In `@example/helmet-ex/main.go`:
- Around line 29-31: Rename the MCP-specific identifiers to the generic "image"
naming: change function buildMCPImage to buildImage and all local variable
usages of mcpImage to image (also update any related occurrences such as the
later variables/uses around buildMCPImage and mcpImage at the other occurrence).
Update the function declaration, all calls, and any comments/docstrings that
reference buildMCPImage or mcpImage to use buildImage and image so the example
file is consistent with the new terminology.

In `@framework/app_test.go`:
- Around line 23-32: TestNewApp_WithoutImage_Succeeds currently verifies NewApp
returns non-nil but doesn't assert the default image is empty; add an assertion
after creation that the App's image field (e.g., app.image or app.Image
depending on visibility) equals the empty string and fail the test (using
t.Fatalf or t.Fatalf-like) if it's not, so the test explicitly checks the
default image behavior of NewApp.

In `@framework/options.go`:
- Around line 27-30: Update the doc comment for WithMCPImage to follow Go
conventions by starting with the function name (e.g., "WithMCPImage returns an
Option that sets the image.") and then include the Deprecated paragraph
"Deprecated: use WithImage instead." so the comment contains a leading
description followed by the deprecation note; ensure the comment remains
associated with the WithMCPImage function that currently forwards to WithImage.

In `@internal/subcmd/mcpserver.go`:
- Around line 42-49: Move the empty-image guard out of Complete() and into
Validate(): remove the fmt.Errorf check from MCPServer.Complete and add the same
check in MCPServer.Validate (returning the same "container image not configured:
use WithImage() option or --image flag" error when m.image == ""), ensuring
Complete() only handles loading/parsing and Validate() enforces required-field
checks for the MCPServer type.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d40d439e-800c-4a9f-8690-d941e2017a43

📥 Commits

Reviewing files that changed from the base of the PR and between 049fbd4 and 02440cf.

📒 Files selected for processing (11)
  • docs/architecture.md
  • docs/cli-reference.md
  • docs/getting-started.md
  • docs/installer-structure.md
  • docs/mcp.md
  • example/helmet-ex/main.go
  • framework/app.go
  • framework/app_test.go
  • framework/options.go
  • internal/subcmd/mcpserver.go
  • internal/subcmd/mcpserver_test.go

@Roming22 Roming22 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

/lgtm

@Roming22 Roming22 merged commit 947c609 into redhat-appstudio:main May 4, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants