@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,236 @@
|
|
1
|
+
import chalk from "chalk";
|
2
|
+
import { execSync, spawn } from "child_process";
|
3
|
+
import fs from "fs";
|
4
|
+
import { globSync } from "glob";
|
5
|
+
import { allSupportedEnvs } from "../libs/k8s-constants";
|
6
|
+
export class CLICommandParser {
|
7
|
+
command;
|
8
|
+
args;
|
9
|
+
env;
|
10
|
+
envForced;
|
11
|
+
help;
|
12
|
+
skipEnvCheck;
|
13
|
+
constructor(cmdArray) {
|
14
|
+
const parsedArgs = this._separateOptions(cmdArray.filter(Boolean), {
|
15
|
+
params: ["--env"],
|
16
|
+
booleans: ["--help", "--skip-env-check"],
|
17
|
+
});
|
18
|
+
const [command, ...args] = parsedArgs.args;
|
19
|
+
this.command = command;
|
20
|
+
this.args = args;
|
21
|
+
this.envForced = Boolean(parsedArgs.options["--env"]);
|
22
|
+
this.env =
|
23
|
+
parsedArgs.options["--env"] ??
|
24
|
+
process.env["MONOREPO_ENV"] ??
|
25
|
+
"development";
|
26
|
+
this.help = Boolean(parsedArgs.options["--help"]);
|
27
|
+
this.skipEnvCheck = Boolean(parsedArgs.options["--skip-env-check"]);
|
28
|
+
// We need to hardcode this to avoid chicken-and-egg problem (validate env depends on constants.yaml existence)
|
29
|
+
if (this.command !== 'init') {
|
30
|
+
this._validateEnv(this.env);
|
31
|
+
}
|
32
|
+
}
|
33
|
+
// Copies the env
|
34
|
+
executorFromEnv(commandStr, options = {}) {
|
35
|
+
const checkEnvYamlOverride = this.skipEnvCheck
|
36
|
+
? { checkEnvYaml: false }
|
37
|
+
: {};
|
38
|
+
return new CommandExecutor(commandStr, {
|
39
|
+
env: this.env,
|
40
|
+
...options,
|
41
|
+
...checkEnvYamlOverride,
|
42
|
+
});
|
43
|
+
}
|
44
|
+
// Example:
|
45
|
+
// const cmd = new CLICommandParser('devops run --some-flag --in workspace arg1'.split(' '));
|
46
|
+
// cmd.parseOptions({ boolean: ['--some-flag'], params: ['--in'] })
|
47
|
+
// # => { args: ['arg1'], options: { '--some-flag': true, '--in': 'workspace' } }
|
48
|
+
//
|
49
|
+
// Note that the global param --env is already extracted and can be accessed with cmd.env
|
50
|
+
parseOptions({ params = [], booleans = [], passthroughArgs = false, } = {}) {
|
51
|
+
return this._separateOptions(this.args, {
|
52
|
+
params,
|
53
|
+
booleans,
|
54
|
+
passthroughArgs,
|
55
|
+
});
|
56
|
+
}
|
57
|
+
_validateEnv(env) {
|
58
|
+
if (!allSupportedEnvs().includes(env)) {
|
59
|
+
console.error(
|
60
|
+
// prettier-ignore
|
61
|
+
`Environment must be one of: ${allSupportedEnvs().join(", ")}. Received: ${env}`);
|
62
|
+
process.exit(1);
|
63
|
+
}
|
64
|
+
return true;
|
65
|
+
}
|
66
|
+
_separateOptions(args, { params = [], booleans = [], passthroughArgs = false, } = {}) {
|
67
|
+
const results = {
|
68
|
+
args: [],
|
69
|
+
argsStr: "",
|
70
|
+
options: {},
|
71
|
+
...(passthroughArgs ? { passthrough: [] } : {}),
|
72
|
+
};
|
73
|
+
const paramsLookup = Object.fromEntries(params.map((x) => [x, true]));
|
74
|
+
const booleansLookup = Object.fromEntries(booleans.map((x) => [x, true]));
|
75
|
+
const passthroughArgsStart = passthroughArgs ? args.indexOf("--") : -1;
|
76
|
+
const numArgsToProcess = passthroughArgsStart === -1 ? args.length : passthroughArgsStart;
|
77
|
+
for (let i = 0; i < numArgsToProcess; ++i) {
|
78
|
+
const curr = args[i];
|
79
|
+
if (paramsLookup[curr]) {
|
80
|
+
const next = args[i + 1];
|
81
|
+
results.options[curr] = next;
|
82
|
+
++i;
|
83
|
+
}
|
84
|
+
else if (booleansLookup[curr]) {
|
85
|
+
results.options[curr] = true;
|
86
|
+
}
|
87
|
+
else {
|
88
|
+
results.args.push(curr);
|
89
|
+
}
|
90
|
+
}
|
91
|
+
results.argsStr = results.args.join(" ");
|
92
|
+
if (passthroughArgs && passthroughArgsStart >= 0) {
|
93
|
+
results.passthrough = args.slice(passthroughArgsStart + 1);
|
94
|
+
}
|
95
|
+
return results;
|
96
|
+
}
|
97
|
+
}
|
98
|
+
export class CommandExecutor {
|
99
|
+
commandStr;
|
100
|
+
env;
|
101
|
+
quiet;
|
102
|
+
redactedCommand;
|
103
|
+
checkEnvYaml;
|
104
|
+
constructor(commandStr, { env, quiet = false, redactedCommand, checkEnvYaml = false, } = {}) {
|
105
|
+
this.env = env;
|
106
|
+
this.quiet = quiet ?? false;
|
107
|
+
this.commandStr = commandStr;
|
108
|
+
this.checkEnvYaml = checkEnvYaml;
|
109
|
+
this.redactedCommand = redactedCommand;
|
110
|
+
}
|
111
|
+
exec({ onlyStatusCode = false, asObject = false, env = {}, } = {}) {
|
112
|
+
this._checkEnvYamlFiles();
|
113
|
+
const fullCommand = this._prepareFullCommand();
|
114
|
+
const envToUse = this._getProcessEnv(env);
|
115
|
+
try {
|
116
|
+
const output = execSync(fullCommand, { env: envToUse });
|
117
|
+
if (onlyStatusCode)
|
118
|
+
return 0;
|
119
|
+
if (!this.quiet)
|
120
|
+
console.log(output.toString());
|
121
|
+
if (asObject)
|
122
|
+
return { statusCode: 0, stdout: output.toString() };
|
123
|
+
return output.toString();
|
124
|
+
}
|
125
|
+
catch (error) {
|
126
|
+
const typedError = error;
|
127
|
+
if (onlyStatusCode)
|
128
|
+
return typedError.status;
|
129
|
+
const stdout = typedError.stdout?.toString().trim();
|
130
|
+
const stderr = typedError.stderr?.toString().trim();
|
131
|
+
if (!this.quiet) {
|
132
|
+
console.warn(stdout);
|
133
|
+
console.error(stderr);
|
134
|
+
}
|
135
|
+
if (asObject)
|
136
|
+
return { statusCode: typedError.status, stdout, stderr };
|
137
|
+
process.exit(typedError.status);
|
138
|
+
}
|
139
|
+
}
|
140
|
+
/** Should be used for CLI commands intended to be used locally. Provides interactivity. Unlike exec(), stdout is not returned. */
|
141
|
+
spawn({ env = {} } = {}) {
|
142
|
+
this._checkEnvYamlFiles();
|
143
|
+
const fullCommand = this._prepareFullCommand();
|
144
|
+
const envToUse = this._getProcessEnv(env);
|
145
|
+
return new Promise((resolve) => {
|
146
|
+
try {
|
147
|
+
const [cmd, ...args] = fullCommand.split(" ").filter(Boolean);
|
148
|
+
const childProcess = spawn(cmd, args, {
|
149
|
+
stdio: "inherit",
|
150
|
+
env: envToUse,
|
151
|
+
});
|
152
|
+
childProcess.on("close", (code) => {
|
153
|
+
if (code !== 0) {
|
154
|
+
console.error(chalk.red(`Process exited with code ${code}`));
|
155
|
+
process.exit(code);
|
156
|
+
}
|
157
|
+
resolve(code);
|
158
|
+
});
|
159
|
+
childProcess.on("error", (error) => {
|
160
|
+
console.error(chalk.red(`Error: ${error.message}`));
|
161
|
+
process.exit(1);
|
162
|
+
});
|
163
|
+
}
|
164
|
+
catch (error) {
|
165
|
+
if (error instanceof Error) {
|
166
|
+
console.error(chalk.red(`${error.message}`));
|
167
|
+
}
|
168
|
+
process.exit(1);
|
169
|
+
}
|
170
|
+
});
|
171
|
+
}
|
172
|
+
_prepareFullCommand() {
|
173
|
+
const envPrefix = this.env ? this._envInjectorPrefix() : "";
|
174
|
+
const fullCommand = [envPrefix, this.commandStr].join(" ").trim();
|
175
|
+
const envPrefixLog = this.env ? `MONOREPO_ENV=${this.env}` : "";
|
176
|
+
const fullCommandLog = [envPrefixLog, fullCommand].join(" ").trim();
|
177
|
+
if (this.redactedCommand) {
|
178
|
+
console.warn(chalk.yellow(fullCommandLog.replace(this.commandStr, this.redactedCommand)));
|
179
|
+
}
|
180
|
+
else {
|
181
|
+
console.warn(chalk.yellow(fullCommandLog));
|
182
|
+
}
|
183
|
+
return fullCommand;
|
184
|
+
}
|
185
|
+
_getProcessEnv(envOverride = {}) {
|
186
|
+
return { ...process.env, MONOREPO_ENV: this.env, ...envOverride };
|
187
|
+
}
|
188
|
+
_envInjectorPrefix() {
|
189
|
+
const envFiles = dotEnvFilesForEnv(this.env);
|
190
|
+
if (envFiles.length === 0) {
|
191
|
+
return "";
|
192
|
+
}
|
193
|
+
else {
|
194
|
+
return `bunx dotenvx -q run -f ${envFiles.join(" ")} -- `;
|
195
|
+
}
|
196
|
+
}
|
197
|
+
_checkEnvYamlFiles() {
|
198
|
+
if (!this.checkEnvYaml)
|
199
|
+
return;
|
200
|
+
const envYamlFiles = globSync("**/env.yaml");
|
201
|
+
const checkEnvCmd = new CommandExecutor(`devops env _validate ${envYamlFiles.join(" ")}`, { env: this.env, quiet: true, checkEnvYaml: false });
|
202
|
+
checkEnvCmd.exec();
|
203
|
+
}
|
204
|
+
}
|
205
|
+
export function dotEnvFilesForEnv(env) {
|
206
|
+
const globalEnvFilePath = "config/.env.global";
|
207
|
+
const specificEnvFilePath = `config/.env.${env}`;
|
208
|
+
const envFiles = [];
|
209
|
+
if (env && fs.existsSync(specificEnvFilePath))
|
210
|
+
envFiles.push(specificEnvFilePath);
|
211
|
+
if (fs.existsSync(globalEnvFilePath))
|
212
|
+
envFiles.push(globalEnvFilePath);
|
213
|
+
return envFiles;
|
214
|
+
}
|
215
|
+
export function printUsageAndExit(text) {
|
216
|
+
console.warn(text);
|
217
|
+
process.exit(1);
|
218
|
+
}
|
219
|
+
export class StrongParams {
|
220
|
+
usage;
|
221
|
+
args;
|
222
|
+
constructor(usage, args) {
|
223
|
+
this.usage = usage;
|
224
|
+
this.args = args;
|
225
|
+
}
|
226
|
+
required(key) {
|
227
|
+
if (!this.args[key]) {
|
228
|
+
console.error(`Missing required argument: ${key}`);
|
229
|
+
printUsageAndExit(this.usage);
|
230
|
+
}
|
231
|
+
return this.args[key];
|
232
|
+
}
|
233
|
+
optional(key) {
|
234
|
+
return this.args[key];
|
235
|
+
}
|
236
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"common.spec.d.ts","sourceRoot":"","sources":["../../src/cli/common.spec.ts"],"names":[],"mappings":""}
|
@@ -0,0 +1,64 @@
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
2
|
+
import { CLICommandParser } from './common';
|
3
|
+
describe('CLICommandParser', () => {
|
4
|
+
// Extra white space intentional
|
5
|
+
const subject = new CLICommandParser('run tmp/test.sh --env production --in workspace --flag arg'.split(' '));
|
6
|
+
it('constructor: builds object correctly', () => {
|
7
|
+
expect(subject.command).toEqual('run');
|
8
|
+
expect(subject.env).toEqual('production');
|
9
|
+
expect(subject.args).toEqual([
|
10
|
+
'tmp/test.sh',
|
11
|
+
'--in',
|
12
|
+
'workspace',
|
13
|
+
'--flag',
|
14
|
+
'arg',
|
15
|
+
]);
|
16
|
+
});
|
17
|
+
describe('parseOptions', () => {
|
18
|
+
it('detects params and booleans', () => {
|
19
|
+
const res = subject.parseOptions({
|
20
|
+
params: ['--in'],
|
21
|
+
booleans: ['--flag'],
|
22
|
+
});
|
23
|
+
expect(res.args).toEqual(['tmp/test.sh', 'arg']);
|
24
|
+
expect(res.argsStr).toEqual('tmp/test.sh arg');
|
25
|
+
expect(res.options).toEqual({ '--in': 'workspace', '--flag': true });
|
26
|
+
});
|
27
|
+
it('leaves intact params that are not in the list', () => {
|
28
|
+
const res = subject.parseOptions();
|
29
|
+
expect(res.args).toEqual([
|
30
|
+
'tmp/test.sh',
|
31
|
+
'--in',
|
32
|
+
'workspace',
|
33
|
+
'--flag',
|
34
|
+
'arg',
|
35
|
+
]);
|
36
|
+
expect(res.argsStr).toEqual('tmp/test.sh --in workspace --flag arg');
|
37
|
+
expect(res.options).toEqual({});
|
38
|
+
});
|
39
|
+
it('handles passthrough args when they exist', () => {
|
40
|
+
const altSubject = new CLICommandParser('run tmp/test.sh --env production --in workspace --flag arg -- p1 p2'.split(' '));
|
41
|
+
const res = altSubject.parseOptions({
|
42
|
+
params: ['--in'],
|
43
|
+
booleans: ['--flag'],
|
44
|
+
passthroughArgs: true,
|
45
|
+
});
|
46
|
+
expect(res.args).toEqual(['tmp/test.sh', 'arg']);
|
47
|
+
expect(res.argsStr).toEqual('tmp/test.sh arg');
|
48
|
+
expect(res.options).toEqual({ '--in': 'workspace', '--flag': true });
|
49
|
+
expect(res.passthrough).toEqual(['p1', 'p2']);
|
50
|
+
});
|
51
|
+
it('handles passthrough args when they do not exist', () => {
|
52
|
+
const altSubject = new CLICommandParser('run tmp/test.sh --env production --in workspace --flag arg'.split(' '));
|
53
|
+
const res = altSubject.parseOptions({
|
54
|
+
params: ['--in'],
|
55
|
+
booleans: ['--flag'],
|
56
|
+
passthroughArgs: true,
|
57
|
+
});
|
58
|
+
expect(res.args).toEqual(['tmp/test.sh', 'arg']);
|
59
|
+
expect(res.argsStr).toEqual('tmp/test.sh arg');
|
60
|
+
expect(res.options).toEqual({ '--in': 'workspace', '--flag': true });
|
61
|
+
expect(res.passthrough).toEqual([]);
|
62
|
+
});
|
63
|
+
});
|
64
|
+
});
|
@@ -0,0 +1,11 @@
|
|
1
|
+
import { CLICommandParser } from "./common";
|
2
|
+
declare function run(cmdObj: CLICommandParser): void;
|
3
|
+
declare const _default: {
|
4
|
+
console: {
|
5
|
+
oneLiner: string;
|
6
|
+
keyExamples: string;
|
7
|
+
run: typeof run;
|
8
|
+
};
|
9
|
+
};
|
10
|
+
export default _default;
|
11
|
+
//# sourceMappingURL=console.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"console.d.ts","sourceRoot":"","sources":["../../src/cli/console.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,gBAAgB,EAAqB,MAAM,UAAU,CAAC;AAgB/D,iBAAS,GAAG,CAAC,MAAM,EAAE,gBAAgB,QAmBpC;;;;;;;;AAED,wBAEE"}
|
@@ -0,0 +1,35 @@
|
|
1
|
+
import { getConst } from "../libs/config";
|
2
|
+
import { envToNamespace, imageDebugName, } from "../libs/k8s-constants";
|
3
|
+
import { kubectlCommand } from "../libs/k8s-helpers";
|
4
|
+
import { CLICommandParser, printUsageAndExit } from "./common";
|
5
|
+
const oneLiner = "Get a shell into the debug pod of an image";
|
6
|
+
const keyExamples = `
|
7
|
+
$ devops console main-node
|
8
|
+
`.trim();
|
9
|
+
const usage = `
|
10
|
+
${oneLiner}
|
11
|
+
|
12
|
+
Each image has a debug pod. This command gets a shell into the debug pod of the specified image.
|
13
|
+
|
14
|
+
EXAMPLES
|
15
|
+
${keyExamples}
|
16
|
+
`;
|
17
|
+
function run(cmdObj) {
|
18
|
+
if (cmdObj.help || cmdObj.args.length === 0)
|
19
|
+
printUsageAndExit(usage);
|
20
|
+
const image = cmdObj.args[0];
|
21
|
+
const debugName = imageDebugName(image);
|
22
|
+
const namespace = envToNamespace(cmdObj.env);
|
23
|
+
const podName = cmdObj
|
24
|
+
.executorFromEnv(kubectlCommand(`get pod -n ${namespace} -l app=${debugName} -o name`, {
|
25
|
+
namespace,
|
26
|
+
}), { quiet: true })
|
27
|
+
.exec()
|
28
|
+
.trim();
|
29
|
+
cmdObj
|
30
|
+
.executorFromEnv(kubectlCommand(`exec -it ${podName} -- /bin/bash`, { namespace }))
|
31
|
+
.spawn();
|
32
|
+
}
|
33
|
+
export default {
|
34
|
+
console: { oneLiner, keyExamples, run },
|
35
|
+
};
|
@@ -0,0 +1,11 @@
|
|
1
|
+
import { CLICommandParser } from "./common";
|
2
|
+
declare function run(cmdObj: CLICommandParser): Promise<void>;
|
3
|
+
declare const _default: {
|
4
|
+
constant: {
|
5
|
+
oneLiner: string;
|
6
|
+
keyExamples: string;
|
7
|
+
run: typeof run;
|
8
|
+
};
|
9
|
+
};
|
10
|
+
export default _default;
|
11
|
+
//# sourceMappingURL=constant.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"constant.d.ts","sourceRoot":"","sources":["../../src/cli/constant.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAqB,MAAM,UAAU,CAAC;AAe/D,iBAAe,GAAG,CAAC,MAAM,EAAE,gBAAgB,iBAI1C;;;;;;;;AAED,wBAEE"}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
import { getConst } from "../libs/config";
|
2
|
+
import { CLICommandParser, printUsageAndExit } from "./common";
|
3
|
+
const oneLiner = "Prints to stdout a constant from constant.yaml";
|
4
|
+
const keyExamples = `$ devops constant infra`;
|
5
|
+
const usage = `
|
6
|
+
${oneLiner}
|
7
|
+
|
8
|
+
GENERAL USAGE
|
9
|
+
devops constant <constant-name>
|
10
|
+
|
11
|
+
EXAMPLES
|
12
|
+
${keyExamples}
|
13
|
+
`;
|
14
|
+
async function run(cmdObj) {
|
15
|
+
if (cmdObj.help || cmdObj.args.length === 0)
|
16
|
+
printUsageAndExit(usage);
|
17
|
+
const [constant] = cmdObj.args;
|
18
|
+
console.log(getConst(constant));
|
19
|
+
}
|
20
|
+
export default {
|
21
|
+
constant: { oneLiner, keyExamples, run },
|
22
|
+
};
|
package/dist/cli/db.d.ts
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
import { CLICommandParser } from "./common";
|
2
|
+
declare function run(cmdObj: CLICommandParser): void;
|
3
|
+
declare const _default: {
|
4
|
+
db: {
|
5
|
+
oneLiner: string;
|
6
|
+
keyExamples: string;
|
7
|
+
run: typeof run;
|
8
|
+
};
|
9
|
+
};
|
10
|
+
export default _default;
|
11
|
+
//# sourceMappingURL=db.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/cli/db.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,gBAAgB,EAAmC,MAAM,UAAU,CAAC;AAsG7E,iBAAS,GAAG,CAAC,MAAM,EAAE,gBAAgB,QAiBpC;;;;;;;;AAED,wBAEE"}
|
package/dist/cli/db.js
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
import { connectToPatroni, connectToPsql, establishTunnel, getDbAdminPassword, getDbBackups, getDbList, getDbPasswords, } from "../libs/k8s-db";
|
2
|
+
import { CLICommandParser, printUsageAndExit, StrongParams } from "./common";
|
3
|
+
const oneLiner = "Utilities to help day to day operations of production and staging databases";
|
4
|
+
const keyExamples = `
|
5
|
+
$ devops db list
|
6
|
+
$ devops db backups
|
7
|
+
$ devops db password ui
|
8
|
+
$ devops db password db-staging
|
9
|
+
$ devops db tunnel db-staging
|
10
|
+
$ devops db patroni db-staging
|
11
|
+
$ devops db psql db-staging
|
12
|
+
`.trim();
|
13
|
+
const usage = `
|
14
|
+
${oneLiner}
|
15
|
+
|
16
|
+
NOTES
|
17
|
+
The admin UI provided by Stackgres is great. It allows you to do most of the operations you need, such as
|
18
|
+
restarting the cluster, upgrading postgres versions, and restoring from backups with point in time recovery (PITR).
|
19
|
+
|
20
|
+
This utility complements the admin UI with a few helpful shortcuts.
|
21
|
+
|
22
|
+
Note that the --env flag should not be used with these commands, as the DB namespaces follow different
|
23
|
+
conventions than the monorepo env.
|
24
|
+
|
25
|
+
This utility assumes that the cluster name and the namespace are always the same.
|
26
|
+
|
27
|
+
COMMANDS
|
28
|
+
list Lists the available clusters
|
29
|
+
backups Lists all available backups
|
30
|
+
password ui Shows the password to the admin UI
|
31
|
+
password <namespace> Shows the superuser, replication, and authenticator password of the remote database
|
32
|
+
patroni <namespace> Obtain a shell to the primary pod's patroni container, where you can run 'patronictl'
|
33
|
+
psql <namespace> Runs 'psql' in the primary pod's postgres-utils container
|
34
|
+
tunnel <namespace> [-p <port>] Sets up a tunnel to the remote database so you can access the DB from your local machine.
|
35
|
+
By default, the port is taken from the namespace to make it easier to create connection profiles locally:
|
36
|
+
db-staging: 7432, db-production: 8432, otherwise: 9432
|
37
|
+
|
38
|
+
EXAMPLES
|
39
|
+
${keyExamples}
|
40
|
+
`;
|
41
|
+
const DEFAULT_PORTS = {
|
42
|
+
"db-staging": "7432",
|
43
|
+
"db-production": "8432",
|
44
|
+
};
|
45
|
+
const handlers = {
|
46
|
+
list: () => {
|
47
|
+
const res = getDbList();
|
48
|
+
console.log(res);
|
49
|
+
},
|
50
|
+
backups: () => {
|
51
|
+
const res = getDbBackups();
|
52
|
+
console.log(res);
|
53
|
+
},
|
54
|
+
password: (opts) => {
|
55
|
+
const namespace = opts.required("namespace");
|
56
|
+
if (namespace === "ui") {
|
57
|
+
const res = getDbAdminPassword();
|
58
|
+
if (!res) {
|
59
|
+
console.error("Failed to get the secret");
|
60
|
+
process.exit(1);
|
61
|
+
}
|
62
|
+
else {
|
63
|
+
console.log(`User: ${res.user}`);
|
64
|
+
console.log(`Password: ${res.password}`);
|
65
|
+
}
|
66
|
+
return;
|
67
|
+
}
|
68
|
+
const res = getDbPasswords(namespace);
|
69
|
+
if (!res) {
|
70
|
+
console.error("Failed to get the secret");
|
71
|
+
process.exit(1);
|
72
|
+
}
|
73
|
+
else {
|
74
|
+
console.log("\nSuperuser");
|
75
|
+
console.log(` ${res.superUser}`);
|
76
|
+
console.log(` ${res.superPassword}`);
|
77
|
+
console.log("\nAuthenticator");
|
78
|
+
console.log(` ${res.authenticatorUser}`);
|
79
|
+
console.log(` ${res.authenticatorPassword}`);
|
80
|
+
console.log("\nReplication");
|
81
|
+
console.log(` ${res.replicationUser}`);
|
82
|
+
console.log(` ${res.replicationPassword}`);
|
83
|
+
console.log();
|
84
|
+
}
|
85
|
+
},
|
86
|
+
tunnel: (opts) => {
|
87
|
+
// prettier-ignore
|
88
|
+
const defaultPort = DEFAULT_PORTS[opts.required("namespace")] || "9432";
|
89
|
+
const port = opts.optional("port") || defaultPort;
|
90
|
+
establishTunnel(opts.required("namespace"), port);
|
91
|
+
},
|
92
|
+
patroni: (opts) => {
|
93
|
+
connectToPatroni(opts.required("namespace"));
|
94
|
+
},
|
95
|
+
psql: (opts) => {
|
96
|
+
connectToPsql(opts.required("namespace"));
|
97
|
+
},
|
98
|
+
};
|
99
|
+
function run(cmdObj) {
|
100
|
+
if (cmdObj.help || cmdObj.args.length < 1)
|
101
|
+
printUsageAndExit(usage);
|
102
|
+
const parsed = cmdObj.parseOptions({ params: ["-p"] });
|
103
|
+
const [command, namespace] = parsed.args;
|
104
|
+
const port = parsed.options["-p"];
|
105
|
+
// @ts-expect-error left as an exercise for the reader
|
106
|
+
const handler = handlers[command];
|
107
|
+
if (!handler) {
|
108
|
+
console.error(`Unknown command: ${command}`);
|
109
|
+
printUsageAndExit(usage);
|
110
|
+
}
|
111
|
+
const params = new StrongParams(usage, {
|
112
|
+
namespace,
|
113
|
+
port,
|
114
|
+
});
|
115
|
+
handler(params);
|
116
|
+
}
|
117
|
+
export default {
|
118
|
+
db: { oneLiner, keyExamples, run },
|
119
|
+
};
|
@@ -0,0 +1,11 @@
|
|
1
|
+
import { CLICommandParser } from "./common";
|
2
|
+
declare function run(cmdObj: CLICommandParser): void;
|
3
|
+
declare const _default: {
|
4
|
+
dml: {
|
5
|
+
oneLiner: string;
|
6
|
+
keyExamples: string;
|
7
|
+
run: typeof run;
|
8
|
+
};
|
9
|
+
};
|
10
|
+
export default _default;
|
11
|
+
//# sourceMappingURL=dml.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"dml.d.ts","sourceRoot":"","sources":["../../src/cli/dml.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAqB,MAAM,UAAU,CAAC;AAoG/D,iBAAS,GAAG,CAAC,MAAM,EAAE,gBAAgB,QAoBpC;;;;;;;;AAED,wBAEE"}
|
package/dist/cli/dml.js
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
import fs from "fs";
|
2
|
+
import { CLICommandParser, printUsageAndExit } from "./common";
|
3
|
+
const oneLiner = "Utilities to manage and run DML scripts in the db project";
|
4
|
+
const keyExamples = `
|
5
|
+
$ devops dml create --name my-dml-name
|
6
|
+
$ devops dml run 20250113153318_my_dml_name
|
7
|
+
`;
|
8
|
+
const usage = `
|
9
|
+
${oneLiner}
|
10
|
+
|
11
|
+
CREATE DML SCRIPTS
|
12
|
+
devops dml create --name <dml-semantic-name>
|
13
|
+
|
14
|
+
This command creates a new folder under /dml using the current timestamp and a
|
15
|
+
snake-case version of the name. Inside the folder, a file called migrate.ts is created.
|
16
|
+
You should write your DML script in this file.
|
17
|
+
|
18
|
+
You can add additional artifacts to the folder, such as a README.md file, sql files, json
|
19
|
+
files, csv files, etc. You can also add optional scripts, such as rollback.ts.
|
20
|
+
|
21
|
+
RUN DML SCRIPTS
|
22
|
+
devops dml run <dml-folder-name> [script-file-name] [-- arg1 arg2 ...]
|
23
|
+
|
24
|
+
The dml-folder-name must be the full name, including the timestamp. This follows prisma
|
25
|
+
conventions.
|
26
|
+
If the optional script-file-name is omitted, 'migrate' is used by default. The name should
|
27
|
+
not include the '.ts' suffix.
|
28
|
+
Optionally, args can be passed to the script as command line arguments after double
|
29
|
+
dash (--).
|
30
|
+
The runner first changes the working directory to 'dml/', then executes the script using
|
31
|
+
'bunx tsx'.
|
32
|
+
|
33
|
+
Note: DML scripts are typically run inside the debug container of the image.
|
34
|
+
|
35
|
+
EXAMPLES
|
36
|
+
${keyExamples.trim()}
|
37
|
+
$ devops dml run 20250113153318_my_dml_name rollback
|
38
|
+
$ devops dml run 20250113153318_my_dml_name -- staging
|
39
|
+
`;
|
40
|
+
const dmlFileTemplate = `
|
41
|
+
/**
|
42
|
+
* Header code that retrieves the context of the DML script.
|
43
|
+
* Feel free to modify this code to suit your needs.
|
44
|
+
*
|
45
|
+
* fullDmlFilePath - path to the current file
|
46
|
+
* fullDmlDirPath - path to the current directory
|
47
|
+
* dmlFile - name of the current DML script file
|
48
|
+
* dmlDir - name of the directory containing the DML scripts
|
49
|
+
* args - command line arguments passed to the script
|
50
|
+
*
|
51
|
+
* Notes:
|
52
|
+
* - the script runs with the cwd set to the dml/ directory
|
53
|
+
* - remove unused variables from this template, otherwise the linter will complain
|
54
|
+
*/
|
55
|
+
|
56
|
+
import { prisma } from 'db';
|
57
|
+
import { basename, dirname, sep } from 'path';
|
58
|
+
import { fileURLToPath } from 'url';
|
59
|
+
|
60
|
+
const fullDmlFilePath = fileURLToPath(import.meta.url);
|
61
|
+
const fullDmlDirPath = dirname(fullDmlFilePath);
|
62
|
+
const dmlFile = basename(fullDmlFilePath);
|
63
|
+
const dmlDir = fullDmlDirPath.split(sep).pop();
|
64
|
+
|
65
|
+
const args = process.argv.slice(2);
|
66
|
+
`.trim();
|
67
|
+
function createDml(name) {
|
68
|
+
const timestamp = new Date()
|
69
|
+
.toISOString()
|
70
|
+
.replace(/[^0-9]/g, "")
|
71
|
+
.slice(0, 14);
|
72
|
+
const nameSnake = name.toLowerCase().replace(/[^a-z0-9]/g, "_");
|
73
|
+
const folderName = `${timestamp}_${nameSnake}`;
|
74
|
+
fs.mkdirSync(`dml/${folderName}`);
|
75
|
+
fs.writeFileSync(`dml/${folderName}/migrate.ts`, dmlFileTemplate);
|
76
|
+
console.log(`\nCreated DML folder: dml/${folderName}\n`);
|
77
|
+
}
|
78
|
+
function runDml(cmdObj, folderName, scriptFileName, args) {
|
79
|
+
scriptFileName ??= "migrate";
|
80
|
+
args ??= [];
|
81
|
+
const script = scriptFileName.endsWith(".ts")
|
82
|
+
? scriptFileName
|
83
|
+
: `${scriptFileName}.ts`;
|
84
|
+
cmdObj
|
85
|
+
.executorFromEnv(
|
86
|
+
// prettier-ignore
|
87
|
+
`devops exec --in dml bun ${folderName}/${script} ${args.join(" ")}`)
|
88
|
+
.exec();
|
89
|
+
}
|
90
|
+
function run(cmdObj) {
|
91
|
+
if (cmdObj.help || cmdObj.args.length < 1)
|
92
|
+
printUsageAndExit(usage);
|
93
|
+
const parsed = cmdObj.parseOptions({
|
94
|
+
passthroughArgs: true,
|
95
|
+
params: ["--name"],
|
96
|
+
});
|
97
|
+
switch (parsed.args[0]) {
|
98
|
+
case "create": {
|
99
|
+
const name = parsed.options["--name"];
|
100
|
+
if (!name)
|
101
|
+
printUsageAndExit(usage);
|
102
|
+
return createDml(name);
|
103
|
+
}
|
104
|
+
case "run": {
|
105
|
+
const [_, folderName, scriptFileName] = parsed.args;
|
106
|
+
if (!folderName)
|
107
|
+
printUsageAndExit(usage);
|
108
|
+
return runDml(cmdObj, folderName, scriptFileName, parsed.passthrough);
|
109
|
+
}
|
110
|
+
default:
|
111
|
+
printUsageAndExit(usage);
|
112
|
+
}
|
113
|
+
}
|
114
|
+
export default {
|
115
|
+
dml: { oneLiner, keyExamples, run },
|
116
|
+
};
|
@@ -0,0 +1,11 @@
|
|
1
|
+
import { CLICommandParser } from "./common";
|
2
|
+
declare function run(cmdObj: CLICommandParser): void;
|
3
|
+
declare const _default: {
|
4
|
+
env: {
|
5
|
+
oneLiner: string;
|
6
|
+
keyExamples: string;
|
7
|
+
run: typeof run;
|
8
|
+
};
|
9
|
+
};
|
10
|
+
export default _default;
|
11
|
+
//# sourceMappingURL=env.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/cli/env.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,gBAAgB,EAGjB,MAAM,UAAU,CAAC;AAwBlB,iBAAS,GAAG,CAAC,MAAM,EAAE,gBAAgB,QA+CpC;;;;;;;;AAED,wBAEE"}
|