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,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const pipelines_1 = require("../../../lib/ci/pipelines");
|
|
5
|
+
const command_1 = require("@heroku-cli/command");
|
|
6
|
+
const api_1 = require("../../../lib/api");
|
|
7
|
+
const validate_1 = require("../../../lib/ci/validate");
|
|
8
|
+
const color_1 = require("@heroku-cli/color");
|
|
9
|
+
function validateInput(str) {
|
|
10
|
+
if (!str.includes('=')) {
|
|
11
|
+
core_1.ux.error(`${color_1.default.cyan(str)} is invalid. Must be in the format ${color_1.default.cyan('FOO=bar')}.`, { exit: 1 });
|
|
12
|
+
}
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
class CiConfigSet extends command_1.Command {
|
|
16
|
+
async run() {
|
|
17
|
+
const { argv, flags } = await this.parse(CiConfigSet);
|
|
18
|
+
(0, validate_1.validateArgvPresent)(argv);
|
|
19
|
+
const vars = {};
|
|
20
|
+
for (const str of argv) {
|
|
21
|
+
const iAmStr = str;
|
|
22
|
+
validateInput(iAmStr);
|
|
23
|
+
const [key, value] = iAmStr.split('=');
|
|
24
|
+
vars[key] = value;
|
|
25
|
+
}
|
|
26
|
+
const pipeline = await (0, pipelines_1.getPipeline)(flags, this.heroku);
|
|
27
|
+
core_1.ux.action.start(`Setting ${Object.keys(vars).join(', ')}`);
|
|
28
|
+
await (0, api_1.setPipelineConfigVars)(this.heroku, pipeline.id, vars);
|
|
29
|
+
core_1.ux.action.stop();
|
|
30
|
+
core_1.ux.styledObject(Object.keys(vars).reduce((memo, key) => {
|
|
31
|
+
memo[color_1.default.green(key)] = vars[key];
|
|
32
|
+
return memo;
|
|
33
|
+
}, {}));
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
exports.default = CiConfigSet;
|
|
37
|
+
CiConfigSet.description = 'set CI config vars';
|
|
38
|
+
CiConfigSet.topic = 'ci';
|
|
39
|
+
CiConfigSet.examples = [
|
|
40
|
+
`$ heroku ci:config:set --pipeline PIPELINE RAILS_ENV=test
|
|
41
|
+
Setting test config vars... done
|
|
42
|
+
RAILS_ENV: test`,
|
|
43
|
+
];
|
|
44
|
+
CiConfigSet.flags = {
|
|
45
|
+
app: command_1.flags.app(),
|
|
46
|
+
pipeline: command_1.flags.pipeline({ required: true }),
|
|
47
|
+
};
|
|
48
|
+
CiConfigSet.strict = false;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Command } from '@heroku-cli/command';
|
|
2
|
+
export default class CiConfigUnset extends Command {
|
|
3
|
+
static description: string;
|
|
4
|
+
static topic: string;
|
|
5
|
+
static examples: string[];
|
|
6
|
+
static strict: boolean;
|
|
7
|
+
static flags: {
|
|
8
|
+
help: import("@oclif/core/lib/interfaces").BooleanFlag<void>;
|
|
9
|
+
app: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
10
|
+
pipeline: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
11
|
+
};
|
|
12
|
+
run(): Promise<void>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
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 pipelines_1 = require("../../../lib/ci/pipelines");
|
|
6
|
+
const api_1 = require("../../../lib/api");
|
|
7
|
+
const validate_1 = require("../../../lib/ci/validate");
|
|
8
|
+
class CiConfigUnset extends command_1.Command {
|
|
9
|
+
async run() {
|
|
10
|
+
const { argv, flags } = await this.parse(CiConfigUnset);
|
|
11
|
+
const isUnset = true;
|
|
12
|
+
(0, validate_1.validateArgvPresent)(argv, isUnset);
|
|
13
|
+
const pipeline = await (0, pipelines_1.getPipeline)(flags, this.heroku);
|
|
14
|
+
const vars = {};
|
|
15
|
+
for (const str of argv) {
|
|
16
|
+
const iAmStr = str;
|
|
17
|
+
vars[iAmStr] = null;
|
|
18
|
+
}
|
|
19
|
+
await core_1.ux.action.start(`Unsetting ${Object.keys(vars).join(', ')}`);
|
|
20
|
+
(0, api_1.setPipelineConfigVars)(this.heroku, pipeline.id, vars);
|
|
21
|
+
core_1.ux.action.stop();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
exports.default = CiConfigUnset;
|
|
25
|
+
CiConfigUnset.description = 'unset CI config vars';
|
|
26
|
+
CiConfigUnset.topic = 'ci';
|
|
27
|
+
CiConfigUnset.examples = [
|
|
28
|
+
'$ heroku ci:config:unset RAILS_ENV',
|
|
29
|
+
];
|
|
30
|
+
CiConfigUnset.strict = false;
|
|
31
|
+
CiConfigUnset.flags = {
|
|
32
|
+
help: command_1.flags.help({ char: 'h' }),
|
|
33
|
+
app: command_1.flags.app({ required: false }),
|
|
34
|
+
pipeline: command_1.flags.pipeline({ required: false }),
|
|
35
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Command } from '@heroku-cli/command';
|
|
2
|
+
export default class Debug extends Command {
|
|
3
|
+
static description: string;
|
|
4
|
+
static help: string;
|
|
5
|
+
static flags: {
|
|
6
|
+
app: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
7
|
+
'no-cache': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
8
|
+
'no-setup': 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
|
+
static topic: string;
|
|
12
|
+
run(): Promise<void>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
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 lodash_1 = require("lodash");
|
|
6
|
+
const api_1 = require("../../lib/api");
|
|
7
|
+
const pipelines_1 = require("../../lib/ci/pipelines");
|
|
8
|
+
const kolkrabbi_api_1 = require("../../lib/pipelines/kolkrabbi-api");
|
|
9
|
+
const dyno_1 = require("../../lib/run/dyno");
|
|
10
|
+
const git_1 = require("../../lib/git/git");
|
|
11
|
+
const source_1 = require("../../lib/ci/source");
|
|
12
|
+
const test_run_1 = require("../../lib/ci/test-run");
|
|
13
|
+
// Default command. Run setup, source profile.d scripts and open a bash session
|
|
14
|
+
const SETUP_COMMAND = 'ci setup && eval $(ci env)';
|
|
15
|
+
class Debug extends command_1.Command {
|
|
16
|
+
async run() {
|
|
17
|
+
var _a, _b;
|
|
18
|
+
const { flags } = await this.parse(Debug);
|
|
19
|
+
const pipeline = await (0, pipelines_1.getPipeline)(flags, this.heroku);
|
|
20
|
+
const kolkrabbi = new kolkrabbi_api_1.default(this.config.userAgent, () => this.heroku.auth);
|
|
21
|
+
const pipelineRepository = await kolkrabbi.getPipelineRepository(pipeline.id);
|
|
22
|
+
const organization = pipelineRepository.organization &&
|
|
23
|
+
pipelineRepository.organization.name;
|
|
24
|
+
const git = new git_1.default();
|
|
25
|
+
const commit = await git.readCommit('HEAD');
|
|
26
|
+
core_1.ux.action.start('Preparing source');
|
|
27
|
+
const sourceBlobUrl = await (0, source_1.createSourceBlob)(commit.ref, this);
|
|
28
|
+
core_1.ux.action.stop();
|
|
29
|
+
// Create test run and wait for it to transition to `debugging`
|
|
30
|
+
core_1.ux.action.start('Creating test run');
|
|
31
|
+
const { body: run } = await (0, api_1.createTestRun)(this.heroku, {
|
|
32
|
+
commit_branch: commit.branch,
|
|
33
|
+
commit_message: commit.message,
|
|
34
|
+
commit_sha: commit.ref,
|
|
35
|
+
debug: true,
|
|
36
|
+
clear_cache: Boolean(flags['no-cache']),
|
|
37
|
+
organization,
|
|
38
|
+
pipeline: pipeline.id,
|
|
39
|
+
source_blob_url: sourceBlobUrl,
|
|
40
|
+
});
|
|
41
|
+
const testRun = await (0, test_run_1.waitForStates)(['debugging', 'errored'], run, this);
|
|
42
|
+
core_1.ux.action.stop();
|
|
43
|
+
if (testRun.status === 'errored') {
|
|
44
|
+
core_1.ux.error(`Test run creation failed while ${testRun.error_state} with message "${testRun.message}"`, { exit: 1 });
|
|
45
|
+
}
|
|
46
|
+
const { body: appSetup } = await (0, api_1.getAppSetup)(this.heroku, (_a = testRun.app_setup) === null || _a === void 0 ? void 0 : _a.id);
|
|
47
|
+
const noSetup = flags['no-setup'];
|
|
48
|
+
core_1.ux.log(`${noSetup ? 'Attaching' : 'Running setup and attaching'} to test dyno...`);
|
|
49
|
+
if (noSetup) {
|
|
50
|
+
core_1.ux.warn('Skipping test setup phase.');
|
|
51
|
+
core_1.ux.warn(`Run \`${SETUP_COMMAND}\``);
|
|
52
|
+
core_1.ux.warn('to execute a build and configure the environment');
|
|
53
|
+
}
|
|
54
|
+
const { body: testNodes } = await (0, api_1.getTestNodes)(this.heroku, testRun.id);
|
|
55
|
+
const dyno = new dyno_1.default({
|
|
56
|
+
heroku: this.heroku,
|
|
57
|
+
app: ((_b = appSetup === null || appSetup === void 0 ? void 0 : appSetup.app) === null || _b === void 0 ? void 0 : _b.id) || '',
|
|
58
|
+
showStatus: false,
|
|
59
|
+
command: '', // command is required, but is not used.
|
|
60
|
+
});
|
|
61
|
+
dyno.dyno = { attach_url: (0, lodash_1.get)(testNodes, [0, 'dyno', 'attach_url']) };
|
|
62
|
+
function sendSetup(data) {
|
|
63
|
+
if (data.toString().includes('$')) {
|
|
64
|
+
dyno.write(SETUP_COMMAND + '\n');
|
|
65
|
+
dyno.removeListener('data', sendSetup);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (!noSetup) {
|
|
69
|
+
dyno.on('data', sendSetup);
|
|
70
|
+
}
|
|
71
|
+
try {
|
|
72
|
+
await dyno.attach();
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
if (error.exitCode)
|
|
76
|
+
this.error(error, { exit: error.exitCode });
|
|
77
|
+
else
|
|
78
|
+
throw error;
|
|
79
|
+
}
|
|
80
|
+
await core_1.ux.action.start('Cleaning up');
|
|
81
|
+
await (0, api_1.updateTestRun)(this.heroku, testRun.id, {
|
|
82
|
+
status: 'cancelled',
|
|
83
|
+
message: 'debug run cancelled by Heroku CLI',
|
|
84
|
+
});
|
|
85
|
+
await core_1.ux.action.stop();
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
exports.default = Debug;
|
|
89
|
+
Debug.description = 'opens an interactive test debugging session with the contents of the current directory';
|
|
90
|
+
Debug.help = `Example:
|
|
91
|
+
|
|
92
|
+
$ heroku ci:debug --pipeline PIPELINE
|
|
93
|
+
Preparing source... done
|
|
94
|
+
Creating test run... done
|
|
95
|
+
Running setup and attaching to test dyno...
|
|
96
|
+
|
|
97
|
+
~ $
|
|
98
|
+
`;
|
|
99
|
+
Debug.flags = {
|
|
100
|
+
app: command_1.flags.app(),
|
|
101
|
+
'no-cache': command_1.flags.boolean({ description: 'start test run with an empty cache' }),
|
|
102
|
+
'no-setup': command_1.flags.boolean({ description: 'start test dyno without running test-setup' }),
|
|
103
|
+
pipeline: command_1.flags.pipeline(),
|
|
104
|
+
};
|
|
105
|
+
Debug.topic = 'ci';
|
package/lib/commands/ci/index.js
CHANGED
|
@@ -6,7 +6,7 @@ const test_run_1 = require("../../lib/ci/test-run");
|
|
|
6
6
|
class CiIndex extends command_1.Command {
|
|
7
7
|
async run() {
|
|
8
8
|
const { flags } = await this.parse(CiIndex);
|
|
9
|
-
const pipeline = await (0, pipelines_1.getPipeline)(flags, this);
|
|
9
|
+
const pipeline = await (0, pipelines_1.getPipeline)(flags, this.heroku);
|
|
10
10
|
const { body: testRuns } = await this.heroku.get(`/pipelines/${pipeline.id}/test-runs`);
|
|
11
11
|
await (0, test_run_1.renderList)(this, testRuns, pipeline, flags.watch, flags.json);
|
|
12
12
|
}
|
package/lib/commands/ci/info.js
CHANGED
|
@@ -7,7 +7,7 @@ const test_run_1 = require("../../lib/ci/test-run");
|
|
|
7
7
|
class CiInfo extends command_1.Command {
|
|
8
8
|
async run() {
|
|
9
9
|
const { args, flags } = await this.parse(CiInfo);
|
|
10
|
-
const pipeline = await (0, pipelines_1.getPipeline)(flags, this);
|
|
10
|
+
const pipeline = await (0, pipelines_1.getPipeline)(flags, this.heroku);
|
|
11
11
|
const { body: testRun } = await this.heroku.get(`/pipelines/${pipeline.id}/test-runs/${args['test-run']}`);
|
|
12
12
|
const { body: testNodes } = await this.heroku.get(`/test-runs/${testRun.id}/test-nodes`);
|
|
13
13
|
await (0, test_run_1.displayTestRunInfo)(this, testRun, testNodes, flags.node);
|
package/lib/commands/ci/last.js
CHANGED
|
@@ -7,7 +7,7 @@ const test_run_1 = require("../../lib/ci/test-run");
|
|
|
7
7
|
class CiLast extends command_1.Command {
|
|
8
8
|
async run() {
|
|
9
9
|
const { flags } = await this.parse(CiLast);
|
|
10
|
-
const pipeline = await (0, pipelines_1.getPipeline)(flags, this);
|
|
10
|
+
const pipeline = await (0, pipelines_1.getPipeline)(flags, this.heroku);
|
|
11
11
|
const headers = { Range: 'number ..; order=desc,max=1' };
|
|
12
12
|
const { body: latestTestRuns } = await this.heroku.get(`/pipelines/${pipeline.id}/test-runs`, { headers });
|
|
13
13
|
if (latestTestRuns.length === 0) {
|
|
@@ -0,0 +1,74 @@
|
|
|
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 fs = require("async-file");
|
|
7
|
+
const writeFile = fs.writeFile;
|
|
8
|
+
const unlinkFile = fs.unlink;
|
|
9
|
+
class CiMigrateManifest extends command_1.Command {
|
|
10
|
+
async run() {
|
|
11
|
+
const appJSONPath = `${process.cwd()}/app.json`;
|
|
12
|
+
const appCiJSONPath = `${process.cwd()}/app-ci.json`;
|
|
13
|
+
let action;
|
|
14
|
+
function showWarning() {
|
|
15
|
+
core_1.ux.log(color_1.default.green('Please check the contents of your app.json before committing to your repo.'));
|
|
16
|
+
}
|
|
17
|
+
async function updateAppJson() {
|
|
18
|
+
// Updating / Creating
|
|
19
|
+
core_1.ux.action.start(`${action.charAt(0).toUpperCase() + action.slice(1)} app.json file`);
|
|
20
|
+
await writeFile(appJSONPath, `${JSON.stringify(appJSON, null, ' ')}\n`);
|
|
21
|
+
core_1.ux.action.stop();
|
|
22
|
+
}
|
|
23
|
+
let appJSON;
|
|
24
|
+
let appCiJSON;
|
|
25
|
+
try {
|
|
26
|
+
appJSON = require(appJSONPath);
|
|
27
|
+
action = 'updating';
|
|
28
|
+
}
|
|
29
|
+
catch (_a) {
|
|
30
|
+
action = 'creating';
|
|
31
|
+
appJSON = {};
|
|
32
|
+
}
|
|
33
|
+
try {
|
|
34
|
+
appCiJSON = require(appCiJSONPath);
|
|
35
|
+
}
|
|
36
|
+
catch (_b) {
|
|
37
|
+
let msg = 'We couldn\'t find an app-ci.json file in the current directory';
|
|
38
|
+
// eslint-disable-next-line no-eq-null, eqeqeq
|
|
39
|
+
if (appJSON.environments == null) {
|
|
40
|
+
msg += `, but we're ${action} ${action === 'updating' ? 'your' : 'a new'} app.json manifest for you.`;
|
|
41
|
+
appJSON.environments = {};
|
|
42
|
+
core_1.ux.log(msg);
|
|
43
|
+
await updateAppJson();
|
|
44
|
+
showWarning();
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
msg += ', and your app.json already has the environments key.';
|
|
48
|
+
core_1.ux.log(msg);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (appCiJSON) {
|
|
52
|
+
if (appJSON.environments && appJSON.environments.test) {
|
|
53
|
+
core_1.ux.warn('Your app.json already had a test key. We\'re overwriting it with the content of your app-ci.json');
|
|
54
|
+
}
|
|
55
|
+
// eslint-disable-next-line no-eq-null, eqeqeq
|
|
56
|
+
if (appJSON.environments == null) {
|
|
57
|
+
appJSON.environments = {};
|
|
58
|
+
}
|
|
59
|
+
appJSON.environments.test = appCiJSON;
|
|
60
|
+
await updateAppJson();
|
|
61
|
+
core_1.ux.action.start('Deleting app-ci.json file');
|
|
62
|
+
await unlinkFile(appCiJSONPath);
|
|
63
|
+
core_1.ux.action.stop();
|
|
64
|
+
showWarning();
|
|
65
|
+
}
|
|
66
|
+
core_1.ux.log('You\'re all set! 🎉');
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
exports.default = CiMigrateManifest;
|
|
70
|
+
CiMigrateManifest.description = 'app-ci.json is deprecated. Run this command to migrate to app.json with an environments key.';
|
|
71
|
+
CiMigrateManifest.topic = 'ci';
|
|
72
|
+
CiMigrateManifest.examples = [
|
|
73
|
+
'$ heroku ci:migrate-manifest',
|
|
74
|
+
];
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Command } from '@heroku-cli/command';
|
|
2
|
+
export default class CiOpen 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, 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
|
+
};
|
|
11
|
+
run(): Promise<void>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const command_1 = require("@heroku-cli/command");
|
|
4
|
+
const open = require("open");
|
|
5
|
+
const pipelines_1 = require("../../lib/ci/pipelines");
|
|
6
|
+
class CiOpen extends command_1.Command {
|
|
7
|
+
async run() {
|
|
8
|
+
const { flags } = await this.parse(CiOpen);
|
|
9
|
+
const pipeline = await (0, pipelines_1.getPipeline)(flags, this.heroku);
|
|
10
|
+
await open(`https://dashboard.heroku.com/pipelines/${pipeline.id}/tests`);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
exports.default = CiOpen;
|
|
14
|
+
CiOpen.description = 'open the Dashboard version of Heroku CI';
|
|
15
|
+
CiOpen.topic = 'ci';
|
|
16
|
+
CiOpen.examples = [
|
|
17
|
+
'$ heroku ci:open --app murmuring-headland-14719',
|
|
18
|
+
];
|
|
19
|
+
CiOpen.flags = {
|
|
20
|
+
help: command_1.flags.help({ char: 'h' }),
|
|
21
|
+
app: command_1.flags.app({ required: true }),
|
|
22
|
+
pipeline: command_1.flags.pipeline({ required: false }),
|
|
23
|
+
};
|
package/lib/commands/ci/rerun.js
CHANGED
|
@@ -8,7 +8,7 @@ const test_run_1 = require("../../lib/ci/test-run");
|
|
|
8
8
|
class CiReRun extends command_1.Command {
|
|
9
9
|
async run() {
|
|
10
10
|
const { flags, args } = await this.parse(CiReRun);
|
|
11
|
-
const pipeline = await (0, pipelines_1.getPipeline)(flags, this);
|
|
11
|
+
const pipeline = await (0, pipelines_1.getPipeline)(flags, this.heroku);
|
|
12
12
|
let sourceTestRun;
|
|
13
13
|
if (args.number) {
|
|
14
14
|
const testRunResponse = await this.heroku.get(`/pipelines/${pipeline.id}/test-runs/${args.number}`);
|
package/lib/commands/ci/run.js
CHANGED
|
@@ -9,7 +9,7 @@ const test_run_1 = require("../../lib/ci/test-run");
|
|
|
9
9
|
class CiRun extends command_1.Command {
|
|
10
10
|
async run() {
|
|
11
11
|
const { flags } = await this.parse(CiRun);
|
|
12
|
-
const pipeline = await (0, pipelines_1.getPipeline)(flags, this);
|
|
12
|
+
const pipeline = await (0, pipelines_1.getPipeline)(flags, this.heroku);
|
|
13
13
|
const commit = await git.readCommit('HEAD');
|
|
14
14
|
core_1.ux.action.start('Preparing source');
|
|
15
15
|
const sourceBlobUrl = await (0, source_1.createSourceBlob)(commit.ref, this);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Command } from '@heroku-cli/command';
|
|
2
|
+
export default class Set extends Command {
|
|
3
|
+
static description: string;
|
|
4
|
+
static strict: boolean;
|
|
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
|
+
run(): Promise<void>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
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 lodash_1 = require("lodash");
|
|
6
|
+
const core_1 = require("@oclif/core");
|
|
7
|
+
const lastRelease = async (client, app) => {
|
|
8
|
+
const { body: releases } = await client.get(`/apps/${app}/releases`, {
|
|
9
|
+
method: 'GET',
|
|
10
|
+
partial: true,
|
|
11
|
+
headers: { Range: 'version ..; order=desc,max=1' },
|
|
12
|
+
});
|
|
13
|
+
return releases[0];
|
|
14
|
+
};
|
|
15
|
+
class Set extends command_1.Command {
|
|
16
|
+
async run() {
|
|
17
|
+
const { flags, argv: _argv } = await this.parse(Set);
|
|
18
|
+
const argv = _argv;
|
|
19
|
+
if (argv.length === 0) {
|
|
20
|
+
core_1.ux.error('Usage: heroku config:set KEY1=VALUE1 [KEY2=VALUE2 ...]\nMust specify KEY and VALUE to set.', { exit: 1 });
|
|
21
|
+
}
|
|
22
|
+
const vars = {};
|
|
23
|
+
argv.forEach((v) => {
|
|
24
|
+
const idx = v.indexOf('=');
|
|
25
|
+
if (idx === -1) {
|
|
26
|
+
core_1.ux.error(`${color_1.default.cyan(v)} is invalid. Must be in the format ${color_1.default.cyan('FOO=bar')}.`, { exit: 1 });
|
|
27
|
+
}
|
|
28
|
+
vars[v.slice(0, idx)] = v.slice(idx + 1);
|
|
29
|
+
});
|
|
30
|
+
const varsCopy = argv.map((v) => color_1.default.green(v.split('=')[0])).join(', ');
|
|
31
|
+
core_1.ux.action.start(`Setting ${varsCopy} and restarting ${color_1.default.app(flags.app)}`);
|
|
32
|
+
let { body: config } = await this.heroku.patch(`/apps/${flags.app}/config-vars`, {
|
|
33
|
+
body: vars,
|
|
34
|
+
});
|
|
35
|
+
const release = await lastRelease(this.heroku, flags.app);
|
|
36
|
+
core_1.ux.action.stop(`done, ${color_1.default.release('v' + release.version)}`);
|
|
37
|
+
config = (0, lodash_1.pickBy)(config, (_, k) => vars[k]);
|
|
38
|
+
config = (0, lodash_1.mapKeys)(config, (_, k) => color_1.default.green(k));
|
|
39
|
+
core_1.ux.styledObject(config);
|
|
40
|
+
await this.config.runHook('recache', { type: 'config', app: flags.app });
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
exports.default = Set;
|
|
44
|
+
Set.description = 'set one or more config vars';
|
|
45
|
+
Set.strict = false;
|
|
46
|
+
Set.aliases = ['config:add'];
|
|
47
|
+
Set.examples = [
|
|
48
|
+
`$ heroku config:set RAILS_ENV=staging
|
|
49
|
+
Setting config vars and restarting example... done, v10
|
|
50
|
+
RAILS_ENV: staging
|
|
51
|
+
|
|
52
|
+
$ heroku config:set RAILS_ENV=staging RACK_ENV=staging
|
|
53
|
+
Setting config vars and restarting example... done, v11
|
|
54
|
+
RAILS_ENV: staging
|
|
55
|
+
RACK_ENV: staging`,
|
|
56
|
+
];
|
|
57
|
+
Set.flags = {
|
|
58
|
+
app: command_1.flags.app({ required: true }),
|
|
59
|
+
};
|
|
@@ -6,9 +6,9 @@ export default class DomainsIndex extends Command {
|
|
|
6
6
|
static flags: {
|
|
7
7
|
extended: import("@oclif/core/lib/interfaces").Flag<boolean>;
|
|
8
8
|
'no-header': import("@oclif/core/lib/interfaces").Flag<boolean>;
|
|
9
|
+
filter: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
9
10
|
sort: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
10
11
|
columns: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
11
|
-
filter: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
12
12
|
csv: import("@oclif/core/lib/interfaces").Flag<boolean>;
|
|
13
13
|
output: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
14
14
|
help: import("@oclif/core/lib/interfaces").BooleanFlag<void>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Command } from '@heroku-cli/command';
|
|
2
|
+
export default class Add extends Command {
|
|
3
|
+
static description: string;
|
|
4
|
+
static flags: {
|
|
5
|
+
app: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
6
|
+
};
|
|
7
|
+
static args: {
|
|
8
|
+
url: import("@oclif/core/lib/interfaces/parser").Arg<string, Record<string, unknown>>;
|
|
9
|
+
};
|
|
10
|
+
run(): Promise<void>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const color_1 = require("@heroku-cli/color");
|
|
5
|
+
const command_1 = require("@heroku-cli/command");
|
|
6
|
+
class Add extends command_1.Command {
|
|
7
|
+
async run() {
|
|
8
|
+
const { flags, args } = await this.parse(Add);
|
|
9
|
+
const { body: drain } = await this.heroku.post(`/apps/${flags.app}/log-drains`, {
|
|
10
|
+
body: { url: args.url },
|
|
11
|
+
});
|
|
12
|
+
core_1.ux.log(`Successfully added drain ${color_1.default.cyan(drain.url || '')}`);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
exports.default = Add;
|
|
16
|
+
Add.description = 'adds a log drain to an app';
|
|
17
|
+
Add.flags = {
|
|
18
|
+
app: command_1.flags.app({ required: true }),
|
|
19
|
+
};
|
|
20
|
+
Add.args = {
|
|
21
|
+
url: core_1.Args.string({ required: true }),
|
|
22
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Command } from '@heroku-cli/command';
|
|
2
|
+
export default class Drains extends Command {
|
|
3
|
+
static description: string;
|
|
4
|
+
static flags: {
|
|
5
|
+
app: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
6
|
+
extended: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
7
|
+
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
8
|
+
};
|
|
9
|
+
run(): Promise<void>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const color_1 = require("@heroku-cli/color");
|
|
5
|
+
const command_1 = require("@heroku-cli/command");
|
|
6
|
+
const lodash_1 = require("lodash");
|
|
7
|
+
function styledDrain(id, name, drain) {
|
|
8
|
+
let output = `${id} (${name})`;
|
|
9
|
+
if (drain.extended)
|
|
10
|
+
output += ` drain_id=${drain.extended.drain_id}`;
|
|
11
|
+
core_1.ux.log(output);
|
|
12
|
+
}
|
|
13
|
+
class Drains extends command_1.Command {
|
|
14
|
+
async run() {
|
|
15
|
+
const { flags } = await this.parse(Drains);
|
|
16
|
+
let path = `/apps/${flags.app}/log-drains`;
|
|
17
|
+
if (flags.extended) {
|
|
18
|
+
path += '?extended=true';
|
|
19
|
+
}
|
|
20
|
+
const { body: drains } = await this.heroku.get(path);
|
|
21
|
+
if (flags.json) {
|
|
22
|
+
core_1.ux.styledJSON(drains);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
const [drainsWithAddons, drainsWithoutAddons] = (0, lodash_1.partition)(drains, 'addon');
|
|
26
|
+
if (drainsWithoutAddons.length > 0) {
|
|
27
|
+
core_1.ux.styledHeader('Drains');
|
|
28
|
+
drainsWithoutAddons.forEach((drain) => {
|
|
29
|
+
styledDrain(drain.url || '', color_1.default.green(drain.token || ''), drain);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
if (drainsWithAddons.length > 0) {
|
|
33
|
+
const addons = await Promise.all(drainsWithAddons.map((d) => { var _a; return this.heroku.get(`/apps/${flags.app}/addons/${(_a = d.addon) === null || _a === void 0 ? void 0 : _a.name}`); }));
|
|
34
|
+
core_1.ux.styledHeader('Add-on Drains');
|
|
35
|
+
addons.forEach(({ body: addon }, i) => {
|
|
36
|
+
var _a;
|
|
37
|
+
styledDrain(color_1.default.yellow(((_a = addon.plan) === null || _a === void 0 ? void 0 : _a.name) || ''), color_1.default.green(addon.name || ''), drainsWithAddons[i]);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
exports.default = Drains;
|
|
44
|
+
Drains.description = 'display the log drains of an app';
|
|
45
|
+
Drains.flags = {
|
|
46
|
+
app: command_1.flags.app({ required: true }),
|
|
47
|
+
extended: command_1.flags.boolean({ char: 'x', hidden: true }),
|
|
48
|
+
json: command_1.flags.boolean({ description: 'output in json format' }),
|
|
49
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Command } from '@heroku-cli/command';
|
|
2
|
+
export default class Remove extends Command {
|
|
3
|
+
static description: string;
|
|
4
|
+
static flags: {
|
|
5
|
+
app: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
6
|
+
};
|
|
7
|
+
static example: string;
|
|
8
|
+
static args: {
|
|
9
|
+
url: import("@oclif/core/lib/interfaces/parser").Arg<string, Record<string, unknown>>;
|
|
10
|
+
};
|
|
11
|
+
run(): Promise<void>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
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
|
+
class Remove extends command_1.Command {
|
|
7
|
+
async run() {
|
|
8
|
+
const { flags, args } = await this.parse(Remove);
|
|
9
|
+
const { body: drain } = await this.heroku.delete(`/apps/${flags.app}/log-drains/${encodeURIComponent(args.url)}`);
|
|
10
|
+
core_1.ux.log(`Successfully removed drain ${color_1.default.cyan(drain.url || '')}`);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
exports.default = Remove;
|
|
14
|
+
Remove.description = 'removes a log drain from an app';
|
|
15
|
+
Remove.flags = {
|
|
16
|
+
app: command_1.flags.app({ required: true }),
|
|
17
|
+
};
|
|
18
|
+
Remove.example = 'drains:remove [URL|TOKEN]';
|
|
19
|
+
Remove.args = {
|
|
20
|
+
url: core_1.Args.string({ required: true }),
|
|
21
|
+
};
|
|
@@ -5,7 +5,7 @@ const command_1 = require("@heroku-cli/command");
|
|
|
5
5
|
const completions_1 = require("@heroku-cli/command/lib/completions");
|
|
6
6
|
const core_1 = require("@oclif/core");
|
|
7
7
|
const inquirer_1 = require("inquirer");
|
|
8
|
-
const api_1 = require("../../lib/
|
|
8
|
+
const api_1 = require("../../lib/api");
|
|
9
9
|
const disambiguate_1 = require("../../lib/pipelines/disambiguate");
|
|
10
10
|
const infer_1 = require("../../lib/pipelines/infer");
|
|
11
11
|
const stages_1 = require("../../lib/pipelines/stages");
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const command_1 = require("@heroku-cli/command");
|
|
4
4
|
const core_1 = require("@oclif/core");
|
|
5
|
-
const api_1 = require("../../lib/
|
|
5
|
+
const api_1 = require("../../lib/api");
|
|
6
6
|
const github_api_1 = require("../../lib/pipelines/github-api");
|
|
7
7
|
const kolkrabbi_api_1 = require("../../lib/pipelines/kolkrabbi-api");
|
|
8
8
|
const get_github_token_1 = require("../../lib/pipelines/setup/get-github-token");
|
|
@@ -5,7 +5,7 @@ const command_1 = require("@heroku-cli/command");
|
|
|
5
5
|
const completions_1 = require("@heroku-cli/command/lib/completions");
|
|
6
6
|
const core_1 = require("@oclif/core");
|
|
7
7
|
const inquirer_1 = require("inquirer");
|
|
8
|
-
const api_1 = require("../../lib/
|
|
8
|
+
const api_1 = require("../../lib/api");
|
|
9
9
|
const infer_1 = require("../../lib/pipelines/infer");
|
|
10
10
|
const stages_1 = require("../../lib/pipelines/stages");
|
|
11
11
|
class Create extends command_1.Command {
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
const color_1 = require("@heroku-cli/color");
|
|
4
4
|
const command_1 = require("@heroku-cli/command");
|
|
5
5
|
const core_1 = require("@oclif/core");
|
|
6
|
-
const api_1 = require("../../lib/
|
|
6
|
+
const api_1 = require("../../lib/api");
|
|
7
7
|
const disambiguate_1 = require("../../lib/pipelines/disambiguate");
|
|
8
8
|
class PipelinesDestroy extends command_1.Command {
|
|
9
9
|
async run() {
|