@contrail/cli 3.1.7 → 3.2.0
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 -1
- package/dist/commands/app/extension/deploy.js +2 -2
- package/dist/commands/app/extension/deployment/list.js +2 -2
- package/dist/helpers/app/app-deployer.js +25 -0
- package/dist/helpers/app/{extension-package.js → extension-package-deployer.js} +1 -4
- package/dist/helpers/app/metadata-extractor.d.ts +1 -0
- package/dist/helpers/app/metadata-extractor.js +100 -0
- package/oclif.manifest.json +1 -1
- package/package.json +1 -1
- /package/dist/helpers/app/{extension-package.d.ts → extension-package-deployer.d.ts} +0 -0
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@ $ npm install -g @contrail/cli
|
|
|
17
17
|
$ contrail COMMAND
|
|
18
18
|
running command...
|
|
19
19
|
$ contrail (--version)
|
|
20
|
-
@contrail/cli/3.
|
|
20
|
+
@contrail/cli/3.2.0 darwin-arm64 node-v20.18.0
|
|
21
21
|
$ contrail --help [COMMAND]
|
|
22
22
|
USAGE
|
|
23
23
|
$ contrail COMMAND
|
|
@@ -10,7 +10,7 @@ const app_extension_packages_1 = require("../../../api/app-extension-packages");
|
|
|
10
10
|
const apps_1 = require("../../../api/apps");
|
|
11
11
|
const login_1 = require("../../../auth/login");
|
|
12
12
|
const basecommand_1 = require("../../../basecommand");
|
|
13
|
-
const
|
|
13
|
+
const extension_package_deployer_1 = require("../../../helpers/app/extension-package-deployer");
|
|
14
14
|
const load_app_config_1 = require("../../../helpers/app/load-app-config");
|
|
15
15
|
const interfaces_1 = require("../../../interfaces");
|
|
16
16
|
const logger_1 = tslib_1.__importDefault(require("../../../logger"));
|
|
@@ -40,7 +40,7 @@ class DeployExtension extends basecommand_1.BaseCommand {
|
|
|
40
40
|
await this.validateExtensionDeclaration(appDeclaration, extensionIdentifier);
|
|
41
41
|
const extensionDir = this.getExtensionDirectory(extensionIdentifier);
|
|
42
42
|
// 2. Package and upload extension
|
|
43
|
-
const createdPackage = await (0,
|
|
43
|
+
const createdPackage = await (0, extension_package_deployer_1.createExtensionPackage)(app.id, extensionDir, { debug: this.flags.debug });
|
|
44
44
|
// 3. Poll until package is ready (timeout after 1 minute)
|
|
45
45
|
const readyPackage = await this.pollUntilPackageIsReady(createdPackage);
|
|
46
46
|
logger_1.default.info("Extension package is ready...Checking for extension deployment");
|
|
@@ -6,7 +6,7 @@ const core_1 = require("@oclif/core");
|
|
|
6
6
|
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
7
7
|
const login_1 = require("../../../../auth/login");
|
|
8
8
|
const basecommand_1 = require("../../../../basecommand");
|
|
9
|
-
const
|
|
9
|
+
const extension_package_deployer_1 = require("../../../../helpers/app/extension-package-deployer");
|
|
10
10
|
const load_app_config_1 = require("../../../../helpers/app/load-app-config");
|
|
11
11
|
const logger_1 = tslib_1.__importDefault(require("../../../../logger"));
|
|
12
12
|
const lodash_1 = require("lodash");
|
|
@@ -26,7 +26,7 @@ class ListExtensionDeployments extends basecommand_1.BaseCommand {
|
|
|
26
26
|
await (0, login_1.authUser)();
|
|
27
27
|
logger_1.default.info(`${chalk_1.default.blue.bold('START')} Listing extension deployments.`);
|
|
28
28
|
const appDeclaration = (0, load_app_config_1.loadAppConfig)();
|
|
29
|
-
const app = await (0,
|
|
29
|
+
const app = await (0, extension_package_deployer_1.getExistingApp)(appDeclaration);
|
|
30
30
|
const packages = this.flags.all
|
|
31
31
|
? await this.getAllExtensionPackages(app.id)
|
|
32
32
|
: await this.getLatest20ExtensionPackages(app.id);
|
|
@@ -14,6 +14,7 @@ const logger_1 = tslib_1.__importDefault(require("../../logger"));
|
|
|
14
14
|
const child_process_1 = tslib_1.__importDefault(require("child_process"));
|
|
15
15
|
const fs_1 = tslib_1.__importDefault(require("fs"));
|
|
16
16
|
const extensions_deployer_1 = require("./extensions-deployer");
|
|
17
|
+
const metadata_extractor_1 = require("./metadata-extractor");
|
|
17
18
|
class AppDeployer {
|
|
18
19
|
debug;
|
|
19
20
|
dryRun;
|
|
@@ -165,6 +166,25 @@ class AppDeployer {
|
|
|
165
166
|
}
|
|
166
167
|
}
|
|
167
168
|
exports.AppDeployer = AppDeployer;
|
|
169
|
+
async function createSourceArchive(tmpDir) {
|
|
170
|
+
logger_1.default.info('Creating source code archive...');
|
|
171
|
+
const sourceFiles = ['src/', 'package.json', 'app.yml'];
|
|
172
|
+
if (fs_1.default.existsSync('package-lock.json')) {
|
|
173
|
+
sourceFiles.push('package-lock.json');
|
|
174
|
+
}
|
|
175
|
+
const sourceDir = `${tmpDir}/source`;
|
|
176
|
+
fs_1.default.mkdirSync(sourceDir, { recursive: true });
|
|
177
|
+
sourceFiles.forEach((sourceFile) => {
|
|
178
|
+
if (!fs_1.default.existsSync(sourceFile))
|
|
179
|
+
return;
|
|
180
|
+
const isDirectory = fs_1.default.statSync(sourceFile).isDirectory();
|
|
181
|
+
const copyOptions = isDirectory ? { recursive: true } : undefined;
|
|
182
|
+
fs_1.default.cpSync(sourceFile, `${sourceDir}/${sourceFile}`, copyOptions);
|
|
183
|
+
});
|
|
184
|
+
await (0, zip_a_folder_1.zip)(`${sourceDir}/`, `${tmpDir}/source-code.zip`);
|
|
185
|
+
logger_1.default.info('Source code archive created.');
|
|
186
|
+
return `${tmpDir}/source-code.zip`;
|
|
187
|
+
}
|
|
168
188
|
async function createNodePackage(appIdentifier, debug, dryRun) {
|
|
169
189
|
// zip src code and package.json and package-lock.json files into a zip file
|
|
170
190
|
// and upload as a code package.
|
|
@@ -178,6 +198,8 @@ async function createNodePackage(appIdentifier, debug, dryRun) {
|
|
|
178
198
|
fs_1.default.cpSync('package-lock.json', 'tmp/package-lock.json');
|
|
179
199
|
}
|
|
180
200
|
fs_1.default.mkdirSync('tmp/node_modules', { recursive: true });
|
|
201
|
+
const buildInfoPath = await (0, metadata_extractor_1.createBuildMetadata)('tmp');
|
|
202
|
+
const sourceArchivePath = await createSourceArchive('tmp');
|
|
181
203
|
logger_1.default.info('Installing production dependencies started...');
|
|
182
204
|
child_process_1.default.execSync('npm install --omit=dev --prefix tmp/');
|
|
183
205
|
logger_1.default.info('Installing production dependencies done.');
|
|
@@ -199,6 +221,9 @@ async function createNodePackage(appIdentifier, debug, dryRun) {
|
|
|
199
221
|
logger_1.default.info('Copying Assets done.');
|
|
200
222
|
// including the app.yml file in the package at the dist level
|
|
201
223
|
fs_1.default.cpSync('app.yml', 'tmp/dist/app.yml');
|
|
224
|
+
// Copy build info and source code zip to dist
|
|
225
|
+
fs_1.default.cpSync(buildInfoPath, 'tmp/dist/build-info.json');
|
|
226
|
+
fs_1.default.cpSync(sourceArchivePath, 'tmp/dist/source-code.zip');
|
|
202
227
|
logger_1.default.info('Zipping package...');
|
|
203
228
|
await (0, zip_a_folder_1.zip)('tmp/', 'tmp.zip');
|
|
204
229
|
logger_1.default.info('Zipping package done.');
|
|
@@ -96,10 +96,7 @@ async function uploadExtensionPackage(appExtensionPackage, tmpDir, options) {
|
|
|
96
96
|
});
|
|
97
97
|
logger_1.default.debug(`${chalk_1.default.green.bold('EXTENSION')} Uploaded extension package to ${appExtensionPackage.uploadURL}`);
|
|
98
98
|
logger_1.default.info(`${chalk_1.default.green.bold('EXTENSION')} Extension package uploaded. ID: ${appExtensionPackage.id}`);
|
|
99
|
-
if (
|
|
100
|
-
logger_1.default.debug(JSON.stringify(result, null, 2));
|
|
101
|
-
}
|
|
102
|
-
if (result.status !== 200) {
|
|
99
|
+
if (result.status < 200 || result.status >= 300) {
|
|
103
100
|
logger_1.default.error(`${chalk_1.default.red.bold('EXTENSION')} Failed to upload extension package. Status: ${result.status}`);
|
|
104
101
|
logger_1.default.error(JSON.stringify(result, null, 2));
|
|
105
102
|
throw new Error(`Failed to upload extension package. Status: ${result.status}`);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function createBuildMetadata(tmpDir: string): string;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createBuildMetadata = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const os = tslib_1.__importStar(require("os"));
|
|
6
|
+
const child_process_1 = require("child_process");
|
|
7
|
+
const fs_1 = tslib_1.__importDefault(require("fs"));
|
|
8
|
+
function createBuildMetadata(tmpDir) {
|
|
9
|
+
const buildTimestamp = new Date();
|
|
10
|
+
const systemInfo = {
|
|
11
|
+
nodeVersion: process.version,
|
|
12
|
+
platform: process.platform,
|
|
13
|
+
architecture: process.arch,
|
|
14
|
+
operatingSystem: os.type(),
|
|
15
|
+
osRelease: os.release(),
|
|
16
|
+
hostname: os.hostname(),
|
|
17
|
+
totalMemory: os.totalmem(),
|
|
18
|
+
freeMemory: os.freemem(),
|
|
19
|
+
cpuCount: os.cpus().length,
|
|
20
|
+
cpuModel: os.cpus()[0]?.model || 'unknown',
|
|
21
|
+
homeDirectory: os.homedir(),
|
|
22
|
+
tmpDirectory: os.tmpdir(),
|
|
23
|
+
processId: process.pid,
|
|
24
|
+
processTitle: process.title,
|
|
25
|
+
execPath: process.execPath,
|
|
26
|
+
workingDirectory: process.cwd(),
|
|
27
|
+
};
|
|
28
|
+
const environmentInfo = {
|
|
29
|
+
shell: process.env.SHELL,
|
|
30
|
+
term: process.env.TERM,
|
|
31
|
+
lang: process.env.LANG,
|
|
32
|
+
timezone: process.env.TZ || Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
33
|
+
};
|
|
34
|
+
let gitInfo = {};
|
|
35
|
+
try {
|
|
36
|
+
const gitCommitHash = (0, child_process_1.execSync)('git rev-parse HEAD', {
|
|
37
|
+
encoding: 'utf8',
|
|
38
|
+
timeout: 5000,
|
|
39
|
+
}).trim();
|
|
40
|
+
const gitBranch = (0, child_process_1.execSync)('git rev-parse --abbrev-ref HEAD', {
|
|
41
|
+
encoding: 'utf8',
|
|
42
|
+
timeout: 5000,
|
|
43
|
+
}).trim();
|
|
44
|
+
const gitRemoteUrl = (0, child_process_1.execSync)('git config --get remote.origin.url', {
|
|
45
|
+
encoding: 'utf8',
|
|
46
|
+
timeout: 5000,
|
|
47
|
+
}).trim();
|
|
48
|
+
const gitCommitMessage = (0, child_process_1.execSync)('git log -1 --pretty=%B', {
|
|
49
|
+
encoding: 'utf8',
|
|
50
|
+
timeout: 5000,
|
|
51
|
+
}).trim();
|
|
52
|
+
const gitAuthor = (0, child_process_1.execSync)('git log -1 --pretty=format:"%an <%ae>"', {
|
|
53
|
+
encoding: 'utf8',
|
|
54
|
+
timeout: 5000,
|
|
55
|
+
}).trim();
|
|
56
|
+
const gitCommitDate = (0, child_process_1.execSync)('git log -1 --pretty=format:"%ai"', {
|
|
57
|
+
encoding: 'utf8',
|
|
58
|
+
timeout: 5000,
|
|
59
|
+
}).trim();
|
|
60
|
+
const gitTagsOutput = (0, child_process_1.execSync)('git tag --points-at HEAD', {
|
|
61
|
+
encoding: 'utf8',
|
|
62
|
+
timeout: 5000,
|
|
63
|
+
}).trim();
|
|
64
|
+
const gitTags = gitTagsOutput ? gitTagsOutput.split('\n') : [];
|
|
65
|
+
gitInfo = {
|
|
66
|
+
commitHash: gitCommitHash,
|
|
67
|
+
shortCommitHash: gitCommitHash.substring(0, 8),
|
|
68
|
+
branch: gitBranch,
|
|
69
|
+
remoteUrl: gitRemoteUrl,
|
|
70
|
+
commitMessage: gitCommitMessage,
|
|
71
|
+
author: gitAuthor,
|
|
72
|
+
commitDate: gitCommitDate,
|
|
73
|
+
tags: gitTags,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
gitInfo = {
|
|
78
|
+
error: 'Git information unavailable',
|
|
79
|
+
message: error instanceof Error ? error.message : 'Unknown git error',
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
const buildInfo = {
|
|
83
|
+
buildTimestamp: buildTimestamp.toISOString(),
|
|
84
|
+
buildTimestampUnix: Math.floor(buildTimestamp.getTime() / 1000),
|
|
85
|
+
buildTool: 'contrail-cli',
|
|
86
|
+
buildUser: process.env.USER || process.env.USERNAME || 'unknown',
|
|
87
|
+
system: systemInfo,
|
|
88
|
+
environment: environmentInfo,
|
|
89
|
+
git: gitInfo,
|
|
90
|
+
metadata: {
|
|
91
|
+
schemaVersion: '1.0.0',
|
|
92
|
+
generatedBy: 'contrail-cli-app-deployer',
|
|
93
|
+
purpose: 'Build and deployment metadata for debugging and auditing',
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
const buildInfoPath = `${tmpDir}/build-info.json`;
|
|
97
|
+
fs_1.default.writeFileSync(buildInfoPath, JSON.stringify(buildInfo, null, 2));
|
|
98
|
+
return buildInfoPath;
|
|
99
|
+
}
|
|
100
|
+
exports.createBuildMetadata = createBuildMetadata;
|
package/oclif.manifest.json
CHANGED
package/package.json
CHANGED
|
File without changes
|