@abgov/nx-oc 12.11.0 → 12.12.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/package.json +1 -1
- package/src/generators/deployment/deployment.js +4 -24
- package/src/generators/deployment/deployment.js.map +1 -1
- package/src/generators/deployment/schema.d.ts +1 -0
- package/src/generators/sandbox/build-files/__projectName__/sandbox-build.yml__tmpl__ +32 -0
- package/src/generators/sandbox/sandbox.js +48 -32
- package/src/generators/sandbox/sandbox.js.map +1 -1
- package/src/generators/sandbox/sandbox.spec.ts +50 -2
- package/src/generators/sandbox/schema.d.ts +3 -0
- package/src/generators/sandbox/schema.json +8 -0
- package/src/utils/app-type.d.ts +18 -0
- package/src/utils/app-type.js +43 -0
- package/src/utils/app-type.js.map +1 -0
- package/src/utils/git-utils.js +4 -2
- package/src/utils/git-utils.js.map +1 -1
- package/src/generators/deployment/dotnet-files/Dockerfile.template +0 -10
- package/src/generators/deployment/frontend-files/Dockerfile.template +0 -8
- package/src/generators/deployment/node-files/Dockerfile.template +0 -8
package/package.json
CHANGED
|
@@ -7,46 +7,26 @@ const path = require("path");
|
|
|
7
7
|
const yaml = require("yaml");
|
|
8
8
|
const pipeline_envs_1 = require("../../pipeline-envs");
|
|
9
9
|
const git_utils_1 = require("../../utils/git-utils");
|
|
10
|
+
const app_type_1 = require("../../utils/app-type");
|
|
10
11
|
const adsp_1 = require("../../adsp");
|
|
11
12
|
const infraManifestFile = '.openshift/environments.yml';
|
|
12
13
|
function normalizeOptions(host, options) {
|
|
13
14
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
14
|
-
var _a, _b, _c, _d;
|
|
15
|
+
var _a, _b, _c, _d, _e;
|
|
15
16
|
const projectName = (0, devkit_1.names)(options.project).fileName;
|
|
16
17
|
const result = host.read(infraManifestFile).toString();
|
|
17
18
|
const { items } = yaml.parse(result);
|
|
18
19
|
const ocInfraProject = ((_b = (_a = items[0]) === null || _a === void 0 ? void 0 : _a.metadata) === null || _b === void 0 ? void 0 : _b.namespace) || '';
|
|
19
20
|
const SA_PREFIX = 'system:serviceaccounts:';
|
|
20
21
|
const ocEnvProjects = (_d = (_c = items[0]) === null || _c === void 0 ? void 0 : _c.subjects) === null || _d === void 0 ? void 0 : _d.filter((s) => s.kind === 'Group' && s.name.startsWith(SA_PREFIX)).map((s) => s.name.replace(SA_PREFIX, ''));
|
|
21
|
-
// TODO: Find a better way to determine this.
|
|
22
22
|
const config = (0, devkit_1.readProjectConfiguration)(host, projectName);
|
|
23
|
-
|
|
24
|
-
if (!appType) {
|
|
25
|
-
switch (config.targets.build.executor) {
|
|
26
|
-
case '@nx/web:webpack':
|
|
27
|
-
case '@angular-devkit/build-angular:browser':
|
|
28
|
-
appType = 'frontend';
|
|
29
|
-
break;
|
|
30
|
-
case '@nx/node:build':
|
|
31
|
-
appType = 'node';
|
|
32
|
-
break;
|
|
33
|
-
case '@nx-dotnet/core:build':
|
|
34
|
-
appType = 'dotnet';
|
|
35
|
-
break;
|
|
36
|
-
case '@nx/webpack:webpack': {
|
|
37
|
-
// More recent version of NX switched to use a generic webpack executor for builds.
|
|
38
|
-
appType =
|
|
39
|
-
config.targets.build.options.target === 'node' ? 'node' : 'frontend';
|
|
40
|
-
break;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
23
|
+
const appType = (_e = options.appType) !== null && _e !== void 0 ? _e : (0, app_type_1.detectApplicationType)(config);
|
|
44
24
|
const adsp = yield (0, adsp_1.getAdspConfiguration)(host, options);
|
|
45
25
|
return Object.assign(Object.assign({}, options), { appType,
|
|
46
26
|
adsp,
|
|
47
27
|
projectName,
|
|
48
28
|
ocInfraProject,
|
|
49
|
-
ocEnvProjects });
|
|
29
|
+
ocEnvProjects, buildOutputPath: (0, app_type_1.getBuildOutputPath)(config) });
|
|
50
30
|
});
|
|
51
31
|
}
|
|
52
32
|
function addFiles(host, options) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deployment.js","sourceRoot":"","sources":["../../../../../../packages/nx-oc/src/generators/deployment/deployment.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"deployment.js","sourceRoot":"","sources":["../../../../../../packages/nx-oc/src/generators/deployment/deployment.ts"],"names":[],"mappings":";;AAkEA,4BAqCC;;AAvGD,uCAOoB;AACpB,6BAA6B;AAC7B,6BAA6B;AAC7B,uDAA2D;AAC3D,qDAAwD;AACxD,mDAAiF;AAEjF,qCAAkD;AAElD,MAAM,iBAAiB,GAAG,6BAA6B,CAAC;AAExD,SAAe,gBAAgB,CAC7B,IAAU,EACV,OAAe;;;QAEf,MAAM,WAAW,GAAG,IAAA,cAAK,EAAC,OAAO,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC;QAEpD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,QAAQ,EAAE,CAAC;QACvD,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACrC,MAAM,cAAc,GAAG,CAAA,MAAA,MAAA,KAAK,CAAC,CAAC,CAAC,0CAAE,QAAQ,0CAAE,SAAS,KAAI,EAAE,CAAC;QAE3D,MAAM,SAAS,GAAG,yBAAyB,CAAC;QAC5C,MAAM,aAAa,GAAG,MAAA,MAAA,KAAK,CAAC,CAAC,CAAC,0CAAE,QAAQ,0CACpC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EACjE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC;QAE7C,MAAM,MAAM,GAAG,IAAA,iCAAwB,EAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QAC3D,MAAM,OAAO,GAAG,MAAA,OAAO,CAAC,OAAO,mCAAI,IAAA,gCAAqB,EAAC,MAAM,CAAC,CAAC;QAEjE,MAAM,IAAI,GAAG,MAAM,IAAA,2BAAoB,EAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAEvD,uCACK,OAAO,KACV,OAAO;YACP,IAAI;YACJ,WAAW;YACX,cAAc;YACd,aAAa,EACb,eAAe,EAAE,IAAA,6BAAkB,EAAC,MAAM,CAAC,IAC3C;IACJ,CAAC;CAAA;AAED,SAAS,QAAQ,CAAC,IAAU,EAAE,OAAyB;;IACrD,MAAM,eAAe,iDAChB,OAAO,GACP,OAAO,CAAC,IAAI,KACf,mBAAmB,EAAE,IAAA,2BAAe,GAAE,EACtC,QAAQ,EAAE,MAAA,OAAO,CAAC,QAAQ,mCAAI,MAAM,EACpC,OAAO,EAAE,MAAA,OAAO,CAAC,OAAO,mCAAI,KAAK,EACjC,IAAI,EAAE,EAAE,GACT,CAAC;IACF,IAAA,sBAAa,EACX,IAAI,EACJ,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,OAAO,CAAC,OAAO,QAAQ,CAAC,EAChD,gBAAgB,OAAO,CAAC,WAAW,EAAE,EACrC,eAAe,CAChB,CAAC;AACJ,CAAC;AAED,mBAA+B,IAAU,EAAE,OAAe;;QACxD,MAAM,MAAM,GAAG,IAAA,iCAAwB,EAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;QAC/D,IAAI,MAAM,CAAC,WAAW,KAAK,aAAa,EAAE,CAAC;YACzC,OAAO,CAAC,GAAG,CAAC,yCAAyC,CAAC,CAAC;YACvD,OAAO;QACT,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,EAAE,CAAC;YACpC,OAAO,CAAC,GAAG,CACT,qEAAqE,CACtE,CAAC;YACF,OAAO;QACT,CAAC;QAED,MAAM,iBAAiB,GAAG,MAAM,gBAAgB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAChE,IAAI,CAAC,iBAAiB,CAAC,OAAO,EAAE,CAAC;YAC/B,OAAO,CAAC,GAAG,CAAC,sDAAsD,CAAC,CAAC;YACpE,OAAO;QACT,CAAC;QAED,MAAM,CAAC,OAAO,mCACT,MAAM,CAAC,OAAO,KACjB,YAAY,EAAE;gBACZ,QAAQ,EAAE,oBAAoB;gBAC9B,OAAO,EAAE;oBACP,SAAS,EAAE,iBAAiB,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC,EAAE,EAAE;;wBAAC,OAAA,CAAC;4BAC9D,OAAO;4BACP,GAAG,EAAE,MAAA,4BAAI,CAAC,CAAC,CAAC,0CAAE,WAAW,EAAE;yBAC5B,CAAC,CAAA;qBAAA,CAAC;iBACJ;aACF,GACF,CAAC;QAEF,IAAA,mCAA0B,EAAC,IAAI,EAAE,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAE1D,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;QAClC,MAAM,IAAA,oBAAW,EAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;CAAA"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Sandbox in-cluster build infrastructure for <%= projectName %>.
|
|
2
|
+
# A binary Docker BuildConfig uploads the local build context (oc start-build
|
|
3
|
+
# --from-dir), builds the image inside the cluster, and pushes it to the
|
|
4
|
+
# ImageStream over the internal registry. This needs no GitHub repo/CI, no
|
|
5
|
+
# externally-exposed registry route, and no local container runtime — unlike
|
|
6
|
+
# the GitHub Actions + GHCR flow used for real environment deployments.
|
|
7
|
+
apiVersion: image.openshift.io/v1
|
|
8
|
+
kind: ImageStream
|
|
9
|
+
metadata:
|
|
10
|
+
name: <%= projectName %>
|
|
11
|
+
labels:
|
|
12
|
+
app: <%= projectName %>
|
|
13
|
+
---
|
|
14
|
+
apiVersion: build.openshift.io/v1
|
|
15
|
+
kind: BuildConfig
|
|
16
|
+
metadata:
|
|
17
|
+
name: <%= projectName %>
|
|
18
|
+
labels:
|
|
19
|
+
app: <%= projectName %>
|
|
20
|
+
spec:
|
|
21
|
+
runPolicy: Serial
|
|
22
|
+
source:
|
|
23
|
+
type: Binary
|
|
24
|
+
binary: {}
|
|
25
|
+
strategy:
|
|
26
|
+
type: Docker
|
|
27
|
+
dockerStrategy:
|
|
28
|
+
dockerfilePath: .openshift/<%= projectName %>/Dockerfile
|
|
29
|
+
output:
|
|
30
|
+
to:
|
|
31
|
+
kind: ImageStreamTag
|
|
32
|
+
name: <%= projectName %>:sandbox
|
|
@@ -6,34 +6,17 @@ const devkit_1 = require("@nx/devkit");
|
|
|
6
6
|
const path = require("path");
|
|
7
7
|
const adsp_1 = require("../../adsp");
|
|
8
8
|
const git_utils_1 = require("../../utils/git-utils");
|
|
9
|
+
const app_type_1 = require("../../utils/app-type");
|
|
9
10
|
function normalizeOptions(host, options) {
|
|
10
11
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
11
|
-
var _a;
|
|
12
|
+
var _a, _b;
|
|
12
13
|
const projectName = (0, devkit_1.names)(options.project).fileName;
|
|
13
14
|
const config = (0, devkit_1.readProjectConfiguration)(host, projectName);
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
switch (config.targets.build.executor) {
|
|
17
|
-
case '@nx/web:webpack':
|
|
18
|
-
case '@angular-devkit/build-angular:browser':
|
|
19
|
-
appType = 'frontend';
|
|
20
|
-
break;
|
|
21
|
-
case '@nx/node:build':
|
|
22
|
-
appType = 'node';
|
|
23
|
-
break;
|
|
24
|
-
case '@nx-dotnet/core:build':
|
|
25
|
-
appType = 'dotnet';
|
|
26
|
-
break;
|
|
27
|
-
case '@nx/webpack:webpack':
|
|
28
|
-
appType =
|
|
29
|
-
config.targets.build.options.target === 'node' ? 'node' : 'frontend';
|
|
30
|
-
break;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
const adsp = yield (0, adsp_1.getAdspConfiguration)(host, Object.assign(Object.assign({}, options), { env: (_a = options.env) !== null && _a !== void 0 ? _a : 'dev' }));
|
|
15
|
+
const appType = (_a = options.appType) !== null && _a !== void 0 ? _a : (0, app_type_1.detectApplicationType)(config);
|
|
16
|
+
const adsp = yield (0, adsp_1.getAdspConfiguration)(host, Object.assign(Object.assign({}, options), { env: (_b = options.env) !== null && _b !== void 0 ? _b : 'dev' }));
|
|
34
17
|
return Object.assign(Object.assign({}, options), { appType,
|
|
35
18
|
adsp,
|
|
36
|
-
projectName });
|
|
19
|
+
projectName, buildOutputPath: (0, app_type_1.getBuildOutputPath)(config) });
|
|
37
20
|
});
|
|
38
21
|
}
|
|
39
22
|
function addManifestFiles(host, options) {
|
|
@@ -46,7 +29,18 @@ function addDatabaseFiles(host, options) {
|
|
|
46
29
|
return;
|
|
47
30
|
(0, devkit_1.generateFiles)(host, path.join(__dirname, 'database-files'), './.openshift/sandbox', { database: options.database, tmpl: '' });
|
|
48
31
|
}
|
|
32
|
+
// In-cluster build infrastructure (ImageStream + binary Docker BuildConfig).
|
|
33
|
+
// The sandbox builds inside the cluster and pushes to the internal registry,
|
|
34
|
+
// so it needs no GitHub repo/CI, no externally-exposed registry route, and no
|
|
35
|
+
// local container runtime.
|
|
36
|
+
function addBuildFiles(host, options) {
|
|
37
|
+
(0, devkit_1.generateFiles)(host, path.join(__dirname, 'build-files'), './.openshift', {
|
|
38
|
+
projectName: options.projectName,
|
|
39
|
+
tmpl: '',
|
|
40
|
+
});
|
|
41
|
+
}
|
|
49
42
|
function addSandboxTarget(host, options) {
|
|
43
|
+
var _a;
|
|
50
44
|
const config = (0, devkit_1.readProjectConfiguration)(host, options.project);
|
|
51
45
|
const { projectName, sandboxProject, database } = options;
|
|
52
46
|
const commands = [];
|
|
@@ -64,27 +58,48 @@ function addSandboxTarget(host, options) {
|
|
|
64
58
|
`-n ${sandboxProject}`);
|
|
65
59
|
commands.push(`oc apply -f .openshift/sandbox/sandbox-mongodb.yml -n ${sandboxProject}`);
|
|
66
60
|
}
|
|
61
|
+
// Ensure any paired backend Services exist first, so this app's nginx can
|
|
62
|
+
// resolve its proxy_pass upstreams at startup (otherwise the pod crashloops
|
|
63
|
+
// until the Service appears). Create only the Service (all nginx needs for
|
|
64
|
+
// DNS) — not the backend's deployment, which has no image until its own
|
|
65
|
+
// sandbox runs. Idempotent: skipped once the Service exists, so it doesn't
|
|
66
|
+
// slow down repeated frontend iteration. Recorded by the composite generators
|
|
67
|
+
// (pevn/mevn/…) as `adsp:proxy-service:<name>:<port>` project tags.
|
|
68
|
+
const PREFIX = 'adsp:proxy-service:';
|
|
69
|
+
const proxyServices = ((_a = config.tags) !== null && _a !== void 0 ? _a : [])
|
|
70
|
+
.filter((tag) => tag.startsWith(PREFIX))
|
|
71
|
+
.map((tag) => {
|
|
72
|
+
const value = tag.slice(PREFIX.length);
|
|
73
|
+
const lastColon = value.lastIndexOf(':');
|
|
74
|
+
return {
|
|
75
|
+
name: value.slice(0, lastColon),
|
|
76
|
+
port: value.slice(lastColon + 1),
|
|
77
|
+
};
|
|
78
|
+
});
|
|
79
|
+
for (const { name, port } of proxyServices) {
|
|
80
|
+
commands.push(`oc get service ${name} -n ${sandboxProject} >/dev/null 2>&1 || ` +
|
|
81
|
+
`oc create service clusterip ${name} --tcp=${port}:${port} -n ${sandboxProject}`);
|
|
82
|
+
}
|
|
83
|
+
// Ensure the in-cluster build infrastructure (ImageStream + BuildConfig).
|
|
84
|
+
commands.push(`oc apply -f .openshift/${projectName}/sandbox-build.yml -n ${sandboxProject}`);
|
|
85
|
+
// Build locally, then build the image in-cluster from the uploaded context
|
|
86
|
+
// and push to the internal registry — no external registry route required.
|
|
87
|
+
commands.push(`npx nx build ${projectName} --configuration production`);
|
|
88
|
+
commands.push(`oc start-build ${projectName} --from-dir=. --follow --wait -n ${sandboxProject}`);
|
|
67
89
|
commands.push(`oc process -f .openshift/${projectName}/${projectName}.yml -p PROJECT=${sandboxProject} | oc apply -f -`);
|
|
68
|
-
commands.push([
|
|
69
|
-
`REGISTRY=$(oc registry info)`,
|
|
70
|
-
`CONTAINER_CLI=$(command -v podman || command -v docker)`,
|
|
71
|
-
`$CONTAINER_CLI login -u $(oc whoami) -p $(oc whoami -t) $REGISTRY`,
|
|
72
|
-
`$CONTAINER_CLI build -t $REGISTRY/${sandboxProject}/${projectName}:sandbox -f .openshift/${projectName}/Dockerfile .`,
|
|
73
|
-
`$CONTAINER_CLI push $REGISTRY/${sandboxProject}/${projectName}:sandbox`,
|
|
74
|
-
].join(' && '));
|
|
75
90
|
commands.push(`oc rollout restart deployment/${projectName} -n ${sandboxProject}`);
|
|
76
|
-
commands.push(`oc rollout status deployment/${projectName} -n ${sandboxProject} --timeout=
|
|
91
|
+
commands.push(`oc rollout status deployment/${projectName} -n ${sandboxProject} --timeout=180s`);
|
|
77
92
|
config.targets = Object.assign(Object.assign({}, config.targets), { sandbox: {
|
|
78
93
|
executor: 'nx:run-commands',
|
|
79
94
|
options: {
|
|
80
95
|
commands,
|
|
81
|
-
|
|
96
|
+
parallel: false,
|
|
82
97
|
},
|
|
83
98
|
}, 'sandbox-teardown': {
|
|
84
99
|
executor: 'nx:run-commands',
|
|
85
100
|
options: {
|
|
86
101
|
commands: [
|
|
87
|
-
`oc delete all,configmap -l app=${projectName} -n ${sandboxProject} --ignore-not-found`,
|
|
102
|
+
`oc delete all,configmap,bc,is -l app=${projectName} -n ${sandboxProject} --ignore-not-found`,
|
|
88
103
|
],
|
|
89
104
|
},
|
|
90
105
|
} });
|
|
@@ -98,6 +113,7 @@ function default_1(host, options) {
|
|
|
98
113
|
return;
|
|
99
114
|
}
|
|
100
115
|
addManifestFiles(host, normalizedOptions);
|
|
116
|
+
addBuildFiles(host, normalizedOptions);
|
|
101
117
|
addDatabaseFiles(host, normalizedOptions);
|
|
102
118
|
addSandboxTarget(host, normalizedOptions);
|
|
103
119
|
yield (0, devkit_1.formatFiles)(host);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../../../../../../packages/nx-oc/src/generators/sandbox/sandbox.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../../../../../../packages/nx-oc/src/generators/sandbox/sandbox.ts"],"names":[],"mappings":"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"}
|
|
@@ -36,10 +36,11 @@ describe('Sandbox Generator', () => {
|
|
|
36
36
|
});
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
function addFrontendProject(host) {
|
|
39
|
+
function addFrontendProject(host, tags?: string[]) {
|
|
40
40
|
addProjectConfiguration(host, 'test', {
|
|
41
41
|
root: 'apps/test',
|
|
42
42
|
projectType: 'application',
|
|
43
|
+
tags,
|
|
43
44
|
targets: {
|
|
44
45
|
build: {
|
|
45
46
|
executor: '@nx/webpack:webpack',
|
|
@@ -84,10 +85,27 @@ describe('Sandbox Generator', () => {
|
|
|
84
85
|
const config = readProjectConfiguration(host, 'test');
|
|
85
86
|
expect(config.targets['sandbox']).toBeTruthy();
|
|
86
87
|
expect(config.targets['sandbox'].executor).toBe('nx:run-commands');
|
|
88
|
+
// Commands run in order (nx:run-commands has no `sequential` option).
|
|
89
|
+
expect(config.targets['sandbox'].options.parallel).toBe(false);
|
|
87
90
|
const cmds: string[] = config.targets['sandbox'].options.commands;
|
|
88
91
|
expect(cmds.some((c) => c.includes('oc rollout restart'))).toBeTruthy();
|
|
89
92
|
expect(cmds.some((c) => c.includes('oc rollout status'))).toBeTruthy();
|
|
90
|
-
|
|
93
|
+
// In-cluster binary build (no local podman / external registry route).
|
|
94
|
+
expect(cmds.some((c) => c.includes('nx build test'))).toBeTruthy();
|
|
95
|
+
expect(
|
|
96
|
+
cmds.some((c) => c.includes('oc start-build test --from-dir=.'))
|
|
97
|
+
).toBeTruthy();
|
|
98
|
+
expect(cmds.some((c) => c.includes('sandbox-build.yml'))).toBeTruthy();
|
|
99
|
+
expect(cmds.some((c) => c.includes('podman'))).toBeFalsy();
|
|
100
|
+
|
|
101
|
+
// The ImageStream + BuildConfig manifest is generated.
|
|
102
|
+
expect(host.exists('.openshift/test/sandbox-build.yml')).toBeTruthy();
|
|
103
|
+
const buildManifest = host
|
|
104
|
+
.read('.openshift/test/sandbox-build.yml')
|
|
105
|
+
.toString();
|
|
106
|
+
expect(buildManifest).toContain('kind: BuildConfig');
|
|
107
|
+
expect(buildManifest).toContain('kind: ImageStream');
|
|
108
|
+
expect(buildManifest).toContain('test:sandbox');
|
|
91
109
|
});
|
|
92
110
|
|
|
93
111
|
it('adds sandbox-teardown nx target', async () => {
|
|
@@ -146,4 +164,34 @@ describe('Sandbox Generator', () => {
|
|
|
146
164
|
const cmds: string[] = config.targets['sandbox'].options.commands;
|
|
147
165
|
expect(cmds.some((c) => c.includes('sandbox-mongodb-creds'))).toBeTruthy();
|
|
148
166
|
});
|
|
167
|
+
|
|
168
|
+
it('ensures paired backend Services from proxy-service tags', async () => {
|
|
169
|
+
const host = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
|
170
|
+
addFrontendProject(host, ['adsp:proxy-service:test-service:3333']);
|
|
171
|
+
|
|
172
|
+
await generator(host, options);
|
|
173
|
+
|
|
174
|
+
const config = readProjectConfiguration(host, 'test');
|
|
175
|
+
const cmds: string[] = config.targets['sandbox'].options.commands;
|
|
176
|
+
const guard = cmds.find((c) => c.includes('oc get service test-service'));
|
|
177
|
+
expect(guard).toBeTruthy();
|
|
178
|
+
// idempotent: only creates the Service (for DNS) when it's missing — no
|
|
179
|
+
// backend deployment, which would have no image until its own sandbox runs.
|
|
180
|
+
expect(guard).toContain('||');
|
|
181
|
+
expect(guard).toContain(
|
|
182
|
+
'oc create service clusterip test-service --tcp=3333:3333'
|
|
183
|
+
);
|
|
184
|
+
expect(guard).not.toContain('test-service.yml');
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it('adds no paired-service guard when there are no proxy-service tags', async () => {
|
|
188
|
+
const host = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
|
189
|
+
addNodeProject(host);
|
|
190
|
+
|
|
191
|
+
await generator(host, options);
|
|
192
|
+
|
|
193
|
+
const config = readProjectConfiguration(host, 'test');
|
|
194
|
+
const cmds: string[] = config.targets['sandbox'].options.commands;
|
|
195
|
+
expect(cmds.some((c) => c.includes('oc get service'))).toBeFalsy();
|
|
196
|
+
});
|
|
149
197
|
});
|
|
@@ -9,10 +9,13 @@ export interface Schema {
|
|
|
9
9
|
env?: string;
|
|
10
10
|
adsp?: AdspConfiguration;
|
|
11
11
|
accessToken?: string;
|
|
12
|
+
tenant?: string;
|
|
13
|
+
tenantRealm?: string;
|
|
12
14
|
}
|
|
13
15
|
|
|
14
16
|
export interface NormalizedSchema extends Schema {
|
|
15
17
|
projectName: string;
|
|
16
18
|
appType: ApplicationType;
|
|
17
19
|
adsp: AdspConfiguration;
|
|
20
|
+
buildOutputPath: string;
|
|
18
21
|
}
|
|
@@ -43,6 +43,14 @@
|
|
|
43
43
|
"type": "string",
|
|
44
44
|
"description": "Access token for retrieving configuration from ADSP APIs.",
|
|
45
45
|
"alias": "at"
|
|
46
|
+
},
|
|
47
|
+
"tenant": {
|
|
48
|
+
"type": "string",
|
|
49
|
+
"description": "ADSP tenant name. Looks up the realm and does a single login, skipping the interactive tenant picker."
|
|
50
|
+
},
|
|
51
|
+
"tenantRealm": {
|
|
52
|
+
"type": "string",
|
|
53
|
+
"description": "Keycloak realm UUID. Optional when --tenant is provided; overrides the realm looked up from the tenant service."
|
|
46
54
|
}
|
|
47
55
|
},
|
|
48
56
|
"required": ["project", "sandboxProject"],
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ProjectConfiguration } from '@nx/devkit';
|
|
2
|
+
import { ApplicationType } from '../generators/deployment/schema';
|
|
3
|
+
/**
|
|
4
|
+
* Detect the application type from the project's build executor.
|
|
5
|
+
*
|
|
6
|
+
* Shared by the deployment and sandbox generators so they stay in sync as new
|
|
7
|
+
* Nx build executors appear (e.g. Vite/Rspack for frontends).
|
|
8
|
+
*/
|
|
9
|
+
export declare function detectApplicationType(config: ProjectConfiguration): ApplicationType | undefined;
|
|
10
|
+
/**
|
|
11
|
+
* The build output directory for a project, relative to the workspace root.
|
|
12
|
+
*
|
|
13
|
+
* Read from the project's `build` target so the generated Dockerfile mirrors
|
|
14
|
+
* the workspace's actual layout (e.g. `dist/apps/<project>` or
|
|
15
|
+
* `packages/<project>/dist`) instead of assuming a fixed path. Falls back to
|
|
16
|
+
* `dist/<projectRoot>`, the Nx default, when the target declares no outputPath.
|
|
17
|
+
*/
|
|
18
|
+
export declare function getBuildOutputPath(config: ProjectConfiguration): string;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.detectApplicationType = detectApplicationType;
|
|
4
|
+
exports.getBuildOutputPath = getBuildOutputPath;
|
|
5
|
+
/**
|
|
6
|
+
* Detect the application type from the project's build executor.
|
|
7
|
+
*
|
|
8
|
+
* Shared by the deployment and sandbox generators so they stay in sync as new
|
|
9
|
+
* Nx build executors appear (e.g. Vite/Rspack for frontends).
|
|
10
|
+
*/
|
|
11
|
+
function detectApplicationType(config) {
|
|
12
|
+
var _a, _b;
|
|
13
|
+
const build = (_a = config.targets) === null || _a === void 0 ? void 0 : _a.build;
|
|
14
|
+
switch (build === null || build === void 0 ? void 0 : build.executor) {
|
|
15
|
+
case '@nx/web:webpack':
|
|
16
|
+
case '@angular-devkit/build-angular:browser':
|
|
17
|
+
case '@nx/vite:build':
|
|
18
|
+
case '@nx/rspack:rspack':
|
|
19
|
+
return 'frontend';
|
|
20
|
+
case '@nx/node:build':
|
|
21
|
+
return 'node';
|
|
22
|
+
case '@nx-dotnet/core:build':
|
|
23
|
+
return 'dotnet';
|
|
24
|
+
case '@nx/webpack:webpack':
|
|
25
|
+
// The generic webpack executor builds both node and browser apps.
|
|
26
|
+
return ((_b = build.options) === null || _b === void 0 ? void 0 : _b.target) === 'node' ? 'node' : 'frontend';
|
|
27
|
+
default:
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The build output directory for a project, relative to the workspace root.
|
|
33
|
+
*
|
|
34
|
+
* Read from the project's `build` target so the generated Dockerfile mirrors
|
|
35
|
+
* the workspace's actual layout (e.g. `dist/apps/<project>` or
|
|
36
|
+
* `packages/<project>/dist`) instead of assuming a fixed path. Falls back to
|
|
37
|
+
* `dist/<projectRoot>`, the Nx default, when the target declares no outputPath.
|
|
38
|
+
*/
|
|
39
|
+
function getBuildOutputPath(config) {
|
|
40
|
+
var _a, _b, _c, _d;
|
|
41
|
+
return (_d = (_c = (_b = (_a = config.targets) === null || _a === void 0 ? void 0 : _a.build) === null || _b === void 0 ? void 0 : _b.options) === null || _c === void 0 ? void 0 : _c.outputPath) !== null && _d !== void 0 ? _d : `dist/${config.root}`;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=app-type.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-type.js","sourceRoot":"","sources":["../../../../../packages/nx-oc/src/utils/app-type.ts"],"names":[],"mappings":";;AASA,sDAoBC;AAUD,gDAEC;AAtCD;;;;;GAKG;AACH,SAAgB,qBAAqB,CACnC,MAA4B;;IAE5B,MAAM,KAAK,GAAG,MAAA,MAAM,CAAC,OAAO,0CAAE,KAAK,CAAC;IACpC,QAAQ,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,QAAQ,EAAE,CAAC;QACxB,KAAK,iBAAiB,CAAC;QACvB,KAAK,uCAAuC,CAAC;QAC7C,KAAK,gBAAgB,CAAC;QACtB,KAAK,mBAAmB;YACtB,OAAO,UAAU,CAAC;QACpB,KAAK,gBAAgB;YACnB,OAAO,MAAM,CAAC;QAChB,KAAK,uBAAuB;YAC1B,OAAO,QAAQ,CAAC;QAClB,KAAK,qBAAqB;YACxB,kEAAkE;YAClE,OAAO,CAAA,MAAA,KAAK,CAAC,OAAO,0CAAE,MAAM,MAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC;QAChE;YACE,OAAO,SAAS,CAAC;IACrB,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,SAAgB,kBAAkB,CAAC,MAA4B;;IAC7D,OAAO,MAAA,MAAA,MAAA,MAAA,MAAM,CAAC,OAAO,0CAAE,KAAK,0CAAE,OAAO,0CAAE,UAAU,mCAAI,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;AAC7E,CAAC"}
|
package/src/utils/git-utils.js
CHANGED
|
@@ -9,8 +9,10 @@ function getGitRemoteUrl() {
|
|
|
9
9
|
const stdout = (0, child_process_1.execSync)("git config --get remote.origin.url", { stdio: "pipe" }).toString();
|
|
10
10
|
return stdout;
|
|
11
11
|
}
|
|
12
|
-
catch (
|
|
13
|
-
|
|
12
|
+
catch (_a) {
|
|
13
|
+
// No 'origin' remote (e.g. a freshly-created workspace) — not an error;
|
|
14
|
+
// sourceRepositoryUrl is simply left unset.
|
|
15
|
+
return undefined;
|
|
14
16
|
}
|
|
15
17
|
}
|
|
16
18
|
// Parses a GitHub remote URL and returns the ghcr.io registry for the org.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git-utils.js","sourceRoot":"","sources":["../../../../../packages/nx-oc/src/utils/git-utils.ts"],"names":[],"mappings":";;AAEA,
|
|
1
|
+
{"version":3,"file":"git-utils.js","sourceRoot":"","sources":["../../../../../packages/nx-oc/src/utils/git-utils.ts"],"names":[],"mappings":";;AAEA,0CAaC;AAKD,4DAOC;AAGD,sCAMC;AApCD,iDAAwC;AAExC,SAAgB,eAAe;IAC7B,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAA,wBAAQ,EACrB,oCAAoC,EACpC,EAAE,KAAK,EAAE,MAAM,EAAE,CAClB,CAAC,QAAQ,EAAE,CAAA;QAEZ,OAAO,MAAM,CAAA;IACf,CAAC;IAAC,WAAM,CAAC;QACP,wEAAwE;QACxE,4CAA4C;QAC5C,OAAO,SAAS,CAAA;IAClB,CAAC;AACH,CAAC;AAED,2EAA2E;AAC3E,2DAA2D;AAC3D,6CAA6C;AAC7C,SAAgB,wBAAwB,CAAC,SAAkB;;IACzD,IAAI,CAAC,SAAS;QAAE,OAAO,SAAS,CAAC;IACjC,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC;IAC7B,MAAM,UAAU,GAAG,GAAG,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC;IACjE,MAAM,QAAQ,GAAK,GAAG,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;IAC1D,MAAM,GAAG,GAAG,MAAA,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAG,CAAC,CAAC,mCAAI,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAG,CAAC,CAAC,CAAC;IAC7C,OAAO,GAAG,CAAC,CAAC,CAAC,WAAW,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AAC5C,CAAC;AAED,qEAAqE;AACrE,SAAgB,aAAa,CAAC,SAAkB;;IAC9C,IAAI,CAAC,SAAS;QAAE,OAAO,SAAS,CAAC;IACjC,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC;IAC7B,MAAM,UAAU,GAAG,GAAG,CAAC,KAAK,CAAC,4CAA4C,CAAC,CAAC;IAC3E,MAAM,QAAQ,GAAK,GAAG,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAC;IACpE,OAAO,MAAA,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAG,CAAC,CAAC,mCAAI,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAG,CAAC,CAAC,CAAC;AAC1C,CAAC"}
|