relacher 0.0.5-rc.7 → 0.0.5
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/lib-types/index.d.ts +1 -0
- package/lib-types/init.d.ts +11 -0
- package/lib-types/types.d.ts +1 -0
- package/lib-types/vcs/git.d.ts +1 -0
- package/lib-types/vcs/index.d.ts +2 -1
- package/lib-types/vcs/jj.d.ts +1 -0
- package/lib-types/versioning/default-data.d.ts +1 -1
- package/lib-types/versioning/types.d.ts +1 -7
- package/package.json +1 -1
- package/src/display/print.ts +7 -1
- package/src/index.ts +1 -0
- package/src/init.ts +74 -0
- package/src/prepare.ts +8 -1
- package/src/run.ts +6 -0
- package/src/types.ts +2 -4
- package/src/vcs/git.ts +8 -0
- package/src/vcs/index.ts +3 -1
- package/src/vcs/jj.ts +26 -2
- package/src/versioning/default-data.ts +5 -5
- package/src/versioning/types.ts +1 -7
- package/src/versioning/vcs-version-manager.ts +44 -35
package/lib-types/index.d.ts
CHANGED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Effect } from 'effect';
|
|
2
|
+
import type { PackageConfig } from './types';
|
|
3
|
+
import { type VcsProvider } from './vcs';
|
|
4
|
+
/**
|
|
5
|
+
* Initializes the `.relacher.lock` file if it does not exist.
|
|
6
|
+
* It resolves the version using each package's `versionFallback`,
|
|
7
|
+
* creates the lockfile, and commits it to establish the baseline.
|
|
8
|
+
*/
|
|
9
|
+
export declare function init(packages: PackageConfig[], options?: {
|
|
10
|
+
cwd?: string;
|
|
11
|
+
}): Effect.Effect<void, Error, VcsProvider>;
|
package/lib-types/types.d.ts
CHANGED
package/lib-types/vcs/git.d.ts
CHANGED
|
@@ -5,5 +5,6 @@ export declare function runGit(cmd: string, cwd: string): Effect.Effect<string,
|
|
|
5
5
|
export declare function getGitCommits(name: string, watch: string[], lastCommit: string | null, cwd: string, exclude?: string[]): Effect.Effect<Commit[], never>;
|
|
6
6
|
export declare function getGitHeadCommit(cwd: string): Effect.Effect<string, never>;
|
|
7
7
|
export declare function findGitLastReleaseCommit(packageName: string, currentVersion: string, cwd: string): Effect.Effect<string | null, never>;
|
|
8
|
+
export declare function isGitDirty(cwd: string): Effect.Effect<boolean, never>;
|
|
8
9
|
export declare function makeGitVcsProvider(cwd: string): VcsProvider;
|
|
9
10
|
export declare const GitVcsProviderLive: (cwd: string) => Layer.Layer<VcsProvider, never, never>;
|
package/lib-types/vcs/index.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { Context, Effect } from 'effect';
|
|
1
|
+
import { Context, type Effect } from 'effect';
|
|
2
2
|
import type { Commit } from '../types';
|
|
3
3
|
export interface VcsProvider {
|
|
4
4
|
readonly getCommits: (name: string, watch: string[], lastCommit: string | null, exclude?: string[]) => Effect.Effect<Commit[], Error>;
|
|
5
5
|
readonly getHeadCommit: () => Effect.Effect<string, Error>;
|
|
6
6
|
readonly findLastReleaseCommit: (packageName: string, currentVersion: string) => Effect.Effect<string | null, Error>;
|
|
7
7
|
readonly commit: (message: string) => Effect.Effect<void, Error>;
|
|
8
|
+
readonly isDirty: () => Effect.Effect<boolean, Error>;
|
|
8
9
|
}
|
|
9
10
|
export declare const VcsProviderService: Context.Service<VcsProvider, VcsProvider>;
|
|
10
11
|
export * from './git';
|
package/lib-types/vcs/jj.d.ts
CHANGED
|
@@ -7,5 +7,6 @@ export declare function runJj(cmd: string, cwd: string, opts?: {
|
|
|
7
7
|
export declare function getJjCommits(name: string, watch: string[], lastCommit: string | null, cwd: string, exclude?: string[]): Effect.Effect<Commit[], never>;
|
|
8
8
|
export declare function getJjHeadCommit(cwd: string): Effect.Effect<string, never>;
|
|
9
9
|
export declare function findJjLastReleaseCommit(packageName: string, currentVersion: string, cwd: string): Effect.Effect<string | null, never>;
|
|
10
|
+
export declare function isJjDirty(cwd: string): Effect.Effect<boolean, never>;
|
|
10
11
|
export declare function makeJjVcsProvider(cwd: string): VcsProvider;
|
|
11
12
|
export declare const JjVcsProviderLive: (cwd: string) => Layer.Layer<VcsProvider, never, never>;
|
|
@@ -12,10 +12,4 @@ export interface SizePatterns {
|
|
|
12
12
|
patch: PatternConfig;
|
|
13
13
|
skip: PatternConfig;
|
|
14
14
|
}
|
|
15
|
-
export
|
|
16
|
-
skip?: Record<string, BumpSize>;
|
|
17
|
-
patch?: Record<string, BumpSize>;
|
|
18
|
-
minor?: Record<string, BumpSize>;
|
|
19
|
-
major?: Record<string, BumpSize>;
|
|
20
|
-
[key: string]: Record<string, BumpSize> | undefined;
|
|
21
|
-
}
|
|
15
|
+
export type CascadeRules = Record<string, BumpSize>;
|
package/package.json
CHANGED
package/src/display/print.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { pipe } from 'effect';
|
|
2
2
|
|
|
3
3
|
import type { PreparedUpdate } from '../types';
|
|
4
|
+
import { defaultSizes } from '../versioning/default-data';
|
|
5
|
+
import { matchBumpSize } from '../versioning/utils';
|
|
4
6
|
|
|
5
7
|
import { getIconForFile } from './devicons';
|
|
6
8
|
import { c, log } from './utils';
|
|
@@ -75,6 +77,10 @@ function getVersionDisplay(oldV: string, newV: string, lastStableVersion?: strin
|
|
|
75
77
|
}
|
|
76
78
|
|
|
77
79
|
export function prettyPrint(prepared: PreparedUpdate): void {
|
|
80
|
+
if (prepared.isDirty) {
|
|
81
|
+
log.warn('The repository has unstaged or uncommitted changes (dirty status).');
|
|
82
|
+
}
|
|
83
|
+
|
|
78
84
|
if (prepared.isInvalid) {
|
|
79
85
|
console.log(c.red('\nErrors detected during preparation:'));
|
|
80
86
|
for (const err of prepared.errors) {
|
|
@@ -116,7 +122,7 @@ export function prettyPrint(prepared: PreparedUpdate): void {
|
|
|
116
122
|
|
|
117
123
|
// 1. Show all commits since the last release with a bump marker if applicable
|
|
118
124
|
for (const commit of report.commits) {
|
|
119
|
-
const commitBump =
|
|
125
|
+
const commitBump = matchBumpSize(commit.message, defaultSizes);
|
|
120
126
|
const affectsBump = commitBump !== 'skip';
|
|
121
127
|
|
|
122
128
|
const marker = affectsBump ? `${c.green('✦')}` : `${c.gray('○')}`;
|
package/src/index.ts
CHANGED
package/src/init.ts
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
|
|
4
|
+
import { Effect } from 'effect';
|
|
5
|
+
|
|
6
|
+
import { log } from './display';
|
|
7
|
+
import { writeLockfile, type LockfileData } from './lockfile';
|
|
8
|
+
import type { PackageConfig } from './types';
|
|
9
|
+
import { VcsProviderService, type VcsProvider } from './vcs';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Initializes the `.relacher.lock` file if it does not exist.
|
|
13
|
+
* It resolves the version using each package's `versionFallback`,
|
|
14
|
+
* creates the lockfile, and commits it to establish the baseline.
|
|
15
|
+
*/
|
|
16
|
+
export function init(
|
|
17
|
+
packages: PackageConfig[],
|
|
18
|
+
options: { cwd?: string } = {},
|
|
19
|
+
): Effect.Effect<void, Error, VcsProvider> {
|
|
20
|
+
return Effect.gen(function*() {
|
|
21
|
+
const cwd = options.cwd || process.cwd();
|
|
22
|
+
const lockPath = path.resolve(cwd, '.relacher.lock');
|
|
23
|
+
|
|
24
|
+
if (fs.existsSync(lockPath)) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const vcs = yield* VcsProviderService;
|
|
29
|
+
|
|
30
|
+
// Check for dirty repository status
|
|
31
|
+
const isDirty = yield* vcs.isDirty();
|
|
32
|
+
if (isDirty) {
|
|
33
|
+
return yield* Effect.fail(
|
|
34
|
+
new Error('Cannot initialize lockfile: repository has dirty status.'),
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const lockfile: LockfileData = { packages: {} };
|
|
39
|
+
|
|
40
|
+
let warn_flag = false;
|
|
41
|
+
for (const pkg of packages) {
|
|
42
|
+
let version = '0.0.0';
|
|
43
|
+
if (pkg.versionFallback) {
|
|
44
|
+
try {
|
|
45
|
+
const fallback = pkg.versionFallback.readFallback(cwd);
|
|
46
|
+
if (fallback) {
|
|
47
|
+
version = fallback;
|
|
48
|
+
}
|
|
49
|
+
} catch (_) {
|
|
50
|
+
log.warn(`Version fallback failed for package ${pkg.name}`);
|
|
51
|
+
warn_flag = true;
|
|
52
|
+
// Fall back to default version if reading fails
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const isPrerelease = version.includes('-');
|
|
57
|
+
lockfile.packages[pkg.name] = {
|
|
58
|
+
version,
|
|
59
|
+
lastStableVersion: isPrerelease ? undefined : version,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (warn_flag) {
|
|
64
|
+
log.warn(
|
|
65
|
+
'One or more package failed to retrieve their version, update .relacher.lockfile manually.',
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
writeLockfile(cwd, lockfile);
|
|
70
|
+
|
|
71
|
+
const commitMessage = `chore: initialize .relacher.lock\n\nInitialized package versions from workspace fallbacks.`;
|
|
72
|
+
yield* vcs.commit(commitMessage);
|
|
73
|
+
}) as Effect.Effect<void, Error, VcsProvider>;
|
|
74
|
+
}
|
package/src/prepare.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
|
|
4
|
-
import { Effect } from 'effect';
|
|
4
|
+
import { Effect, Option } from 'effect';
|
|
5
5
|
|
|
6
6
|
import type {
|
|
7
7
|
Commit,
|
|
@@ -13,6 +13,7 @@ import type {
|
|
|
13
13
|
DependencyError,
|
|
14
14
|
} from './types';
|
|
15
15
|
import type { UpdateAction, UpdateActionResolved } from './updater';
|
|
16
|
+
import { VcsProviderService } from './vcs';
|
|
16
17
|
import { VersionManagerService, type VersionManager } from './versioning';
|
|
17
18
|
import type { BumpSize } from './versioning/types';
|
|
18
19
|
|
|
@@ -190,10 +191,14 @@ export function prepare(
|
|
|
190
191
|
name: err.name,
|
|
191
192
|
message: err.message,
|
|
192
193
|
})) as DependencyError[],
|
|
194
|
+
isDirty: false,
|
|
193
195
|
};
|
|
194
196
|
}
|
|
195
197
|
|
|
196
198
|
const versionManager = yield* VersionManagerService;
|
|
199
|
+
const vcsOption = yield* Effect.serviceOption(VcsProviderService);
|
|
200
|
+
const isDirty = Option.isSome(vcsOption) ? yield* vcsOption.value.isDirty() : false;
|
|
201
|
+
|
|
197
202
|
const cwd = options.cwd || process.cwd();
|
|
198
203
|
|
|
199
204
|
const items = yield* initReportItems(packages, cwd, options.excludeNestedWatches);
|
|
@@ -215,6 +220,7 @@ export function prepare(
|
|
|
215
220
|
name: r.name,
|
|
216
221
|
message: `Package ${r.name} is missing a version or a required update file.`,
|
|
217
222
|
})) as DependencyError[],
|
|
223
|
+
isDirty,
|
|
218
224
|
};
|
|
219
225
|
}
|
|
220
226
|
|
|
@@ -222,6 +228,7 @@ export function prepare(
|
|
|
222
228
|
isEmpty,
|
|
223
229
|
deps,
|
|
224
230
|
isInvalid: false,
|
|
231
|
+
isDirty,
|
|
225
232
|
};
|
|
226
233
|
}) as Effect.Effect<PreparedUpdate, Error, VersionManager>;
|
|
227
234
|
}
|
package/src/run.ts
CHANGED
|
@@ -56,6 +56,12 @@ export function run(
|
|
|
56
56
|
return Effect.gen(function*() {
|
|
57
57
|
const vcs = yield* VcsProviderService;
|
|
58
58
|
|
|
59
|
+
// Check for dirty repository status
|
|
60
|
+
const isDirty = yield* vcs.isDirty();
|
|
61
|
+
if (isDirty) {
|
|
62
|
+
return yield* Effect.fail(new Error('Cannot run release: repository has dirty status.'));
|
|
63
|
+
}
|
|
64
|
+
|
|
59
65
|
// Reject run early if preparation is flagged as invalid
|
|
60
66
|
if (prepared.isInvalid) {
|
|
61
67
|
const messages = prepared.errors
|
package/src/types.ts
CHANGED
|
@@ -41,10 +41,8 @@ export interface DependencyError {
|
|
|
41
41
|
export type PreparedUpdate = {
|
|
42
42
|
isEmpty: boolean;
|
|
43
43
|
deps: DependencyUpdateReport[];
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
| { isInvalid: false }
|
|
47
|
-
);
|
|
44
|
+
isDirty?: boolean;
|
|
45
|
+
} & ({ isInvalid: true; errors: DependencyError[] } | { isInvalid: false });
|
|
48
46
|
|
|
49
47
|
export interface DependencyUpdateReport {
|
|
50
48
|
name: string;
|
package/src/vcs/git.ts
CHANGED
|
@@ -115,6 +115,12 @@ export function findGitLastReleaseCommit(
|
|
|
115
115
|
);
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
+
export function isGitDirty(cwd: string): Effect.Effect<boolean, never> {
|
|
119
|
+
return runGit('git diff --name-only', cwd).pipe(
|
|
120
|
+
Effect.map((output) => output.trim().length > 0),
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
|
|
118
124
|
// Service Factory Implementation
|
|
119
125
|
export function makeGitVcsProvider(cwd: string): VcsProvider {
|
|
120
126
|
return VcsProviderService.of({
|
|
@@ -131,6 +137,8 @@ export function makeGitVcsProvider(cwd: string): VcsProvider {
|
|
|
131
137
|
Effect.flatMap(() => runGit(`git commit -m "${message}"`, cwd)),
|
|
132
138
|
Effect.asVoid,
|
|
133
139
|
),
|
|
140
|
+
|
|
141
|
+
isDirty: () => isGitDirty(cwd),
|
|
134
142
|
});
|
|
135
143
|
}
|
|
136
144
|
|
package/src/vcs/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Context, Effect } from 'effect';
|
|
1
|
+
import { Context, type Effect } from 'effect';
|
|
2
2
|
|
|
3
3
|
import type { Commit } from '../types';
|
|
4
4
|
|
|
@@ -18,6 +18,8 @@ export interface VcsProvider {
|
|
|
18
18
|
) => Effect.Effect<string | null, Error>;
|
|
19
19
|
|
|
20
20
|
readonly commit: (message: string) => Effect.Effect<void, Error>;
|
|
21
|
+
|
|
22
|
+
readonly isDirty: () => Effect.Effect<boolean, Error>;
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
export const VcsProviderService = Context.Service<VcsProvider>('VcsProviderService');
|
package/src/vcs/jj.ts
CHANGED
|
@@ -93,7 +93,6 @@ export function findJjLastReleaseCommit(
|
|
|
93
93
|
currentVersion: string,
|
|
94
94
|
cwd: string,
|
|
95
95
|
): Effect.Effect<string | null, never> {
|
|
96
|
-
// Query only commits modifying the lockfile using highly-compatible path filtering
|
|
97
96
|
return runJj('log --no-graph -T \'commit_id ++ "\\n"\' -- .relacher.lock', cwd).pipe(
|
|
98
97
|
Effect.map((output) => {
|
|
99
98
|
const hashes = output
|
|
@@ -106,7 +105,6 @@ export function findJjLastReleaseCommit(
|
|
|
106
105
|
|
|
107
106
|
for (const hash of hashes) {
|
|
108
107
|
try {
|
|
109
|
-
// Attempt the retrieval, catching any command or JSON-parsing errors
|
|
110
108
|
const content = execSync(`jj file show .relacher.lock -r ${hash}`, {
|
|
111
109
|
cwd,
|
|
112
110
|
encoding: 'utf8',
|
|
@@ -131,6 +129,30 @@ export function findJjLastReleaseCommit(
|
|
|
131
129
|
);
|
|
132
130
|
}
|
|
133
131
|
|
|
132
|
+
export function isJjDirty(cwd: string): Effect.Effect<boolean, never> {
|
|
133
|
+
return Effect.gen(function*() {
|
|
134
|
+
// 1. Check if current commit @ is not empty
|
|
135
|
+
const currentStatus = yield* runJj(
|
|
136
|
+
'log --no-graph -r @ -T \'if(empty, "empty", "not-empty")\'',
|
|
137
|
+
cwd,
|
|
138
|
+
);
|
|
139
|
+
if (currentStatus.trim() === 'not-empty') {
|
|
140
|
+
return true;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// 2. Check if there are any commits without a description in the history (excluding root and the current commit)
|
|
144
|
+
const historyDescriptions = yield* runJj(
|
|
145
|
+
'log --no-graph -r "::@ & ~@ & ~root()" -T \'if(description, "1", "0")\'',
|
|
146
|
+
cwd,
|
|
147
|
+
);
|
|
148
|
+
if (historyDescriptions.includes('0')) {
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return false;
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
|
|
134
156
|
// Service Factory Implementation
|
|
135
157
|
export function makeJjVcsProvider(cwd: string): VcsProvider {
|
|
136
158
|
return VcsProviderService.of({
|
|
@@ -143,6 +165,8 @@ export function makeJjVcsProvider(cwd: string): VcsProvider {
|
|
|
143
165
|
findJjLastReleaseCommit(packageName, currentVersion, cwd),
|
|
144
166
|
|
|
145
167
|
commit: (message) => runJj(`commit -m "${message}"`, cwd).pipe(Effect.asVoid),
|
|
168
|
+
|
|
169
|
+
isDirty: () => isJjDirty(cwd),
|
|
146
170
|
});
|
|
147
171
|
}
|
|
148
172
|
|
|
@@ -7,9 +7,9 @@ export const defaultSizes: SizePatterns = {
|
|
|
7
7
|
skip: { pattern: '^release|^chore|^infra|^docs|^test|^ci|^build' },
|
|
8
8
|
};
|
|
9
9
|
|
|
10
|
-
export const defaultCascadeRules:
|
|
11
|
-
skip:
|
|
12
|
-
patch:
|
|
13
|
-
minor:
|
|
14
|
-
major:
|
|
10
|
+
export const defaultCascadeRules: CascadeRules = {
|
|
11
|
+
skip: 'skip',
|
|
12
|
+
patch: 'patch',
|
|
13
|
+
minor: 'patch',
|
|
14
|
+
major: 'minor',
|
|
15
15
|
};
|
package/src/versioning/types.ts
CHANGED
|
@@ -12,10 +12,4 @@ export interface SizePatterns {
|
|
|
12
12
|
skip: PatternConfig;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
export
|
|
16
|
-
skip?: Record<string, BumpSize>;
|
|
17
|
-
patch?: Record<string, BumpSize>;
|
|
18
|
-
minor?: Record<string, BumpSize>;
|
|
19
|
-
major?: Record<string, BumpSize>;
|
|
20
|
-
[key: string]: Record<string, BumpSize> | undefined;
|
|
21
|
-
}
|
|
15
|
+
export type CascadeRules = Record<string, BumpSize>;
|
|
@@ -47,28 +47,6 @@ const getBumpSizeByPriority = (priorityValue: number, originalBump: BumpSize): B
|
|
|
47
47
|
return 'skip';
|
|
48
48
|
};
|
|
49
49
|
|
|
50
|
-
const getCascadeRule = (
|
|
51
|
-
original: BumpSize,
|
|
52
|
-
dependencyBump: BumpSize,
|
|
53
|
-
activeRules: Record<string, Record<string, BumpSize> | undefined>,
|
|
54
|
-
): BumpSize | undefined => {
|
|
55
|
-
const origKey =
|
|
56
|
-
typeof original === 'string' ? original : original.size ? `pre-${original.size}` : 'pre';
|
|
57
|
-
const depKey =
|
|
58
|
-
typeof dependencyBump === 'string'
|
|
59
|
-
? dependencyBump
|
|
60
|
-
: dependencyBump.size
|
|
61
|
-
? `pre-${dependencyBump.size}`
|
|
62
|
-
: 'pre';
|
|
63
|
-
|
|
64
|
-
const rule = activeRules[origKey]?.[depKey];
|
|
65
|
-
if (rule !== undefined) return rule;
|
|
66
|
-
|
|
67
|
-
const fallBackOrigKey = typeof original === 'string' ? original : 'patch';
|
|
68
|
-
const fallBackDepKey = typeof dependencyBump === 'string' ? dependencyBump : 'patch';
|
|
69
|
-
return activeRules[fallBackOrigKey]?.[fallBackDepKey];
|
|
70
|
-
};
|
|
71
|
-
|
|
72
50
|
const isVersionGreater = (v1: string, v2: string): boolean => {
|
|
73
51
|
const parts1 = v1.replace(/^v/, '').split('.').map(Number);
|
|
74
52
|
const parts2 = v2.replace(/^v/, '').split('.').map(Number);
|
|
@@ -175,28 +153,59 @@ export const makeVcsVersionManager = (
|
|
|
175
153
|
},
|
|
176
154
|
|
|
177
155
|
propagateBumps: (sorted) => {
|
|
178
|
-
const activeRules: Record<string,
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
156
|
+
const activeRules: Record<string, BumpSize> = {
|
|
157
|
+
patch: 'patch',
|
|
158
|
+
minor: 'patch',
|
|
159
|
+
major: 'patch',
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
// Helper to merge cascade rules from both flat and legacy nested structures defensively
|
|
163
|
+
const mergeRules = (rules: any) => {
|
|
164
|
+
if (!rules) return;
|
|
165
|
+
for (const [key, val] of Object.entries(rules)) {
|
|
166
|
+
if (typeof val === 'string') {
|
|
167
|
+
activeRules[key] = val as BumpSize;
|
|
168
|
+
} else if (val && typeof val === 'object') {
|
|
169
|
+
for (const [subKey, subVal] of Object.entries(val)) {
|
|
170
|
+
if (typeof subVal === 'string') {
|
|
171
|
+
activeRules[subKey] = subVal as BumpSize;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
183
176
|
};
|
|
184
177
|
|
|
178
|
+
mergeRules(defaultCascadeRules);
|
|
179
|
+
mergeRules(cascadeRules);
|
|
180
|
+
|
|
185
181
|
for (const item of sorted) {
|
|
186
|
-
let
|
|
182
|
+
let maxCascadedBump: BumpSize = 'skip';
|
|
183
|
+
|
|
187
184
|
for (const depName of item.depends) {
|
|
188
185
|
const depItem = sorted.find((r) => r.name === depName);
|
|
189
|
-
if (depItem) {
|
|
190
|
-
|
|
191
|
-
|
|
186
|
+
if (depItem && depItem.bump !== 'skip') {
|
|
187
|
+
const depBumpKey =
|
|
188
|
+
typeof depItem.bump === 'string'
|
|
189
|
+
? depItem.bump
|
|
190
|
+
: depItem.bump.kind === 'pre'
|
|
191
|
+
? depItem.bump.size
|
|
192
|
+
? `pre-${depItem.bump.size}`
|
|
193
|
+
: 'pre'
|
|
194
|
+
: 'patch';
|
|
195
|
+
|
|
196
|
+
const cascadedResult = activeRules[depBumpKey];
|
|
197
|
+
if (
|
|
198
|
+
cascadedResult &&
|
|
199
|
+
getBumpPriority(cascadedResult) > getBumpPriority(maxCascadedBump)
|
|
200
|
+
) {
|
|
201
|
+
maxCascadedBump = cascadedResult;
|
|
192
202
|
}
|
|
193
203
|
}
|
|
194
204
|
}
|
|
195
205
|
|
|
196
|
-
if
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
item.bump = targetBump;
|
|
206
|
+
// Apply the cascaded bump only if its priority exceeds the package's existing bump
|
|
207
|
+
if (getBumpPriority(maxCascadedBump) > getBumpPriority(item.bump)) {
|
|
208
|
+
item.bump = maxCascadedBump;
|
|
200
209
|
}
|
|
201
210
|
|
|
202
211
|
item.newVersion =
|