@abgov/nx-oc 13.0.0-beta.1 → 13.0.0-beta.3

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.
Files changed (43) hide show
  1. package/executors.json +5 -0
  2. package/migrations.json +10 -0
  3. package/package.json +4 -1
  4. package/src/adsp/adsp-utils.d.ts +10 -0
  5. package/src/adsp/adsp-utils.js +48 -0
  6. package/src/adsp/adsp-utils.js.map +1 -1
  7. package/src/build-assets.spec.ts +62 -0
  8. package/src/executors/sandbox/sandbox.d.ts +5 -0
  9. package/src/executors/sandbox/sandbox.js +183 -0
  10. package/src/executors/sandbox/sandbox.js.map +1 -0
  11. package/src/executors/sandbox/sandbox.spec.ts +186 -0
  12. package/src/executors/sandbox/schema.d.ts +12 -0
  13. package/src/executors/sandbox/schema.json +50 -0
  14. package/src/generators/deployment/deployment.js +11 -25
  15. package/src/generators/deployment/deployment.js.map +1 -1
  16. package/src/generators/deployment/deployment.spec.ts +5 -2
  17. package/src/generators/deployment/dotnet-files/Dockerfile__tmpl__ +16 -0
  18. package/src/generators/deployment/frontend-files/Dockerfile__tmpl__ +10 -0
  19. package/src/generators/deployment/node-files/Dockerfile__tmpl__ +10 -0
  20. package/src/generators/deployment/node-files/__projectName__.yml__tmpl__ +12 -1
  21. package/src/generators/deployment/schema.d.ts +1 -0
  22. package/src/generators/sandbox/database-files/sandbox-postgres.yml__tmpl__ +3 -1
  23. package/src/generators/sandbox/files/SANDBOX.md__tmpl__ +91 -0
  24. package/src/generators/sandbox/sandbox.js +109 -56
  25. package/src/generators/sandbox/sandbox.js.map +1 -1
  26. package/src/generators/sandbox/sandbox.spec.ts +110 -13
  27. package/src/generators/sandbox/schema.d.ts +10 -0
  28. package/src/generators/sandbox/schema.json +13 -0
  29. package/src/migrations/convert-sandbox-target/convert-sandbox-target.d.ts +2 -0
  30. package/src/migrations/convert-sandbox-target/convert-sandbox-target.js +54 -0
  31. package/src/migrations/convert-sandbox-target/convert-sandbox-target.js.map +1 -0
  32. package/src/migrations/convert-sandbox-target/convert-sandbox-target.spec.ts +111 -0
  33. package/src/utils/app-type.d.ts +18 -0
  34. package/src/utils/app-type.js +43 -0
  35. package/src/utils/app-type.js.map +1 -0
  36. package/src/utils/git-utils.js +4 -2
  37. package/src/utils/git-utils.js.map +1 -1
  38. package/src/utils/oc-utils.d.ts +1 -0
  39. package/src/utils/oc-utils.js +21 -0
  40. package/src/utils/oc-utils.js.map +1 -1
  41. package/src/generators/deployment/dotnet-files/Dockerfile.template +0 -10
  42. package/src/generators/deployment/frontend-files/Dockerfile.template +0 -8
  43. package/src/generators/deployment/node-files/Dockerfile.template +0 -8
