@abgov/nx-oc 12.14.1 → 12.15.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abgov/nx-oc",
3
- "version": "12.14.1",
3
+ "version": "12.15.0",
4
4
  "license": "Apache-2.0",
5
5
  "main": "src/index.js",
6
6
  "description": "Government of Alberta - Nx plugin for OpenShift.",
@@ -1,19 +1,8 @@
1
1
  "use strict";
2
- var _a, _b, _c, _d, _e, _f;
3
2
  Object.defineProperty(exports, "__esModule", { value: true });
4
3
  exports.environments = void 0;
5
4
  exports.environments = {
6
- dev: {
7
- accessServiceUrl: (_a = process.env.ADSP_E2E_ACCESS_URL) !== null && _a !== void 0 ? _a : 'https://access.adsp-dev.gov.ab.ca',
8
- directoryServiceUrl: (_b = process.env.ADSP_E2E_DIRECTORY_URL) !== null && _b !== void 0 ? _b : 'https://directory-service.adsp-dev.gov.ab.ca',
9
- },
10
- test: {
11
- accessServiceUrl: (_c = process.env.ADSP_E2E_ACCESS_URL) !== null && _c !== void 0 ? _c : 'https://access-uat.alberta.ca',
12
- directoryServiceUrl: (_d = process.env.ADSP_E2E_DIRECTORY_URL) !== null && _d !== void 0 ? _d : 'https://directory-service.adsp-uat.alberta.ca',
13
- },
14
- prod: {
15
- accessServiceUrl: (_e = process.env.ADSP_E2E_ACCESS_URL) !== null && _e !== void 0 ? _e : 'https://access.alberta.ca',
16
- directoryServiceUrl: (_f = process.env.ADSP_E2E_DIRECTORY_URL) !== null && _f !== void 0 ? _f : 'https://directory-service.adsp.alberta.ca',
17
- },
5
+ dev: { accessServiceUrl: "http://localhost:46205", directoryServiceUrl: "http://localhost:46205" },
6
+ test: { accessServiceUrl: "http://localhost:46205", directoryServiceUrl: "http://localhost:46205" },
7
+ prod: { accessServiceUrl: "http://localhost:46205", directoryServiceUrl: "http://localhost:46205" },
18
8
  };
19
- //# sourceMappingURL=environments.js.map
@@ -0,0 +1,62 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ // minimatch is always present (nx depends on it); used only in this test.
4
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
5
+ import minimatch = require('minimatch');
6
+
7
+ /**
8
+ * Guards the source -> published-package boundary.
9
+ *
10
+ * The build copies non-source files (generator templates, schemas, static
11
+ * assets) into the package via the build target's `assets` globs. Any such file
12
+ * NOT matched by a glob is silently dropped from the published package, so a
13
+ * consumer's generate produces output referencing a file that was never
14
+ * shipped. This is exactly how `Dockerfile__tmpl__` was lost: the rename from
15
+ * `Dockerfile.template` (dotted) to `Dockerfile__tmpl__` (dotless) stopped it
16
+ * matching `**\/*.!(ts)`.
17
+ *
18
+ * Unit tests of the generators can't catch this — they resolve templates from
19
+ * the source tree, never the packaged output. This asserts the invariant
20
+ * directly: every non-TypeScript file under src is covered by an asset glob.
21
+ */
22
+ describe('build assets packaging', () => {
23
+ const srcRoot = __dirname;
24
+ const projectRoot = path.join(srcRoot, '..');
25
+ const repoRoot = path.join(projectRoot, '..', '..');
26
+
27
+ function listFiles(dir: string): string[] {
28
+ return fs.readdirSync(dir, { withFileTypes: true }).flatMap((entry) => {
29
+ const full = path.join(dir, entry.name);
30
+ return entry.isDirectory() ? listFiles(full) : [full];
31
+ });
32
+ }
33
+
34
+ it('matches every non-TypeScript src file with an asset glob', () => {
35
+ const project = JSON.parse(
36
+ fs.readFileSync(path.join(projectRoot, 'project.json'), 'utf-8')
37
+ );
38
+ const assets: unknown[] = project.targets.build.options.assets ?? [];
39
+
40
+ // Globs whose input is this package's src directory.
41
+ const srcGlobs = assets
42
+ .filter(
43
+ (a): a is { input: string; glob: string } =>
44
+ typeof a === 'object' &&
45
+ a !== null &&
46
+ 'input' in a &&
47
+ path.resolve(repoRoot, (a as { input: string }).input) === srcRoot
48
+ )
49
+ .map((a) => a.glob);
50
+
51
+ // Every non-source file under src must ship (tsc only emits .ts -> .js).
52
+ const mustShip = listFiles(srcRoot)
53
+ .filter((f) => !/\.tsx?$/.test(f))
54
+ .map((f) => path.relative(srcRoot, f));
55
+
56
+ const unmatched = mustShip.filter(
57
+ (rel) => !srcGlobs.some((glob) => minimatch(rel, glob, { dot: true }))
58
+ );
59
+
60
+ expect(unmatched).toEqual([]);
61
+ });
62
+ });
@@ -31,7 +31,13 @@ function normalizeOptions(host, options) {
31
31
  }
