Skip to content

fix(helm): support OCI chart installs - #1815

Merged
nadaverell merged 3 commits into
skyhook-io:mainfrom
StefanSa:work/pr1646-oci-install
Sep 22, 2026
Merged

nadaverell merged 3 commits into
skyhook-io:mainfrom
StefanSa:work/pr1646-oci-install

Conversation

@StefanSa

@StefanSa StefanSa commented Sep 18, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • support chart detail and install flows for direct OCI references
  • support OCI chart URLs returned by classic repository indexes
  • use Radar’s existing Helm registry client and pin the requested chart version
  • preserve the existing non-OCI HTTP download path

This extracts the self-contained OCI install gap identified by hisco during review of #1646.

Tests

  • focused OCI install and existing OCI helper tests (21 passed)
  • go vet ./internal/helm
  • gofmt and git diff checks

Note

Medium Risk
Changes cluster install and chart-fetch paths and OCI registry auth/timeout behavior; mistakes could break installs or pull wrong chart versions, though HTTP-only flows are preserved and tests are extensive.

Overview
Adds OCI Helm chart support for chart detail, install (with progress), and index entries that point at oci:// URLs.

Centralizes resolution in resolveOCIChartURL (prefix vs full tag/digest refs) and locateChartPath, which wires Helm’s registry client from existing helm registry login credentials and maps OCI latest to an empty version for tag resolution. Chart pulls use newRegistryClientForChartPull (no probe timeout); synchronous registry probes keep the short timeout.

GetChartDetail and install paths branch on OCI repositories; non-OCI installs still use the direct HTTP download path to avoid stale local index cache failures. A chartPathLocator hook supports tests; new oci_install_test.go covers URL resolution, install/detail/progress flows, pre-install rejection, and live registry tag selection.

Reviewed by Cursor Bugbot for commit a37624a. Bugbot is set up for automated code reviews on this repo. Configure here.

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Support OCI chart details and installs

🐞 Bug fix 🧊 Tests 🕐 20-40 Minutes

Grey Divider

AI Description

â€Ē Supports chart details and installs from direct OCI references and OCI-backed repository indexes.
â€Ē Reuses Helm registry credentials while pinning the resolved chart version.
â€Ē Preserves direct HTTP downloads for non-OCI charts.
Diagram