@@ -0,0 +1,50 @@
1
+ {
2
+ "version": 2,
3
+ "outputCapture": "direct-nodejs",
4
+ "$schema": "http://json-schema.org/schema",
5
+ "title": "Sandbox deploy executor",
6
+ "description": "Builds the project image locally with podman, pushes it to the container registry, imports it into the sandbox namespace, and rolls out the deployment.",
7
+ "type": "object",
8
+ "properties": {
9
+ "sandboxProject": {
10
+ "type": "string",
11
+ "description": "The OpenShift namespace to deploy the sandbox into."
12
+ },
13
+ "registry": {
14
+ "type": "string",
15
+ "description": "Container registry the sandbox image is published to (e.g. ghcr.io/my-org)."
16
+ },
17
+ "database": {
18
+ "type": "string",
19
+ "enum": ["none", "postgres", "mongo"],
20
+ "default": "none",
21
+ "description": "Provision a shared sandbox database of this type before deploying."
22
+ },
23
+ "appType": {
24
+ "type": "string",
25
+ "enum": ["node", "frontend", "dotnet"],
26
+ "description": "Application type. Detected from the project configuration when omitted."
27
+ },
28
+ "imageTag": {
29
+ "type": "string",
30
+ "default": "sandbox",
31
+ "description": "Image tag pushed and imported into the namespace imagestream."
32
+ },
33
+ "skipBuild": {
34
+ "type": "boolean",
35
+ "default": false,
36
+ "description": "Skip the nx build + podman build steps and reuse the already-built image (resume a partial deploy)."
37
+ },
38
+ "skipPush": {
39
+ "type": "boolean",
40
+ "default": false,
41
+ "description": "Skip the registry login + push and reuse the already-pushed image (resume from the import step)."
42
+ },
43
+ "importRetries": {
44
+ "type": "number",
45
+ "default": 5,
46
+ "description": "How many times to retry oc import-image (absorbs the 409 from oc tag's async reconcile)."
47
+ }
48
+ },
49
+ "required": ["sandboxProject", "registry"]
50
+ }
@@ -7,51 +7,37 @@ 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
- let appType = options.appType;
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) {
53
33
  var _a, _b;
54
- 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: '' });
55
41
  (0, devkit_1.generateFiles)(host, path.join(__dirname, `${options.appType}-files`), `./.openshift/${options.projectName}`, templateOptions);
56
42
  }
57
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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"}
@@ -158,6 +158,10 @@ describe('Deployment Generator', () => {
158
158
  const manifest = host.read('.openshift/test/test.yml').toString();
159
159
  expect(manifest).toContain('readinessProbe');
160
160
  expect(manifest).toContain('livenessProbe');
161
+ // The service authenticates with ADSP using a confidential client secret,
162
+ // injected from the ${APP_NAME}-secrets Secret.
163
+ expect(manifest).toContain('CLIENT_SECRET');
164
+ expect(manifest).toContain('${APP_NAME}-secrets');
161
165
  });
162
166
 
