Skip to content

feat: implement helm pull command #101

Description

@bradctrlplus

Background

helm pull downloads a chart from a repository (HTTP or OCI) to the local filesystem, optionally untarring it. Common uses: offline installs, chart inspection, customization, CI caching. See helm pull docs.

Helm SDK action: action.NewPullWithOpts (upstream).

Acceptance criteria

  • Helm.pull("repo/chart").call() downloads to current directory and returns the resulting file Path
  • Builder methods: .withDestination(Path), .untar(), .withUntarDir(String), .withVersion(String)
  • Repo + auth: .withRepo(String), .withUsername(String), .withPassword(String), .passCredentials(), .withRepositoryConfig(Path), .withRepositoryCache(Path)
  • TLS: .withCertFile(Path), .withKeyFile(Path), .withCaFile(Path), .insecureSkipTlsVerify(), .plainHttp()
  • Verification: .verify(), .withKeyring(Path)
  • Versioning: .devel()
  • .debug()
  • Works with oci://... chart references
  • Integration tests use the built-in HTTP and OCI test servers (see Tests below)

Proposed Java API

PathchartFile = Helm.pull("bitnami/nginx")
.withVersion("15.0.0")
.withRepo("https://charts.bitnami.com/bitnami")
.withDestination(Paths.get("/tmp/charts"))
.untar()
.call();

Implementation guide

Follow AGENTS.md → "Adding a new Helm command".
Reference impl: ShowCommand + show.go — same shape (chart-keyed, repo + TLS options, uses the shared newRegistryClient helper for OCI).

Go (native/internal/helm/pull.go)

  • Build config with NewCfg(&CfgOptions{...})do not construct action.Configuration{} directly. Every other command in the codebase goes through NewCfg; staying consistent is required for kubeconfig / settings handling.
  • Build a registry.Client via the existing newRegistryClient(...) helper in registry.go:94.
  • client := action.NewPullWithOpts(action.WithConfig(cfg)), then set Settings, RepoURL, Version, Username, Password, CertFile, KeyFile, CaFile, InsecureSkipTLSverify, PlainHTTP, Verify, Keyring, Devel, DestDir, Untar, UntarDir, PassCredentialsAll.
  • client.Run(chart) returns (string, error) — the string is helm's CLI output (typically empty for pull). Compute the resulting file/directory path from DestDir + chart filename + version and return it as the first string returned by your helm.Pull(...) function so the Java side can parse it back to Path.

CGO bridge (native/main.go)

  • Add struct PullOptions { ... } alongside other option structs.
  • Add //export Pull wrapping helm.Pull(...) via runCommand(func() (string, error) { ... }). There is no result(...) helper — every other export uses runCommand.

JNA + Java

  • lib/api/.../PullOptions.java: mirror the C struct field order (@Structure.FieldOrder).
  • Add Result Pull(PullOptions options) to HelmLib.
  • helm-java/.../PullCommand.java extends HelmCommand<Path>. call() runs the command and returns Paths.get(result.out.trim()).
  • Add Helm.pull(String chart) static factory. Use HelmLibHolder.INSTANCE directly — it is the HelmLib instance, there is no .helmLib() method.

Tests

  • Location: helm-java/src/test/java/com/marcnuri/helm/HelmPullTest.java.
  • Start a local repo server using the low-level JNA call (the high-level builder isn't exposed) — see HelmTestServerTest for the pattern:
    finalResultr = Helm.HelmLibHolder.INSTANCE.RepoServerStart(newRepoServerOptions());
    // r.out contains the URL
  • For OCI, use RepoOciServerStart similarly.
  • Scenario suggestions:
    • Valid: fromRepo, withVersion, withDestination (asserts file exists at expected path), withUntar (asserts directory contents), withRepoUrl, fromOciRegistry
    • Invalid: nonExistentChart, nonExistentVersion
  • No KinD container needed — pull is client-only.

Contributor checklist

  • Java 8 syntax only
  • Apache 2.0 header (or make license)
  • @author Javadoc tag
  • DCO sign-off (git commit -s)
  • make build-native && ./mvnw test -pl helm-java -Dtest=HelmPullTest green

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions