heroku 8.7.1 → 9.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 +4 -1
- package/lib/commands/apps/create.d.ts +28 -0
- package/lib/commands/apps/create.js +194 -0
- package/lib/commands/apps/destroy.d.ts +14 -0
- package/lib/commands/apps/destroy.js +46 -0
- package/lib/commands/apps/errors.d.ts +12 -0
- package/lib/commands/apps/errors.js +119 -0
- package/lib/commands/apps/favorites/add.d.ts +9 -0
- package/lib/commands/apps/favorites/add.js +37 -0
- package/lib/commands/apps/favorites/index.d.ts +9 -0
- package/lib/commands/apps/favorites/index.js +25 -0
- package/lib/commands/apps/favorites/remove.d.ts +9 -0
- package/lib/commands/apps/favorites/remove.js +27 -0
- package/lib/commands/apps/index.d.ts +16 -0
- package/lib/commands/apps/index.js +119 -0
- package/lib/commands/apps/info.d.ts +18 -0
- package/lib/commands/apps/info.js +163 -0
- package/lib/commands/apps/open.d.ts +14 -0
- package/lib/commands/apps/open.js +29 -0
- package/lib/commands/apps/rename.d.ts +15 -0
- package/lib/commands/apps/rename.js +50 -0
- package/lib/commands/apps/stacks/index.d.ts +10 -0
- package/lib/commands/apps/stacks/index.js +43 -0
- package/lib/commands/apps/stacks/set.d.ts +14 -0
- package/lib/commands/apps/stacks/set.js +41 -0
- package/lib/commands/auth/logout.js +1 -0
- package/lib/commands/ci/config/get.d.ts +16 -0
- package/lib/commands/ci/config/get.js +37 -0
- package/lib/commands/ci/config/index.d.ts +12 -0
- package/lib/commands/ci/config/index.js +43 -0
- package/lib/commands/ci/config/set.d.ts +12 -0
- package/lib/commands/ci/config/set.js +48 -0
- package/lib/commands/ci/config/unset.d.ts +13 -0
- package/lib/commands/ci/config/unset.js +35 -0
- package/lib/commands/ci/debug.d.ts +13 -0
- package/lib/commands/ci/debug.js +105 -0
- package/lib/commands/ci/index.js +1 -1
- package/lib/commands/ci/info.js +1 -1
- package/lib/commands/ci/last.js +1 -1
- package/lib/commands/ci/migrate-manifest.d.ts +7 -0
- package/lib/commands/ci/migrate-manifest.js +74 -0
- package/lib/commands/ci/open.d.ts +12 -0
- package/lib/commands/ci/open.js +23 -0
- package/lib/commands/ci/rerun.js +1 -1
- package/lib/commands/ci/run.js +1 -1
- package/lib/commands/config/set.d.ts +11 -0
- package/lib/commands/config/set.js +59 -0
- package/lib/commands/domains/index.d.ts +1 -1
- package/lib/commands/drains/add.d.ts +11 -0
- package/lib/commands/drains/add.js +22 -0
- package/lib/commands/drains/index.d.ts +10 -0
- package/lib/commands/drains/index.js +49 -0
- package/lib/commands/drains/remove.d.ts +12 -0
- package/lib/commands/drains/remove.js +21 -0
- package/lib/commands/pipelines/add.js +1 -1
- package/lib/commands/pipelines/connect.js +1 -1
- package/lib/commands/pipelines/create.js +1 -1
- package/lib/commands/pipelines/destroy.js +1 -1
- package/lib/commands/pipelines/diff.js +1 -1
- package/lib/commands/pipelines/info.js +1 -1
- package/lib/commands/pipelines/promote.js +1 -1
- package/lib/commands/pipelines/remove.js +1 -1
- package/lib/commands/pipelines/rename.js +1 -1
- package/lib/commands/pipelines/setup.js +1 -1
- package/lib/commands/pipelines/transfer.js +1 -1
- package/lib/commands/pipelines/update.js +1 -1
- package/lib/lib/{pipelines/api.d.ts → api.d.ts} +10 -5
- package/lib/lib/{pipelines/api.js → api.js} +48 -4
- package/lib/lib/apps/confirm-app.d.ts +1 -0
- package/lib/lib/apps/confirm-app.js +23 -0
- package/lib/lib/apps/error_info.d.ts +7 -0
- package/lib/lib/apps/error_info.js +185 -0
- package/lib/lib/buildpacks/buildpacks.js +3 -4
- package/lib/lib/ci/git.d.ts +7 -1
- package/lib/lib/ci/git.js +44 -1
- package/lib/lib/ci/pipelines.d.ts +3 -3
- package/lib/lib/ci/pipelines.js +10 -9
- package/lib/lib/ci/test-run.d.ts +1 -0
- package/lib/lib/ci/test-run.js +2 -1
- package/lib/lib/ci/validate.d.ts +2 -0
- package/lib/lib/ci/validate.js +10 -0
- package/lib/lib/git/git.d.ts +11 -0
- package/lib/lib/git/git.js +38 -0
- package/lib/lib/git/push.d.ts +1 -0
- package/lib/lib/git/push.js +6 -0
- package/lib/lib/pipelines/disambiguate.js +1 -1
- package/lib/lib/pipelines/ownership.js +1 -1
- package/lib/lib/pipelines/setup/create-apps.d.ts +2 -1
- package/lib/lib/pipelines/setup/create-apps.js +1 -1
- package/lib/lib/pipelines/setup/poll-app-setups.js +1 -1
- package/lib/lib/types/favorites.d.ts +7 -0
- package/lib/lib/types/favorites.js +2 -0
- package/oclif.manifest.json +879 -11
- package/package.json +8 -4
- package/lib/lib/buildpacks/push.d.ts +0 -0
- package/lib/lib/buildpacks/push.js +0 -4
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const command_1 = require("@heroku-cli/command");
|
|
5
|
+
const _ = require("lodash");
|
|
6
|
+
const color_1 = require("@heroku-cli/color");
|
|
7
|
+
const completions_1 = require("@heroku-cli/command/lib/completions");
|
|
8
|
+
function annotateAppName(app) {
|
|
9
|
+
let name = `${app.name}`;
|
|
10
|
+
if (app.locked && app.internal_routing) {
|
|
11
|
+
name = `${app.name} [internal/locked]`;
|
|
12
|
+
}
|
|
13
|
+
else if (app.locked) {
|
|
14
|
+
name = `${app.name} [locked]`;
|
|
15
|
+
}
|
|
16
|
+
else if (app.internal_routing) {
|
|
17
|
+
name = `${app.name} [internal]`;
|
|
18
|
+
}
|
|
19
|
+
return name;
|
|
20
|
+
}
|
|
21
|
+
function regionizeAppName(app) {
|
|
22
|
+
const name = annotateAppName(app);
|
|
23
|
+
if (app.region && app.region.name !== 'us') {
|
|
24
|
+
return `${name} (${color_1.default.green(app.region.name)})`;
|
|
25
|
+
}
|
|
26
|
+
return name;
|
|
27
|
+
}
|
|
28
|
+
function listApps(apps) {
|
|
29
|
+
apps.forEach((app) => core_1.ux.log(regionizeAppName(app)));
|
|
30
|
+
}
|
|
31
|
+
function print(apps, user, space, team) {
|
|
32
|
+
if (apps.length === 0) {
|
|
33
|
+
if (space)
|
|
34
|
+
core_1.ux.log(`There are no apps in space ${color_1.default.green(space)}.`);
|
|
35
|
+
else if (team)
|
|
36
|
+
core_1.ux.log(`There are no apps in team ${color_1.default.magenta(team)}.`);
|
|
37
|
+
else
|
|
38
|
+
core_1.ux.log('You have no apps.');
|
|
39
|
+
}
|
|
40
|
+
else if (space) {
|
|
41
|
+
core_1.ux.styledHeader(`Apps in space ${color_1.default.green(space)}`);
|
|
42
|
+
listApps(apps);
|
|
43
|
+
}
|
|
44
|
+
else if (team) {
|
|
45
|
+
core_1.ux.styledHeader(`Apps in team ${color_1.default.magenta(team)}`);
|
|
46
|
+
listApps(apps);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
apps = _.partition(apps, (app) => app.owner.email === user.email);
|
|
50
|
+
if (apps[0].length > 0) {
|
|
51
|
+
core_1.ux.styledHeader(`${color_1.default.cyan(user.email)} Apps`);
|
|
52
|
+
listApps(apps[0]);
|
|
53
|
+
}
|
|
54
|
+
const columns = {
|
|
55
|
+
name: { get: regionizeAppName },
|
|
56
|
+
email: { get: ({ owner }) => owner.email },
|
|
57
|
+
};
|
|
58
|
+
if (apps[1].length > 0) {
|
|
59
|
+
core_1.ux.styledHeader('Collaborated Apps');
|
|
60
|
+
core_1.ux.table(apps[1], columns, { 'no-header': true });
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
class AppsIndex extends command_1.Command {
|
|
65
|
+
async run() {
|
|
66
|
+
const { flags } = await this.parse(AppsIndex);
|
|
67
|
+
const teamIdentifier = flags.team;
|
|
68
|
+
let team = (!flags.personal && teamIdentifier) ? teamIdentifier : null;
|
|
69
|
+
const space = flags.space;
|
|
70
|
+
const internalRouting = flags['internal-routing'];
|
|
71
|
+
if (space) {
|
|
72
|
+
const teamResponse = await this.heroku.get(`/spaces/${space}`);
|
|
73
|
+
team = teamResponse.body.team.name;
|
|
74
|
+
}
|
|
75
|
+
let path = '/users/~/apps';
|
|
76
|
+
if (team)
|
|
77
|
+
path = `/teams/${team}/apps`;
|
|
78
|
+
else if (flags.all)
|
|
79
|
+
path = '/apps';
|
|
80
|
+
const [appsResponse, userResponse] = await Promise.all([
|
|
81
|
+
this.heroku.get(path),
|
|
82
|
+
this.heroku.get('/account'),
|
|
83
|
+
]);
|
|
84
|
+
let apps = appsResponse.body;
|
|
85
|
+
const user = userResponse.body;
|
|
86
|
+
apps = _.sortBy(apps, 'name');
|
|
87
|
+
if (space) {
|
|
88
|
+
apps = apps.filter((a) => a.space && (a.space.name === space || a.space.id === space));
|
|
89
|
+
}
|
|
90
|
+
if (internalRouting) {
|
|
91
|
+
apps = apps.filter((a) => a.internal_routing);
|
|
92
|
+
}
|
|
93
|
+
if (flags.json) {
|
|
94
|
+
core_1.ux.styledJSON(apps);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
print(apps, user, space, team);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
exports.default = AppsIndex;
|
|
102
|
+
AppsIndex.description = 'list your apps';
|
|
103
|
+
AppsIndex.topic = 'apps';
|
|
104
|
+
AppsIndex.aliases = ['list', 'apps:list'];
|
|
105
|
+
AppsIndex.examples = [
|
|
106
|
+
'$ heroku apps',
|
|
107
|
+
];
|
|
108
|
+
AppsIndex.flags = {
|
|
109
|
+
all: command_1.flags.boolean({ char: 'A', description: 'include apps in all teams' }),
|
|
110
|
+
json: command_1.flags.boolean({ char: 'j', description: 'output in json format' }),
|
|
111
|
+
space: command_1.flags.string({
|
|
112
|
+
char: 's',
|
|
113
|
+
description: 'filter by space',
|
|
114
|
+
completion: completions_1.SpaceCompletion,
|
|
115
|
+
}),
|
|
116
|
+
personal: command_1.flags.boolean({ char: 'p', description: 'list apps in personal account when a default team is set' }),
|
|
117
|
+
'internal-routing': command_1.flags.boolean({ char: 'i', description: 'filter to Internal Web Apps', hidden: true }),
|
|
118
|
+
team: command_1.flags.team(),
|
|
119
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Command } from '@heroku-cli/command';
|
|
2
|
+
export default class AppsInfo extends Command {
|
|
3
|
+
static description: string;
|
|
4
|
+
static topic: string;
|
|
5
|
+
static aliases: string[];
|
|
6
|
+
static examples: string[];
|
|
7
|
+
static help: string;
|
|
8
|
+
static flags: {
|
|
9
|
+
app: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
10
|
+
shell: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
extended: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
12
|
+
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
13
|
+
};
|
|
14
|
+
static args: {
|
|
15
|
+
app: import("@oclif/core/lib/interfaces/parser").Arg<string | undefined, Record<string, unknown>>;
|
|
16
|
+
};
|
|
17
|
+
run(): Promise<void>;
|
|
18
|
+
}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const command_1 = require("@heroku-cli/command");
|
|
5
|
+
const util = require("util");
|
|
6
|
+
const _ = require("lodash");
|
|
7
|
+
const filesize = require('filesize');
|
|
8
|
+
const { countBy, snakeCase } = _;
|
|
9
|
+
function formatDate(date) {
|
|
10
|
+
return date.toISOString();
|
|
11
|
+
}
|
|
12
|
+
async function getInfo(app, client, extended) {
|
|
13
|
+
const promises = [
|
|
14
|
+
client.heroku.get(`/apps/${app}/addons`),
|
|
15
|
+
client.heroku.request(`/apps/${app}`, {
|
|
16
|
+
headers: { Accept: 'application/vnd.heroku+json; version=3.cedar-acm' },
|
|
17
|
+
}),
|
|
18
|
+
client.heroku.get(`/apps/${app}/dynos`).catch(() => ({ body: [] })),
|
|
19
|
+
client.heroku.get(`/apps/${app}/collaborators`).catch(() => ({ body: [] })),
|
|
20
|
+
client.heroku.get(`/apps/${app}/pipeline-couplings`).catch(() => ({ body: null })),
|
|
21
|
+
];
|
|
22
|
+
if (extended) {
|
|
23
|
+
promises.push(client.heroku.get(`/apps/${app}?extended=true`));
|
|
24
|
+
}
|
|
25
|
+
const [{ body: addons }, { body: appWithMoreInfo }, { body: dynos }, { body: collaborators }, { body: pipelineCouplings }, appExtendedResponse,] = await Promise.all(promises);
|
|
26
|
+
const data = {
|
|
27
|
+
addons,
|
|
28
|
+
app: appWithMoreInfo,
|
|
29
|
+
dynos,
|
|
30
|
+
collaborators,
|
|
31
|
+
pipeline_coupling: pipelineCouplings,
|
|
32
|
+
};
|
|
33
|
+
if (appExtendedResponse) {
|
|
34
|
+
data.appExtended = appExtendedResponse.body;
|
|
35
|
+
}
|
|
36
|
+
if (extended) {
|
|
37
|
+
data.appExtended.acm = data.app.acm;
|
|
38
|
+
data.app = data.appExtended;
|
|
39
|
+
delete data.appExtended;
|
|
40
|
+
}
|
|
41
|
+
return data;
|
|
42
|
+
}
|
|
43
|
+
function print(info, addons, collaborators, extended) {
|
|
44
|
+
const data = {};
|
|
45
|
+
data.Addons = addons;
|
|
46
|
+
data.Collaborators = collaborators;
|
|
47
|
+
if (info.app.archived_at)
|
|
48
|
+
data['Archived At'] = formatDate(new Date(info.app.archived_at));
|
|
49
|
+
if (info.app.cron_finished_at)
|
|
50
|
+
data['Cron Finished At'] = formatDate(new Date(info.app.cron_finished_at));
|
|
51
|
+
if (info.app.cron_next_run)
|
|
52
|
+
data['Cron Next Run'] = formatDate(new Date(info.app.cron_next_run));
|
|
53
|
+
if (info.app.database_size)
|
|
54
|
+
data['Database Size'] = filesize(info.app.database_size, { round: 0 });
|
|
55
|
+
if (info.app.create_status !== 'complete')
|
|
56
|
+
data['Create Status'] = info.app.create_status;
|
|
57
|
+
if (info.app.space)
|
|
58
|
+
data.Space = info.app.space.name;
|
|
59
|
+
if (info.app.space && info.app.internal_routing)
|
|
60
|
+
data['Internal Routing'] = info.app.internal_routing;
|
|
61
|
+
if (info.pipeline_coupling)
|
|
62
|
+
data.Pipeline = `${info.pipeline_coupling.pipeline.name} - ${info.pipeline_coupling.stage}`;
|
|
63
|
+
data['Auto Cert Mgmt'] = info.app.acm;
|
|
64
|
+
data['Git URL'] = info.app.git_url;
|
|
65
|
+
data['Web URL'] = info.app.web_url;
|
|
66
|
+
data['Repo Size'] = filesize(info.app.repo_size, { round: 0 });
|
|
67
|
+
data['Slug Size'] = filesize(info.app.slug_size, { round: 0 });
|
|
68
|
+
data.Owner = info.app.owner.email;
|
|
69
|
+
data.Region = info.app.region.name;
|
|
70
|
+
data.Dynos = countBy(info.dynos, 'type');
|
|
71
|
+
data.Stack = (function (app) {
|
|
72
|
+
let stack = info.app.stack.name;
|
|
73
|
+
if (app.stack.name !== app.build_stack.name) {
|
|
74
|
+
stack += ` (next build will use ${app.build_stack.name})`;
|
|
75
|
+
}
|
|
76
|
+
return stack;
|
|
77
|
+
})(info.app);
|
|
78
|
+
core_1.ux.styledHeader(info.app.name);
|
|
79
|
+
core_1.ux.styledObject(data);
|
|
80
|
+
if (extended) {
|
|
81
|
+
core_1.ux.log('\n\n--- Extended Information ---\n\n');
|
|
82
|
+
if (info.app.extended) {
|
|
83
|
+
core_1.ux.log(util.inspect(info.app.extended));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
class AppsInfo extends command_1.Command {
|
|
88
|
+
async run() {
|
|
89
|
+
const { flags, args } = await this.parse(AppsInfo);
|
|
90
|
+
const app = args.app || flags.app;
|
|
91
|
+
if (!app)
|
|
92
|
+
throw new Error('No app specified.\nUSAGE: heroku apps:info --app my-app');
|
|
93
|
+
const info = await getInfo(app, this, flags.extended);
|
|
94
|
+
const addons = info.addons.map((a) => { var _a; return (_a = a.plan) === null || _a === void 0 ? void 0 : _a.name; }).sort();
|
|
95
|
+
const collaborators = info.collaborators.map((c) => c.user.email)
|
|
96
|
+
.filter((c) => c !== info.app.owner.email)
|
|
97
|
+
.sort();
|
|
98
|
+
function shell() {
|
|
99
|
+
function print(k, v) {
|
|
100
|
+
core_1.ux.log(`${snakeCase(k)}=${v}`);
|
|
101
|
+
}
|
|
102
|
+
print('auto_cert_mgmt', info.app.acm);
|
|
103
|
+
print('addons', addons);
|
|
104
|
+
print('collaborators', collaborators);
|
|
105
|
+
if (info.app.archived_at)
|
|
106
|
+
print('archived_at', formatDate(new Date(info.app.archived_at)));
|
|
107
|
+
if (info.app.cron_finished_at)
|
|
108
|
+
print('cron_finished_at', formatDate(new Date(info.app.cron_finished_at)));
|
|
109
|
+
if (info.app.cron_next_run)
|
|
110
|
+
print('cron_next_run', formatDate(new Date(info.app.cron_next_run)));
|
|
111
|
+
if (info.app.database_size)
|
|
112
|
+
print('database_size', filesize(info.app.database_size, { round: 0 }));
|
|
113
|
+
if (info.app.create_status !== 'complete')
|
|
114
|
+
print('create_status', info.app.create_status);
|
|
115
|
+
if (info.pipeline_coupling)
|
|
116
|
+
print('pipeline', `${info.pipeline_coupling.pipeline.name}:${info.pipeline_coupling.stage}`);
|
|
117
|
+
print('git_url', info.app.git_url);
|
|
118
|
+
print('web_url', info.app.web_url);
|
|
119
|
+
print('repo_size', filesize(info.app.repo_size, { round: 0 }));
|
|
120
|
+
print('slug_size', filesize(info.app.slug_size, { round: 0 }));
|
|
121
|
+
print('owner', info.app.owner.email);
|
|
122
|
+
print('region', info.app.region.name);
|
|
123
|
+
print('dynos', util.inspect(countBy(info.dynos, 'type')));
|
|
124
|
+
print('stack', info.app.stack.name);
|
|
125
|
+
}
|
|
126
|
+
if (flags.shell) {
|
|
127
|
+
shell();
|
|
128
|
+
}
|
|
129
|
+
else if (flags.json) {
|
|
130
|
+
core_1.ux.styledJSON(info);
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
print(info, addons, collaborators, flags.extended);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
exports.default = AppsInfo;
|
|
138
|
+
AppsInfo.description = 'show detailed app information';
|
|
139
|
+
AppsInfo.topic = 'apps';
|
|
140
|
+
AppsInfo.aliases = ['info'];
|
|
141
|
+
AppsInfo.examples = [
|
|
142
|
+
'$ heroku apps:info',
|
|
143
|
+
'$ heroku apps:info --shell',
|
|
144
|
+
];
|
|
145
|
+
AppsInfo.help = `$ heroku apps:info
|
|
146
|
+
=== example
|
|
147
|
+
Git URL: https://git.heroku.com/example.git
|
|
148
|
+
Repo Size: 5M
|
|
149
|
+
...
|
|
150
|
+
|
|
151
|
+
$ heroku apps:info --shell
|
|
152
|
+
git_url=https://git.heroku.com/example.git
|
|
153
|
+
repo_size=5000000
|
|
154
|
+
...`;
|
|
155
|
+
AppsInfo.flags = {
|
|
156
|
+
app: command_1.flags.app(),
|
|
157
|
+
shell: command_1.flags.boolean({ char: 's', description: 'output more shell friendly key/value pairs' }),
|
|
158
|
+
extended: command_1.flags.boolean({ char: 'x', hidden: true }),
|
|
159
|
+
json: command_1.flags.boolean({ char: 'j', description: 'output in json format' }),
|
|
160
|
+
};
|
|
161
|
+
AppsInfo.args = {
|
|
162
|
+
app: core_1.Args.string({ hidden: true }),
|
|
163
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Command } from '@heroku-cli/command';
|
|
2
|
+
export default class AppsOpen extends Command {
|
|
3
|
+
static description: string;
|
|
4
|
+
static topic: string;
|
|
5
|
+
static aliases: string[];
|
|
6
|
+
static examples: string[];
|
|
7
|
+
static flags: {
|
|
8
|
+
app: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
9
|
+
};
|
|
10
|
+
static args: {
|
|
11
|
+
path: import("@oclif/core/lib/interfaces/parser").Arg<string | undefined, Record<string, unknown>>;
|
|
12
|
+
};
|
|
13
|
+
run(): Promise<void>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const command_1 = require("@heroku-cli/command");
|
|
5
|
+
const open = require("open");
|
|
6
|
+
class AppsOpen extends command_1.Command {
|
|
7
|
+
async run() {
|
|
8
|
+
const { flags, args } = await this.parse(AppsOpen);
|
|
9
|
+
const appResponse = await this.heroku.get(`/apps/${flags.app}`);
|
|
10
|
+
const app = appResponse.body;
|
|
11
|
+
const path = args.path || '';
|
|
12
|
+
const url = new URL(path, app.web_url);
|
|
13
|
+
await open(url.toString());
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
exports.default = AppsOpen;
|
|
17
|
+
AppsOpen.description = 'open the app in a web browser';
|
|
18
|
+
AppsOpen.topic = 'apps';
|
|
19
|
+
AppsOpen.aliases = ['open'];
|
|
20
|
+
AppsOpen.examples = [
|
|
21
|
+
'$ heroku open -a myapp',
|
|
22
|
+
'$ heroku open -a myapp /foo',
|
|
23
|
+
];
|
|
24
|
+
AppsOpen.flags = {
|
|
25
|
+
app: command_1.flags.app({ required: true }),
|
|
26
|
+
};
|
|
27
|
+
AppsOpen.args = {
|
|
28
|
+
path: core_1.Args.string({ required: false }),
|
|
29
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Command } from '@heroku-cli/command';
|
|
2
|
+
export default class AppsRename extends Command {
|
|
3
|
+
static description: string;
|
|
4
|
+
static help: string;
|
|
5
|
+
static topic: string;
|
|
6
|
+
static aliases: string[];
|
|
7
|
+
static examples: string[];
|
|
8
|
+
static flags: {
|
|
9
|
+
app: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
10
|
+
};
|
|
11
|
+
static args: {
|
|
12
|
+
newname: import("@oclif/core/lib/interfaces/parser").Arg<string, Record<string, unknown>>;
|
|
13
|
+
};
|
|
14
|
+
run(): Promise<void>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const command_1 = require("@heroku-cli/command");
|
|
5
|
+
const _ = require("lodash");
|
|
6
|
+
const git = require("../../lib/ci/git");
|
|
7
|
+
const color_1 = require("@heroku-cli/color");
|
|
8
|
+
class AppsRename extends command_1.Command {
|
|
9
|
+
async run() {
|
|
10
|
+
const { flags, args } = await this.parse(AppsRename);
|
|
11
|
+
const oldApp = flags.app;
|
|
12
|
+
const newApp = args.newname;
|
|
13
|
+
core_1.ux.action.start(`Renaming ${color_1.default.cyan(oldApp)} to ${color_1.default.green(newApp)}`);
|
|
14
|
+
const appResponse = await this.heroku.patch(`/apps/${oldApp}`, { body: { name: newApp } });
|
|
15
|
+
const app = appResponse.body;
|
|
16
|
+
core_1.ux.action.stop();
|
|
17
|
+
const gitUrl = git.gitUrl(app.name);
|
|
18
|
+
core_1.ux.log(`${app.web_url} | ${gitUrl}`);
|
|
19
|
+
if (!app.web_url.includes('https')) {
|
|
20
|
+
core_1.ux.log('Please note that it may take a few minutes for Heroku to provision a SSL certificate for your application.');
|
|
21
|
+
}
|
|
22
|
+
if (git.inGitRepo()) {
|
|
23
|
+
// delete git remotes pointing to this app
|
|
24
|
+
await _(await git.listRemotes())
|
|
25
|
+
.filter(r => git.gitUrl(oldApp) === r[1] || git.sshGitUrl(oldApp) === r[1])
|
|
26
|
+
.map(r => r[0])
|
|
27
|
+
.uniq()
|
|
28
|
+
.map(r => {
|
|
29
|
+
return git.rmRemote(r)
|
|
30
|
+
.then(() => git.createRemote(r, gitUrl))
|
|
31
|
+
.then(() => core_1.ux.log(`Git remote ${r} updated`));
|
|
32
|
+
}).value();
|
|
33
|
+
}
|
|
34
|
+
core_1.ux.warn("Don't forget to update git remotes for all other local checkouts of the app.");
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
exports.default = AppsRename;
|
|
38
|
+
AppsRename.description = 'rename an app';
|
|
39
|
+
AppsRename.help = 'This will locally update the git remote if it is set to the old app.';
|
|
40
|
+
AppsRename.topic = 'apps';
|
|
41
|
+
AppsRename.aliases = ['rename'];
|
|
42
|
+
AppsRename.examples = [
|
|
43
|
+
'$ heroku apps:rename --app oldname newname',
|
|
44
|
+
];
|
|
45
|
+
AppsRename.flags = {
|
|
46
|
+
app: command_1.flags.app({ required: true }),
|
|
47
|
+
};
|
|
48
|
+
AppsRename.args = {
|
|
49
|
+
newname: core_1.Args.string({ required: true }),
|
|
50
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Command } from '@heroku-cli/command';
|
|
2
|
+
export default class StacksIndex extends Command {
|
|
3
|
+
static description: string;
|
|
4
|
+
static topic: string;
|
|
5
|
+
static aliases: string[];
|
|
6
|
+
static flags: {
|
|
7
|
+
app: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
8
|
+
};
|
|
9
|
+
run(): Promise<void>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const command_1 = require("@heroku-cli/command");
|
|
5
|
+
const _ = require("lodash");
|
|
6
|
+
const color_1 = require("@heroku-cli/color");
|
|
7
|
+
function updateCedarName(stack) {
|
|
8
|
+
if (stack === 'cedar') {
|
|
9
|
+
return 'cedar-10';
|
|
10
|
+
}
|
|
11
|
+
return stack;
|
|
12
|
+
}
|
|
13
|
+
class StacksIndex extends command_1.Command {
|
|
14
|
+
async run() {
|
|
15
|
+
const { flags } = await this.parse(StacksIndex);
|
|
16
|
+
const [appResponse, stackResponse] = await Promise.all([
|
|
17
|
+
this.heroku.get(`/apps/${flags.app}`),
|
|
18
|
+
this.heroku.get('/stacks'),
|
|
19
|
+
]);
|
|
20
|
+
const app = appResponse.body;
|
|
21
|
+
const stacks = stackResponse.body;
|
|
22
|
+
const sortedStacks = _.sortBy(stacks, 'name');
|
|
23
|
+
core_1.ux.styledHeader(`${color_1.default.app(app.name)} Available Stacks`);
|
|
24
|
+
for (const stack of sortedStacks) {
|
|
25
|
+
if (stack.name === app.stack.name) {
|
|
26
|
+
core_1.ux.log(color_1.default.green('* ' + updateCedarName(stack.name)));
|
|
27
|
+
}
|
|
28
|
+
else if (stack.name === app.build_stack.name) {
|
|
29
|
+
core_1.ux.log(` ${updateCedarName(stack.name)} (active on next deploy)`);
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
core_1.ux.log(` ${updateCedarName(stack.name)}`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
exports.default = StacksIndex;
|
|
38
|
+
StacksIndex.description = 'show the list of available stacks';
|
|
39
|
+
StacksIndex.topic = 'apps';
|
|
40
|
+
StacksIndex.aliases = ['stack'];
|
|
41
|
+
StacksIndex.flags = {
|
|
42
|
+
app: command_1.flags.app({ required: true }),
|
|
43
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Command } from '@heroku-cli/command';
|
|
2
|
+
export default class Set extends Command {
|
|
3
|
+
static description: string;
|
|
4
|
+
static example: string;
|
|
5
|
+
static aliases: string[];
|
|
6
|
+
static flags: {
|
|
7
|
+
app: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
8
|
+
remote: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
9
|
+
};
|
|
10
|
+
static args: {
|
|
11
|
+
stack: import("@oclif/core/lib/interfaces/parser").Arg<string, Record<string, unknown>>;
|
|
12
|
+
};
|
|
13
|
+
run(): Promise<void>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const color_1 = require("@heroku-cli/color");
|
|
4
|
+
const command_1 = require("@heroku-cli/command");
|
|
5
|
+
const core_1 = require("@oclif/core");
|
|
6
|
+
const push_1 = require("../../../lib/git/push");
|
|
7
|
+
function map(stack) {
|
|
8
|
+
return stack === 'cedar-10' ? 'cedar' : stack;
|
|
9
|
+
}
|
|
10
|
+
class Set extends command_1.Command {
|
|
11
|
+
async run() {
|
|
12
|
+
var _a, _b;
|
|
13
|
+
const { flags, args } = await this.parse(Set);
|
|
14
|
+
const stack = map(args.stack);
|
|
15
|
+
core_1.ux.action.start(`Setting stack to ${color_1.default.green(stack)}`);
|
|
16
|
+
const { body: app } = await this.heroku.patch(`/apps/${flags.app}`, {
|
|
17
|
+
body: { build_stack: stack },
|
|
18
|
+
});
|
|
19
|
+
// A redeployment is not required for apps that have never been deployed, since
|
|
20
|
+
// API updates the app's `stack` to match `build_stack` immediately.
|
|
21
|
+
if (((_a = app.stack) === null || _a === void 0 ? void 0 : _a.name) !== ((_b = app.build_stack) === null || _b === void 0 ? void 0 : _b.name)) {
|
|
22
|
+
core_1.ux.log(`You will need to redeploy ${color_1.default.app(flags.app)} for the change to take effect.`);
|
|
23
|
+
core_1.ux.log(`Run ${color_1.default.cmd((0, push_1.default)(flags.remote))} to trigger a new build on ${color_1.default.app(flags.app)}.`);
|
|
24
|
+
}
|
|
25
|
+
core_1.ux.action.stop();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
exports.default = Set;
|
|
29
|
+
Set.description = 'set the stack of an app';
|
|
30
|
+
Set.example = `$ heroku stack:set heroku-22 -a myapp
|
|
31
|
+
Setting stack to heroku-22... done
|
|
32
|
+
You will need to redeploy myapp for the change to take effect.
|
|
33
|
+
Run git push heroku main to trigger a new build on myapp.`;
|
|
34
|
+
Set.aliases = ['stack:set'];
|
|
35
|
+
Set.flags = {
|
|
36
|
+
app: command_1.flags.app({ required: true }),
|
|
37
|
+
remote: command_1.flags.remote(),
|
|
38
|
+
};
|
|
39
|
+
Set.args = {
|
|
40
|
+
stack: core_1.Args.string({ required: true }),
|
|
41
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Command } from '@heroku-cli/command';
|
|
2
|
+
export default class CiConfigGet extends Command {
|
|
3
|
+
static description: string;
|
|
4
|
+
static topic: string;
|
|
5
|
+
static examples: string[];
|
|
6
|
+
static flags: {
|
|
7
|
+
help: import("@oclif/core/lib/interfaces").BooleanFlag<void>;
|
|
8
|
+
app: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
9
|
+
pipeline: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
10
|
+
shell: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
};
|
|
12
|
+
static args: {
|
|
13
|
+
key: import("@oclif/core/lib/interfaces/parser").Arg<string, Record<string, unknown>>;
|
|
14
|
+
};
|
|
15
|
+
run(): Promise<void>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const command_1 = require("@heroku-cli/command");
|
|
4
|
+
const core_1 = require("@oclif/core");
|
|
5
|
+
const shellescape = require("shell-escape");
|
|
6
|
+
const api_1 = require("../../../lib/api");
|
|
7
|
+
const pipelines_1 = require("../../../lib/ci/pipelines");
|
|
8
|
+
class CiConfigGet extends command_1.Command {
|
|
9
|
+
async run() {
|
|
10
|
+
const { args, flags } = await this.parse(CiConfigGet);
|
|
11
|
+
const pipeline = await (0, pipelines_1.getPipeline)(flags, this.heroku);
|
|
12
|
+
const { body: config } = await (0, api_1.getPipelineConfigVars)(this.heroku, pipeline.id);
|
|
13
|
+
const value = config[args.key];
|
|
14
|
+
if (flags.shell) {
|
|
15
|
+
core_1.ux.log(`${args.key}=${shellescape([value])}`);
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
core_1.ux.log((value !== null && value !== undefined) ? value : 'undefined');
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
exports.default = CiConfigGet;
|
|
23
|
+
CiConfigGet.description = 'get a CI config var';
|
|
24
|
+
CiConfigGet.topic = 'ci';
|
|
25
|
+
CiConfigGet.examples = [
|
|
26
|
+
`$ heroku ci:config:get --pipeline=PIPELINE RAILS_ENV
|
|
27
|
+
test`,
|
|
28
|
+
];
|
|
29
|
+
CiConfigGet.flags = {
|
|
30
|
+
help: command_1.flags.help({ char: 'h' }),
|
|
31
|
+
app: command_1.flags.app({ required: false }),
|
|
32
|
+
pipeline: command_1.flags.pipeline({ required: false }),
|
|
33
|
+
shell: command_1.flags.boolean({ char: 's', description: 'output config var in shell format' }),
|
|
34
|
+
};
|
|
35
|
+
CiConfigGet.args = {
|
|
36
|
+
key: core_1.Args.string({ required: true }),
|
|
37
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Command } from '@heroku-cli/command';
|
|
2
|
+
export default class CiConfig extends Command {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static flags: {
|
|
6
|
+
app: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
7
|
+
shell: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
8
|
+
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
9
|
+
pipeline: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
10
|
+
};
|
|
11
|
+
run(): Promise<void>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const command_1 = require("@heroku-cli/command");
|
|
4
|
+
const core_1 = require("@oclif/core");
|
|
5
|
+
const color_1 = require("@heroku-cli/color");
|
|
6
|
+
const shellescape = require("shell-escape");
|
|
7
|
+
const pipelines_1 = require("../../../lib/ci/pipelines");
|
|
8
|
+
const api_1 = require("../../../lib/api");
|
|
9
|
+
class CiConfig extends command_1.Command {
|
|
10
|
+
async run() {
|
|
11
|
+
const { flags } = await this.parse(CiConfig);
|
|
12
|
+
const pipeline = await (0, pipelines_1.getPipeline)(flags, this.heroku);
|
|
13
|
+
const { body: config } = await (0, api_1.getPipelineConfigVars)(this.heroku, pipeline.id);
|
|
14
|
+
if (flags.shell) {
|
|
15
|
+
Object.keys(config).forEach(key => {
|
|
16
|
+
core_1.ux.log(`${key}=${shellescape([config[key]])}`);
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
else if (flags.json) {
|
|
20
|
+
core_1.ux.styledJSON(config);
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
core_1.ux.styledHeader(`${pipeline.name} test config vars`);
|
|
24
|
+
const formattedConfig = {};
|
|
25
|
+
Object.keys(config).forEach(key => {
|
|
26
|
+
formattedConfig[color_1.default.green(key)] = config[key];
|
|
27
|
+
});
|
|
28
|
+
core_1.ux.styledObject(formattedConfig);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
exports.default = CiConfig;
|
|
33
|
+
CiConfig.description = 'display CI config vars';
|
|
34
|
+
CiConfig.examples = [
|
|
35
|
+
`$ heroku ci:config --app murmuring-headland-14719 --json
|
|
36
|
+
`,
|
|
37
|
+
];
|
|
38
|
+
CiConfig.flags = {
|
|
39
|
+
app: command_1.flags.string({ char: 'a', description: 'app name' }),
|
|
40
|
+
shell: command_1.flags.boolean({ char: 's', description: 'output config vars in shell format' }),
|
|
41
|
+
json: command_1.flags.boolean({ description: 'output config vars in json format' }),
|
|
42
|
+
pipeline: command_1.flags.pipeline(),
|
|
43
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Command } from '@heroku-cli/command';
|
|
2
|
+
export default class CiConfigSet extends Command {
|
|
3
|
+
static description: string;
|
|
4
|
+
static topic: string;
|
|
5
|
+
static examples: string[];
|
|
6
|
+
static flags: {
|
|
7
|
+
app: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
8
|
+
pipeline: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
9
|
+
};
|
|
10
|
+
static strict: boolean;
|
|
11
|
+
run(): Promise<void>;
|
|
12
|
+
}
|