32
32
  function addFiles(host, options) {
33
33
  var _a, _b;
34
- const templateOptions = Object.assign(Object.assign(Object.assign({}, options), options.adsp), { sourceRepositoryUrl: (0, git_utils_1.getGitRemoteUrl)(), database: (_a = options.database) !== null && _a !== void 0 ? _a : 'none', sandbox: (_b = options.sandbox) !== null && _b !== void 0 ? _b : false, tmpl: '' });
34
+ const templateOptions = Object.assign(Object.assign(Object.assign({}, options), options.adsp), {
35
+ // Clean https URL for the image's source label (never the raw remote, which
36
+ // may be an SSH URL or carry a trailing newline).
37
+ sourceRepositoryUrl: (() => {
38
+ const repo = (0, git_utils_1.getGitHubRepo)((0, git_utils_1.getGitRemoteUrl)());
39
+ return repo ? `https://github.com/${repo}` : '';
40
+ })(), database: (_a = options.database) !== null && _a !== void 0 ? _a : 'none', sandbox: (_b = options.sandbox) !== null && _b !== void 0 ? _b : false, tmpl: '' });
35
41
  (0, devkit_1.generateFiles)(host, path.join(__dirname, `${options.appType}-files`), `./.openshift/${options.projectName}`, templateOptions);
36
42
  }
37
43
  function default_1(host, options) {
@@ -1 +1 @@
1
- {"version":3,"file":"deployment.js","sourceRoot":"","sources":["../../../../../../packages/nx-oc/src/generators/deployment/deployment.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"deployment.js","sourceRoot":"","sources":["../../../../../../packages/nx-oc/src/generators/deployment/deployment.ts"],"names":[],"mappings":"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"}
@@ -5,6 +5,10 @@ COPY . .
5
5
  RUN dotnet publish ${PROJECT} -c Release -o /app/publish
6
6
 
7
7
  FROM registry.access.redhat.com/ubi8/dotnet-80-runtime
8
+ <% if (sourceRepositoryUrl) { %>
9
+ # Provenance: associate the image with its source repo (shown in GHCR).
10
+ LABEL org.opencontainers.image.source=<%= sourceRepositoryUrl %>
11
+ <% } %>
8
12
  WORKDIR /app
9
13
  COPY --from=build /app/publish .
10
14
  ENV ASPNETCORE_URLS=http://+:5000
@@ -1,5 +1,8 @@
1
1
  FROM registry.access.redhat.com/ubi9/nginx-120
2
-
2
+ <% if (sourceRepositoryUrl) { %>
3
+ # Provenance: associate the image with its source repo (shown in GHCR).
4
+ LABEL org.opencontainers.image.source=<%= sourceRepositoryUrl %>
5
+ <% } %>
3
6
  # Build output path mirrors the workspace layout (from the project's build target).
4
7
  COPY ./<%= buildOutputPath %>/nginx.conf "${NGINX_CONF_PATH}"
5
8
  COPY ./<%= buildOutputPath %> .
@@ -1,5 +1,8 @@
1
1
  FROM registry.access.redhat.com/ubi9/nodejs-24
2
-
2
+ <% if (sourceRepositoryUrl) { %>
3
+ # Provenance: associate the image with its source repo (shown in GHCR).
4
+ LABEL org.opencontainers.image.source=<%= sourceRepositoryUrl %>
5
+ <% } %>
3
6
  # Build output path mirrors the workspace layout (from the project's build target).
4
7
  COPY ./<%= buildOutputPath %> .
5
8
  COPY ./node_modules ./node_modules
@@ -8,6 +8,43 @@ const adsp_1 = require("../../adsp");
8
8
  const git_utils_1 = require("../../utils/git-utils");
9
9
  const oc_utils_1 = require("../../utils/oc-utils");
10
10
  const app_type_1 = require("../../utils/app-type");
11
+ const SANDBOX_GENERATOR = '@abgov/nx-oc:sandbox';
12
+ // Resolves the sandbox container registry once per workspace and persists it to
13
+ // nx.json so subsequent sandbox generations reuse it without re-prompting:
14
+ // --registry flag → nx.json → derived from git remote (ghcr.io/<org>) → prompt.
15
+ function resolveRegistry(host, registry, remoteUrl) {
16
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
17
+ var _a, _b, _c;
18
+ if (registry)
19
+ return persistRegistry(host, registry);
20
+ const stored = (_c = (_b = (_a = (0, devkit_1.readNxJson)(host)) === null || _a === void 0 ? void 0 : _a.generators) === null || _b === void 0 ? void 0 : _b[SANDBOX_GENERATOR]) === null || _c === void 0 ? void 0 : _c.registry;
21
+ if (stored)
22
+ return stored;
23
+ const derived = (0, git_utils_1.deriveRegistryFromRemote)(remoteUrl);
24
+ if (derived) {
25
+ console.log(`\n✓ Sandbox registry: ${derived.toLowerCase()} (derived from git remote)\n`);
26
+ return persistRegistry(host, derived);
27
+ }
28
+ const { prompt } = yield Promise.resolve().then(() => require('enquirer'));
29
+ const { registry: answered } = yield prompt({
30
+ type: 'input',
31
+ name: 'registry',
32
+ message: 'What container registry should sandbox images be published to (e.g., ghcr.io/my-org)?',
33
+ });
34
+ return persistRegistry(host, answered);
35
+ });
36
+ }
37
+ // Container registries (GHCR) require lowercase paths, so normalize on store.
38
+ function persistRegistry(host, registry) {
39
+ var _a, _b, _c;
40
+ const value = registry.toLowerCase();
41
+ const nxJson = (_a = (0, devkit_1.readNxJson)(host)) !== null && _a !== void 0 ? _a : {};
42
+ const generators = ((_b = nxJson.generators) !== null && _b !== void 0 ? _b : {});
43
+ generators[SANDBOX_GENERATOR] = Object.assign(Object.assign({}, ((_c = generators[SANDBOX_GENERATOR]) !== null && _c !== void 0 ? _c : {})), { registry: value });
44
+ nxJson.generators = generators;
45
+ (0, devkit_1.updateNxJson)(host, nxJson);
46
+ return value;
47
+ }
11
48
  function normalizeOptions(host, options) {
12
49
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
13
50
  var _a, _b;
@@ -15,14 +52,22 @@ function normalizeOptions(host, options) {
15
52
  const config = (0, devkit_1.readProjectConfiguration)(host, projectName);
16
53
  const appType = (_a = options.appType) !== null && _a !== void 0 ? _a : (0, app_type_1.detectApplicationType)(config);
17
54
  const adsp = yield (0, adsp_1.getAdspConfiguration)(host, Object.assign(Object.assign({}, options), { env: (_b = options.env) !== null && _b !== void 0 ? _b : 'dev' }));
55
+ const remoteUrl = (0, git_utils_1.getGitRemoteUrl)();
56
+ const registry = (yield resolveRegistry(host, options.registry, remoteUrl)).toLowerCase();
57
+ // Prefix the image with the (per-user) sandbox namespace so images from
58
+ // different experimenters never collide on GHCR's org-global package names.
59
+ const imageName = `${options.sandboxProject}-${projectName}`.toLowerCase();
60
+ const repoSlug = (0, git_utils_1.getGitHubRepo)(remoteUrl);
18
61
  return Object.assign(Object.assign({}, options), { appType,
19
62
  adsp,
20
- projectName, buildOutputPath: (0, app_type_1.getBuildOutputPath)(config) });
63
+ projectName, buildOutputPath: (0, app_type_1.getBuildOutputPath)(config), registry, registryHost: registry.split('/')[0], registryOrg: registry.split('/').slice(1).join('/'), imageName, imageRef: `${registry}/${imageName}:sandbox`, sourceRepositoryUrl: repoSlug ? `https://github.com/${repoSlug}` : undefined });
21
64
  });
