@phystack/cli 4.3.40-dev
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/LICENSE.md +19 -0
- package/README.md +24 -0
- package/bin/index.js +2 -0
- package/dist/commands/app/build-apps.js +66 -0
- package/dist/commands/app/build-apps.js.map +1 -0
- package/dist/commands/app/build-container-remote.js +171 -0
- package/dist/commands/app/build-container-remote.js.map +1 -0
- package/dist/commands/app/build-container.js +330 -0
- package/dist/commands/app/build-container.js.map +1 -0
- package/dist/commands/app/build.js +393 -0
- package/dist/commands/app/build.js.map +1 -0
- package/dist/commands/app/create.js +451 -0
- package/dist/commands/app/create.js.map +1 -0
- package/dist/commands/app/deploy.js +176 -0
- package/dist/commands/app/deploy.js.map +1 -0
- package/dist/commands/app/device-picker.js +150 -0
- package/dist/commands/app/device-picker.js.map +1 -0
- package/dist/commands/app/import.js +303 -0
- package/dist/commands/app/import.js.map +1 -0
- package/dist/commands/app/list.js +26 -0
- package/dist/commands/app/list.js.map +1 -0
- package/dist/commands/app/publish.js +327 -0
- package/dist/commands/app/publish.js.map +1 -0
- package/dist/commands/app/settings.js +129 -0
- package/dist/commands/app/settings.js.map +1 -0
- package/dist/commands/app/types.js +13 -0
- package/dist/commands/app/types.js.map +1 -0
- package/dist/commands/app/upload-description.js +139 -0
- package/dist/commands/app/upload-description.js.map +1 -0
- package/dist/commands/app/upload-settings.js +29 -0
- package/dist/commands/app/upload-settings.js.map +1 -0
- package/dist/commands/app/utils.js +86 -0
- package/dist/commands/app/utils.js.map +1 -0
- package/dist/commands/auth/login.js +111 -0
- package/dist/commands/auth/login.js.map +1 -0
- package/dist/commands/auth/logout.js +19 -0
- package/dist/commands/auth/logout.js.map +1 -0
- package/dist/commands/descriptor/create.js +143 -0
- package/dist/commands/descriptor/create.js.map +1 -0
- package/dist/commands/descriptor/index.js +36 -0
- package/dist/commands/descriptor/index.js.map +1 -0
- package/dist/commands/descriptor/publish.js +163 -0
- package/dist/commands/descriptor/publish.js.map +1 -0
- package/dist/commands/descriptor/show.js +68 -0
- package/dist/commands/descriptor/show.js.map +1 -0
- package/dist/commands/dev/develop.js +175 -0
- package/dist/commands/dev/develop.js.map +1 -0
- package/dist/commands/dev/forward.js +118 -0
- package/dist/commands/dev/forward.js.map +1 -0
- package/dist/commands/dev/index.js +66 -0
- package/dist/commands/dev/index.js.map +1 -0
- package/dist/commands/dev/list.js +96 -0
- package/dist/commands/dev/list.js.map +1 -0
- package/dist/commands/dev/screen-devtools.js +156 -0
- package/dist/commands/dev/screen-devtools.js.map +1 -0
- package/dist/commands/dev/select.js +118 -0
- package/dist/commands/dev/select.js.map +1 -0
- package/dist/commands/dev/shell.js +171 -0
- package/dist/commands/dev/shell.js.map +1 -0
- package/dist/commands/dev/vnc.js +75 -0
- package/dist/commands/dev/vnc.js.map +1 -0
- package/dist/commands/device/select.js +118 -0
- package/dist/commands/device/select.js.map +1 -0
- package/dist/commands/flash.js +1120 -0
- package/dist/commands/flash.js.map +1 -0
- package/dist/commands/inst/create.js +55 -0
- package/dist/commands/inst/create.js.map +1 -0
- package/dist/commands/inst/index.js +15 -0
- package/dist/commands/inst/index.js.map +1 -0
- package/dist/commands/inst/list.js +26 -0
- package/dist/commands/inst/list.js.map +1 -0
- package/dist/commands/legacydev/debug.js +11 -0
- package/dist/commands/legacydev/debug.js.map +1 -0
- package/dist/commands/legacydev/deploy.js +15 -0
- package/dist/commands/legacydev/deploy.js.map +1 -0
- package/dist/commands/legacydev/dumpTwin.js +27 -0
- package/dist/commands/legacydev/dumpTwin.js.map +1 -0
- package/dist/commands/legacydev/forward.js +104 -0
- package/dist/commands/legacydev/forward.js.map +1 -0
- package/dist/commands/legacydev/index.js +188 -0
- package/dist/commands/legacydev/index.js.map +1 -0
- package/dist/commands/legacydev/invoke.js +29 -0
- package/dist/commands/legacydev/invoke.js.map +1 -0
- package/dist/commands/legacydev/js.js +69 -0
- package/dist/commands/legacydev/js.js.map +1 -0
- package/dist/commands/legacydev/list.js +196 -0
- package/dist/commands/legacydev/list.js.map +1 -0
- package/dist/commands/legacydev/logs.js +60 -0
- package/dist/commands/legacydev/logs.js.map +1 -0
- package/dist/commands/legacydev/modules.js +50 -0
- package/dist/commands/legacydev/modules.js.map +1 -0
- package/dist/commands/legacydev/move.js +23 -0
- package/dist/commands/legacydev/move.js.map +1 -0
- package/dist/commands/legacydev/ota.js +88 -0
- package/dist/commands/legacydev/ota.js.map +1 -0
- package/dist/commands/legacydev/patchTwin.js +21 -0
- package/dist/commands/legacydev/patchTwin.js.map +1 -0
- package/dist/commands/legacydev/pin.js +23 -0
- package/dist/commands/legacydev/pin.js.map +1 -0
- package/dist/commands/legacydev/pub.js +25 -0
- package/dist/commands/legacydev/pub.js.map +1 -0
- package/dist/commands/legacydev/rdp.js +64 -0
- package/dist/commands/legacydev/rdp.js.map +1 -0
- package/dist/commands/legacydev/screen-devtools.js +142 -0
- package/dist/commands/legacydev/screen-devtools.js.map +1 -0
- package/dist/commands/legacydev/settingsShow.js +89 -0
- package/dist/commands/legacydev/settingsShow.js.map +1 -0
- package/dist/commands/legacydev/settingsUpdate.js +114 -0
- package/dist/commands/legacydev/settingsUpdate.js.map +1 -0
- package/dist/commands/legacydev/shell.js +167 -0
- package/dist/commands/legacydev/shell.js.map +1 -0
- package/dist/commands/legacydev/showTwin.js +9 -0
- package/dist/commands/legacydev/showTwin.js.map +1 -0
- package/dist/commands/legacydev/statusLog.js +56 -0
- package/dist/commands/legacydev/statusLog.js.map +1 -0
- package/dist/commands/legacydev/sub.js +39 -0
- package/dist/commands/legacydev/sub.js.map +1 -0
- package/dist/commands/legacydev/vnc.js +61 -0
- package/dist/commands/legacydev/vnc.js.map +1 -0
- package/dist/commands/tenant/index.js +21 -0
- package/dist/commands/tenant/index.js.map +1 -0
- package/dist/commands/tenant/list.js +14 -0
- package/dist/commands/tenant/list.js.map +1 -0
- package/dist/commands/tenant/select.js +87 -0
- package/dist/commands/tenant/select.js.map +1 -0
- package/dist/commands/vm/create.js +718 -0
- package/dist/commands/vm/create.js.map +1 -0
- package/dist/commands/vm/index.js +130 -0
- package/dist/commands/vm/index.js.map +1 -0
- package/dist/commands/vm/list.js +124 -0
- package/dist/commands/vm/list.js.map +1 -0
- package/dist/commands/vm/logs.js +66 -0
- package/dist/commands/vm/logs.js.map +1 -0
- package/dist/commands/vm/remove.js +180 -0
- package/dist/commands/vm/remove.js.map +1 -0
- package/dist/commands/vm/shell.js +400 -0
- package/dist/commands/vm/shell.js.map +1 -0
- package/dist/commands/vm/start.js +861 -0
- package/dist/commands/vm/start.js.map +1 -0
- package/dist/commands/vm/stop.js +232 -0
- package/dist/commands/vm/stop.js.map +1 -0
- package/dist/index.js +158 -0
- package/dist/index.js.map +1 -0
- package/dist/services/admin-api/admin-api.types.js +3 -0
- package/dist/services/admin-api/admin-api.types.js.map +1 -0
- package/dist/services/admin-api/device-modules.admin-api.service.js +58 -0
- package/dist/services/admin-api/device-modules.admin-api.service.js.map +1 -0
- package/dist/services/admin-api/devices-admin-api.service.js +213 -0
- package/dist/services/admin-api/devices-admin-api.service.js.map +1 -0
- package/dist/services/admin-api/gridapps-admin-api.service.js +59 -0
- package/dist/services/admin-api/gridapps-admin-api.service.js.map +1 -0
- package/dist/services/admin-api/index.js +157 -0
- package/dist/services/admin-api/index.js.map +1 -0
- package/dist/services/admin-api/installations-admin-api.service.js +29 -0
- package/dist/services/admin-api/installations-admin-api.service.js.map +1 -0
- package/dist/services/admin-api/organizations-admin-api.service.js +53 -0
- package/dist/services/admin-api/organizations-admin-api.service.js.map +1 -0
- package/dist/services/auth/device-grant-auth.service.js +224 -0
- package/dist/services/auth/device-grant-auth.service.js.map +1 -0
- package/dist/services/phyhub/index.js +200 -0
- package/dist/services/phyhub/index.js.map +1 -0
- package/dist/services/phyhub/phyhub.types.js +3 -0
- package/dist/services/phyhub/phyhub.types.js.map +1 -0
- package/dist/utils/device-fetcher.js +92 -0
- package/dist/utils/device-fetcher.js.map +1 -0
- package/dist/utils/devices.js +41 -0
- package/dist/utils/devices.js.map +1 -0
- package/dist/utils/docker-credentials.js +720 -0
- package/dist/utils/docker-credentials.js.map +1 -0
- package/dist/utils/emulated-device.js +91 -0
- package/dist/utils/emulated-device.js.map +1 -0
- package/dist/utils/index.js +180 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/modules.js +36 -0
- package/dist/utils/modules.js.map +1 -0
- package/dist/utils/org-selector.js +108 -0
- package/dist/utils/org-selector.js.map +1 -0
- package/dist/utils/proxy.js +31 -0
- package/dist/utils/proxy.js.map +1 -0
- package/dist/utils/registry-credentials.js +113 -0
- package/dist/utils/registry-credentials.js.map +1 -0
- package/dist/utils/statuses.js +124 -0
- package/dist/utils/statuses.js.map +1 -0
- package/dist/utils/templates.js +197 -0
- package/dist/utils/templates.js.map +1 -0
- package/dist/utils/tenant-storage.js +88 -0
- package/dist/utils/tenant-storage.js.map +1 -0
- package/dist/utils/vm.js +434 -0
- package/dist/utils/vm.js.map +1 -0
- package/dist/utils/with-spinner.js +20 -0
- package/dist/utils/with-spinner.js.map +1 -0
- package/package.json +103 -0
package/LICENSE.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
5
|
+
in the Software without restriction, including without limitation the rights
|
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
8
|
+
furnished to do so, subject to the following conditions:
|
|
9
|
+
|
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
|
11
|
+
copies or substantial portions of the Software.
|
|
12
|
+
|
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
19
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Phygrid Grid CLI (phy)
|
|
2
|
+
|
|
3
|
+
The [phy cli](https://developer.omborigrid.com/#/cli/setup) is a supplementary tool for Phygrid development and device management.
|
|
4
|
+
Phygrid Console: [console.omborigrid.com](https://console.omborigrid.com/)
|
|
5
|
+
|
|
6
|
+
## 📦 Install
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
npm i -g @phystack/cli
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## 🔨 Instructions
|
|
13
|
+
|
|
14
|
+
Explore other commands using the `--help` command
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
phy --help
|
|
18
|
+
phy -h
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## 🔗 Links
|
|
22
|
+
- [Phygrid Website](https://phygrid.com/)
|
|
23
|
+
- [CLI Setup](https://developer.omborigrid.com/#/cli/setup)
|
|
24
|
+
- [Other Commands](https://developer.omborigrid.com/#/cli/reference)
|
package/bin/index.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
9
|
+
const cross_spawn_1 = __importDefault(require("cross-spawn"));
|
|
10
|
+
const execCommand = (cmd, cwd, args = []) => {
|
|
11
|
+
const result = cross_spawn_1.default.sync(cmd, args, {
|
|
12
|
+
cwd,
|
|
13
|
+
stdio: ['inherit', 'inherit'],
|
|
14
|
+
shell: true,
|
|
15
|
+
});
|
|
16
|
+
const stderrStr = result.stderr?.toString() || '';
|
|
17
|
+
if (result.status !== 0 ||
|
|
18
|
+
stderrStr.indexOf('UnhandledPromiseRejectionWarning') !== -1) {
|
|
19
|
+
throw new Error(`Error running: ${cmd}: ${stderrStr}`);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
exports.default = async () => {
|
|
23
|
+
try {
|
|
24
|
+
const cwd = process.cwd();
|
|
25
|
+
const gridAppsPath = path_1.default.join(cwd, 'public', 'gridapps');
|
|
26
|
+
const gridSettingsPath = path_1.default.join(cwd, 'grid-settings');
|
|
27
|
+
if (!fs_extra_1.default.existsSync(gridSettingsPath)) {
|
|
28
|
+
throw new Error(`Grid settings not found: ${gridSettingsPath}`);
|
|
29
|
+
}
|
|
30
|
+
fs_extra_1.default.ensureDirSync(gridAppsPath);
|
|
31
|
+
console.log(`Created dir: ${gridAppsPath}`);
|
|
32
|
+
// eslint-disable-next-line
|
|
33
|
+
const { general: generalSettings } = require(gridSettingsPath);
|
|
34
|
+
// example release value: GridApp v1.1.0
|
|
35
|
+
const packageVersion = generalSettings.release.split('v')[1];
|
|
36
|
+
try {
|
|
37
|
+
// download pre-built version of app-container
|
|
38
|
+
fs_extra_1.default.mkdirSync(`${gridAppsPath}/app-container`);
|
|
39
|
+
execCommand(`curl https://app.omborigrid.com/app-container/${packageVersion}/app-container.tar | tar xf - -C app-container`, gridAppsPath);
|
|
40
|
+
}
|
|
41
|
+
catch (e) {
|
|
42
|
+
const packageNameProviderPart = `ga-${generalSettings.provider}`;
|
|
43
|
+
const packageName = `@ombori/${packageNameProviderPart}@<=${packageVersion}`;
|
|
44
|
+
console.log(`Downloading package: ${packageName}`);
|
|
45
|
+
execCommand(`npm pack "${packageName}"`, gridAppsPath);
|
|
46
|
+
execCommand(`tar xf ombori-${packageNameProviderPart}*.tgz && rm ombori-${packageNameProviderPart}*.tgz`, gridAppsPath);
|
|
47
|
+
console.log(`Building package: ${packageName}`);
|
|
48
|
+
execCommand(`yarn && yarn build`, path_1.default.join(gridAppsPath, 'package'));
|
|
49
|
+
execCommand(`rm -rf ${generalSettings.provider}`, gridAppsPath); // remove directory if exists
|
|
50
|
+
execCommand(`mv package/build ${generalSettings.provider}`, gridAppsPath);
|
|
51
|
+
execCommand(`rm -rf package`, gridAppsPath);
|
|
52
|
+
}
|
|
53
|
+
// copy all grid apps that were part of grid settings to output dir
|
|
54
|
+
const gridAppDirs = fs_extra_1.default
|
|
55
|
+
.readdirSync(gridSettingsPath)
|
|
56
|
+
.filter((file) => fs_extra_1.default.statSync(path_1.default.join(gridSettingsPath, file)).isDirectory());
|
|
57
|
+
console.log(`Found grid app directories: ${gridAppDirs}, will be copied to output dir`);
|
|
58
|
+
await Promise.all(gridAppDirs.map((dir) => fs_extra_1.default.copy(path_1.default.join(gridSettingsPath, dir), path_1.default.join(gridAppsPath, dir))));
|
|
59
|
+
console.log(chalk_1.default.green(`✓ Build apps successful`));
|
|
60
|
+
}
|
|
61
|
+
catch (err) {
|
|
62
|
+
console.error(chalk_1.default.red(`❗️There was an error: ${err.message}`));
|
|
63
|
+
throw err;
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
//# sourceMappingURL=build-apps.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-apps.js","sourceRoot":"","sources":["../../../src/commands/app/build-apps.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.findArchs = void 0;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const child_process_1 = require("child_process");
|
|
10
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
11
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
12
|
+
const DEFAULT_REGISTRY = 'docker.io';
|
|
13
|
+
// Function to generate a random short unique ID
|
|
14
|
+
const generateShortId = () => {
|
|
15
|
+
return crypto_1.default.randomBytes(4).toString('hex');
|
|
16
|
+
};
|
|
17
|
+
const runRemoteCommand = async (deviceHostname, command, checkOutput = false) => {
|
|
18
|
+
return new Promise((resolve, reject) => {
|
|
19
|
+
let output = '';
|
|
20
|
+
const sshProcess = (0, child_process_1.spawn)('ssh', ['-tt', `dev@${deviceHostname}`, `TERM=xterm-256color ${command}`], {
|
|
21
|
+
stdio: checkOutput
|
|
22
|
+
? ['inherit', 'pipe', 'inherit']
|
|
23
|
+
: ['inherit', 'inherit', 'inherit'],
|
|
24
|
+
});
|
|
25
|
+
if (checkOutput) {
|
|
26
|
+
sshProcess.stdout?.on('data', (data) => {
|
|
27
|
+
output += data.toString();
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
sshProcess.on('close', (code) => {
|
|
31
|
+
if (checkOutput) {
|
|
32
|
+
resolve(output.trim());
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
resolve(code === 0);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
sshProcess.on('error', (error) => {
|
|
39
|
+
console.error(chalk_1.default.red(`Failed to execute remote command: ${error.message}`));
|
|
40
|
+
reject(error);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
const getSystemArch = async (deviceHostname) => {
|
|
45
|
+
const arch = (await runRemoteCommand(deviceHostname, 'uname -m', true));
|
|
46
|
+
// Map common architecture names to our standard names
|
|
47
|
+
switch (arch) {
|
|
48
|
+
case 'x86_64':
|
|
49
|
+
return 'amd64';
|
|
50
|
+
case 'aarch64':
|
|
51
|
+
return 'arm64';
|
|
52
|
+
default:
|
|
53
|
+
throw new Error(`Unsupported architecture: ${arch}`);
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
const findArchs = (dir, currentArch) => {
|
|
57
|
+
const result = {};
|
|
58
|
+
// Check for architecture-specific Dockerfile
|
|
59
|
+
const specificDockerfile = `Dockerfile.${currentArch}`;
|
|
60
|
+
const hasSpecificDockerfile = fs_1.default.existsSync(path_1.default.join(dir, specificDockerfile));
|
|
61
|
+
// Check for generic Dockerfile
|
|
62
|
+
const hasGenericDockerfile = fs_1.default.existsSync(path_1.default.join(dir, 'Dockerfile'));
|
|
63
|
+
if (!hasSpecificDockerfile && !hasGenericDockerfile) {
|
|
64
|
+
throw new Error(`No Dockerfile found for architecture ${currentArch}. ` +
|
|
65
|
+
`Expected either 'Dockerfile.${currentArch}' or 'Dockerfile'`);
|
|
66
|
+
}
|
|
67
|
+
// If we have a specific Dockerfile for this architecture, use it
|
|
68
|
+
if (hasSpecificDockerfile) {
|
|
69
|
+
result[currentArch] = specificDockerfile;
|
|
70
|
+
}
|
|
71
|
+
// Otherwise use the generic Dockerfile if it exists
|
|
72
|
+
else if (hasGenericDockerfile) {
|
|
73
|
+
result[currentArch] = 'Dockerfile';
|
|
74
|
+
}
|
|
75
|
+
return result;
|
|
76
|
+
};
|
|
77
|
+
exports.findArchs = findArchs;
|
|
78
|
+
async function build({ tag, dir, arch, dockerfile, deviceHostname, remoteDir, phygridLocalNpm = false, isInProjectsDir = false }) {
|
|
79
|
+
// Convert ~ to /home/dev for remote paths
|
|
80
|
+
const fullRemoteDir = remoteDir.replace('~', '/home/dev');
|
|
81
|
+
console.log(chalk_1.default.dim('Checking for yarn installation...'));
|
|
82
|
+
await runRemoteCommand(deviceHostname, 'which yarn || sudo npm install -g yarn');
|
|
83
|
+
console.log(chalk_1.default.dim('Installing dependencies...'));
|
|
84
|
+
await runRemoteCommand(deviceHostname, `cd ${fullRemoteDir} && yarn install`);
|
|
85
|
+
console.log(chalk_1.default.dim('Building application...'));
|
|
86
|
+
await runRemoteCommand(deviceHostname, `cd ${fullRemoteDir} && yarn devbuild`);
|
|
87
|
+
const platform = arch === 'arm64' ? 'linux/arm64/v8' : 'linux/amd64';
|
|
88
|
+
console.log(chalk_1.default.dim(`Building Docker container for ${platform}...`));
|
|
89
|
+
// Add the build arg for PHYGRID_LOCAL_NPM if enabled
|
|
90
|
+
const buildArgs = phygridLocalNpm
|
|
91
|
+
? `--build-arg PHYGRID_LOCAL_NPM=true`
|
|
92
|
+
: '';
|
|
93
|
+
await runRemoteCommand(deviceHostname, `cd ${fullRemoteDir} && sudo docker buildx build ${buildArgs} --platform ${platform} --load --rm -f "${dockerfile}" -t ${tag} .`);
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
async function buildContainer({ name, version, registry, deviceHostname, remoteDir, customImageName, phygridLocalNpm = false, isInProjectsDir = false }) {
|
|
97
|
+
const currentArch = await getSystemArch(deviceHostname);
|
|
98
|
+
const archs = (0, exports.findArchs)(process.cwd(), currentArch);
|
|
99
|
+
console.log(chalk_1.default.dim(`Building ${chalk_1.default.blueBright(name)} for architecture ${chalk_1.default.greenBright(currentArch)}`));
|
|
100
|
+
// Use the custom image name if provided, otherwise construct it
|
|
101
|
+
const tag = customImageName || `${name}:${version}-${currentArch}`;
|
|
102
|
+
await build({
|
|
103
|
+
dir: process.cwd(),
|
|
104
|
+
tag,
|
|
105
|
+
arch: currentArch,
|
|
106
|
+
dockerfile: archs[currentArch],
|
|
107
|
+
deviceHostname,
|
|
108
|
+
remoteDir,
|
|
109
|
+
phygridLocalNpm,
|
|
110
|
+
isInProjectsDir
|
|
111
|
+
});
|
|
112
|
+
console.log(chalk_1.default.dim(`Build done ${tag}`));
|
|
113
|
+
return tag;
|
|
114
|
+
}
|
|
115
|
+
async function createLocalTwin(deviceHostname, image, createOptions) {
|
|
116
|
+
const twinConfig = {
|
|
117
|
+
type: 'Edge',
|
|
118
|
+
properties: {
|
|
119
|
+
desired: {
|
|
120
|
+
image,
|
|
121
|
+
createOptions,
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
};
|
|
125
|
+
const twinConfigJson = JSON.stringify(twinConfig).replace(/'/g, "\\'");
|
|
126
|
+
const command = `phyctl local create -t '${twinConfigJson}'`;
|
|
127
|
+
console.log(chalk_1.default.dim('Creating local twin...'));
|
|
128
|
+
await runRemoteCommand(deviceHostname, command);
|
|
129
|
+
}
|
|
130
|
+
exports.default = async (moduleName, { deviceHostname, remoteDir, phygridLocalNpm = false, isInProjectsDir = false }) => {
|
|
131
|
+
const cwd = process.cwd();
|
|
132
|
+
const packageFile = path_1.default.join(cwd, 'package.json');
|
|
133
|
+
const settingsFile = path_1.default.join(cwd, 'settings.json');
|
|
134
|
+
if (!fs_1.default.existsSync(packageFile)) {
|
|
135
|
+
throw new Error('Run this command from a module repository');
|
|
136
|
+
}
|
|
137
|
+
if (!fs_1.default.existsSync(settingsFile)) {
|
|
138
|
+
throw new Error('settings.json file is required');
|
|
139
|
+
}
|
|
140
|
+
const info = JSON.parse(fs_1.default.readFileSync(packageFile).toString());
|
|
141
|
+
const createOptions = JSON.parse(fs_1.default.readFileSync(settingsFile).toString());
|
|
142
|
+
const { name } = info;
|
|
143
|
+
const dockerCredentials = info['docker-credentials'];
|
|
144
|
+
const registry = dockerCredentials?.registry || info['container-registry'] || DEFAULT_REGISTRY;
|
|
145
|
+
const version = generateShortId();
|
|
146
|
+
// Check if a custom image name is specified in docker-credentials
|
|
147
|
+
let customImageName = null;
|
|
148
|
+
if (dockerCredentials?.image) {
|
|
149
|
+
customImageName = dockerCredentials.image;
|
|
150
|
+
console.log(chalk_1.default.dim(`Using custom image name from docker-credentials: ${chalk_1.default.blue(customImageName)}`));
|
|
151
|
+
}
|
|
152
|
+
// Log if using local phygrid-npm
|
|
153
|
+
if (phygridLocalNpm) {
|
|
154
|
+
console.log(chalk_1.default.cyan('Using local phygrid-npm packages for Docker build'));
|
|
155
|
+
}
|
|
156
|
+
console.log(chalk_1.default.dim(`Building ${name}...`));
|
|
157
|
+
const imageName = await buildContainer({
|
|
158
|
+
name,
|
|
159
|
+
version,
|
|
160
|
+
registry,
|
|
161
|
+
deviceHostname,
|
|
162
|
+
remoteDir,
|
|
163
|
+
customImageName,
|
|
164
|
+
phygridLocalNpm,
|
|
165
|
+
isInProjectsDir
|
|
166
|
+
});
|
|
167
|
+
// Create local twin with the built image
|
|
168
|
+
await createLocalTwin(deviceHostname, imageName, createOptions);
|
|
169
|
+
return imageName;
|
|
170
|
+
};
|
|
171
|
+
//# sourceMappingURL=build-container-remote.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-container-remote.js","sourceRoot":"","sources":["../../../src/commands/app/build-container-remote.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.findArchs = void 0;
|
|
7
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const child_process_1 = __importDefault(require("child_process"));
|
|
10
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
11
|
+
const docker_credentials_1 = require("../../utils/docker-credentials");
|
|
12
|
+
const registry_credentials_1 = require("../../utils/registry-credentials");
|
|
13
|
+
const DEFAULT_REGISTRY = 'docker.io';
|
|
14
|
+
const ALL_ARCHS = ['arm64', 'amd64'];
|
|
15
|
+
const findArchs = (dir, filter) => {
|
|
16
|
+
// Only support a single Dockerfile, no platform-specific Dockerfiles
|
|
17
|
+
const hasDockerfile = fs_extra_1.default.existsSync(path_1.default.join(dir, 'Dockerfile'));
|
|
18
|
+
if (!hasDockerfile) {
|
|
19
|
+
console.error(chalk_1.default.red('❌ Dockerfile not found. Please create a Dockerfile in the project root.'));
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
const result = {};
|
|
23
|
+
// Determine which architectures to include based on filter
|
|
24
|
+
if (filter === 'all') {
|
|
25
|
+
// Include all supported architectures
|
|
26
|
+
for (const arch of ALL_ARCHS) {
|
|
27
|
+
result[arch] = 'Dockerfile';
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
// Include only the specified architecture
|
|
32
|
+
result[filter] = 'Dockerfile';
|
|
33
|
+
}
|
|
34
|
+
return result;
|
|
35
|
+
};
|
|
36
|
+
exports.findArchs = findArchs;
|
|
37
|
+
function setupBuildxBuilder() {
|
|
38
|
+
const builderName = 'phygrid-multiplatform';
|
|
39
|
+
try {
|
|
40
|
+
// Check if our builder already exists
|
|
41
|
+
const result = child_process_1.default.execSync('docker buildx ls', { encoding: 'utf8' });
|
|
42
|
+
if (result.includes(builderName)) {
|
|
43
|
+
console.log(chalk_1.default.dim(`Using existing buildx builder: ${builderName}`));
|
|
44
|
+
// Make sure it's active
|
|
45
|
+
child_process_1.default.execSync(`docker buildx use ${builderName}`, { stdio: 'pipe' });
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
// Builder list failed, continue to create
|
|
51
|
+
}
|
|
52
|
+
console.log(chalk_1.default.dim('Setting up Docker buildx for multi-platform builds...'));
|
|
53
|
+
// Check if running in CI environment
|
|
54
|
+
const isCI = process.env.CI || process.env.GITHUB_ACTIONS || process.env.GITLAB_CI;
|
|
55
|
+
if (isCI) {
|
|
56
|
+
console.log(chalk_1.default.dim('CI environment detected, setting up QEMU and buildx...'));
|
|
57
|
+
// Set up QEMU for cross-platform emulation
|
|
58
|
+
try {
|
|
59
|
+
console.log(chalk_1.default.dim('Setting up QEMU for cross-platform builds...'));
|
|
60
|
+
child_process_1.default.execSync('docker run --rm --privileged multiarch/qemu-user-static --reset -p yes', {
|
|
61
|
+
stdio: 'inherit',
|
|
62
|
+
});
|
|
63
|
+
console.log(chalk_1.default.green('✓ QEMU set up successfully'));
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
console.log(chalk_1.default.yellow('Warning: QEMU setup failed, cross-platform builds may not work'));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// Create and use a new buildx builder instance
|
|
70
|
+
try {
|
|
71
|
+
console.log(chalk_1.default.dim(`Creating buildx builder: ${builderName}...`));
|
|
72
|
+
child_process_1.default.execSync(`docker buildx create --name ${builderName} --use --bootstrap`, {
|
|
73
|
+
stdio: 'inherit',
|
|
74
|
+
});
|
|
75
|
+
console.log(chalk_1.default.green(`✓ Buildx builder '${builderName}' created and activated`));
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
console.log(chalk_1.default.yellow('Warning: Failed to create buildx builder, trying default...'));
|
|
79
|
+
// Try to use the default builder
|
|
80
|
+
try {
|
|
81
|
+
child_process_1.default.execSync('docker buildx use default', { stdio: 'pipe' });
|
|
82
|
+
}
|
|
83
|
+
catch (e) {
|
|
84
|
+
throw new Error('Failed to set up Docker buildx for multi-platform builds');
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
async function build({ tag, dir, archs, dockerfiles, registry, pushCredentials, shouldPush = false, isPrivateRepo = false }) {
|
|
89
|
+
// Extract base image name without version tag for cache-from
|
|
90
|
+
const baseImage = tag.split(':')[0];
|
|
91
|
+
const cacheImage = `${baseImage}:latest`;
|
|
92
|
+
// Check if latest tag exists in registry for caching
|
|
93
|
+
let cacheFromArg = '';
|
|
94
|
+
try {
|
|
95
|
+
child_process_1.default.execSync(`docker manifest inspect ${cacheImage}`, { stdio: 'pipe' });
|
|
96
|
+
cacheFromArg = `--cache-from=${cacheImage}`;
|
|
97
|
+
console.log(chalk_1.default.dim(`Using cache from: ${cacheImage}`));
|
|
98
|
+
}
|
|
99
|
+
catch (e) {
|
|
100
|
+
// Cache image doesn't exist, skip cache-from arg
|
|
101
|
+
console.log(chalk_1.default.dim(`No cache image found: ${cacheImage}`));
|
|
102
|
+
}
|
|
103
|
+
// Build platforms string for all architectures
|
|
104
|
+
const platforms = archs
|
|
105
|
+
.map((arch) => (arch === 'arm64' ? 'linux/arm64/v8' : 'linux/amd64'))
|
|
106
|
+
.join(',');
|
|
107
|
+
const platformArg = `--platform=${platforms}`;
|
|
108
|
+
// Use first Dockerfile in the list (should be the same for multiarch builds)
|
|
109
|
+
const dockerfile = dockerfiles[0];
|
|
110
|
+
// Check if building for multiple platforms
|
|
111
|
+
const isMultiPlatform = archs.length > 1;
|
|
112
|
+
// Set up buildx for multi-platform builds if needed
|
|
113
|
+
if (isMultiPlatform || shouldPush) {
|
|
114
|
+
setupBuildxBuilder();
|
|
115
|
+
}
|
|
116
|
+
// Determine output strategy
|
|
117
|
+
let outputArg = '';
|
|
118
|
+
let cmdExplanation = '';
|
|
119
|
+
if (shouldPush) {
|
|
120
|
+
// Push to registry for publish command
|
|
121
|
+
outputArg = '--push';
|
|
122
|
+
cmdExplanation = 'Pushing image to registry...';
|
|
123
|
+
// Login to Docker registry with push credentials (only needed when pushing)
|
|
124
|
+
if (pushCredentials && pushCredentials.username && pushCredentials.password) {
|
|
125
|
+
console.log(chalk_1.default.dim(`Logging in to registry ${registry} with push credentials...`));
|
|
126
|
+
try {
|
|
127
|
+
child_process_1.default.execSync(`docker login ${registry} -u ${pushCredentials.username} -p ${pushCredentials.password}`, { stdio: 'pipe' });
|
|
128
|
+
console.log(chalk_1.default.green('✓ Logged in to registry for pushing'));
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
console.error(chalk_1.default.red(`Failed to login to registry: ${error.message}`));
|
|
132
|
+
// Continue with build as Docker might use cached credentials
|
|
133
|
+
}
|
|
134
|
+
// For Docker Hub, ensure the repository exists before pushing
|
|
135
|
+
await (0, docker_credentials_1.createDockerHubRepository)(registry, tag, pushCredentials.username, pushCredentials.password, isPrivateRepo);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
else if (isMultiPlatform) {
|
|
139
|
+
// Multi-platform builds cannot be loaded into daemon
|
|
140
|
+
console.log(chalk_1.default.yellow('⚠️ Multi-platform builds cannot be loaded into Docker daemon'));
|
|
141
|
+
console.log(chalk_1.default.yellow(' Build will be skipped. Use "yarn publish" to build and push multi-platform images'));
|
|
142
|
+
return true;
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
// Single platform: load into daemon
|
|
146
|
+
outputArg = '--load';
|
|
147
|
+
cmdExplanation = 'Loading image into Docker daemon...';
|
|
148
|
+
console.log(chalk_1.default.dim(cmdExplanation));
|
|
149
|
+
}
|
|
150
|
+
// When pushing, also tag as latest for better cache hits on subsequent builds
|
|
151
|
+
const baseImageName = tag.split(':')[0];
|
|
152
|
+
const versionTag = tag.split(':')[1] || 'latest';
|
|
153
|
+
const latestTag = `${baseImageName}:latest`;
|
|
154
|
+
const tagsArg = shouldPush ? `-t ${tag} -t ${latestTag}` : `-t ${tag}`;
|
|
155
|
+
const buildCmd = `docker buildx build ${platformArg} ${cacheFromArg} --build-arg BUILDKIT_INLINE_CACHE=1 ${outputArg} --rm -f "${dir}/${dockerfile}" ${tagsArg} "${dir}"`;
|
|
156
|
+
console.log(`$ ${buildCmd}`);
|
|
157
|
+
child_process_1.default.execSync(buildCmd, {
|
|
158
|
+
stdio: 'inherit',
|
|
159
|
+
});
|
|
160
|
+
if (shouldPush) {
|
|
161
|
+
console.log(chalk_1.default.green(`✓ Image pushed to registry (tagged as ${versionTag} and latest)`));
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
console.log(chalk_1.default.green(`✓ Image loaded into Docker daemon`));
|
|
165
|
+
}
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
168
|
+
async function buildModule({ name, version, registry, arch: selectedArch = 'all', platforms: platformsFromGridApp = null, customImageName = null, pushCredentials = null, shouldPush = false, isPrivateRepo = false, architecturesFromPackageJson = null, }) {
|
|
169
|
+
const dir = process.cwd();
|
|
170
|
+
// Priority: explicit --arch flag > package.json architectures > .gridapp platforms > default (both)
|
|
171
|
+
let archFilter;
|
|
172
|
+
if (selectedArch !== 'all') {
|
|
173
|
+
// Explicit arch was provided via --arch flag (highest priority)
|
|
174
|
+
archFilter = selectedArch;
|
|
175
|
+
console.log(chalk_1.default.dim(`Using architecture from --arch flag: ${chalk_1.default.blue(selectedArch)}`));
|
|
176
|
+
}
|
|
177
|
+
else if (architecturesFromPackageJson && architecturesFromPackageJson.length > 0) {
|
|
178
|
+
// Use architectures from package.json docker-credentials
|
|
179
|
+
archFilter = architecturesFromPackageJson.length === 1 ? architecturesFromPackageJson[0] : 'all';
|
|
180
|
+
console.log(chalk_1.default.dim(`Using architectures from package.json: ${chalk_1.default.blue(architecturesFromPackageJson.join(', '))}`));
|
|
181
|
+
}
|
|
182
|
+
else if (platformsFromGridApp && platformsFromGridApp.length > 0) {
|
|
183
|
+
// Use platforms from .gridapp file (for backward compatibility)
|
|
184
|
+
archFilter = platformsFromGridApp.length === 1 ? platformsFromGridApp[0] : 'all';
|
|
185
|
+
console.log(chalk_1.default.dim(`Using architectures from .gridapp: ${chalk_1.default.blue(platformsFromGridApp.join(', '))}`));
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
// Default to both architectures
|
|
189
|
+
archFilter = 'all';
|
|
190
|
+
console.log(chalk_1.default.dim(`Using default architectures: ${chalk_1.default.blue('arm64, amd64')}`));
|
|
191
|
+
}
|
|
192
|
+
const archsMap = (0, exports.findArchs)(dir, archFilter);
|
|
193
|
+
const archs = Object.keys(archsMap);
|
|
194
|
+
console.log(chalk_1.default.dim(`Building ${chalk_1.default.blueBright(name)} for architectures ${chalk_1.default.greenBright(archs.join(' '))}`));
|
|
195
|
+
// Use the custom image name if provided, otherwise construct it
|
|
196
|
+
// Ensure the tag always has a version
|
|
197
|
+
let tag;
|
|
198
|
+
if (customImageName) {
|
|
199
|
+
// Check if customImageName already has a version tag
|
|
200
|
+
if (customImageName.includes(':')) {
|
|
201
|
+
tag = customImageName;
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
// Add version tag if missing
|
|
205
|
+
tag = `${customImageName}:${version}`;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
tag = `${registry}/${name}:${version}`;
|
|
210
|
+
}
|
|
211
|
+
console.log(chalk_1.default.dim(`Using image tag: ${chalk_1.default.blue(tag)}`));
|
|
212
|
+
// Build all architectures in a single command using the single Dockerfile
|
|
213
|
+
await build({
|
|
214
|
+
dir,
|
|
215
|
+
tag,
|
|
216
|
+
archs,
|
|
217
|
+
dockerfiles: archs.map(() => 'Dockerfile'),
|
|
218
|
+
registry,
|
|
219
|
+
pushCredentials,
|
|
220
|
+
shouldPush,
|
|
221
|
+
isPrivateRepo,
|
|
222
|
+
});
|
|
223
|
+
console.log(chalk_1.default.dim('Build done'));
|
|
224
|
+
}
|
|
225
|
+
exports.default = async (moduleName, options = {}) => {
|
|
226
|
+
const { arch, platforms, shouldPush = false } = options;
|
|
227
|
+
const cwd = process.cwd();
|
|
228
|
+
const packageFile = path_1.default.join(cwd, 'package.json');
|
|
229
|
+
if (!fs_extra_1.default.existsSync(packageFile))
|
|
230
|
+
throw new Error('Run this command from a module repository');
|
|
231
|
+
const info = JSON.parse(fs_extra_1.default.readFileSync(packageFile).toString());
|
|
232
|
+
let { name, version } = info;
|
|
233
|
+
const dockerCredentials = info['docker-credentials'];
|
|
234
|
+
const registry = dockerCredentials?.registry || info['container-registry'] || DEFAULT_REGISTRY;
|
|
235
|
+
// Check if a custom image name is specified in docker-credentials
|
|
236
|
+
let customImageName = null;
|
|
237
|
+
// Get repository privacy setting (default to false for public)
|
|
238
|
+
const isPrivateRepo = dockerCredentials?.isPrivate === true;
|
|
239
|
+
// Get architectures from docker-credentials (default to both if not specified)
|
|
240
|
+
const architecturesFromPackageJson = dockerCredentials?.architectures || null;
|
|
241
|
+
if (dockerCredentials?.image) {
|
|
242
|
+
customImageName = dockerCredentials.image;
|
|
243
|
+
console.log(chalk_1.default.dim(`Using custom image name from docker-credentials: ${chalk_1.default.blue(customImageName)}`));
|
|
244
|
+
}
|
|
245
|
+
if (architecturesFromPackageJson) {
|
|
246
|
+
console.log(chalk_1.default.dim(`Architectures from package.json: ${chalk_1.default.blue(architecturesFromPackageJson.join(', '))}`));
|
|
247
|
+
}
|
|
248
|
+
if (moduleName) {
|
|
249
|
+
const [modName, modVersion] = moduleName.split('@');
|
|
250
|
+
name = modName || name;
|
|
251
|
+
version = modVersion || version;
|
|
252
|
+
}
|
|
253
|
+
// Set up Docker registry authentication based on whether we're pushing
|
|
254
|
+
let pushCredentials = null;
|
|
255
|
+
if (shouldPush) {
|
|
256
|
+
// Only authenticate with registry when pushing
|
|
257
|
+
// First check environment variables
|
|
258
|
+
const envPushUsername = process.env.PHYGRID_REGISTRY_PUSH_USERNAME;
|
|
259
|
+
const envPushPassword = process.env.PHYGRID_REGISTRY_PUSH_PASSWORD;
|
|
260
|
+
if (envPushUsername && envPushPassword) {
|
|
261
|
+
console.log(chalk_1.default.dim('Using push credentials from environment variables'));
|
|
262
|
+
pushCredentials = {
|
|
263
|
+
username: envPushUsername,
|
|
264
|
+
password: envPushPassword,
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
// Check if credentials exist in registry credentials store
|
|
269
|
+
const storedCredentials = await (0, registry_credentials_1.getRegistryCredentials)(registry);
|
|
270
|
+
// If stored credentials exist, use them
|
|
271
|
+
if (storedCredentials &&
|
|
272
|
+
storedCredentials.push &&
|
|
273
|
+
storedCredentials.push.username &&
|
|
274
|
+
storedCredentials.push.password) {
|
|
275
|
+
console.log(chalk_1.default.dim('Using stored push credentials'));
|
|
276
|
+
pushCredentials = {
|
|
277
|
+
username: storedCredentials.push.username,
|
|
278
|
+
password: storedCredentials.push.password,
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
else {
|
|
282
|
+
// If no stored credentials, verify new ones
|
|
283
|
+
console.log(chalk_1.default.dim('No stored credentials found. Verifying Docker registry credentials...'));
|
|
284
|
+
const verifiedCredentials = await (0, docker_credentials_1.setupDockerCredentials)(registry, name, packageFile, customImageName);
|
|
285
|
+
pushCredentials = {
|
|
286
|
+
username: verifiedCredentials.pushUsername,
|
|
287
|
+
password: verifiedCredentials.pushPassword,
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
// If a custom image name is provided, use it directly
|
|
293
|
+
if (customImageName) {
|
|
294
|
+
// Extract name and version from the custom image
|
|
295
|
+
const parts = customImageName.split(':');
|
|
296
|
+
const customTag = parts.length > 1 ? parts[1] : version;
|
|
297
|
+
const customName = parts[0].split('/').pop();
|
|
298
|
+
// Ensure the custom image name has a version tag
|
|
299
|
+
if (!customImageName.includes(':')) {
|
|
300
|
+
customImageName = `${customImageName}:${version}`;
|
|
301
|
+
console.log(chalk_1.default.dim(`Adding version tag to custom image name: ${chalk_1.default.blue(customImageName)}`));
|
|
302
|
+
}
|
|
303
|
+
await buildModule({
|
|
304
|
+
name: customName,
|
|
305
|
+
version: customTag,
|
|
306
|
+
registry,
|
|
307
|
+
arch,
|
|
308
|
+
platforms,
|
|
309
|
+
customImageName,
|
|
310
|
+
pushCredentials,
|
|
311
|
+
shouldPush,
|
|
312
|
+
isPrivateRepo,
|
|
313
|
+
architecturesFromPackageJson,
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
else {
|
|
317
|
+
await buildModule({
|
|
318
|
+
name,
|
|
319
|
+
version,
|
|
320
|
+
registry,
|
|
321
|
+
arch,
|
|
322
|
+
platforms,
|
|
323
|
+
pushCredentials,
|
|
324
|
+
shouldPush,
|
|
325
|
+
isPrivateRepo,
|
|
326
|
+
architecturesFromPackageJson,
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
};
|
|
330
|
+
//# sourceMappingURL=build-container.js.map
|