Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion src/pkg/migrate/heroku.go
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,11 @@ func (h *HerokuClient) GetPGInfo(ctx context.Context, addonID string) (PGInfo, e
return herokuGet[PGInfo](ctx, h, url)
}

// herokuGet performs an HTTP GET to the given URL using the HerokuClient's token,
// decodes the JSON response into a value of type T, and returns that value.
// The request uses the provided context and sets Heroku-specific Accept and
// Content-Type headers. If the response has a non-2xx status or the body cannot
// be decoded as JSON, an error is returned describing the failure.
func herokuGet[T any](ctx context.Context, h *HerokuClient, url string) (T, error) {
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
if err != nil {
Expand Down Expand Up @@ -328,6 +333,13 @@ func authenticateHerokuCLI() error {
return nil
}

// getHerokuAuthTokenFromCLI obtains a short-lived Heroku API token by invoking the local Heroku CLI.
//
// It checks that the `heroku` executable is available, ensures the CLI is authenticated, runs
// `heroku authorizations:create --expires-in=300 --json`, and parses the resulting JSON for the token.
//
// The returned string is the extracted access token. An error is returned if the CLI is not installed,
// authentication fails, the command cannot be executed, or the command output cannot be parsed.
func getHerokuAuthTokenFromCLI() (string, error) {
_, err := exec.LookPath("heroku")
if err != nil {
Expand Down Expand Up @@ -400,4 +412,4 @@ func getHerokuAuthToken() (string, error) {
}

return token, nil
}
}
Loading