22
65
  }
23
66
  function addManifestFiles(host, options) {
24
- var _a;
25
- const templateOptions = Object.assign(Object.assign(Object.assign({}, options), options.adsp), { sourceRepositoryUrl: (0, git_utils_1.getGitRemoteUrl)(), database: (_a = options.database) !== null && _a !== void 0 ? _a : 'none', sandbox: true, ocInfraProject: options.sandboxProject, tmpl: '' });
67
+ var _a, _b;
68
+ const templateOptions = Object.assign(Object.assign(Object.assign({}, options), options.adsp), {
69
+ // Clean https URL for the image's source label (provenance / UI connect).
70
+ sourceRepositoryUrl: (_a = options.sourceRepositoryUrl) !== null && _a !== void 0 ? _a : '', database: (_b = options.database) !== null && _b !== void 0 ? _b : 'none', sandbox: true, ocInfraProject: options.sandboxProject, tmpl: '' });
26
71
  (0, devkit_1.generateFiles)(host, path.join(__dirname, `../deployment/${options.appType}-files`), `./.openshift/${options.projectName}`, templateOptions);
27
72
  }
28
73
  function addDatabaseFiles(host, options) {
@@ -30,20 +75,10 @@ function addDatabaseFiles(host, options) {
30
75
  return;
31
76
  (0, devkit_1.generateFiles)(host, path.join(__dirname, 'database-files'), './.openshift/sandbox', { database: options.database, tmpl: '' });
32
77
  }
33
- // In-cluster build infrastructure (ImageStream + binary Docker BuildConfig).
34
- // The sandbox builds inside the cluster and pushes to the internal registry,
35
- // so it needs no GitHub repo/CI, no externally-exposed registry route, and no
36
- // local container runtime.
37
- function addBuildFiles(host, options) {
38
- (0, devkit_1.generateFiles)(host, path.join(__dirname, 'build-files'), './.openshift', {
39
- projectName: options.projectName,
40
- tmpl: '',
41
- });
42
- }
43
78
  function addSandboxTarget(host, options) {
44
79
  var _a;
45
80
  const config = (0, devkit_1.readProjectConfiguration)(host, options.project);
46
- const { projectName, sandboxProject, database, appType } = options;
81
+ const { projectName, sandboxProject, database, appType, imageRef, registryHost, registryOrg, imageName, } = options;
47
82
  const commands = [];
48
83
  // ADSP services authenticate with the access service using a confidential
49
84
  // Keycloak client secret. The express-service generator writes it to the
@@ -100,12 +135,26 @@ function addSandboxTarget(host, options) {
100
135
  commands.push(`oc get service ${name} -n ${sandboxProject} >/dev/null 2>&1 || ` +
101
136
  `oc create service clusterip ${name} --tcp=${port}:${port} -n ${sandboxProject}`);
102
137
  }
103
- // Ensure the in-cluster build infrastructure (ImageStream + BuildConfig).
104
- commands.push(`oc apply -f .openshift/${projectName}/sandbox-build.yml -n ${sandboxProject}`);
105
- // Build locally, then build the image in-cluster from the uploaded context
106
- // and push to the internal registry no external registry route required.
138
+ // Build the image locally and push to the container registry, then import it
139
+ // into the namespace's imagestream. reference-policy=local mirrors it into the
140
+ // internal registry so pods pull in-cluster (no per-pod pull secret, no node
141
+ // egress to the registry). This replaces the in-cluster BuildConfig: no
142
+ // full-workspace upload, and local layer caching makes iteration fast.
107
143
  commands.push(`npx nx build ${projectName} --configuration production`);
108
- commands.push(`oc start-build ${projectName} --from-dir=. --follow --wait -n ${sandboxProject}`);
144
+ commands.push(`podman build --platform=linux/amd64 -f .openshift/${projectName}/Dockerfile -t ${imageRef} .`);
145
+ // Prereq: the publishing account is logged in with write:packages. gh supplies
146
+ // the token so no PAT is stored; the same session token backs the pull secret.
147
+ commands.push(`gh auth token | podman login ${registryHost} -u "$(gh api user -q .login)" --password-stdin`);
148
+ commands.push(`podman push ${imageRef}`);
149
+ // Per-deploy pull secret from the gh session (sandbox images are re-imported
150
+ // every run, so a session token is sufficient — no long-lived PAT needed).
151
+ commands.push(`oc create secret docker-registry ghcr-pull ` +
152
+ `--docker-server=${registryHost} --docker-username="$(gh api user -q .login)" --docker-password="$(gh auth token)" ` +
153
+ `-n ${sandboxProject} --dry-run=client -o yaml | oc apply -f -`);
154
+ // oc tag sets/repoints the imagestream tag (import-image refuses to change an
155
+ // existing tag's source); import --confirm then pulls the manifest.
156
+ commands.push(`oc tag ${imageRef} ${projectName}:sandbox --reference-policy=local -n ${sandboxProject}`);
157
+ commands.push(`oc import-image ${projectName}:sandbox --confirm -n ${sandboxProject}`);
109
158
  commands.push(`oc process -f .openshift/${projectName}/${projectName}.yml -p PROJECT=${sandboxProject} | oc apply -f -`);
110
159
  commands.push(`oc rollout restart deployment/${projectName} -n ${sandboxProject}`);
111
160
  commands.push(`oc rollout status deployment/${projectName} -n ${sandboxProject} --timeout=180s`);
@@ -119,7 +168,12 @@ function addSandboxTarget(host, options) {
119
168
  executor: 'nx:run-commands',
120
169
  options: {
121
170
  commands: [
122
- `oc delete all,configmap,bc,is -l app=${projectName} -n ${sandboxProject} --ignore-not-found`,
171
+ `oc delete all,configmap,is -l app=${projectName} -n ${sandboxProject} --ignore-not-found`,
172
+ `oc delete imagestream ${projectName} -n ${sandboxProject} --ignore-not-found`,
173
+ // Remove the sandbox package (needs delete:packages). Best-effort:
174
+ // sandbox packages are the unlinked ones and can also be pruned org-wide
175
+ // via `select(.repository == null)`.
176
+ `gh api --method DELETE /orgs/${registryOrg}/packages/container/${imageName} 2>/dev/null || true`,
123
177
  ],
124
178
  },
125
179
  } });
