@releasehub/cli 1.0.0 → 1.1.0
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/README.md +184 -0
- package/dist/__tests__/ai.test.d.ts +2 -0
- package/dist/__tests__/ai.test.d.ts.map +1 -0
- package/dist/__tests__/ai.test.js +140 -0
- package/dist/__tests__/ai.test.js.map +1 -0
- package/dist/__tests__/formatters.test.d.ts +2 -0
- package/dist/__tests__/formatters.test.d.ts.map +1 -0
- package/dist/__tests__/formatters.test.js +133 -0
- package/dist/__tests__/formatters.test.js.map +1 -0
- package/dist/__tests__/generate.integration.test.d.ts +2 -0
- package/dist/__tests__/generate.integration.test.d.ts.map +1 -0
- package/dist/__tests__/generate.integration.test.js +162 -0
- package/dist/__tests__/generate.integration.test.js.map +1 -0
- package/dist/__tests__/github.test.d.ts +2 -0
- package/dist/__tests__/github.test.d.ts.map +1 -0
- package/dist/__tests__/github.test.js +44 -0
- package/dist/__tests__/github.test.js.map +1 -0
- package/dist/commands/ai.d.ts.map +1 -1
- package/dist/commands/ai.js +8 -3
- package/dist/commands/ai.js.map +1 -1
- package/dist/commands/config.d.ts +3 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +60 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/generate.d.ts +1 -0
- package/dist/commands/generate.d.ts.map +1 -1
- package/dist/commands/generate.js +23 -6
- package/dist/commands/generate.js.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/ai.d.ts.map +1 -1
- package/dist/lib/ai.js +25 -0
- package/dist/lib/ai.js.map +1 -1
- package/dist/lib/config.d.ts +3 -1
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +11 -1
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/github.d.ts.map +1 -1
- package/dist/lib/github.js +3 -2
- package/dist/lib/github.js.map +1 -1
- package/package.json +11 -3
package/README.md
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# ReleaseHub
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@releasehub/cli)
|
|
4
|
+
[](https://www.npmjs.com/package/@releasehub/cli)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
[](https://nodejs.org)
|
|
7
|
+
|
|
8
|
+
> AI-powered release notes from your terminal.
|
|
9
|
+
|
|
10
|
+
ReleaseHub reads your merged pull requests, filters the noise, rewrites technical titles into plain language, and outputs GitHub release notes, a changelog entry, or a Slack message — in one command.
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npx @releasehub/cli generate --from v2.3.0 --to v2.4.0
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install -g @releasehub/cli
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Requires Node.js 18 or later.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Quick start
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
# 1. Connect your GitHub account
|
|
32
|
+
releasehub auth login
|
|
33
|
+
|
|
34
|
+
# 2. Add your AI key (Anthropic or OpenAI)
|
|
35
|
+
releasehub ai add-key
|
|
36
|
+
|
|
37
|
+
# 3. Generate release notes
|
|
38
|
+
releasehub generate --from v2.3.0 --to v2.4.0
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Output formats
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# GitHub Release markdown (default)
|
|
47
|
+
releasehub generate --from v2.3.0 --to v2.4.0 --format github-release
|
|
48
|
+
|
|
49
|
+
# Keep a Changelog format
|
|
50
|
+
releasehub generate --from v2.3.0 --to v2.4.0 --format changelog
|
|
51
|
+
|
|
52
|
+
# Compact Slack message
|
|
53
|
+
releasehub generate --from v2.3.0 --to v2.4.0 --format slack
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**Example output** (`--format github-release`):
|
|
57
|
+
|
|
58
|
+
```markdown
|
|
59
|
+
## v2.4.0
|
|
60
|
+
|
|
61
|
+
This release includes 2 new features, 3 improvements and 1 bug fix.
|
|
62
|
+
|
|
63
|
+
### ✨ New Features
|
|
64
|
+
|
|
65
|
+
- You can now export reports as CSV directly from the dashboard
|
|
66
|
+
- Added keyboard shortcuts for the most common actions
|
|
67
|
+
|
|
68
|
+
### 🔧 Improvements
|
|
69
|
+
|
|
70
|
+
- Search results now load noticeably faster
|
|
71
|
+
- Dark mode contrast improved across all pages
|
|
72
|
+
- Notification preferences are easier to find in settings
|
|
73
|
+
|
|
74
|
+
### 🐛 Bug Fixes
|
|
75
|
+
|
|
76
|
+
- Fixed an issue where file uploads would silently fail on slow connections
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Write to a file
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
releasehub generate --from v2.3.0 --to v2.4.0 --output RELEASE.md
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Publish as a GitHub Release
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
releasehub generate --from v2.3.0 --to v2.4.0 --publish
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Use in CI (GitHub Actions)
|
|
94
|
+
|
|
95
|
+
```yaml
|
|
96
|
+
- name: Generate release notes
|
|
97
|
+
env:
|
|
98
|
+
RELEASEHUB_GITHUB_TOKEN: ${{ secrets.RELEASEHUB_GITHUB_TOKEN }}
|
|
99
|
+
RELEASEHUB_ANTHROPIC_KEY: ${{ secrets.RELEASEHUB_ANTHROPIC_KEY }}
|
|
100
|
+
run: |
|
|
101
|
+
npx @releasehub/cli generate \
|
|
102
|
+
--from ${{ github.event.release.target_commitish }} \
|
|
103
|
+
--to ${{ github.ref_name }} \
|
|
104
|
+
--format github-release \
|
|
105
|
+
--quiet \
|
|
106
|
+
--output release-notes.md
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## Commands
|
|
112
|
+
|
|
113
|
+
| Command | Description |
|
|
114
|
+
|---|---|
|
|
115
|
+
| `releasehub auth login` | Connect your GitHub account via OAuth |
|
|
116
|
+
| `releasehub auth logout` | Disconnect and remove saved token |
|
|
117
|
+
| `releasehub ai add-key` | Add an Anthropic or OpenAI key |
|
|
118
|
+
| `releasehub ai switch` | Switch active AI provider |
|
|
119
|
+
| `releasehub ai status` | Show provider status and validate keys |
|
|
120
|
+
| `releasehub generate` | Generate release notes from merged PRs |
|
|
121
|
+
|
|
122
|
+
### `generate` flags
|
|
123
|
+
|
|
124
|
+
| Flag | Default | Description |
|
|
125
|
+
|---|---|---|
|
|
126
|
+
| `--from <tag>` | required | Start tag |
|
|
127
|
+
| `--to <tag>` | required | End tag |
|
|
128
|
+
| `--repo <owner/name>` | auto-detect | Repository (defaults to git remote) |
|
|
129
|
+
| `--format <format>` | `github-release` | `github-release` \| `changelog` \| `slack` |
|
|
130
|
+
| `--output <file>` | stdout | Write output to a file |
|
|
131
|
+
| `--publish` | — | Publish as a GitHub Release |
|
|
132
|
+
| `--quiet` | — | Suppress progress output (CI mode) |
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## AI providers
|
|
137
|
+
|
|
138
|
+
| Provider | Model | Set key via |
|
|
139
|
+
|---|---|---|
|
|
140
|
+
| Anthropic | claude-sonnet-4-6 | `releasehub ai add-key` or `RELEASEHUB_ANTHROPIC_KEY` |
|
|
141
|
+
| OpenAI | gpt-4o | `releasehub ai add-key` or `RELEASEHUB_OPENAI_KEY` |
|
|
142
|
+
|
|
143
|
+
Anthropic is the default. Switch with `releasehub ai switch`.
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## Environment variables
|
|
148
|
+
|
|
149
|
+
| Variable | Description |
|
|
150
|
+
|---|---|
|
|
151
|
+
| `RELEASEHUB_GITHUB_TOKEN` | GitHub personal access token (alternative to `auth login`) |
|
|
152
|
+
| `RELEASEHUB_ANTHROPIC_KEY` | Anthropic API key |
|
|
153
|
+
| `RELEASEHUB_OPENAI_KEY` | OpenAI API key |
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Repo structure
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
releasehub/
|
|
161
|
+
├── apps/
|
|
162
|
+
│ └── web/ # Landing page + docs (React + Vite)
|
|
163
|
+
├── packages/
|
|
164
|
+
│ └── cli/ # @releasehub/cli npm package
|
|
165
|
+
└── planning/ # Product docs, milestones, architecture
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## Support
|
|
171
|
+
|
|
172
|
+
If ReleaseHub saves you time, consider buying me a coffee:
|
|
173
|
+
|
|
174
|
+
<a href="https://www.buymeacoffee.com/beratbozkurt0" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me a Coffee" style="height: 60px !important;width: 217px !important;" ></a>
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## License
|
|
179
|
+
|
|
180
|
+
MIT — see [LICENSE](LICENSE).
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
Built by [@berat](https://twitter.com/beratbuilds)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/ai.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
+
// parseResponse is not exported — test it indirectly via the output shape
|
|
3
|
+
// We test the logic that surrounds AI calls: prompt building and response parsing
|
|
4
|
+
// ─── buildUserPrompt (extracted logic) ────────────────────────────────────────
|
|
5
|
+
function buildUserPrompt(prs) {
|
|
6
|
+
const list = prs.map(pr => {
|
|
7
|
+
const labels = pr.labels.length ? `\nLabels: ${pr.labels.join(', ')}` : '';
|
|
8
|
+
const issues = pr.linked_issues.length ? `\nLinked issues: ${pr.linked_issues.join(', ')}` : '';
|
|
9
|
+
const body = pr.body ? `\nBody: ${pr.body.slice(0, 300)}` : '';
|
|
10
|
+
return `#${pr.number}: ${pr.title}${labels}${issues}${body}`;
|
|
11
|
+
}).join('\n\n');
|
|
12
|
+
return `Analyze these ${prs.length} pull requests:\n\n${list}`;
|
|
13
|
+
}
|
|
14
|
+
// ─── parseResponse (extracted logic) ──────────────────────────────────────────
|
|
15
|
+
function parseResponse(raw) {
|
|
16
|
+
const cleaned = raw
|
|
17
|
+
.replace(/```(?:json)?\n?/g, '')
|
|
18
|
+
.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F]/g, '')
|
|
19
|
+
.trim();
|
|
20
|
+
return JSON.parse(cleaned);
|
|
21
|
+
}
|
|
22
|
+
// ─── Tests ────────────────────────────────────────────────────────────────────
|
|
23
|
+
describe('buildUserPrompt', () => {
|
|
24
|
+
it('includes PR number and title', () => {
|
|
25
|
+
const prompt = buildUserPrompt([
|
|
26
|
+
{ number: 42, title: 'Fix login bug', body: null, labels: [], linked_issues: [] },
|
|
27
|
+
]);
|
|
28
|
+
expect(prompt).toContain('#42: Fix login bug');
|
|
29
|
+
});
|
|
30
|
+
it('includes labels when present', () => {
|
|
31
|
+
const prompt = buildUserPrompt([
|
|
32
|
+
{ number: 1, title: 'Add feature', body: null, labels: ['enhancement', 'ui'], linked_issues: [] },
|
|
33
|
+
]);
|
|
34
|
+
expect(prompt).toContain('Labels: enhancement, ui');
|
|
35
|
+
});
|
|
36
|
+
it('omits labels line when empty', () => {
|
|
37
|
+
const prompt = buildUserPrompt([
|
|
38
|
+
{ number: 1, title: 'Add feature', body: null, labels: [], linked_issues: [] },
|
|
39
|
+
]);
|
|
40
|
+
expect(prompt).not.toContain('Labels:');
|
|
41
|
+
});
|
|
42
|
+
it('includes linked issues when present', () => {
|
|
43
|
+
const prompt = buildUserPrompt([
|
|
44
|
+
{ number: 1, title: 'Fix', body: null, labels: [], linked_issues: ['#10', '#11'] },
|
|
45
|
+
]);
|
|
46
|
+
expect(prompt).toContain('Linked issues: #10, #11');
|
|
47
|
+
});
|
|
48
|
+
it('truncates body to 300 chars', () => {
|
|
49
|
+
const longBody = 'x'.repeat(500);
|
|
50
|
+
const prompt = buildUserPrompt([
|
|
51
|
+
{ number: 1, title: 'Fix', body: longBody, labels: [], linked_issues: [] },
|
|
52
|
+
]);
|
|
53
|
+
const bodyLine = prompt.split('\n').find(l => l.startsWith('Body:'));
|
|
54
|
+
expect(bodyLine.length).toBeLessThanOrEqual(310);
|
|
55
|
+
});
|
|
56
|
+
it('states correct PR count in header', () => {
|
|
57
|
+
const prs = [
|
|
58
|
+
{ number: 1, title: 'A', body: null, labels: [], linked_issues: [] },
|
|
59
|
+
{ number: 2, title: 'B', body: null, labels: [], linked_issues: [] },
|
|
60
|
+
{ number: 3, title: 'C', body: null, labels: [], linked_issues: [] },
|
|
61
|
+
];
|
|
62
|
+
const prompt = buildUserPrompt(prs);
|
|
63
|
+
expect(prompt).toContain('Analyze these 3 pull requests');
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
describe('parseResponse', () => {
|
|
67
|
+
it('parses clean JSON array', () => {
|
|
68
|
+
const raw = JSON.stringify([{ category: 'bugfix', visible: true }]);
|
|
69
|
+
const result = parseResponse(raw);
|
|
70
|
+
expect(result).toHaveLength(1);
|
|
71
|
+
expect(result[0].category).toBe('bugfix');
|
|
72
|
+
});
|
|
73
|
+
it('strips markdown code fences', () => {
|
|
74
|
+
const raw = '```json\n[{"category":"feature"}]\n```';
|
|
75
|
+
const result = parseResponse(raw);
|
|
76
|
+
expect(result[0].category).toBe('feature');
|
|
77
|
+
});
|
|
78
|
+
it('strips code fences without language tag', () => {
|
|
79
|
+
const raw = '```\n[{"category":"bugfix"}]\n```';
|
|
80
|
+
const result = parseResponse(raw);
|
|
81
|
+
expect(result[0].category).toBe('bugfix');
|
|
82
|
+
});
|
|
83
|
+
it('handles multiple items', () => {
|
|
84
|
+
const items = [
|
|
85
|
+
{ category: 'feature', visible: true },
|
|
86
|
+
{ category: 'internal', visible: false },
|
|
87
|
+
];
|
|
88
|
+
const result = parseResponse(JSON.stringify(items));
|
|
89
|
+
expect(result).toHaveLength(2);
|
|
90
|
+
});
|
|
91
|
+
it('throws on invalid JSON', () => {
|
|
92
|
+
expect(() => parseResponse('not json')).toThrow();
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
// ─── Gemini provider mock ──────────────────────────────────────────────────────
|
|
96
|
+
vi.mock('@google/generative-ai', () => ({
|
|
97
|
+
GoogleGenerativeAI: vi.fn().mockImplementation(() => ({
|
|
98
|
+
getGenerativeModel: vi.fn().mockReturnValue({
|
|
99
|
+
generateContent: vi.fn().mockResolvedValue({
|
|
100
|
+
response: {
|
|
101
|
+
text: () => JSON.stringify([
|
|
102
|
+
{
|
|
103
|
+
original_title: 'Add search',
|
|
104
|
+
rewritten_title: 'You can now search across all items',
|
|
105
|
+
category: 'feature',
|
|
106
|
+
visible: true,
|
|
107
|
+
confidence: 0.95,
|
|
108
|
+
reasoning: 'New user-facing capability',
|
|
109
|
+
},
|
|
110
|
+
]),
|
|
111
|
+
},
|
|
112
|
+
}),
|
|
113
|
+
}),
|
|
114
|
+
})),
|
|
115
|
+
}));
|
|
116
|
+
vi.mock('../lib/config.js', () => ({
|
|
117
|
+
getActiveProvider: vi.fn(() => 'gemini'),
|
|
118
|
+
getActiveAIKey: vi.fn(() => 'AIza-test-key'),
|
|
119
|
+
}));
|
|
120
|
+
describe('analyzeWithGemini (via analyzePullRequests)', () => {
|
|
121
|
+
it('calls GoogleGenerativeAI with the active key', async () => {
|
|
122
|
+
const { GoogleGenerativeAI } = await import('@google/generative-ai');
|
|
123
|
+
const { analyzePullRequests } = await import('../lib/ai.js');
|
|
124
|
+
await analyzePullRequests([
|
|
125
|
+
{ number: 1, title: 'Add search', body: null, labels: [], author: 'alice', merged_at: '', url: '', linked_issues: [] },
|
|
126
|
+
]);
|
|
127
|
+
expect(GoogleGenerativeAI).toHaveBeenCalledWith('AIza-test-key');
|
|
128
|
+
});
|
|
129
|
+
it('returns parsed AnalyzedChange from Gemini response', async () => {
|
|
130
|
+
const { analyzePullRequests } = await import('../lib/ai.js');
|
|
131
|
+
const result = await analyzePullRequests([
|
|
132
|
+
{ number: 1, title: 'Add search', body: null, labels: [], author: 'alice', merged_at: '', url: '', linked_issues: [] },
|
|
133
|
+
]);
|
|
134
|
+
expect(result.changes).toHaveLength(1);
|
|
135
|
+
expect(result.changes[0].category).toBe('feature');
|
|
136
|
+
expect(result.changes[0].visible).toBe(true);
|
|
137
|
+
expect(result.changes[0].rewritten_title).toContain('search');
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
//# sourceMappingURL=ai.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai.test.js","sourceRoot":"","sources":["../../src/__tests__/ai.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatters.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/formatters.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { formatGitHubRelease, formatChangelog, formatSlack, formatOutput, } from '../lib/formatters.js';
|
|
3
|
+
// ─── Fixtures ─────────────────────────────────────────────────────────────────
|
|
4
|
+
const change = (overrides = {}) => ({
|
|
5
|
+
original_title: 'fix something',
|
|
6
|
+
rewritten_title: 'Fixed an issue with something',
|
|
7
|
+
category: 'bugfix',
|
|
8
|
+
visible: true,
|
|
9
|
+
confidence: 0.95,
|
|
10
|
+
reasoning: 'user-facing fix',
|
|
11
|
+
...overrides,
|
|
12
|
+
});
|
|
13
|
+
const feature = (title = 'You can now do something new') => change({ category: 'feature', rewritten_title: title });
|
|
14
|
+
const bugfix = (title = 'Fixed an issue where X happened') => change({ category: 'bugfix', rewritten_title: title });
|
|
15
|
+
const breaking = (title = 'Breaking: old behavior removed') => change({ category: 'breaking', rewritten_title: title });
|
|
16
|
+
const internal = () => change({ category: 'internal', visible: false, rewritten_title: 'Refactored internals' });
|
|
17
|
+
// ─── formatGitHubRelease ──────────────────────────────────────────────────────
|
|
18
|
+
describe('formatGitHubRelease', () => {
|
|
19
|
+
it('renders version heading', () => {
|
|
20
|
+
const out = formatGitHubRelease({ version: 'v1.2.0', changes: [feature()] });
|
|
21
|
+
expect(out).toContain('## v1.2.0');
|
|
22
|
+
});
|
|
23
|
+
it('groups changes under correct headers', () => {
|
|
24
|
+
const out = formatGitHubRelease({
|
|
25
|
+
version: 'v1.0.0',
|
|
26
|
+
changes: [feature(), bugfix(), breaking()],
|
|
27
|
+
});
|
|
28
|
+
expect(out).toContain('### ⚠️ Breaking Changes');
|
|
29
|
+
expect(out).toContain('### ✨ New Features');
|
|
30
|
+
expect(out).toContain('### 🐛 Bug Fixes');
|
|
31
|
+
});
|
|
32
|
+
it('filters out internal changes', () => {
|
|
33
|
+
const out = formatGitHubRelease({
|
|
34
|
+
version: 'v1.0.0',
|
|
35
|
+
changes: [feature(), internal()],
|
|
36
|
+
});
|
|
37
|
+
expect(out).not.toContain('Refactored internals');
|
|
38
|
+
expect(out).toContain('You can now do something new');
|
|
39
|
+
});
|
|
40
|
+
it('shows empty state when all changes are internal', () => {
|
|
41
|
+
const out = formatGitHubRelease({ version: 'v1.0.0', changes: [internal()] });
|
|
42
|
+
expect(out).toContain('No user-facing changes');
|
|
43
|
+
});
|
|
44
|
+
it('includes summary sentence', () => {
|
|
45
|
+
const out = formatGitHubRelease({
|
|
46
|
+
version: 'v1.0.0',
|
|
47
|
+
changes: [feature(), bugfix()],
|
|
48
|
+
});
|
|
49
|
+
expect(out).toContain('This release includes');
|
|
50
|
+
});
|
|
51
|
+
it('puts breaking changes before features', () => {
|
|
52
|
+
const out = formatGitHubRelease({
|
|
53
|
+
version: 'v1.0.0',
|
|
54
|
+
changes: [feature(), breaking()],
|
|
55
|
+
});
|
|
56
|
+
const breakingPos = out.indexOf('Breaking Changes');
|
|
57
|
+
const featurePos = out.indexOf('New Features');
|
|
58
|
+
expect(breakingPos).toBeLessThan(featurePos);
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
// ─── formatChangelog ──────────────────────────────────────────────────────────
|
|
62
|
+
describe('formatChangelog', () => {
|
|
63
|
+
it('includes today\'s date', () => {
|
|
64
|
+
const today = new Date().toISOString().split('T')[0];
|
|
65
|
+
const out = formatChangelog({ version: 'v1.0.0', changes: [feature()] });
|
|
66
|
+
expect(out).toContain(today);
|
|
67
|
+
});
|
|
68
|
+
it('renders version in Keep a Changelog format', () => {
|
|
69
|
+
const out = formatChangelog({ version: 'v1.0.0', changes: [feature()] });
|
|
70
|
+
expect(out).toMatch(/## \[v1\.0\.0\]/);
|
|
71
|
+
});
|
|
72
|
+
it('filters out internal changes', () => {
|
|
73
|
+
const out = formatChangelog({ version: 'v1.0.0', changes: [feature(), internal()] });
|
|
74
|
+
expect(out).not.toContain('Refactored internals');
|
|
75
|
+
});
|
|
76
|
+
it('shows empty state when all changes are internal', () => {
|
|
77
|
+
const out = formatChangelog({ version: 'v1.0.0', changes: [internal()] });
|
|
78
|
+
expect(out).toContain('No user-facing changes');
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
// ─── formatSlack ──────────────────────────────────────────────────────────────
|
|
82
|
+
describe('formatSlack', () => {
|
|
83
|
+
it('starts with bold version', () => {
|
|
84
|
+
const out = formatSlack({ version: 'v1.0.0', changes: [feature()] });
|
|
85
|
+
expect(out).toContain('*🚀 v1.0.0*');
|
|
86
|
+
});
|
|
87
|
+
it('filters out internal changes', () => {
|
|
88
|
+
const out = formatSlack({ version: 'v1.0.0', changes: [feature(), internal()] });
|
|
89
|
+
expect(out).not.toContain('Refactored internals');
|
|
90
|
+
});
|
|
91
|
+
it('always shows breaking changes', () => {
|
|
92
|
+
const manyFeatures = Array.from({ length: 10 }, (_, i) => feature(`Feature ${i}`));
|
|
93
|
+
const out = formatSlack({
|
|
94
|
+
version: 'v1.0.0',
|
|
95
|
+
changes: [breaking(), ...manyFeatures],
|
|
96
|
+
});
|
|
97
|
+
expect(out).toContain('Breaking: old behavior removed');
|
|
98
|
+
});
|
|
99
|
+
it('caps output at 6 items with overflow message', () => {
|
|
100
|
+
const changes = Array.from({ length: 10 }, (_, i) => feature(`Feature ${i}`));
|
|
101
|
+
const out = formatSlack({ version: 'v1.0.0', changes });
|
|
102
|
+
expect(out).toContain('+ 4 more updates');
|
|
103
|
+
});
|
|
104
|
+
it('shows empty state when all changes are internal', () => {
|
|
105
|
+
const out = formatSlack({ version: 'v1.0.0', changes: [internal()] });
|
|
106
|
+
expect(out).toContain('No user-facing changes');
|
|
107
|
+
});
|
|
108
|
+
it('truncates long titles at 80 chars', () => {
|
|
109
|
+
const longTitle = 'A'.repeat(100);
|
|
110
|
+
const out = formatSlack({ version: 'v1.0.0', changes: [feature(longTitle)] });
|
|
111
|
+
const lines = out.split('\n').filter(l => l.includes('A'));
|
|
112
|
+
expect(lines[0].length).toBeLessThanOrEqual(90); // emoji + space + 80 chars
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
// ─── formatOutput ─────────────────────────────────────────────────────────────
|
|
116
|
+
describe('formatOutput', () => {
|
|
117
|
+
it('dispatches to github-release', () => {
|
|
118
|
+
const out = formatOutput('github-release', { version: 'v1.0.0', changes: [feature()] });
|
|
119
|
+
expect(out).toContain('## v1.0.0');
|
|
120
|
+
});
|
|
121
|
+
it('dispatches to changelog', () => {
|
|
122
|
+
const out = formatOutput('changelog', { version: 'v1.0.0', changes: [feature()] });
|
|
123
|
+
expect(out).toContain('[v1.0.0]');
|
|
124
|
+
});
|
|
125
|
+
it('dispatches to slack', () => {
|
|
126
|
+
const out = formatOutput('slack', { version: 'v1.0.0', changes: [feature()] });
|
|
127
|
+
expect(out).toContain('🚀');
|
|
128
|
+
});
|
|
129
|
+
it('throws on unknown format', () => {
|
|
130
|
+
expect(() => formatOutput('unknown', { version: 'v1.0.0', changes: [] })).toThrow('Unknown format');
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
//# sourceMappingURL=formatters.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatters.test.js","sourceRoot":"","sources":["../../src/__tests__/formatters.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate.integration.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/generate.integration.test.ts"],"names":[],"mappings":""}
|