graph TD
  A["Chart request"] --> B{"OCI source?"}
  B -->|Yes| C["Helm locator"] --> D["OCI registry"] --> E["Chart archive"] --> F["Chart loader"]
  B -->|No| G["HTTP download"] --> E
  F --> H["Detail or install"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Use Helm locator for every transport
  • ➕ Creates one chart acquisition pipeline.
  • ➕ Reduces explicit OCI versus HTTP branching.
  • ➖ Reintroduces failures from unrelated stale or missing repository index caches.
  • ➖ Changes a proven non-OCI download path beyond the OCI fix scope.
2. Temporarily register OCI sources
  • ➕ Could reuse existing OCI source discovery behavior.
  • ➕ Centralizes OCI references in the source inventory.
  • ➖ Introduces persistent or concurrent configuration side effects.
  • ➖ Could mutate source inventory for rejected or failed installations.

Recommendation: Keep the PR's transport-specific approach. Using Helm's locator and existing registry credentials only for OCI enables authenticated pulls and version pinning, while retaining the direct HTTP path that avoids unrelated repository-cache failures and leaving OCI source inventory unchanged.

Files changed (2) +342 / -54

Bug fix (1) +149 / -54
client.goAdd OCI-aware chart resolution to detail and install flows +149/-54

Add OCI-aware chart resolution to detail and install flows

â€Ē Adds centralized OCI reference normalization and version-pinned chart location using Helm's registry client. Chart detail and both installation paths now accept direct OCI references and OCI URLs from repository indexes, while non-OCI progress installs retain direct HTTP downloads. Shared chart-detail extraction removes duplicated metadata processing.

internal/helm/client.go

Tests (1) +193 / -0
oci_install_test.goCover direct and indexed OCI chart workflows +193/-0

Cover direct and indexed OCI chart workflows

â€Ē Adds focused tests for OCI chart details, standard and progress installations, exact locator arguments, and wrapped registry errors. Tests also verify rejected installs do not perform chart lookup or mutate configured OCI sources.

internal/helm/oci_install_test.go

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

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want higher recall? High effort reviews run extra passes and find more bugs. A team admin can switch effort levels in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 3309c48. Configure here.

Comment thread internal/helm/client.go
@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Sep 18, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (1) 📎 Requirement gaps (0) ðŸŽĻ UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Slow registry downloads fail ✓ Resolved 🐞 Bug ☞ Reliability
Description
locateChartPath uses newRegistryClientConcrete, whose HTTP client has the five-second
ociProbeTimeout intended for registry tag discovery. OCI installs and chart-detail loads now use
that client for archive pulls, so a request taking more than five seconds through a slow registry or
network fails before the chart can load.
Code

internal/helm/client.go[2942]

+		registryClient, err := c.newRegistryClientConcrete()
Evidence
The new locator constructs the registry client at the changed call site and installs it on Helm's
chart locator. That constructor configures an http.Client with ociProbeTimeout, while the
constant and comments explicitly describe five seconds as a bound for synchronous tag lookup rather
than chart downloads; all newly supported OCI detail and install flows pass through this locator.

internal/helm/client.go[2925-2948]
internal/helm/client.go[3410-3421]
internal/helm/client.go[3708-3713]
internal/helm/client.go[3897-3907]
internal/helm/oci_sources.go[16-22]
internal/helm/oci_sources.go[153-168]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
OCI chart pulls use the registry discovery client's five-second HTTP timeout, causing valid downloads to fail on slower networks or registries.
## Fix Focus Areas
- internal/helm/client.go[2941-2948]
- internal/helm/oci_sources.go[153-168]
## Recommended Fix
Create separate registry-client construction paths for discovery and chart pulls. Retain the five-second timeout for tag discovery, but give chart pulls an appropriately longer or configurable timeout and add a test proving the pull path does not inherit `ociProbeTimeout`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. HTTP fallback comment records history 📘 Rule violation ⚙ Maintainability
Description
The comment above httpClient.Get says to preserve the existing direct HTTP path, framing the
implementation in terms of its state before this change. It appears whenever maintainers inspect the
non-OCI download branch and can be rewritten as a timeless explanation of why Helm's downloader is
unsuitable.
Code

internal/helm/client.go[R3909-3911]

+		// Preserve the existing direct HTTP path. Helm's ChartDownloader loads all
+		// locally registered indexes and can fail because an unrelated cache entry
+		// is stale or missing.
Evidence
Rule 3036538 prohibits change-history references in added code comments. The added comment
characterizes the branch as preserving the existing path instead of stating only its lasting
technical rationale.

Rule 3036538: Disallow references to tickets or PR history in code comments
internal/helm/client.go[3909-3911]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The comment describes the direct HTTP path as `existing`, recording change history rather than only the enduring reason for the implementation.
## Fix Focus Areas
- internal/helm/client.go[3909-3911]
## Recommended Fix
Rephrase the comment without historical wording, for example: `Use direct HTTP because Helm's ChartDownloader loads all locally registered indexes and can fail when an unrelated cache entry is stale or missing.`

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Tagged chart references become invalid ✓ Resolved 🐞 Bug ≡ Correctness
Description
resolveOCIChartURL recognizes a complete chart reference only when the raw source ends with /,
without accounting for a tag or digest suffix. A source such as oci://registry/acme/widget:1.2.3
or oci://registry/acme/widget@sha256:â€Ķ therefore becomes â€Ķ/widget:1.2.3/widget or
â€Ķ/widget@sha256:â€Ķ/widget in both detail and install flows.
Code

internal/helm/client.go[R2919-2922]

+	if strings.HasSuffix(source, "/"+chartName) {
+		return source, nil
+	}
+	return source + "/" + chartName, nil
Evidence
The resolver's suffix check and append operation directly produce the malformed paths for tagged and
digested sources. Both direct detail and both installation implementations invoke this resolver for
every caller-provided OCI repository, while InstallRequest exposes the repository and chart name
as separate unrestricted fields.

internal/helm/client.go[2906-2923]
internal/helm/client.go[3410-3418]
internal/helm/client.go[3571-3581]
internal/helm/client.go[3758-3768]
internal/helm/types.go[371-379]
internal/helm/handlers.go[1087-1120]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Complete OCI chart references carrying a tag or digest are mistaken for repository prefixes, so the chart name is appended a second time.
## Fix Focus Areas
- internal/helm/client.go[2906-2923]
- internal/helm/oci_install_test.go[56-74]
- internal/helm/oci_install_test.go[114-158]
## Recommended Fix
Parse the final OCI path component structurally and compare the chart name after separating any tag or digest. Preserve already-complete references, define how an embedded tag interacts with the separate version argument, and add detail and install tests for tagged and digested inputs.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
ðŸ’Ą Did you know, you can route each action level your way: inline, summary, both, or drop

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread internal/helm/client.go
Comment on lines +3909 to +3911
// Preserve the existing direct HTTP path. Helm's ChartDownloader loads all
// locally registered indexes and can fail because an unrelated cache entry
// is stale or missing.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

2. Http fallback comment records history 📘 Rule violation ⚙ Maintainability

The comment above httpClient.Get says to preserve the existing direct HTTP path, framing the
implementation in terms of its state before this change. It appears whenever maintainers inspect the
non-OCI download branch and can be rewritten as a timeless explanation of why Helm's downloader is
unsuitable.
Agent Prompt
## Issue description
The comment describes the direct HTTP path as `existing`, recording change history rather than only the enduring reason for the implementation.

## Fix Focus Areas
- internal/helm/client.go[3909-3911]

## Recommended Fix
Rephrase the comment without historical wording, for example: `Use direct HTTP because Helm's ChartDownloader loads all locally registered indexes and can fail when an unrelated cache entry is stale or missing.`

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread internal/helm/client.go Outdated
Comment thread internal/helm/client.go Outdated
Comment thread internal/helm/client.go
// Preserve the existing direct HTTP path. Helm's ChartDownloader loads all
// locally registered indexes and can fail because an unrelated cache entry
// is stale or missing.
chartResp, err := httpClient.Get(chartURL)

@nadaverell nadaverell left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM, tested live. made one tiny fix to handling "latest" + test for it.

Thanks for the PR!

@nadaverell
nadaverell merged commit 3867191 into skyhook-io:main Sep 22, 2026
9 checks passed
nadaverell added a commit that referenced this pull request Sep 27, 2026
Adds the v1.15.0 entry to the What's New catalog. This replaces #1877,
which was stacked on the closed #1876; the dialog landed on main in
#1902 instead. `scripts/check-whats-new.sh` (#1908) refuses to release
v1.15.0 without this entry, so this must merge before the tag.

## Highlights
A full-width lead card, then a 2x2 grid. Each secondary card has its own
icon color, so they read apart.

1. **AI investigations that show their work** (lead, no CTA; the
investigations workspace redirects home in run modes that can't host
local agents). This recaps the v1.14.1 rework (#1766, #1802) on purpose:
it's the first What's New dialog, and we want to put AI investigations
in front of people. OpenCode (#1265) is the new v1.15 part.
2. **Full manifest diffs for Argo CD resources** (#1622)
3. **Rightsizing and cost data in MCP**: new agent tools, and risks lead
before savings in the UI too (#1820, #1723)
4. **Deeper batch + AI/ML workloads support**: Kueue, JobSet and Ray
pages; Job and JobSet details show why a queued job has no Pods (#1874,
#1885, #1900, #1849, #1893, #1897)
5. **Canary and blue-green in Topology** (#1626)

## Also in this release
Eight one-liners, paired by length because the grid fills row by row:
table sort memory (#1428), OCI Helm installs (#1815), expiring TLS
certificates in Checks (#1829), Radar Desktop keeping preferences across
restarts (#1907), Pod vs template in Issues (#1848), PVC usage
availability (#1828), Strimzi and admission webhook failures in Issues
(#1840, #1830), `--listen-address` (#1845).

Left out: security fixes, dependency bumps, refactors and CI,
accessibility work (#1901, #1909), and narrow items (ALB action
annotations, INSTALL_DIR). No usage-stats line is needed, because
#1879's consent question already sits in this dialog.

## UI changes beyond the catalog
- The heading names the release line (`v1.15`, via `releaseLine`), since
patch releases show the same notes. The "You just updated from → to"
line keeps exact versions.
- An optional `tone` on highlights colors the icon tile (violet, teal,
emerald, indigo). It uses Radar's existing `bg-X-500/10 text-X-600
dark:text-X-400` pattern, and was checked in light and dark themes.

## Verification
- `scripts/check-whats-new.sh v1.15.0` → found notes
- `make tsc` clean; What's New and usage-data tests: 39 passed
- Previewed live with `VERSION=v1.15.0 make build`, opening
`/?whats-new`, with #1879's consent question in place

The matching public changelog is skyhook-dev/marketing#312.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Release-notes catalog and presentational What's New UI only; no auth,
API, or data-handling changes.
> 
> **Overview**
> Adds the **v1.15.0** What's New catalog entry (five highlights with
CTAs where appropriate, plus eight improvement one-liners) so
`check-whats-new` can ship the tag.
> 
> The dialog heading now shows the **minor release line** via new
`releaseLine()` (e.g. `v1.15` instead of `v1.15.0`), while the upgrade
subtitle still uses exact versions. Secondary highlight cards can set an
optional **`tone`** (violet, teal, emerald, indigo) for distinct icon
tiles; the lead card stays on the accent style.
> 
> Tests cover `releaseLine` and the preview dialog title expectation.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
f0038c3. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants