@kodus/cli 0.0.11 → 0.0.12
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/index.js +2 -4
- package/package.json +1 -1
- package/src/commands/install.js +50 -17
- package/src/utils/helpers.js +11 -1
- package/templates/.env.example +142 -0
package/index.js
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import { program } from "commander";
|
|
4
|
-
import {
|
|
5
|
-
import { dirname, join } from 'path';
|
|
6
|
-
import { setupEnvironment } from './src/commands/install.js';
|
|
4
|
+
import { setupEnvironment } from "./src/commands/install.js";
|
|
7
5
|
|
|
8
6
|
// CLI version
|
|
9
|
-
program.version("0.0.
|
|
7
|
+
program.version("0.0.12");
|
|
10
8
|
|
|
11
9
|
// Install command
|
|
12
10
|
program
|
package/package.json
CHANGED
package/src/commands/install.js
CHANGED
|
@@ -6,10 +6,13 @@ import path from "path";
|
|
|
6
6
|
import { execSync } from "child_process";
|
|
7
7
|
import { DEFAULT_CONFIG, DOCKER_NETWORKS, CRITICAL_ERRORS } from "../config/default.js";
|
|
8
8
|
import {
|
|
9
|
-
|
|
9
|
+
generateBase64Secret,
|
|
10
|
+
generateHexSecret,
|
|
11
|
+
generateWebhookToken,
|
|
10
12
|
generateDbPassword,
|
|
11
13
|
copyTemplates,
|
|
12
14
|
createDockerNetworks,
|
|
15
|
+
updateEnvFile,
|
|
13
16
|
} from "../utils/helpers.js";
|
|
14
17
|
import { fileURLToPath } from 'url';
|
|
15
18
|
import { dirname } from 'path';
|
|
@@ -50,6 +53,24 @@ const waitForService = async (serviceName, successMessage, errorMessage) => {
|
|
|
50
53
|
}
|
|
51
54
|
};
|
|
52
55
|
|
|
56
|
+
const copyEnvFile = async () => {
|
|
57
|
+
const envExamplePath = path.join(__dirname, '../../templates/.env.example');
|
|
58
|
+
const envPath = path.join(process.cwd(), '.env');
|
|
59
|
+
|
|
60
|
+
if (!fs.existsSync(envExamplePath)) {
|
|
61
|
+
console.error(chalk.red('Error: .env.example file not found in templates directory'));
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
try {
|
|
66
|
+
await fs.copy(envExamplePath, envPath);
|
|
67
|
+
console.log(chalk.green('.env file created successfully from template'));
|
|
68
|
+
} catch (error) {
|
|
69
|
+
console.error(chalk.red('Error copying .env file:', error.message));
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
|
|
53
74
|
export const setupEnvironment = async () => {
|
|
54
75
|
try {
|
|
55
76
|
// Check prerequisites
|
|
@@ -81,6 +102,8 @@ export const setupEnvironment = async () => {
|
|
|
81
102
|
process.exit(1);
|
|
82
103
|
}
|
|
83
104
|
|
|
105
|
+
await copyEnvFile();
|
|
106
|
+
|
|
84
107
|
// Environment type selection
|
|
85
108
|
const { envType } = await inquirer.prompt([
|
|
86
109
|
{
|
|
@@ -205,13 +228,15 @@ export const setupEnvironment = async () => {
|
|
|
205
228
|
},
|
|
206
229
|
]);
|
|
207
230
|
|
|
208
|
-
//
|
|
209
|
-
const
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
API_JWT_SECRET:
|
|
214
|
-
API_JWT_REFRESHSECRET:
|
|
231
|
+
// Update environment variables with generated values
|
|
232
|
+
const envUpdates = {
|
|
233
|
+
NEXTAUTH_SECRET: generateBase64Secret(),
|
|
234
|
+
JWT_SECRET_KEY: generateBase64Secret(),
|
|
235
|
+
API_CRYPTO_KEY: generateHexSecret(),
|
|
236
|
+
API_JWT_SECRET: generateBase64Secret(),
|
|
237
|
+
API_JWT_REFRESHSECRET: generateBase64Secret(),
|
|
238
|
+
CODE_MANAGEMENT_SECRET: generateHexSecret(),
|
|
239
|
+
CODE_MANAGEMENT_WEBHOOK_TOKEN: generateWebhookToken(),
|
|
215
240
|
API_PG_DB_PASSWORD: generateDbPassword(),
|
|
216
241
|
API_MG_DB_PASSWORD: generateDbPassword(),
|
|
217
242
|
RABBITMQ_DEFAULT_PASS: generateDbPassword(),
|
|
@@ -224,15 +249,9 @@ export const setupEnvironment = async () => {
|
|
|
224
249
|
...gitConfig,
|
|
225
250
|
};
|
|
226
251
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
.map(([key, value]) => `${key}=${value}`)
|
|
231
|
-
.join("\n");
|
|
232
|
-
|
|
233
|
-
const envPath = path.join(process.cwd(), '.env');
|
|
234
|
-
fs.writeFileSync(envPath, envContentString);
|
|
235
|
-
envSpinner.succeed("Created .env file");
|
|
252
|
+
const envSpinner = ora("Updating environment variables").start();
|
|
253
|
+
await updateEnvFile(envUpdates);
|
|
254
|
+
envSpinner.succeed("Environment variables updated");
|
|
236
255
|
|
|
237
256
|
// Create Docker networks
|
|
238
257
|
createDockerNetworks(DOCKER_NETWORKS);
|
|
@@ -262,6 +281,12 @@ export const setupEnvironment = async () => {
|
|
|
262
281
|
"MongoDB failed to start"
|
|
263
282
|
);
|
|
264
283
|
|
|
284
|
+
await waitForService(
|
|
285
|
+
"kodus_web",
|
|
286
|
+
"✓ Ready in",
|
|
287
|
+
"Web service failed to start"
|
|
288
|
+
);
|
|
289
|
+
|
|
265
290
|
// Setup database
|
|
266
291
|
const dbSpinner = ora("Setting up database").start();
|
|
267
292
|
try {
|
|
@@ -315,6 +340,14 @@ export const setupEnvironment = async () => {
|
|
|
315
340
|
|
|
316
341
|
if (startServices) {
|
|
317
342
|
execSync("docker-compose up -d", { stdio: "ignore" });
|
|
343
|
+
|
|
344
|
+
// Wait for web service to be ready after restart
|
|
345
|
+
await waitForService(
|
|
346
|
+
"kodus_web",
|
|
347
|
+
"✓ Ready in",
|
|
348
|
+
"Web service failed to start"
|
|
349
|
+
);
|
|
350
|
+
|
|
318
351
|
console.log(chalk.green("\nServices started successfully!"));
|
|
319
352
|
}
|
|
320
353
|
} catch (error) {
|
package/src/utils/helpers.js
CHANGED
|
@@ -10,7 +10,17 @@ import { dirname } from 'path';
|
|
|
10
10
|
const __filename = fileURLToPath(import.meta.url);
|
|
11
11
|
const __dirname = dirname(__filename);
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
// Base64 secret key (for JWT and auth)
|
|
14
|
+
export const generateBase64Secret = () => crypto.randomBytes(32).toString('base64');
|
|
15
|
+
|
|
16
|
+
// Hex secret key (for crypto and management)
|
|
17
|
+
export const generateHexSecret = () => crypto.randomBytes(32).toString('hex');
|
|
18
|
+
|
|
19
|
+
// URL-safe base64 secret (for webhook tokens)
|
|
20
|
+
export const generateWebhookToken = () => {
|
|
21
|
+
const base64 = crypto.randomBytes(32).toString('base64');
|
|
22
|
+
return base64.replace(/=/g, '').replace(/\+/g, '_').replace(/\//g, '-');
|
|
23
|
+
};
|
|
14
24
|
|
|
15
25
|
export const generateDbPassword = () =>
|
|
16
26
|
crypto
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# =============================================
|
|
2
|
+
# Environment Configuration Example File
|
|
3
|
+
# Copy this file to .env and adjust the values
|
|
4
|
+
# =============================================
|
|
5
|
+
|
|
6
|
+
## ---- BASIC SYSTEM CONFIGURATION ----
|
|
7
|
+
|
|
8
|
+
# Web Application Settings
|
|
9
|
+
WEB_NODE_ENV="self-hosted" # self-hosted, development, production
|
|
10
|
+
WEB_HOSTNAME_API="localhost" # API hostname
|
|
11
|
+
WEB_PORT_API=3001 # API port
|
|
12
|
+
WEB_PORT=3000 # Web application port
|
|
13
|
+
GLOBAL_API_CONTAINER_NAME="kodus-orchestrator" # API container name
|
|
14
|
+
|
|
15
|
+
# Authentication Settings
|
|
16
|
+
NEXTAUTH_URL="http://localhost:3000" # Base URL for authentication
|
|
17
|
+
NEXTAUTH_SECRET="" # NextAuth secret key (generate with: openssl rand -base64 32)
|
|
18
|
+
JWT_SECRET_KEY="" # JWT secret key (generate with: openssl rand -base64 32)
|
|
19
|
+
|
|
20
|
+
## ---- API CONFIGURATION ----
|
|
21
|
+
|
|
22
|
+
# General API Settings
|
|
23
|
+
API_NODE_ENV="development" # development, production, test
|
|
24
|
+
API_LOG_LEVEL=error # error, warn, info, debug
|
|
25
|
+
API_LOG_PRETTY=true # Log formatting
|
|
26
|
+
API_HOST=0.0.0.0 # API host
|
|
27
|
+
API_PORT=3001 # API port
|
|
28
|
+
API_RATE_MAX_REQUEST=100 # Request rate limit
|
|
29
|
+
API_RATE_INTERVAL=1000 # Rate limit interval in ms
|
|
30
|
+
API_CLOUD_MODE=false # Enable/disable cloud mode
|
|
31
|
+
API_CRYPTO_KEY= # Crypto key for encryption/decryption
|
|
32
|
+
|
|
33
|
+
# JWT Configuration
|
|
34
|
+
API_JWT_EXPIRES_IN=365d # Token expiration time
|
|
35
|
+
API_JWT_SECRET=secret # JWT secret key
|
|
36
|
+
API_JWT_REFRESHSECRET=refreshSecret # Refresh token secret key
|
|
37
|
+
API_JWT_REFRESH_EXPIRES_IN=7d # Refresh token expiration time
|
|
38
|
+
|
|
39
|
+
## ---- DATABASE CONFIGURATION ----
|
|
40
|
+
|
|
41
|
+
# PostgreSQL Settings
|
|
42
|
+
API_DATABASE_ENV="development" # development, production, test
|
|
43
|
+
API_PG_DB_HOST=db_kodus_postgres # PostgreSQL host
|
|
44
|
+
API_PG_DB_PORT=5432 # PostgreSQL port
|
|
45
|
+
API_PG_DB_USERNAME=kodusdev # Database username
|
|
46
|
+
API_PG_DB_PASSWORD= # Database password
|
|
47
|
+
API_PG_DB_DATABASE=kodus_db # Database name
|
|
48
|
+
|
|
49
|
+
# MongoDB Settings
|
|
50
|
+
API_MG_DB_HOST=db_kodus_mongodb # MongoDB host
|
|
51
|
+
API_MG_DB_PORT=27017 # MongoDB port
|
|
52
|
+
API_MG_DB_USERNAME=kodusdev # Database username
|
|
53
|
+
API_MG_DB_PASSWORD= # Database password
|
|
54
|
+
API_MG_DB_DATABASE=kodus # Database name
|
|
55
|
+
API_MG_DB_PRODUCTION_CONFIG='' # Additional production settings
|
|
56
|
+
|
|
57
|
+
## ---- LLM API KEYS ----
|
|
58
|
+
|
|
59
|
+
# API Keys for LLM Providers
|
|
60
|
+
API_OPEN_AI_APIKEY= # OpenAI API key
|
|
61
|
+
API_GOOGLE_AI_API_KEY= # Google AI API key
|
|
62
|
+
API_ANTHROPIC_API_KEY= # Anthropic API key
|
|
63
|
+
API_NOVITA_AI_API_KEY= # Novita AI API key
|
|
64
|
+
API_VERTEX_AI_API_KEY= # Vertex AI API key
|
|
65
|
+
|
|
66
|
+
# Available LLM Models
|
|
67
|
+
API_LLM_MODEL_CHATGPT_3_5_TURBO=gpt-4o-mini
|
|
68
|
+
API_LLM_MODEL_CHATGPT_3_5_TURBO_16K=gpt-4o-mini
|
|
69
|
+
API_LLM_MODEL_CHATGPT_4=gpt-4o-mini
|
|
70
|
+
API_LLM_MODEL_CHATGPT_4_TURBO=gpt-4o-mini
|
|
71
|
+
API_LLM_MODEL_CHATGPT_4_ALL=gpt-4o
|
|
72
|
+
API_LLM_MODEL_CHATGPT_4_ALL_MINI=gpt-4o-mini
|
|
73
|
+
API_LLM_MODEL_CLAUDE_3_5_SONNET=claude-3-5-sonnet-20241022
|
|
74
|
+
API_LLM_MODEL_CLAUDE_3_5_SONNET_20241022=claude-3-5-sonnet-20241022
|
|
75
|
+
API_LLM_MODEL_GEMINI_1_5_PRO=gpt-4o-mini
|
|
76
|
+
API_LLM_MODEL_GEMINI_1_5_PRO_EXP=gpt-4o-mini
|
|
77
|
+
|
|
78
|
+
## ---- CRON CONFIGURATION ----
|
|
79
|
+
# Format: minute hour day_of_month month day_of_week
|
|
80
|
+
# Example: 0 1 * * 5 = Every Friday at 01:00
|
|
81
|
+
|
|
82
|
+
API_CRON_AUTOMATION_INTERACTION_MONITOR=0 1 * * 5
|
|
83
|
+
API_CRON_AUTOMATION_ISSUES_DETAILS=0 1 * * 5
|
|
84
|
+
API_CRON_COMPILE_SPRINT=0 1 * * 5
|
|
85
|
+
API_CRON_METRICS=* 5 * * *
|
|
86
|
+
API_CRON_AUTOMATION_DAILY_CHECKIN=* 5 * * *
|
|
87
|
+
API_CRON_SPRINT_RETRO=* 5 * * *
|
|
88
|
+
API_CRON_TEAM_ARTIFACTS_WEEKLY=* 5 * * *
|
|
89
|
+
API_CRON_TEAM_ARTIFACTS_DAILY=* 5 * * *
|
|
90
|
+
API_CRON_AUTOMATION_TEAM_PROGRESS_TRACKER=* 5 * * *
|
|
91
|
+
API_CRON_ORGANIZATION_METRICS=* 5 * * *
|
|
92
|
+
API_CRON_AUTOMATION_EXECUTIVE_CHECKIN=* 5 * * *
|
|
93
|
+
API_CRON_ORGANIZATION_ARTIFACTS_WEEKLY=* 5 * * *
|
|
94
|
+
API_CRON_ORGANIZATION_ARTIFACTS_DAILY=* 5 * * *
|
|
95
|
+
API_CRON_ENRICH_TEAM_ARTIFACTS_WEEKLY=* 5 * * *
|
|
96
|
+
API_CRON_SYNC_CODE_REVIEW_REACTIONS=* 5 * * *
|
|
97
|
+
API_CRON_KODY_LEARNING=0 0 * * 6
|
|
98
|
+
API_CRON_CHECK_IF_PR_SHOULD_BE_APPROVED=/2 * * * # A CADA 2 MINUTOS;
|
|
99
|
+
## ---- GIT INTEGRATIONS ----
|
|
100
|
+
|
|
101
|
+
CODE_MANAGEMENT_SECRET=
|
|
102
|
+
CODE_MANAGEMENT_WEBHOOK_TOKEN=
|
|
103
|
+
|
|
104
|
+
# GitHub Settings (Fill only if using GitHub)
|
|
105
|
+
API_GITHUB_CODE_MANAGEMENT_WEBHOOK= # GitHub webhook URL
|
|
106
|
+
API_GITHUB_APP_ID= # GitHub App ID
|
|
107
|
+
API_GITHUB_CLIENT_SECRET= # GitHub App Client Secret
|
|
108
|
+
API_GITHUB_PRIVATE_KEY="" # GitHub App Private Key
|
|
109
|
+
WEB_GITHUB_INSTALL_URL="" # GitHub App Installation URL
|
|
110
|
+
WEB_OAUTH_GITHUB_CLIENT_ID="" # GitHub OAuth Client ID
|
|
111
|
+
WEB_OAUTH_GITHUB_CLIENT_SECRET="" # GitHub OAuth Client Secret
|
|
112
|
+
|
|
113
|
+
# GitLab Settings (Fill only if using GitLab)
|
|
114
|
+
API_GITLAB_TOKEN_URL="https://gitlab.com/oauth/token"
|
|
115
|
+
API_GITLAB_CODE_MANAGEMENT_WEBHOOK= # GitLab webhook URL
|
|
116
|
+
WEB_GITLAB_SCOPES="read_api read_user read_repository"
|
|
117
|
+
WEB_GITLAB_OAUTH_URL="https://gitlab.com/oauth/authorize"
|
|
118
|
+
WEB_OAUTH_GITLAB_CLIENT_ID="" # GitLab OAuth Client ID
|
|
119
|
+
WEB_OAUTH_GITLAB_CLIENT_SECRET="" # GitLab OAuth Client Secret
|
|
120
|
+
|
|
121
|
+
# Bitbucket Settings (Fill only if using Bitbucket)
|
|
122
|
+
WEB_BITBUCKET_INSTALL_URL="" # Bitbucket Installation URL
|
|
123
|
+
GLOBAL_BITBUCKET_CODE_MANAGEMENT_WEBHOOK= # Bitbucket webhook URL
|
|
124
|
+
|
|
125
|
+
## ---- ADDITIONAL INTEGRATIONS ----
|
|
126
|
+
|
|
127
|
+
# Communication Integrations
|
|
128
|
+
WEB_CONNECTION_SLACK="" # Slack connection URL
|
|
129
|
+
WEB_CONNECTION_DISCORD="" # Discord connection URL
|
|
130
|
+
|
|
131
|
+
# JIRA Integration
|
|
132
|
+
WEB_JIRA_SCOPES="read%3Aissue-type%3Ajira%20read%3Aproject%3Ajira%20read%3Aproject.property%3Ajira%20read%3Auser%3Ajira%20read%3Aapplication-role%3Ajira%20read%3Aavatar%3Ajira%20read%3Agroup%3Ajira%20read%3Aissue-type-hierarchy%3Ajira%20read%3Aproject-category%3Ajira%20read%3Aproject-version%3Ajira%20read%3Aproject.component%3Ajira%20read%3Aissue-details%3Ajira%20read%3Aaudit-log%3Ajira%20read%3Afield-configuration%3Ajira%20read%3Aissue-meta%3Ajira%20read%3Aissue-security-level%3Ajira%20read%3Aissue.vote%3Ajira%20read%3Aissue.changelog%3Ajira%20read%3Aissue%3Ajira%20read%3Astatus%3Ajira%20read%3Afield%3Ajira%20write%3Awebhook%3Ajira%20read%3Awebhook%3Ajira%20read%3Aissue-status%3Ajira%20read%3Aboard-scope.admin%3Ajira-software%20read%3Ajql%3Ajira%20delete%3Awebhook%3Ajira%20read%3Acomment.property%3Ajira%20read%3Aproject-role%3Ajira%20read%3Aepic%3Ajira-software%20read%3Aboard-scope%3Ajira-software%20read%3Asprint%3Ajira-software%20read%3Afield.default-value%3Ajira%20read%3Afield.option%3Ajira%20read%3Aissue%3Ajira-software%20read%3Acomment%3Ajira%20read%3Aattachment%3Ajira%20read%3Aissue-worklog%3Ajira%20write%3Aissue-link-type%3Ajira%20write%3Afield%3Ajira%20write%3Aworkflow%3Ajira%20write%3Aproject%3Ajira"
|
|
133
|
+
|
|
134
|
+
# Support Settings
|
|
135
|
+
WEB_ANALYTICS_HOSTNAME="" # Analytics hostname
|
|
136
|
+
WEB_SUPPORT_DOCS_URL="https://docs.kodus.io" # Documentation URL
|
|
137
|
+
WEB_SUPPORT_DISCORD_INVITE_URL="https://discord.gg/CceCdAke" # Discord invite URL
|
|
138
|
+
WEB_SUPPORT_TALK_TO_FOUNDER_URL="https://cal.com/gabrielmalinosqui/30min" # Scheduling URL
|
|
139
|
+
|
|
140
|
+
# RabbitMQ Configuration
|
|
141
|
+
API_RABBITMQ_URI= # RabbitMQ connection URI
|
|
142
|
+
API_RABBITMQ_ENABLED=false # Enable/disable RabbitMQ
|