163
167
  it('can generate deployment for dotnet', async () => {
@@ -218,8 +222,7 @@ describe('Deployment Generator', () => {
218
222
  const manifest = host.read('.openshift/test/test.yml').toString();
219
223
  expect(manifest).toContain('DATABASE_URL');
220
224
  expect(manifest).toContain('initContainers');
221
- expect(manifest).toContain('prisma');
222
- expect(manifest).toContain('migrate');
225
+ expect(manifest).toContain('migrate.js');
223
226
  });
224
227
 
225
228
  it('includes MONGODB_URI secretKeyRef without init container for mongo node deployment', async () => {
@@ -0,0 +1,16 @@
1
+ FROM registry.access.redhat.com/ubi8/dotnet-80 AS build
2
+ ARG PROJECT
3
+ WORKDIR /src
4
+ COPY . .
5
+ RUN dotnet publish ${PROJECT} -c Release -o /app/publish
6
+
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
+ <% } %>
12
+ WORKDIR /app
13
+ COPY --from=build /app/publish .
14
+ ENV ASPNETCORE_URLS=http://+:5000
15
+ EXPOSE 5000
16
+ CMD ["dotnet", "<%= projectName %>.dll"]
@@ -0,0 +1,10 @@
1
+ FROM registry.access.redhat.com/ubi9/nginx-120
2
+ <% if (sourceRepositoryUrl) { %>
3
+ # Provenance: associate the image with its source repo (shown in GHCR).
4
+ LABEL org.opencontainers.image.source=<%= sourceRepositoryUrl %>
5
+ <% } %>
6
+ # Build output path mirrors the workspace layout (from the project's build target).
7
+ COPY ./<%= buildOutputPath %>/nginx.conf "${NGINX_CONF_PATH}"
8
+ COPY ./<%= buildOutputPath %> .
9
+
10
+ CMD nginx -g "daemon off;"
@@ -0,0 +1,10 @@
1
+ FROM registry.access.redhat.com/ubi9/nodejs-24
2
+ <% if (sourceRepositoryUrl) { %>
3
+ # Provenance: associate the image with its source repo (shown in GHCR).
4
+ LABEL org.opencontainers.image.source=<%= sourceRepositoryUrl %>
5
+ <% } %>
6
+ # Build output path mirrors the workspace layout (from the project's build target).
7
+ COPY ./<%= buildOutputPath %> .
8
+ COPY ./node_modules ./node_modules
9
+
10
+ CMD node main.js
@@ -91,7 +91,7 @@ objects:
91
91
  <% } else { %>
92
92
  image: image-registry.openshift-image-registry.svc:5000/${INFRA_PROJECT}/${APP_NAME}:${DEPLOY_TAG}
93
93
  <% } %>
94
- command: ["npx", "prisma", "migrate", "deploy"]
94
+ command: ["node", "migrate.js"]
95
95
  envFrom:
96
96
  - configMapRef:
97
97
  name: ${APP_NAME}
@@ -127,6 +127,17 @@ objects:
127
127
  value: '3333'
128
128
  - name: LOG_LEVEL
129
129
  value: info
130
+ # ADSP confidential-client secret the service uses to authenticate
131
+ # with the access service. Sandbox: created by `nx run <app>:sandbox`
132
+ # from the service's .env.
133
+ <% if (!sandbox) { %>
134
+ # Other envs: oc create secret generic ${APP_NAME}-secrets --from-literal=CLIENT_SECRET=<secret>
135
+ <% } %>
136
+ - name: CLIENT_SECRET
137
+ valueFrom:
138
+ secretKeyRef:
139
+ name: ${APP_NAME}-secrets
140
+ key: CLIENT_SECRET
130
141
  <% if (database === 'postgres') { %>
131
142
  <% if (sandbox) { %>
132
143
  - name: POSTGRES_PASSWORD
@@ -19,4 +19,5 @@ export interface NormalizedSchema extends Schema {
19
19
  ocInfraProject: string;
20
20
  ocEnvProjects: string[];
21
21
  adsp: AdspConfiguration;
22
+ buildOutputPath: string;
22
23
  }
@@ -3,7 +3,9 @@
3
3
  # deleted on re-apply, so data persists across deployments.
4
4
  #
5
5
  # Multiple apps in the same namespace share this instance. Each app uses its
6
- # own database (<appName>_sandbox) created automatically by Prisma migrate.
6
+ # own database (<appName>_sandbox): the `nx run <app>:sandbox` target creates it
7
+ # (idempotently) after Postgres is ready, and the app's migrate init container
8
+ # applies the schema on deploy.
7
9
  #
8
10
  # Credentials are stored in the sandbox-postgres-creds Secret, created once
9
11
  # per namespace by `nx run <app>:sandbox` on first use. Subsequent apps read
@@ -0,0 +1,91 @@
1
+ # Sandbox deploy — <%= projectName %>
2
+
3
+ Deploy runbook for coding agents. `nx run <%= projectName %>:sandbox` builds the
4
+ image **locally with podman**, pushes it to GHCR, imports it into the
5
+ `<%= sandboxProject %>` namespace, and rolls out — no git push or CI wait. The
6
+ orchestration lives in the `@abgov/nx-oc:sandbox` executor (versioned in the
7
+ plugin), so the steps below are what it runs for you.
8
+
9
+ ## What the target does, in order
10
+
11
+ 1. **Preflight** — `oc` login, `gh` auth, and `podman` machine are checked up
12
+ front; a failure here stops before the build with an actionable message.
13
+ 2. Upsert the pull secret + <% if (appType === 'node') { %>the `CLIENT_SECRET` secret + <% } %>any paired Services<% if (database && database !== 'none') { %> + the shared `<%= database %>` database<% } %>.
14
+ 3. `nx build <%= projectName %> --configuration production`
15
+ 4. `podman build` → `podman login` (gh token) → `podman push` to
16
+ `<%= registry %>/<%= imageName %>:sandbox`.
17
+ 5. `oc tag … --reference-policy=local` then `oc import-image` (retried to absorb
18
+ the tag-reconcile 409).
19
+ 6. `oc process | oc apply` the manifest, then `oc rollout restart` + `status`.
20
+
21
+ ## Options (resume a partial deploy without rebuilding)
22
+
23
+ ```bash
24
+ nx run <%= projectName %>:sandbox --skipBuild # reuse the built image; re-push + import + roll out
25
+ nx run <%= projectName %>:sandbox --skipBuild --skipPush # reuse the pushed image; re-import + roll out only
26
+ nx run <%= projectName %>:sandbox --imageTag=<tag> # push/import under a different tag
27
+ nx run <%= projectName %>:sandbox --importRetries=8 # more import retries on a slow cluster
28
+ ```
29
+
30
+ ## Preflight failures — cause → fix
31
+
32
+ - **`'podman' is required …`** — podman not installed. `brew install podman` (macOS).
33
+ - **`podman is installed but not responding`** — machine stopped. `podman machine start`.
34
+ - **`'gh' is required …`** — GitHub CLI not installed. See https://cli.github.com.
35
+ - **`gh is installed but not authenticated`** — run `gh auth login`.
36
+ - **oc login prompts / fails** — `oc login` to your cluster, targeting the
37
+ `<%= sandboxProject %>` namespace (`oc project <%= sandboxProject %>`).
38
+
39
+ ## If the deploy fails mid-way (work around by hand)
40
+
41
+ The executor stops at the first failing step. After fixing the cause, the
42
+ fastest path is usually `--skipBuild` (or `--skipBuild --skipPush`) to resume.
43
+ If you need to drive it manually, these are the remaining steps — the image ref
44
+ is `<%= registry %>/<%= imageName %>:sandbox`:
45
+
46
+ ```bash
47
+ NS=<%= sandboxProject %>
48
+ REF=<%= registry %>/<%= imageName %>:sandbox
49
+ # (1) push, if not already pushed
50
+ gh auth token | podman login <%= registryHost %> -u "$(gh api user -q .login)" --password-stdin
51
+ podman push "$REF"
52
+ # (2) point the imagestream at it and import (retry absorbs the tag race)
53
+ oc tag "$REF" <%= projectName %>:sandbox --reference-policy=local -n "$NS"
54
+ until oc import-image <%= projectName %>:sandbox --confirm -n "$NS"; do sleep 3; done
55
+ # (3) apply the manifest and roll out
56
+ oc process -f .openshift/<%= projectName %>/<%= projectName %>.yml -p PROJECT="$NS" | oc apply -f -
57
+ oc rollout restart deployment/<%= projectName %> -n "$NS"
58
+ oc rollout status deployment/<%= projectName %> -n "$NS" --timeout=180s
59
+ ```
60
+
61
+ ## Verify
62
+
63
+ ```bash
64
+ oc get pods -n <%= sandboxProject %> -l name=<%= projectName %>
65
+ <% if (appType === 'node') { %>curl "https://$(oc get route <%= projectName %> -n <%= sandboxProject %> -o jsonpath='{.spec.host}')/health"<% } else { %>curl -I "https://$(oc get route <%= projectName %> -n <%= sandboxProject %> -o jsonpath='{.spec.host}')/"<% } %>
66
+ ```
67
+
68
+ ## Known issues & workarounds
69
+
70
+ - **`podman push` / import fails with an auth error** — the *active* `gh`
71
+ account lacks `write:packages` (or access to the org). Preflight only confirms
72
+ *an* account is logged in, not its scope. Check `gh auth status`; switch with
73
+ `gh auth switch -u <account>`, then re-run with `--skipBuild`.
74
+ - **Pod `FailedCreate` "exceeded quota"** — the namespace CPU quota is full.
75
+ Free room: `oc get deploy -n <%= sandboxProject %>` then delete stale apps
76
+ (`oc delete all,configmap,is -l app=<old-app> -n <%= sandboxProject %>`), and re-run.
77
+ - **Pod `CrashLoopBackOff`** — `oc logs -n <%= sandboxProject %> <pod> -c <%= projectName %>`.<% if (appType === 'node' && database && database !== 'none') { %>
78
+ For the DB migration, also check the init container:
79
+ `oc logs -n <%= sandboxProject %> <pod> -c <%= projectName %>-migrate`.<% } %>
80
+ <% if (appType === 'frontend') { %>- **Sign-in returns `Invalid redirect_uri`** — the sandbox Route wasn't
81
+ registered on the Keycloak public client (the generator does this when it can
82
+ resolve the cluster ingress domain). Add `https://<%= projectName %>-<%= sandboxProject %>.<ingress-domain>/*`
83
+ to the client's valid redirect URIs.
84
+ <% } %>- **Import 409 "object has been modified"** — the `oc tag` reconcile race; the
85
+ executor already retries. If you hit it manually, just re-run the import.
86
+
87
+ ## Teardown
88
+
89
+ ```bash
90
+ nx run <%= projectName %>:sandbox-teardown # remove sandbox resources + delete the GHCR image
91
+ ```
@@ -6,41 +6,86 @@ 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 oc_utils_1 = require("../../utils/oc-utils");
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
+ }
9
48
  function normalizeOptions(host, options) {
10
49
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
11
- var _a;
50
+ var _a, _b;
12
51
  const projectName = (0, devkit_1.names)(options.project).fileName;
13
52
  const config = (0, devkit_1.readProjectConfiguration)(host, projectName);
14
- let appType = options.appType;
15
- if (!appType) {
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' }));
53
+ const appType = (_a = options.appType) !== null && _a !== void 0 ? _a : (0, app_type_1.detectApplicationType)(config);
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);
34
61
  return Object.assign(Object.assign({}, options), { appType,
35
62
  adsp,
36
- projectName });
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 });
37
64
  });
