fix: poll for publish completion in interactive sdk publish - #315
Merged
Conversation
Interactive `sdk publish` returned as soon as the publishing API accepted the request, printing a link and exiting 0 regardless of the outcome, while non-interactive polled to a terminal state and exited non-zero on failure. Move the polling, the running notice, and the closing log-URL note into the shared `SdkPublishAction`, so both modes report the same outcome and exit code. `pollPublishingStatus`, `publishingRunningNotice`, and `postPublishingMessage` move to the shared `SdkPublishPrompts`; the interactive-only `sdkPublishingInProgress` note is dropped since publishing is no longer in flight when the command exits. The poller now reports `succeeded | failed | cancelled` instead of a boolean. The spinner prints its own cancel line and removes its signal listeners on Ctrl+C, so the previous loop kept polling invisibly until a second Ctrl+C killed the process; it now aborts the wait, tells the user publishing continues on APIMatic, prints the log URL, and exits 130. Refs #312, #313 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Cancelling the publishing wait printed no "still running" notice and no log URL, and exited 0 for an abandoned publish. `spin.start()` calls `block()` from `@clack/core`, which puts stdin in raw mode and registers a keypress listener that calls `process.exit(0)` on Ctrl+C. Raw mode also stops the terminal raising SIGINT, so the spinner's `onCancel` never fired: the process died mid-await and the spinner's `exit` listener printed its cancel line with the green submit symbol on the way out. clack exposes no way to opt out of `block()` — `spinner()` takes `output` and `signal` but never `input`, and `updateSettings` can only add key aliases — so `startCancellableSpinner` takes the key back. It removes the listener `block()` added, found by diffing stdin's keypress listeners against a snapshot taken before `start()`, and installs one that flags cancellation and aborts the pending poll timer. `pollPublishingStatus` now stops its own spinner on cancel, guarded by `isCancelled` so the SIGTERM path clack does handle does not print twice. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This reverts commit 221cb63.
This reverts commit 49ce016.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
mrafnadeem-apimatic
requested review from
Shield-Jaguar,
aliasghar98 and
saeedjamshaid
as code owners
August 11, 2026 09:04
|
saeedjamshaid
left a comment
Collaborator
There was a problem hiding this comment.
Automated review of the polling change. 15 findings: 6 correctness issues in the new pollPublishingStatus loop and the action wiring, 1 architecture note, and 8 quality/hygiene items. Ordered roughly most-severe first in the inline comments below.
saeedjamshaid
approved these changes
Aug 11, 2026
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.



Problem
The two modes of
apimatic sdk publishdisagreed about when the command was done.success(), so the command exited0whether publishing later succeeded or failed.getSdkPublishingLogevery 10 s to a terminal state, printed the closing note, and returnedfailed()when publishing did not succeed.On cancellation with Ctrl+C, the CLI should say,
Publishing is still running on APIMatic and will continue without the CLI..Change
Polling moved into the shared
SdkPublishAction, so both modes run one identical post-POST sequence: running notice → poll → closing note with the log URL. The poll runs after thewithDirPathblock closes, releasing the temp directory holding the zipped SDK before the CLI sits waiting for minutes.sdkPublishingInProgressmessage is deleted — publishing is no longer in flight when the command exits, so its wording had become wrong. Non-interactive's log URL wording is reused verbatim for both outcomes; the log URL is useful on success and essential on failure.pollPublishingStatusreturns'succeeded' | 'failed' | 'cancelled'(exported from the prompts module, followingQuickstartFlow). A boolean cannot express cancel-vs-fail, and the distinction matters for planned work.ActionResultstays out of the prompts layer.SdkPublishAction.executenow returnsPromise<ActionResult>rather thanActionResult<PublishingInfo>. Nothing reads the payload now that the action prints its own notes, and the old signature carried a hazard: the dry-run branch returnssuccess()with no value, sogetValue()on it throws.Deliberately not in scope
events.every(...)is vacuously true on an empty array, so an empty or partially-populated publish log reports instant false success. Tracked in sdk publish: missing array length check makes an empty publish-log report a false success #312, along with the lack of retry tolerance on transient status-fetch errors and the unbounded wait.portal-service.ts'spollUntilCompletedwould suggest) means inventing a status-callback seam across a layer boundary — a refactor riding along on a parity fix.SdkPublishValidationFailedEventmodels a rejected publish request; folding remote failures into it would corrupt that metric. Tracked in sdk publish: no telemetry for publishes that fail after being accepted #313.Testing
test/has no publish coverage and no prompts tests at all. Meaningful coverage here needs either fake timers plus stdout capture against a live clack spinner, or dependency injection intoSdkPublishAction(which constructs its ownSdkPublishPrompts,PublishingApiService, andGenerateAction) — either is larger and riskier than this parity fix. Verified manually instead.Automated:
pnpm buildandpnpm lintclean.Manual (against a real publishing profile):
[Published] | [Published], exit0.1, log URL printed.🤖 Generated with Claude Code