refactor(api)!: KubeService throws unchecked domain exceptions (#500)#505
Merged
Conversation
…xception (#500) First slice of the 0.4.0 API freeze. The KubeService contract declared `throws Exception` on all 9 methods — impossible to narrow after a 1.0 semver commitment without breaking every caller's catch blocks, and it leaked the kubernetes-client `ApiException` out of HelmKubeService. - KubeService: drop `throws Exception`; document the unchecked JhelmException hierarchy (KubernetesOperationException / ReleaseStorageException / WaitTimeoutException) via @throws instead. - HelmKubeService: translate the client's checked ApiException into KubernetesOperationException (preserving the HTTP status code) in every read/delete path; handle InterruptedException in waitForReady; wrap manifest parse failures. The public surface no longer leaks ApiException. - RetryableKubeService / ObservableKubeService: drop `throws Exception`; the retry predicate already classifies KubernetesOperationException via isTransient(), so retry/observe behaviour is unchanged. BREAKING CHANGE: KubeService methods no longer declare `throws Exception`. Callers catching the checked Exception should catch JhelmException (or a subtype) instead. Behaviour is otherwise identical. Verified: 184 jhelm-kube unit tests green; format/PMD/Checkstyle clean; full reactor compiles. Cluster integration tests run in CI. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U5yvjG89AqMHPAGJawSmg9
Contributor
Files
|
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
Contributor
Files
|
This was referenced Jun 26, 2026
alexmond
added a commit
that referenced
this pull request
Jun 26, 2026
…) (#512) Second slice of the 0.4.0 API freeze (after #505 did KubeService). Every public method in core/action/* declared `throws Exception`, which is impossible to narrow after a 1.0 semver commitment and leaks checked IO/ serialization exceptions out of the public surface. - ChartLoader.load(File): drop `throws IOException`; wrap internal IO in the unchecked ChartLoadException at the public boundary (private loadFromDir keeps the IO, also keeps both methods under the MethodLength limit). - Action layer: drop `throws Exception` from all public methods. Pure KubeService delegators (list/status/history/get/rollback/uninstall/test) need no body change since #505 already made KubeService unchecked. - Where a real checked exception remained, wrap into the JhelmException hierarchy: Files/tar/HTTP IOException (Create/Package/Verify/SearchHub) and Jackson serialization -> JhelmException; the still-checked collaborators (HookExecutor.run, PostRenderProcessor.process, LifecycleListener.onEvent) are caught and wrapped at the call site (narrowly scoped, so specific subtypes like DeploymentFailedException still propagate from the main path). - Callers: CreateCommand `catch (IOException)` -> `catch (JhelmException)`; three tests swap `assertThrows`/Mockito stubs from IOException to JhelmException. BREAKING CHANGE: core/action/* and ChartLoader.load no longer declare `throws Exception`/`throws IOException`. Callers catching the checked Exception should catch JhelmException (or a subtype). Behaviour is otherwise identical. Verified: full reactor build green — jhelm-core 499, jhelm-cli 171, jhelm-rest 55 tests, 0 failures; PMD/Checkstyle clean. Claude-Session: https://claude.ai/code/session_01U5yvjG89AqMHPAGJawSmg9 Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
alexmond
added a commit
that referenced
this pull request
Jun 26, 2026
Third slice of the 0.4.0 API freeze. HelmKubeService.listPods and installConfigMap were the last two public methods declaring the kubernetes-client checked `ApiException`, pinning the client major version into jhelm's public API (the interface methods were already cleaned in #505). - listPods: translate ApiException -> KubernetesOperationException (preserving the HTTP status code); drop `throws ApiException`. - installConfigMap: replace the broad `catch (Exception)` + raw re-throw with a precise `catch (ApiException)`. The 409 replace path is extracted to a private replaceConfigMap that also translates its ApiException (it was a second uncaught leak). Drop `throws ApiException`. - Test: testInstallConfigMapThrowsOnOtherApiError now asserts KubernetesOperationException instead of ApiException. Both methods have no production callers (test-only today) but are intentional public API with unit + integration coverage, so they're wrapped, not removed. BREAKING CHANGE: HelmKubeService.listPods/installConfigMap no longer declare `throws ApiException`; failures surface as the unchecked KubernetesOperationException (carrying the HTTP status). The kubernetes-client ApiException no longer appears anywhere on jhelm's public method surface. Verified: jhelm-kube 191 tests green; jhelm-cli/jhelm-rest build clean; PMD/Checkstyle clean. Claude-Session: https://claude.ai/code/session_01U5yvjG89AqMHPAGJawSmg9 Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
First slice of #500 (0.4.0 API freeze) — eliminating
throws Exceptionfrom the public surface, starting with theKubeServicecontract.Why (1.0 blocker)
KubeServicedeclaredthrows Exceptionon all 9 methods. After a 1.0 semver commitment that's impossible to narrow without breaking every caller'scatchblocks, and it leaked the kubernetes-clientApiExceptionout ofHelmKubeService— pinning the client major version into jhelm's API.What changed
KubeService— droppedthrows Exception; documents the uncheckedJhelmExceptionhierarchy (KubernetesOperationException/ReleaseStorageException/WaitTimeoutException) via@throws.HelmKubeService— translates the client's checkedApiException→KubernetesOperationException(preserving the HTTP status code) on every read/delete path; handlesInterruptedExceptioninwaitForReady; wraps manifest-parse failures. No longer leaksApiException.RetryableKubeService/ObservableKubeService— droppedthrows Exception. The retry predicate already classifiesKubernetesOperationExceptionviaisTransient(), so retry/observe behavior is unchanged.KubeServicemethods no longer declarethrows Exception. Callers catching the checkedExceptionshould catchJhelmException(or a subtype). Behavior is otherwise identical — this is part of the deliberate pre-1.0 API freeze.Verification
jhelm-kubeunit tests green (incl.HelmKubeServiceTest,RetryableKubeServiceTest,ObservableKubeServiceTest)Part of #500.
🤖 Generated with Claude Code