@vaharoni/devops 1.0.47
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +51 -0
- package/dist/app-support/crypto/index.d.ts +15 -0
- package/dist/app-support/crypto/index.d.ts.map +1 -0
- package/dist/app-support/crypto/index.js +30 -0
- package/dist/app-support/crypto/internal-token.d.ts +20 -0
- package/dist/app-support/crypto/internal-token.d.ts.map +1 -0
- package/dist/app-support/crypto/internal-token.js +42 -0
- package/dist/app-support/crypto/internal-token.spec.d.ts +2 -0
- package/dist/app-support/crypto/internal-token.spec.d.ts.map +1 -0
- package/dist/app-support/crypto/internal-token.spec.js +45 -0
- package/dist/app-support/crypto/secret.d.ts +3 -0
- package/dist/app-support/crypto/secret.d.ts.map +1 -0
- package/dist/app-support/crypto/secret.js +12 -0
- package/dist/app-support/crypto/secret.spec.d.ts +2 -0
- package/dist/app-support/crypto/secret.spec.d.ts.map +1 -0
- package/dist/app-support/crypto/secret.spec.js +15 -0
- package/dist/app-support/discovery/dev-discovery-loader.d.ts +2 -0
- package/dist/app-support/discovery/dev-discovery-loader.d.ts.map +1 -0
- package/dist/app-support/discovery/dev-discovery-loader.js +30 -0
- package/dist/app-support/discovery/service-endpoint.d.ts +2 -0
- package/dist/app-support/discovery/service-endpoint.d.ts.map +1 -0
- package/dist/app-support/discovery/service-endpoint.js +10 -0
- package/dist/cli/affected.d.ts +11 -0
- package/dist/cli/affected.d.ts.map +1 -0
- package/dist/cli/affected.js +103 -0
- package/dist/cli/common.d.ts +89 -0
- package/dist/cli/common.d.ts.map +1 -0
- package/dist/cli/common.js +236 -0
- package/dist/cli/common.spec.d.ts +2 -0
- package/dist/cli/common.spec.d.ts.map +1 -0
- package/dist/cli/common.spec.js +64 -0
- package/dist/cli/console.d.ts +11 -0
- package/dist/cli/console.d.ts.map +1 -0
- package/dist/cli/console.js +35 -0
- package/dist/cli/constant.d.ts +11 -0
- package/dist/cli/constant.d.ts.map +1 -0
- package/dist/cli/constant.js +22 -0
- package/dist/cli/db.d.ts +11 -0
- package/dist/cli/db.d.ts.map +1 -0
- package/dist/cli/db.js +119 -0
- package/dist/cli/dml.d.ts +11 -0
- package/dist/cli/dml.d.ts.map +1 -0
- package/dist/cli/dml.js +116 -0
- package/dist/cli/env.d.ts +11 -0
- package/dist/cli/env.d.ts.map +1 -0
- package/dist/cli/env.js +67 -0
- package/dist/cli/exec.d.ts +11 -0
- package/dist/cli/exec.d.ts.map +1 -0
- package/dist/cli/exec.js +50 -0
- package/dist/cli/image.d.ts +11 -0
- package/dist/cli/image.d.ts.map +1 -0
- package/dist/cli/image.js +140 -0
- package/dist/cli/init.d.ts +11 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +66 -0
- package/dist/cli/internal-curl.d.ts +11 -0
- package/dist/cli/internal-curl.d.ts.map +1 -0
- package/dist/cli/internal-curl.js +43 -0
- package/dist/cli/job.d.ts +11 -0
- package/dist/cli/job.d.ts.map +1 -0
- package/dist/cli/job.js +67 -0
- package/dist/cli/jwt.d.ts +11 -0
- package/dist/cli/jwt.d.ts.map +1 -0
- package/dist/cli/jwt.js +27 -0
- package/dist/cli/namespace.d.ts +11 -0
- package/dist/cli/namespace.d.ts.map +1 -0
- package/dist/cli/namespace.js +70 -0
- package/dist/cli/prep-build.d.ts +11 -0
- package/dist/cli/prep-build.d.ts.map +1 -0
- package/dist/cli/prep-build.js +82 -0
- package/dist/cli/prisma.d.ts +11 -0
- package/dist/cli/prisma.d.ts.map +1 -0
- package/dist/cli/prisma.js +25 -0
- package/dist/cli/redis.d.ts +11 -0
- package/dist/cli/redis.d.ts.map +1 -0
- package/dist/cli/redis.js +76 -0
- package/dist/cli/registry.d.ts +11 -0
- package/dist/cli/registry.d.ts.map +1 -0
- package/dist/cli/registry.js +58 -0
- package/dist/cli/run-many.d.ts +11 -0
- package/dist/cli/run-many.d.ts.map +1 -0
- package/dist/cli/run-many.js +50 -0
- package/dist/cli/run.d.ts +11 -0
- package/dist/cli/run.d.ts.map +1 -0
- package/dist/cli/run.js +37 -0
- package/dist/cli/template.d.ts +11 -0
- package/dist/cli/template.d.ts.map +1 -0
- package/dist/cli/template.js +123 -0
- package/dist/cli/test.d.ts +11 -0
- package/dist/cli/test.d.ts.map +1 -0
- package/dist/cli/test.js +28 -0
- package/dist/devops.d.ts +3 -0
- package/dist/devops.d.ts.map +1 -0
- package/dist/devops.js +103 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/libs/affected-entities.d.ts +15 -0
- package/dist/libs/affected-entities.d.ts.map +1 -0
- package/dist/libs/affected-entities.js +52 -0
- package/dist/libs/config.d.ts +6 -0
- package/dist/libs/config.d.ts.map +1 -0
- package/dist/libs/config.js +98 -0
- package/dist/libs/dependencies.d.ts +19 -0
- package/dist/libs/dependencies.d.ts.map +1 -0
- package/dist/libs/dependencies.js +62 -0
- package/dist/libs/dependencies.spec.d.ts +2 -0
- package/dist/libs/dependencies.spec.d.ts.map +1 -0
- package/dist/libs/dependencies.spec.js +21 -0
- package/dist/libs/digital-ocean/container-reg.d.ts +6 -0
- package/dist/libs/digital-ocean/container-reg.d.ts.map +1 -0
- package/dist/libs/digital-ocean/container-reg.js +69 -0
- package/dist/libs/discovery/dependencies.d.ts +19 -0
- package/dist/libs/discovery/dependencies.d.ts.map +1 -0
- package/dist/libs/discovery/dependencies.js +62 -0
- package/dist/libs/discovery/dependencies.spec.d.ts +2 -0
- package/dist/libs/discovery/dependencies.spec.d.ts.map +1 -0
- package/dist/libs/discovery/dependencies.spec.js +21 -0
- package/dist/libs/discovery/images.d.ts +5 -0
- package/dist/libs/discovery/images.d.ts.map +1 -0
- package/dist/libs/discovery/images.js +45 -0
- package/dist/libs/discovery/index.d.ts +5 -0
- package/dist/libs/discovery/index.d.ts.map +1 -0
- package/dist/libs/discovery/index.js +55 -0
- package/dist/libs/discovery/package-json-processor.d.ts +3 -0
- package/dist/libs/discovery/package-json-processor.d.ts.map +1 -0
- package/dist/libs/discovery/package-json-processor.js +34 -0
- package/dist/libs/discovery/process-common.d.ts +25 -0
- package/dist/libs/discovery/process-common.d.ts.map +1 -0
- package/dist/libs/discovery/process-common.js +40 -0
- package/dist/libs/discovery/process-package-json.d.ts +3 -0
- package/dist/libs/discovery/process-package-json.d.ts.map +1 -0
- package/dist/libs/discovery/process-package-json.js +34 -0
- package/dist/libs/discovery/process-pyproject-toml.d.ts +3 -0
- package/dist/libs/discovery/process-pyproject-toml.d.ts.map +1 -0
- package/dist/libs/discovery/process-pyproject-toml.js +36 -0
- package/dist/libs/discovery/pyproject-toml-processor.d.ts +3 -0
- package/dist/libs/discovery/pyproject-toml-processor.d.ts.map +1 -0
- package/dist/libs/discovery/pyproject-toml-processor.js +39 -0
- package/dist/libs/git-helpers.d.ts +8 -0
- package/dist/libs/git-helpers.d.ts.map +1 -0
- package/dist/libs/git-helpers.js +20 -0
- package/dist/libs/hetzner/reg-secret.d.ts +3 -0
- package/dist/libs/hetzner/reg-secret.d.ts.map +1 -0
- package/dist/libs/hetzner/reg-secret.js +39 -0
- package/dist/libs/k8s-constants.d.ts +12 -0
- package/dist/libs/k8s-constants.d.ts.map +1 -0
- package/dist/libs/k8s-constants.js +66 -0
- package/dist/libs/k8s-db.d.ts +18 -0
- package/dist/libs/k8s-db.d.ts.map +1 -0
- package/dist/libs/k8s-db.js +73 -0
- package/dist/libs/k8s-generate.d.ts +17 -0
- package/dist/libs/k8s-generate.d.ts.map +1 -0
- package/dist/libs/k8s-generate.js +179 -0
- package/dist/libs/k8s-helpers.d.ts +11 -0
- package/dist/libs/k8s-helpers.d.ts.map +1 -0
- package/dist/libs/k8s-helpers.js +42 -0
- package/dist/libs/k8s-image-config.d.ts +8 -0
- package/dist/libs/k8s-image-config.d.ts.map +1 -0
- package/dist/libs/k8s-image-config.js +113 -0
- package/dist/libs/k8s-job-waiter.d.ts +8 -0
- package/dist/libs/k8s-job-waiter.d.ts.map +1 -0
- package/dist/libs/k8s-job-waiter.js +84 -0
- package/dist/libs/k8s-namespace.d.ts +7 -0
- package/dist/libs/k8s-namespace.d.ts.map +1 -0
- package/dist/libs/k8s-namespace.js +27 -0
- package/dist/libs/k8s-redis.d.ts +6 -0
- package/dist/libs/k8s-redis.d.ts.map +1 -0
- package/dist/libs/k8s-redis.js +31 -0
- package/dist/libs/k8s-secrets-manager.d.ts +5 -0
- package/dist/libs/k8s-secrets-manager.d.ts.map +1 -0
- package/dist/libs/k8s-secrets-manager.js +61 -0
- package/dist/libs/validate-env.d.ts +56 -0
- package/dist/libs/validate-env.d.ts.map +1 -0
- package/dist/libs/validate-env.js +214 -0
- package/dist/libs/validate-env.spec.d.ts +2 -0
- package/dist/libs/validate-env.spec.d.ts.map +1 -0
- package/dist/libs/validate-env.spec.js +168 -0
- package/dist/libs/workspace-discovery.d.ts +2 -0
- package/dist/libs/workspace-discovery.d.ts.map +1 -0
- package/dist/libs/workspace-discovery.js +75 -0
- package/dist/test.d.ts +2 -0
- package/dist/test.d.ts.map +1 -0
- package/dist/test.js +1 -0
- package/dist/types/index.d.ts +925 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +79 -0
- package/package.json +55 -0
- package/src/app-support/crypto/index.ts +31 -0
- package/src/app-support/crypto/internal-token.spec.ts +53 -0
- package/src/app-support/crypto/internal-token.ts +82 -0
- package/src/app-support/crypto/secret.spec.ts +18 -0
- package/src/app-support/crypto/secret.ts +13 -0
- package/src/app-support/discovery/dev-discovery-loader.ts +35 -0
- package/src/app-support/discovery/service-endpoint.ts +12 -0
- package/src/cli/affected.ts +116 -0
- package/src/cli/common.spec.ts +78 -0
- package/src/cli/common.ts +323 -0
- package/src/cli/console.ts +46 -0
- package/src/cli/constant.ts +25 -0
- package/src/cli/db.ts +133 -0
- package/src/cli/dml.ts +126 -0
- package/src/cli/env.ts +87 -0
- package/src/cli/exec.sh +21 -0
- package/src/cli/exec.ts +57 -0
- package/src/cli/image.ts +197 -0
- package/src/cli/init.ts +75 -0
- package/src/cli/internal-curl.ts +48 -0
- package/src/cli/job.ts +80 -0
- package/src/cli/jwt.ts +32 -0
- package/src/cli/namespace.ts +78 -0
- package/src/cli/prep-build.ts +96 -0
- package/src/cli/prisma.ts +33 -0
- package/src/cli/redis.ts +83 -0
- package/src/cli/registry.ts +76 -0
- package/src/cli/run-many.ts +61 -0
- package/src/cli/run.ts +46 -0
- package/src/cli/template.ts +169 -0
- package/src/cli/test.ts +30 -0
- package/src/devops.ts +119 -0
- package/src/index.ts +3 -0
- package/src/libs/affected-entities.ts +71 -0
- package/src/libs/config.ts +117 -0
- package/src/libs/digital-ocean/container-reg.ts +81 -0
- package/src/libs/discovery/dependencies.spec.ts +25 -0
- package/src/libs/discovery/dependencies.ts +73 -0
- package/src/libs/discovery/images.ts +57 -0
- package/src/libs/discovery/index.ts +60 -0
- package/src/libs/discovery/process-common.ts +55 -0
- package/src/libs/discovery/process-package-json.ts +47 -0
- package/src/libs/discovery/process-pyproject-toml.ts +43 -0
- package/src/libs/git-helpers.ts +32 -0
- package/src/libs/hetzner/reg-secret.ts +54 -0
- package/src/libs/k8s-constants.ts +83 -0
- package/src/libs/k8s-db.ts +83 -0
- package/src/libs/k8s-generate.ts +211 -0
- package/src/libs/k8s-helpers.ts +59 -0
- package/src/libs/k8s-image-config.ts +165 -0
- package/src/libs/k8s-job-waiter.ts +124 -0
- package/src/libs/k8s-namespace.ts +41 -0
- package/src/libs/k8s-redis.ts +31 -0
- package/src/libs/k8s-secrets-manager.ts +79 -0
- package/src/libs/validate-env.spec.ts +223 -0
- package/src/libs/validate-env.ts +266 -0
- package/src/target-templates/.devops/config/constants.yaml +17 -0
- package/src/target-templates/.devops/config/images.yaml +88 -0
- package/src/target-templates/.devops/docker-images/common/docker-common.sh +23 -0
- package/src/target-templates/.devops/docker-images/node-services/node-exec.sh +8 -0
- package/src/target-templates/.devops/docker-images/node-services/node-run.sh +8 -0
- package/src/target-templates/.devops/docker-images/node-services.Dockerfile +34 -0
- package/src/target-templates/.devops/docker-images/python-services/python-exec.sh +8 -0
- package/src/target-templates/.devops/docker-images/python-services/python-run.sh +8 -0
- package/src/target-templates/.devops/docker-images/python-services.Dockerfile +29 -0
- package/src/target-templates/.devops/env.example.yaml +23 -0
- package/src/target-templates/.devops/infra/hetzner/abandoned/harbor-values.yaml +30 -0
- package/src/target-templates/.devops/infra/hetzner/abandoned/hcloud-config.yaml +134 -0
- package/src/target-templates/.devops/infra/hetzner/cert-manager.yaml +25 -0
- package/src/target-templates/.devops/infra/hetzner/harbor-cert.yaml +13 -0
- package/src/target-templates/.devops/infra/hetzner/harbor-values.yaml +76 -0
- package/src/target-templates/.devops/infra/hetzner/hcloud-config.yaml +113 -0
- package/src/target-templates/.devops/infra/hetzner/ingress-nginx-annotations.yaml +49 -0
- package/src/target-templates/.devops/infra/hetzner/ingress-nginx-configmap.yaml +8 -0
- package/src/target-templates/.devops/infra/hetzner/retain-storage-class.yaml +8 -0
- package/src/target-templates/.devops/infra/monitoring-ingress.yaml +62 -0
- package/src/target-templates/.devops/infra/stackgres-ui-ingress.yaml +35 -0
- package/src/target-templates/.devops/infra/test.yaml +60 -0
- package/src/target-templates/.devops/manifests/_index.yaml +21 -0
- package/src/target-templates/.devops/manifests/cron-jobs.yaml.hb +55 -0
- package/src/target-templates/.devops/manifests/db-migrate-job.yaml.hb +42 -0
- package/src/target-templates/.devops/manifests/deployment-debug.yaml.hb +44 -0
- package/src/target-templates/.devops/manifests/deployment-process.yaml.hb +47 -0
- package/src/target-templates/.devops/manifests/deployment-web.yaml.hb +53 -0
- package/src/target-templates/.devops/manifests/ingress.yaml.hb +21 -0
- package/src/target-templates/.devops/manifests/prefect.yaml.hb +62 -0
- package/src/target-templates/.devops/manifests/service.yaml.hb +15 -0
- package/src/target-templates/.devops/milvus/production/milvus-values.yaml +2 -0
- package/src/target-templates/.devops/milvus/staging/milvus-values.yaml +2 -0
- package/src/target-templates/.devops/postgres/DailyOperatorRestart.yaml +54 -0
- package/src/target-templates/.devops/postgres/production/cluster/PodDisruptionBudget.yaml +27 -0
- package/src/target-templates/.devops/postgres/production/cluster/SGCluster.yaml +47 -0
- package/src/target-templates/.devops/postgres/production/cluster/StackGres-alerts.yaml +191 -0
- package/src/target-templates/.devops/postgres/production/configurations/06-SGDistributedLogs.yaml +11 -0
- package/src/target-templates/.devops/postgres/production/configurations/07-SGObjectStorage.yaml +18 -0
- package/src/target-templates/.devops/postgres/production/configurations/08-SGScript.yaml +12 -0
- package/src/target-templates/.devops/postgres/staging/cluster/SGCluster.yaml +42 -0
- package/src/target-templates/.devops/postgres/staging/configurations/07-SGObjectStorage.yaml +18 -0
- package/src/target-templates/.devops/postgres/staging/configurations/08-SGScript.yaml +12 -0
- package/src/target-templates/.devops/prefect/production/prefect-values.yaml +14 -0
- package/src/target-templates/.devops/prefect/staging/prefect-values.yaml +14 -0
- package/src/target-templates/.devops/redis/production/redis-values.yaml +20 -0
- package/src/target-templates/.devops/redis/staging/redis-values.yaml +8 -0
- package/src/target-templates/.envrc +5 -0
- package/src/target-templates/.github/actions/build-image@v1/action.yaml +86 -0
- package/src/target-templates/.github/actions/connect-to-digital-ocean@v1/action.yaml +29 -0
- package/src/target-templates/.github/actions/connect-to-hetzner@v1/action.yaml +31 -0
- package/src/target-templates/.github/actions/connect-to-infra@v1/action.yaml +46 -0
- package/src/target-templates/.github/actions/db-migrate@v1/action.yaml +23 -0
- package/src/target-templates/.github/actions/deploy-image@v1/action.yaml +33 -0
- package/src/target-templates/.github/actions/setup-prereq@v1/action.yaml +29 -0
- package/src/target-templates/.github/workflows/k8s-build.yaml +84 -0
- package/src/target-templates/applications/example-data-pipeline/pyproject.toml +14 -0
- package/src/target-templates/applications/example-data-pipeline/src/example_data_pipeline/main.py +38 -0
- package/src/target-templates/applications/example-node/index.ts +30 -0
- package/src/target-templates/applications/example-node/package.json +26 -0
- package/src/target-templates/applications/example-node/tsconfig.json +3 -0
- package/src/target-templates/applications/example-python/pyproject.toml +20 -0
- package/src/target-templates/applications/example-python/src/example_python/__init__.py +0 -0
- package/src/target-templates/applications/example-python/src/example_python/main.py +13 -0
- package/src/target-templates/applications/example-python/src/example_python/scripts.py +17 -0
- package/src/target-templates/applications/example-python/tests/__init__.py +0 -0
- package/src/target-templates/applications/jobs/README.md +68 -0
- package/src/target-templates/applications/jobs/index.ts +1 -0
- package/src/target-templates/applications/jobs/package.json +30 -0
- package/src/target-templates/applications/jobs/tsconfig.json +3 -0
- package/src/target-templates/config/.env.development +1 -0
- package/src/target-templates/config/.env.global +4 -0
- package/src/target-templates/config/.env.test +1 -0
- package/src/target-templates/db/db/__init__.py +0 -0
- package/src/target-templates/db/db/db_client_test.py +46 -0
- package/src/target-templates/db/db-client-test.ts +140 -0
- package/src/target-templates/db/db-client.ts +19 -0
- package/src/target-templates/db/env.yaml +4 -0
- package/src/target-templates/db/package.json +17 -0
- package/src/target-templates/db/prisma/schema.prisma +24 -0
- package/src/target-templates/db/prisma-setup-vitest.ts +27 -0
- package/src/target-templates/db/pyproject.toml +14 -0
- package/src/target-templates/db/tsconfig.json +3 -0
- package/src/target-templates/devops +3 -0
- package/src/target-templates/devopspy +3 -0
- package/src/target-templates/dml/package.json +7 -0
- package/src/target-templates/dml/tsconfig.json +3 -0
- package/src/target-templates/libs/example-node-lib/bun.lock +27 -0
- package/src/target-templates/libs/example-node-lib/index.ts +3 -0
- package/src/target-templates/libs/example-node-lib/package.json +12 -0
- package/src/target-templates/libs/example-node-lib/tsconfig.json +3 -0
- package/src/target-templates/libs/example-python-lib/pyproject.toml +11 -0
- package/src/target-templates/libs/example-python-lib/src/example_python_lib/__init__.py +2 -0
- package/src/target-templates/pyproject.toml +19 -0
- package/src/target-templates/tmp/.gitkeep +0 -0
- package/src/target-templates/tsconfig.json +27 -0
- package/src/test.ts +0 -0
- package/src/types/index.ts +173 -0
@@ -0,0 +1,47 @@
|
|
1
|
+
import chalk from "chalk";
|
2
|
+
import fs from "fs";
|
3
|
+
import { globSync } from "glob";
|
4
|
+
import path from "path";
|
5
|
+
import { packageFileNodeSchema, type PackageData } from "../../types";
|
6
|
+
import { PackageDataProcessor } from "./process-common";
|
7
|
+
|
8
|
+
const rootPkgJsonPath = path.join(process.cwd(), "package.json");
|
9
|
+
const rootPkgJson = JSON.parse(fs.readFileSync(rootPkgJsonPath, "utf8")) as {
|
10
|
+
workspaces: string[];
|
11
|
+
};
|
12
|
+
|
13
|
+
const _workspaces: Record<string, PackageData> = {};
|
14
|
+
let _workspacesLoaded = false;
|
15
|
+
|
16
|
+
export function nodeWorkspaces() {
|
17
|
+
if (!_workspacesLoaded) {
|
18
|
+
const allPackageJsons = (rootPkgJson.workspaces ?? []).flatMap((workspaceGlob) =>
|
19
|
+
globSync(path.join(workspaceGlob, "package.json"))
|
20
|
+
);
|
21
|
+
|
22
|
+
const processor = new PackageDataProcessor({
|
23
|
+
language: "node",
|
24
|
+
pathList: allPackageJsons,
|
25
|
+
zodSchema: packageFileNodeSchema,
|
26
|
+
fileParser: JSON.parse,
|
27
|
+
nameExtractor: (data) => data.name,
|
28
|
+
});
|
29
|
+
|
30
|
+
processor.convert((data) => {
|
31
|
+
const { dependencies, ...rest } = data;
|
32
|
+
const dependencyNames = Object.keys(dependencies ?? []);
|
33
|
+
return { ...rest, dependencyNames: processor.filterDependencies(dependencyNames) };
|
34
|
+
}).forEach(pkgData => {
|
35
|
+
_workspaces[pkgData.name] = pkgData
|
36
|
+
})
|
37
|
+
|
38
|
+
console.warn(
|
39
|
+
chalk.yellow(
|
40
|
+
// prettier-ignore
|
41
|
+
`Node workspace discovery initialized. Workspaces found: ${Object.keys(_workspaces).join(", ")}`
|
42
|
+
)
|
43
|
+
);
|
44
|
+
_workspacesLoaded = true;
|
45
|
+
}
|
46
|
+
return _workspaces;
|
47
|
+
}
|
@@ -0,0 +1,43 @@
|
|
1
|
+
import chalk from "chalk";
|
2
|
+
import { globSync } from "glob";
|
3
|
+
import { packageFilePythonSchema, type PackageData } from "../../types";
|
4
|
+
import { PackageDataProcessor } from "./process-common";
|
5
|
+
import TOML from '@iarna/toml';
|
6
|
+
|
7
|
+
const _workspaces: Record<string, PackageData> = {};
|
8
|
+
let _workspacesLoaded = false;
|
9
|
+
|
10
|
+
export function pythonWorkspaces() {
|
11
|
+
if (!_workspacesLoaded) {
|
12
|
+
const allPyprojectTomls = globSync("**/*/pyproject.toml");
|
13
|
+
const processor = new PackageDataProcessor({
|
14
|
+
language: "python",
|
15
|
+
pathList: allPyprojectTomls,
|
16
|
+
zodSchema: packageFilePythonSchema,
|
17
|
+
fileParser: TOML.parse,
|
18
|
+
nameExtractor: (data) => data.project.name,
|
19
|
+
});
|
20
|
+
|
21
|
+
processor.convert((data) => {
|
22
|
+
const deployment = data.tool?.devops?.deployment;
|
23
|
+
const scripts = data.tool?.devops?.scripts;
|
24
|
+
const dependencyNames = data.project.dependencies ?? [];
|
25
|
+
return {
|
26
|
+
scripts,
|
27
|
+
deployment,
|
28
|
+
dependencyNames: processor.filterDependencies(dependencyNames)
|
29
|
+
}
|
30
|
+
}).forEach(pkgData => {
|
31
|
+
_workspaces[pkgData.name] = pkgData
|
32
|
+
})
|
33
|
+
|
34
|
+
console.warn(
|
35
|
+
chalk.yellow(
|
36
|
+
// prettier-ignore
|
37
|
+
`Python workspace discovery initialized. Workspaces found: ${Object.keys(_workspaces).join(", ")}`
|
38
|
+
)
|
39
|
+
);
|
40
|
+
_workspacesLoaded = true;
|
41
|
+
}
|
42
|
+
return _workspaces;
|
43
|
+
}
|
@@ -0,0 +1,32 @@
|
|
1
|
+
import { CommandExecutor } from "../cli/common";
|
2
|
+
|
3
|
+
export function commitExists(sha: string) {
|
4
|
+
const statusCode = new CommandExecutor(
|
5
|
+
`git merge-base --is-ancestor "${sha}" HEAD`
|
6
|
+
).exec({ onlyStatusCode: true });
|
7
|
+
return statusCode === 0;
|
8
|
+
}
|
9
|
+
|
10
|
+
export function firstCommit() {
|
11
|
+
const res = new CommandExecutor(`git rev-list --max-parents=0 HEAD`, {
|
12
|
+
quiet: true,
|
13
|
+
}).exec();
|
14
|
+
return res?.trim();
|
15
|
+
}
|
16
|
+
|
17
|
+
export function isAffected(
|
18
|
+
path: string,
|
19
|
+
opts: { baseSha?: string; headSha?: string; skipCheck?: boolean } = {}
|
20
|
+
) {
|
21
|
+
const baseSha = opts.baseSha || "HEAD^";
|
22
|
+
const headSha = opts.headSha || "HEAD";
|
23
|
+
// When in doubt, assume it's affected
|
24
|
+
if (!opts.skipCheck && (!commitExists(baseSha) || !commitExists(headSha)))
|
25
|
+
return true;
|
26
|
+
|
27
|
+
const statusCode = new CommandExecutor(
|
28
|
+
`git diff --quiet ${baseSha} ${headSha} -- ${path}`,
|
29
|
+
{ quiet: true }
|
30
|
+
).exec({ onlyStatusCode: true });
|
31
|
+
return statusCode !== 0;
|
32
|
+
}
|
@@ -0,0 +1,54 @@
|
|
1
|
+
import { CommandExecutor } from "../../cli/common";
|
2
|
+
import { getConst } from "../config";
|
3
|
+
import { envToNamespace } from "../k8s-constants";
|
4
|
+
import { kubectlCommand } from "../k8s-helpers";
|
5
|
+
|
6
|
+
function isApplicable() {
|
7
|
+
const infra = getConst("infra");
|
8
|
+
if (infra !== "hetzner") {
|
9
|
+
console.warn(
|
10
|
+
"Setting up registry permissions is only needed for Harbor in a Hetzner setup"
|
11
|
+
);
|
12
|
+
return false;
|
13
|
+
}
|
14
|
+
return true;
|
15
|
+
}
|
16
|
+
|
17
|
+
export function copySecretHarborToNamespace(monorepoEnv: string) {
|
18
|
+
if (!isApplicable()) return;
|
19
|
+
|
20
|
+
const cmd = kubectlCommand("get secret harbor-registry-secret -o json", {
|
21
|
+
monorepoEnv,
|
22
|
+
namespace: "harbor",
|
23
|
+
});
|
24
|
+
const secretStr = new CommandExecutor(cmd, { quiet: true }).exec();
|
25
|
+
const secretJson = JSON.parse(secretStr);
|
26
|
+
const {
|
27
|
+
apiVersion,
|
28
|
+
data,
|
29
|
+
kind,
|
30
|
+
metadata: { name },
|
31
|
+
type,
|
32
|
+
} = secretJson;
|
33
|
+
|
34
|
+
const relevantParts = {
|
35
|
+
apiVersion,
|
36
|
+
data,
|
37
|
+
kind,
|
38
|
+
metadata: { name, namespace: envToNamespace(monorepoEnv) },
|
39
|
+
type,
|
40
|
+
};
|
41
|
+
// prettier-ignore
|
42
|
+
const copyCmd = `echo '${JSON.stringify(relevantParts)}' | kubectl apply -f -`;
|
43
|
+
new CommandExecutor(copyCmd, { quiet: true }).exec();
|
44
|
+
}
|
45
|
+
|
46
|
+
export function patchServiceAccountImagePullSecret(monorepoEnv: string) {
|
47
|
+
if (!isApplicable()) return;
|
48
|
+
|
49
|
+
const cmd = kubectlCommand(
|
50
|
+
`patch serviceaccount default -p '{"imagePullSecrets": [{"name": "harbor-registry-secret"}]}'`,
|
51
|
+
{ monorepoEnv }
|
52
|
+
);
|
53
|
+
new CommandExecutor(cmd, { quiet: true }).exec();
|
54
|
+
}
|
@@ -0,0 +1,83 @@
|
|
1
|
+
import { getConst, getImageData } from "./config";
|
2
|
+
|
3
|
+
export const MISSING_DOMAIN_KEY_ERROR = "$$$MISSING_DOMAIN_KEY$$$"
|
4
|
+
const DEFAULT_REMOTE_ENVS = ["staging", "production"];
|
5
|
+
const DEFAULT_LOCAL_ENVS = ["development", "test"];
|
6
|
+
|
7
|
+
let _remoteSupportedEnvs: string[];
|
8
|
+
function remoteSupportedEnvs() {
|
9
|
+
if (_remoteSupportedEnvs) return _remoteSupportedEnvs;
|
10
|
+
const extra = getConst("extra-remote-environments", { ignoreIfInvalid: true }) ?? [];
|
11
|
+
_remoteSupportedEnvs = [...DEFAULT_REMOTE_ENVS, ...extra];
|
12
|
+
return _remoteSupportedEnvs;
|
13
|
+
}
|
14
|
+
|
15
|
+
let _localSupportedEnvs: string[];
|
16
|
+
function localSupportedEnvs() {
|
17
|
+
if (_localSupportedEnvs) return _localSupportedEnvs;
|
18
|
+
const extra = getConst("extra-local-environments", { ignoreIfInvalid: true }) ?? [];
|
19
|
+
_localSupportedEnvs = [...DEFAULT_LOCAL_ENVS, ...extra];
|
20
|
+
return _localSupportedEnvs
|
21
|
+
}
|
22
|
+
|
23
|
+
export function allSupportedEnvs() {
|
24
|
+
return [...remoteSupportedEnvs(), ...localSupportedEnvs()];
|
25
|
+
}
|
26
|
+
|
27
|
+
function validateEnv(monorepoEnv?: string) {
|
28
|
+
if (!monorepoEnv) throw new Error("MONOREPO_ENV cannot be empty");
|
29
|
+
if (!remoteSupportedEnvs().includes(monorepoEnv)) {
|
30
|
+
console.error(
|
31
|
+
`MONOREPO_ENV must be one of: ${remoteSupportedEnvs().join(", ")}. Can be set using --env flag.`
|
32
|
+
);
|
33
|
+
process.exit(1);
|
34
|
+
}
|
35
|
+
}
|
36
|
+
|
37
|
+
export function envToNamespace(monorepoEnv?: string) {
|
38
|
+
validateEnv(monorepoEnv);
|
39
|
+
return `${getConst("project-name")}-${monorepoEnv}`;
|
40
|
+
}
|
41
|
+
|
42
|
+
export function secretName() {
|
43
|
+
return `${getConst("project-name")}-secret`;
|
44
|
+
}
|
45
|
+
|
46
|
+
export function imageDebugName(image: string) {
|
47
|
+
return `${image}-debug`;
|
48
|
+
}
|
49
|
+
|
50
|
+
export function imageConfigMap(image: string) {
|
51
|
+
return `image-config-${image}`;
|
52
|
+
}
|
53
|
+
|
54
|
+
export function containerRegistryRepoName(image: string, monorepoEnv: string) {
|
55
|
+
validateEnv(monorepoEnv);
|
56
|
+
return `${getConst("project-name")}-${monorepoEnv}-${image}`;
|
57
|
+
}
|
58
|
+
|
59
|
+
export function containerRegistryPath() {
|
60
|
+
return [getConst("registry-base-url"), getConst("registry-name")].join("/");
|
61
|
+
}
|
62
|
+
|
63
|
+
export function containerRegistryRepoPath(
|
64
|
+
image: string,
|
65
|
+
monorepoEnv: string,
|
66
|
+
gitSha: string
|
67
|
+
) {
|
68
|
+
return [
|
69
|
+
getConst("registry-base-url"),
|
70
|
+
getConst("registry-name"),
|
71
|
+
[containerRegistryRepoName(image, monorepoEnv), gitSha].join(":"),
|
72
|
+
].join("/");
|
73
|
+
}
|
74
|
+
|
75
|
+
export function domainNameForEnv(image: string, monorepoEnv: string) {
|
76
|
+
const imageData = getImageData(image);
|
77
|
+
const value = imageData["domains"]?.[monorepoEnv] ?? MISSING_DOMAIN_KEY_ERROR;
|
78
|
+
return value;
|
79
|
+
}
|
80
|
+
|
81
|
+
export function dbMigrateJobName(gitSha: string) {
|
82
|
+
return `db-migrate-job-${gitSha.slice(0, 8)}`;
|
83
|
+
}
|
@@ -0,0 +1,83 @@
|
|
1
|
+
import { CommandExecutor } from "../cli/common";
|
2
|
+
import { kubectlCommand } from "./k8s-helpers";
|
3
|
+
|
4
|
+
export function getDbList() {
|
5
|
+
const cmd = kubectlCommand(`get sgcluster -A`);
|
6
|
+
const res = new CommandExecutor(cmd, { quiet: true }).exec();
|
7
|
+
if (!res) return null;
|
8
|
+
return res;
|
9
|
+
}
|
10
|
+
|
11
|
+
export function getDbBackups() {
|
12
|
+
const cmd = kubectlCommand(`get sgbkp -A`);
|
13
|
+
const res = new CommandExecutor(cmd, { quiet: true }).exec();
|
14
|
+
if (!res) return null;
|
15
|
+
return res;
|
16
|
+
}
|
17
|
+
|
18
|
+
export function getDbAdminPassword() {
|
19
|
+
const cmd = kubectlCommand(
|
20
|
+
`get secrets/stackgres-restapi-admin -o jsonpath="{.data}"`,
|
21
|
+
{ namespace: "stackgres" }
|
22
|
+
);
|
23
|
+
const res = new CommandExecutor(cmd, { quiet: true }).exec();
|
24
|
+
if (!res) return null;
|
25
|
+
try {
|
26
|
+
const resJson = JSON.parse(res);
|
27
|
+
const password = atob(resJson["clearPassword"]);
|
28
|
+
const user = atob(resJson["k8sUsername"]);
|
29
|
+
return { user, password };
|
30
|
+
} catch {
|
31
|
+
return null;
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
export function getDbPasswords(namespace: string) {
|
36
|
+
const cmd = kubectlCommand(`get secrets/${namespace} -o jsonpath="{.data}"`, {
|
37
|
+
namespace,
|
38
|
+
});
|
39
|
+
const res = new CommandExecutor(cmd, { quiet: true }).exec();
|
40
|
+
if (!res) return null;
|
41
|
+
try {
|
42
|
+
const resJson = JSON.parse(res);
|
43
|
+
const superUser = atob(resJson["superuser-username"]);
|
44
|
+
const superPassword = atob(resJson["superuser-password"]);
|
45
|
+
const authenticatorUser = atob(resJson["authenticator-username"]);
|
46
|
+
const authenticatorPassword = atob(resJson["authenticator-password"]);
|
47
|
+
const replicationUser = atob(resJson["replication-username"]);
|
48
|
+
const replicationPassword = atob(resJson["replication-password"]);
|
49
|
+
return {
|
50
|
+
superUser,
|
51
|
+
superPassword,
|
52
|
+
authenticatorUser,
|
53
|
+
authenticatorPassword,
|
54
|
+
replicationUser,
|
55
|
+
replicationPassword,
|
56
|
+
};
|
57
|
+
} catch {
|
58
|
+
return null;
|
59
|
+
}
|
60
|
+
}
|
61
|
+
|
62
|
+
export function connectToPatroni(namespace: string) {
|
63
|
+
const cmd = kubectlCommand(
|
64
|
+
`exec -it ${namespace}-0 -c patroni -- /bin/bash`,
|
65
|
+
{ namespace }
|
66
|
+
);
|
67
|
+
new CommandExecutor(cmd).spawn();
|
68
|
+
}
|
69
|
+
|
70
|
+
export function connectToPsql(namespace: string) {
|
71
|
+
const cmd = kubectlCommand(
|
72
|
+
`exec -it ${namespace}-0 -c postgres-util -- psql`,
|
73
|
+
{ namespace }
|
74
|
+
);
|
75
|
+
new CommandExecutor(cmd).spawn();
|
76
|
+
}
|
77
|
+
|
78
|
+
export function establishTunnel(namespace: string, port: string) {
|
79
|
+
const cmd = kubectlCommand(`port-forward pod/${namespace}-0 ${port}:5432`, {
|
80
|
+
namespace,
|
81
|
+
});
|
82
|
+
new CommandExecutor(cmd).spawn();
|
83
|
+
}
|
@@ -0,0 +1,211 @@
|
|
1
|
+
import type { PackageData, TemplateDbMigrateObject, TemplateDebugObject, TemplateDeploymentObject, TemplateSharedContext } from "../types";
|
2
|
+
import { BASE_SECRET_KEY } from "./k8s-namespace";
|
3
|
+
import { containerRegistryRepoPath, dbMigrateJobName, domainNameForEnv, envToNamespace, imageDebugName, MISSING_DOMAIN_KEY_ERROR, secretName } from "./k8s-constants";
|
4
|
+
import { getWorkspaceScale } from "./k8s-image-config";
|
5
|
+
import path from "path";
|
6
|
+
import yaml from "yaml";
|
7
|
+
import fs from 'fs';
|
8
|
+
import { globSync } from "glob";
|
9
|
+
import _, { template } from 'lodash';
|
10
|
+
import Handlebars from "handlebars";
|
11
|
+
import { getImageData } from "./config";
|
12
|
+
import { getImageDescendentData } from "./discovery/images";
|
13
|
+
|
14
|
+
const MANIFEST_FOLDER_PATH = path.join(process.cwd(), '.devops/manifests');
|
15
|
+
const MANIFEST_INDEX_FILE_PATH = path.join(MANIFEST_FOLDER_PATH, '_index.yaml');
|
16
|
+
const DB_MIGRATE_TEMPLATE_NAME = 'db-migrate';
|
17
|
+
|
18
|
+
type RenderFn = (template: string) => string;
|
19
|
+
|
20
|
+
// = Interface
|
21
|
+
|
22
|
+
export function generateImageDeployments(
|
23
|
+
monorepoEnv: string,
|
24
|
+
image: string,
|
25
|
+
gitSha: string
|
26
|
+
) {
|
27
|
+
const generator = new ImageContextGenerator(monorepoEnv, image, gitSha);
|
28
|
+
const apps = getImageDescendentData(image)
|
29
|
+
.filter((packageData) => packageData.deployment)
|
30
|
+
.flatMap((projectData) => {
|
31
|
+
const context = generator.getDeployment(projectData);
|
32
|
+
const renderFn = (template: string) => Handlebars.compile(template)(context);
|
33
|
+
return generateManifestForDeployment(projectData.rootPath, projectData.deployment!.template, renderFn);
|
34
|
+
});
|
35
|
+
const debug = generateDebugDeployment(monorepoEnv, image, gitSha);
|
36
|
+
const manifest = [debug, ...apps].join("\n---\n");
|
37
|
+
return ensureProperDomainsPresent(manifest, monorepoEnv, image);
|
38
|
+
}
|
39
|
+
|
40
|
+
export function generateWorkspaceDeployment(packageData: PackageData, monorepoEnv: string, image: string, gitSha: string) {
|
41
|
+
const generator = new ImageContextGenerator(monorepoEnv, image, gitSha);
|
42
|
+
const context = generator.getDeployment(packageData);
|
43
|
+
const renderFn = (template: string) => Handlebars.compile(template)(context);
|
44
|
+
const manifest = generateManifestForDeployment(packageData.rootPath, packageData.deployment!.template, renderFn).join("\n---\n");
|
45
|
+
return ensureProperDomainsPresent(manifest, monorepoEnv, image);
|
46
|
+
}
|
47
|
+
|
48
|
+
export function generateDebugDeployment(
|
49
|
+
monorepoEnv: string,
|
50
|
+
image: string,
|
51
|
+
gitSha: string
|
52
|
+
) {
|
53
|
+
const generator = new ImageContextGenerator(monorepoEnv, image, gitSha);
|
54
|
+
const context = generator.getDebug();
|
55
|
+
const renderFn = (template: string) => Handlebars.compile(template)(context);
|
56
|
+
const debugTemplate = getImageData(image)["debug-template"];
|
57
|
+
return generateManifestsFromTemplateName(debugTemplate, renderFn).map(x => yaml.stringify(x)).join("\n---\n");
|
58
|
+
}
|
59
|
+
|
60
|
+
export function generateDbMigrateJob(
|
61
|
+
monorepoEnv: string,
|
62
|
+
image: string,
|
63
|
+
gitSha: string
|
64
|
+
) {
|
65
|
+
const generator = new ImageContextGenerator(monorepoEnv, image, gitSha);
|
66
|
+
const context = generator.getDbMigrate();
|
67
|
+
const renderFn = (template: string) => Handlebars.compile(template)(context);
|
68
|
+
return generateManifestsFromTemplateName(DB_MIGRATE_TEMPLATE_NAME, renderFn).map(x => yaml.stringify(x)).join("\n---\n");
|
69
|
+
}
|
70
|
+
|
71
|
+
// = Verification
|
72
|
+
|
73
|
+
function ensureProperDomainsPresent(manifest: string, monorepoEnv: string, image: string) {
|
74
|
+
if (manifest.includes(MISSING_DOMAIN_KEY_ERROR)) {
|
75
|
+
console.error(`The image ${image} does not have a domain defined for the environment ${monorepoEnv}. Please add it to the .devops/config/images.yaml.`);
|
76
|
+
process.exit(1);
|
77
|
+
}
|
78
|
+
return manifest;
|
79
|
+
}
|
80
|
+
|
81
|
+
// = Generation logic
|
82
|
+
|
83
|
+
// L1 generation: composite
|
84
|
+
|
85
|
+
function generateManifestForDeployment(rootPath: string, templateName: string, renderFn: RenderFn): string[] {
|
86
|
+
const defaults = generateManifestsFromTemplateName(templateName, renderFn);
|
87
|
+
const overrides = generateManifestFromFilesInFolder(rootPath, renderFn);
|
88
|
+
const keyExtractor = (manifest: { kind: string, metadata: { name: string } }) => `${manifest.kind}-${manifest.metadata.name}`;
|
89
|
+
const defaultTemplateLookup = _.keyBy(defaults, keyExtractor);
|
90
|
+
const overrideTemplateLookup = _.keyBy(overrides, keyExtractor);
|
91
|
+
const mergedTemplates = _.merge(defaultTemplateLookup, overrideTemplateLookup);
|
92
|
+
return Object.values(mergedTemplates).map(x => yaml.stringify(x));
|
93
|
+
}
|
94
|
+
|
95
|
+
// L2 generation
|
96
|
+
|
97
|
+
function generateManifestsFromTemplateName(templateName: string, renderFn: RenderFn): object[] {
|
98
|
+
const entries = manifestFilesForTemplate(templateName);
|
99
|
+
if (!entries) {
|
100
|
+
console.error(`No entries found for ${templateName} in ${MANIFEST_INDEX_FILE_PATH}`);
|
101
|
+
process.exit(1);
|
102
|
+
}
|
103
|
+
return generateManifestsFromFileList(entries.map(entry => path.join(MANIFEST_FOLDER_PATH, entry)), renderFn);
|
104
|
+
}
|
105
|
+
|
106
|
+
// L2 generation
|
107
|
+
|
108
|
+
function generateManifestFromFilesInFolder(folderPath: string, renderFn: RenderFn): object[] {
|
109
|
+
const manifestOverridePath = path.join(folderPath, 'manifests');
|
110
|
+
if (!fs.existsSync(manifestOverridePath)) {
|
111
|
+
return []
|
112
|
+
}
|
113
|
+
const files = globSync(path.join(manifestOverridePath, '**/*')).filter(x => fs.lstatSync(x).isFile());
|
114
|
+
return generateManifestsFromFileList(files, renderFn);
|
115
|
+
}
|
116
|
+
|
117
|
+
// L3 generation
|
118
|
+
|
119
|
+
function generateManifestsFromFileList(filesList: string[], renderFn: RenderFn): object[] {
|
120
|
+
return filesList.flatMap((filePath) => {
|
121
|
+
try {
|
122
|
+
const manifestFileStr = fs.readFileSync(filePath, 'utf8');
|
123
|
+
const renderedStr = renderFn(manifestFileStr);
|
124
|
+
const res = yaml.parseAllDocuments(renderedStr);
|
125
|
+
res.forEach((doc) => {
|
126
|
+
if (!doc.get("kind") || !doc.getIn(["metadata", "name"])) {
|
127
|
+
console.error(`Invalid manifest file ${filePath}: kind and metadata.name must be present`);
|
128
|
+
console.error(doc.toString())
|
129
|
+
process.exit(1);
|
130
|
+
}
|
131
|
+
})
|
132
|
+
return res.map(x => x.toJSON());
|
133
|
+
} catch (e) {
|
134
|
+
if (e instanceof Error) {
|
135
|
+
console.error(`Could not parse ${filePath}: ${e.message}`);
|
136
|
+
} else {
|
137
|
+
console.error(`Could not parse ${filePath}`);
|
138
|
+
}
|
139
|
+
process.exit(1);
|
140
|
+
}
|
141
|
+
})
|
142
|
+
}
|
143
|
+
|
144
|
+
// Infra: the template index file
|
145
|
+
|
146
|
+
let _manifestIndex: Record<string, string[]>;
|
147
|
+
function manifestFilesForTemplate(template: string) {
|
148
|
+
if (!_manifestIndex) {
|
149
|
+
try {
|
150
|
+
const indexFileStr = fs.readFileSync(MANIFEST_INDEX_FILE_PATH, 'utf8');
|
151
|
+
_manifestIndex = yaml.parse(indexFileStr)
|
152
|
+
} catch {
|
153
|
+
console.error(`Unable to process ${MANIFEST_INDEX_FILE_PATH}`);
|
154
|
+
process.exit(1)
|
155
|
+
}
|
156
|
+
}
|
157
|
+
return _manifestIndex[template];
|
158
|
+
}
|
159
|
+
|
160
|
+
// Infra: the image context generator
|
161
|
+
|
162
|
+
export class ImageContextGenerator {
|
163
|
+
replicaMap: Record<string, number>;
|
164
|
+
imageContext: Omit<TemplateSharedContext, 'project_name'>;
|
165
|
+
|
166
|
+
constructor(public monorepoEnv: string, public image: string, public gitSha: string) {
|
167
|
+
this.replicaMap = getWorkspaceScale(monorepoEnv, image);
|
168
|
+
this.imageContext = {
|
169
|
+
monorepo_env: monorepoEnv,
|
170
|
+
namespace: envToNamespace(monorepoEnv),
|
171
|
+
env_secret_name: secretName(),
|
172
|
+
env_base_secret_key: BASE_SECRET_KEY,
|
173
|
+
domain_name: domainNameForEnv(image, monorepoEnv),
|
174
|
+
image_path: containerRegistryRepoPath(image, monorepoEnv, gitSha),
|
175
|
+
}
|
176
|
+
}
|
177
|
+
|
178
|
+
getDeployment(pkgData: PackageData): TemplateDeploymentObject {
|
179
|
+
if (!pkgData.deployment) {
|
180
|
+
console.error(`The deployment key is missing for workspace ${pkgData.name}`);
|
181
|
+
process.exit(1);
|
182
|
+
}
|
183
|
+
return {
|
184
|
+
// Basic context
|
185
|
+
project_name: pkgData.name,
|
186
|
+
...this.imageContext,
|
187
|
+
// Defaults that can be overriden by pkgData.deployment
|
188
|
+
app_name: pkgData.name,
|
189
|
+
subdomain: pkgData.deployment.service_name,
|
190
|
+
// This may override the defaults above
|
191
|
+
...pkgData.deployment,
|
192
|
+
// Override from config map
|
193
|
+
replicas: this.replicaMap[pkgData.name] ?? 1,
|
194
|
+
}
|
195
|
+
}
|
196
|
+
|
197
|
+
getDbMigrate(): TemplateDbMigrateObject {
|
198
|
+
return {
|
199
|
+
...this.imageContext,
|
200
|
+
db_migrate_job_name: dbMigrateJobName(this.gitSha),
|
201
|
+
}
|
202
|
+
}
|
203
|
+
|
204
|
+
getDebug(): TemplateDebugObject {
|
205
|
+
return {
|
206
|
+
...this.imageContext,
|
207
|
+
debug_pod_name: imageDebugName(this.image)
|
208
|
+
}
|
209
|
+
}
|
210
|
+
}
|
211
|
+
|
@@ -0,0 +1,59 @@
|
|
1
|
+
import { CommandExecutor } from "../cli/common";
|
2
|
+
import { envToNamespace } from "./k8s-constants";
|
3
|
+
import fs from "fs";
|
4
|
+
|
5
|
+
const TMP_MANIFEST_FOLDER = "tmp/k8s-manifests";
|
6
|
+
|
7
|
+
export function kubectlCommand(
|
8
|
+
cmd: string,
|
9
|
+
opts: { monorepoEnv?: string; namespace?: string } = {}
|
10
|
+
) {
|
11
|
+
if (opts.monorepoEnv || opts.namespace) {
|
12
|
+
const namespace = opts.namespace ?? envToNamespace(opts.monorepoEnv);
|
13
|
+
return `kubectl -n ${namespace} ${cmd}`;
|
14
|
+
} else {
|
15
|
+
return `kubectl ${cmd}`;
|
16
|
+
}
|
17
|
+
}
|
18
|
+
|
19
|
+
export function upsertConfigMapCommand(monorepoEnv: string, configMapName: string, data: Record<string, string>) {
|
20
|
+
const manifest = {
|
21
|
+
apiVersion: 'v1',
|
22
|
+
kind: 'ConfigMap',
|
23
|
+
metadata: {
|
24
|
+
name: configMapName,
|
25
|
+
namespace: envToNamespace(monorepoEnv),
|
26
|
+
labels: {
|
27
|
+
env: monorepoEnv
|
28
|
+
}
|
29
|
+
},
|
30
|
+
data
|
31
|
+
}
|
32
|
+
const applyCmd = kubectlCommand(`apply -f -`, { monorepoEnv });
|
33
|
+
return `echo '${JSON.stringify(manifest)}' | ${applyCmd}`;
|
34
|
+
}
|
35
|
+
|
36
|
+
export function patchSecretKeyCommand(monorepoEnv: string, secretName: string, secretKey: string, secretValue: string) {
|
37
|
+
const redactedCommand = kubectlCommand(
|
38
|
+
`patch secret ${secretName} -p='{"stringData": {"${secretKey}": **REDACTED**}}'`,
|
39
|
+
{ monorepoEnv }
|
40
|
+
);
|
41
|
+
const fullCommand = redactedCommand.replace(
|
42
|
+
"**REDACTED**",
|
43
|
+
JSON.stringify(secretValue)
|
44
|
+
);
|
45
|
+
return { fullCommand, redactedCommand };
|
46
|
+
}
|
47
|
+
|
48
|
+
export function applyHandler(
|
49
|
+
filePrefix: string,
|
50
|
+
command: "apply" | "delete",
|
51
|
+
manifest: string
|
52
|
+
) {
|
53
|
+
if (!fs.existsSync(TMP_MANIFEST_FOLDER)) {
|
54
|
+
fs.mkdirSync(TMP_MANIFEST_FOLDER, { recursive: true });
|
55
|
+
}
|
56
|
+
const path = `${TMP_MANIFEST_FOLDER}/${filePrefix}-${Date.now()}.yaml`;
|
57
|
+
fs.writeFileSync(path, manifest);
|
58
|
+
new CommandExecutor(kubectlCommand(`${command} -f ${path}`)).exec();
|
59
|
+
}
|