@@ -156,7 +210,6 @@ function default_1(host, options) {
156
210
  return;
157
211
  }
158
212
  addManifestFiles(host, normalizedOptions);
159
- addBuildFiles(host, normalizedOptions);
160
213
  addDatabaseFiles(host, normalizedOptions);
161
214
  addSandboxTarget(host, normalizedOptions);
162
215
  yield registerSandboxRedirectUri(normalizedOptions);
@@ -1 +1 @@
1
- {"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../../../../../../packages/nx-oc/src/generators/sandbox/sandbox.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../../../../../../packages/nx-oc/src/generators/sandbox/sandbox.ts"],"names":[],"mappings":";;AAmUA,4BAYC;;AA/UD,uCASoB;AACpB,6BAA6B;AAC7B,qCAAyE;AACzE,qDAI+B;AAC/B,mDAA+D;AAC/D,mDAAiF;AAGjF,MAAM,iBAAiB,GAAG,sBAAsB,CAAC;AAEjD,gFAAgF;AAChF,2EAA2E;AAC3E,kFAAkF;AAClF,SAAe,eAAe,CAC5B,IAAU,EACV,QAA4B,EAC5B,SAA6B;;;QAE7B,IAAI,QAAQ;YAAE,OAAO,eAAe,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAErD,MAAM,MAAM,GAAG,MAAA,MACb,MAAA,IAAA,mBAAU,EAAC,IAAI,CAAC,0CAAE,UAGnB,0CAAG,iBAAiB,CAAC,0CAAE,QAAQ,CAAC;QACjC,IAAI,MAAM;YAAE,OAAO,MAAM,CAAC;QAE1B,MAAM,OAAO,GAAG,IAAA,oCAAwB,EAAC,SAAS,CAAC,CAAC;QACpD,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,CAAC,GAAG,CAAC,yBAAyB,OAAO,CAAC,WAAW,EAAE,8BAA8B,CAAC,CAAC;YAC1F,OAAO,eAAe,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACxC,CAAC;QAED,MAAM,EAAE,MAAM,EAAE,GAAG,2CAAa,UAAU,EAAC,CAAC;QAC5C,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAuB;YAChE,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,UAAU;YAChB,OAAO,EACL,uFAAuF;SAC1F,CAAC,CAAC;QACH,OAAO,eAAe,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACzC,CAAC;CAAA;AAED,8EAA8E;AAC9E,SAAS,eAAe,CAAC,IAAU,EAAE,QAAgB;;IACnD,MAAM,KAAK,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;IACrC,MAAM,MAAM,GAAG,MAAA,IAAA,mBAAU,EAAC,IAAI,CAAC,mCAAI,EAAE,CAAC;IACtC,MAAM,UAAU,GAAG,CAAC,MAAA,MAAM,CAAC,UAAU,mCAAI,EAAE,CAG1C,CAAC;IACF,UAAU,CAAC,iBAAiB,CAAC,mCACxB,CAAC,MAAA,UAAU,CAAC,iBAAiB,CAAC,mCAAI,EAAE,CAAC,KACxC,QAAQ,EAAE,KAAK,GAChB,CAAC;IACF,MAAM,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,IAAA,qBAAY,EAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC3B,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAe,gBAAgB,CAC7B,IAAU,EACV,OAAe;;;QAEf,MAAM,WAAW,GAAG,IAAA,cAAK,EAAC,OAAO,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC;QAEpD,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,kCACvC,OAAO,KACV,GAAG,EAAE,MAAC,OAAO,CAAC,GAA+B,mCAAI,KAAK,IACtD,CAAC;QAEH,MAAM,SAAS,GAAG,IAAA,2BAAe,GAAE,CAAC;QACpC,MAAM,QAAQ,GAAG,CAAC,MAAM,eAAe,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QAC1F,wEAAwE;QACxE,4EAA4E;QAC5E,MAAM,SAAS,GAAG,GAAG,OAAO,CAAC,cAAc,IAAI,WAAW,EAAE,CAAC,WAAW,EAAE,CAAC;QAC3E,MAAM,QAAQ,GAAG,IAAA,yBAAa,EAAC,SAAS,CAAC,CAAC;QAE1C,uCACK,OAAO,KACV,OAAO;YACP,IAAI;YACJ,WAAW,EACX,eAAe,EAAE,IAAA,6BAAkB,EAAC,MAAM,CAAC,EAC3C,QAAQ,EACR,YAAY,EAAE,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EACpC,WAAW,EAAE,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EACnD,SAAS,EACT,QAAQ,EAAE,GAAG,QAAQ,IAAI,SAAS,UAAU,EAC5C,mBAAmB,EAAE,QAAQ,CAAC,CAAC,CAAC,sBAAsB,QAAQ,EAAE,CAAC,CAAC,CAAC,SAAS,IAC5E;IACJ,CAAC;CAAA;AAED,SAAS,gBAAgB,CAAC,IAAU,EAAE,OAAyB;;IAC7D,MAAM,eAAe,iDAChB,OAAO,GACP,OAAO,CAAC,IAAI;QACf,0EAA0E;QAC1E,mBAAmB,EAAE,MAAA,OAAO,CAAC,mBAAmB,mCAAI,EAAE,EACtD,QAAQ,EAAE,MAAA,OAAO,CAAC,QAAQ,mCAAI,MAAM,EACpC,OAAO,EAAE,IAAI,EACb,cAAc,EAAE,OAAO,CAAC,cAAc,EACtC,IAAI,EAAE,EAAE,GACT,CAAC;IACF,IAAA,sBAAa,EACX,IAAI,EACJ,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,iBAAiB,OAAO,CAAC,OAAO,QAAQ,CAAC,EAC9D,gBAAgB,OAAO,CAAC,WAAW,EAAE,EACrC,eAAe,CAChB,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAU,EAAE,OAAyB;IAC7D,IAAI,CAAC,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,QAAQ,KAAK,MAAM;QAAE,OAAO;IAC7D,IAAA,sBAAa,EACX,IAAI,EACJ,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,gBAAgB,CAAC,EACtC,sBAAsB,EACtB,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE,CACzC,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAU,EAAE,OAAyB;;IAC7D,MAAM,MAAM,GAAG,IAAA,iCAAwB,EAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/D,MAAM,EACJ,WAAW,EACX,cAAc,EACd,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,YAAY,EACZ,WAAW,EACX,SAAS,GACV,GAAG,OAAO,CAAC;IAEZ,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,0EAA0E;IAC1E,yEAAyE;IACzE,yEAAyE;IACzE,2EAA2E;IAC3E,8EAA8E;IAC9E,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;QACvB,QAAQ,CAAC,IAAI,CACX,4BAA4B,WAAW,WAAW;YAChD,6DAA6D,MAAM,CAAC,IAAI,qCAAqC;YAC7G,MAAM,cAAc,2CAA2C,CAClE,CAAC;IACJ,CAAC;IAED,IAAI,QAAQ,KAAK,UAAU,EAAE,CAAC;QAC5B,QAAQ,CAAC,IAAI,CACX,2CAA2C,cAAc,kBAAkB;YACzE,kDAAkD;YAClD,oFAAoF;YACpF,MAAM,cAAc,EAAE,CACzB,CAAC;QACF,QAAQ,CAAC,IAAI,CACX,0DAA0D,cAAc,EAAE,CAC3E,CAAC;QACF,yEAAyE;QACzE,uEAAuE;QACvE,sEAAsE;QACtE,+DAA+D;QAC/D,MAAM,MAAM,GAAG,GAAG,WAAW,UAAU,CAAC;QACxC,QAAQ,CAAC,IAAI,CACX,oDAAoD,cAAc,qBAAqB;YACrF,cAAc,cAAc,kCAAkC;YAC9D,8EAA8E,MAAM,OAAO;YAC3F,uCAAuC,MAAM,GAAG,CACnD,CAAC;IACJ,CAAC;SAAM,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QAChC,QAAQ,CAAC,IAAI,CACX,0CAA0C,cAAc,kBAAkB;YACxE,iDAAiD;YACjD,iFAAiF;YACjF,MAAM,cAAc,EAAE,CACzB,CAAC;QACF,QAAQ,CAAC,IAAI,CACX,yDAAyD,cAAc,EAAE,CAC1E,CAAC;IACJ,CAAC;IAED,0EAA0E;IAC1E,4EAA4E;IAC5E,2EAA2E;IAC3E,wEAAwE;IACxE,2EAA2E;IAC3E,8EAA8E;IAC9E,oEAAoE;IACpE,MAAM,MAAM,GAAG,qBAAqB,CAAC;IACrC,MAAM,aAAa,GAAG,CAAC,MAAA,MAAM,CAAC,IAAI,mCAAI,EAAE,CAAC;SACtC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;SACvC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QACX,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACvC,MAAM,SAAS,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QACzC,OAAO;YACL,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC;YAC/B,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC;SACjC,CAAC;IACJ,CAAC,CAAC,CAAC;IACL,KAAK,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,aAAa,EAAE,CAAC;QAC3C,QAAQ,CAAC,IAAI,CACX,kBAAkB,IAAI,OAAO,cAAc,sBAAsB;YAC/D,+BAA+B,IAAI,UAAU,IAAI,IAAI,IAAI,OAAO,cAAc,EAAE,CACnF,CAAC;IACJ,CAAC;IAED,6EAA6E;IAC7E,+EAA+E;IAC/E,6EAA6E;IAC7E,wEAAwE;IACxE,uEAAuE;IACvE,QAAQ,CAAC,IAAI,CAAC,gBAAgB,WAAW,6BAA6B,CAAC,CAAC;IACxE,QAAQ,CAAC,IAAI,CACX,qDAAqD,WAAW,kBAAkB,QAAQ,IAAI,CAC/F,CAAC;IACF,+EAA+E;IAC/E,+EAA+E;IAC/E,QAAQ,CAAC,IAAI,CACX,gCAAgC,YAAY,iDAAiD,CAC9F,CAAC;IACF,QAAQ,CAAC,IAAI,CAAC,eAAe,QAAQ,EAAE,CAAC,CAAC;IACzC,6EAA6E;IAC7E,2EAA2E;IAC3E,QAAQ,CAAC,IAAI,CACX,6CAA6C;QAC3C,mBAAmB,YAAY,qFAAqF;QACpH,MAAM,cAAc,2CAA2C,CAClE,CAAC;IACF,8EAA8E;IAC9E,oEAAoE;IACpE,QAAQ,CAAC,IAAI,CACX,UAAU,QAAQ,IAAI,WAAW,wCAAwC,cAAc,EAAE,CAC1F,CAAC;IACF,QAAQ,CAAC,IAAI,CACX,mBAAmB,WAAW,yBAAyB,cAAc,EAAE,CACxE,CAAC;IAEF,QAAQ,CAAC,IAAI,CACX,4BAA4B,WAAW,IAAI,WAAW,mBAAmB,cAAc,kBAAkB,CAC1G,CAAC;IAEF,QAAQ,CAAC,IAAI,CACX,iCAAiC,WAAW,OAAO,cAAc,EAAE,CACpE,CAAC;IACF,QAAQ,CAAC,IAAI,CACX,gCAAgC,WAAW,OAAO,cAAc,iBAAiB,CAClF,CAAC;IAEF,MAAM,CAAC,OAAO,mCACT,MAAM,CAAC,OAAO,KACjB,OAAO,EAAE;YACP,QAAQ,EAAE,iBAAiB;YAC3B,OAAO,EAAE;gBACP,QAAQ;gBACR,QAAQ,EAAE,KAAK;aAChB;SACF,EACD,kBAAkB,EAAE;YAClB,QAAQ,EAAE,iBAAiB;YAC3B,OAAO,EAAE;gBACP,QAAQ,EAAE;oBACR,qCAAqC,WAAW,OAAO,cAAc,qBAAqB;oBAC1F,yBAAyB,WAAW,OAAO,cAAc,qBAAqB;oBAC9E,mEAAmE;oBACnE,yEAAyE;oBACzE,qCAAqC;oBACrC,gCAAgC,WAAW,uBAAuB,SAAS,sBAAsB;iBAClG;aACF;SACF,GACF,CAAC;IAEF,IAAA,mCAA0B,EAAC,IAAI,EAAE,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;AAC5D,CAAC;AAED,+EAA+E;AAC/E,2EAA2E;AAC3E,iFAAiF;AACjF,6EAA6E;AAC7E,qCAAqC;AACrC,SAAe,0BAA0B,CAAC,OAAyB;;QACjE,IAAI,OAAO,CAAC,OAAO,KAAK,UAAU;YAAE,OAAO;QAC3C,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC;QACtD,IAAI,CAAC,CAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,WAAW,CAAA;YAAE,OAAO;QAE/B,MAAM,aAAa,GAAG,IAAA,kCAAuB,GAAE,CAAC;QAChD,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,OAAO,CAAC,GAAG,CACT,8FAA8F;gBAC5F,2EAA2E,CAC9E,CAAC;YACF,OAAO;QACT,CAAC;QAED,MAAM,QAAQ,GAAG,WAAW,WAAW,IAAI,cAAc,IAAI,aAAa,EAAE,CAAC;QAC7E,MAAM,QAAQ,GAAG,WAAW,IAAI,CAAC,MAAM,IAAI,WAAW,EAAE,CAAC;QACzD,MAAM,IAAA,4BAAqB,EACzB,IAAI,CAAC,gBAAgB,EACrB,IAAI,CAAC,WAAW,EAChB,QAAQ,EACR,CAAC,GAAG,QAAQ,IAAI,CAAC,EACjB,IAAI,CAAC,WAAW,CACjB,CAAC;IACJ,CAAC;CAAA;AAED,mBAA+B,IAAU,EAAE,OAAe;;QACxD,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,8DAA8D,CAAC,CAAC;YAC5E,OAAO;QACT,CAAC;QAED,gBAAgB,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;QAC1C,gBAAgB,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;QAC1C,gBAAgB,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;QAC1C,MAAM,0BAA0B,CAAC,iBAAiB,CAAC,CAAC;QACpD,MAAM,IAAA,oBAAW,EAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;CAAA"}
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  addProjectConfiguration,
3
+ readNxJson,
3
4
  readProjectConfiguration,
