Skip to content

feat: implement helm rollback command #351

Description

@manusa

Background

helm rollback reverts a release to a previous revision. Without it, recovering from a bad install/upgrade requires uninstall + re-install, losing release history. See helm rollback docs.

Helm SDK action: action.NewRollback (upstream).

Acceptance criteria

  • Helm.rollback("release").call() rolls a release back one revision and returns the resulting Release
  • .toRevision(int) targets a specific revision; 0 (or unset) = previous
  • Flags supported: --cleanup-on-fail, --dry-run, --force, --no-hooks, --wait, --timeout, --history-max, --namespace, --debug, kube-config (path + contents)
  • Integration tests in HelmKubernetesTest.Rollback (nested class — shares the KinD container)
  • Non-existent release surfaces a meaningful IllegalStateException

Proposed Java API

Release r = Helm.rollback("my-release")
    .toRevision(2)
    .cleanupOnFail()
    .waitReady()
    .withTimeout(300)
    .withKubeConfig(kubeConfigPath)
    .call();

Implementation guide

Follow AGENTS.md → "Adding a new Helm command" for the 9-step workflow.
Reference impl to copy patterns from: StatusCommand — same shape (keyed by release name, returns Release, uses Release.parseSingle()).

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

  • Build config with NewCfg(&CfgOptions{ KubeConfig, KubeConfigContents, Namespace }) — same as status.go.
  • client := action.NewRollback(cfg). Map options: client.Version (= revision; 0 means previous), CleanupOnFail, DryRun, Force, DisableHooks, Wait, Timeout (time.Duration(seconds) * time.Second), MaxHistory.
  • client.Run(releaseName) returns only an error (no payload).
  • After success, fetch state with action.NewStatus(cfg).Run(name) and return StatusReport(rel, true, options.Debug) — same pattern as status.go.

CGO bridge (native/main.go)

  • Add struct RollbackOptions { ... } next to the other option structs.
  • Add //export Rollback wrapping helm.Rollback(...) via runCommand(func() (string, error) { ... }).

JNA + Java

  • lib/api/.../RollbackOptions.java: mirror the C struct field order exactly (@Structure.FieldOrder).
  • Add Result Rollback(RollbackOptions options) to HelmLib.
  • helm-java/.../RollbackCommand.java extends HelmCommand<Release>; call() returns parseSingle(run(hl -> hl.Rollback(...))).
  • Add Helm.rollback(String releaseName) static factory next to Helm.status(...).

Tests

  • Add as a nested Rollback class inside HelmKubernetesTest, not a separate file — the KinD container is shared via @BeforeAll. Use the static kubeConfigFile / kubeConfigContents fields.
  • Scenario suggestions:
    • Valid: toPreviousRevision (install → upgrade → rollback → assert revision == "3"), toSpecificRevision, withNamespace, withKubeConfigContents
    • Invalid: nonExistentReleaseassertThatThrownBy(cmd::call).hasMessageContaining("release: not found")
  • Skeleton:
    @Nested
    class Rollback {
      @Nested
      class Valid {
        @Test
        void toPreviousRevision() {
          helm.install().withKubeConfig(kubeConfigFile).withName("r1").call();
          helm.upgrade().withKubeConfig(kubeConfigFile).withName("r1").call();
          Release r = Helm.rollback("r1").withKubeConfig(kubeConfigFile).call();
          assertThat(r).returns("3", Release::getRevision);
        }
      }
    }

Contributor checklist

  • Java 8 syntax only (no var, Path.of, records, Map.of)
  • Apache 2.0 header on new files (or run make license)
  • @author Javadoc tag on each new class
  • DCO sign-off on every commit (git commit -s)
  • make build-native && ./mvnw test -pl helm-java -Dtest=HelmKubernetesTest passes locally

References

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions