heroku 8.1.9 → 8.2.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -6
- package/autocomplete-scripts/README.md +7 -0
- package/autocomplete-scripts/bash/heroku.bash +59 -0
- package/autocomplete-scripts/brew/bash +4 -0
- package/autocomplete-scripts/brew/zsh/_heroku +59 -0
- package/autocomplete-scripts/zsh/_heroku +53 -0
- package/bin/bats-test-runner.js +7 -0
- package/bin/dev +17 -0
- package/bin/dev.cmd +3 -0
- package/bin/run +36 -1
- package/lib/analytics.d.ts +2 -2
- package/lib/analytics.js +3 -4
- package/lib/commands/auth/2fa/disable.d.ts +7 -0
- package/lib/commands/auth/2fa/disable.js +16 -0
- package/lib/commands/auth/2fa/index.d.ts +6 -0
- package/lib/commands/auth/2fa/index.js +18 -0
- package/lib/commands/auth/login.d.ts +8 -0
- package/lib/commands/auth/login.js +25 -0
- package/lib/commands/auth/logout.d.ts +6 -0
- package/lib/commands/auth/logout.js +14 -0
- package/lib/commands/auth/token.d.ts +7 -0
- package/lib/commands/auth/token.js +31 -0
- package/lib/commands/auth/whoami.d.ts +7 -0
- package/lib/commands/auth/whoami.js +26 -0
- package/lib/commands/authorizations/create.d.ts +13 -0
- package/lib/commands/authorizations/create.js +41 -0
- package/lib/commands/authorizations/index.d.ts +9 -0
- package/lib/commands/authorizations/index.js +35 -0
- package/lib/commands/authorizations/info.d.ts +11 -0
- package/lib/commands/authorizations/info.js +25 -0
- package/lib/commands/authorizations/revoke.d.ts +10 -0
- package/lib/commands/authorizations/revoke.js +22 -0
- package/lib/commands/authorizations/rotate.d.ts +8 -0
- package/lib/commands/authorizations/rotate.js +19 -0
- package/lib/commands/authorizations/update.d.ts +13 -0
- package/lib/commands/authorizations/update.js +36 -0
- package/lib/commands/autocomplete/create.d.ts +29 -0
- package/lib/commands/autocomplete/create.js +213 -0
- package/lib/commands/autocomplete/doctor.d.ts +12 -0
- package/lib/commands/autocomplete/doctor.js +97 -0
- package/lib/commands/autocomplete/index.d.ts +12 -0
- package/lib/commands/autocomplete/index.js +67 -0
- package/lib/commands/autocomplete/options.d.ts +25 -0
- package/lib/commands/autocomplete/options.js +210 -0
- package/lib/commands/autocomplete/script.d.ts +10 -0
- package/lib/commands/autocomplete/script.js +23 -0
- package/lib/commands/buildpacks/add.d.ts +13 -0
- package/lib/commands/buildpacks/add.js +43 -0
- package/lib/commands/buildpacks/clear.d.ts +9 -0
- package/lib/commands/buildpacks/clear.js +17 -0
- package/lib/commands/buildpacks/index.d.ts +9 -0
- package/lib/commands/buildpacks/index.js +25 -0
- package/lib/commands/buildpacks/info.d.ts +8 -0
- package/lib/commands/buildpacks/info.js +41 -0
- package/lib/commands/buildpacks/remove.d.ts +13 -0
- package/lib/commands/buildpacks/remove.js +55 -0
- package/lib/commands/buildpacks/search.d.ts +13 -0
- package/lib/commands/buildpacks/search.js +69 -0
- package/lib/commands/buildpacks/set.d.ts +13 -0
- package/lib/commands/buildpacks/set.js +42 -0
- package/lib/commands/buildpacks/versions.d.ts +8 -0
- package/lib/commands/buildpacks/versions.js +56 -0
- package/lib/commands/certs/auto/wait.d.ts +9 -0
- package/lib/commands/certs/auto/wait.js +14 -0
- package/lib/commands/ci/index.d.ts +12 -0
- package/lib/commands/ci/index.js +25 -0
- package/lib/commands/ci/info.d.ts +14 -0
- package/lib/commands/ci/info.js +29 -0
- package/lib/commands/ci/last.d.ts +11 -0
- package/lib/commands/ci/last.js +31 -0
- package/lib/commands/ci/rerun.d.ts +13 -0
- package/lib/commands/ci/rerun.js +53 -0
- package/lib/commands/ci/run.d.ts +10 -0
- package/lib/commands/ci/run.js +42 -0
- package/lib/commands/clients/create.d.ts +14 -0
- package/lib/commands/clients/create.js +37 -0
- package/lib/commands/clients/destroy.d.ts +8 -0
- package/lib/commands/clients/destroy.js +18 -0
- package/lib/commands/clients/index.d.ts +8 -0
- package/lib/commands/clients/index.js +32 -0
- package/lib/commands/clients/info.d.ts +13 -0
- package/lib/commands/clients/info.js +33 -0
- package/lib/commands/clients/rotate.d.ts +12 -0
- package/lib/commands/clients/rotate.js +33 -0
- package/lib/commands/clients/update.d.ts +13 -0
- package/lib/commands/clients/update.js +38 -0
- package/lib/commands/config/edit.d.ts +23 -0
- package/lib/commands/config/edit.js +132 -0
- package/lib/commands/config/get.d.ts +16 -0
- package/lib/commands/config/get.js +35 -0
- package/lib/commands/config/index.d.ts +11 -0
- package/lib/commands/config/index.js +33 -0
- package/lib/commands/config/unset.d.ts +12 -0
- package/lib/commands/config/unset.js +51 -0
- package/lib/commands/console.d.ts +11 -0
- package/lib/commands/console.js +30 -0
- package/lib/commands/domains/add.d.ts +19 -0
- package/lib/commands/domains/add.js +117 -0
- package/lib/commands/domains/clear.d.ts +11 -0
- package/lib/commands/domains/clear.js +26 -0
- package/lib/commands/domains/index.d.ts +40 -0
- package/lib/commands/domains/index.js +79 -0
- package/lib/commands/domains/info.d.ts +14 -0
- package/lib/commands/domains/info.js +25 -0
- package/lib/commands/domains/remove.d.ts +14 -0
- package/lib/commands/domains/remove.js +26 -0
- package/lib/commands/domains/update.d.ts +15 -0
- package/lib/commands/domains/update.js +40 -0
- package/lib/commands/domains/wait.d.ts +13 -0
- package/lib/commands/domains/wait.js +32 -0
- package/lib/commands/git/clone.d.ts +13 -0
- package/lib/commands/git/clone.js +29 -0
- package/lib/commands/git/credentials.d.ts +9 -0
- package/lib/commands/git/credentials.js +32 -0
- package/lib/commands/git/remote.d.ts +11 -0
- package/lib/commands/git/remote.js +44 -0
- package/lib/commands/labs/disable.d.ts +11 -0
- package/lib/commands/labs/disable.js +65 -0
- package/lib/commands/local/index.d.ts +17 -0
- package/lib/commands/local/index.js +75 -0
- package/lib/commands/local/run.d.ts +11 -0
- package/lib/commands/local/run.js +38 -0
- package/lib/commands/local/version.d.ts +5 -0
- package/lib/commands/local/version.js +13 -0
- package/lib/commands/logs.d.ts +16 -0
- package/lib/commands/logs.js +45 -0
- package/lib/commands/pipelines/add.d.ts +14 -0
- package/lib/commands/pipelines/add.js +61 -0
- package/lib/commands/pipelines/connect.d.ts +12 -0
- package/lib/commands/pipelines/connect.js +52 -0
- package/lib/commands/pipelines/create.d.ts +15 -0
- package/lib/commands/pipelines/create.js +91 -0
- package/lib/commands/pipelines/destroy.d.ts +9 -0
- package/lib/commands/pipelines/destroy.js +27 -0
- package/lib/commands/pipelines/diff.d.ts +19 -0
- package/lib/commands/pipelines/diff.js +152 -0
- package/lib/commands/pipelines/index.d.ts +9 -0
- package/lib/commands/pipelines/index.js +27 -0
- package/lib/commands/pipelines/info.d.ts +13 -0
- package/lib/commands/pipelines/info.js +43 -0
- package/lib/commands/pipelines/open.d.ts +9 -0
- package/lib/commands/pipelines/open.js +19 -0
- package/lib/commands/pipelines/promote.d.ts +12 -0
- package/lib/commands/pipelines/promote.js +216 -0
- package/lib/commands/pipelines/remove.d.ts +10 -0
- package/lib/commands/pipelines/remove.js +23 -0
- package/lib/commands/pipelines/rename.d.ts +10 -0
- package/lib/commands/pipelines/rename.js +33 -0
- package/lib/commands/pipelines/setup.d.ts +14 -0
- package/lib/commands/pipelines/setup.js +91 -0
- package/lib/commands/pipelines/transfer.d.ts +13 -0
- package/lib/commands/pipelines/transfer.js +65 -0
- package/lib/commands/pipelines/update.d.ts +11 -0
- package/lib/commands/pipelines/update.js +32 -0
- package/lib/commands/ps/autoscale/disable.d.ts +9 -0
- package/lib/commands/ps/autoscale/disable.js +35 -0
- package/lib/commands/ps/autoscale/enable.d.ts +13 -0
- package/lib/commands/ps/autoscale/enable.js +65 -0
- package/lib/commands/ps/wait.d.ts +12 -0
- package/lib/commands/ps/wait.js +78 -0
- package/lib/commands/rake.d.ts +14 -0
- package/lib/commands/rake.js +46 -0
- package/lib/commands/regions.d.ts +11 -0
- package/lib/commands/regions.js +45 -0
- package/lib/commands/reviewapps/disable.d.ts +17 -0
- package/lib/commands/reviewapps/disable.js +102 -0
- package/lib/commands/reviewapps/enable.d.ts +14 -0
- package/lib/commands/reviewapps/enable.js +89 -0
- package/lib/commands/run/detached.d.ts +15 -0
- package/lib/commands/run/detached.js +56 -0
- package/lib/commands/run/index.d.ts +18 -0
- package/lib/commands/run/index.js +64 -0
- package/lib/commands/run/inside.d.ts +15 -0
- package/lib/commands/run/inside.js +55 -0
- package/lib/commands/sessions/destroy.d.ts +8 -0
- package/lib/commands/sessions/destroy.js +18 -0
- package/lib/commands/sessions/index.d.ts +8 -0
- package/lib/commands/sessions/index.js +31 -0
- package/lib/commands/status.d.ts +8 -0
- package/lib/commands/status.js +46 -0
- package/lib/commands/webhooks/add.d.ts +16 -0
- package/lib/commands/webhooks/add.js +47 -0
- package/lib/commands/webhooks/deliveries/index.d.ts +12 -0
- package/lib/commands/webhooks/deliveries/index.js +80 -0
- package/lib/commands/webhooks/deliveries/info.d.ts +14 -0
- package/lib/commands/webhooks/deliveries/info.js +42 -0
- package/lib/commands/webhooks/events/index.d.ts +11 -0
- package/lib/commands/webhooks/events/index.js +46 -0
- package/lib/commands/webhooks/events/info.d.ts +14 -0
- package/lib/commands/webhooks/events/info.js +31 -0
- package/lib/commands/webhooks/index.d.ts +11 -0
- package/lib/commands/webhooks/index.js +45 -0
- package/lib/commands/webhooks/info.d.ts +14 -0
- package/lib/commands/webhooks/info.js +31 -0
- package/lib/commands/webhooks/remove.d.ts +14 -0
- package/lib/commands/webhooks/remove.js +29 -0
- package/lib/commands/webhooks/update.d.ts +19 -0
- package/lib/commands/webhooks/update.js +41 -0
- package/lib/file.js +2 -3
- package/lib/global_telemetry.d.ts +53 -0
- package/lib/global_telemetry.js +82 -0
- package/lib/hooks/command_not_found/performance_analytics.d.ts +3 -0
- package/lib/hooks/command_not_found/performance_analytics.js +7 -0
- package/lib/hooks/init/terms-of-service.js +3 -4
- package/lib/hooks/init/version.d.ts +2 -1
- package/lib/hooks/init/version.js +1 -2
- package/lib/hooks/postrun/performance_analytics.d.ts +3 -0
- package/lib/hooks/postrun/performance_analytics.js +11 -0
- package/lib/hooks/prerun/analytics.d.ts +2 -1
- package/lib/hooks/prerun/analytics.js +4 -4
- package/lib/hooks/recache.d.ts +3 -0
- package/lib/hooks/recache.js +56 -0
- package/lib/hooks/update/brew.d.ts +2 -1
- package/lib/hooks/update/brew.js +3 -5
- package/lib/hooks/update/completions.d.ts +2 -1
- package/lib/hooks/update/completions.js +2 -3
- package/lib/hooks/update/plugin-migrate.d.ts +2 -1
- package/lib/hooks/update/plugin-migrate.js +3 -5
- package/lib/hooks/update/tidy.d.ts +2 -1
- package/lib/hooks/update/tidy.js +3 -5
- package/lib/lib/authorizations/authorizations.d.ts +2 -0
- package/lib/lib/authorizations/authorizations.js +39 -0
- package/lib/lib/autocomplete/base.d.ts +11 -0
- package/lib/lib/autocomplete/base.js +44 -0
- package/lib/lib/autocomplete/cache.d.ts +2 -0
- package/lib/lib/autocomplete/cache.js +28 -0
- package/lib/lib/autocomplete/completions.d.ts +37 -0
- package/lib/lib/autocomplete/completions.js +261 -0
- package/lib/lib/buildpacks/buildpacks.d.ts +32 -0
- package/lib/lib/buildpacks/buildpacks.js +161 -0
- package/lib/lib/buildpacks/push.d.ts +0 -0
- package/lib/lib/buildpacks/push.js +4 -0
- package/lib/lib/ci/git.d.ts +8 -0
- package/lib/lib/ci/git.js +71 -0
- package/lib/lib/ci/interfaces/kolkrabbi.d.ts +311 -0
- package/lib/lib/ci/interfaces/kolkrabbi.js +7 -0
- package/lib/lib/ci/pipelines.d.ts +3 -0
- package/lib/lib/ci/pipelines.js +57 -0
- package/lib/lib/ci/source.d.ts +2 -0
- package/lib/lib/ci/source.js +42 -0
- package/lib/lib/ci/test-run.d.ts +5 -0
- package/lib/lib/ci/test-run.js +232 -0
- package/lib/lib/clients/clients.d.ts +1 -0
- package/lib/lib/clients/clients.js +25 -0
- package/lib/lib/config/quote.d.ts +2 -0
- package/lib/lib/config/quote.js +33 -0
- package/lib/lib/config/util.d.ts +3 -0
- package/lib/lib/config/util.js +12 -0
- package/lib/lib/domains/wait-for-domain.d.ts +3 -0
- package/lib/lib/domains/wait-for-domain.js +19 -0
- package/lib/lib/git/git.d.ts +8 -0
- package/lib/lib/git/git.js +56 -0
- package/lib/lib/local/fork-foreman.d.ts +1 -0
- package/lib/lib/local/fork-foreman.js +33 -0
- package/lib/lib/local/load-foreman-procfile.d.ts +0 -0
- package/lib/lib/local/load-foreman-procfile.js +2 -0
- package/lib/lib/local/run-foreman.d.ts +0 -0
- package/lib/lib/local/run-foreman.js +2 -0
- package/lib/lib/pipelines/api.d.ts +25 -0
- package/lib/lib/pipelines/api.js +130 -0
- package/lib/lib/pipelines/disambiguate.d.ts +3 -0
- package/lib/lib/pipelines/disambiguate.js +49 -0
- package/lib/lib/pipelines/github-api.d.ts +8 -0
- package/lib/lib/pipelines/github-api.js +18 -0
- package/lib/lib/pipelines/infer.d.ts +1 -0
- package/lib/lib/pipelines/infer.js +11 -0
- package/lib/lib/pipelines/key-by.d.ts +1 -0
- package/lib/lib/pipelines/key-by.js +11 -0
- package/lib/lib/pipelines/kolkrabbi-api.d.ts +14 -0
- package/lib/lib/pipelines/kolkrabbi-api.js +62 -0
- package/lib/lib/pipelines/ownership.d.ts +4 -0
- package/lib/lib/pipelines/ownership.js +40 -0
- package/lib/lib/pipelines/render-pipeline.d.ts +6 -0
- package/lib/lib/pipelines/render-pipeline.js +52 -0
- package/lib/lib/pipelines/setup/create-apps.d.ts +1 -0
- package/lib/lib/pipelines/setup/create-apps.js +44 -0
- package/lib/lib/pipelines/setup/get-ci-settings.d.ts +4 -0
- package/lib/lib/pipelines/setup/get-ci-settings.js +19 -0
- package/lib/lib/pipelines/setup/get-github-token.d.ts +1 -0
- package/lib/lib/pipelines/setup/get-github-token.js +10 -0
- package/lib/lib/pipelines/setup/get-name-and-repo.d.ts +1 -0
- package/lib/lib/pipelines/setup/get-name-and-repo.js +47 -0
- package/lib/lib/pipelines/setup/get-repo.d.ts +1 -0
- package/lib/lib/pipelines/setup/get-repo.js +8 -0
- package/lib/lib/pipelines/setup/get-settings.d.ts +9 -0
- package/lib/lib/pipelines/setup/get-settings.js +39 -0
- package/lib/lib/pipelines/setup/poll-app-setups.d.ts +1 -0
- package/lib/lib/pipelines/setup/poll-app-setups.js +25 -0
- package/lib/lib/pipelines/setup/setup-pipeline.d.ts +1 -0
- package/lib/lib/pipelines/setup/setup-pipeline.js +15 -0
- package/lib/lib/pipelines/setup/validate.d.ts +9 -0
- package/lib/lib/pipelines/setup/validate.js +31 -0
- package/lib/lib/pipelines/stages.d.ts +7 -0
- package/lib/lib/pipelines/stages.js +22 -0
- package/lib/lib/run/colorize.d.ts +2 -0
- package/lib/lib/run/colorize.js +300 -0
- package/lib/lib/run/dyno.d.ts +72 -0
- package/lib/lib/run/dyno.js +397 -0
- package/lib/lib/run/helpers.d.ts +2 -0
- package/lib/lib/run/helpers.js +34 -0
- package/lib/lib/run/line-transform.d.ts +4 -0
- package/lib/lib/run/line-transform.js +26 -0
- package/lib/lib/run/log-displayer.d.ts +10 -0
- package/lib/lib/run/log-displayer.js +79 -0
- package/lib/lib/sessions/sessions.d.ts +7 -0
- package/lib/lib/sessions/sessions.js +2 -0
- package/lib/lib/status/util.d.ts +1 -0
- package/lib/lib/status/util.js +14 -0
- package/lib/lib/webhooks/base.d.ts +13 -0
- package/lib/lib/webhooks/base.js +28 -0
- package/lib/user-config.js +2 -3
- package/oclif.manifest.json +3376 -2
- package/package.json +80 -43
- package/lib/hooks/update/b.d.ts +0 -2
- package/lib/hooks/update/b.js +0 -48
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
/// <reference types="node" />
|
|
3
|
+
/// <reference types="node" />
|
|
4
|
+
/// <reference types="node" />
|
|
5
|
+
import { APIClient } from '@heroku-cli/command';
|
|
6
|
+
import { IOptions } from '@heroku-cli/command/lib/api-client';
|
|
7
|
+
import { Dyno as APIDyno } from '@heroku-cli/schema';
|
|
8
|
+
import { HTTP } from 'http-call';
|
|
9
|
+
import * as net from 'net';
|
|
10
|
+
import { Duplex } from 'stream';
|
|
11
|
+
import * as tls from 'tls';
|
|
12
|
+
import { URL } from 'url';
|
|
13
|
+
interface HerokuApiClientRun extends APIClient {
|
|
14
|
+
options: IOptions & {
|
|
15
|
+
rejectUnauthorized?: boolean;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
interface DynoOpts {
|
|
19
|
+
'exit-code'?: boolean;
|
|
20
|
+
'no-tty'?: boolean;
|
|
21
|
+
app: string;
|
|
22
|
+
attach?: boolean;
|
|
23
|
+
command: string;
|
|
24
|
+
dyno?: string;
|
|
25
|
+
env?: string;
|
|
26
|
+
heroku: APIClient;
|
|
27
|
+
listen?: boolean;
|
|
28
|
+
notify?: boolean;
|
|
29
|
+
showStatus?: boolean;
|
|
30
|
+
size?: string;
|
|
31
|
+
type?: string;
|
|
32
|
+
}
|
|
33
|
+
export default class Dyno extends Duplex {
|
|
34
|
+
opts: DynoOpts;
|
|
35
|
+
get _useSSH(): boolean | undefined;
|
|
36
|
+
dyno?: APIDyno;
|
|
37
|
+
heroku: HerokuApiClientRun;
|
|
38
|
+
input: any;
|
|
39
|
+
p: any;
|
|
40
|
+
reject?: (reason?: any) => void;
|
|
41
|
+
resolve?: (value?: unknown) => void;
|
|
42
|
+
uri?: URL;
|
|
43
|
+
legacyUri?: {
|
|
44
|
+
[key: string]: any;
|
|
45
|
+
};
|
|
46
|
+
unpipeStdin: any;
|
|
47
|
+
useSSH: any;
|
|
48
|
+
private _notified?;
|
|
49
|
+
private _startedAt?;
|
|
50
|
+
constructor(opts: DynoOpts);
|
|
51
|
+
/**
|
|
52
|
+
* Starts the dyno
|
|
53
|
+
*/
|
|
54
|
+
start(): Promise<void>;
|
|
55
|
+
_doStart(retries?: number): Promise<HTTP<unknown> | undefined>;
|
|
56
|
+
attach(): any;
|
|
57
|
+
_rendezvous(): Promise<unknown>;
|
|
58
|
+
_ssh(retries?: number): Promise<unknown>;
|
|
59
|
+
_connect(): Promise<unknown>;
|
|
60
|
+
_handle(localServer: net.Server): void;
|
|
61
|
+
_isDebug(): boolean | "" | undefined;
|
|
62
|
+
_env(): {
|
|
63
|
+
[key: string]: any;
|
|
64
|
+
};
|
|
65
|
+
_status(status: string | undefined): string;
|
|
66
|
+
_readData(c?: tls.TLSSocket): (data: string) => void;
|
|
67
|
+
_readStdin(c: tls.TLSSocket): void;
|
|
68
|
+
_read(): void;
|
|
69
|
+
_write(chunk: any, encoding: any, callback: any): void;
|
|
70
|
+
_notify(): void;
|
|
71
|
+
}
|
|
72
|
+
export {};
|
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
|
4
|
+
const color_1 = require("@heroku-cli/color");
|
|
5
|
+
const notifications_1 = require("@heroku-cli/notifications");
|
|
6
|
+
const child_process_1 = require("child_process");
|
|
7
|
+
const core_1 = require("@oclif/core");
|
|
8
|
+
const debug_1 = require("debug");
|
|
9
|
+
const https = require("https");
|
|
10
|
+
const net = require("net");
|
|
11
|
+
const stream_1 = require("stream");
|
|
12
|
+
const tls = require("tls");
|
|
13
|
+
const tty = require("tty");
|
|
14
|
+
const url_1 = require("url");
|
|
15
|
+
const helpers_1 = require("./helpers");
|
|
16
|
+
const debug = (0, debug_1.default)('heroku:run');
|
|
17
|
+
const wait = (ms) => new Promise(resolve => setTimeout(() => resolve(), ms));
|
|
18
|
+
class Dyno extends stream_1.Duplex {
|
|
19
|
+
constructor(opts) {
|
|
20
|
+
super();
|
|
21
|
+
this.opts = opts;
|
|
22
|
+
this.cork();
|
|
23
|
+
this.opts = opts;
|
|
24
|
+
this.heroku = opts.heroku;
|
|
25
|
+
if (this.opts.showStatus === undefined) {
|
|
26
|
+
this.opts.showStatus = true;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
get _useSSH() {
|
|
30
|
+
if (this.uri) {
|
|
31
|
+
/* tslint:disable:no-http-string */
|
|
32
|
+
return this.uri.protocol === 'http:' || this.uri.protocol === 'https:';
|
|
33
|
+
/* tslint:enable:no-http-string */
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Starts the dyno
|
|
38
|
+
*/
|
|
39
|
+
async start() {
|
|
40
|
+
this._startedAt = Date.now();
|
|
41
|
+
if (this.opts.showStatus) {
|
|
42
|
+
core_1.ux.action.start(`Running ${color_1.default.cyan.bold(this.opts.command)} on ${color_1.default.app(this.opts.app)}`);
|
|
43
|
+
}
|
|
44
|
+
await this._doStart();
|
|
45
|
+
}
|
|
46
|
+
async _doStart(retries = 2) {
|
|
47
|
+
const command = this.opts['exit-code'] ? `${this.opts.command}; echo "\uFFFF heroku-command-exit-status: $?"` : this.opts.command;
|
|
48
|
+
try {
|
|
49
|
+
const dyno = await this.heroku.post(this.opts.dyno ? `/apps/${this.opts.app}/dynos/${this.opts.dyno}` : `/apps/${this.opts.app}/dynos`, {
|
|
50
|
+
headers: {
|
|
51
|
+
Accept: this.opts.dyno ? 'application/vnd.heroku+json; version=3.run-inside' : 'application/vnd.heroku+json; version=3',
|
|
52
|
+
},
|
|
53
|
+
body: {
|
|
54
|
+
command,
|
|
55
|
+
attach: this.opts.attach,
|
|
56
|
+
size: this.opts.size,
|
|
57
|
+
type: this.opts.type,
|
|
58
|
+
env: this._env(),
|
|
59
|
+
force_no_tty: this.opts['no-tty'],
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
// @ts-ignore
|
|
63
|
+
this.dyno = dyno.body;
|
|
64
|
+
if (this.opts.attach || this.opts.dyno) {
|
|
65
|
+
// @ts-ignore
|
|
66
|
+
if (this.dyno.name && this.opts.dyno === undefined) {
|
|
67
|
+
// @ts-ignore
|
|
68
|
+
this.opts.dyno = this.dyno.name;
|
|
69
|
+
}
|
|
70
|
+
await this.attach();
|
|
71
|
+
}
|
|
72
|
+
else if (this.opts.showStatus) {
|
|
73
|
+
core_1.ux.action.stop(this._status('done'));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
// Currently the runtime API sends back a 409 in the event the
|
|
78
|
+
// release isn't found yet. API just forwards this response back to
|
|
79
|
+
// the client, so we'll need to retry these. This usually
|
|
80
|
+
// happens when you create an app and immediately try to run a
|
|
81
|
+
// one-off dyno. No pause between attempts since this is
|
|
82
|
+
// typically a very short-lived condition.
|
|
83
|
+
if (error.statusCode === 409 && retries > 0) {
|
|
84
|
+
return this._doStart(retries - 1);
|
|
85
|
+
}
|
|
86
|
+
throw error;
|
|
87
|
+
}
|
|
88
|
+
finally {
|
|
89
|
+
core_1.ux.action.stop();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// Attaches stdin/stdout to dyno
|
|
93
|
+
attach() {
|
|
94
|
+
this.pipe(process.stdout);
|
|
95
|
+
if (this.dyno && this.dyno.attach_url) {
|
|
96
|
+
this.uri = new url_1.URL(this.dyno.attach_url);
|
|
97
|
+
this.legacyUri = (0, url_1.parse)(this.dyno.attach_url);
|
|
98
|
+
}
|
|
99
|
+
if (this._useSSH) {
|
|
100
|
+
this.p = this._ssh();
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
this.p = this._rendezvous();
|
|
104
|
+
}
|
|
105
|
+
return this.p.then(() => {
|
|
106
|
+
this.end();
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
_rendezvous() {
|
|
110
|
+
return new Promise((resolve, reject) => {
|
|
111
|
+
this.resolve = resolve;
|
|
112
|
+
this.reject = reject;
|
|
113
|
+
if (this.opts.showStatus) {
|
|
114
|
+
core_1.ux.action.status = this._status('starting');
|
|
115
|
+
}
|
|
116
|
+
// @ts-ignore
|
|
117
|
+
const c = tls.connect(Number.parseInt(this.uri.port, 10), this.uri.hostname, {
|
|
118
|
+
rejectUnauthorized: this.heroku.options.rejectUnauthorized,
|
|
119
|
+
});
|
|
120
|
+
c.setTimeout(1000 * 60 * 60);
|
|
121
|
+
c.setEncoding('utf8');
|
|
122
|
+
c.on('connect', () => {
|
|
123
|
+
debug('connect');
|
|
124
|
+
// @ts-ignore eslint-disable-next-line no-unsafe-optional-chaining
|
|
125
|
+
const pathnameWithSearchParams = this.uri.pathname + this.uri.search;
|
|
126
|
+
c.write(pathnameWithSearchParams.slice(1) + '\r\n', () => {
|
|
127
|
+
if (this.opts.showStatus) {
|
|
128
|
+
core_1.ux.action.status = this._status('connecting');
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
c.on('data', this._readData(c));
|
|
133
|
+
c.on('close', () => {
|
|
134
|
+
debug('close');
|
|
135
|
+
// @ts-ignore
|
|
136
|
+
this.opts['exit-code'] ? this.reject('No exit code returned') : this.resolve();
|
|
137
|
+
if (this.unpipeStdin) {
|
|
138
|
+
this.unpipeStdin();
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
c.on('error', this.reject);
|
|
142
|
+
c.on('timeout', () => {
|
|
143
|
+
debug('timeout');
|
|
144
|
+
c.end();
|
|
145
|
+
// @ts-ignore
|
|
146
|
+
this.reject(new Error('timed out'));
|
|
147
|
+
});
|
|
148
|
+
process.once('SIGINT', () => c.end());
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
async _ssh(retries = 20) {
|
|
152
|
+
const interval = 1000;
|
|
153
|
+
try {
|
|
154
|
+
const { body: dyno } = await this.heroku.get(`/apps/${this.opts.app}/dynos/${this.opts.dyno}`);
|
|
155
|
+
// @ts-ignore
|
|
156
|
+
this.dyno = dyno;
|
|
157
|
+
// @ts-ignore
|
|
158
|
+
core_1.ux.action.stop(this._status(this.dyno.state));
|
|
159
|
+
// @ts-ignore
|
|
160
|
+
if (this.dyno.state === 'starting' || this.dyno.state === 'up') {
|
|
161
|
+
return this._connect();
|
|
162
|
+
}
|
|
163
|
+
await wait(interval);
|
|
164
|
+
return this._ssh();
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
// the API sometimes responds with a 404 when the dyno is not yet ready
|
|
168
|
+
if (error.http.statusCode === 404 && retries > 0) {
|
|
169
|
+
return this._ssh(retries - 1);
|
|
170
|
+
}
|
|
171
|
+
throw error;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
_connect() {
|
|
175
|
+
return new Promise((resolve, reject) => {
|
|
176
|
+
this.resolve = resolve;
|
|
177
|
+
this.reject = reject;
|
|
178
|
+
// @ts-ignore
|
|
179
|
+
const options = this.legacyUri;
|
|
180
|
+
options.headers = { Connection: 'Upgrade', Upgrade: 'tcp' };
|
|
181
|
+
options.rejectUnauthorized = false;
|
|
182
|
+
const r = https.request(options);
|
|
183
|
+
r.end();
|
|
184
|
+
r.on('error', this.reject);
|
|
185
|
+
r.on('upgrade', (_, remote) => {
|
|
186
|
+
const s = net.createServer(client => {
|
|
187
|
+
client.on('end', () => {
|
|
188
|
+
s.close();
|
|
189
|
+
// @ts-ignore
|
|
190
|
+
this.resolve();
|
|
191
|
+
});
|
|
192
|
+
client.on('connect', () => s.close());
|
|
193
|
+
client.on('error', () => this.reject);
|
|
194
|
+
remote.on('error', () => this.reject);
|
|
195
|
+
client.setNoDelay(true);
|
|
196
|
+
remote.setNoDelay(true);
|
|
197
|
+
remote.on('data', (data) => client.write(data));
|
|
198
|
+
client.on('data', data => remote.write(data));
|
|
199
|
+
});
|
|
200
|
+
s.listen(0, 'localhost', () => this._handle(s));
|
|
201
|
+
// abort the request when the local pipe server is closed
|
|
202
|
+
s.on('close', () => {
|
|
203
|
+
r.abort();
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
_handle(localServer) {
|
|
209
|
+
const addr = localServer.address();
|
|
210
|
+
const host = addr.address;
|
|
211
|
+
const port = addr.port;
|
|
212
|
+
let lastErr = '';
|
|
213
|
+
// does not actually uncork but allows error to be displayed when attempting to read
|
|
214
|
+
this.uncork();
|
|
215
|
+
if (this.opts.listen) {
|
|
216
|
+
core_1.ux.log(`listening on port ${host}:${port} for ssh client`);
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
const params = [host, '-p', port.toString(), '-oStrictHostKeyChecking=no', '-oUserKnownHostsFile=/dev/null', '-oServerAliveInterval=20'];
|
|
220
|
+
// Debug SSH
|
|
221
|
+
if (this._isDebug()) {
|
|
222
|
+
params.push('-vvv');
|
|
223
|
+
}
|
|
224
|
+
const stdio = [0, 1, 'pipe'];
|
|
225
|
+
if (this.opts['exit-code']) {
|
|
226
|
+
stdio[1] = 'pipe';
|
|
227
|
+
if (process.stdout.isTTY) {
|
|
228
|
+
// force tty
|
|
229
|
+
params.push('-t');
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
const sshProc = (0, child_process_1.spawn)('ssh', params, { stdio });
|
|
233
|
+
// only receives stdout with --exit-code
|
|
234
|
+
if (sshProc.stdout) {
|
|
235
|
+
sshProc.stdout.setEncoding('utf8');
|
|
236
|
+
sshProc.stdout.on('data', this._readData());
|
|
237
|
+
}
|
|
238
|
+
// @ts-ignore
|
|
239
|
+
sshProc.stderr.on('data', data => {
|
|
240
|
+
lastErr = data;
|
|
241
|
+
// supress host key and permission denied messages
|
|
242
|
+
if (this._isDebug() || (data.includes("Warning: Permanently added '[127.0.0.1]") && data.includes('Permission denied (publickey).'))) {
|
|
243
|
+
process.stderr.write(data);
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
sshProc.on('close', () => {
|
|
247
|
+
// there was a problem connecting with the ssh key
|
|
248
|
+
if (lastErr.length > 0 && lastErr.includes('Permission denied')) {
|
|
249
|
+
const msgs = ['There was a problem connecting to the dyno.'];
|
|
250
|
+
if (process.env.SSH_AUTH_SOCK) {
|
|
251
|
+
msgs.push('Confirm that your ssh key is added to your agent by running `ssh-add`.');
|
|
252
|
+
}
|
|
253
|
+
msgs.push('Check that your ssh key has been uploaded to heroku with `heroku keys:add`.');
|
|
254
|
+
// eslint-disable-next-line unicorn/no-array-push-push
|
|
255
|
+
msgs.push(`See ${color_1.default.cyan('https://devcenter.heroku.com/articles/one-off-dynos#shield-private-spaces')}`);
|
|
256
|
+
core_1.ux.error(msgs.join('\n'));
|
|
257
|
+
}
|
|
258
|
+
// cleanup local server
|
|
259
|
+
localServer.close();
|
|
260
|
+
});
|
|
261
|
+
this.p
|
|
262
|
+
.then(() => sshProc.kill())
|
|
263
|
+
.catch(() => sshProc.kill());
|
|
264
|
+
}
|
|
265
|
+
this._notify();
|
|
266
|
+
}
|
|
267
|
+
_isDebug() {
|
|
268
|
+
const debug = process.env.HEROKU_DEBUG;
|
|
269
|
+
return debug && (debug === '1' || debug.toUpperCase() === 'TRUE');
|
|
270
|
+
}
|
|
271
|
+
_env() {
|
|
272
|
+
const c = this.opts.env ? (0, helpers_1.buildEnvFromFlag)(this.opts.env) : {};
|
|
273
|
+
c.TERM = process.env.TERM;
|
|
274
|
+
if (tty.isatty(1)) {
|
|
275
|
+
c.COLUMNS = process.stdout.columns;
|
|
276
|
+
c.LINES = process.stdout.rows;
|
|
277
|
+
}
|
|
278
|
+
return c;
|
|
279
|
+
}
|
|
280
|
+
_status(status) {
|
|
281
|
+
// @ts-ignore
|
|
282
|
+
const size = this.dyno.size > 0 ? ` (${this.dyno.size})` : '';
|
|
283
|
+
// @ts-ignore
|
|
284
|
+
return `${status}, ${this.dyno.name || this.opts.dyno}${size}`;
|
|
285
|
+
}
|
|
286
|
+
_readData(c) {
|
|
287
|
+
let firstLine = true;
|
|
288
|
+
return (data) => {
|
|
289
|
+
debug('input: %o', data);
|
|
290
|
+
// discard first line
|
|
291
|
+
if (c && firstLine) {
|
|
292
|
+
if (this.opts.showStatus)
|
|
293
|
+
core_1.ux.action.stop(this._status('up'));
|
|
294
|
+
firstLine = false;
|
|
295
|
+
this._readStdin(c);
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
this._notify();
|
|
299
|
+
// carriage returns break json parsing of output
|
|
300
|
+
if (!process.stdout.isTTY) {
|
|
301
|
+
// eslint-disable-next-line no-control-regex, prefer-regex-literals
|
|
302
|
+
data = data.replace(new RegExp('\r\n', 'g'), '\n');
|
|
303
|
+
}
|
|
304
|
+
const exitCode = data.match(/\uFFFF heroku-command-exit-status: (\d+)/m);
|
|
305
|
+
if (exitCode) {
|
|
306
|
+
debug('got exit code: %d', exitCode[1]);
|
|
307
|
+
this.push(data.replace(/^\uFFFF heroku-command-exit-status: \d+$\n?/m, ''));
|
|
308
|
+
const code = Number.parseInt(exitCode[1], 10);
|
|
309
|
+
if (code === 0) {
|
|
310
|
+
// @ts-ignore
|
|
311
|
+
this.resolve();
|
|
312
|
+
}
|
|
313
|
+
else {
|
|
314
|
+
const err = new Error(`Process exited with code ${color_1.default.red(code.toString())}`);
|
|
315
|
+
err.exitCode = code;
|
|
316
|
+
// @ts-ignore
|
|
317
|
+
this.reject(err);
|
|
318
|
+
}
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
this.push(data);
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
_readStdin(c) {
|
|
325
|
+
this.input = c;
|
|
326
|
+
const stdin = process.stdin;
|
|
327
|
+
stdin.setEncoding('utf8');
|
|
328
|
+
// without this the CLI will hang on rake db:migrate
|
|
329
|
+
// until a character is pressed
|
|
330
|
+
if (stdin.unref) {
|
|
331
|
+
stdin.unref();
|
|
332
|
+
}
|
|
333
|
+
if (!this.opts['no-tty'] && tty.isatty(0)) {
|
|
334
|
+
// @ts-ignore
|
|
335
|
+
stdin.setRawMode(true);
|
|
336
|
+
stdin.pipe(c);
|
|
337
|
+
let sigints = [];
|
|
338
|
+
stdin.on('data', function (c) {
|
|
339
|
+
if (c === '\u0003') {
|
|
340
|
+
sigints.push(Date.now());
|
|
341
|
+
}
|
|
342
|
+
sigints = sigints.filter(d => d > Date.now() - 1000);
|
|
343
|
+
if (sigints.length >= 4) {
|
|
344
|
+
core_1.ux.error('forcing dyno disconnect', { exit: 1 });
|
|
345
|
+
}
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
else {
|
|
349
|
+
stdin.pipe(new stream_1.Transform({
|
|
350
|
+
objectMode: true,
|
|
351
|
+
transform: (chunk, _, next) => c.write(chunk, next),
|
|
352
|
+
// eslint-disable-next-line unicorn/no-hex-escape
|
|
353
|
+
flush: done => c.write('\x04', done),
|
|
354
|
+
}));
|
|
355
|
+
}
|
|
356
|
+
this.uncork();
|
|
357
|
+
}
|
|
358
|
+
_read() {
|
|
359
|
+
if (this.useSSH) {
|
|
360
|
+
throw new Error('Cannot read stream from ssh dyno');
|
|
361
|
+
}
|
|
362
|
+
// do not need to do anything to handle Readable interface
|
|
363
|
+
}
|
|
364
|
+
_write(chunk, encoding, callback) {
|
|
365
|
+
if (this.useSSH) {
|
|
366
|
+
throw new Error('Cannot write stream to ssh dyno');
|
|
367
|
+
}
|
|
368
|
+
if (!this.input)
|
|
369
|
+
throw new Error('no input');
|
|
370
|
+
this.input.write(chunk, encoding, callback);
|
|
371
|
+
}
|
|
372
|
+
_notify() {
|
|
373
|
+
try {
|
|
374
|
+
if (this._notified)
|
|
375
|
+
return;
|
|
376
|
+
this._notified = true;
|
|
377
|
+
if (!this.opts.notify)
|
|
378
|
+
return;
|
|
379
|
+
// only show notifications if dyno took longer than 20 seconds to start
|
|
380
|
+
// @ts-ignore
|
|
381
|
+
if (Date.now() - this._startedAt < 1000 * 20)
|
|
382
|
+
return;
|
|
383
|
+
const notification = {
|
|
384
|
+
// @ts-ignore
|
|
385
|
+
title: this.opts.app,
|
|
386
|
+
subtitle: `heroku run ${this.opts.command}`,
|
|
387
|
+
message: 'dyno is up',
|
|
388
|
+
// sound: true
|
|
389
|
+
};
|
|
390
|
+
(0, notifications_1.notify)(notification);
|
|
391
|
+
}
|
|
392
|
+
catch (error) {
|
|
393
|
+
core_1.ux.warn(error);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
exports.default = Dyno;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildEnvFromFlag = exports.buildCommand = void 0;
|
|
4
|
+
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
|
5
|
+
const core_1 = require("@oclif/core");
|
|
6
|
+
function buildCommand(args) {
|
|
7
|
+
if (args.length === 1) {
|
|
8
|
+
// do not add quotes around arguments if there is only one argument
|
|
9
|
+
// `heroku run "rake test"` should work like `heroku run rake test`
|
|
10
|
+
return args[0];
|
|
11
|
+
}
|
|
12
|
+
let cmd = '';
|
|
13
|
+
for (let arg of args) {
|
|
14
|
+
if (arg.includes(' ') || arg.includes('"')) {
|
|
15
|
+
arg = '"' + arg.replace(/"/g, '\\"') + '"';
|
|
16
|
+
}
|
|
17
|
+
cmd = cmd + ' ' + arg;
|
|
18
|
+
}
|
|
19
|
+
return cmd.trim();
|
|
20
|
+
}
|
|
21
|
+
exports.buildCommand = buildCommand;
|
|
22
|
+
function buildEnvFromFlag(flag) {
|
|
23
|
+
const env = {};
|
|
24
|
+
for (const v of flag.split(';')) {
|
|
25
|
+
const m = v.match(/^\s*([\w.-]+)\s*=\s*(.*)?\s*$/);
|
|
26
|
+
// @ts-ignore
|
|
27
|
+
if (m)
|
|
28
|
+
env[m[1]] = m[2];
|
|
29
|
+
else
|
|
30
|
+
core_1.ux.warn(`env flag ${v} appears invalid. Avoid using ';' in values.`);
|
|
31
|
+
}
|
|
32
|
+
return env;
|
|
33
|
+
}
|
|
34
|
+
exports.buildEnvFromFlag = buildEnvFromFlag;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
|
4
|
+
const stream = require("stream");
|
|
5
|
+
// this splits a stream into lines
|
|
6
|
+
const transform = new stream.Transform({ decodeStrings: false });
|
|
7
|
+
transform._transform = function (chunk, _encoding, next) {
|
|
8
|
+
let data = chunk;
|
|
9
|
+
// @ts-ignore
|
|
10
|
+
if (this._lastLineData)
|
|
11
|
+
data = this._lastLineData + data;
|
|
12
|
+
const lines = data.split('\n');
|
|
13
|
+
// @ts-ignore
|
|
14
|
+
this._lastLineData = lines.splice(-1, 1)[0];
|
|
15
|
+
lines.forEach(this.push.bind(this));
|
|
16
|
+
next();
|
|
17
|
+
};
|
|
18
|
+
transform._flush = function (done) {
|
|
19
|
+
// @ts-ignore
|
|
20
|
+
if (this._lastLineData)
|
|
21
|
+
this.push(this._lastLineData);
|
|
22
|
+
// @ts-ignore
|
|
23
|
+
this._lastLineData = null;
|
|
24
|
+
done();
|
|
25
|
+
};
|
|
26
|
+
exports.default = transform;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { APIClient } from '@heroku-cli/command';
|
|
2
|
+
interface LogDisplayerOptions {
|
|
3
|
+
app: string;
|
|
4
|
+
dyno: string;
|
|
5
|
+
lines?: number;
|
|
6
|
+
tail: boolean;
|
|
7
|
+
source?: string;
|
|
8
|
+
}
|
|
9
|
+
declare function logDisplayer(heroku: APIClient, options: LogDisplayerOptions): Promise<unknown>;
|
|
10
|
+
export default logDisplayer;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const http_call_1 = require("http-call");
|
|
5
|
+
const url_1 = require("url");
|
|
6
|
+
const colorize_1 = require("./colorize");
|
|
7
|
+
const line_transform_1 = require("./line-transform");
|
|
8
|
+
const EventSource = require('@heroku/eventsource');
|
|
9
|
+
async function readLogsV1(logplexURL) {
|
|
10
|
+
const { response } = await http_call_1.default.stream(logplexURL);
|
|
11
|
+
return new Promise(function (resolve, reject) {
|
|
12
|
+
response.setEncoding('utf8');
|
|
13
|
+
line_transform_1.default.setEncoding('utf8');
|
|
14
|
+
response.pipe(line_transform_1.default);
|
|
15
|
+
line_transform_1.default.on('data', line => core_1.ux.log((0, colorize_1.default)(line)));
|
|
16
|
+
response.on('end', resolve);
|
|
17
|
+
response.on('error', reject);
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
function readLogsV2(logplexURL) {
|
|
21
|
+
return new Promise(function (resolve, reject) {
|
|
22
|
+
const u = new url_1.URL(logplexURL);
|
|
23
|
+
const isTail = u.searchParams.get('tail') === 'true';
|
|
24
|
+
const userAgent = process.env.HEROKU_DEBUG_USER_AGENT || 'heroku-run';
|
|
25
|
+
const proxy = process.env.https_proxy || process.env.HTTPS_PROXY;
|
|
26
|
+
const es = new EventSource(logplexURL, {
|
|
27
|
+
proxy,
|
|
28
|
+
headers: {
|
|
29
|
+
'User-Agent': userAgent,
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
es.addEventListener('error', function (err) {
|
|
33
|
+
if (err && (err.status || err.message)) {
|
|
34
|
+
const msg = (isTail && (err.status === 404 || err.status === 403)) ?
|
|
35
|
+
'Log stream timed out. Please try again.' :
|
|
36
|
+
`Logs eventsource failed with: ${err.status} ${err.message}`;
|
|
37
|
+
reject(msg);
|
|
38
|
+
es.close();
|
|
39
|
+
}
|
|
40
|
+
if (!isTail) {
|
|
41
|
+
resolve();
|
|
42
|
+
es.close();
|
|
43
|
+
}
|
|
44
|
+
// should only land here if --tail and no error status or message
|
|
45
|
+
});
|
|
46
|
+
es.addEventListener('message', function (e) {
|
|
47
|
+
e.data.trim().split(/\n+/).forEach(line => {
|
|
48
|
+
core_1.ux.log((0, colorize_1.default)(line));
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
function readLogs(logplexURL) {
|
|
54
|
+
const u = new url_1.URL(logplexURL);
|
|
55
|
+
if (u.searchParams.has('srv')) {
|
|
56
|
+
return readLogsV1(logplexURL);
|
|
57
|
+
}
|
|
58
|
+
return readLogsV2(logplexURL);
|
|
59
|
+
}
|
|
60
|
+
async function logDisplayer(heroku, options) {
|
|
61
|
+
process.stdout.on('error', err => {
|
|
62
|
+
if (err.code === 'EPIPE') {
|
|
63
|
+
process.exit(0);
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
core_1.ux.error(err.stack, { exit: 1 });
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
const response = await heroku.post(`/apps/${options.app}/log-sessions`, {
|
|
70
|
+
body: {
|
|
71
|
+
tail: options.tail,
|
|
72
|
+
dyno: options.dyno,
|
|
73
|
+
source: options.source,
|
|
74
|
+
lines: options.lines,
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
return readLogs(response.body.logplex_url);
|
|
78
|
+
}
|
|
79
|
+
exports.default = logDisplayer;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function maxBy<T>(arr: T[], fn: (i: T) => number): T | undefined;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.maxBy = void 0;
|
|
4
|
+
function maxBy(arr, fn) {
|
|
5
|
+
let max;
|
|
6
|
+
for (const cur of arr) {
|
|
7
|
+
const i = fn(cur);
|
|
8
|
+
if (!max || i > max.i) {
|
|
9
|
+
max = { i, element: cur };
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
return max && max.element;
|
|
13
|
+
}
|
|
14
|
+
exports.maxBy = maxBy;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { APIClient, Command } from '@heroku-cli/command';
|
|
2
|
+
import { Config } from '@oclif/core';
|
|
3
|
+
export default abstract class extends Command {
|
|
4
|
+
webhooksClient: APIClient;
|
|
5
|
+
protected constructor(argv: string[], config: Config);
|
|
6
|
+
webhookType(context: {
|
|
7
|
+
pipeline?: string;
|
|
8
|
+
app?: string;
|
|
9
|
+
}): {
|
|
10
|
+
path: string;
|
|
11
|
+
display: string;
|
|
12
|
+
};
|
|
13
|
+
}
|