infra-kit 0.1.50 → 0.1.52

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.
@@ -4,7 +4,7 @@ import { z } from 'zod'
4
4
  import { $ } from 'zx'
5
5
 
6
6
  import { ENVs } from 'src/lib/constants'
7
- import { getReleasePRs } from 'src/lib/gh-release-prs'
7
+ import { getReleasePRs } from 'src/integrations/gh'
8
8
  import { logger } from 'src/lib/logger'
9
9
  import type { ToolsExecutionResult } from 'src/types'
10
10
 
@@ -1,6 +1,6 @@
1
1
  import { z } from 'zod'
2
2
 
3
- import { getReleasePRs } from 'src/lib/gh-release-prs'
3
+ import { getReleasePRs } from 'src/integrations/gh'
4
4
  import { logger } from 'src/lib/logger'
5
5
  import type { ToolsExecutionResult } from 'src/types'
6
6
 
@@ -5,7 +5,7 @@ import { z } from 'zod'
5
5
  import { $ } from 'zx'
6
6
 
7
7
  import { WORKTREES_DIR_SUFFIX } from 'src/lib/constants'
8
- import { getReleasePRs } from 'src/lib/gh-release-prs'
8
+ import { getReleasePRs } from 'src/integrations/gh'
9
9
  import { getCurrentWorktrees, getProjectRoot } from 'src/lib/git-utils'
10
10
  import { logger } from 'src/lib/logger'
11
11
  import type { RequiredConfirmedOptionArg, ToolsExecutionResult } from 'src/types'
@@ -4,7 +4,7 @@ import { z } from 'zod'
4
4
  import { $ } from 'zx'
5
5
 
6
6
  import { WORKTREES_DIR_SUFFIX } from 'src/lib/constants'
7
- import { getReleasePRs } from 'src/lib/gh-release-prs'
7
+ import { getReleasePRs } from 'src/integrations/gh'
8
8
  import { getCurrentWorktrees, getProjectRoot } from 'src/lib/git-utils'
9
9
  import { logger } from 'src/lib/logger'
10
10
  import type { RequiredConfirmedOptionArg, ToolsExecutionResult } from 'src/types'
package/src/entry/cli.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import { loadEnvFromGitRoot } from 'src/lib/load-env'
2
+
1
3
  import { Command } from 'commander'
2
4
 
3
5
  // Commands
@@ -13,6 +15,9 @@ import { worktreesSync } from 'src/commands/worktrees-sync'
13
15
  // Integrations
14
16
  import { validateGitHubCliAndAuth } from 'src/integrations/gh'
15
17
 
18
+ // Load .env before anything else
19
+ await loadEnvFromGitRoot()
20
+
16
21
  const program = new Command()
17
22
 
18
23
  program
package/src/entry/mcp.ts CHANGED
@@ -1,3 +1,6 @@
1
+ /* eslint-disable antfu/no-top-level-await */
2
+ import { loadEnvFromGitRoot } from 'src/lib/load-env'
3
+
1
4
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
2
5
  import process from 'node:process'
3
6
 
@@ -6,10 +9,14 @@ import { initLoggerMcp } from 'src/lib/logger'
6
9
 
7
10
  import { createMcpServer } from '../mcp/server'
8
11
 
12
+ // Load .env before anything else
13
+ await loadEnvFromGitRoot()
14
+
9
15
  const logger = initLoggerMcp()
10
16
 
