Skip to content

provider name enhancements#615

Open
dubinsky wants to merge 1 commit intoskevetter:mainfrom
dubinsky:provider-name
Open

provider name enhancements#615
dubinsky wants to merge 1 commit intoskevetter:mainfrom
dubinsky:provider-name

Conversation

@dubinsky
Copy link

@dubinsky dubinsky commented Mar 16, 2026

  • chore: typos and minor cleanup
  • feat: convey to the provider the name it is running under
  • feat: use DEVPOD_PROVIDER_<provider name>_SOURCE environment variable
  • feat: scope command flags environment variables by the first-level subcommand name

Summary by CodeRabbit

  • New Features

    • Provider add accepts a name, Git repo, URL, or local path; named providers are included in the workspace environment.
    • CLI supports per-command environment variable overrides for flags.
  • Bug Fixes

    • Provider delete ignores extra arguments and will fall back to a configured default when none is specified.
  • Documentation

    • Clarified usage and error messages for provider and update commands.
  • Style

    • Standardized punctuation and phrasing across CLI help and provider docs.

@coderabbitai
Copy link

coderabbitai bot commented Mar 16, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds provider-name validation and multi-source resolution (positional or DEVPOD_PROVIDER[_]_SOURCE) to provider add; separates clone-vs-add flows; relaxes provider delete arg validation; updates ToEnvironment signature and callers to accept provider name; introduces per-command environment variable prefixes; punctuation/docs tweaks.

Changes

Cohort / File(s) Summary
Provider add/update/delete CLI
cmd/provider/add.go, cmd/provider/update.go, cmd/provider/delete.go
add: validate providerName (regex + max length), resolve providerSource from arg or env (DEVPOD_PROVIDER_SOURCE or DEVPOD_PROVIDER_<NAME>_SOURCE), require source for new provider, use providerName when cloning; update: usage/error text adjusted; delete: ignores extra args and uses first arg or default.
Provider environment API & call sites
pkg/provider/env.go, pkg/provider/download.go, pkg/driver/custom/custom.go
ToEnvironment(...) signature extended with providerName; call sites updated to pass config.Name or ""; when non-empty, env includes DEVPOD_PROVIDER=<name>.
CLI root/env flag handling
cmd/root.go
Propagates commandPrefix for environment flag inheritance; enables per-subcommand DEVPOD__... env lookups; updated function signatures.
CLI help text and docs
cmd/up.go, docs/pages/developing-providers/options.mdx, docs/pages/managing-providers/add-provider.mdx
Punctuation/wording tweaks: change ". E.g." to ", e.g." and small grammar adjustments in help/docs.
IDE option descriptions
pkg/ide/jupyter/jupyter.go, pkg/ide/openvscode/openvscode.go, pkg/ide/rstudio/rstudio.go
Standardized BindAddressOption descriptions to use comma + "e.g." formatting; no behavioral changes.
Validation/error message wording
pkg/provider/parse.go, pkg/workspace/workspace.go, cmd/context/create.go
Minor wording/punctuation fixes (e.g., "smaller case" → "lower case", ". E.g." → ", e.g.").
Kubernetes provider metadata
providers/kubernetes/provider.yaml
Adjusted multiple option description strings to comma + "e.g." phrasing; no functional changes.

Sequence Diagram(s)

sequenceDiagram
    participant User as User
    participant CLI as devpod CLI (cmd/provider/add)
    participant Env as OS Env
    participant Store as ProviderStore
    participant Service as ProviderService

    User->>CLI: run "devpod provider add [name?] [source?]"
    CLI->>CLI: validate providerName if provided (regex + length)
    CLI->>Env: read DEVPOD_PROVIDER_SOURCE
    CLI->>Env: if name provided read DEVPOD_PROVIDER_<NAME>_SOURCE
    CLI->>CLI: resolve providerSource (arg or env)
    alt FromExisting set
        CLI->>Store: check referenced provider exists
        Store-->>CLI: exists / not found
        alt exists
            CLI->>Service: CloneProvider(existingRef, providerName)
            Service-->>Store: create cloned provider
            Service-->>CLI: success
        else not found
            CLI-->>User: error "provider not found"
        end
    else adding new provider
        alt providerSource present
            CLI->>Service: AddProvider(providerName, providerSource)
            Service-->>Store: create provider
            Service-->>CLI: success
        else missing source
            CLI-->>User: error "must provide provider source"
        end
    end
    CLI-->>User: final status
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • skevetter
🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 36.36% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'provider name enhancements' partially relates to the changeset. While some changes involve provider naming features, the PR includes broader changes like typo fixes, command flag scoping by subcommand, and various documentation updates that extend beyond just provider name enhancements.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
📝 Coding Plan
  • Generate coding plan for human review comments

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.

