@versu/core 0.11.0 → 0.13.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 +139 -114
- package/dist/changes/index.d.ts +13 -0
- package/dist/changes/index.d.ts.map +1 -0
- package/dist/{changelog → changes}/index.js +43 -40
- package/dist/changes/index.js.map +1 -0
- package/dist/config/schema.d.ts +295 -3
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +19 -7
- package/dist/config/schema.js.map +1 -1
- package/dist/config/templates/main-module.d.ts +1 -1
- package/dist/config/templates/main-module.d.ts.map +1 -1
- package/dist/config/templates/main-module.js +1 -1
- package/dist/config/templates/main-release-module.d.ts +1 -1
- package/dist/config/templates/main-release-module.d.ts.map +1 -1
- package/dist/config/templates/main-release-module.js +2 -2
- package/dist/config/templates/main-release-root.d.ts +1 -1
- package/dist/config/templates/main-release-root.d.ts.map +1 -1
- package/dist/config/templates/main-release-root.js +2 -2
- package/dist/config/types.d.ts +8 -8
- package/dist/config/types.d.ts.map +1 -1
- package/dist/git/index.d.ts +45 -3
- package/dist/git/index.d.ts.map +1 -1
- package/dist/git/index.js +59 -13
- package/dist/git/index.js.map +1 -1
- package/dist/git/types.d.ts +0 -43
- package/dist/git/types.d.ts.map +1 -1
- package/dist/index.d.ts +7 -16
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -10
- package/dist/index.js.map +1 -1
- package/dist/services/changes-renderer.d.ts +21 -0
- package/dist/services/changes-renderer.d.ts.map +1 -0
- package/dist/services/changes-renderer.js +37 -0
- package/dist/services/changes-renderer.js.map +1 -0
- package/dist/services/commit-analyzer.d.ts +3 -9
- package/dist/services/commit-analyzer.d.ts.map +1 -1
- package/dist/services/commit-analyzer.js +7 -21
- package/dist/services/commit-analyzer.js.map +1 -1
- package/dist/services/version-bumper.d.ts +0 -5
- package/dist/services/version-bumper.d.ts.map +1 -1
- package/dist/services/version-bumper.js +0 -5
- package/dist/services/version-bumper.js.map +1 -1
- package/dist/services/versu-runner.d.ts +2 -0
- package/dist/services/versu-runner.d.ts.map +1 -1
- package/dist/services/versu-runner.js +9 -8
- package/dist/services/versu-runner.js.map +1 -1
- package/dist/utils/file.d.ts +8 -0
- package/dist/utils/file.d.ts.map +1 -1
- package/dist/utils/file.js +16 -0
- package/dist/utils/file.js.map +1 -1
- package/dist/utils/version.d.ts +1 -1
- package/dist/utils/version.js +1 -1
- package/package.json +1 -1
- package/dist/changelog/index.d.ts +0 -15
- package/dist/changelog/index.d.ts.map +0 -1
- package/dist/changelog/index.js.map +0 -1
- package/dist/services/changelog-generator.d.ts +0 -21
- package/dist/services/changelog-generator.d.ts.map +0 -1
- package/dist/services/changelog-generator.js +0 -37
- package/dist/services/changelog-generator.js.map +0 -1
package/README.md
CHANGED
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
|
|
9
9
|
The core business logic powering Versu. This package is completely framework-agnostic and can be integrated into any TypeScript/JavaScript project, CI/CD system, or custom tooling.
|
|
10
10
|
|
|
11
|
+
For comprehensive documentation, examples, and configuration options, please refer to the our website <https://versuhq.github.io/>.
|
|
12
|
+
|
|
11
13
|
## Installation
|
|
12
14
|
|
|
13
15
|
```bash
|
|
@@ -17,16 +19,14 @@ npm install @versu/core
|
|
|
17
19
|
## Quick Start
|
|
18
20
|
|
|
19
21
|
```typescript
|
|
20
|
-
import { VersuRunner } from
|
|
22
|
+
import { VersuRunner, type RunnerOptions } from "@versu/core";
|
|
23
|
+
|
|
24
|
+
const options: RunnerOptions = {
|
|
25
|
+
repoRoot: "/path/to/repository",
|
|
26
|
+
// ...other options as needed
|
|
27
|
+
};
|
|
21
28
|
|
|
22
|
-
const runner = new VersuRunner(
|
|
23
|
-
repoRoot: '/path/to/repository',
|
|
24
|
-
adapter: 'gradle', // Optional - auto-detected if not specified
|
|
25
|
-
dryRun: false,
|
|
26
|
-
pushTags: true,
|
|
27
|
-
pushChanges: true,
|
|
28
|
-
generateChangelog: true
|
|
29
|
-
});
|
|
29
|
+
const runner = new VersuRunner(options);
|
|
30
30
|
|
|
31
31
|
const result = await runner.run();
|
|
32
32
|
|
|
@@ -35,173 +35,193 @@ console.log(`Changed modules:`, result.changedModules);
|
|
|
35
35
|
console.log(`Created tags:`, result.createdTags);
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
-
For detailed pre-release configuration and examples, see [PRERELEASE.md](./PRERELEASE.md).
|
|
39
|
-
|
|
40
38
|
## VersuRunner API
|
|
41
39
|
|
|
42
40
|
### Options
|
|
43
41
|
|
|
44
42
|
```typescript
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
43
|
+
type RunnerOptions = {
|
|
44
|
+
// Required
|
|
45
|
+
repoRoot: string; // Absolute path to repository root
|
|
46
|
+
prereleaseMode: boolean; // Generate pre-release versions
|
|
47
|
+
prereleaseId: string; // Pre-release identifier, e.g. 'alpha', 'beta', 'rc'
|
|
48
|
+
bumpUnchanged: boolean; // Bump modules with no changes (prerelease mode only)
|
|
49
|
+
addBuildMetadata: boolean; // Append short SHA as build metadata (+sha)
|
|
50
|
+
timestampVersions: boolean; // Use timestamp-based pre-release identifiers
|
|
51
|
+
appendSnapshot: boolean; // Append -SNAPSHOT suffix (Gradle only)
|
|
52
|
+
createTags: boolean; // Create git tags for bumped modules
|
|
53
|
+
generateChangelog: boolean; // Generate CHANGELOG.md files
|
|
54
|
+
generateReleaseNotes: boolean; // Generate release notes files (e.g. RELEASE.md)
|
|
55
|
+
pushChanges: boolean; // Commit and push version changes to remote
|
|
56
|
+
dryRun: boolean; // Preview changes without writing anything
|
|
57
|
+
|
|
58
|
+
// Optional
|
|
59
|
+
adapter?: string; // Language adapter ID (auto-detected if omitted)
|
|
60
|
+
changelogFilename?: string; // Changelog filename (default: 'CHANGELOG.md')
|
|
61
|
+
releaseNotesFilename?: string; // Release notes filename (default: 'RELEASE.md')
|
|
62
|
+
fromRef?: string; // Git ref to use as the lower boundary for commit analysis
|
|
63
|
+
provider?: string; // Version control provider name (auto-detected if omitted)
|
|
64
|
+
};
|
|
59
65
|
```
|
|
60
66
|
|
|
61
67
|
### Result
|
|
62
68
|
|
|
63
69
|
```typescript
|
|
64
|
-
|
|
65
|
-
bumped: boolean;
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
changelogPaths: string[]; // Generated changelog file paths
|
|
73
|
-
}
|
|
70
|
+
type RunnerResult = {
|
|
71
|
+
bumped: boolean; // Whether any version was updated
|
|
72
|
+
discoveredModules: Array<Module>; // All modules found in the repository
|
|
73
|
+
changedModules: Array<ModuleChangeResult>; // Modules whose version changed
|
|
74
|
+
createdTags: string[]; // Git tags that were created
|
|
75
|
+
changelogPaths: string[]; // Generated changelog file paths
|
|
76
|
+
releaseNotesPaths: string[]; // Generated release notes file paths
|
|
77
|
+
};
|
|
74
78
|
```
|
|
75
79
|
|
|
76
80
|
## Configuration
|
|
77
81
|
|
|
78
82
|
Versu core uses [cosmiconfig](https://github.com/davidtheclark/cosmiconfig) for configuration loading and [Zod](https://github.com/colinhacks/zod) for validation.
|
|
79
83
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
1. `package.json` (in a `"versu"` property)
|
|
83
|
-
2. `.versurc.json`
|
|
84
|
-
3. `.versurc.yaml` / `.versurc.yml`
|
|
85
|
-
4. `.versurc.js` or `versu.config.js` (JavaScript)
|
|
84
|
+
You can provide configuration in any of the supported config files (e.g., `.versurc`, `versu.config.js`, etc.) or via `package.json` under the `versu` key. For the full list please refer to [cosmiconfig search places documentation](https://github.com/cosmiconfig/cosmiconfig?tab=readme-ov-file#searchplaces).
|
|
86
85
|
|
|
87
86
|
### Configuration Example
|
|
88
87
|
|
|
89
88
|
```json
|
|
90
89
|
{
|
|
91
|
-
"
|
|
92
|
-
"
|
|
93
|
-
|
|
94
|
-
"
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
"
|
|
90
|
+
"versioning": {
|
|
91
|
+
"breakingChange": {
|
|
92
|
+
"stable": "major",
|
|
93
|
+
"prerelease": "premajor"
|
|
94
|
+
},
|
|
95
|
+
"unknownCommitType": {
|
|
96
|
+
"stable": "patch",
|
|
97
|
+
"prerelease": "prepatch"
|
|
98
98
|
},
|
|
99
|
-
"
|
|
100
|
-
"
|
|
101
|
-
|
|
102
|
-
|
|
99
|
+
"commitTypes": {
|
|
100
|
+
"feat": {
|
|
101
|
+
"stable": "minor",
|
|
102
|
+
"prerelease": "preminor"
|
|
103
|
+
},
|
|
104
|
+
"fix": {
|
|
105
|
+
"stable": "patch",
|
|
106
|
+
"prerelease": "prepatch"
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
"cascadeRules": {
|
|
110
|
+
"stable": {
|
|
111
|
+
"major": "major",
|
|
112
|
+
"minor": "minor",
|
|
113
|
+
"patch": "patch"
|
|
114
|
+
},
|
|
115
|
+
"prerelease": {
|
|
116
|
+
"major": "premajor",
|
|
117
|
+
"minor": "preminor",
|
|
118
|
+
"patch": "prepatch"
|
|
119
|
+
}
|
|
103
120
|
}
|
|
104
121
|
},
|
|
105
122
|
"changelog": {
|
|
106
123
|
"root": {
|
|
107
124
|
"context": {
|
|
108
|
-
"prependPlaceholder": "<!--
|
|
125
|
+
"prependPlaceholder": "<!-- Next Version Placeholder -->"
|
|
109
126
|
}
|
|
110
127
|
},
|
|
111
128
|
"module": {
|
|
112
129
|
"context": {
|
|
113
|
-
"prependPlaceholder": "<!--
|
|
130
|
+
"prependPlaceholder": "<!-- Next Version Placeholder -->"
|
|
114
131
|
}
|
|
115
132
|
}
|
|
116
133
|
}
|
|
117
134
|
}
|
|
118
135
|
```
|
|
119
136
|
|
|
120
|
-
**Changelog Configuration:**
|
|
137
|
+
**Changelog & Release Notes Configuration:**
|
|
121
138
|
|
|
122
139
|
- `changelog.root` - Configuration for root-level CHANGELOG.md generation
|
|
123
140
|
- `changelog.module` - Configuration for per-module CHANGELOG.md generation
|
|
124
|
-
- `context.prependPlaceholder` - Placeholder string in changelog files where new entries are inserted
|
|
125
|
-
- `options` - Advanced changelog generation options (templates, grouping, sorting)
|
|
141
|
+
- `changelog.context.prependPlaceholder` - Placeholder string in changelog files where new entries are inserted
|
|
142
|
+
- `changelog.context.options` - Advanced changelog generation options (templates, grouping, sorting)
|
|
126
143
|
|
|
127
|
-
|
|
144
|
+
Release notes follows the same pattern under `release` key.
|
|
128
145
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
### Gradle Adapter
|
|
132
|
-
|
|
133
|
-
Gradle support is provided by the **[@versu/plugin-gradle][plugin-gradle]** package.
|
|
134
|
-
|
|
135
|
-
**Features:**
|
|
136
|
-
|
|
137
|
-
- Multi-module project detection
|
|
138
|
-
- Version management through root `gradle.properties`
|
|
139
|
-
- Dependency detection
|
|
140
|
-
- Both Groovy and Kotlin DSL support
|
|
141
|
-
|
|
142
|
-
**Version Format:**
|
|
146
|
+
Versu uses [conventional-changelog-writer](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-writer) for changelog and release notes generation. You can pass any options supported by conventional-changelog-writer through the `options` field. For advanced customization with functions (like `transform`, `commitsGroupsSort`), use JavaScript configuration files (`.versurc.js` or `versu.config.js`).
|
|
143
147
|
|
|
144
|
-
|
|
145
|
-
# Root module
|
|
146
|
-
version=1.0.0
|
|
148
|
+
## Adapters
|
|
147
149
|
|
|
148
|
-
|
|
149
|
-
core.version=2.1.0
|
|
150
|
-
api.version=1.5.0
|
|
151
|
-
```
|
|
150
|
+
Versu supports multiple language ecosystems through adapters. The core package includes a plugin system for adding new adapter support. In order to support additional ecosystems, you need to implement the required interfaces and register them as plugins.
|
|
152
151
|
|
|
153
152
|
### Creating Custom Adapters
|
|
154
153
|
|
|
155
154
|
To add support for new project types, create a plugin package that implements the adapter interfaces:
|
|
156
155
|
|
|
157
156
|
```typescript
|
|
158
|
-
import {
|
|
159
|
-
AdapterIdentifier,
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
157
|
+
import {
|
|
158
|
+
type AdapterIdentifier,
|
|
159
|
+
type AdapterMetadata,
|
|
160
|
+
type ModuleDetector,
|
|
161
|
+
type ProjectInformation,
|
|
162
|
+
type VersionUpdateStrategy,
|
|
163
|
+
type ModuleRegistry,
|
|
164
|
+
type ModuleSystemFactory,
|
|
165
|
+
exists,
|
|
166
|
+
} from "@versu/core";
|
|
167
167
|
|
|
168
168
|
// 1. Adapter identifier for auto-detection
|
|
169
169
|
class MyAdapterIdentifier implements AdapterIdentifier {
|
|
170
170
|
readonly metadata: AdapterMetadata = {
|
|
171
|
-
id:
|
|
172
|
-
capabilities: { supportsSnapshots: false }
|
|
171
|
+
id: "my-adapter",
|
|
172
|
+
capabilities: { supportsSnapshots: false },
|
|
173
173
|
};
|
|
174
174
|
|
|
175
175
|
async accept(projectRoot: string): Promise<boolean> {
|
|
176
176
|
// Check for adapter-specific files
|
|
177
|
-
return await
|
|
177
|
+
return await exists(path.join(projectRoot, "my-build-file"));
|
|
178
178
|
}
|
|
179
179
|
}
|
|
180
180
|
|
|
181
181
|
// 2. Module detector for discovering project structure
|
|
182
182
|
class MyModuleDetector implements ModuleDetector {
|
|
183
|
-
|
|
183
|
+
constructor(
|
|
184
|
+
readonly repoRoot: string,
|
|
185
|
+
readonly outputFile: string,
|
|
186
|
+
) {}
|
|
187
|
+
|
|
188
|
+
async detect(): Promise<ProjectInformation> {
|
|
184
189
|
// Discover and return modules and dependencies
|
|
185
190
|
return {
|
|
191
|
+
moduleIds: ["root", "module-a"],
|
|
186
192
|
modules: [
|
|
187
|
-
{
|
|
188
|
-
|
|
193
|
+
{
|
|
194
|
+
id: "root",
|
|
195
|
+
name: "root",
|
|
196
|
+
path: this.repoRoot,
|
|
197
|
+
type: "root",
|
|
198
|
+
affectedModules: new Set(["module-a"]),
|
|
199
|
+
version: "1.0.0",
|
|
200
|
+
declaredVersion: false,
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
id: "module-a",
|
|
204
|
+
name: "module-a",
|
|
205
|
+
path: join(this.repoRoot, "module-a"),
|
|
206
|
+
type: "module",
|
|
207
|
+
affectedModules: new Set([]),
|
|
208
|
+
version: "2.0.0",
|
|
209
|
+
declaredVersion: true,
|
|
210
|
+
},
|
|
189
211
|
],
|
|
190
|
-
dependencies: [
|
|
191
|
-
{ from: 'module-a', to: 'root' }
|
|
192
|
-
]
|
|
193
212
|
};
|
|
194
213
|
}
|
|
195
214
|
}
|
|
196
215
|
|
|
197
216
|
// 3. Version update strategy for applying changes
|
|
198
217
|
class MyVersionUpdateStrategy implements VersionUpdateStrategy {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
218
|
+
constructor(private readonly moduleRegistry: ModuleRegistry) {}
|
|
219
|
+
|
|
220
|
+
async writeVersionUpdates(
|
|
221
|
+
moduleVersions: Map<string, string>,
|
|
202
222
|
): Promise<void> {
|
|
203
223
|
// Apply version changes to build files
|
|
204
|
-
for (const
|
|
224
|
+
for (const [moduleId, newVersion] of moduleVersions) {
|
|
205
225
|
// Update version in your project's format
|
|
206
226
|
}
|
|
207
227
|
}
|
|
@@ -209,12 +229,16 @@ class MyVersionUpdateStrategy implements VersionUpdateStrategy {
|
|
|
209
229
|
|
|
210
230
|
// 4. Module system factory to tie it all together
|
|
211
231
|
class MyModuleSystemFactory implements ModuleSystemFactory {
|
|
212
|
-
|
|
213
|
-
|
|
232
|
+
constructor(private readonly repoRoot: string) {}
|
|
233
|
+
|
|
234
|
+
createDetector(outputFile: string): ModuleDetector {
|
|
235
|
+
return new MyModuleDetector(this.repoRoot, outputFile);
|
|
214
236
|
}
|
|
215
|
-
|
|
216
|
-
createVersionUpdateStrategy(
|
|
217
|
-
|
|
237
|
+
|
|
238
|
+
createVersionUpdateStrategy(
|
|
239
|
+
moduleRegistry: ModuleRegistry,
|
|
240
|
+
): VersionUpdateStrategy {
|
|
241
|
+
return new MyVersionUpdateStrategy(moduleRegistry);
|
|
218
242
|
}
|
|
219
243
|
}
|
|
220
244
|
```
|
|
@@ -222,19 +246,20 @@ class MyModuleSystemFactory implements ModuleSystemFactory {
|
|
|
222
246
|
Then create a plugin:
|
|
223
247
|
|
|
224
248
|
```typescript
|
|
225
|
-
import type { PluginContract } from
|
|
249
|
+
import type { PluginContract } from "@versu/core";
|
|
226
250
|
|
|
227
251
|
const myPlugin: PluginContract = {
|
|
228
|
-
id:
|
|
229
|
-
name:
|
|
230
|
-
description:
|
|
231
|
-
version:
|
|
232
|
-
author:
|
|
252
|
+
id: "my-adapter",
|
|
253
|
+
name: "My Adapter",
|
|
254
|
+
description: "Support for my build system",
|
|
255
|
+
version: "1.0.0",
|
|
256
|
+
author: "Your Name",
|
|
233
257
|
adapters: [
|
|
234
258
|
{
|
|
235
|
-
id:
|
|
259
|
+
id: "my-adapter",
|
|
236
260
|
adapterIdentifier: () => new MyAdapterIdentifier(),
|
|
237
|
-
moduleSystemFactory: (repoRoot: string) =>
|
|
261
|
+
moduleSystemFactory: (repoRoot: string) =>
|
|
262
|
+
new MyModuleSystemFactory(repoRoot),
|
|
238
263
|
},
|
|
239
264
|
],
|
|
240
265
|
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ModuleChangeResult } from "../services/version-applier.js";
|
|
2
|
+
import { Commit } from "conventional-commits-parser";
|
|
3
|
+
import { ModuleChangesConfig } from "../config/types.js";
|
|
4
|
+
/** Generate changes for multiple modules. */
|
|
5
|
+
export declare function generateChangesForModules(moduleResults: ModuleChangeResult[], getCommitsForModule: (moduleId: string) => Promise<{
|
|
6
|
+
commits: Commit[];
|
|
7
|
+
lastTag: string | null;
|
|
8
|
+
}>, repoRoot: string, dryRun: boolean, filename: string, multiModule: boolean, config?: ModuleChangesConfig, provider?: string): Promise<string[]>;
|
|
9
|
+
export declare function generateRootChanges(moduleResults: ModuleChangeResult[], getCommitsForModule: (moduleId: string) => Promise<{
|
|
10
|
+
commits: Commit[];
|
|
11
|
+
lastTag: string | null;
|
|
12
|
+
}>, repoRoot: string, dryRun: boolean, filename: string, config?: ModuleChangesConfig, provider?: string): Promise<string | undefined>;
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/changes/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAOpE,OAAO,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AASrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAgDzD,6CAA6C;AAC7C,wBAAsB,yBAAyB,CAC7C,aAAa,EAAE,kBAAkB,EAAE,EACnC,mBAAmB,EAAE,CACnB,QAAQ,EAAE,MAAM,KACb,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,EAC3D,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,OAAO,EACf,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,OAAO,EACpB,MAAM,CAAC,EAAE,mBAAmB,EAC5B,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,EAAE,CAAC,CAoFnB;AAED,wBAAsB,mBAAmB,CACvC,aAAa,EAAE,kBAAkB,EAAE,EACnC,mBAAmB,EAAE,CACnB,QAAQ,EAAE,MAAM,KACb,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,EAC3D,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,OAAO,EACf,QAAQ,EAAE,MAAM,EAChB,MAAM,CAAC,EAAE,mBAAmB,EAC5B,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CA4E7B"}
|
|
@@ -3,7 +3,7 @@ import { join } from "path";
|
|
|
3
3
|
import { writeChangelogString, } from "conventional-changelog-writer";
|
|
4
4
|
import { logger } from "../utils/logger.js";
|
|
5
5
|
import { exists } from "../utils/file.js";
|
|
6
|
-
import { getCurrentRepoUrl, parseRepoUrl } from "../git/index.js";
|
|
6
|
+
import { getCurrentRepoUrl, getModuleTagName, parseRepoUrl, parseTagName, } from "../git/index.js";
|
|
7
7
|
import { isReleaseVersion } from "../semver/index.js";
|
|
8
8
|
import Handlebars from "handlebars";
|
|
9
9
|
Handlebars.registerHelper("eq", (a, b) => a === b);
|
|
@@ -11,17 +11,17 @@ Handlebars.registerHelper("ne", (a, b) => a !== b);
|
|
|
11
11
|
Handlebars.registerHelper("and", (a, b) => a && b);
|
|
12
12
|
Handlebars.registerHelper("or", (a, b) => a || b);
|
|
13
13
|
Handlebars.registerHelper("not", (a) => !a);
|
|
14
|
-
/** Update or create
|
|
15
|
-
|
|
16
|
-
let fileContent =
|
|
17
|
-
if (await exists(
|
|
18
|
-
logger.info("Updating existing
|
|
19
|
-
// Try to read existing
|
|
20
|
-
const existingContent = await fs.readFile(
|
|
21
|
-
const newContent = `${prependPlaceholder}\n\n${
|
|
14
|
+
/** Update or create changes file for a module. */
|
|
15
|
+
async function updateChangesFile(content, filePath, prependPlaceholder) {
|
|
16
|
+
let fileContent = content;
|
|
17
|
+
if (await exists(filePath)) {
|
|
18
|
+
logger.info("Updating existing changes", { path: filePath });
|
|
19
|
+
// Try to read existing changes
|
|
20
|
+
const existingContent = await fs.readFile(filePath, "utf8");
|
|
21
|
+
const newContent = `${prependPlaceholder}\n\n${content.trimEnd()}`;
|
|
22
22
|
fileContent = existingContent.replace(prependPlaceholder, newContent);
|
|
23
23
|
}
|
|
24
|
-
await fs.writeFile(
|
|
24
|
+
await fs.writeFile(filePath, fileContent, "utf8");
|
|
25
25
|
}
|
|
26
26
|
async function buildContextRepository(options = {}) {
|
|
27
27
|
const repoUrl = await getCurrentRepoUrl(options);
|
|
@@ -33,36 +33,36 @@ async function buildContextRepository(options = {}) {
|
|
|
33
33
|
repository: repo,
|
|
34
34
|
};
|
|
35
35
|
}
|
|
36
|
-
/** Generate
|
|
37
|
-
export async function
|
|
38
|
-
const
|
|
36
|
+
/** Generate changes for multiple modules. */
|
|
37
|
+
export async function generateChangesForModules(moduleResults, getCommitsForModule, repoRoot, dryRun, filename, multiModule, config, provider) {
|
|
38
|
+
const renderedPaths = [];
|
|
39
39
|
if (!config) {
|
|
40
|
-
throw new Error(`Missing required
|
|
40
|
+
throw new Error(`Missing required changes rendering configuration`);
|
|
41
41
|
}
|
|
42
42
|
const prependPlaceholder = config?.context?.prependPlaceholder;
|
|
43
43
|
if (!prependPlaceholder) {
|
|
44
|
-
throw new Error("Missing required context property 'prependPlaceholder'");
|
|
44
|
+
throw new Error("Missing required changes rendering context property 'prependPlaceholder'");
|
|
45
45
|
}
|
|
46
46
|
const contextRepository = await buildContextRepository({ cwd: repoRoot });
|
|
47
47
|
for (const moduleResult of moduleResults) {
|
|
48
48
|
if (moduleResult.type === "root" && multiModule) {
|
|
49
|
-
logger.info("Skipping root module for individual
|
|
49
|
+
logger.info("Skipping root module for individual changes generation since multi-module changes enabled", { moduleId: moduleResult.id });
|
|
50
50
|
continue;
|
|
51
51
|
}
|
|
52
52
|
if (!moduleResult.declaredVersion) {
|
|
53
|
-
logger.debug("Module has no declared version, skipping
|
|
53
|
+
logger.debug("Module has no declared version, skipping changes generation", { moduleId: moduleResult.id });
|
|
54
54
|
continue;
|
|
55
55
|
}
|
|
56
56
|
const { commits, lastTag } = await getCommitsForModule(moduleResult.id);
|
|
57
57
|
if (commits.length === 0) {
|
|
58
|
-
logger.info("No commits found, skipping
|
|
58
|
+
logger.info("No commits found, skipping rendering changes", {
|
|
59
59
|
moduleId: moduleResult.id,
|
|
60
60
|
});
|
|
61
61
|
continue;
|
|
62
62
|
}
|
|
63
|
-
const
|
|
63
|
+
const renderedPath = join(repoRoot, moduleResult.path, filename);
|
|
64
64
|
let prepend = true;
|
|
65
|
-
if (await exists(
|
|
65
|
+
if (await exists(renderedPath)) {
|
|
66
66
|
prepend = false;
|
|
67
67
|
}
|
|
68
68
|
const isRelease = isReleaseVersion(moduleResult.to);
|
|
@@ -71,7 +71,7 @@ export async function generateChangelogsForModules(moduleResults, getCommitsForM
|
|
|
71
71
|
? `${moduleResult.name}@${moduleResult.to}`
|
|
72
72
|
: undefined;
|
|
73
73
|
const previousTag = lastTag || undefined;
|
|
74
|
-
const
|
|
74
|
+
const changesContent = await writeChangelogString(commits, {
|
|
75
75
|
version: version,
|
|
76
76
|
previousTag: previousTag,
|
|
77
77
|
currentTag: currentTag,
|
|
@@ -82,55 +82,58 @@ export async function generateChangelogsForModules(moduleResults, getCommitsForM
|
|
|
82
82
|
provider,
|
|
83
83
|
}, config?.options);
|
|
84
84
|
if (dryRun) {
|
|
85
|
-
logger.info("Dry run enabled, skipping writing
|
|
85
|
+
logger.info("Dry run enabled, skipping writing changes to file", {
|
|
86
86
|
moduleId: moduleResult.id,
|
|
87
87
|
});
|
|
88
|
-
logger.debug("Generated
|
|
88
|
+
logger.debug("Generated changes content", { changesContent });
|
|
89
89
|
}
|
|
90
90
|
else {
|
|
91
|
-
await
|
|
91
|
+
await updateChangesFile(changesContent, renderedPath, prependPlaceholder);
|
|
92
92
|
}
|
|
93
|
-
|
|
93
|
+
renderedPaths.push(renderedPath);
|
|
94
94
|
}
|
|
95
|
-
return
|
|
95
|
+
return renderedPaths;
|
|
96
96
|
}
|
|
97
|
-
export async function
|
|
97
|
+
export async function generateRootChanges(moduleResults, getCommitsForModule, repoRoot, dryRun, filename, config, provider) {
|
|
98
98
|
const moduleResult = moduleResults.find((result) => result.type === "root");
|
|
99
99
|
if (!moduleResult) {
|
|
100
|
-
logger.info("No root module found, skipping root
|
|
100
|
+
logger.info("No root module found, skipping root changes generation");
|
|
101
101
|
return;
|
|
102
102
|
}
|
|
103
103
|
if (!config) {
|
|
104
|
-
throw new Error(`Missing required
|
|
104
|
+
throw new Error(`Missing required changes rendering configuration`);
|
|
105
105
|
}
|
|
106
|
-
logger.info("Loading root
|
|
106
|
+
logger.info("Loading root changes configuration");
|
|
107
107
|
const prependPlaceholder = config?.context?.prependPlaceholder;
|
|
108
108
|
if (!prependPlaceholder) {
|
|
109
|
-
throw new Error("Missing required context property 'prependPlaceholder'");
|
|
109
|
+
throw new Error("Missing required changes rendering context property 'prependPlaceholder'");
|
|
110
110
|
}
|
|
111
111
|
const contextRepository = await buildContextRepository({ cwd: repoRoot });
|
|
112
112
|
const { commits, lastTag } = await getCommitsForModule(moduleResult.id);
|
|
113
113
|
if (commits.length === 0) {
|
|
114
|
-
logger.info("No commits found, skipping root
|
|
114
|
+
logger.info("No commits found, skipping root changes", {
|
|
115
115
|
moduleId: moduleResult.id,
|
|
116
116
|
});
|
|
117
117
|
return;
|
|
118
118
|
}
|
|
119
|
-
const
|
|
119
|
+
const renderedPath = join(repoRoot, moduleResult.path, filename);
|
|
120
120
|
let prepend = true;
|
|
121
|
-
if (await exists(
|
|
121
|
+
if (await exists(renderedPath)) {
|
|
122
122
|
prepend = false;
|
|
123
123
|
}
|
|
124
124
|
const isRelease = isReleaseVersion(moduleResult.to);
|
|
125
125
|
const version = isRelease ? moduleResult.to : undefined;
|
|
126
126
|
const currentTag = isRelease
|
|
127
|
-
?
|
|
127
|
+
? getModuleTagName(moduleResult.name, moduleResult.to)
|
|
128
128
|
: undefined;
|
|
129
129
|
const previousTag = lastTag || undefined;
|
|
130
|
-
const
|
|
130
|
+
const changesContent = await writeChangelogString(commits, {
|
|
131
131
|
moduleResults,
|
|
132
132
|
version: version,
|
|
133
133
|
previousTag: previousTag,
|
|
134
|
+
previousTagVersion: previousTag
|
|
135
|
+
? parseTagName(previousTag).version
|
|
136
|
+
: undefined,
|
|
134
137
|
currentTag: currentTag,
|
|
135
138
|
linkCompare: previousTag && currentTag ? true : false,
|
|
136
139
|
...contextRepository,
|
|
@@ -139,14 +142,14 @@ export async function generateRootChangelog(moduleResults, getCommitsForModule,
|
|
|
139
142
|
provider,
|
|
140
143
|
}, config?.options);
|
|
141
144
|
if (dryRun) {
|
|
142
|
-
logger.info("Dry run enabled, skipping writing root
|
|
145
|
+
logger.info("Dry run enabled, skipping writing root changes to file", {
|
|
143
146
|
moduleId: moduleResult.id,
|
|
144
147
|
});
|
|
145
|
-
logger.debug("Generated root
|
|
148
|
+
logger.debug("Generated root changes content", { changesContent });
|
|
146
149
|
}
|
|
147
150
|
else {
|
|
148
|
-
await
|
|
151
|
+
await updateChangesFile(changesContent, renderedPath, prependPlaceholder);
|
|
149
152
|
}
|
|
150
|
-
return
|
|
153
|
+
return renderedPath;
|
|
151
154
|
}
|
|
152
155
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/changes/index.ts"],"names":[],"mappings":"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"}
|