heroku 9.3.3-beta.0 → 10.0.0-alpha.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 +1 -0
- package/lib/commands/access/index.js +1 -1
- package/lib/commands/apps/errors.js +1 -1
- package/lib/commands/apps/favorites/add.js +1 -1
- package/lib/commands/buildpacks/add.js +1 -1
- package/lib/commands/buildpacks/info.js +1 -1
- package/lib/commands/buildpacks/set.js +1 -1
- package/lib/commands/buildpacks/versions.js +1 -1
- package/lib/commands/logs.d.ts +5 -3
- package/lib/commands/logs.js +64 -23
- package/lib/commands/members/index.js +1 -1
- package/lib/commands/orgs/open.js +1 -1
- package/lib/commands/pg/copy.js +1 -1
- package/lib/commands/pipelines/promote.js +3 -3
- package/lib/commands/ps/restart.d.ts +2 -1
- package/lib/commands/ps/restart.js +43 -11
- package/lib/commands/ps/stop.d.ts +3 -2
- package/lib/commands/ps/stop.js +40 -9
- package/lib/commands/ps/type.js +4 -4
- package/lib/commands/spaces/create.d.ts +6 -5
- package/lib/commands/spaces/create.js +24 -10
- package/lib/commands/spaces/index.d.ts +2 -2
- package/lib/commands/spaces/index.js +6 -1
- package/lib/commands/spaces/info.js +5 -3
- package/lib/commands/spaces/wait.js +5 -3
- package/lib/commands/telemetry/add.d.ts +17 -0
- package/lib/commands/telemetry/add.js +60 -0
- package/lib/commands/telemetry/index.d.ts +13 -0
- package/lib/commands/telemetry/index.js +49 -0
- package/lib/commands/telemetry/info.d.ts +10 -0
- package/lib/commands/telemetry/info.js +24 -0
- package/lib/commands/telemetry/remove.d.ts +15 -0
- package/lib/commands/telemetry/remove.js +63 -0
- package/lib/commands/telemetry/update.d.ts +16 -0
- package/lib/commands/telemetry/update.js +60 -0
- package/lib/file.js +0 -2
- package/lib/lib/apps/generation.d.ts +4 -0
- package/lib/lib/apps/generation.js +24 -0
- package/lib/lib/run/colorize.js +1 -1
- package/lib/lib/run/log-displayer.d.ts +3 -2
- package/lib/lib/run/log-displayer.js +45 -33
- package/lib/lib/spaces/spaces.d.ts +4 -2
- package/lib/lib/spaces/spaces.js +2 -1
- package/lib/lib/telemetry/util.d.ts +3 -0
- package/lib/lib/telemetry/util.js +29 -0
- package/oclif.manifest.json +406 -61
- package/package.json +6 -6
- package/lib/lib/run/line-transform.d.ts +0 -4
- package/lib/lib/run/line-transform.js +0 -26
package/README.md
CHANGED
|
@@ -71,6 +71,7 @@ For other issues, [submit a support ticket](https://help.heroku.com/).
|
|
|
71
71
|
* [`heroku spaces`](docs/spaces.md) - list available spaces
|
|
72
72
|
* [`heroku status`](docs/status.md) - display current status of the Heroku platform
|
|
73
73
|
* [`heroku teams`](docs/teams.md) - manage teams
|
|
74
|
+
* [`heroku telemetry`](docs/telemetry.md) - list telemetry drains
|
|
74
75
|
* [`heroku update`](docs/update.md) - update the Heroku CLI
|
|
75
76
|
* [`heroku version`](docs/version.md)
|
|
76
77
|
* [`heroku webhooks`](docs/webhooks.md) - list webhooks on an app
|
|
@@ -48,7 +48,7 @@ function buildCollaboratorsArray(collaboratorsRaw, admins) {
|
|
|
48
48
|
class AccessIndex extends command_1.Command {
|
|
49
49
|
async run() {
|
|
50
50
|
var _a, _b;
|
|
51
|
-
const { flags
|
|
51
|
+
const { flags } = await this.parse(AccessIndex);
|
|
52
52
|
const { app: appName, json } = flags;
|
|
53
53
|
const { body: app } = await this.heroku.get(`/apps/${appName}`);
|
|
54
54
|
let { body: collaborators } = await this.heroku.get(`/apps/${appName}/collaborators`);
|
|
@@ -37,7 +37,7 @@ const sumErrors = (errors) => {
|
|
|
37
37
|
class Errors extends command_1.Command {
|
|
38
38
|
async run() {
|
|
39
39
|
const { flags } = await this.parse(Errors);
|
|
40
|
-
const hours = Number.parseInt(flags.hours);
|
|
40
|
+
const hours = Number.parseInt(flags.hours, 10);
|
|
41
41
|
const NOW = new Date().toISOString();
|
|
42
42
|
const YESTERDAY = new Date(Date.now() - (hours * 60 * 60 * 1000)).toISOString();
|
|
43
43
|
const DATE_QUERY = `start_time=${YESTERDAY}&end_time=${NOW}&step=1h`;
|
|
@@ -9,7 +9,7 @@ class Add extends command_1.Command {
|
|
|
9
9
|
const { app } = flags;
|
|
10
10
|
core_1.ux.action.start(`Adding ${color_1.default.app(app)} to favorites`);
|
|
11
11
|
const { body: favorites } = await this.heroku.get('/favorites?type=app', { hostname: 'particleboard.heroku.com' });
|
|
12
|
-
if (favorites.
|
|
12
|
+
if (favorites.some(f => f.resource_name === app)) {
|
|
13
13
|
throw new Error(`${color_1.default.app(app)} is already a favorite app.`);
|
|
14
14
|
}
|
|
15
15
|
try {
|
|
@@ -17,7 +17,7 @@ class Add extends command_1.Command {
|
|
|
17
17
|
spliceIndex = buildpacks.length;
|
|
18
18
|
}
|
|
19
19
|
else {
|
|
20
|
-
// eslint-disable-next-line unicorn/no-array-
|
|
20
|
+
// eslint-disable-next-line unicorn/no-array-method-this-argument
|
|
21
21
|
const foundIndex = buildpackCommand.findIndex(buildpacks, flags.index);
|
|
22
22
|
spliceIndex = (foundIndex === -1) ? buildpacks.length : foundIndex;
|
|
23
23
|
}
|
|
@@ -9,7 +9,7 @@ class Info extends command_1.Command {
|
|
|
9
9
|
const { args } = await this.parse(Info);
|
|
10
10
|
const registry = new buildpack_registry_1.BuildpackRegistry();
|
|
11
11
|
true_myth_1.Result.match({
|
|
12
|
-
Ok:
|
|
12
|
+
Ok: () => { },
|
|
13
13
|
Err: err => {
|
|
14
14
|
this.error(`Could not publish the buildpack.\n${err}`);
|
|
15
15
|
},
|
|
@@ -17,7 +17,7 @@ class Set extends command_1.Command {
|
|
|
17
17
|
spliceIndex = 0;
|
|
18
18
|
}
|
|
19
19
|
else {
|
|
20
|
-
// eslint-disable-next-line unicorn/no-array-
|
|
20
|
+
// eslint-disable-next-line unicorn/no-array-method-this-argument
|
|
21
21
|
const foundIndex = buildpackCommand.findIndex(buildpacks, flags.index);
|
|
22
22
|
spliceIndex = (foundIndex === -1) ? buildpacks.length : foundIndex;
|
|
23
23
|
}
|
package/lib/commands/logs.d.ts
CHANGED
|
@@ -4,13 +4,15 @@ export default class Logs extends Command {
|
|
|
4
4
|
static examples: string[];
|
|
5
5
|
static flags: {
|
|
6
6
|
app: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
7
|
-
|
|
7
|
+
'dyno-name': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
8
|
+
'force-colors': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
9
|
+
'no-color': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
8
10
|
num: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
9
11
|
ps: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
10
|
-
|
|
12
|
+
remote: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
11
13
|
source: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
12
14
|
tail: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
13
|
-
'
|
|
15
|
+
'process-type': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
14
16
|
};
|
|
15
17
|
run(): Promise<void>;
|
|
16
18
|
}
|
package/lib/commands/logs.js
CHANGED
|
@@ -1,45 +1,86 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
|
4
|
-
// tslint:disable:file-name-casing
|
|
5
3
|
const color_1 = require("@heroku-cli/color");
|
|
6
4
|
const command_1 = require("@heroku-cli/command");
|
|
7
5
|
const completions_1 = require("@heroku-cli/command/lib/completions");
|
|
8
6
|
const log_displayer_1 = require("../lib/run/log-displayer");
|
|
7
|
+
const tsheredoc_1 = require("tsheredoc");
|
|
9
8
|
class Logs extends command_1.Command {
|
|
10
9
|
async run() {
|
|
11
10
|
const { flags } = await this.parse(Logs);
|
|
12
|
-
|
|
11
|
+
const { app, 'dyno-name': dyno, 'force-colors': forceColors, num, ps, source, tail, 'process-type': type } = flags;
|
|
12
|
+
if (forceColors)
|
|
13
|
+
color_1.default.enabled = true;
|
|
13
14
|
await (0, log_displayer_1.default)(this.heroku, {
|
|
14
|
-
app
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
tail
|
|
19
|
-
|
|
15
|
+
app,
|
|
16
|
+
dyno,
|
|
17
|
+
lines: num || 100,
|
|
18
|
+
source,
|
|
19
|
+
tail,
|
|
20
|
+
type: type || ps,
|
|
20
21
|
});
|
|
21
22
|
}
|
|
22
23
|
}
|
|
23
24
|
exports.default = Logs;
|
|
24
|
-
Logs.description =
|
|
25
|
-
|
|
25
|
+
Logs.description = (0, tsheredoc_1.default) `
|
|
26
|
+
display recent log output
|
|
27
|
+
disable colors with --no-color, HEROKU_LOGS_COLOR=0, or HEROKU_COLOR=0
|
|
28
|
+
`;
|
|
26
29
|
Logs.examples = [
|
|
27
|
-
'
|
|
28
|
-
'
|
|
29
|
-
'
|
|
30
|
-
'
|
|
30
|
+
'heroku logs --app=my-app',
|
|
31
|
+
'heroku logs --num=50 --app=my-app',
|
|
32
|
+
'heroku logs --dyno-name=web-123-456 --app=my-app',
|
|
33
|
+
'heroku logs --process-type=web --app=my-app',
|
|
34
|
+
'heroku logs --app=my-app --tail',
|
|
31
35
|
];
|
|
32
36
|
Logs.flags = {
|
|
33
37
|
app: command_1.flags.app({ required: true }),
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
ps: command_1.flags.string({ char: 'p', description: 'hidden alias for dyno', hidden: true }),
|
|
37
|
-
dyno: command_1.flags.string({
|
|
38
|
+
'dyno-name': command_1.flags.string({
|
|
39
|
+
aliases: ['dyno'],
|
|
38
40
|
char: 'd',
|
|
39
|
-
description: 'only show output from this dyno
|
|
41
|
+
description: 'only show output from this dyno (such as "web-123-456" or "worker.2")',
|
|
42
|
+
}),
|
|
43
|
+
'force-colors': command_1.flags.boolean({
|
|
44
|
+
description: 'force use of colors (even on non-tty output)',
|
|
45
|
+
}),
|
|
46
|
+
// supports-color NPM package will parse ARGV looking for flag `--no-color`, but
|
|
47
|
+
// we need to define it here for OClif not to error out on an inexistent flag.
|
|
48
|
+
'no-color': command_1.flags.boolean({
|
|
49
|
+
default: false,
|
|
50
|
+
hidden: true,
|
|
51
|
+
relationships: [
|
|
52
|
+
{ type: 'none', flags: ['force-colors'] },
|
|
53
|
+
],
|
|
54
|
+
}),
|
|
55
|
+
num: command_1.flags.integer({
|
|
56
|
+
char: 'n',
|
|
57
|
+
description: 'number of lines to display (ignored for Fir generation apps)',
|
|
58
|
+
}),
|
|
59
|
+
ps: command_1.flags.string({
|
|
60
|
+
char: 'p',
|
|
61
|
+
hidden: true,
|
|
62
|
+
description: 'hidden alias for type',
|
|
63
|
+
relationships: [
|
|
64
|
+
{ type: 'none', flags: ['dyno-name'] },
|
|
65
|
+
],
|
|
66
|
+
completion: completions_1.ProcessTypeCompletion,
|
|
67
|
+
}),
|
|
68
|
+
remote: command_1.flags.remote(),
|
|
69
|
+
source: command_1.flags.string({
|
|
70
|
+
char: 's',
|
|
71
|
+
description: 'only show output from this source (such as "app" or "heroku")',
|
|
72
|
+
}),
|
|
73
|
+
tail: command_1.flags.boolean({
|
|
74
|
+
char: 't',
|
|
75
|
+
default: false,
|
|
76
|
+
description: 'continually stream logs (defaults to true for Fir generation apps)',
|
|
77
|
+
}),
|
|
78
|
+
'process-type': command_1.flags.string({
|
|
79
|
+
char: 'p',
|
|
80
|
+
description: 'only show output from this process type (such as "web" or "worker")',
|
|
81
|
+
relationships: [
|
|
82
|
+
{ type: 'none', flags: ['dyno-name', 'ps'] },
|
|
83
|
+
],
|
|
40
84
|
completion: completions_1.ProcessTypeCompletion,
|
|
41
85
|
}),
|
|
42
|
-
source: command_1.flags.string({ char: 's', description: 'only show output from this source (such as "app" or "heroku")' }),
|
|
43
|
-
tail: command_1.flags.boolean({ char: 't', description: 'continually stream logs' }),
|
|
44
|
-
'force-colors': command_1.flags.boolean({ description: 'force use of colors (even on non-tty output)' }),
|
|
45
86
|
};
|
|
@@ -29,7 +29,7 @@ class MembersIndex extends command_1.Command {
|
|
|
29
29
|
let teamInvites = [];
|
|
30
30
|
if (teamInfo.type === 'team') {
|
|
31
31
|
const { body: orgFeatures } = await this.heroku.get(`/teams/${team}/features`);
|
|
32
|
-
if (orgFeatures.
|
|
32
|
+
if (orgFeatures.some((feature => feature.name === 'team-invite-acceptance' && feature.enabled))) {
|
|
33
33
|
const invitesResponse = await this.heroku.get(`/teams/${team}/invitations`, { headers: {
|
|
34
34
|
Accept: 'application/vnd.heroku+json; version=3.team-invitations',
|
|
35
35
|
},
|
|
@@ -10,7 +10,7 @@ class OrgsOpen extends command_1.Command {
|
|
|
10
10
|
await open(url);
|
|
11
11
|
}
|
|
12
12
|
async run() {
|
|
13
|
-
const { flags
|
|
13
|
+
const { flags } = await this.parse(OrgsOpen);
|
|
14
14
|
const team = flags.team;
|
|
15
15
|
const { body: org } = await this.heroku.get(`/teams/${team}`);
|
|
16
16
|
await OrgsOpen.openUrl(`https://dashboard.heroku.com/teams/${org.name}`);
|
package/lib/commands/pg/copy.js
CHANGED
|
@@ -38,7 +38,7 @@ class Copy extends command_1.Command {
|
|
|
38
38
|
const { flags, args } = await this.parse(Copy);
|
|
39
39
|
const { 'wait-interval': waitInterval, verbose, confirm, app } = flags;
|
|
40
40
|
const pgbackups = (0, backups_1.default)(app, this.heroku);
|
|
41
|
-
const interval = Math.max(3, Number.parseInt(waitInterval || '0')) || 3;
|
|
41
|
+
const interval = Math.max(3, Number.parseInt(waitInterval || '0', 10)) || 3;
|
|
42
42
|
const [source, target] = await Promise.all([getAttachmentInfo(this.heroku, args.source, app), getAttachmentInfo(this.heroku, args.target, app)]);
|
|
43
43
|
if (source.url === target.url)
|
|
44
44
|
throw new Error('Cannot copy database onto itself');
|
|
@@ -35,7 +35,7 @@ function isFailed(promotionTarget) {
|
|
|
35
35
|
}
|
|
36
36
|
function pollPromotionStatus(heroku, id, needsReleaseCommand) {
|
|
37
37
|
return heroku.get(`/pipeline-promotions/${id}/promotion-targets`).then(function ({ body: targets }) {
|
|
38
|
-
if (targets.every(isComplete)) {
|
|
38
|
+
if (targets.every(isComplete)) {
|
|
39
39
|
return targets;
|
|
40
40
|
}
|
|
41
41
|
//
|
|
@@ -98,7 +98,7 @@ async function getRelease(heroku, app, releaseId) {
|
|
|
98
98
|
return release;
|
|
99
99
|
}
|
|
100
100
|
async function streamReleaseCommand(heroku, targets, promotion) {
|
|
101
|
-
if (targets.length !== 1 || targets.every(isComplete)) {
|
|
101
|
+
if (targets.length !== 1 || targets.every(isComplete)) {
|
|
102
102
|
return pollPromotionStatus(heroku, promotion.id, false);
|
|
103
103
|
}
|
|
104
104
|
const target = targets[0];
|
|
@@ -190,7 +190,7 @@ class Promote extends command_1.Command {
|
|
|
190
190
|
memo[app.name] = details;
|
|
191
191
|
return memo;
|
|
192
192
|
}, {});
|
|
193
|
-
if (promotionTargets.every(isSucceeded)) {
|
|
193
|
+
if (promotionTargets.every(isSucceeded)) {
|
|
194
194
|
core_1.ux.log('\nPromotion successful');
|
|
195
195
|
}
|
|
196
196
|
else {
|
|
@@ -5,13 +5,14 @@ export default class Restart extends Command {
|
|
|
5
5
|
static aliases: string[];
|
|
6
6
|
static hiddenAliases: string[];
|
|
7
7
|
static examples: string[];
|
|
8
|
-
static help: string;
|
|
9
8
|
static args: {
|
|
10
9
|
dyno: import("@oclif/core/lib/interfaces/parser").Arg<string | undefined, Record<string, unknown>>;
|
|
11
10
|
};
|
|
12
11
|
static flags: {
|
|
13
12
|
app: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
14
13
|
remote: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
14
|
+
'dyno-name': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
15
|
+
'process-type': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
15
16
|
};
|
|
16
17
|
run(): Promise<void>;
|
|
17
18
|
}
|
|
@@ -3,36 +3,68 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
const command_1 = require("@heroku-cli/command");
|
|
4
4
|
const color_1 = require("@heroku-cli/color");
|
|
5
5
|
const core_1 = require("@oclif/core");
|
|
6
|
+
const completions_1 = require("@heroku-cli/command/lib/completions");
|
|
7
|
+
const tsheredoc_1 = require("tsheredoc");
|
|
6
8
|
class Restart extends command_1.Command {
|
|
7
9
|
async run() {
|
|
8
10
|
const { args, flags } = await this.parse(Restart);
|
|
9
11
|
const app = flags.app;
|
|
10
|
-
const dyno = args.dyno;
|
|
12
|
+
const dyno = flags['dyno-name'] || args.dyno;
|
|
13
|
+
const type = flags['process-type'];
|
|
11
14
|
let msg = 'Restarting';
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
let restartUrl;
|
|
16
|
+
if (type) {
|
|
17
|
+
msg += ` all ${color_1.default.cyan(type)} dynos`;
|
|
18
|
+
restartUrl = `/apps/${app}/formations/${encodeURIComponent(type)}`;
|
|
19
|
+
}
|
|
20
|
+
else if (dyno) {
|
|
21
|
+
if (args.dyno) {
|
|
22
|
+
core_1.ux.warn(`DYNO is a deprecated argument. Use ${color_1.default.cmd('--dyno-name')} or ${color_1.default.cmd('--process-type')} instead.`);
|
|
23
|
+
}
|
|
24
|
+
msg += ` dyno ${color_1.default.cyan(dyno)}`;
|
|
25
|
+
restartUrl = `/apps/${app}/dynos/${encodeURIComponent(dyno)}`;
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
msg += ' all dynos';
|
|
29
|
+
restartUrl = `/apps/${app}/dynos`;
|
|
30
|
+
}
|
|
15
31
|
msg += ` on ${color_1.default.app(app)}`;
|
|
16
32
|
core_1.ux.action.start(msg);
|
|
17
|
-
await this.heroku.delete(
|
|
33
|
+
await this.heroku.delete(restartUrl, {
|
|
34
|
+
headers: {
|
|
35
|
+
Accept: 'application/vnd.heroku+json; version=3.sdk',
|
|
36
|
+
},
|
|
37
|
+
});
|
|
18
38
|
core_1.ux.action.stop();
|
|
19
39
|
}
|
|
20
40
|
}
|
|
21
41
|
exports.default = Restart;
|
|
22
|
-
Restart.description =
|
|
42
|
+
Restart.description = (0, tsheredoc_1.default)(`
|
|
43
|
+
restart an app dyno or process type
|
|
44
|
+
if neither --dyno nor --type are specified, restarts all dynos on app
|
|
45
|
+
`);
|
|
23
46
|
Restart.topic = 'ps';
|
|
24
47
|
Restart.aliases = ['dyno:restart'];
|
|
25
48
|
Restart.hiddenAliases = ['restart'];
|
|
26
49
|
Restart.examples = [
|
|
27
|
-
'$ heroku ps:restart web.1',
|
|
28
|
-
'$ heroku ps:restart web',
|
|
29
|
-
'$ heroku ps:restart',
|
|
50
|
+
'$ heroku ps:restart --app myapp --dyno-name web.1',
|
|
51
|
+
'$ heroku ps:restart --app myapp --process-type web',
|
|
52
|
+
'$ heroku ps:restart --app myapp',
|
|
30
53
|
];
|
|
31
|
-
Restart.help = 'if DYNO is not specified, restarts all dynos on app';
|
|
32
54
|
Restart.args = {
|
|
33
|
-
dyno: core_1.Args.string({ required: false }),
|
|
55
|
+
dyno: core_1.Args.string({ description: 'name of the dyno to restart', required: false, deprecated: true }),
|
|
34
56
|
};
|
|
35
57
|
Restart.flags = {
|
|
36
58
|
app: command_1.flags.app({ required: true }),
|
|
37
59
|
remote: command_1.flags.remote(),
|
|
60
|
+
'dyno-name': command_1.flags.string({
|
|
61
|
+
char: 'd',
|
|
62
|
+
description: 'name of the dyno to restart',
|
|
63
|
+
}),
|
|
64
|
+
'process-type': command_1.flags.string({
|
|
65
|
+
char: 'p',
|
|
66
|
+
description: 'name of the process type to restart',
|
|
67
|
+
completion: completions_1.ProcessTypeCompletion,
|
|
68
|
+
exclusive: ['dyno-name'],
|
|
69
|
+
}),
|
|
38
70
|
};
|
|
@@ -5,13 +5,14 @@ export default class Stop extends Command {
|
|
|
5
5
|
static aliases: string[];
|
|
6
6
|
static hiddenAliases: string[];
|
|
7
7
|
static examples: string[];
|
|
8
|
-
static help: string;
|
|
9
8
|
static args: {
|
|
10
|
-
dyno: import("@oclif/core/lib/interfaces/parser").Arg<string, Record<string, unknown>>;
|
|
9
|
+
dyno: import("@oclif/core/lib/interfaces/parser").Arg<string | undefined, Record<string, unknown>>;
|
|
11
10
|
};
|
|
12
11
|
static flags: {
|
|
13
12
|
app: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
14
13
|
remote: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
14
|
+
'dyno-name': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
15
|
+
'process-type': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
15
16
|
};
|
|
16
17
|
run(): Promise<void>;
|
|
17
18
|
}
|
package/lib/commands/ps/stop.js
CHANGED
|
@@ -3,31 +3,62 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
const command_1 = require("@heroku-cli/command");
|
|
4
4
|
const color_1 = require("@heroku-cli/color");
|
|
5
5
|
const core_1 = require("@oclif/core");
|
|
6
|
+
const completions_1 = require("@heroku-cli/command/lib/completions");
|
|
7
|
+
const tsheredoc_1 = require("tsheredoc");
|
|
6
8
|
class Stop extends command_1.Command {
|
|
7
9
|
async run() {
|
|
8
10
|
const { args, flags } = await this.parse(Stop);
|
|
9
11
|
const app = flags.app;
|
|
10
|
-
const dyno = args.dyno;
|
|
11
|
-
const type =
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
const dyno = flags['dyno-name'] || args.dyno;
|
|
13
|
+
const type = flags['process-type'];
|
|
14
|
+
let msg = 'Stopping';
|
|
15
|
+
let stopUrl = '';
|
|
16
|
+
if (type) {
|
|
17
|
+
msg += ` all ${color_1.default.cyan(type)} dynos`;
|
|
18
|
+
stopUrl = `/apps/${app}/formations/${encodeURIComponent(type)}/actions/stop`;
|
|
19
|
+
}
|
|
20
|
+
else if (dyno) {
|
|
21
|
+
if (args.dyno) {
|
|
22
|
+
core_1.ux.warn(`DYNO is a deprecated argument. Use ${color_1.default.cmd('--dyno-name')} or ${color_1.default.cmd('--process-type')} instead.`);
|
|
23
|
+
}
|
|
24
|
+
msg += ` dyno ${color_1.default.cyan(dyno)}`;
|
|
25
|
+
stopUrl = `/apps/${app}/dynos/${encodeURIComponent(dyno)}/actions/stop`;
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
core_1.ux.error((0, tsheredoc_1.default)(`
|
|
29
|
+
Please specify a process type or dyno name to stop.
|
|
30
|
+
See more help with --help
|
|
31
|
+
`));
|
|
32
|
+
}
|
|
33
|
+
msg += ` on ${color_1.default.app(app)}`;
|
|
34
|
+
core_1.ux.action.start(msg);
|
|
35
|
+
await this.heroku.post(stopUrl, { headers: { Accept: 'application/vnd.heroku+json; version=3.sdk' } });
|
|
14
36
|
core_1.ux.action.stop();
|
|
15
37
|
}
|
|
16
38
|
}
|
|
17
39
|
exports.default = Stop;
|
|
18
|
-
Stop.description = 'stop app dyno';
|
|
40
|
+
Stop.description = 'stop an app dyno or process type';
|
|
19
41
|
Stop.topic = 'ps';
|
|
20
42
|
Stop.aliases = ['dyno:stop', 'ps:kill', 'dyno:kill'];
|
|
21
43
|
Stop.hiddenAliases = ['stop', 'kill'];
|
|
22
44
|
Stop.examples = [
|
|
23
|
-
'$ heroku ps:stop run.1828',
|
|
24
|
-
'$ heroku ps:stop run',
|
|
45
|
+
'$ heroku ps:stop --app myapp --dyno-name run.1828',
|
|
46
|
+
'$ heroku ps:stop --app myapp --process-type run',
|
|
25
47
|
];
|
|
26
|
-
Stop.help = 'stop app dyno or dyno type';
|
|
27
48
|
Stop.args = {
|
|
28
|
-
dyno: core_1.Args.string({ required: true }),
|
|
49
|
+
dyno: core_1.Args.string({ description: 'name of the dyno to stop', required: false, deprecated: true }),
|
|
29
50
|
};
|
|
30
51
|
Stop.flags = {
|
|
31
52
|
app: command_1.flags.app({ required: true }),
|
|
32
53
|
remote: command_1.flags.remote(),
|
|
54
|
+
'dyno-name': command_1.flags.string({
|
|
55
|
+
char: 'd',
|
|
56
|
+
description: 'name of the dyno to stop',
|
|
57
|
+
}),
|
|
58
|
+
'process-type': command_1.flags.string({
|
|
59
|
+
char: 'p',
|
|
60
|
+
description: 'name of the process type to stop',
|
|
61
|
+
completion: completions_1.ProcessTypeCompletion,
|
|
62
|
+
exclusive: ['dyno-name'],
|
|
63
|
+
}),
|
|
33
64
|
};
|
package/lib/commands/ps/type.js
CHANGED
|
@@ -51,7 +51,6 @@ const displayFormation = async (heroku, app) => {
|
|
|
51
51
|
}
|
|
52
52
|
return {
|
|
53
53
|
// this rule does not realize `size` isn't used on an array
|
|
54
|
-
/* eslint-disable unicorn/explicit-length-check */
|
|
55
54
|
type: color_1.default.green(d.type || ''),
|
|
56
55
|
size: color_1.default.cyan(d.size),
|
|
57
56
|
qty: color_1.default.yellow(`${d.quantity}`),
|
|
@@ -73,7 +72,7 @@ const displayFormation = async (heroku, app) => {
|
|
|
73
72
|
if (formation.length === 0) {
|
|
74
73
|
throw emptyFormationErr(app);
|
|
75
74
|
}
|
|
76
|
-
core_1.ux.styledHeader('
|
|
75
|
+
core_1.ux.styledHeader('Process Types');
|
|
77
76
|
core_1.ux.table(formationTableData, {
|
|
78
77
|
type: {},
|
|
79
78
|
size: {},
|
|
@@ -81,6 +80,7 @@ const displayFormation = async (heroku, app) => {
|
|
|
81
80
|
'cost/hour': {},
|
|
82
81
|
'max cost/month': {},
|
|
83
82
|
});
|
|
83
|
+
core_1.ux.log();
|
|
84
84
|
core_1.ux.styledHeader('Dyno Totals');
|
|
85
85
|
core_1.ux.table(dynoTotalsTableData, {
|
|
86
86
|
type: {},
|
|
@@ -99,12 +99,12 @@ class Type extends command_1.Command {
|
|
|
99
99
|
if (!argv || argv.length === 0)
|
|
100
100
|
return [];
|
|
101
101
|
const { body: formation } = await this.heroku.get(`/apps/${app}/formation`);
|
|
102
|
-
if (argv.
|
|
102
|
+
if (argv.some(a => a.match(/=/))) {
|
|
103
103
|
return (0, lodash_1.compact)(argv.map(arg => {
|
|
104
104
|
const match = arg.match(/^([a-zA-Z0-9_]+)=([\w-]+)$/);
|
|
105
105
|
const type = match && match[1];
|
|
106
106
|
const size = match && match[2];
|
|
107
|
-
if (!type || !size || !formation.
|
|
107
|
+
if (!type || !size || !formation.some(p => p.type === type)) {
|
|
108
108
|
throw new Error(`Type ${color_1.default.red(type || '')} not found in process formation.\nTypes: ${color_1.default.yellow(formation.map(f => f.type)
|
|
109
109
|
.join(', '))}`);
|
|
110
110
|
}
|
|
@@ -4,15 +4,16 @@ export default class Create extends Command {
|
|
|
4
4
|
static description: string;
|
|
5
5
|
static examples: string[];
|
|
6
6
|
static flags: {
|
|
7
|
-
space: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
8
7
|
channel: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
9
|
-
|
|
8
|
+
cidr: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
9
|
+
'data-cidr': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
10
10
|
features: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
11
|
+
generation: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
12
|
+
'kpi-url': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
11
13
|
'log-drain-url': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
14
|
+
region: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
12
15
|
shield: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
13
|
-
|
|
14
|
-
'kpi-url': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
15
|
-
'data-cidr': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
16
|
+
space: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
16
17
|
team: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
17
18
|
};
|
|
18
19
|
static args: {
|
|
@@ -10,7 +10,7 @@ const parsers_1 = require("../../lib/spaces/parsers");
|
|
|
10
10
|
class Create extends command_1.Command {
|
|
11
11
|
async run() {
|
|
12
12
|
const { flags, args } = await this.parse(Create);
|
|
13
|
-
const { channel, region, features, 'log-drain-url': logDrainUrl, shield, cidr, 'kpi-url': kpiUrl, 'data-cidr': dataCidr, team } = flags;
|
|
13
|
+
const { channel, region, features, generation, 'log-drain-url': logDrainUrl, shield, cidr, 'kpi-url': kpiUrl, 'data-cidr': dataCidr, team } = flags;
|
|
14
14
|
const spaceName = flags.space || args.space;
|
|
15
15
|
if (!spaceName) {
|
|
16
16
|
core_1.ux.error((0, tsheredoc_1.default) `
|
|
@@ -23,9 +23,21 @@ class Create extends command_1.Command {
|
|
|
23
23
|
const spaceType = shield ? 'Shield' : 'Standard';
|
|
24
24
|
core_1.ux.action.start(`Creating space ${color_1.default.green(spaceName)} in team ${color_1.default.cyan(team)}`);
|
|
25
25
|
const { body: space } = await this.heroku.post('/spaces', {
|
|
26
|
+
headers: {
|
|
27
|
+
Accept: 'application/vnd.heroku+json; version=3.sdk',
|
|
28
|
+
},
|
|
26
29
|
body: {
|
|
27
|
-
|
|
28
|
-
|
|
30
|
+
channel_name: channel,
|
|
31
|
+
cidr,
|
|
32
|
+
data_cidr: dataCidr,
|
|
33
|
+
features: (0, parsers_1.splitCsv)(features),
|
|
34
|
+
generation,
|
|
35
|
+
kpi_url: kpiUrl,
|
|
36
|
+
log_drain_url: logDrainUrl,
|
|
37
|
+
name: spaceName,
|
|
38
|
+
region,
|
|
39
|
+
shield,
|
|
40
|
+
team,
|
|
29
41
|
},
|
|
30
42
|
});
|
|
31
43
|
core_1.ux.action.stop();
|
|
@@ -33,8 +45,8 @@ class Create extends command_1.Command {
|
|
|
33
45
|
core_1.ux.warn(`Use ${color_1.default.cmd('heroku spaces:wait')} to track allocation.`);
|
|
34
46
|
core_1.ux.styledHeader(space.name);
|
|
35
47
|
core_1.ux.styledObject({
|
|
36
|
-
ID: space.id, Team: space.team.name, Region: space.region.name, CIDR: space.cidr, 'Data CIDR': space.data_cidr, State: space.state, Shield: (0, spaces_1.displayShieldState)(space), 'Created at': space.created_at,
|
|
37
|
-
}, ['ID', 'Team', 'Region', 'CIDR', 'Data CIDR', 'State', 'Shield', 'Created at']);
|
|
48
|
+
ID: space.id, Team: space.team.name, Region: space.region.name, CIDR: space.cidr, 'Data CIDR': space.data_cidr, State: space.state, Shield: (0, spaces_1.displayShieldState)(space), Generation: space.generation, 'Created at': space.created_at,
|
|
49
|
+
}, ['ID', 'Team', 'Region', 'CIDR', 'Data CIDR', 'State', 'Shield', 'Generation', 'Created at']);
|
|
38
50
|
}
|
|
39
51
|
}
|
|
40
52
|
exports.default = Create;
|
|
@@ -54,18 +66,20 @@ Create.examples = [(0, tsheredoc_1.default) `
|
|
|
54
66
|
CIDR: 10.0.0.0/16
|
|
55
67
|
Data CIDR: 172.23.0.0/20
|
|
56
68
|
State: allocating
|
|
69
|
+
Generation: fir
|
|
57
70
|
Created at: 2016-01-06T03:23:13Z
|
|
58
71
|
`];
|
|
59
72
|
Create.flags = {
|
|
60
|
-
space: command_1.flags.string({ char: 's', description: 'name of space to create' }),
|
|
61
73
|
channel: command_1.flags.string({ hidden: true }),
|
|
62
|
-
|
|
74
|
+
cidr: command_1.flags.string({ description: 'RFC-1918 CIDR the space will use' }),
|
|
75
|
+
'data-cidr': command_1.flags.string({ description: 'RFC-1918 CIDR used by Heroku Data resources for the space' }),
|
|
63
76
|
features: command_1.flags.string({ hidden: true, description: 'a list of features separated by commas' }),
|
|
77
|
+
generation: command_1.flags.string({ description: 'generation for space', default: 'cedar', options: ['cedar', 'fir'] }),
|
|
78
|
+
'kpi-url': command_1.flags.string({ hidden: true, description: 'self-managed KPI endpoint to use' }),
|
|
64
79
|
'log-drain-url': command_1.flags.string({ hidden: true, description: 'direct log drain url' }),
|
|
80
|
+
region: command_1.flags.string({ description: 'region name', completion: completions_1.RegionCompletion }),
|
|
65
81
|
shield: command_1.flags.boolean({ hidden: true, description: 'create a Shield space' }),
|
|
66
|
-
|
|
67
|
-
'kpi-url': command_1.flags.string({ hidden: true, description: 'self-managed KPI endpoint to use' }),
|
|
68
|
-
'data-cidr': command_1.flags.string({ description: 'RFC-1918 CIDR used by Heroku Data resources for the space' }),
|
|
82
|
+
space: command_1.flags.string({ char: 's', description: 'name of space to create' }),
|
|
69
83
|
team: command_1.flags.team({ required: true }),
|
|
70
84
|
};
|
|
71
85
|
Create.args = {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Command } from '@heroku-cli/command';
|
|
2
|
-
import
|
|
3
|
-
declare type SpaceArray = Array<Required<
|
|
2
|
+
import { Space } from '../../lib/types/fir';
|
|
3
|
+
declare type SpaceArray = Array<Required<Space>>;
|
|
4
4
|
export default class Index extends Command {
|
|
5
5
|
static topic: string;
|
|
6
6
|
static description: string;
|
|
@@ -7,7 +7,11 @@ class Index extends command_1.Command {
|
|
|
7
7
|
async run() {
|
|
8
8
|
const { flags } = await this.parse(Index);
|
|
9
9
|
const { team, json } = flags;
|
|
10
|
-
let { body: spaces } = await this.heroku.get('/spaces'
|
|
10
|
+
let { body: spaces } = await this.heroku.get('/spaces', {
|
|
11
|
+
headers: {
|
|
12
|
+
Accept: 'application/vnd.heroku+json; version=3.sdk',
|
|
13
|
+
},
|
|
14
|
+
});
|
|
11
15
|
if (team) {
|
|
12
16
|
spaces = spaces.filter(s => s.team.name === team);
|
|
13
17
|
}
|
|
@@ -39,6 +43,7 @@ class Index extends command_1.Command {
|
|
|
39
43
|
Team: { get: space => space.team.name },
|
|
40
44
|
Region: { get: space => space.region.name },
|
|
41
45
|
State: { get: space => space.state },
|
|
46
|
+
Generation: { get: space => space.generation },
|
|
42
47
|
createdAt: {
|
|
43
48
|
header: 'Created At',
|
|
44
49
|
get: space => space.created_at,
|