Skip to content

Commit d22bf4f

Browse files
committed
fix: rename plugin name back + refine jira connection
See: https://semantic-release.gitbook.io/semantic-release/developer-guide/plugin
1 parent 1d46dd7 commit d22bf4f

File tree

6 files changed

+50
-34
lines changed

6 files changed

+50
-34
lines changed

CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ This is a semantic-release plugin that automatically adds comments to JIRA issue
3737
JIRA authentication is configured via environment variables (for security):
3838

3939
```bash
40-
JIRA_HOST=domain.atlassian.net
40+
JIRA_BASE_URL=https://domain.atlassian.net
4141
4242
JIRA_TOKEN=api-token
4343
SEMANTIC_RELEASE_PACKAGE=project-name # set by semantic-release

src/__tests__/index.test.ts

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { addJiraIssueComment, verifyConditions } from '../index';
1+
import { success, verifyConditions } from '../index';
22
import { JiraClient } from '../jira-client';
33
import { IssueExtractor } from '../issue-extractor';
44
import { PluginConfig, Context } from '../types';
@@ -9,7 +9,7 @@ jest.mock('../issue-extractor');
99
const MockedJiraClient = JiraClient as jest.MockedClass<typeof JiraClient>;
1010
const MockedIssueExtractor = IssueExtractor as jest.MockedClass<typeof IssueExtractor>;
1111

12-
describe('addJiraIssueComment', () => {
12+
describe('success', () => {
1313
let pluginConfig: PluginConfig;
1414
let context: Context;
1515
let mockLogger: { log: jest.Mock; error: jest.Mock };
@@ -35,7 +35,7 @@ describe('addJiraIssueComment', () => {
3535
};
3636

3737
// Set up JIRA environment variables
38-
process.env.JIRA_HOST = 'test.atlassian.net';
38+
process.env.JIRA_BASE_URL = 'https://test.atlassian.net';
3939
process.env.JIRA_EMAIL = '[email protected]';
4040
process.env.JIRA_TOKEN = 'test-token';
4141

@@ -55,10 +55,10 @@ describe('addJiraIssueComment', () => {
5555
MockedJiraClient.mockImplementation(() => mockJiraClient as any);
5656
MockedIssueExtractor.mockImplementation(() => mockExtractor as any);
5757

58-
await addJiraIssueComment(pluginConfig, context);
58+
await success(pluginConfig, context);
5959

6060
expect(MockedJiraClient).toHaveBeenCalledWith({
61-
host: 'test.atlassian.net',
61+
baseUrl: 'https://test.atlassian.net',
6262
6363
token: 'test-token'
6464
});
@@ -84,19 +84,19 @@ describe('addJiraIssueComment', () => {
8484

8585
pluginConfig.commentTemplate = 'Released {{version}} with tag {{gitTag}}';
8686

87-
await addJiraIssueComment(pluginConfig, context);
87+
await success(pluginConfig, context);
8888

8989
expect(mockJiraClient.addComment).toHaveBeenCalledWith('ABC-123', 'Released 1.0.0 with tag v1.0.0');
9090
});
9191

9292
it('should handle missing JIRA config gracefully', async () => {
93-
delete process.env.JIRA_HOST;
93+
delete process.env.JIRA_BASE_URL;
9494
delete process.env.JIRA_EMAIL;
9595
delete process.env.JIRA_TOKEN;
9696

97-
await addJiraIssueComment(pluginConfig, context);
97+
await success(pluginConfig, context);
9898

99-
expect(mockLogger.error).toHaveBeenCalledWith('JIRA configuration is missing. Please set JIRA_HOST, JIRA_EMAIL, and JIRA_TOKEN environment variables.');
99+
expect(mockLogger.error).toHaveBeenCalledWith('JIRA configuration is missing. Please set JIRA_BASE_URL, JIRA_EMAIL, and JIRA_TOKEN environment variables.');
100100
});
101101

102102
it('should handle no issues found', async () => {
@@ -106,7 +106,7 @@ describe('addJiraIssueComment', () => {
106106

107107
MockedIssueExtractor.mockImplementation(() => mockExtractor as any);
108108

109-
await addJiraIssueComment(pluginConfig, context);
109+
await success(pluginConfig, context);
110110

111111
expect(mockLogger.log).toHaveBeenCalledWith('No JIRA issues found in commits.');
112112
});
@@ -125,7 +125,7 @@ describe('addJiraIssueComment', () => {
125125
MockedJiraClient.mockImplementation(() => mockJiraClient as any);
126126
MockedIssueExtractor.mockImplementation(() => mockExtractor as any);
127127

128-
await addJiraIssueComment(pluginConfig, context);
128+
await success(pluginConfig, context);
129129

130130
expect(mockJiraClient.addComment).toHaveBeenCalledWith('ABC-123', 'The issue (ABC-123) was included in version 1.0.0 of my-awesome-package 🎉');
131131
});
@@ -146,7 +146,7 @@ describe('addJiraIssueComment', () => {
146146

147147
pluginConfig.commentTemplate = '{{packageName}} {{version}} deployed with {{gitTag}} for {{issueKey}}';
148148

149-
await addJiraIssueComment(pluginConfig, context);
149+
await success(pluginConfig, context);
150150

151151
expect(mockJiraClient.addComment).toHaveBeenCalledWith('ABC-123', 'test-package 1.0.0 deployed with v1.0.0 for ABC-123');
152152
});
@@ -163,7 +163,7 @@ describe('addJiraIssueComment', () => {
163163
MockedJiraClient.mockImplementation(() => mockJiraClient as any);
164164
MockedIssueExtractor.mockImplementation(() => mockExtractor as any);
165165

166-
await addJiraIssueComment(pluginConfig, context);
166+
await success(pluginConfig, context);
167167

168168
expect(mockLogger.error).toHaveBeenCalledWith('Failed to add comment to ABC-123: API Error');
169169
});
@@ -193,7 +193,7 @@ describe('verifyConditions', () => {
193193
};
194194

195195
// Set up JIRA environment variables
196-
process.env.JIRA_HOST = 'test.atlassian.net';
196+
process.env.JIRA_BASE_URL = 'https://test.atlassian.net';
197197
process.env.JIRA_EMAIL = '[email protected]';
198198
process.env.JIRA_TOKEN = 'test-token';
199199

@@ -210,7 +210,7 @@ describe('verifyConditions', () => {
210210
await verifyConditions(pluginConfig, context);
211211

212212
expect(MockedJiraClient).toHaveBeenCalledWith({
213-
host: 'test.atlassian.net',
213+
baseUrl: 'https://test.atlassian.net',
214214
215215
token: 'test-token'
216216
});
@@ -219,11 +219,11 @@ describe('verifyConditions', () => {
219219
expect(mockLogger.log).toHaveBeenCalledWith('JIRA credentials verified successfully');
220220
});
221221

222-
it('should throw error when JIRA_HOST is missing', async () => {
223-
delete process.env.JIRA_HOST;
222+
it('should throw error when JIRA_BASE_URL is missing', async () => {
223+
delete process.env.JIRA_BASE_URL;
224224

225225
await expect(verifyConditions(pluginConfig, context))
226-
.rejects.toThrow('JIRA plugin configuration is invalid:\n - JIRA_HOST environment variable is required');
226+
.rejects.toThrow('JIRA plugin configuration is invalid:\n - JIRA_BASE_URL environment variable is required');
227227
});
228228

229229
it('should throw error when JIRA_EMAIL is missing', async () => {
@@ -241,11 +241,11 @@ describe('verifyConditions', () => {
241241
});
242242

243243
it('should throw error when multiple environment variables are missing', async () => {
244-
delete process.env.JIRA_HOST;
244+
delete process.env.JIRA_BASE_URL;
245245
delete process.env.JIRA_EMAIL;
246246

247247
await expect(verifyConditions(pluginConfig, context))
248-
.rejects.toThrow('JIRA plugin configuration is invalid:\n - JIRA_HOST environment variable is required\n - JIRA_EMAIL environment variable is required');
248+
.rejects.toThrow('JIRA plugin configuration is invalid:\n - JIRA_BASE_URL environment variable is required\n - JIRA_EMAIL environment variable is required');
249249
});
250250

251251
it('should throw error when JIRA authentication fails', async () => {

src/__tests__/jira-client.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ describe('JiraClient', () => {
1616

1717
beforeEach(() => {
1818
config = {
19-
host: 'test.atlassian.net',
19+
baseUrl: 'https://test.atlassian.net',
2020
2121
token: 'test-token'
2222
};
@@ -135,7 +135,7 @@ describe('JiraClient', () => {
135135
mockIsAxiosError.mockReturnValue(true);
136136

137137
await expect(client.getServerInfo())
138-
.rejects.toThrow('Failed to get server info: 401 Unauthorized');
138+
.rejects.toThrow('Failed to get server info from https://test.atlassian.net: 401 Unauthorized');
139139
});
140140
});
141141
});

src/index.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ const DEFAULT_COMMENT_TEMPLATE = 'The issue ({{issueKey}}) was included in versi
66

77
function getJiraConfig(): JiraConfig {
88
return {
9-
host: process.env.JIRA_HOST || '',
9+
baseUrl: process.env.JIRA_BASE_URL || '',
1010
email: process.env.JIRA_EMAIL || '',
1111
token: process.env.JIRA_TOKEN || ''
1212
};
@@ -15,8 +15,8 @@ function getJiraConfig(): JiraConfig {
1515
function validateJiraConfig(jiraConfig: JiraConfig): string[] {
1616
const errors: string[] = [];
1717

18-
if (!jiraConfig.host) {
19-
errors.push('JIRA_HOST environment variable is required');
18+
if (!jiraConfig.baseUrl) {
19+
errors.push('JIRA_BASE_URL environment variable is required');
2020
}
2121

2222
if (!jiraConfig.email) {
@@ -57,7 +57,7 @@ export async function verifyConditions(pluginConfig: PluginConfig, context: Cont
5757
}
5858
}
5959

60-
export async function addJiraIssueComment(pluginConfig: PluginConfig, context: Context): Promise<void> {
60+
export async function success(pluginConfig: PluginConfig, context: Context): Promise<void> {
6161
const { commentTemplate = DEFAULT_COMMENT_TEMPLATE, issuePattern } = pluginConfig;
6262
const { nextRelease, commits, logger } = context;
6363

@@ -66,7 +66,7 @@ export async function addJiraIssueComment(pluginConfig: PluginConfig, context: C
6666
const errors = validateJiraConfig(jiraConfig);
6767

6868
if (errors.length > 0) {
69-
logger.error('JIRA configuration is missing. Please set JIRA_HOST, JIRA_EMAIL, and JIRA_TOKEN environment variables.');
69+
logger.error('JIRA configuration is missing. Please set JIRA_BASE_URL, JIRA_EMAIL, and JIRA_TOKEN environment variables.');
7070
return;
7171
}
7272

@@ -115,4 +115,4 @@ export async function addJiraIssueComment(pluginConfig: PluginConfig, context: C
115115
}
116116

117117
// Export the plugin configuration
118-
export default { verifyConditions, addJiraIssueComment };
118+
export default { verifyConditions, success };

src/jira-client.ts

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,17 @@ export class JiraClient {
55
private client: AxiosInstance;
66

77
constructor(private config: JiraConfig) {
8+
// Ensure baseUrl has proper format and append /rest/api/3 if not already present
9+
let baseUrl = config.baseUrl.replace(/\/$/, ''); // Remove trailing slash
10+
if (!baseUrl.startsWith('http')) {
11+
baseUrl = `https://${baseUrl}`;
12+
}
13+
if (!baseUrl.includes('/rest/api/3')) {
14+
baseUrl = baseUrl + '/rest/api/3';
15+
}
16+
817
this.client = axios.create({
9-
baseURL: `https://${config.host}/rest/api/3`,
18+
baseURL: baseUrl,
1019
headers: {
1120
'Authorization': `Basic ${Buffer.from(`${config.email}:${config.token}`).toString('base64')}`,
1221
'Accept': 'application/json',
@@ -36,7 +45,9 @@ export class JiraClient {
3645
});
3746
} catch (error) {
3847
if (axios.isAxiosError(error)) {
39-
throw new Error(`Failed to add comment to ${issueKey}: ${error.response?.status} ${error.response?.statusText}`);
48+
const status = error.response?.status || 'No response';
49+
const statusText = error.response?.statusText || error.message || 'Unknown error';
50+
throw new Error(`Failed to add comment to ${issueKey}: ${status} ${statusText}`);
4051
}
4152
throw error;
4253
}
@@ -48,7 +59,9 @@ export class JiraClient {
4859
return response.data;
4960
} catch (error) {
5061
if (axios.isAxiosError(error)) {
51-
throw new Error(`Failed to get issue ${issueKey}: ${error.response?.status} ${error.response?.statusText}`);
62+
const status = error.response?.status || 'No response';
63+
const statusText = error.response?.statusText || error.message || 'Unknown error';
64+
throw new Error(`Failed to get issue ${issueKey}: ${status} ${statusText}`);
5265
}
5366
throw error;
5467
}
@@ -60,7 +73,10 @@ export class JiraClient {
6073
return response.data;
6174
} catch (error) {
6275
if (axios.isAxiosError(error)) {
63-
throw new Error(`Failed to get server info: ${error.response?.status} ${error.response?.statusText}`);
76+
const status = error.response?.status || 'No response';
77+
const statusText = error.response?.statusText || error.message || 'Unknown error';
78+
const baseUrl = this.config.baseUrl;
79+
throw new Error(`Failed to get server info from ${baseUrl}: ${status} ${statusText}`);
6480
}
6581
throw error;
6682
}

src/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
export interface JiraConfig {
2-
host: string;
2+
baseUrl: string;
33
email: string;
44
token: string;
55
projectKey?: string;

0 commit comments

Comments
 (0)