@vaharoni/devops 1.1.0 → 1.1.2
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/dist/cli/init.d.ts.map +1 -1
- package/dist/cli/init.js +196 -46
- package/dist/libs/init-generator.d.ts +41 -0
- package/dist/libs/init-generator.d.ts.map +1 -0
- package/dist/libs/init-generator.js +123 -0
- package/package.json +3 -1
- package/src/cli/init.ts +221 -48
- package/src/libs/init-generator.ts +165 -0
- package/src/target-templates/README.md +1 -0
- package/src/target-templates/cluster-resource-options/README.md +2 -0
- package/src/target-templates/{.devops → cluster-resource-options}/postgres/production/configurations/07-SGObjectStorage.yaml +1 -1
- package/src/target-templates/{.devops → cluster-resource-options}/postgres/production/configurations/08-SGScript.yaml +1 -1
- package/src/target-templates/{.devops → cluster-resource-options}/postgres/staging/configurations/07-SGObjectStorage.yaml +1 -1
- package/src/target-templates/{.devops → cluster-resource-options}/postgres/staging/configurations/08-SGScript.yaml +1 -1
- package/src/target-templates/infra-variants/README.md +2 -0
- package/src/target-templates/infra-variants/digitalocean/.devops/config/constants.yaml +18 -0
- package/src/target-templates/infra-variants/digitalocean/.github/workflows/k8s-build.yaml +73 -0
- package/src/target-templates/infra-variants/gcloud/.devops/config/constants.yaml +15 -0
- package/src/target-templates/infra-variants/gcloud/.devops/manifests/ingress.yaml.hb +22 -0
- package/src/target-templates/infra-variants/gcloud/.github/workflows/k8s-build.yaml +77 -0
- package/src/target-templates/{.devops → infra-variants/hetzner/.devops}/config/constants.yaml +4 -4
- package/src/target-templates/{.devops → infra-variants/hetzner/.devops}/infra/hetzner/abandoned/harbor-values.yaml +2 -2
- package/src/target-templates/{.devops → infra-variants/hetzner/.devops}/infra/hetzner/abandoned/hcloud-config.yaml +1 -1
- package/src/target-templates/{.devops → infra-variants/hetzner/.devops}/infra/hetzner/harbor-cert.yaml +2 -2
- package/src/target-templates/{.devops → infra-variants/hetzner/.devops}/infra/hetzner/harbor-values.yaml +2 -2
- package/src/target-templates/{.devops → infra-variants/hetzner/.devops}/infra/hetzner/hcloud-config.yaml +1 -1
- package/src/target-templates/{.github → infra-variants/hetzner/.github}/workflows/k8s-build.yaml +0 -4
- package/src/target-templates/lang-variants-common/README.md +4 -0
- package/src/target-templates/{.devops → lang-variants-common/python/.devops}/config/images.yaml +4 -4
- package/src/target-templates/{.devops → lang-variants-common/python/.devops}/manifests/prefect.yaml.hb +1 -0
- package/src/target-templates/{pyproject.toml → lang-variants-common/python/pyproject.toml} +1 -1
- package/src/target-templates/lang-variants-common/typescript/.devops/config/images.yaml +69 -0
- package/src/target-templates/lang-variants-common/typescript/.devops/manifests/_index.yaml +19 -0
- package/src/target-templates/{.devops → lang-variants-common/typescript/.devops}/manifests/cron-jobs.yaml.hb +1 -0
- package/src/target-templates/{.devops → lang-variants-common/typescript/.devops}/manifests/db-migrate-job.yaml.hb +1 -0
- package/src/target-templates/{.devops → lang-variants-common/typescript/.devops}/manifests/deployment-debug.yaml.hb +1 -0
- package/src/target-templates/{.devops → lang-variants-common/typescript/.devops}/manifests/deployment-process.yaml.hb +1 -0
- package/src/target-templates/{.devops → lang-variants-common/typescript/.devops}/manifests/deployment-web.yaml.hb +1 -0
- package/src/target-templates/lang-variants-common/typescript/.github/actions/connect-to-gke@v1/action.yaml +43 -0
- package/src/target-templates/{.github → lang-variants-common/typescript/.github}/actions/connect-to-infra@v1/action.yaml +22 -1
- package/src/target-templates/lang-variants-prisma/README.md +3 -0
- package/src/target-templates/config/.env.development +0 -1
- package/src/target-templates/config/.env.global +0 -4
- package/src/target-templates/config/.env.test +0 -1
- package/src/target-templates/libs/example-node-lib/bun.lock +0 -27
- /package/src/target-templates/{.devops/infra/test.yaml → cluster-resource-options/dns-test/dns-test.yaml} +0 -0
- /package/src/target-templates/{.devops → cluster-resource-options}/milvus/production/milvus-values.yaml +0 -0
- /package/src/target-templates/{.devops → cluster-resource-options}/milvus/staging/milvus-values.yaml +0 -0
- /package/src/target-templates/{.devops/infra → cluster-resource-options/monitoring-ingress}/monitoring-ingress.yaml +0 -0
- /package/src/target-templates/{.devops/postgres/DailyOperatorRestart.yaml → cluster-resource-options/postgres/daily-operator-restart.yaml} +0 -0
- /package/src/target-templates/{.devops → cluster-resource-options}/postgres/production/cluster/PodDisruptionBudget.yaml +0 -0
- /package/src/target-templates/{.devops → cluster-resource-options}/postgres/production/cluster/SGCluster.yaml +0 -0
- /package/src/target-templates/{.devops → cluster-resource-options}/postgres/production/cluster/StackGres-alerts.yaml +0 -0
- /package/src/target-templates/{.devops → cluster-resource-options}/postgres/production/configurations/06-SGDistributedLogs.yaml +0 -0
- /package/src/target-templates/{.devops/infra → cluster-resource-options/postgres}/stackgres-ui-ingress.yaml +0 -0
- /package/src/target-templates/{.devops → cluster-resource-options}/postgres/staging/cluster/SGCluster.yaml +0 -0
- /package/src/target-templates/{.devops → cluster-resource-options}/prefect/production/prefect-values.yaml +0 -0
- /package/src/target-templates/{.devops → cluster-resource-options}/prefect/staging/prefect-values.yaml +0 -0
- /package/src/target-templates/{.devops → cluster-resource-options}/redis/production/redis-values.yaml +0 -0
- /package/src/target-templates/{.devops → cluster-resource-options}/redis/staging/redis-values.yaml +0 -0
- /package/src/target-templates/{.devops → infra-variants/hetzner/.devops}/infra/hetzner/cert-manager.yaml +0 -0
- /package/src/target-templates/{.devops → infra-variants/hetzner/.devops}/infra/hetzner/ingress-nginx-annotations.yaml +0 -0
- /package/src/target-templates/{.devops → infra-variants/hetzner/.devops}/infra/hetzner/ingress-nginx-configmap.yaml +0 -0
- /package/src/target-templates/{.devops → infra-variants/hetzner/.devops}/infra/hetzner/retain-storage-class.yaml +0 -0
- /package/src/target-templates/{.devops → lang-variants-common/python/.devops}/docker-images/python-services/python-exec.sh +0 -0
- /package/src/target-templates/{.devops → lang-variants-common/python/.devops}/docker-images/python-services/python-run.sh +0 -0
- /package/src/target-templates/{.devops → lang-variants-common/python/.devops}/docker-images/python-services.Dockerfile +0 -0
- /package/src/target-templates/{.devops → lang-variants-common/python/.devops}/manifests/_index.yaml +0 -0
- /package/src/target-templates/{applications → lang-variants-common/python/applications}/example-data-pipeline/pyproject.toml +0 -0
- /package/src/target-templates/{applications → lang-variants-common/python/applications}/example-data-pipeline/src/example_data_pipeline/main.py +0 -0
- /package/src/target-templates/{applications → lang-variants-common/python/applications}/example-python/pyproject.toml +0 -0
- /package/src/target-templates/{applications → lang-variants-common/python/applications}/example-python/src/example_python/__init__.py +0 -0
- /package/src/target-templates/{applications → lang-variants-common/python/applications}/example-python/src/example_python/main.py +0 -0
- /package/src/target-templates/{applications → lang-variants-common/python/applications}/example-python/src/example_python/scripts.py +0 -0
- /package/src/target-templates/{applications → lang-variants-common/python/applications}/example-python/tests/__init__.py +0 -0
- /package/src/target-templates/{devopspy → lang-variants-common/python/devopspy} +0 -0
- /package/src/target-templates/{libs → lang-variants-common/python/libs}/example-python-lib/pyproject.toml +0 -0
- /package/src/target-templates/{libs → lang-variants-common/python/libs}/example-python-lib/src/example_python_lib/__init__.py +0 -0
- /package/src/target-templates/{.devops → lang-variants-common/typescript/.devops}/docker-images/common/docker-common.sh +0 -0
- /package/src/target-templates/{.devops → lang-variants-common/typescript/.devops}/docker-images/node-services/node-exec.sh +0 -0
- /package/src/target-templates/{.devops → lang-variants-common/typescript/.devops}/docker-images/node-services/node-run.sh +0 -0
- /package/src/target-templates/{.devops → lang-variants-common/typescript/.devops}/docker-images/node-services.Dockerfile +0 -0
- /package/src/target-templates/{.devops → lang-variants-common/typescript/.devops}/env.example.yaml +0 -0
- /package/src/target-templates/{.devops → lang-variants-common/typescript/.devops}/manifests/ingress.yaml.hb +0 -0
- /package/src/target-templates/{.devops → lang-variants-common/typescript/.devops}/manifests/service.yaml.hb +0 -0
- /package/src/target-templates/{.github → lang-variants-common/typescript/.github}/actions/build-image@v1/action.yaml +0 -0
- /package/src/target-templates/{.github → lang-variants-common/typescript/.github}/actions/connect-to-digital-ocean@v1/action.yaml +0 -0
- /package/src/target-templates/{.github → lang-variants-common/typescript/.github}/actions/connect-to-hetzner@v1/action.yaml +0 -0
- /package/src/target-templates/{.github → lang-variants-common/typescript/.github}/actions/db-migrate@v1/action.yaml +0 -0
- /package/src/target-templates/{.github → lang-variants-common/typescript/.github}/actions/deploy-image@v1/action.yaml +0 -0
- /package/src/target-templates/{.github → lang-variants-common/typescript/.github}/actions/setup-prereq@v1/action.yaml +0 -0
- /package/src/target-templates/{applications → lang-variants-common/typescript/applications}/example-node/index.ts +0 -0
- /package/src/target-templates/{applications → lang-variants-common/typescript/applications}/example-node/package.json +0 -0
- /package/src/target-templates/{applications → lang-variants-common/typescript/applications}/example-node/tsconfig.json +0 -0
- /package/src/target-templates/{applications → lang-variants-common/typescript/applications}/jobs/README.md +0 -0
- /package/src/target-templates/{applications → lang-variants-common/typescript/applications}/jobs/index.ts +0 -0
- /package/src/target-templates/{applications → lang-variants-common/typescript/applications}/jobs/package.json +0 -0
- /package/src/target-templates/{applications → lang-variants-common/typescript/applications}/jobs/tsconfig.json +0 -0
- /package/src/target-templates/{devops → lang-variants-common/typescript/devops} +0 -0
- /package/src/target-templates/{libs → lang-variants-common/typescript/libs}/example-node-lib/index.ts +0 -0
- /package/src/target-templates/{libs → lang-variants-common/typescript/libs}/example-node-lib/package.json +0 -0
- /package/src/target-templates/{libs → lang-variants-common/typescript/libs}/example-node-lib/tsconfig.json +0 -0
- /package/src/target-templates/{tmp → lang-variants-common/typescript/tmp}/.gitkeep +0 -0
- /package/src/target-templates/{tsconfig.json → lang-variants-common/typescript/tsconfig.json} +0 -0
- /package/src/target-templates/{db → lang-variants-prisma/python/db}/db/__init__.py +0 -0
- /package/src/target-templates/{db → lang-variants-prisma/python/db}/db/db_client_test.py +0 -0
- /package/src/target-templates/{db → lang-variants-prisma/python/db}/pyproject.toml +0 -0
- /package/src/target-templates/{db → lang-variants-prisma/typescript/db}/db-client-test.ts +0 -0
- /package/src/target-templates/{db → lang-variants-prisma/typescript/db}/db-client.ts +0 -0
- /package/src/target-templates/{db → lang-variants-prisma/typescript/db}/env.yaml +0 -0
- /package/src/target-templates/{db → lang-variants-prisma/typescript/db}/package.json +0 -0
- /package/src/target-templates/{db → lang-variants-prisma/typescript/db}/prisma/schema.prisma +0 -0
- /package/src/target-templates/{db → lang-variants-prisma/typescript/db}/prisma-setup-vitest.ts +0 -0
- /package/src/target-templates/{db → lang-variants-prisma/typescript/db}/tsconfig.json +0 -0
- /package/src/target-templates/{dml → lang-variants-prisma/typescript/dml}/package.json +0 -0
- /package/src/target-templates/{dml → lang-variants-prisma/typescript/dml}/tsconfig.json +0 -0
package/dist/cli/init.d.ts.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAqB,MAAM,UAAU,CAAC;AAmB/D,iBAAe,GAAG,CAAC,MAAM,EAAE,gBAAgB,iBAG1C;;;;;;;;AAED,wBAEE"}
|
package/dist/cli/init.js
CHANGED
@@ -1,11 +1,8 @@
|
|
1
|
-
import
|
2
|
-
import
|
3
|
-
import fs from "fs-extra";
|
4
|
-
const __file__ = url.fileURLToPath(import.meta.url);
|
5
|
-
const __root__ = path.join(path.dirname(__file__), "../..");
|
6
|
-
const templatesDir = path.join(__root__, "src/target-templates");
|
7
|
-
const targetDir = process.cwd(); // User's current working directory
|
1
|
+
import inquirer from "inquirer";
|
2
|
+
import { InitGenerator } from "../libs/init-generator";
|
8
3
|
import { CLICommandParser, printUsageAndExit } from "./common";
|
4
|
+
import chalk from "chalk";
|
5
|
+
import fs from 'fs-extra';
|
9
6
|
const oneLiner = "Initializes the devops utility by copying template files to the current folder";
|
10
7
|
const keyExamples = `$ devops init`;
|
11
8
|
const usage = `
|
@@ -20,52 +17,205 @@ EXAMPLES
|
|
20
17
|
async function run(cmdObj) {
|
21
18
|
if (cmdObj.help)
|
22
19
|
printUsageAndExit(usage);
|
23
|
-
|
20
|
+
createFiles();
|
24
21
|
}
|
25
22
|
export default {
|
26
23
|
init: { oneLiner, keyExamples, run },
|
27
24
|
};
|
28
|
-
async function
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
});
|
37
|
-
console.log(successMessage);
|
25
|
+
async function createFiles() {
|
26
|
+
const tc = new InitGenerator();
|
27
|
+
const userChoices = await getUserChoices(tc.projectName);
|
28
|
+
// Language variants
|
29
|
+
tc.addCopiedFolder("lang-variants-common/typescript", ".");
|
30
|
+
if (userChoices.usePython) {
|
31
|
+
tc.addCopiedFolder("lang-variants-common/python", ".");
|
32
|
+
tc.enableSubtitution("pyproject.toml");
|
38
33
|
}
|
39
|
-
|
40
|
-
|
41
|
-
|
34
|
+
tc.enableSubtitution(".devops/config/images.yaml");
|
35
|
+
tc.setMessageGenerator(".envrc", envrcMessage);
|
36
|
+
// gitignore
|
37
|
+
const gitIgnore = gitIgnoreContent(userChoices.infraVariant, userChoices.usePython);
|
38
|
+
tc.addGeneratedFile(".gitignore", gitIgnore);
|
39
|
+
tc.setMessageGenerator(".gitignore", gitignoreMessageGen(gitIgnore));
|
40
|
+
// Infra variants
|
41
|
+
tc.addCopiedFolder(`infra-variants/${userChoices.infraVariant}`, ".");
|
42
|
+
tc.enableSubtitution(".devops/config/constants.yaml");
|
43
|
+
if (userChoices.infraVariant === "hetzner") {
|
44
|
+
tc.enableSubtitution(".devops/infra/hetzner/harbor-cert.yaml");
|
45
|
+
tc.enableSubtitution(".devops/infra/hetzner/harbor-values.yaml");
|
46
|
+
tc.enableSubtitution(".devops/infra/hetzner/hcloud-config.yaml");
|
42
47
|
}
|
48
|
+
// Prisma
|
49
|
+
if (userChoices.usePrisma) {
|
50
|
+
tc.addCopiedFolder("lang-variants-prisma/typescript", ".");
|
51
|
+
if (userChoices.usePython) {
|
52
|
+
tc.addCopiedFolder("lang-variants-prisma/python", ".");
|
53
|
+
}
|
54
|
+
}
|
55
|
+
// Cluster resources
|
56
|
+
const clusterResources = new Set(userChoices.clusterResources);
|
57
|
+
if (clusterResources.has("dns-test")) {
|
58
|
+
tc.addCopiedFolder("cluster-resource-options/dns-test", ".devops/infra/dns-test");
|
59
|
+
}
|
60
|
+
if (clusterResources.has("monitoring-ingress")) {
|
61
|
+
tc.addCopiedFolder("cluster-resource-options/monitoring-ingress", ".devops/infra/monitoring-ingress");
|
62
|
+
}
|
63
|
+
if (clusterResources.has("postgres")) {
|
64
|
+
tc.addCopiedFolder("cluster-resource-options/postgres", ".devops/infra/postgres");
|
65
|
+
// prettier-ignore
|
66
|
+
tc.enableSubtitution(".devops/infra/postgres/staging/configurations/07-SGObjectStorage.yaml");
|
67
|
+
// prettier-ignore
|
68
|
+
tc.enableSubtitution(".devops/infra/postgres/staging/configurations/08-SGScript.yaml");
|
69
|
+
// prettier-ignore
|
70
|
+
tc.enableSubtitution(".devops/infra/postgres/production/configurations/07-SGObjectStorage.yaml");
|
71
|
+
// prettier-ignore
|
72
|
+
tc.enableSubtitution(".devops/infra/postgres/production/configurations/08-SGScript.yaml");
|
73
|
+
}
|
74
|
+
if (clusterResources.has("redis")) {
|
75
|
+
tc.addCopiedFolder("cluster-resource-options/redis", ".devops/infra/redis");
|
76
|
+
}
|
77
|
+
if (clusterResources.has("milvus")) {
|
78
|
+
tc.addCopiedFolder("cluster-resource-options/milvus", ".devops/infra/milvus");
|
79
|
+
}
|
80
|
+
if (clusterResources.has("prefect") && userChoices.usePython) {
|
81
|
+
tc.addCopiedFolder("cluster-resource-options/prefect", ".devops/infra/prefect");
|
82
|
+
}
|
83
|
+
tc.run({
|
84
|
+
substitution: {
|
85
|
+
'PROJECT_NAME': userChoices.projectName,
|
86
|
+
'STAGING_DOMAIN': userChoices.stagingDomain,
|
87
|
+
'PRODUCTION_DOMAIN': userChoices.productionDomain,
|
88
|
+
'GCLOUD_PROJECT_ID': userChoices.gcloudProjectId,
|
89
|
+
'REGISTRY_IMAGE_PATH_PREFIX': userChoices.registryImagePathPrefix,
|
90
|
+
'REGISTRY_BASE_URL': userChoices.registryBaseUrl,
|
91
|
+
},
|
92
|
+
messages: [
|
93
|
+
packageJsonMessage(userChoices.usePrisma)
|
94
|
+
]
|
95
|
+
});
|
43
96
|
}
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
To finish the setup:
|
48
|
-
|
49
|
-
1. add the following entry to the main package.json:
|
50
|
-
"workspaces": [
|
51
|
-
"libs/**",
|
52
|
-
"applications/**",
|
97
|
+
function packageJsonMessage(usePrisma) {
|
98
|
+
const prismaMessage = usePrisma
|
99
|
+
? `,
|
53
100
|
"db/**",
|
54
|
-
"dml/**"
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
101
|
+
"dml/**"`
|
102
|
+
: "";
|
103
|
+
return `add the following entry to the main ${chalk.blue("package.json")}:
|
104
|
+
${chalk.yellow(`"workspaces": [
|
105
|
+
"libs/**",
|
106
|
+
"applications/**"${prismaMessage}
|
107
|
+
],`)}`;
|
108
|
+
}
|
109
|
+
function gitIgnoreContent(infraVariant, usePython) {
|
110
|
+
const common = `**/.env*
|
59
111
|
config/kubeconfig
|
60
112
|
tmp/**
|
61
|
-
!tmp/**/.gitkeep
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
113
|
+
!tmp/**/.gitkeep`;
|
114
|
+
const gcloud = infraVariant === 'gcloud'
|
115
|
+
? 'config/gke_gcloud_auth_plugin_cache'
|
116
|
+
: null;
|
117
|
+
const python = usePython
|
118
|
+
? `venv/
|
119
|
+
**/__pycache__`
|
120
|
+
: null;
|
121
|
+
return [common, gcloud, python].filter(Boolean).join('\n');
|
122
|
+
}
|
123
|
+
function gitignoreMessageGen(content) {
|
124
|
+
return (exists) => {
|
125
|
+
if (!exists)
|
126
|
+
return;
|
127
|
+
return `add the following to your ${chalk.blue(".gitignore")}:
|
128
|
+
${chalk.yellow(content)}`;
|
129
|
+
};
|
130
|
+
}
|
131
|
+
function envrcMessage(targetExists, fileInfo) {
|
132
|
+
if (fileInfo.type !== 'copied')
|
133
|
+
throw new Error(`envrcMessage() expects a copied file, got ${fileInfo.type}`);
|
134
|
+
if (targetExists) {
|
135
|
+
const content = fs.readFileSync(fileInfo.sourceAbs, 'utf-8');
|
136
|
+
return `add the following to your ${chalk.blue(".envrc")} and run ${chalk.yellow("direnv allow")}:
|
137
|
+
${chalk.yellow(content)}`;
|
138
|
+
}
|
139
|
+
else {
|
140
|
+
return `Enable ${chalk.blue(".envrc")} by installing ${chalk.blue('direnv')} and running ${chalk.yellow("direnv allow")}`;
|
141
|
+
}
|
142
|
+
}
|
143
|
+
function getUserChoices(projectName) {
|
144
|
+
const defaultProjectName = projectName || "changeme";
|
145
|
+
return inquirer.prompt([
|
146
|
+
{
|
147
|
+
type: "input",
|
148
|
+
name: "projectName",
|
149
|
+
message: `Enter the project name (default: '${defaultProjectName}')`,
|
150
|
+
default: defaultProjectName,
|
151
|
+
},
|
152
|
+
{
|
153
|
+
type: "input",
|
154
|
+
name: "stagingDomain",
|
155
|
+
message: "Enter the staging domain (default: 'staging.com')",
|
156
|
+
default: "staging.com",
|
157
|
+
},
|
158
|
+
{
|
159
|
+
type: "input",
|
160
|
+
name: "productionDomain",
|
161
|
+
message: "Enter the production domain (default: 'production.com')",
|
162
|
+
default: "production.com",
|
163
|
+
},
|
164
|
+
{
|
165
|
+
type: "list",
|
166
|
+
name: "infraVariant",
|
167
|
+
message: "Where does your cluster run?",
|
168
|
+
choices: [
|
169
|
+
{ name: "Google Cloud", value: "gcloud" },
|
170
|
+
{ name: "Digital Ocean", value: "digitalocean" },
|
171
|
+
{ name: "Hetzner", value: "hetzner" },
|
172
|
+
],
|
173
|
+
},
|
174
|
+
{
|
175
|
+
type: "input",
|
176
|
+
name: "gcloudProjectId",
|
177
|
+
message: "Enter the GCP project ID (default: 'changeme')",
|
178
|
+
default: "changeme",
|
179
|
+
when: (answers) => answers.infraVariant === "gcloud",
|
180
|
+
},
|
181
|
+
{
|
182
|
+
type: "input",
|
183
|
+
name: "registryImagePathPrefix",
|
184
|
+
message: (answers) => `Enter your Digital Ocean container registry name (default: '${answers.projectName}')`,
|
185
|
+
default: (answers) => answers.projectName,
|
186
|
+
when: (answers) => answers.infraVariant === "digitalocean",
|
187
|
+
},
|
188
|
+
{
|
189
|
+
type: "input",
|
190
|
+
name: "registryBaseUrl",
|
191
|
+
message: (answers) => `Enter your registry base URL (default: 'registry.${answers.stagingDomain}')`,
|
192
|
+
default: (answers) => `registry.${answers.stagingDomain}`,
|
193
|
+
when: (answers) => answers.infraVariant === "hetzner",
|
194
|
+
},
|
195
|
+
{
|
196
|
+
type: "confirm",
|
197
|
+
name: "usePython",
|
198
|
+
message: "Add support for Python?",
|
199
|
+
default: true,
|
200
|
+
},
|
201
|
+
{
|
202
|
+
type: "confirm",
|
203
|
+
name: "usePrisma",
|
204
|
+
message: "Add support for Prisma?",
|
205
|
+
default: true,
|
206
|
+
},
|
207
|
+
{
|
208
|
+
type: "checkbox",
|
209
|
+
name: "clusterResources",
|
210
|
+
message: "Optional manifests and helm charts to add",
|
211
|
+
choices: (answers) => [
|
212
|
+
{ name: "Manifest to test DNS setup", value: "dns-test" },
|
213
|
+
{ name: "Manifest to setup ingress for graphana and prometheus", value: "monitoring-ingress" },
|
214
|
+
{ name: "Stackgres CRDs and manifests for Postgres", value: "postgres" },
|
215
|
+
{ name: "Redis Helm chart values", value: "redis" },
|
216
|
+
{ name: "Milvus helm chart values", value: "milvus" },
|
217
|
+
...(answers.usePython ? [{ name: "Prefect Helm chart values", value: "prefect" }] : [])
|
218
|
+
]
|
219
|
+
}
|
220
|
+
]);
|
221
|
+
}
|
@@ -0,0 +1,41 @@
|
|
1
|
+
type MessageGeneratorFn = (targetExists: boolean, fileInfo: InitGeneratorFileInfo) => string | null | undefined;
|
2
|
+
type CommonFileInfo = {
|
3
|
+
targetRel: string;
|
4
|
+
targetAbs: string;
|
5
|
+
targetFolderAbs: string;
|
6
|
+
targetExists: boolean;
|
7
|
+
messageGenerator?: MessageGeneratorFn;
|
8
|
+
};
|
9
|
+
export type InitGeneratorCopiedFileInfo = CommonFileInfo & {
|
10
|
+
type: "copied";
|
11
|
+
sourceRel: string;
|
12
|
+
sourceAbs: string;
|
13
|
+
enableSubstitution?: boolean;
|
14
|
+
};
|
15
|
+
type InitGeneratorGeneratedFileInfo = CommonFileInfo & {
|
16
|
+
type: "generated";
|
17
|
+
content: string;
|
18
|
+
};
|
19
|
+
export type InitGeneratorFileInfo = InitGeneratorCopiedFileInfo | InitGeneratorGeneratedFileInfo;
|
20
|
+
export declare class InitGenerator {
|
21
|
+
projectName?: string;
|
22
|
+
/** The key is targetRel */
|
23
|
+
files: Record<string, InitGeneratorFileInfo>;
|
24
|
+
constructor();
|
25
|
+
_ensureFileExists(targetRel: string): void;
|
26
|
+
enableSubtitution(targetRel: string): void;
|
27
|
+
setMessageGenerator(targetRel: string, messageGen: MessageGeneratorFn): void;
|
28
|
+
addGeneratedFile(targetRel: string, content: string): void;
|
29
|
+
/**
|
30
|
+
* @param source relative path under the templates folder. All files and folders under `source` are copied directly under `target`.
|
31
|
+
* @param target relative path under the project root folder.
|
32
|
+
* If the target file exists already in `files`, it will be overridden.
|
33
|
+
*/
|
34
|
+
addCopiedFolder(source: string, target: string): void;
|
35
|
+
run({ substitution, messages, }: {
|
36
|
+
substitution?: Record<string, string | undefined>;
|
37
|
+
messages?: string[];
|
38
|
+
}): void;
|
39
|
+
}
|
40
|
+
export {};
|
41
|
+
//# sourceMappingURL=init-generator.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"init-generator.d.ts","sourceRoot":"","sources":["../../src/libs/init-generator.ts"],"names":[],"mappings":"AAWA,KAAK,kBAAkB,GAAG,CAAC,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,qBAAqB,KAAK,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;AAEhH,KAAK,cAAc,GAAG;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,OAAO,CAAC;IACtB,gBAAgB,CAAC,EAAE,kBAAkB,CAAC;CACvC,CAAA;AAED,MAAM,MAAM,2BAA2B,GAAG,cAAc,GAAE;IACxD,IAAI,EAAE,QAAQ,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B,CAAA;AAED,KAAK,8BAA8B,GAAG,cAAc,GAAG;IACrD,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG,2BAA2B,GAAG,8BAA8B,CAAC;AAEjG,qBAAa,aAAa;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,2BAA2B;IAC3B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAM;;IASlD,iBAAiB,CAAC,SAAS,EAAE,MAAM;IAMnC,iBAAiB,CAAC,SAAS,EAAE,MAAM;IAQnC,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,kBAAkB;IAKrE,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;IAcnD;;;;OAIG;IACH,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAsB9C,GAAG,CAAC,EACF,YAAiB,EACjB,QAAa,GACd,EAAG;QACF,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;QAClD,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;KACrB;CAkDF"}
|
@@ -0,0 +1,123 @@
|
|
1
|
+
import url from "url";
|
2
|
+
import path from "path";
|
3
|
+
import fs from "fs-extra";
|
4
|
+
import chalk from "chalk";
|
5
|
+
import fg from 'fast-glob';
|
6
|
+
const __file__ = url.fileURLToPath(import.meta.url);
|
7
|
+
const __root__ = path.join(path.dirname(__file__), "../..");
|
8
|
+
const templatesDir = path.join(__root__, "src/target-templates");
|
9
|
+
const targetDir = process.cwd(); // User's current working directory
|
10
|
+
export class InitGenerator {
|
11
|
+
projectName;
|
12
|
+
/** The key is targetRel */
|
13
|
+
files = {};
|
14
|
+
constructor() {
|
15
|
+
if (fs.existsSync("package.json")) {
|
16
|
+
const packageJson = fs.readJSONSync("package.json");
|
17
|
+
this.projectName = packageJson.name;
|
18
|
+
}
|
19
|
+
}
|
20
|
+
_ensureFileExists(targetRel) {
|
21
|
+
if (!this.files[targetRel]) {
|
22
|
+
throw new Error(`File for target "${targetRel}" not found.`);
|
23
|
+
}
|
24
|
+
}
|
25
|
+
enableSubtitution(targetRel) {
|
26
|
+
this._ensureFileExists(targetRel);
|
27
|
+
if (this.files[targetRel].type !== "copied") {
|
28
|
+
throw new Error(`File for target "${targetRel}" is not a copied file.`);
|
29
|
+
}
|
30
|
+
this.files[targetRel].enableSubstitution = true;
|
31
|
+
}
|
32
|
+
setMessageGenerator(targetRel, messageGen) {
|
33
|
+
this._ensureFileExists(targetRel);
|
34
|
+
this.files[targetRel].messageGenerator = messageGen;
|
35
|
+
}
|
36
|
+
addGeneratedFile(targetRel, content) {
|
37
|
+
const targetAbs = path.join(targetDir, targetRel);
|
38
|
+
const targetFolderAbs = path.dirname(targetAbs);
|
39
|
+
const exists = fs.existsSync(targetAbs);
|
40
|
+
this.files[targetRel] = {
|
41
|
+
type: "generated",
|
42
|
+
targetRel,
|
43
|
+
targetAbs,
|
44
|
+
targetFolderAbs,
|
45
|
+
targetExists: exists,
|
46
|
+
content,
|
47
|
+
};
|
48
|
+
}
|
49
|
+
/**
|
50
|
+
* @param source relative path under the templates folder. All files and folders under `source` are copied directly under `target`.
|
51
|
+
* @param target relative path under the project root folder.
|
52
|
+
* If the target file exists already in `files`, it will be overridden.
|
53
|
+
*/
|
54
|
+
addCopiedFolder(source, target) {
|
55
|
+
const pathPrefix = path.join(templatesDir, source);
|
56
|
+
const glob = path.join(pathPrefix, '**/*');
|
57
|
+
fg.globSync(glob, { dot: true }).forEach((sourceAbs) => {
|
58
|
+
const sourceRel = path.relative(templatesDir, sourceAbs);
|
59
|
+
const pathUnderSource = path.relative(pathPrefix, sourceAbs);
|
60
|
+
const targetRel = path.join(target, pathUnderSource);
|
61
|
+
const targetAbs = path.join(targetDir, targetRel);
|
62
|
+
const targetFolderAbs = path.dirname(targetAbs);
|
63
|
+
const exists = fs.existsSync(targetAbs);
|
64
|
+
this.files[targetRel] = {
|
65
|
+
type: "copied",
|
66
|
+
sourceRel,
|
67
|
+
targetRel,
|
68
|
+
sourceAbs,
|
69
|
+
targetAbs,
|
70
|
+
targetFolderAbs,
|
71
|
+
targetExists: exists,
|
72
|
+
};
|
73
|
+
});
|
74
|
+
}
|
75
|
+
run({ substitution = {}, messages = [], }) {
|
76
|
+
const fileMessages = [];
|
77
|
+
Object.values(this.files).forEach((fileInfo) => {
|
78
|
+
if (fileInfo.messageGenerator) {
|
79
|
+
const message = fileInfo.messageGenerator(fileInfo.targetExists, fileInfo);
|
80
|
+
if (message) {
|
81
|
+
fileMessages.push(message);
|
82
|
+
}
|
83
|
+
}
|
84
|
+
if (fileInfo.targetExists) {
|
85
|
+
console.log(`Skipped ${chalk.yellow(fileInfo.targetRel)} (exists)`);
|
86
|
+
return;
|
87
|
+
}
|
88
|
+
// Create or copy
|
89
|
+
if (!fs.existsSync(fileInfo.targetFolderAbs)) {
|
90
|
+
fs.mkdirSync(fileInfo.targetFolderAbs, { recursive: true });
|
91
|
+
}
|
92
|
+
if (fileInfo.type === 'generated') {
|
93
|
+
fs.writeFileSync(fileInfo.targetAbs, fileInfo.content, 'utf8');
|
94
|
+
}
|
95
|
+
else if (fileInfo.enableSubstitution) {
|
96
|
+
const content = fs.readFileSync(fileInfo.sourceAbs, 'utf8');
|
97
|
+
const substitutedContent = content.replace(/\$([A-Z_]+)/g, (_, varName) => {
|
98
|
+
const value = substitution[varName];
|
99
|
+
if (!value) {
|
100
|
+
throw new Error(`${chalk.blue("TemplateCopier.run()")}: Variable ${chalk.yellow(varName)} is needed by ${chalk.yellow(fileInfo.targetRel)} but is undefined.`);
|
101
|
+
}
|
102
|
+
return value;
|
103
|
+
});
|
104
|
+
fs.writeFileSync(fileInfo.targetAbs, substitutedContent);
|
105
|
+
}
|
106
|
+
else {
|
107
|
+
fs.copySync(fileInfo.sourceAbs, fileInfo.targetAbs, {
|
108
|
+
overwrite: false,
|
109
|
+
errorOnExist: false,
|
110
|
+
dereference: false,
|
111
|
+
});
|
112
|
+
}
|
113
|
+
console.log(`Created ${chalk.green(fileInfo.targetRel)}`);
|
114
|
+
});
|
115
|
+
const allMessages = [...messages, ...fileMessages];
|
116
|
+
if (!allMessages.length)
|
117
|
+
return;
|
118
|
+
console.log(chalk.blue("\nNext steps:"));
|
119
|
+
allMessages.forEach((msg, i) => {
|
120
|
+
console.log(`${i + 1}. ${msg}\n`);
|
121
|
+
});
|
122
|
+
}
|
123
|
+
}
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "@vaharoni/devops",
|
3
3
|
"type": "module",
|
4
|
-
"version": "1.1.
|
4
|
+
"version": "1.1.2",
|
5
5
|
"description": "Devops utility",
|
6
6
|
"main": "./dist/index.js",
|
7
7
|
"types": "./dist/index.d.ts",
|
@@ -34,9 +34,11 @@
|
|
34
34
|
"@iarna/toml": "^2.2.5",
|
35
35
|
"chalk": "^5.3.0",
|
36
36
|
"concurrently": "^9.1.2",
|
37
|
+
"fast-glob": "^3.3.3",
|
37
38
|
"fs-extra": "11.2.0",
|
38
39
|
"glob": "^11.0.1",
|
39
40
|
"handlebars": "^4.7.8",
|
41
|
+
"inquirer": "^12.7.0",
|
40
42
|
"lodash": "^4.17.21",
|
41
43
|
"tsx": "^4.19.3",
|
42
44
|
"yaml": "^2.4.2",
|