infra-kit 0.1.58 → 0.1.59
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.js +15 -15
- package/dist/cli.js.map +4 -4
- package/dist/mcp.js +15 -15
- package/dist/mcp.js.map +4 -4
- package/package.json +7 -6
- package/src/commands/{gh-release-deploy/gh-release-deploy.ts → gh-release-deploy-all/gh-release-deploy-all.ts} +5 -5
- package/src/commands/gh-release-deploy-all/index.ts +1 -0
- package/src/commands/gh-release-deploy-service/gh-release-deploy-service.ts +159 -0
- package/src/commands/gh-release-deploy-service/index.ts +1 -0
- package/src/commands/release-create/release-create.ts +1 -1
- package/src/entry/cli.ts +14 -3
- package/src/lib/git-utils/git-utils.ts +1 -0
- package/src/lib/load-env/load-env.ts +4 -4
- package/src/mcp/tools/index.ts +4 -2
- package/src/commands/gh-release-deploy/index.ts +0 -1
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "infra-kit",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.59",
|
|
5
5
|
"description": "infra-kit",
|
|
6
6
|
"main": "dist/cli.js",
|
|
7
7
|
"module": "dist/cli.js",
|
|
@@ -30,21 +30,22 @@
|
|
|
30
30
|
"fix": "pnpm run prettier-fix && pnpm run eslint-fix && pnpm run qa"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@inquirer/checkbox": "^5.0.
|
|
34
|
-
"@inquirer/confirm": "^6.0.
|
|
35
|
-
"@inquirer/select": "^5.0.
|
|
36
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
33
|
+
"@inquirer/checkbox": "^5.0.3",
|
|
34
|
+
"@inquirer/confirm": "^6.0.3",
|
|
35
|
+
"@inquirer/select": "^5.0.3",
|
|
36
|
+
"@modelcontextprotocol/sdk": "^1.25.1",
|
|
37
37
|
"commander": "^14.0.2",
|
|
38
38
|
"dotenv": "^17.2.3",
|
|
39
39
|
"pino": "^10.1.0",
|
|
40
40
|
"pino-pretty": "^13.1.3",
|
|
41
|
+
"yaml": "^2.7.0",
|
|
41
42
|
"zod": "^3.25.76",
|
|
42
43
|
"zx": "^8.8.5"
|
|
43
44
|
},
|
|
44
45
|
"devDependencies": {
|
|
45
46
|
"@pkg/eslint-config": "workspace:*",
|
|
46
47
|
"@pkg/vitest-config": "workspace:*",
|
|
47
|
-
"esbuild": "^0.27.
|
|
48
|
+
"esbuild": "^0.27.2",
|
|
48
49
|
"typescript": "^5.9.3"
|
|
49
50
|
}
|
|
50
51
|
}
|
|
@@ -8,7 +8,7 @@ import { ENVs } from 'src/lib/constants'
|
|
|
8
8
|
import { logger } from 'src/lib/logger'
|
|
9
9
|
import type { ToolsExecutionResult } from 'src/types'
|
|
10
10
|
|
|
11
|
-
interface
|
|
11
|
+
interface GhReleaseDeployAllArgs {
|
|
12
12
|
version: string
|
|
13
13
|
env: string
|
|
14
14
|
}
|
|
@@ -16,7 +16,7 @@ interface GhReleaseDeployArgs {
|
|
|
16
16
|
/**
|
|
17
17
|
* Deploy a release branch to an environment
|
|
18
18
|
*/
|
|
19
|
-
export const
|
|
19
|
+
export const ghReleaseDeployAll = async (args: GhReleaseDeployAllArgs): Promise<ToolsExecutionResult> => {
|
|
20
20
|
const { version, env } = args
|
|
21
21
|
|
|
22
22
|
// TODO: add validation for semver version for version variable
|
|
@@ -100,8 +100,8 @@ export const ghReleaseDeploy = async (args: GhReleaseDeployArgs): Promise<ToolsE
|
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
// MCP Tool Registration
|
|
103
|
-
export const
|
|
104
|
-
name: 'gh-release-deploy',
|
|
103
|
+
export const ghReleaseDeployAllMcpTool = {
|
|
104
|
+
name: 'gh-release-deploy-all',
|
|
105
105
|
description: 'Deploy a release branch to a specified environment',
|
|
106
106
|
inputSchema: {
|
|
107
107
|
version: z.string().describe('Version to deploy (e.g., "1.2.5")'),
|
|
@@ -113,5 +113,5 @@ export const ghReleaseDeployMcpTool = {
|
|
|
113
113
|
environment: z.string().describe('The environment deployed to'),
|
|
114
114
|
success: z.boolean().describe('Whether the deployment was successful'),
|
|
115
115
|
},
|
|
116
|
-
handler:
|
|
116
|
+
handler: ghReleaseDeployAll,
|
|
117
117
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { ghReleaseDeployAll, ghReleaseDeployAllMcpTool } from './gh-release-deploy-all'
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import select from '@inquirer/select'
|
|
2
|
+
import fs from 'node:fs/promises'
|
|
3
|
+
import { resolve } from 'node:path'
|
|
4
|
+
import process from 'node:process'
|
|
5
|
+
import yaml from 'yaml'
|
|
6
|
+
import { z } from 'zod'
|
|
7
|
+
import { $ } from 'zx'
|
|
8
|
+
|
|
9
|
+
import { getReleasePRs } from 'src/integrations/gh'
|
|
10
|
+
import { ENVs } from 'src/lib/constants'
|
|
11
|
+
import { getProjectRoot } from 'src/lib/git-utils'
|
|
12
|
+
import { logger } from 'src/lib/logger'
|
|
13
|
+
import type { ToolsExecutionResult } from 'src/types'
|
|
14
|
+
|
|
15
|
+
interface GhReleaseDeployServiceArgs {
|
|
16
|
+
version: string
|
|
17
|
+
env: string
|
|
18
|
+
service: string
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Deploy a specific service in a release branch to an environment
|
|
23
|
+
*/
|
|
24
|
+
export const ghReleaseDeployService = async (args: GhReleaseDeployServiceArgs): Promise<ToolsExecutionResult> => {
|
|
25
|
+
const { version, env, service } = args
|
|
26
|
+
|
|
27
|
+
// TODO: add validation for semver version for version variable
|
|
28
|
+
|
|
29
|
+
const releasePRsList: string[] = ['dev'] // ["release/v1.8.0", "release/v1.9.0"]
|
|
30
|
+
|
|
31
|
+
const releasePRs = await getReleasePRs()
|
|
32
|
+
|
|
33
|
+
releasePRsList.push(...releasePRs)
|
|
34
|
+
|
|
35
|
+
let selectedReleaseBranch = '' // "release/v1.8.0"
|
|
36
|
+
|
|
37
|
+
if (version) {
|
|
38
|
+
selectedReleaseBranch = `release/v${version}`
|
|
39
|
+
} else {
|
|
40
|
+
selectedReleaseBranch = await select({
|
|
41
|
+
message: '🌿 Select release branch',
|
|
42
|
+
choices: releasePRsList.map((pr) => ({
|
|
43
|
+
name: pr.replace('release/v', ''),
|
|
44
|
+
value: pr,
|
|
45
|
+
})),
|
|
46
|
+
})
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Check if release branch exists in the list
|
|
50
|
+
if (!releasePRsList.includes(selectedReleaseBranch)) {
|
|
51
|
+
logger.error(`❌ Release branch ${selectedReleaseBranch} not found in open PRs. Exiting...`)
|
|
52
|
+
process.exit(1)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
let selectedEnv = ''
|
|
56
|
+
|
|
57
|
+
if (env) {
|
|
58
|
+
selectedEnv = env
|
|
59
|
+
} else {
|
|
60
|
+
selectedEnv = await select({
|
|
61
|
+
message: '🧪 Select environment',
|
|
62
|
+
choices: ENVs.map((env) => ({
|
|
63
|
+
name: env,
|
|
64
|
+
value: env,
|
|
65
|
+
})),
|
|
66
|
+
})
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (!ENVs.includes(selectedEnv)) {
|
|
70
|
+
logger.error(`❌ Invalid environment: ${selectedEnv}. Exiting...`)
|
|
71
|
+
process.exit(1)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Parse available services from workflow file
|
|
75
|
+
const availableServices = await parseServicesFromWorkflow()
|
|
76
|
+
|
|
77
|
+
let selectedService = ''
|
|
78
|
+
|
|
79
|
+
if (service) {
|
|
80
|
+
selectedService = service
|
|
81
|
+
} else {
|
|
82
|
+
selectedService = await select({
|
|
83
|
+
message: '🚀 Select service to deploy',
|
|
84
|
+
choices: availableServices.map((svc) => ({
|
|
85
|
+
name: svc,
|
|
86
|
+
value: svc,
|
|
87
|
+
})),
|
|
88
|
+
})
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (!availableServices.includes(selectedService)) {
|
|
92
|
+
logger.error(`❌ Invalid service: ${selectedService}. Available services: ${availableServices.join(', ')}`)
|
|
93
|
+
process.exit(1)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
try {
|
|
97
|
+
$.quiet = true
|
|
98
|
+
|
|
99
|
+
await $`gh workflow run deploy-single-service.yml --ref ${selectedReleaseBranch} -f environment=${selectedEnv} -f service=${selectedService}`
|
|
100
|
+
|
|
101
|
+
$.quiet = false
|
|
102
|
+
|
|
103
|
+
logger.info(
|
|
104
|
+
`Successfully launched deploy-single-service workflow_dispatch for release branch: ${selectedReleaseBranch}, environment: ${selectedEnv}, service: ${selectedService}`,
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
const structuredContent = {
|
|
108
|
+
releaseBranch: selectedReleaseBranch,
|
|
109
|
+
version: selectedReleaseBranch.replace('release/v', ''),
|
|
110
|
+
environment: selectedEnv,
|
|
111
|
+
service: selectedService,
|
|
112
|
+
success: true,
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return {
|
|
116
|
+
content: [
|
|
117
|
+
{
|
|
118
|
+
type: 'text',
|
|
119
|
+
text: JSON.stringify(structuredContent, null, 2),
|
|
120
|
+
},
|
|
121
|
+
],
|
|
122
|
+
structuredContent,
|
|
123
|
+
}
|
|
124
|
+
} catch (error: unknown) {
|
|
125
|
+
logger.error({ error }, '❌ Error launching workflow')
|
|
126
|
+
process.exit(1)
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Parse available services from the workflow file
|
|
132
|
+
*/
|
|
133
|
+
const parseServicesFromWorkflow = async (): Promise<string[]> => {
|
|
134
|
+
const projectRoot = await getProjectRoot()
|
|
135
|
+
const workflowPath = resolve(projectRoot, '.github/workflows/deploy-single-service.yml')
|
|
136
|
+
const content = await fs.readFile(workflowPath, 'utf-8')
|
|
137
|
+
const parsed = yaml.parse(content)
|
|
138
|
+
|
|
139
|
+
return parsed.on.workflow_dispatch.inputs.service.options
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// MCP Tool Registration
|
|
143
|
+
export const ghReleaseDeployServiceMcpTool = {
|
|
144
|
+
name: 'gh-release-deploy-service',
|
|
145
|
+
description: 'Deploy a specific service in a release branch to a specified environment',
|
|
146
|
+
inputSchema: {
|
|
147
|
+
version: z.string().describe('Version to deploy (e.g., "1.2.5")'),
|
|
148
|
+
env: z.string().describe('Environment to deploy to (e.g., "dev", "renana", "oriana")'),
|
|
149
|
+
service: z.string().describe('Service to deploy (e.g., "client-be", "client-fe")'),
|
|
150
|
+
},
|
|
151
|
+
outputSchema: {
|
|
152
|
+
releaseBranch: z.string().describe('The release branch that was deployed'),
|
|
153
|
+
version: z.string().describe('The version that was deployed'),
|
|
154
|
+
environment: z.string().describe('The environment deployed to'),
|
|
155
|
+
service: z.string().describe('The service that was deployed'),
|
|
156
|
+
success: z.boolean().describe('Whether the deployment was successful'),
|
|
157
|
+
},
|
|
158
|
+
handler: ghReleaseDeployService,
|
|
159
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { ghReleaseDeployService, ghReleaseDeployServiceMcpTool } from './gh-release-deploy-service'
|
|
@@ -32,7 +32,7 @@ export const releaseCreate = async (args: ReleaseCreateArgs): Promise<ToolsExecu
|
|
|
32
32
|
version = await question('Enter version (e.g. 1.2.5): ')
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
// Validate input
|
|
35
|
+
// Validate input (validate the version is a valid semver)
|
|
36
36
|
if (!version || version.trim() === '') {
|
|
37
37
|
logger.error('No version provided. Exiting...')
|
|
38
38
|
process.exit(1)
|
package/src/entry/cli.ts
CHANGED
|
@@ -3,7 +3,8 @@ import { Command } from 'commander'
|
|
|
3
3
|
// Commands
|
|
4
4
|
import { ghMergeDev } from 'src/commands/gh-merge-dev'
|
|
5
5
|
import { ghReleaseDeliver } from 'src/commands/gh-release-deliver'
|
|
6
|
-
import {
|
|
6
|
+
import { ghReleaseDeployAll } from 'src/commands/gh-release-deploy-all'
|
|
7
|
+
import { ghReleaseDeployService } from 'src/commands/gh-release-deploy-service'
|
|
7
8
|
import { ghReleaseList } from 'src/commands/gh-release-list'
|
|
8
9
|
import { releaseCreate } from 'src/commands/release-create'
|
|
9
10
|
import { releaseCreateBatch } from 'src/commands/release-create-batch'
|
|
@@ -67,12 +68,22 @@ program
|
|
|
67
68
|
})
|
|
68
69
|
|
|
69
70
|
program
|
|
70
|
-
.command('release-deploy')
|
|
71
|
+
.command('release-deploy-all')
|
|
71
72
|
.description('Deploy any release branch to any environment')
|
|
72
73
|
.option('-v, --version <version>', 'Specify the version to deploy, e.g. 1.2.5')
|
|
73
74
|
.option('-e, --env <env>', 'Specify the environment to deploy to, e.g. dev')
|
|
74
75
|
.action(async (options) => {
|
|
75
|
-
await
|
|
76
|
+
await ghReleaseDeployAll({ version: options.version, env: options.env })
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
program
|
|
80
|
+
.command('release-deploy-service')
|
|
81
|
+
.description('Deploy specific service in release branch to any environment')
|
|
82
|
+
.option('-v, --version <version>', 'Specify the version to deploy, e.g. 1.2.5')
|
|
83
|
+
.option('-e, --env <env>', 'Specify the environment to deploy to, e.g. dev')
|
|
84
|
+
.option('-s, --service <service>', 'Specify the service to deploy, e.g. client-be')
|
|
85
|
+
.action(async (options) => {
|
|
86
|
+
await ghReleaseDeployService({ version: options.version, env: options.env, service: options.service })
|
|
76
87
|
})
|
|
77
88
|
|
|
78
89
|
program
|
|
@@ -2,18 +2,18 @@ import { config } from 'dotenv'
|
|
|
2
2
|
import { resolve } from 'node:path'
|
|
3
3
|
import { $ } from 'zx'
|
|
4
4
|
|
|
5
|
+
import { getProjectRoot } from 'src/lib/git-utils'
|
|
5
6
|
import { logger } from 'src/lib/logger'
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Load .env file from git repository root
|
|
9
|
-
* Uses
|
|
10
|
+
* Uses getProjectRoot to find the repository root, works regardless of where package is installed
|
|
10
11
|
*/
|
|
11
|
-
export async
|
|
12
|
+
export const loadEnvFromGitRoot = async (): Promise<void> => {
|
|
12
13
|
try {
|
|
13
14
|
$.quiet = true
|
|
14
15
|
|
|
15
|
-
const
|
|
16
|
-
const gitRoot = result.stdout.trim()
|
|
16
|
+
const gitRoot = await getProjectRoot()
|
|
17
17
|
|
|
18
18
|
config({ path: resolve(gitRoot, '.env'), quiet: true })
|
|
19
19
|
|
package/src/mcp/tools/index.ts
CHANGED
|
@@ -2,7 +2,8 @@ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
|
|
|
2
2
|
|
|
3
3
|
import { ghMergeDevMcpTool } from 'src/commands/gh-merge-dev'
|
|
4
4
|
import { ghReleaseDeliverMcpTool } from 'src/commands/gh-release-deliver'
|
|
5
|
-
import {
|
|
5
|
+
import { ghReleaseDeployAllMcpTool } from 'src/commands/gh-release-deploy-all'
|
|
6
|
+
import { ghReleaseDeployServiceMcpTool } from 'src/commands/gh-release-deploy-service'
|
|
6
7
|
import { ghReleaseListMcpTool } from 'src/commands/gh-release-list'
|
|
7
8
|
import { releaseCreateMcpTool } from 'src/commands/release-create'
|
|
8
9
|
import { releaseCreateBatchMcpTool } from 'src/commands/release-create-batch'
|
|
@@ -17,7 +18,8 @@ const tools = [
|
|
|
17
18
|
releaseCreateMcpTool,
|
|
18
19
|
releaseCreateBatchMcpTool,
|
|
19
20
|
ghReleaseDeliverMcpTool,
|
|
20
|
-
|
|
21
|
+
ghReleaseDeployAllMcpTool,
|
|
22
|
+
ghReleaseDeployServiceMcpTool,
|
|
21
23
|
ghReleaseListMcpTool,
|
|
22
24
|
worktreesAddMcpTool,
|
|
23
25
|
worktreesListMcpTool,
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { ghReleaseDeploy, ghReleaseDeployMcpTool } from './gh-release-deploy'
|