refactor: use @heroku/sdk for pipelines commands#3717
Merged
eablack merged 3 commits intoMay 20, 2026
Conversation
Replace direct Platform API calls in pipelines (list), pipelines:create, pipelines:info (via disambiguate), and pipelines:promote with @heroku/sdk equivalents: - pipeline.list() / pipeline.info() / pipeline.create() - pipelineCoupling.create() - account.infoByUser() / team.info() - promotePipeline() composition with onReleaseStream callback The release-command output streaming previously implemented inline in promote.ts now flows through the SDK's onReleaseStream hook, which hands a web ReadableStream to the CLI to pipe to stdout. The local poll/stream/2FA helpers are removed. Promote.promotePipeline is exposed as a static reference so tests can stub the SDK call (matches the prior Cmd.sleep convention). Adds a local PipelineCreateBody type that extends @heroku/types' PipelineCreateOpts with the undocumented `generation` request field the platform accepts but the schema doesn't declare. Adds tmp/ to the eslint ignore list.
…tion - pipelines:destroy now calls SDK pipeline.delete(). - pipelines:update now calls SDK pipelineCoupling.infoByApp() + pipelineCoupling.update(). - Drop the lib/api.ts listPipelineApps wrapper and have the four consumers (info, diff, transfer, promote) import the SDK composition directly. AppWithPipelineCoupling type also moves to the SDK; render-pipeline.ts widens it locally to satisfy hux.table's Record<string, unknown> row constraint. - Removes the now-unused getAppFilter helper, listCouplings helper, and FILTERS_HEADER constant from lib/api.ts. - Bumps @heroku/sdk to the eb/feat/list-pipeline-apps branch which exposes the new listPipelineApps composition.
eablack
added a commit
that referenced
this pull request
May 21, 2026
The integration branch's #3717 imports from @heroku/sdk/compositions/pipeline, but the SDK's exports cleanup (heroku-sdk#26) replaced compositions/ with resources/. Update each call site to use the new shape: - listPipelineApps → pipelineCouplingExtensions.listApps via HerokuSDK - promotePipeline → standalone import (kept as a static reference on the Promote command class so existing sinon stubs continue to work) - AppWithPipelineCoupling, ReleaseStreamContext → type imports from resources/platform/pipeline-{coupling,promotion} The promote test's stub callback now sees a 3-arg signature (ctx, body, options) instead of 2-arg, and firstCall.args[0] becomes [1] for body assertions. Test scope cleanup for addons/index and addons/info: split the 'apiSdk' nock scope (Accept-Expansion required) from the 'api' scope (no expansion). Global /addons and /addons/<id>/addon-attachments don't accept the expansion header, matching the SDK's per-call header scoping in heroku-sdk#27.
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.
Summary
pipelines(list),pipelines:create,pipelines:info(viadisambiguate's UUID branch),pipelines:promote,pipelines:destroy, andpipelines:updatewith@heroku/sdkequivalents (pipeline.list/info/create/delete,pipelineCoupling.create/infoByApp/update,account.infoByUser,team.info,promotePipeline).pipelines:promotetopromotePipeline'sonReleaseStreamcallback. The release-command output streaming logic that lived in this file (busl fetch with retry, single-target early-exit, release info lookup) now lives in the SDK; the CLI just pipes the resultingReadableStream<Uint8Array>toprocess.stdout. Drops ~80 lines of poll/stream/2FA helpers.listPipelineAppswrapper fromsrc/lib/api.tsand have its four consumers (info,diff,transfer,promote) import the new SDK composition directly. TheAppWithPipelineCouplingtype also moves to the SDK;render-pipeline.tswidens it locally withRecord<string, unknown>to satisfyhux.table's row constraint. Removes the now-unusedgetAppFilter/listCouplingshelpers andFILTERS_HEADERconstant fromlib/api.ts.PipelineCreateBodytype that extends@heroku/types'PipelineCreateOptswith the undocumentedgenerationfield the API accepts but the heroku/api schema doesn't declare. Comment in source explains why.Promote.promotePipelineas a static reference so tests can stub the SDK call without changing production code (mirrors the priorCmd.sleepconvention).tmp/**/*to the eslint ignore list (build artifacts were producing 138k unrelated lint errors).Type of Change
Testing
Notes: Smoke-tested against real apps in the
heroku-dev-toolsteam using a locally built CLI. Both promotion paths exercised: standard polling and the single-target release-command streaming path (the more complex behavior the SDK'sonReleaseStreamcallback now drives).updateanddestroyexercised against the same pipeline.Steps:
npm run buildto compile the refactored CLI.pipelines:updatere-stages an app:/sourcesfor a signed S3 pair, upload a small tarball containing aProcfilewith bothweb:andrelease:processes (release script prints lines over ~10s so the streaming path is observable), then POST/apps/eb-sdk-test-staging/buildswith theget_url. Wait for statussucceeded.Running release command...followed by the streamedstep 1 / 10...step 10 / 10lines emitted in real time, thenPromotion successfulandeb-sdk-test-prod: succeeded. This exercisesHerokuApiClient.stream()→ SDKonReleaseStream→stream.pipeTo(WritableStream)→process.stdout.pipelines:destroyremoves the pipeline:heroku apps:destroyfor both apps.Related Issues
GUS work item: W-22265744