Copy link

@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: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@cmd/provider/add.go`:
- Around line 76-79: The error message returned when
provider.ProviderNameRegEx.MatchString(providerName) fails contains a typo
"smaller case"; update the fmt.Errorf(...) string in that return statement to
read "lowercase" instead of "smaller case" so the message becomes: "provider
name can only include lowercase letters, numbers or dashes".
- Around line 94-96: The constructed environment variable name in the else
branch builds sourceEnvVar without an underscore before "SOURCE"; update the
expression that sets sourceEnvVar (currently using
"DEVPOD_PROVIDER_"+strings.ToUpper(providerName)+"SOURCE") to include the
missing underscore so the result is
"DEVPOD_PROVIDER_"+strings.ToUpper(providerName)+"_SOURCE", ensuring the
environment variable matches the documented DEVPOD_PROVIDER_<provider
name>_SOURCE format.

In `@cmd/provider/update.go`:
- Around line 51-52: The error message returned from the validation in
cmd/provider/update.go currently always states a source is required even though
the one-argument form (update <name>) is valid; update the fmt.Errorf call (the
return that builds the message) to mention the valid single-argument form or
clarify that either "update <name>" is allowed or "update <name> <source>" with
examples (reference the fmt.Errorf invocation in this file to locate and replace
the string).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0236da0f-fc7a-4543-be3d-360ca09d1211

📥 Commits

Reviewing files that changed from the base of the PR and between 766e86f and 25803bf.

📒 Files selected for processing (15)
  • cmd/provider/add.go
  • cmd/provider/delete.go
  • cmd/provider/update.go
  • cmd/up.go
  • docs/pages/developing-providers/options.mdx
  • docs/pages/managing-providers/add-provider.mdx
  • pkg/driver/custom/custom.go
  • pkg/ide/jupyter/jupyter.go
  • pkg/ide/openvscode/openvscode.go
  • pkg/ide/rstudio/rstudio.go
  • pkg/provider/download.go
  • pkg/provider/env.go
  • pkg/provider/parse.go
  • pkg/workspace/workspace.go
  • providers/kubernetes/provider.yaml
💤 Files with no reviewable changes (1)
  • cmd/provider/delete.go

Comment on lines +51 to +52
return fmt.Errorf("please specify either a local file, URL or Git repository, " +
"e.g. devpod provider update my-provider skevetter/devpod-provider-gcloud")
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Error message should include the valid one-argument form.

Current text implies a source is always required, but len(args)==1 is valid (update <name>). This can confuse users on bad invocations.

💡 Proposed wording fix
-		return fmt.Errorf("please specify either a local file, URL or Git repository, " +
-			"e.g. devpod provider update my-provider skevetter/devpod-provider-gcloud")
+		return fmt.Errorf("please specify a provider name and optionally a local file, URL, or Git repository, " +
+			"e.g. devpod provider update my-provider skevetter/devpod-provider-gcloud")
📝 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.

Suggested change
return fmt.Errorf("please specify either a local file, URL or Git repository, " +
"e.g. devpod provider update my-provider skevetter/devpod-provider-gcloud")
return fmt.Errorf("please specify a provider name and optionally a local file, URL, or Git repository, " +
"e.g. devpod provider update my-provider skevetter/devpod-provider-gcloud")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cmd/provider/update.go` around lines 51 - 52, The error message returned from
the validation in cmd/provider/update.go currently always states a source is
required even though the one-argument form (update <name>) is valid; update the
fmt.Errorf call (the return that builds the message) to mention the valid
single-argument form or clarify that either "update <name>" is allowed or
"update <name> <source>" with examples (reference the fmt.Errorf invocation in
this file to locate and replace the string).