4
5
  } from '@nx/devkit';
5
6
  import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
@@ -26,6 +27,7 @@ describe('Sandbox Generator', () => {
26
27
  const options: Schema = {
27
28
  project: 'test',
28
29
  sandboxProject: 'test-sandbox',
30
+ registry: 'ghcr.io/test-org',
29
31
  };
30
32
 
31
33
  function addNodeProject(host) {
@@ -95,13 +97,36 @@ describe('Sandbox Generator', () => {
95
97
  const cmds: string[] = config.targets['sandbox'].options.commands;
96
98
  expect(cmds.some((c) => c.includes('oc rollout restart'))).toBeTruthy();
97
99
  expect(cmds.some((c) => c.includes('oc rollout status'))).toBeTruthy();
98
- // In-cluster binary build (no local podman / external registry route).
99
100
  expect(cmds.some((c) => c.includes('nx build test'))).toBeTruthy();
101
+
102
+ // Local podman build + push to the prescribed registry, with the image name
103
+ // prefixed by the (per-user) sandbox namespace to avoid GHCR's org-global
104
+ // name collisions.
105
+ const imageRef = 'ghcr.io/test-org/test-sandbox-test:sandbox';
106
+ expect(
107
+ cmds.some((c) => c.includes('podman build') && c.includes(imageRef))
108
+ ).toBeTruthy();
109
+ expect(cmds.some((c) => c.includes(`podman push ${imageRef}`))).toBeTruthy();
110
+ expect(cmds.some((c) => c.includes('podman login ghcr.io'))).toBeTruthy();
111
+
112
+ // Import into the namespace imagestream; pods pull from the internal registry.
100
113
  expect(
101
- cmds.some((c) => c.includes('oc start-build test --from-dir=.'))
114
+ cmds.some((c) =>
115
+ c.includes(`oc tag ${imageRef} test:sandbox --reference-policy=local`)
116
+ )
102
117
  ).toBeTruthy();
103
- expect(cmds.some((c) => c.includes('sandbox-build.yml'))).toBeTruthy();
104
- expect(cmds.some((c) => c.includes('podman'))).toBeFalsy();
118
+ expect(
119
+ cmds.some((c) => c.includes('oc import-image test:sandbox --confirm'))
120
+ ).toBeTruthy();
121
+ // Per-deploy pull secret from the gh session (no stored PAT).
122
+ expect(
123
+ cmds.some((c) => c.includes('oc create secret docker-registry ghcr-pull'))
124
+ ).toBeTruthy();
125
+
126
+ // The in-cluster BuildConfig flow is gone.
127
+ expect(cmds.some((c) => c.includes('oc start-build'))).toBeFalsy();
128
+ expect(host.exists('.openshift/test/sandbox-build.yml')).toBeFalsy();
129
+
105
130
  // A node service's ADSP client secret is mirrored from .env into an
106
131
  // OpenShift Secret the deployment reads.
107
132
  expect(
@@ -111,15 +136,20 @@ describe('Sandbox Generator', () => {
111
136
  c.includes('CLIENT_SECRET')
112
137
  )
113
138
  ).toBeTruthy();
139
+ });
140
+
141
+ it('persists the resolved registry to nx.json for reuse', async () => {
142
+ const host = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
143
+ addNodeProject(host);
144
+
145
+ await generator(host, options);
114
146
 
115
- // The ImageStream + BuildConfig manifest is generated.
116
- expect(host.exists('.openshift/test/sandbox-build.yml')).toBeTruthy();
117
- const buildManifest = host
118
- .read('.openshift/test/sandbox-build.yml')
119
- .toString();
120
- expect(buildManifest).toContain('kind: BuildConfig');
121
- expect(buildManifest).toContain('kind: ImageStream');
122
- expect(buildManifest).toContain('test:sandbox');
147
+ const nxJson = readNxJson(host);
148
+ expect(
149
+ (nxJson.generators as Record<string, { registry?: string }>)[
150
+ '@abgov/nx-oc:sandbox'
151
+ ].registry
152
+ ).toBe('ghcr.io/test-org');
123
153
  });
124
154
 
125
155
  it('adds sandbox-teardown nx target', async () => {
@@ -136,6 +166,12 @@ describe('Sandbox Generator', () => {
136
166
  expect(cmds.some((c) => c.includes('test-sandbox'))).toBeTruthy();
137
167
  expect(cmds.some((c) => c.includes('-l app=test'))).toBeTruthy();
138
168
  expect(cmds.some((c) => c.includes('all,configmap'))).toBeTruthy();
169
+ // Teardown also removes the sandbox package (best-effort).
170
+ expect(
171
+ cmds.some((c) =>
172
+ c.includes('packages/container/test-sandbox-test')
173
+ )
174
+ ).toBeTruthy();
139
175
  });
140
176
 
141
177
  it('generates shared postgres manifest with secret-backed DATABASE_URL', async () => {
@@ -11,6 +11,7 @@ export interface Schema {
11
11
  accessToken?: string;
12
12
  tenant?: string;
13
13
  tenantRealm?: string;
14
+ registry?: string;
14
15
  }
15
16
 
16
17
  export interface NormalizedSchema extends Schema {
@@ -18,4 +19,10 @@ export interface NormalizedSchema extends Schema {
18
19
  appType: ApplicationType;
19
20
  adsp: AdspConfiguration;
20
21
  buildOutputPath: string;
22
+ registry: string;
23
+ registryHost: string;
24
+ registryOrg: string;
25
+ imageName: string;
26
+ imageRef: string;
27
+ sourceRepositoryUrl?: string;
21
28
  }
@@ -51,6 +51,11 @@
51
51
  "tenantRealm": {
52
52
  "type": "string",
53
53
  "description": "Keycloak realm UUID. Optional when --tenant is provided; overrides the realm looked up from the tenant service."
54
+ },
55
+ "registry": {
56
+ "type": "string",
57
+ "description": "Container registry to publish the sandbox image to (e.g., ghcr.io/my-org). Defaults to the value stored in nx.json, then derived from the git remote. Persisted to nx.json on first use.",
58
+ "alias": "r"
54
59
  }
55
60
  },
56
61
  "required": ["project", "sandboxProject"],
@@ -1,32 +0,0 @@
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