38
65
  }
39
66
  function addManifestFiles(host, options) {
40
- var _a;
41
- 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: '' });
42
71
  (0, devkit_1.generateFiles)(host, path.join(__dirname, `../deployment/${options.appType}-files`), `./.openshift/${options.projectName}`, templateOptions);
43
72
  }
73
+ // Emit the per-app deploy + troubleshooting runbook next to the manifests, so a
74
+ // coding agent has one canonical, app-aware source (rather than the guidance
75
+ // being duplicated across every app's AGENTS.md).
76
+ function addSandboxDoc(host, options) {
77
+ var _a;
78
+ (0, devkit_1.generateFiles)(host, path.join(__dirname, 'files'), `./.openshift/${options.projectName}`, {
79
+ projectName: options.projectName,
80
+ appType: options.appType,
81
+ database: (_a = options.database) !== null && _a !== void 0 ? _a : 'none',
82
+ sandboxProject: options.sandboxProject,
83
+ registry: options.registry,
84
+ registryHost: options.registryHost,
85
+ imageName: options.imageName,
86
+ tmpl: '',
87
+ });
88
+ }
44
89
  function addDatabaseFiles(host, options) {
45
90
  if (!options.database || options.database === 'none')
46
91
  return;
@@ -48,48 +93,54 @@ function addDatabaseFiles(host, options) {
48
93
  }
49
94
  function addSandboxTarget(host, options) {
50
95
  const config = (0, devkit_1.readProjectConfiguration)(host, options.project);
51
- const { projectName, sandboxProject, database } = options;
52
- const commands = [];
53
- if (database === 'postgres') {
54
- commands.push(`oc get secret sandbox-postgres-creds -n ${sandboxProject} 2>/dev/null || ` +
55
- `oc create secret generic sandbox-postgres-creds ` +
56
- `--from-literal=POSTGRESQL_ADMIN_PASSWORD=$(openssl rand -base64 24 | tr -d '/+=') ` +
57
- `-n ${sandboxProject}`);
58
- commands.push(`oc apply -f .openshift/sandbox/sandbox-postgres.yml -n ${sandboxProject}`);
59
- }
60
- else if (database === 'mongo') {
61
- commands.push(`oc get secret sandbox-mongodb-creds -n ${sandboxProject} 2>/dev/null || ` +
62
- `oc create secret generic sandbox-mongodb-creds ` +
63
- `--from-literal=MONGODB_ADMIN_PASSWORD=$(openssl rand -base64 24 | tr -d '/+=') ` +
64
- `-n ${sandboxProject}`);
65
- commands.push(`oc apply -f .openshift/sandbox/sandbox-mongodb.yml -n ${sandboxProject}`);
66
- }
67
- 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
- commands.push(`oc rollout restart deployment/${projectName} -n ${sandboxProject}`);
76
- commands.push(`oc rollout status deployment/${projectName} -n ${sandboxProject} --timeout=120s`);
96
+ const { projectName, sandboxProject, database, appType, registry, registryOrg, imageName, } = options;
97
+ // The deploy orchestration (preflight, build → podman → push → import with
98
+ // retry → rollout, database/paired-service provisioning) lives in the
99
+ // @abgov/nx-oc:sandbox executor, versioned in the plugin so bug fixes reach
100
+ // every project on `npm update` instead of being baked into project.json.
77
101
  config.targets = Object.assign(Object.assign({}, config.targets), { sandbox: {
78
- executor: 'nx:run-commands',
79
- options: {
80
- commands,
81
- sequential: true,
82
- },
102
+ executor: '@abgov/nx-oc:sandbox',
103
+ options: Object.assign({ sandboxProject,
104
+ registry,
105
+ appType }, (database && database !== 'none' ? { database } : {})),
83
106
  }, 'sandbox-teardown': {
84
107
  executor: 'nx:run-commands',
85
108
  options: {
86
109
  commands: [
87
- `oc delete all,configmap -l app=${projectName} -n ${sandboxProject} --ignore-not-found`,
110
+ `oc delete all,configmap,is -l app=${projectName} -n ${sandboxProject} --ignore-not-found`,
111
+ `oc delete imagestream ${projectName} -n ${sandboxProject} --ignore-not-found`,
112
+ // Remove the sandbox package (needs delete:packages). Best-effort:
113
+ // sandbox packages are the unlinked ones and can also be pruned org-wide
114
+ // via `select(.repository == null)`.
115
+ `gh api --method DELETE /orgs/${registryOrg}/packages/container/${imageName} 2>/dev/null || true`,
88
116
  ],
89
117
  },
90
118
  } });
91
119
  (0, devkit_1.updateProjectConfiguration)(host, options.project, config);
92
120
  }
121
+ // Register the sandbox deployment's Route with the frontend's public client so
122
+ // browser sign-in works against the deployed URL — not just localhost. The
123
+ // Route host is deterministic by convention (<app>-<namespace>.<ingressDomain>),
124
+ // so this happens once at generate time using the token already obtained for
125
+ // ADSP config — no per-deploy login.
126
+ function registerSandboxRedirectUri(options) {
127
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
128
+ if (options.appType !== 'frontend')
129
+ return;
130
+ const { adsp, projectName, sandboxProject } = options;
131
+ if (!(adsp === null || adsp === void 0 ? void 0 : adsp.accessToken))
132
+ return;
133
+ const ingressDomain = (0, oc_utils_1.getClusterIngressDomain)();
134
+ if (!ingressDomain) {
135
+ console.log('[nx-oc] Could not determine the cluster ingress domain; skipping redirect URI registration. ' +
136
+ 'Add the deployment Route to the client manually if browser sign-in fails.');
137
+ return;
138
+ }
139
+ const routeUrl = `https://${projectName}-${sandboxProject}.${ingressDomain}`;
140
+ const clientId = `urn:ads:${adsp.tenant}:${projectName}`;
141
+ yield (0, adsp_1.addClientRedirectUris)(adsp.accessServiceUrl, adsp.tenantRealm, clientId, [`${routeUrl}/*`], adsp.accessToken);
142
+ });
143
+ }
93
144
  function default_1(host, options) {
94
145
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
95
146
  const normalizedOptions = yield normalizeOptions(host, options);
@@ -99,7 +150,9 @@ function default_1(host, options) {
99
150
  }
100
151
  addManifestFiles(host, normalizedOptions);
101
152
  addDatabaseFiles(host, normalizedOptions);
153
+ addSandboxDoc(host, normalizedOptions);
102
154
  addSandboxTarget(host, normalizedOptions);
155
+ yield registerSandboxRedirectUri(normalizedOptions);
103
156
  yield (0, devkit_1.formatFiles)(host);
104
157
  });
105
158
  }
@@ -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":"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"}