@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
package/dist/devops.js
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
#!/usr/bin/env bun
|
2
|
+
// This file behaves as a façade for various devops scripts
|
3
|
+
import { CLICommandParser, printUsageAndExit } from "./cli/common";
|
4
|
+
import affected from "./cli/affected";
|
5
|
+
import constant from "./cli/constant";
|
6
|
+
import console from "./cli/console";
|
7
|
+
import db from "./cli/db";
|
8
|
+
import dml from "./cli/dml";
|
9
|
+
import registry from "./cli/registry";
|
10
|
+
import env from "./cli/env";
|
11
|
+
import exec from "./cli/exec";
|
12
|
+
import prepBuild from "./cli/prep-build";
|
13
|
+
import prisma from "./cli/prisma";
|
14
|
+
import run from "./cli/run";
|
15
|
+
import runMany from "./cli/run-many";
|
16
|
+
import test from "./cli/test";
|
17
|
+
import init from "./cli/init";
|
18
|
+
import redis from "./cli/redis";
|
19
|
+
import internalCurl from "./cli/internal-curl";
|
20
|
+
import jwt from "./cli/jwt";
|
21
|
+
import namespace from "./cli/namespace";
|
22
|
+
import image from "./cli/image";
|
23
|
+
import template from "./cli/template";
|
24
|
+
import job from "./cli/job";
|
25
|
+
const [_node, _scriptPath, ...commandArgs] = process.argv;
|
26
|
+
const allImports = [
|
27
|
+
// day-to-day
|
28
|
+
init,
|
29
|
+
run,
|
30
|
+
runMany,
|
31
|
+
exec,
|
32
|
+
env,
|
33
|
+
prisma,
|
34
|
+
dml,
|
35
|
+
db,
|
36
|
+
redis,
|
37
|
+
console,
|
38
|
+
test,
|
39
|
+
//= Infra
|
40
|
+
namespace,
|
41
|
+
image,
|
42
|
+
template,
|
43
|
+
job,
|
44
|
+
//= Deployment
|
45
|
+
prepBuild,
|
46
|
+
affected,
|
47
|
+
constant,
|
48
|
+
registry,
|
49
|
+
internalCurl,
|
50
|
+
jwt
|
51
|
+
];
|
52
|
+
const commands = {};
|
53
|
+
allImports.forEach((imported) => {
|
54
|
+
Object.entries(imported).forEach(([key, object]) => {
|
55
|
+
const { oneLiner, keyExamples, run } = object;
|
56
|
+
commands[key] = { oneLiner, keyExamples, run, key };
|
57
|
+
});
|
58
|
+
});
|
59
|
+
const keyLength = Math.max(...Object.keys(commands).map((x) => x.length)) + 10;
|
60
|
+
const newLine = "\n ";
|
61
|
+
const GENERAL_USAGE = `
|
62
|
+
Devops utilities for the monorepo.
|
63
|
+
|
64
|
+
USAGE
|
65
|
+
devops <command> <args> <env-options>
|
66
|
+
|
67
|
+
CHOOSING ENV with <env-options>
|
68
|
+
By default, all commands run under the env specified in MONOREPO_ENV env variable, or development if it does not exist.
|
69
|
+
The test command is an exception: its environment is forced to test.
|
70
|
+
When running in development, the env files config/.env.development and config/.env.global are injected, where the
|
71
|
+
former overrides the latter.
|
72
|
+
|
73
|
+
To override the environment in which a command is executed in, use --env <some-env>. This overrides the MONOREPO_ENV variable.
|
74
|
+
You can use it anywhere in the command, i.e. the following are equivalent:
|
75
|
+
$ devops --env staging run project:task
|
76
|
+
$ devops run project:task --env staging
|
77
|
+
|
78
|
+
Supported environments: development, staging, test, and production.
|
79
|
+
|
80
|
+
Certain commands like run, exec, and prisma ensure that the env variables exist and correspond to env.yaml files in the repo.
|
81
|
+
To skip this check, use --skip-env-check.
|
82
|
+
|
83
|
+
|
84
|
+
COMMANDS
|
85
|
+
${Object.values(commands)
|
86
|
+
.map((cmd) => [cmd.key, " ".repeat(keyLength - cmd.key.length), cmd.oneLiner].join(""))
|
87
|
+
.join(newLine)}
|
88
|
+
`;
|
89
|
+
// EXAMPLES
|
90
|
+
// ${Object.values(commands)
|
91
|
+
// .map((cmd) =>
|
92
|
+
// cmd.keyExamples
|
93
|
+
// .split("\n")
|
94
|
+
// .map((x) => x.trim())
|
95
|
+
// .filter(Boolean)
|
96
|
+
// .join(newLine)
|
97
|
+
// )
|
98
|
+
// .join(newLine)}
|
99
|
+
const commandObj = new CLICommandParser(commandArgs);
|
100
|
+
const chosenCommand = commands[commandObj.command];
|
101
|
+
if (!chosenCommand)
|
102
|
+
printUsageAndExit(GENERAL_USAGE);
|
103
|
+
chosenCommand.run(commandObj);
|
package/dist/index.d.ts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,0CAA0C,CAAC;AACzD,cAAc,sBAAsB,CAAC"}
|
package/dist/index.js
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
type AffectedOpts = {
|
2
|
+
baseSha?: string;
|
3
|
+
headSha?: string;
|
4
|
+
fromLiveVersion?: boolean;
|
5
|
+
monorepoEnv?: string;
|
6
|
+
};
|
7
|
+
export declare function isImageAffected(image: string, opts?: AffectedOpts): boolean;
|
8
|
+
export declare function findImagesAffected(opts?: AffectedOpts): string[];
|
9
|
+
export declare function isWorkspaceAffected(workspaceName: string, opts?: {
|
10
|
+
baseSha?: string;
|
11
|
+
headSha?: string;
|
12
|
+
}): boolean;
|
13
|
+
export declare function findImagesWithAffectedWorkspace(workspaceName: string, opts?: AffectedOpts): string[];
|
14
|
+
export {};
|
15
|
+
//# sourceMappingURL=affected-entities.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"affected-entities.d.ts","sourceRoot":"","sources":["../../src/libs/affected-entities.ts"],"names":[],"mappings":"AAMA,KAAK,YAAY,GAAG;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,GAAE,YAAiB,WAoBrE;AAED,wBAAgB,kBAAkB,CAAC,IAAI,GAAE,YAAiB,YAIzD;AAED,wBAAgB,mBAAmB,CACjC,aAAa,EAAE,MAAM,EACrB,IAAI,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,WAIlD;AAED,wBAAgB,+BAA+B,CAC7C,aAAa,EAAE,MAAM,EACrB,IAAI,GAAE,YAAiB,YAmBxB"}
|
@@ -0,0 +1,52 @@
|
|
1
|
+
import { getImageNames } from "./config";
|
2
|
+
import { getWorkspace } from "./discovery";
|
3
|
+
import { getImageDescendentData, getWorkspaceImages } from "./discovery/images";
|
4
|
+
import { commitExists, isAffected } from "./git-helpers";
|
5
|
+
import { getImageVersion } from "./k8s-image-config";
|
6
|
+
export function isImageAffected(image, opts = {}) {
|
7
|
+
const headSha = opts.headSha ?? "HEAD";
|
8
|
+
let baseSha;
|
9
|
+
if (opts.fromLiveVersion) {
|
10
|
+
if (!opts.monorepoEnv) {
|
11
|
+
throw new Error("monorepoEnv is required when fromLiveVersion is true");
|
12
|
+
}
|
13
|
+
baseSha = getImageVersion(opts.monorepoEnv, image);
|
14
|
+
if (!baseSha)
|
15
|
+
return true;
|
16
|
+
}
|
17
|
+
baseSha ??= opts.baseSha ?? "HEAD^";
|
18
|
+
const descendentData = getImageDescendentData(image);
|
19
|
+
if (!commitExists(baseSha) || !commitExists(headSha))
|
20
|
+
return true;
|
21
|
+
for (const { rootPath } of descendentData) {
|
22
|
+
if (isAffected(rootPath, { baseSha, headSha, skipCheck: true })) {
|
23
|
+
return true;
|
24
|
+
}
|
25
|
+
}
|
26
|
+
return false;
|
27
|
+
}
|
28
|
+
export function findImagesAffected(opts = {}) {
|
29
|
+
return getImageNames().filter((imageName) => isImageAffected(imageName, opts));
|
30
|
+
}
|
31
|
+
export function isWorkspaceAffected(workspaceName, opts = {}) {
|
32
|
+
const data = getWorkspace(workspaceName);
|
33
|
+
return isAffected(data.rootPath, opts);
|
34
|
+
}
|
35
|
+
export function findImagesWithAffectedWorkspace(workspaceName, opts = {}) {
|
36
|
+
const res = [];
|
37
|
+
const headSha = opts.headSha ?? "HEAD";
|
38
|
+
const defaultBaseSha = opts.baseSha ?? "HEAD^";
|
39
|
+
const rootPath = getWorkspace(workspaceName).rootPath;
|
40
|
+
if (opts.fromLiveVersion && !opts.monorepoEnv) {
|
41
|
+
throw new Error("monorepoEnv is required when fromLiveVersion is true");
|
42
|
+
}
|
43
|
+
for (const imageName of getWorkspaceImages(workspaceName)) {
|
44
|
+
const baseSha = opts.fromLiveVersion
|
45
|
+
? getImageVersion(opts.monorepoEnv, imageName)
|
46
|
+
: defaultBaseSha;
|
47
|
+
if (isAffected(rootPath, { baseSha, headSha })) {
|
48
|
+
res.push(imageName);
|
49
|
+
}
|
50
|
+
}
|
51
|
+
return res;
|
52
|
+
}
|
@@ -0,0 +1,6 @@
|
|
1
|
+
import { type ConstFileSchema, type SingleImageSchema, type SingleTemplateSchema } from "../types";
|
2
|
+
export declare const getConst: <T extends keyof ConstFileSchema>(key: T, opts?: {
|
3
|
+
ignoreIfInvalid?: boolean;
|
4
|
+
}) => ConstFileSchema[T] | undefined;
|
5
|
+
export declare const getImageData: (imageName: string) => SingleImageSchema, getImageNames: () => string[], getTemplateData: (templateName: string) => SingleTemplateSchema;
|
6
|
+
//# sourceMappingURL=config.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/libs/config.ts"],"names":[],"mappings":"AAIA,OAAO,EAAoC,KAAK,eAAe,EAAwB,KAAK,iBAAiB,EAAE,KAAK,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAM3J,eAAO,MAAQ,QAAQ,GA2BH,CAAC,SAAS,MAAM,eAAe,OAAO,CAAC,SAAQ;IAAE,eAAe,CAAC,EAAE,OAAO,CAAA;CAAE,KAAQ,eAAe,CAAC,CAAC,CAAC,GAAG,SAAS,AA3BxF,CAAC;AAC/C,eAAO,MAAQ,YAAY,cAkEQ,MAAM,KAAG,iBAAiB,EAlEhC,aAAa,kBAAE,eAAe,iBAwFlB,MAAM,KAAG,oBAAoB,AAxFa,CAAC"}
|
@@ -0,0 +1,98 @@
|
|
1
|
+
import { readFileSync } from "fs";
|
2
|
+
import yaml from "yaml";
|
3
|
+
import path from "path";
|
4
|
+
import { getWorkspace } from "./discovery";
|
5
|
+
import { constFileSchema, imageFileSchema } from "../types";
|
6
|
+
const constantsFilePath = path.join(process.cwd(), ".devops/config/constants.yaml");
|
7
|
+
const imagesFilePath = path.join(process.cwd(), ".devops/config/images.yaml");
|
8
|
+
// We want these to be lazy loaded so that calling devops in a context that does not need the config files won't fail
|
9
|
+
export const { getConst } = processConstFile();
|
10
|
+
export const { getImageData, getImageNames, getTemplateData } = processImagesFile();
|
11
|
+
// Process config/constants.yaml
|
12
|
+
function processConstFile() {
|
13
|
+
let constants;
|
14
|
+
function constFileData() {
|
15
|
+
if (constants)
|
16
|
+
return constants;
|
17
|
+
try {
|
18
|
+
const constantsYaml = readFileSync(constantsFilePath, "utf8");
|
19
|
+
constants = yaml.parse(constantsYaml);
|
20
|
+
}
|
21
|
+
catch (e) {
|
22
|
+
// This is only a warning - the file may not exist, which is fine if getConst is called with ignoreIfInvalid
|
23
|
+
console.warn("Warning: cannot read .devops/config/constants.yaml");
|
24
|
+
return { valid: false };
|
25
|
+
}
|
26
|
+
const parseRes = constFileSchema.safeParse(constants);
|
27
|
+
if (parseRes.error) {
|
28
|
+
// This is an error - if the file exists, it must be valid
|
29
|
+
console.error(`Error parsing config/constants.yaml: ${parseRes.error.toString()}`);
|
30
|
+
process.exit(1);
|
31
|
+
}
|
32
|
+
constants = { valid: true, data: parseRes.data };
|
33
|
+
return constants;
|
34
|
+
}
|
35
|
+
function getConst(key, opts = {}) {
|
36
|
+
const { valid, data } = constFileData();
|
37
|
+
if (!valid && !opts.ignoreIfInvalid) {
|
38
|
+
console.error(".devops/config/constants.yaml is invalid");
|
39
|
+
process.exit(1);
|
40
|
+
}
|
41
|
+
const value = data?.[key];
|
42
|
+
if (!value && !opts.ignoreIfInvalid) {
|
43
|
+
console.error(`Missing constant in .devops/config/constants.yaml: ${key}`);
|
44
|
+
process.exit(1);
|
45
|
+
}
|
46
|
+
return value;
|
47
|
+
}
|
48
|
+
return { getConst };
|
49
|
+
}
|
50
|
+
// Process config/images.yaml
|
51
|
+
function processImagesFile() {
|
52
|
+
let images;
|
53
|
+
function imagesFileData() {
|
54
|
+
if (images)
|
55
|
+
return images;
|
56
|
+
try {
|
57
|
+
const imagesYaml = readFileSync(imagesFilePath, "utf8");
|
58
|
+
images = yaml.parse(imagesYaml);
|
59
|
+
}
|
60
|
+
catch (e) {
|
61
|
+
console.error("Error reading .devops/config/images.yaml");
|
62
|
+
process.exit(1);
|
63
|
+
}
|
64
|
+
const parseRes = imageFileSchema.safeParse(images);
|
65
|
+
if (parseRes.error) {
|
66
|
+
console.error(`Error parsing config/images.yaml: ${parseRes.error.toString()}`);
|
67
|
+
process.exit(1);
|
68
|
+
}
|
69
|
+
return images;
|
70
|
+
}
|
71
|
+
function getImageData(imageName) {
|
72
|
+
const imageData = imagesFileData()['images'][imageName];
|
73
|
+
if (!imageData) {
|
74
|
+
console.error(`Image ${imageName} not found in .devops/config/images.yaml`);
|
75
|
+
process.exit(1);
|
76
|
+
}
|
77
|
+
imageData.applications.forEach((project) => {
|
78
|
+
const data = getWorkspace(project);
|
79
|
+
if (!data) {
|
80
|
+
console.error(`Project ${project} not found for image ${imageName} in .devops/config/images.yaml`);
|
81
|
+
process.exit(1);
|
82
|
+
}
|
83
|
+
});
|
84
|
+
return imageData;
|
85
|
+
}
|
86
|
+
function getTemplateData(templateName) {
|
87
|
+
const templateData = imagesFileData()['templates'][templateName];
|
88
|
+
if (!templateData) {
|
89
|
+
console.error(`Template ${templateName} not found in .devops/config/images.yaml`);
|
90
|
+
process.exit(1);
|
91
|
+
}
|
92
|
+
return templateData;
|
93
|
+
}
|
94
|
+
function getImageNames() {
|
95
|
+
return Object.keys(imagesFileData()["images"]);
|
96
|
+
}
|
97
|
+
return { getImageData, getImageNames, getTemplateData };
|
98
|
+
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
import type { ProjectData } from "../types";
|
2
|
+
export declare class WorkspaceDependencies {
|
3
|
+
getAllProjects: () => Record<string, ProjectData>;
|
4
|
+
dependencies: Record<string, DependencyNode>;
|
5
|
+
loaded: boolean;
|
6
|
+
projects: Record<string, ProjectData>;
|
7
|
+
constructor(getAllProjects: () => Record<string, ProjectData>);
|
8
|
+
_getOrCreate(name: string): DependencyNode;
|
9
|
+
_buildTree(): void;
|
10
|
+
getDependents(workspaceName: string): string[];
|
11
|
+
}
|
12
|
+
declare class DependencyNode {
|
13
|
+
name: string;
|
14
|
+
dependsOn: Set<string>;
|
15
|
+
constructor(name: string);
|
16
|
+
flattenDependents(allDependencies: Record<string, DependencyNode>, visited?: Set<string>): string[];
|
17
|
+
}
|
18
|
+
export {};
|
19
|
+
//# sourceMappingURL=dependencies.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"dependencies.d.ts","sourceRoot":"","sources":["../../src/libs/dependencies.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE5C,qBAAa,qBAAqB;IAKb,cAAc,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC;IAJpE,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAM;IAClD,MAAM,UAAS;IACf,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAM;gBAExB,cAAc,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC;IAEpE,YAAY,CAAC,IAAI,EAAE,MAAM;IASzB,UAAU;IAcV,aAAa,CAAC,aAAa,EAAE,MAAM;CAWpC;AAED,cAAM,cAAc;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;gBAEX,IAAI,EAAE,MAAM;IAKxB,iBAAiB,CACf,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,EAC/C,OAAO,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC;CAexB"}
|
@@ -0,0 +1,62 @@
|
|
1
|
+
import chalk from "chalk";
|
2
|
+
export class WorkspaceDependencies {
|
3
|
+
getAllProjects;
|
4
|
+
dependencies = {};
|
5
|
+
loaded = false;
|
6
|
+
projects = {};
|
7
|
+
constructor(getAllProjects) {
|
8
|
+
this.getAllProjects = getAllProjects;
|
9
|
+
}
|
10
|
+
_getOrCreate(name) {
|
11
|
+
let node = this.dependencies[name];
|
12
|
+
if (!node) {
|
13
|
+
node = new DependencyNode(name);
|
14
|
+
this.dependencies[name] = node;
|
15
|
+
}
|
16
|
+
return node;
|
17
|
+
}
|
18
|
+
_buildTree() {
|
19
|
+
this.projects = this.getAllProjects();
|
20
|
+
this.loaded = true;
|
21
|
+
for (const workspace of Object.keys(this.projects)) {
|
22
|
+
const node = this._getOrCreate(workspace);
|
23
|
+
const { data } = this.projects[workspace];
|
24
|
+
for (const dep of data.dependencyNames ?? []) {
|
25
|
+
if (this.projects[dep]) {
|
26
|
+
node.dependsOn.add(dep);
|
27
|
+
}
|
28
|
+
}
|
29
|
+
}
|
30
|
+
}
|
31
|
+
getDependents(workspaceName) {
|
32
|
+
if (!this.loaded) {
|
33
|
+
this._buildTree();
|
34
|
+
}
|
35
|
+
const node = this.dependencies[workspaceName];
|
36
|
+
if (!node) {
|
37
|
+
console.error(chalk.red(`\nWorkspace ${workspaceName} not found\n`));
|
38
|
+
process.exit(1);
|
39
|
+
}
|
40
|
+
return node.flattenDependents(this.dependencies);
|
41
|
+
}
|
42
|
+
}
|
43
|
+
class DependencyNode {
|
44
|
+
name;
|
45
|
+
dependsOn;
|
46
|
+
constructor(name) {
|
47
|
+
this.name = name;
|
48
|
+
this.dependsOn = new Set();
|
49
|
+
}
|
50
|
+
flattenDependents(allDependencies, visited) {
|
51
|
+
visited ??= new Set();
|
52
|
+
visited.add(this.name);
|
53
|
+
const notVisitedDependents = [];
|
54
|
+
for (const dep of this.dependsOn) {
|
55
|
+
if (!visited.has(dep)) {
|
56
|
+
const node = allDependencies[dep];
|
57
|
+
notVisitedDependents.push(...node.flattenDependents(allDependencies, visited));
|
58
|
+
}
|
59
|
+
}
|
60
|
+
return [this.name, ...notVisitedDependents];
|
61
|
+
}
|
62
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"dependencies.spec.d.ts","sourceRoot":"","sources":["../../src/libs/dependencies.spec.ts"],"names":[],"mappings":""}
|
@@ -0,0 +1,21 @@
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
2
|
+
import { WorkspaceDependencies } from './dependencies';
|
3
|
+
describe('createDependencyResolver', () => {
|
4
|
+
const projects = {
|
5
|
+
'@local/a': { rootPath: 'applications/a', data: { name: '@local/a', dependencies: { '@local/b': 'workspace:*', '@local/d': 'workspace:*', external1: "^1.0.0" } } },
|
6
|
+
'@local/b': { rootPath: 'applications/b', data: { name: '@local/b', dependencies: { '@local/c': 'workspace:*', external2: "^1.0.0" } } },
|
7
|
+
'@local/c': { rootPath: 'applications/c', data: { name: '@local/c', dependencies: { external3: "^1.0.0" } } },
|
8
|
+
'@local/d': { rootPath: 'applications/d', data: { name: '@local/d' } },
|
9
|
+
'@local/e': { rootPath: 'applications/e', data: { name: '@local/e', dependencies: { '@local/f': 'workspace:*' } } },
|
10
|
+
'@local/f': { rootPath: 'applications/f', data: { name: '@local/f', dependencies: { '@local/e': 'workspace:*' } } },
|
11
|
+
};
|
12
|
+
it('should return dependents of a given project', () => {
|
13
|
+
const resolver = new WorkspaceDependencies(() => projects);
|
14
|
+
expect(resolver.getDependents('@local/a')).toEqual(['@local/a', '@local/b', '@local/c', '@local/d']);
|
15
|
+
expect(resolver.getDependents('@local/b')).toEqual(['@local/b', '@local/c']);
|
16
|
+
expect(resolver.getDependents('@local/c')).toEqual(['@local/c']);
|
17
|
+
expect(resolver.getDependents('@local/d')).toEqual(['@local/d']);
|
18
|
+
expect(resolver.getDependents('@local/e')).toEqual(['@local/e', '@local/f']);
|
19
|
+
expect(resolver.getDependents('@local/f')).toEqual(['@local/f', '@local/e']);
|
20
|
+
});
|
21
|
+
});
|
@@ -0,0 +1,6 @@
|
|
1
|
+
export declare function prune(
|
2
|
+
/** To keep the image-related constants simple, this accepts the full URL including the prefix registry.digitalocean.com */
|
3
|
+
registryFullName: string,
|
4
|
+
/** The name of the repository inside the registry */
|
5
|
+
repoName: string): void;
|
6
|
+
//# sourceMappingURL=container-reg.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"container-reg.d.ts","sourceRoot":"","sources":["../../../src/libs/digital-ocean/container-reg.ts"],"names":[],"mappings":"AA0DA,wBAAgB,KAAK;AACnB,2HAA2H;AAC3H,gBAAgB,EAAE,MAAM;AACxB,qDAAqD;AACrD,QAAQ,EAAE,MAAM,QAkBjB"}
|
@@ -0,0 +1,69 @@
|
|
1
|
+
import { CommandExecutor } from "../../cli/common";
|
2
|
+
import { z } from "zod";
|
3
|
+
import { getConst } from "../config";
|
4
|
+
const repoTagMetadataSchema = z.object({
|
5
|
+
// What we rely on
|
6
|
+
tag: z.string().optional(),
|
7
|
+
updated_at: z.string(),
|
8
|
+
manifest_digest: z.string(),
|
9
|
+
// Other fields that existed in the output
|
10
|
+
// registry_name: z.string().optional(),
|
11
|
+
// repository: z.string().optional(),
|
12
|
+
// compressed_size_bytes: z.number().optional(),
|
13
|
+
// size_bytes: z.number().optional(),
|
14
|
+
});
|
15
|
+
const repoTagMetadataSchemaOutput = z.array(repoTagMetadataSchema);
|
16
|
+
/** The metadata is returned in descending order (most recent first) */
|
17
|
+
function getRepoTagMetadata(repoName) {
|
18
|
+
// Get the metadata for the tags in the repository
|
19
|
+
const cmd = `doctl registry repository list-tags ${repoName} -o json`;
|
20
|
+
const res = new CommandExecutor(cmd, { quiet: true }).exec();
|
21
|
+
if (!res)
|
22
|
+
return [];
|
23
|
+
try {
|
24
|
+
const parsed = JSON.parse(res);
|
25
|
+
const parseRes = repoTagMetadataSchemaOutput.safeParse(parsed);
|
26
|
+
if (parseRes.error) {
|
27
|
+
console.error(`Error schema-parsing output from "${cmd}": ${parseRes.error.toString()}`);
|
28
|
+
console.error(">>> Command output");
|
29
|
+
console.error(res);
|
30
|
+
process.exit(1);
|
31
|
+
}
|
32
|
+
return parseRes.data
|
33
|
+
.filter((data) => data.tag)
|
34
|
+
.sort((a, b) => new Date(b.updated_at).getTime() - new Date(a.updated_at).getTime());
|
35
|
+
}
|
36
|
+
catch (e) {
|
37
|
+
console.error(`Error JSON-parsing output from "${cmd}": ${res}`);
|
38
|
+
process.exit(1);
|
39
|
+
}
|
40
|
+
}
|
41
|
+
function deleteRepoTag(repoName, tag) {
|
42
|
+
const cmd = `doctl registry repository delete-tag ${repoName} ${tag} --force`;
|
43
|
+
new CommandExecutor(cmd).exec();
|
44
|
+
}
|
45
|
+
function stargGarbageCollection(registryName) {
|
46
|
+
const cmd = `doctl registry garbage-collection start --include-untagged-manifests ${registryName} --force`;
|
47
|
+
new CommandExecutor(cmd).exec();
|
48
|
+
}
|
49
|
+
export function prune(
|
50
|
+
/** To keep the image-related constants simple, this accepts the full URL including the prefix registry.digitalocean.com */
|
51
|
+
registryFullName,
|
52
|
+
/** The name of the repository inside the registry */
|
53
|
+
repoName) {
|
54
|
+
const infra = getConst("infra");
|
55
|
+
if (infra !== "digitalocean") {
|
56
|
+
console.warn("Pruning is only supported for the DigitalOcean container registry");
|
57
|
+
return;
|
58
|
+
}
|
59
|
+
const tags = getRepoTagMetadata(repoName);
|
60
|
+
const versionsToKeep = Number(getConst("image-versions-to-keep"));
|
61
|
+
if (!tags.length || tags.length <= versionsToKeep)
|
62
|
+
return;
|
63
|
+
const tagsToDelete = tags.slice(versionsToKeep);
|
64
|
+
tagsToDelete.forEach((tag) => {
|
65
|
+
deleteRepoTag(repoName, tag.tag);
|
66
|
+
});
|
67
|
+
const registryName = registryFullName.split("/").slice(-1)[0];
|
68
|
+
stargGarbageCollection(registryName);
|
69
|
+
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
import type { PackageData } from "../../types";
|
2
|
+
export declare class WorkspaceDependencies {
|
3
|
+
getAllProjects: () => Record<string, PackageData>;
|
4
|
+
dependencies: Record<string, DependencyNode>;
|
5
|
+
loaded: boolean;
|
6
|
+
workspaces: Record<string, PackageData>;
|
7
|
+
constructor(getAllProjects: () => Record<string, PackageData>);
|
8
|
+
_getOrCreate(name: string): DependencyNode;
|
9
|
+
_buildTree(): void;
|
10
|
+
getDependents(workspaceName: string): string[];
|
11
|
+
}
|
12
|
+
declare class DependencyNode {
|
13
|
+
name: string;
|
14
|
+
dependsOn: Set<string>;
|
15
|
+
constructor(name: string);
|
16
|
+
flattenDependents(allDependencies: Record<string, DependencyNode>, visited?: Set<string>): string[];
|
17
|
+
}
|
18
|
+
export {};
|
19
|
+
//# sourceMappingURL=dependencies.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"dependencies.d.ts","sourceRoot":"","sources":["../../../src/libs/discovery/dependencies.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,qBAAa,qBAAqB;IAKb,cAAc,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC;IAJpE,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAM;IAClD,MAAM,UAAS;IACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAM;gBAE1B,cAAc,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC;IAEpE,YAAY,CAAC,IAAI,EAAE,MAAM;IASzB,UAAU;IAcV,aAAa,CAAC,aAAa,EAAE,MAAM;CAWpC;AAED,cAAM,cAAc;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;gBAEX,IAAI,EAAE,MAAM;IAKxB,iBAAiB,CACf,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,EAC/C,OAAO,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC;CAexB"}
|
@@ -0,0 +1,62 @@
|
|
1
|
+
import chalk from "chalk";
|
2
|
+
export class WorkspaceDependencies {
|
3
|
+
getAllProjects;
|
4
|
+
dependencies = {};
|
5
|
+
loaded = false;
|
6
|
+
workspaces = {};
|
7
|
+
constructor(getAllProjects) {
|
8
|
+
this.getAllProjects = getAllProjects;
|
9
|
+
}
|
10
|
+
_getOrCreate(name) {
|
11
|
+
let node = this.dependencies[name];
|
12
|
+
if (!node) {
|
13
|
+
node = new DependencyNode(name);
|
14
|
+
this.dependencies[name] = node;
|
15
|
+
}
|
16
|
+
return node;
|
17
|
+
}
|
18
|
+
_buildTree() {
|
19
|
+
this.workspaces = this.getAllProjects();
|
20
|
+
this.loaded = true;
|
21
|
+
for (const workspace of Object.keys(this.workspaces)) {
|
22
|
+
const node = this._getOrCreate(workspace);
|
23
|
+
const data = this.workspaces[workspace];
|
24
|
+
for (const dep of data.dependencyNames ?? []) {
|
25
|
+
if (this.workspaces[dep]) {
|
26
|
+
node.dependsOn.add(dep);
|
27
|
+
}
|
28
|
+
}
|
29
|
+
}
|
30
|
+
}
|
31
|
+
getDependents(workspaceName) {
|
32
|
+
if (!this.loaded) {
|
33
|
+
this._buildTree();
|
34
|
+
}
|
35
|
+
const node = this.dependencies[workspaceName];
|
36
|
+
if (!node) {
|
37
|
+
console.error(chalk.red(`\nWorkspace ${workspaceName} not found\n`));
|
38
|
+
process.exit(1);
|
39
|
+
}
|
40
|
+
return node.flattenDependents(this.dependencies);
|
41
|
+
}
|
42
|
+
}
|
43
|
+
class DependencyNode {
|
44
|
+
name;
|
45
|
+
dependsOn;
|
46
|
+
constructor(name) {
|
47
|
+
this.name = name;
|
48
|
+
this.dependsOn = new Set();
|
49
|
+
}
|
50
|
+
flattenDependents(allDependencies, visited) {
|
51
|
+
visited ??= new Set();
|
52
|
+
visited.add(this.name);
|
53
|
+
const notVisitedDependents = [];
|
54
|
+
for (const dep of this.dependsOn) {
|
55
|
+
if (!visited.has(dep)) {
|
56
|
+
const node = allDependencies[dep];
|
57
|
+
notVisitedDependents.push(...node.flattenDependents(allDependencies, visited));
|
58
|
+
}
|
59
|
+
}
|
60
|
+
return [this.name, ...notVisitedDependents];
|
61
|
+
}
|
62
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"dependencies.spec.d.ts","sourceRoot":"","sources":["../../../src/libs/discovery/dependencies.spec.ts"],"names":[],"mappings":""}
|
@@ -0,0 +1,21 @@
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
2
|
+
import { WorkspaceDependencies } from './dependencies';
|
3
|
+
describe('createDependencyResolver', () => {
|
4
|
+
const projects = {
|
5
|
+
'@local/a': { language: "node", rootPath: 'applications/a', name: '@local/a', dependencyNames: ['@local/b', '@local/d', 'external1'] },
|
6
|
+
'@local/b': { language: "node", rootPath: 'applications/b', name: '@local/b', dependencyNames: ['@local/c', 'external2'] },
|
7
|
+
'@local/c': { language: "node", rootPath: 'applications/c', name: '@local/c', dependencyNames: ['external3'] },
|
8
|
+
'@local/d': { language: "node", rootPath: 'applications/d', name: '@local/d', dependencyNames: [] },
|
9
|
+
'@local/e': { language: "node", rootPath: 'applications/e', name: '@local/e', dependencyNames: ['@local/f'] },
|
10
|
+
'@local/f': { language: "node", rootPath: 'applications/f', name: '@local/f', dependencyNames: ['@local/e'] }
|
11
|
+
};
|
12
|
+
it('should return dependents of a given project', () => {
|
13
|
+
const resolver = new WorkspaceDependencies(() => projects);
|
14
|
+
expect(resolver.getDependents('@local/a')).toEqual(['@local/a', '@local/b', '@local/c', '@local/d']);
|
15
|
+
expect(resolver.getDependents('@local/b')).toEqual(['@local/b', '@local/c']);
|
16
|
+
expect(resolver.getDependents('@local/c')).toEqual(['@local/c']);
|
17
|
+
expect(resolver.getDependents('@local/d')).toEqual(['@local/d']);
|
18
|
+
expect(resolver.getDependents('@local/e')).toEqual(['@local/e', '@local/f']);
|
19
|
+
expect(resolver.getDependents('@local/f')).toEqual(['@local/f', '@local/e']);
|
20
|
+
});
|
21
|
+
});
|
@@ -0,0 +1,5 @@
|
|
1
|
+
import type { PackageData } from "../../types";
|
2
|
+
/** The dependent workspaces are specified in config/images.yaml */
|
3
|
+
export declare function getImageDescendentData(imageName: string): PackageData[];
|
4
|
+
export declare function getWorkspaceImages(workspaceName: string): string[];
|
5
|
+
//# sourceMappingURL=images.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"images.d.ts","sourceRoot":"","sources":["../../../src/libs/discovery/images.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AA0B/C,mEAAmE;AACnE,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,iBAIvD;AAqBD,wBAAgB,kBAAkB,CAAC,aAAa,EAAE,MAAM,YAGvD"}
|