11
17
  const startServer = async () => {
12
18
  let server
19
+
13
20
  try {
14
21
  server = await createMcpServer()
15
22
 
@@ -39,3 +39,35 @@ export const getReleasePRs = async (): Promise<string[]> => {
39
39
  process.exit(1)
40
40
  }
41
41
  }
42
+
43
+ // Function to create a release branch
44
+ export const createReleaseBranch = async (
45
+ version: string,
46
+ ): Promise<{ branchName: string; prUrl: string }> => {
47
+ const branchName = `release/v${version}`
48
+
49
+ try {
50
+ await $`git switch dev`
51
+ await $`git pull origin dev`
52
+ await $`git checkout -b ${branchName}`
53
+ await $`git push -u origin ${branchName}`
54
+ await $`git commit --allow-empty-message --allow-empty --message ''`
55
+ await $`git push origin ${branchName}`
56
+
57
+ // Create PR and capture URL
58
+ const prResult =
59
+ await $`gh pr create --title "Release v${version}" --body "Release v${version}" --base dev --head ${branchName}`
60
+
61
+ const prLink = prResult.stdout.trim()
62
+
63
+ await $`git switch dev`
64
+
65
+ return {
66
+ branchName,
67
+ prUrl: prLink,
68
+ }
69
+ } catch (error: unknown) {
70
+ logger.error({ error, branchName }, `Error creating release branch ${branchName}`)
71
+ throw error
72
+ }
73
+ }
@@ -0,0 +1 @@
1
+ export { createReleaseBranch, getReleasePRs } from './gh-release-prs'
@@ -1 +1,2 @@
1
1
  export { validateGitHubCliAndAuth } from './gh-cli-auth'
2
+ export { createReleaseBranch, getReleasePRs } from './gh-release-prs'
@@ -0,0 +1,136 @@
1
+ import process from 'node:process'
2
+
3
+ import { logger } from 'src/lib/logger'
4
+ import type {
5
+ CreateJiraVersionParams,
6
+ CreateJiraVersionResult,
7
+ JiraConfig,
8
+ JiraVersion,
9
+ } from './types.js'
10
+
11
+ /**
12
+ * Creates a new version in Jira using the REST API
13
+ * @param params - Version creation parameters
14
+ * @param config - Jira configuration (baseUrl, token, projectId)
15
+ * @returns Result containing created version or error
16
+ */
17
+ export const createJiraVersion = async (
18
+ params: CreateJiraVersionParams,
19
+ config: JiraConfig,
20
+ ): Promise<CreateJiraVersionResult> => {
21
+ try {
22
+ const { baseUrl, token, email, projectId } = config
23
+
24
+ // Use current date if not provided
25
+ // const releaseDate =
26
+ // params.releaseDate || new Date().toISOString().split('T')[0] // 2025-12-06
27
+
28
+ // Prepare request body
29
+ const requestBody = {
30
+ name: params.name,
31
+ projectId: params.projectId || projectId,
32
+ description: params.description || '',
33
+ // releaseDate,
34
+ released: params.released ?? true,
35
+ archived: params.archived ?? false,
36
+ }
37
+
38
+ // logger.info(
39
+ // { version: params.name, projectId: requestBody.projectId },
40
+ // 'Creating Jira version',
41
+ // )
42
+
43
+ // Make API request
44
+ const url = `${baseUrl}/rest/api/3/version`
45
+
46
+ // Create Basic auth credentials
47
+ const credentials = btoa(`${email}:${token}`)
48
+
49
+ const response = await fetch(url, {
50
+ method: 'POST',
51
+ headers: {
52
+ Accept: 'application/json',
53
+ 'Content-Type': 'application/json',
54
+ Authorization: `Basic ${credentials}`,
55
+ },
56
+ body: JSON.stringify(requestBody),
57
+ })
58
+
59
+ if (!response.ok) {
60
+ const errorText = await response.text()
61
+ logger.error(
62
+ {
63
+ status: response.status,
64
+ statusText: response.statusText,
65
+ error: errorText,
66
+ },
67
+ 'Failed to create Jira version',
68
+ )
69
+
70
+ return {
71
+ success: false,
72
+ error: `HTTP ${response.status}: ${response.statusText}`,
73
+ }
74
+ }
75
+
76
+ const version = (await response.json()) as JiraVersion
77
+
78
+ // logger.info(
79
+ // { versionId: version.id, versionName: version.name },
80
+ // 'Successfully created Jira version',
81
+ // )
82
+
83
+ return {
84
+ success: true,
85
+ version,
86
+ }
87
+ } catch (error) {
88
+ logger.error({ error }, 'Error creating Jira version')
89
+
90
+ return {
91
+ success: false,
92
+ error: error instanceof Error ? error.message : String(error),
93
+ }
94
+ }
95
+ }
96
+
97
+ /**
98
+ * Loads Jira configuration from environment variables
99
+ * @returns Jira config if all required env vars are present, null otherwise
100
+ */
101
+ export const loadJiraConfig = (): JiraConfig | null => {
102
+ const baseUrl = process.env.JIRA_BASE_URL
103
+ const token = process.env.JIRA_TOKEN || process.env.JIRA_API_TOKEN
104
+ const projectIdStr = process.env.JIRA_PROJECT_ID
105
+ const email = process.env.JIRA_EMAIL
106
+
107
+ if (!baseUrl || !token || !projectIdStr || !email) {
108
+ logger.debug(
109
+ {
110
+ hasBaseUrl: !!baseUrl,
111
+ hasToken: !!token,
112
+ hasProjectId: !!projectIdStr,
113
+ hasEmail: !!email,
114
+ },
115
+ 'Jira configuration incomplete, skipping Jira integration',
116
+ )
117
+ return null
118
+ }
119
+
120
+ const projectId = Number.parseInt(projectIdStr, 10)
121
+
122
+ if (Number.isNaN(projectId)) {
123
+ logger.warn(
124
+ { projectIdStr },
125
+ 'Invalid JIRA_PROJECT_ID (must be numeric), skipping Jira integration',
126
+ )
127
+ return null
128
+ }
129
+
130
+ return {
131
+ baseUrl: baseUrl.replace(/\/$/, ''), // Remove trailing slash
132
+ token,
133
+ projectId,
134
+ email,
135
+ }
136
+ }
@@ -0,0 +1,7 @@
1
+ export { createJiraVersion, loadJiraConfig } from './api.js'
2
+ export type {
3
+ CreateJiraVersionParams,
4
+ CreateJiraVersionResult,
5
+ JiraConfig,
6
+ JiraVersion,
7
+ } from './types.js'
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Jira Version API types
3
+ */
4
+
5
+ export interface JiraVersion {
6
+ /** ID of the version */
7
+ id: string
8
+ /** URL of the version */
9
+ self: string
10
+ /** Name of the version */
11
+ name: string
12
+ /** Description of the version */
13
+ description?: string
14
+ /** Whether the version is archived */
15
+ archived: boolean
16
+ /** Whether the version is released */
17
+ released: boolean
18
+ /** Release date in ISO format (YYYY-MM-DD) */
19
+ releaseDate?: string
20
+ /** User-friendly release date */
21
+ userReleaseDate?: string
22
+ /** Project key */
23
+ project?: string
24
+ /** Project ID */
25
+ projectId: number
26
+ }
27
+
28
+ export interface CreateJiraVersionParams {
29
+ /** Name of the version (e.g., "v1.2.5") */
30
+ name: string
31
+ /** Project ID (numeric) */
32
+ projectId: number
33
+ /** Description of the version */
34
+ description?: string
35
+ /** Release date in ISO format (YYYY-MM-DD). Defaults to current date if not provided */
36
+ releaseDate?: string
37
+ /** Whether the version is released. Defaults to true */
38
+ released?: boolean
39
+ /** Whether the version is archived. Defaults to false */
40
+ archived?: boolean
41
+ }
42
+
43
+ export interface JiraConfig {
44
+ /** Jira base URL (e.g., https://your-domain.atlassian.net) */
45
+ baseUrl: string
46
+ /** Jira API token */
47
+ token: string
48
+ /** Jira project ID */
49
+ projectId: number
50
+ /** Email associated with Jira account (for Basic Auth) */
51
+ email: string
52
+ }
53
+
54
+ export interface CreateJiraVersionResult {
55
+ success: boolean
56
+ version?: JiraVersion
57
+ error?: string
58
+ }
@@ -0,0 +1,23 @@
1
+ import { config } from 'dotenv'
2
+ import { resolve } from 'node:path'
3
+ import { $ } from 'zx'
4
+
5
+ /**
6
+ * Load .env file from git repository root
7
+ * Uses git rev-parse to find the repository root, works regardless of where package is installed
8
+ */
9
+ export async function loadEnvFromGitRoot(): Promise<void> {
10
+ try {
11
+ $.quiet = true
12
+
13
+ const result = await $`git rev-parse --show-toplevel`
14
+ const gitRoot = result.stdout.trim()
15
+
16
+ config({ path: resolve(gitRoot, '.env') })
17
+ } catch {
18
+ // Git command failed - not in a git repository or git not available
19
+ // This is acceptable, env vars might be provided another way
20
+ } finally {
21
+ $.quiet = false
22
+ }
23
+ }
@@ -1 +0,0 @@
1
- export { getReleasePRs } from './gh-release-prs'