@dubinsky dubinsky force-pushed the provider-name branch 3 times, most recently from 0c2bf10 to 6d9999c Compare March 16, 2026 18:13
@dubinsky dubinsky requested a review from skevetter March 16, 2026 18:43
Copy link

@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.

🧹 Nitpick comments (1)
pkg/ide/jupyter/jupyter.go (1)

44-45: Fix the "Notebook" typo in the struct name.

The JupyterNotbookServer type (and constructor) misspells "Notebook" as "Notbook" in lines 44, 45, 53, 60, 69, and 109. Since this PR addresses typos, rename it to JupyterNotebookServer. All references are localized to this file.

✏️ Proposed fix
 func NewJupyterNotebookServer(
 	workspaceFolder string,
 	userName string,
 	values map[string]config.OptionValue,
 	log log.Logger,
-) *JupyterNotbookServer {
-	return &JupyterNotbookServer{
+) *JupyterNotebookServer {
+	return &JupyterNotebookServer{
 		values:          values,
 		workspaceFolder: workspaceFolder,
 		userName:        userName,
 		log:             log,
 	}
 }

-type JupyterNotbookServer struct {
+type JupyterNotebookServer struct {
 	values          map[string]config.OptionValue
 	workspaceFolder string
 	userName        string
 	log             log.Logger
 }

-func (o *JupyterNotbookServer) Install() error {
+func (o *JupyterNotebookServer) Install() error {

-func (o *JupyterNotbookServer) installNotebook() error {
+func (o *JupyterNotebookServer) installNotebook() error {

-func (o *JupyterNotbookServer) Start() error {
+func (o *JupyterNotebookServer) Start() error {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/ide/jupyter/jupyter.go` around lines 44 - 45, Rename the misspelled type
and its constructor from JupyterNotbookServer to JupyterNotebookServer and
update all local references in this file accordingly: change the type
declaration, the constructor return type (where the function currently returns
*JupyterNotbookServer), the constructor name if it matches the type, and any
method receivers or variables named JupyterNotbookServer (references at the
locations around lines 44, 53, 60, 69, 109). Ensure receiver declarations (e.g.,
func (s *JupyterNotbookServer) ...) and any instantiations or type assertions
are updated to the new JupyterNotebookServer identifier so the file compiles.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@pkg/ide/jupyter/jupyter.go`:
- Around line 44-45: Rename the misspelled type and its constructor from
JupyterNotbookServer to JupyterNotebookServer and update all local references in
this file accordingly: change the type declaration, the constructor return type
(where the function currently returns *JupyterNotbookServer), the constructor
name if it matches the type, and any method receivers or variables named
JupyterNotbookServer (references at the locations around lines 44, 53, 60, 69,
109). Ensure receiver declarations (e.g., func (s *JupyterNotbookServer) ...)
and any instantiations or type assertions are updated to the new
JupyterNotebookServer identifier so the file compiles.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: fac076a7-70be-446f-8d92-a251873b3da1

📥 Commits

Reviewing files that changed from the base of the PR and between 25803bf and cd5cd2d.

📒 Files selected for processing (16)
  • cmd/context/create.go
  • cmd/provider/add.go
  • cmd/provider/delete.go
  • cmd/provider/update.go
  • cmd/up.go
  • docs/pages/developing-providers/options.mdx
  • docs/pages/managing-providers/add-provider.mdx
  • pkg/driver/custom/custom.go
  • pkg/ide/jupyter/jupyter.go
  • pkg/ide/openvscode/openvscode.go
  • pkg/ide/rstudio/rstudio.go
  • pkg/provider/download.go
  • pkg/provider/env.go
  • pkg/provider/parse.go
  • pkg/workspace/workspace.go
  • providers/kubernetes/provider.yaml
💤 Files with no reviewable changes (1)
  • cmd/provider/delete.go
🚧 Files skipped from review as they are similar to previous changes (7)
  • providers/kubernetes/provider.yaml
  • cmd/provider/update.go
  • pkg/ide/openvscode/openvscode.go
  • cmd/up.go
  • pkg/ide/rstudio/rstudio.go
  • docs/pages/developing-providers/options.mdx
  • pkg/workspace/workspace.go

Copy link

@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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
cmd/root.go (1)

171-183: ⚠️ Potential issue | 🟠 Major

Breaking change: subcommand flags now require prefixed environment variables.

Previously, a flag like --ide on the up subcommand could be set via DEVPOD_IDE. After this change, it requires DEVPOD_UP_IDE. This affects all subcommand-specific flags across multiple commands including up, status, build, and ssh.

Any user scripts or automation relying on the old DEVPOD_* environment variable names for subcommand flags will break after this update. Ensure this breaking change is documented in release notes or a migration guide.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cmd/root.go` around lines 171 - 183, The change to require
DEVPOD_<SUBCOMMAND>_<FLAG> breaks existing DEVPOD_<FLAG> env vars; update
inheritFlagsFromEnvironment to preserve backward compatibility by checking for
the legacy environment variable name (constructed as suffix, e.g., "DEVPOD_IDE")
if the prefixed name ("DEVPOD_"+commandPrefix+suffix) is not set — lookup both
names and prefer the more specific prefixed var but fall back to the legacy var;
modify the logic where environmentVariable is determined in
inheritFlagsFromEnvironment and use both names when calling os.Getenv or
equivalent so subcommand flags continue to respect existing DEVPOD_* environment
variables while still supporting DEVPOD_<SUBCOMMAND>_*.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@cmd/root.go`:
- Around line 160-166: The code assumes sub.Use is non-empty and calls
strings.Fields(sub.Use)[0], which can panic; replace that with a defensive
check: split sub.Use via strings.Fields into a slice (e.g., fields :=
strings.Fields(sub.Use)) and if len(fields) > 0 use strings.ToUpper(fields[0]) +
"_" for subCommandPrefix, otherwise fall back to a safe alternative such as
strings.ToUpper(sub.Name()) + "_" (or just use commandPrefix if provided), then
call inheritCommandFlagsFromEnvironment(sub, subCommandPrefix); update the block
that computes subCommandPrefix (references: sub.Use, subCommandPrefix,
inheritCommandFlagsFromEnvironment, sub.Name()) accordingly.

---

Outside diff comments:
In `@cmd/root.go`:
- Around line 171-183: The change to require DEVPOD_<SUBCOMMAND>_<FLAG> breaks
existing DEVPOD_<FLAG> env vars; update inheritFlagsFromEnvironment to preserve
backward compatibility by checking for the legacy environment variable name
(constructed as suffix, e.g., "DEVPOD_IDE") if the prefixed name
("DEVPOD_"+commandPrefix+suffix) is not set — lookup both names and prefer the
more specific prefixed var but fall back to the legacy var; modify the logic
where environmentVariable is determined in inheritFlagsFromEnvironment and use
both names when calling os.Getenv or equivalent so subcommand flags continue to
respect existing DEVPOD_* environment variables while still supporting
DEVPOD_<SUBCOMMAND>_*.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: cbff8bdf-4435-42f8-ad96-47aef84f627e

📥 Commits

Reviewing files that changed from the base of the PR and between cd5cd2d and d954028.

📒 Files selected for processing (1)
  • cmd/root.go

Comment on lines +160 to +166
var subCommandPrefix string
if commandPrefix == "" {
subCommandPrefix = strings.ToUpper(strings.Fields(sub.Use)[0]) + "_"
} else {
subCommandPrefix = commandPrefix
}
inheritCommandFlagsFromEnvironment(sub, subCommandPrefix)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Potential panic if sub.Use is empty.

strings.Fields(sub.Use)[0] will cause an index out of bounds panic if any subcommand has an empty or whitespace-only Use field. While current subcommands appear to have valid values, this is fragile for future additions.

🛡️ Proposed defensive check
 	for _, sub := range cmd.Commands() {
 		var subCommandPrefix string
 		if commandPrefix == "" {
-			subCommandPrefix = strings.ToUpper(strings.Fields(sub.Use)[0]) + "_"
+			fields := strings.Fields(sub.Use)
+			if len(fields) == 0 {
+				continue // skip commands with empty Use field
+			}
+			subCommandPrefix = strings.ToUpper(fields[0]) + "_"
 		} else {
 			subCommandPrefix = commandPrefix
 		}
 		inheritCommandFlagsFromEnvironment(sub, subCommandPrefix)
 	}
📝 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.

Suggested change
var subCommandPrefix string
if commandPrefix == "" {
subCommandPrefix = strings.ToUpper(strings.Fields(sub.Use)[0]) + "_"
} else {
subCommandPrefix = commandPrefix
}
inheritCommandFlagsFromEnvironment(sub, subCommandPrefix)
var subCommandPrefix string
if commandPrefix == "" {
fields := strings.Fields(sub.Use)
if len(fields) == 0 {
continue // skip commands with empty Use field
}
subCommandPrefix = strings.ToUpper(fields[0]) + "_"
} else {
subCommandPrefix = commandPrefix
}
inheritCommandFlagsFromEnvironment(sub, subCommandPrefix)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cmd/root.go` around lines 160 - 166, The code assumes sub.Use is non-empty
and calls strings.Fields(sub.Use)[0], which can panic; replace that with a
defensive check: split sub.Use via strings.Fields into a slice (e.g., fields :=
strings.Fields(sub.Use)) and if len(fields) > 0 use strings.ToUpper(fields[0]) +
"_" for subCommandPrefix, otherwise fall back to a safe alternative such as
strings.ToUpper(sub.Name()) + "_" (or just use commandPrefix if provided), then
call inheritCommandFlagsFromEnvironment(sub, subCommandPrefix); update the block
that computes subCommandPrefix (references: sub.Use, subCommandPrefix,
inheritCommandFlagsFromEnvironment, sub.Name()) accordingly.

Copy link

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@cmd/provider/add.go`:
- Around line 103-106: The code currently only errors if devPodConfig.Current()
!= nil && devPodConfig.Current().Providers[cmd.FromExisting] == nil, which lets
execution continue when devPodConfig.Current() is nil; update the logic to
explicitly check for a nil current context (devPodConfig.Current() == nil) and
return a clear error (e.g., "no current devpod context") before attempting to
access Providers or calling CloneProvider, and keep the existing check that
returns "provider %s does not exist" when Current() is non-nil but
Providers[cmd.FromExisting] is nil; ensure these checks occur prior to invoking
CloneProvider or any access to Current().Providers.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 06b22b7a-c2e5-42e1-a349-56b802031854

📥 Commits

Reviewing files that changed from the base of the PR and between d954028 and 36dd5d5.

📒 Files selected for processing (17)
  • cmd/context/create.go
  • cmd/provider/add.go
  • cmd/provider/delete.go
  • cmd/provider/update.go
  • cmd/root.go
  • cmd/up.go
  • docs/pages/developing-providers/options.mdx
  • docs/pages/managing-providers/add-provider.mdx
  • pkg/driver/custom/custom.go
  • pkg/ide/jupyter/jupyter.go
  • pkg/ide/openvscode/openvscode.go
  • pkg/ide/rstudio/rstudio.go
  • pkg/provider/download.go
  • pkg/provider/env.go
  • pkg/provider/parse.go
  • pkg/workspace/workspace.go
  • providers/kubernetes/provider.yaml
💤 Files with no reviewable changes (1)
  • cmd/provider/delete.go
🚧 Files skipped from review as they are similar to previous changes (9)
  • pkg/provider/env.go
  • pkg/driver/custom/custom.go
  • cmd/up.go
  • docs/pages/developing-providers/options.mdx
  • pkg/workspace/workspace.go
  • providers/kubernetes/provider.yaml
  • cmd/provider/update.go
  • pkg/ide/rstudio/rstudio.go
  • cmd/context/create.go

Comment on lines +103 to +106
if devPodConfig.Current() != nil &&
devPodConfig.Current().Providers[cmd.FromExisting] == nil {
return fmt.Errorf("provider %s does not exist", cmd.FromExisting)
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Logic issue: missing error when devPodConfig.Current() is nil.

The condition devPodConfig.Current() != nil && ...Providers[cmd.FromExisting] == nil short-circuits when Current() is nil, allowing the code to proceed to CloneProvider. This will likely fail later with a less informative error.

The check should also error when there is no current context configuration.

🐛 Proposed fix
 	if cmd.FromExisting != "" {
-		if devPodConfig.Current() != nil &&
-			devPodConfig.Current().Providers[cmd.FromExisting] == nil {
+		if devPodConfig.Current() == nil ||
+			devPodConfig.Current().Providers[cmd.FromExisting] == nil {
 			return fmt.Errorf("provider %s does not exist", cmd.FromExisting)
 		}
📝 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.

Suggested change
if devPodConfig.Current() != nil &&
devPodConfig.Current().Providers[cmd.FromExisting] == nil {
return fmt.Errorf("provider %s does not exist", cmd.FromExisting)
}
if cmd.FromExisting != "" {
if devPodConfig.Current() == nil ||
devPodConfig.Current().Providers[cmd.FromExisting] == nil {
return fmt.Errorf("provider %s does not exist", cmd.FromExisting)
}
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cmd/provider/add.go` around lines 103 - 106, The code currently only errors
if devPodConfig.Current() != nil &&
devPodConfig.Current().Providers[cmd.FromExisting] == nil, which lets execution
continue when devPodConfig.Current() is nil; update the logic to explicitly
check for a nil current context (devPodConfig.Current() == nil) and return a
clear error (e.g., "no current devpod context") before attempting to access
Providers or calling CloneProvider, and keep the existing check that returns
"provider %s does not exist" when Current() is non-nil but
Providers[cmd.FromExisting] is nil; ensure these checks occur prior to invoking
CloneProvider or any access to Current().Providers.

Copy link

@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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
cmd/provider/add.go (1)

37-47: ⚠️ Potential issue | 🟡 Minor

Reject extra positional args explicitly.

At line 87, only the single-arg case is handled; extra arguments are silently ignored. Add an argument validator to the Cobra command to enforce this explicitly, consistent with other commands in the codebase.

Proposed fix
 	addCmd := &cobra.Command{
 		Use:   "add [name, GitHub link, URL or path]",
 		Short: "Adds a new provider to DevPod",
+		Args:  cobra.MaximumNArgs(1),
 		PreRunE: func(cobraCommand *cobra.Command, args []string) error {
 			if cmd.FromExisting != "" {
 				return cobraCommand.MarkFlagRequired("name")
 			}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cmd/provider/add.go` around lines 37 - 47, The command currently handles only
a single positional argument in RunE but silently ignores extras; update the
Cobra command definition in cmd/provider/add.go (the command struct with
Use/Short/PreRunE/RunE) to validate argument count explicitly by adding an Args
validator (e.g., cobra.MaximumNArgs(1) or a custom Args function) so any extra
positional args are rejected; ensure this validation is applied alongside the
existing PreRunE that checks cmd.FromExisting so the command fails fast when
more than one positional argument is provided.
♻️ Duplicate comments (1)
cmd/provider/add.go (1)

103-106: ⚠️ Potential issue | 🟠 Major

Handle nil current context before checking provider existence.

At Line 103, devPodConfig.Current() == nil skips this guard and falls through to clone logic. This should fail fast with a clear error before attempting clone operations.

🐛 Proposed fix
 	if cmd.FromExisting != "" {
-		if devPodConfig.Current() != nil &&
-			devPodConfig.Current().Providers[cmd.FromExisting] == nil {
+		current := devPodConfig.Current()
+		if current == nil {
+			return fmt.Errorf("no current devpod context")
+		}
+		if current.Providers[cmd.FromExisting] == nil {
 			return fmt.Errorf("provider %s does not exist", cmd.FromExisting)
 		}
 		providerWithOptions, err := workspace.CloneProvider(
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cmd/provider/add.go` around lines 103 - 106, The current guard only checks
provider existence when devPodConfig.Current() != nil, which lets execution
continue when Current() is nil; add an explicit fast-fail check for a nil
current context before any clone/provider lookups (e.g., if
devPodConfig.Current() == nil return fmt.Errorf("no current context set") ) so
that the code referencing devPodConfig.Current().Providers and cmd.FromExisting
never runs against a nil context; update the logic around the
devPodConfig.Current(), Providers and cmd.FromExisting checks to first validate
the current context is non-nil and then validate the requested provider exists.
🧹 Nitpick comments (1)
cmd/provider/add.go (1)

92-97: Make named source env vars shell-friendly for dashed provider names.

Provider names allow dashes, but Line 95 builds DEVPOD_PROVIDER_<NAME>_SOURCE directly from name. For names like my-provider, this yields env keys that are awkward/impossible to set via common export syntax. Consider normalizing - to _ (and optionally falling back to the raw form for compatibility).

♻️ Suggested refactor
 	if providerSource == "" {
 		var sourceEnvVar string
 		if providerName == "" {
 			sourceEnvVar = "DEVPOD_PROVIDER_SOURCE"
 		} else {
-			sourceEnvVar = "DEVPOD_PROVIDER_" + strings.ToUpper(providerName) + "_SOURCE"
+			normalized := strings.ToUpper(strings.ReplaceAll(providerName, "-", "_"))
+			sourceEnvVar = "DEVPOD_PROVIDER_" + normalized + "_SOURCE"
 		}
 		providerSource = os.Getenv(sourceEnvVar)
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cmd/provider/add.go` around lines 92 - 97, The env var key built for provider
source uses the raw providerName (DEVPOD_PROVIDER_<NAME>_SOURCE), which breaks
common shell export syntax for dashed names; change the construction so you
first normalize providerName by replacing '-' with '_' (e.g., normalized :=
strings.ReplaceAll(providerName, "-", "_")), then build sourceEnvVar using
strings.ToUpper(normalized) and read os.Getenv(sourceEnvVar); if that lookup is
empty, fall back to the original raw-uppercased form (DEVPOD_PROVIDER_ +
strings.ToUpper(providerName) + _SOURCE) for compatibility. Update the code
around the variables providerName, sourceEnvVar and providerSource to perform
the normalize-then-fallback lookup while preserving the existing special-case
when providerName == "".
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@providers/kubernetes/provider.yaml`:
- Around line 68-70: Fix the subject-verb agreement in the PVC_ACCESS_MODE
description string: change "the storage class support the given access mode" to
"the storage class supports the given access mode" so the singular subject
"storage class" matches the verb; locate the PVC_ACCESS_MODE description in
provider.yaml and update the text accordingly.

---

Outside diff comments:
In `@cmd/provider/add.go`:
- Around line 37-47: The command currently handles only a single positional
argument in RunE but silently ignores extras; update the Cobra command
definition in cmd/provider/add.go (the command struct with
Use/Short/PreRunE/RunE) to validate argument count explicitly by adding an Args
validator (e.g., cobra.MaximumNArgs(1) or a custom Args function) so any extra
positional args are rejected; ensure this validation is applied alongside the
existing PreRunE that checks cmd.FromExisting so the command fails fast when
more than one positional argument is provided.

---

Duplicate comments:
In `@cmd/provider/add.go`:
- Around line 103-106: The current guard only checks provider existence when
devPodConfig.Current() != nil, which lets execution continue when Current() is
nil; add an explicit fast-fail check for a nil current context before any
clone/provider lookups (e.g., if devPodConfig.Current() == nil return
fmt.Errorf("no current context set") ) so that the code referencing
devPodConfig.Current().Providers and cmd.FromExisting never runs against a nil
context; update the logic around the devPodConfig.Current(), Providers and
cmd.FromExisting checks to first validate the current context is non-nil and
then validate the requested provider exists.

---

Nitpick comments:
In `@cmd/provider/add.go`:
- Around line 92-97: The env var key built for provider source uses the raw
providerName (DEVPOD_PROVIDER_<NAME>_SOURCE), which breaks common shell export
syntax for dashed names; change the construction so you first normalize
providerName by replacing '-' with '_' (e.g., normalized :=
strings.ReplaceAll(providerName, "-", "_")), then build sourceEnvVar using
strings.ToUpper(normalized) and read os.Getenv(sourceEnvVar); if that lookup is
empty, fall back to the original raw-uppercased form (DEVPOD_PROVIDER_ +
strings.ToUpper(providerName) + _SOURCE) for compatibility. Update the code
around the variables providerName, sourceEnvVar and providerSource to perform
the normalize-then-fallback lookup while preserving the existing special-case
when providerName == "".

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: de115631-5f85-4084-8ea3-249c0d8a9cbc

📥 Commits

Reviewing files that changed from the base of the PR and between 36dd5d5 and 6dc58a7.

📒 Files selected for processing (17)
  • cmd/context/create.go
  • cmd/provider/add.go
  • cmd/provider/delete.go
  • cmd/provider/update.go
  • cmd/root.go
  • cmd/up.go
  • docs/pages/developing-providers/options.mdx
  • docs/pages/managing-providers/add-provider.mdx
  • pkg/driver/custom/custom.go
  • pkg/ide/jupyter/jupyter.go
  • pkg/ide/openvscode/openvscode.go
  • pkg/ide/rstudio/rstudio.go
  • pkg/provider/download.go
  • pkg/provider/env.go
  • pkg/provider/parse.go
  • pkg/workspace/workspace.go
  • providers/kubernetes/provider.yaml
💤 Files with no reviewable changes (1)
  • cmd/provider/delete.go
🚧 Files skipped from review as they are similar to previous changes (12)
  • cmd/up.go
  • cmd/provider/update.go
  • docs/pages/managing-providers/add-provider.mdx
  • pkg/provider/parse.go
  • pkg/ide/rstudio/rstudio.go
  • cmd/context/create.go
  • pkg/workspace/workspace.go
  • pkg/driver/custom/custom.go
  • cmd/root.go
  • docs/pages/developing-providers/options.mdx
  • pkg/provider/env.go
  • pkg/ide/jupyter/jupyter.go

Comment on lines 68 to 70
PVC_ACCESS_MODE:
description: If defined, DevPod will use the given access mode to create the persistent volume claim. You will need to ensure the storage class support the given access mode!. E.g. RWO or ROX or RWX or RWOP
description: If defined, DevPod will use the given access mode to create the persistent volume claim. You will need to ensure the storage class support the given access mode, e.g. RWO or ROX or RWX or RWOP
global: true
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix subject-verb agreement: "support" → "supports".

The sentence has a grammatical error: "the storage class support" should be "the storage class supports" (singular subject requires singular verb).

📝 Proposed fix
   PVC_ACCESS_MODE:
-    description: If defined, DevPod will use the given access mode to create the persistent volume claim. You will need to ensure the storage class support the given access mode, e.g. RWO or ROX or RWX or RWOP
+    description: If defined, DevPod will use the given access mode to create the persistent volume claim. You will need to ensure the storage class supports the given access mode, e.g. RWO or ROX or RWX or RWOP
     global: true
📝 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.

Suggested change
PVC_ACCESS_MODE:
description: If defined, DevPod will use the given access mode to create the persistent volume claim. You will need to ensure the storage class support the given access mode!. E.g. RWO or ROX or RWX or RWOP
description: If defined, DevPod will use the given access mode to create the persistent volume claim. You will need to ensure the storage class support the given access mode, e.g. RWO or ROX or RWX or RWOP
global: true
PVC_ACCESS_MODE:
description: If defined, DevPod will use the given access mode to create the persistent volume claim. You will need to ensure the storage class supports the given access mode, e.g. RWO or ROX or RWX or RWOP
global: true
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@providers/kubernetes/provider.yaml` around lines 68 - 70, Fix the
subject-verb agreement in the PVC_ACCESS_MODE description string: change "the
storage class support the given access mode" to "the storage class supports the
given access mode" so the singular subject "storage class" matches the verb;
locate the PVC_ACCESS_MODE description in provider.yaml and update the text
accordingly.

- chore: typos and minor cleanup
- feat: convey to the provider the name it is running under
- feat: use `DEVPOD_PROVIDER_<provider name>_SOURCE` environment variable
- feat: scope command flags environment variables by the first-level subcommand name
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant