@bobfrankston/npmglobalize 1.0.160 → 1.0.162
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 +27 -0
- package/cli.js +3 -0
- package/ignorepatterns.json5 +2 -1
- package/lib.d.ts +17 -1
- package/lib.js +198 -22
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -189,6 +189,31 @@ npmglobalize -np # --nopublish (formerly --apply)
|
|
|
189
189
|
npmglobalize --cleanup # Restore original file: references
|
|
190
190
|
```
|
|
191
191
|
|
|
192
|
+
### 📝 Release Notes via `.commitmsg`
|
|
193
|
+
|
|
194
|
+
For multi-line or reusable release notes, write them to a `.commitmsg` file in the package root instead of passing them on the command line:
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
cat > .commitmsg <<'EOF'
|
|
198
|
+
Added foo feature
|
|
199
|
+
Fixed bar regression
|
|
200
|
+
EOF
|
|
201
|
+
npmglobalize
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Behavior:
|
|
205
|
+
- If `-m` / `-message` is **not** given and `.commitmsg` exists, its contents are used as the commit message (and force a release even if the working tree is otherwise clean).
|
|
206
|
+
- After a successful `npm publish`, npmglobalize:
|
|
207
|
+
1. Appends the contents to `npmchanges.md` under a `## v<version> — <YYYY-MM-DD>` header (creating the file if needed)
|
|
208
|
+
2. Deletes `.commitmsg`
|
|
209
|
+
3. Commits both changes as `Log v<version> to npmchanges.md` and pushes
|
|
210
|
+
|
|
211
|
+
Notes:
|
|
212
|
+
- **Git/GitHub only.** npm publish does not consume git commit messages; `npmchanges.md` lives in the git repo and on GitHub but is excluded from the published npm tarball (the standard `*.md` rule keeps only `README.md`).
|
|
213
|
+
- If both `-m` and `.commitmsg` are present, `-m` wins and `.commitmsg` is left alone (not consumed).
|
|
214
|
+
- If publish fails, `.commitmsg` is preserved for the next attempt.
|
|
215
|
+
- `.commitmsg` is auto-added to `.npmignore` (security pattern) so it never leaks into the tarball.
|
|
216
|
+
|
|
192
217
|
### 🔧 Git Integration & Error Recovery
|
|
193
218
|
|
|
194
219
|
**Automatic tag conflict resolution**:
|
|
@@ -288,6 +313,8 @@ Publishing requires being on a branch so commits and tags can be properly tracke
|
|
|
288
313
|
-nopublish, -np Just transform, don't publish (persisted to config)
|
|
289
314
|
-cleanup Restore file: dependencies from .dependencies backup
|
|
290
315
|
-m, -message <msg> Custom commit message (forces release even without changes)
|
|
316
|
+
If -m not given, a `.commitmsg` file (if present) is used instead.
|
|
317
|
+
See "Release Notes via .commitmsg" below.
|
|
291
318
|
```
|
|
292
319
|
|
|
293
320
|
### Dependency Options
|
package/cli.js
CHANGED
|
@@ -27,6 +27,9 @@ Release Options:
|
|
|
27
27
|
-nopublish, -np Just transform, don't publish (persisted to config)
|
|
28
28
|
-cleanup Restore from .dependencies
|
|
29
29
|
-m, -message <msg> Custom commit message (forces release even without changes)
|
|
30
|
+
If -m not given and a .commitmsg file exists in cwd, its
|
|
31
|
+
contents are used. After a successful publish it is appended
|
|
32
|
+
to npmchanges.md (with version header) and deleted.
|
|
30
33
|
|
|
31
34
|
Dependency Options:
|
|
32
35
|
-update-deps, -ud Update package.json to latest (minor/patch only, safe)
|
package/ignorepatterns.json5
CHANGED
package/lib.d.ts
CHANGED
|
@@ -186,12 +186,25 @@ export declare function getFileRefs(pkg: any): Map<string, {
|
|
|
186
186
|
name: string;
|
|
187
187
|
value: string;
|
|
188
188
|
}>;
|
|
189
|
+
/** Expand workspace entries (which may include globs like 'packages/*') to relative
|
|
190
|
+
* dir paths from rootDir, normalized to forward slashes. Only `<base>/*` is expanded;
|
|
191
|
+
* more exotic globs (`**`, `?`, character classes) are passed through unchanged. */
|
|
192
|
+
export declare function expandWorkspaceEntries(rootDir: string, entries: string[]): string[];
|
|
189
193
|
/** Resolve workspace entries to package info. Skips dirs without package.json or with private:true. */
|
|
190
194
|
export declare function resolveWorkspacePackages(rootDir: string): Array<{
|
|
191
195
|
name: string;
|
|
192
196
|
dir: string;
|
|
193
197
|
pkg: any;
|
|
194
198
|
}>;
|
|
199
|
+
/** Like resolveWorkspacePackages but INCLUDES private packages and exposes the
|
|
200
|
+
* workspaces[] entry (relative path) for each. Use for build ordering, where
|
|
201
|
+
* a private workspace package is still part of the dep graph. */
|
|
202
|
+
export declare function resolveAllWorkspacePackages(rootDir: string): Array<{
|
|
203
|
+
name: string;
|
|
204
|
+
dir: string;
|
|
205
|
+
pkg: any;
|
|
206
|
+
entry: string;
|
|
207
|
+
}>;
|
|
195
208
|
/** Build a dependency graph among workspace packages. Returns Map<name, Set<depName>>. */
|
|
196
209
|
export declare function buildDependencyGraph(packages: Array<{
|
|
197
210
|
name: string;
|
|
@@ -244,7 +257,10 @@ export declare function compareVersions(a: number[], b: number[]): number;
|
|
|
244
257
|
/** Fix version/tag mismatches */
|
|
245
258
|
export declare function fixVersionTagMismatch(cwd: string, pkg: any, verbose?: boolean): boolean;
|
|
246
259
|
/** Return declared deps (dependencies + devDependencies) that don't resolve from
|
|
247
|
-
* `pkgDir`. Skips `
|
|
260
|
+
* `pkgDir`. Skips `workspace:`/`link:` specs (handled by workspace tooling /
|
|
261
|
+
* rarely used). `file:` deps are checked: npm installs them as junctions
|
|
262
|
+
* (Windows) or symlinks, and `fs.existsSync` traverses both, so a missing
|
|
263
|
+
* file: dep is a real out-of-sync case worth flagging.
|
|
248
264
|
* A declared dep that doesn't resolve means `package.json` and installed
|
|
249
265
|
* `node_modules/` are out of sync (e.g. dep added but `npm install` not re-run). */
|
|
250
266
|
export declare function missingDeps(pkgDir: string, pkg: any): string[];
|
package/lib.js
CHANGED
|
@@ -685,6 +685,41 @@ export function getFileRefs(pkg) {
|
|
|
685
685
|
return refs;
|
|
686
686
|
}
|
|
687
687
|
// ─── Workspace helpers ───────────────────────────────────────────────
|
|
688
|
+
/** Expand workspace entries (which may include globs like 'packages/*') to relative
|
|
689
|
+
* dir paths from rootDir, normalized to forward slashes. Only `<base>/*` is expanded;
|
|
690
|
+
* more exotic globs (`**`, `?`, character classes) are passed through unchanged. */
|
|
691
|
+
export function expandWorkspaceEntries(rootDir, entries) {
|
|
692
|
+
const expanded = [];
|
|
693
|
+
const seen = new Set();
|
|
694
|
+
const push = (rel) => { if (!seen.has(rel)) {
|
|
695
|
+
seen.add(rel);
|
|
696
|
+
expanded.push(rel);
|
|
697
|
+
} };
|
|
698
|
+
for (const entry of entries) {
|
|
699
|
+
const norm = entry.replace(/\\/g, '/');
|
|
700
|
+
const m = norm.match(/^(.+?)\/\*$/);
|
|
701
|
+
if (m && !m[1].includes('*')) {
|
|
702
|
+
const baseDir = path.resolve(rootDir, m[1]);
|
|
703
|
+
if (!fs.existsSync(baseDir) || !fs.statSync(baseDir).isDirectory())
|
|
704
|
+
continue;
|
|
705
|
+
const subs = fs.readdirSync(baseDir).sort();
|
|
706
|
+
for (const sub of subs) {
|
|
707
|
+
if (sub.startsWith('.'))
|
|
708
|
+
continue;
|
|
709
|
+
const subPath = path.join(baseDir, sub);
|
|
710
|
+
if (!fs.statSync(subPath).isDirectory())
|
|
711
|
+
continue;
|
|
712
|
+
if (!fs.existsSync(path.join(subPath, 'package.json')))
|
|
713
|
+
continue;
|
|
714
|
+
push(`${m[1]}/${sub}`);
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
else {
|
|
718
|
+
push(norm);
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
return expanded;
|
|
722
|
+
}
|
|
688
723
|
/** Resolve workspace entries to package info. Skips dirs without package.json or with private:true. */
|
|
689
724
|
export function resolveWorkspacePackages(rootDir) {
|
|
690
725
|
const rootPkg = readPackageJson(rootDir);
|
|
@@ -692,7 +727,7 @@ export function resolveWorkspacePackages(rootDir) {
|
|
|
692
727
|
if (!Array.isArray(workspaces))
|
|
693
728
|
return [];
|
|
694
729
|
const results = [];
|
|
695
|
-
for (const entry of workspaces) {
|
|
730
|
+
for (const entry of expandWorkspaceEntries(rootDir, workspaces)) {
|
|
696
731
|
const pkgDir = path.resolve(rootDir, entry);
|
|
697
732
|
const pkgJsonPath = path.join(pkgDir, 'package.json');
|
|
698
733
|
if (!fs.existsSync(pkgJsonPath))
|
|
@@ -704,6 +739,87 @@ export function resolveWorkspacePackages(rootDir) {
|
|
|
704
739
|
}
|
|
705
740
|
return results;
|
|
706
741
|
}
|
|
742
|
+
/** Like resolveWorkspacePackages but INCLUDES private packages and exposes the
|
|
743
|
+
* workspaces[] entry (relative path) for each. Use for build ordering, where
|
|
744
|
+
* a private workspace package is still part of the dep graph. */
|
|
745
|
+
export function resolveAllWorkspacePackages(rootDir) {
|
|
746
|
+
const rootPkg = readPackageJson(rootDir);
|
|
747
|
+
const workspaces = rootPkg.workspaces;
|
|
748
|
+
if (!Array.isArray(workspaces))
|
|
749
|
+
return [];
|
|
750
|
+
const results = [];
|
|
751
|
+
for (const entry of expandWorkspaceEntries(rootDir, workspaces)) {
|
|
752
|
+
const pkgDir = path.resolve(rootDir, entry);
|
|
753
|
+
const pkgJsonPath = path.join(pkgDir, 'package.json');
|
|
754
|
+
if (!fs.existsSync(pkgJsonPath))
|
|
755
|
+
continue;
|
|
756
|
+
const pkg = readPackageJson(pkgDir);
|
|
757
|
+
results.push({ name: pkg.name || entry, dir: pkgDir, pkg, entry });
|
|
758
|
+
}
|
|
759
|
+
return results;
|
|
760
|
+
}
|
|
761
|
+
/** Workspace-root build with `npm run ... --workspaces` runs sub-packages in
|
|
762
|
+
* workspaces[] array order. If that order doesn't match topological dep order,
|
|
763
|
+
* a consumer can be compiled against a sibling whose .d.ts/.js is still stale.
|
|
764
|
+
* Temporarily rewrites workspaces[] to topological order for the build, then
|
|
765
|
+
* restores it. Returns undefined if no rewrite is needed (or no build script
|
|
766
|
+
* uses --workspaces). */
|
|
767
|
+
function reorderWorkspacesForBuild(cwd, pkg, verbose) {
|
|
768
|
+
if (!Array.isArray(pkg.workspaces) || pkg.workspaces.length < 2)
|
|
769
|
+
return undefined;
|
|
770
|
+
const buildScript = typeof pkg.scripts?.build === 'string' ? pkg.scripts.build : '';
|
|
771
|
+
if (!buildScript.includes('--workspaces') && !buildScript.includes('-ws'))
|
|
772
|
+
return undefined;
|
|
773
|
+
const all = resolveAllWorkspacePackages(cwd);
|
|
774
|
+
if (all.length < 2)
|
|
775
|
+
return undefined;
|
|
776
|
+
const graph = buildDependencyGraph(all);
|
|
777
|
+
let order;
|
|
778
|
+
try {
|
|
779
|
+
order = topologicalSort(graph);
|
|
780
|
+
}
|
|
781
|
+
catch (e) {
|
|
782
|
+
console.error(colors.yellow(` Skipping workspace reorder: ${e.message}`));
|
|
783
|
+
return undefined;
|
|
784
|
+
}
|
|
785
|
+
const nameToEntry = new Map();
|
|
786
|
+
for (const p of all)
|
|
787
|
+
nameToEntry.set(p.name, p.entry);
|
|
788
|
+
const newEntries = order
|
|
789
|
+
.map(n => nameToEntry.get(n))
|
|
790
|
+
.filter((e) => !!e);
|
|
791
|
+
// If the expanded current order already matches topological order AND has no
|
|
792
|
+
// globs, nothing to do. (When globs are present, npm expands them in fs order
|
|
793
|
+
// — we always need to write an explicit list.)
|
|
794
|
+
const original = pkg.workspaces.slice();
|
|
795
|
+
const hasGlob = original.some(e => e.includes('*'));
|
|
796
|
+
if (!hasGlob) {
|
|
797
|
+
const cur = original.map(e => e.replace(/\\/g, '/'));
|
|
798
|
+
if (cur.length === newEntries.length && cur.every((v, i) => v === newEntries[i])) {
|
|
799
|
+
return undefined;
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
pkg.workspaces = newEntries;
|
|
803
|
+
writePackageJson(cwd, pkg);
|
|
804
|
+
if (verbose) {
|
|
805
|
+
console.log(colors.dim(` Reordered workspaces[] for topological build: ${newEntries.join(' → ')}`));
|
|
806
|
+
}
|
|
807
|
+
let restored = false;
|
|
808
|
+
return () => {
|
|
809
|
+
if (restored)
|
|
810
|
+
return;
|
|
811
|
+
restored = true;
|
|
812
|
+
try {
|
|
813
|
+
pkg.workspaces = original;
|
|
814
|
+
const onDisk = readPackageJson(cwd);
|
|
815
|
+
onDisk.workspaces = original;
|
|
816
|
+
writePackageJson(cwd, onDisk);
|
|
817
|
+
}
|
|
818
|
+
catch (e) {
|
|
819
|
+
console.error(colors.yellow(` Warning: failed to restore workspaces[]: ${e.message}`));
|
|
820
|
+
}
|
|
821
|
+
};
|
|
822
|
+
}
|
|
707
823
|
/** Build a dependency graph among workspace packages. Returns Map<name, Set<depName>>. */
|
|
708
824
|
export function buildDependencyGraph(packages) {
|
|
709
825
|
const nameSet = new Set(packages.map(p => p.name));
|
|
@@ -1338,7 +1454,10 @@ function depResolves(startDir, depName) {
|
|
|
1338
1454
|
}
|
|
1339
1455
|
}
|
|
1340
1456
|
/** Return declared deps (dependencies + devDependencies) that don't resolve from
|
|
1341
|
-
* `pkgDir`. Skips `
|
|
1457
|
+
* `pkgDir`. Skips `workspace:`/`link:` specs (handled by workspace tooling /
|
|
1458
|
+
* rarely used). `file:` deps are checked: npm installs them as junctions
|
|
1459
|
+
* (Windows) or symlinks, and `fs.existsSync` traverses both, so a missing
|
|
1460
|
+
* file: dep is a real out-of-sync case worth flagging.
|
|
1342
1461
|
* A declared dep that doesn't resolve means `package.json` and installed
|
|
1343
1462
|
* `node_modules/` are out of sync (e.g. dep added but `npm install` not re-run). */
|
|
1344
1463
|
export function missingDeps(pkgDir, pkg) {
|
|
@@ -1350,7 +1469,7 @@ export function missingDeps(pkgDir, pkg) {
|
|
|
1350
1469
|
for (const [name, spec] of Object.entries(deps)) {
|
|
1351
1470
|
if (typeof spec !== 'string')
|
|
1352
1471
|
continue;
|
|
1353
|
-
if (spec.startsWith('
|
|
1472
|
+
if (spec.startsWith('workspace:') || spec.startsWith('link:'))
|
|
1354
1473
|
continue;
|
|
1355
1474
|
if (!depResolves(pkgDir, name))
|
|
1356
1475
|
missing.push(name);
|
|
@@ -3281,25 +3400,34 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
|
|
|
3281
3400
|
ensureFileDepModules(cwd, verbose);
|
|
3282
3401
|
console.log(`${timestamp()} Running build...`);
|
|
3283
3402
|
if (!dryRun) {
|
|
3284
|
-
//
|
|
3285
|
-
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
|
|
3403
|
+
// For workspace roots whose build invokes `--workspaces`, npm uses
|
|
3404
|
+
// workspaces[] array order; rewrite to topological order so deps build
|
|
3405
|
+
// before consumers (avoids stale-.d.ts errors in cross-package imports).
|
|
3406
|
+
const restoreWorkspaces = reorderWorkspacesForBuild(cwd, pkg, verbose);
|
|
3407
|
+
try {
|
|
3408
|
+
// Always capture output so we can extract tsc errors for the summary
|
|
3409
|
+
const buildResult = runCommand('npm', ['run', 'build'], { cwd, silent: true });
|
|
3410
|
+
if (!buildResult.success) {
|
|
3411
|
+
const buildOutput = buildResult.stderr || buildResult.output;
|
|
3412
|
+
if (buildOutput)
|
|
3413
|
+
console.error(buildOutput);
|
|
3414
|
+
console.error(colors.red('ERROR: Build failed'));
|
|
3415
|
+
diagnoseBuildFailure(buildOutput || '', cwd);
|
|
3416
|
+
const firstErr = extractFirstTscError(buildOutput || '');
|
|
3417
|
+
recordBuildIssue(pkg.name || path.basename(cwd), 'error', firstErr || 'Build failed');
|
|
3418
|
+
if (!force) {
|
|
3419
|
+
return false;
|
|
3420
|
+
}
|
|
3421
|
+
console.log(colors.yellow('Continuing with --force despite build failure...'));
|
|
3422
|
+
}
|
|
3423
|
+
else {
|
|
3424
|
+
if (verbose && buildResult.output)
|
|
3425
|
+
process.stdout.write(buildResult.output);
|
|
3426
|
+
console.log(`${timestamp()} ${colors.green('✓ Build succeeded')}`);
|
|
3296
3427
|
}
|
|
3297
|
-
console.log(colors.yellow('Continuing with --force despite build failure...'));
|
|
3298
3428
|
}
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
process.stdout.write(buildResult.output);
|
|
3302
|
-
console.log(`${timestamp()} ${colors.green('✓ Build succeeded')}`);
|
|
3429
|
+
finally {
|
|
3430
|
+
restoreWorkspaces?.();
|
|
3303
3431
|
}
|
|
3304
3432
|
}
|
|
3305
3433
|
else {
|
|
@@ -3919,11 +4047,29 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
|
|
|
3919
4047
|
}
|
|
3920
4048
|
// Re-check git status after all transformations and potential commits
|
|
3921
4049
|
currentGitStatus = getGitStatus(cwd);
|
|
4050
|
+
// If no -m given, fall back to .commitmsg file contents (one-shot changelog entry).
|
|
4051
|
+
// Consumed (appended to npmchanges.md + deleted) only after a successful publish.
|
|
4052
|
+
const commitMsgPath = path.join(cwd, '.commitmsg');
|
|
4053
|
+
let commitMsgFromFile = null;
|
|
4054
|
+
let effectiveMessage = message;
|
|
4055
|
+
if (!effectiveMessage && fs.existsSync(commitMsgPath)) {
|
|
4056
|
+
try {
|
|
4057
|
+
const content = fs.readFileSync(commitMsgPath, 'utf-8').trim();
|
|
4058
|
+
if (content) {
|
|
4059
|
+
commitMsgFromFile = content;
|
|
4060
|
+
effectiveMessage = content;
|
|
4061
|
+
console.log(colors.cyan(` Using .commitmsg for commit message (${content.split('\n')[0].slice(0, 60)}${content.length > 60 ? '…' : ''})`));
|
|
4062
|
+
}
|
|
4063
|
+
}
|
|
4064
|
+
catch (err) {
|
|
4065
|
+
console.error(colors.yellow(` Warning: could not read .commitmsg: ${err.message}`));
|
|
4066
|
+
}
|
|
4067
|
+
}
|
|
3922
4068
|
// Check if there are changes to commit or a custom message
|
|
3923
4069
|
// Skip this check for first publish (currentAccess null) or just-initialized repos
|
|
3924
4070
|
const isFirstPublish = !currentAccess;
|
|
3925
4071
|
let skipVersionBump = false;
|
|
3926
|
-
if (!currentGitStatus.hasUncommitted && !
|
|
4072
|
+
if (!currentGitStatus.hasUncommitted && !effectiveMessage && !justInitialized && !isFirstPublish) {
|
|
3927
4073
|
// Check if the current version is actually on npm (it might have failed to publish previously)
|
|
3928
4074
|
const versionCheck = spawnSafe('npm', ['view', `${pkg.name}@${pkg.version}`, 'version'], {
|
|
3929
4075
|
shell: process.platform === 'win32',
|
|
@@ -4074,7 +4220,7 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
|
|
|
4074
4220
|
}
|
|
4075
4221
|
// Git operations
|
|
4076
4222
|
if (currentGitStatus.hasUncommitted) {
|
|
4077
|
-
const commitMsg =
|
|
4223
|
+
const commitMsg = effectiveMessage || 'Pre-release commit';
|
|
4078
4224
|
console.log(`${timestamp()} Committing changes: ${commitMsg}`);
|
|
4079
4225
|
if (!dryRun) {
|
|
4080
4226
|
// Remove 'nul' files that break git on Windows
|
|
@@ -4701,6 +4847,36 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
|
|
|
4701
4847
|
const finalAccess = effectiveNpmVisibility || currentAccess || (isScoped ? 'restricted' : 'public');
|
|
4702
4848
|
const accessLabel = (finalAccess === 'restricted' || finalAccess === 'private') ? 'PRIVATE' : 'PUBLIC';
|
|
4703
4849
|
console.log(`${timestamp()} ${colors.green(`✓ Published to npm as ${accessLabel}`)}`);
|
|
4850
|
+
// Consume .commitmsg: append to npmchanges.md, delete the file, commit+push.
|
|
4851
|
+
// Only runs if .commitmsg was actually used as the commit message.
|
|
4852
|
+
if (commitMsgFromFile) {
|
|
4853
|
+
try {
|
|
4854
|
+
const publishedVersion = readPackageJson(cwd).version;
|
|
4855
|
+
const npmChangesPath = path.join(cwd, 'npmchanges.md');
|
|
4856
|
+
const date = new Date().toISOString().slice(0, 10);
|
|
4857
|
+
const header = `## v${publishedVersion} — ${date}\n\n`;
|
|
4858
|
+
const entry = header + commitMsgFromFile.trim() + '\n\n';
|
|
4859
|
+
const existing = fs.existsSync(npmChangesPath)
|
|
4860
|
+
? fs.readFileSync(npmChangesPath, 'utf-8')
|
|
4861
|
+
: '# npm Publish Changes\n\n';
|
|
4862
|
+
const sep = existing.endsWith('\n') ? '' : '\n';
|
|
4863
|
+
fs.writeFileSync(npmChangesPath, existing + sep + entry);
|
|
4864
|
+
try {
|
|
4865
|
+
fs.unlinkSync(commitMsgPath);
|
|
4866
|
+
}
|
|
4867
|
+
catch { /* ignore */ }
|
|
4868
|
+
runCommand('git', ['add', 'npmchanges.md', '.commitmsg'], { cwd, silent: true });
|
|
4869
|
+
const logResult = gitCommit(`Log v${publishedVersion} to npmchanges.md`, cwd);
|
|
4870
|
+
if (logResult.success) {
|
|
4871
|
+
console.log(colors.green(` ✓ Appended to npmchanges.md and removed .commitmsg`));
|
|
4872
|
+
if (currentGitStatus.hasRemote)
|
|
4873
|
+
pushWithProtection(cwd, verbose);
|
|
4874
|
+
}
|
|
4875
|
+
}
|
|
4876
|
+
catch (err) {
|
|
4877
|
+
console.error(colors.yellow(` Warning: could not update npmchanges.md: ${err.message}`));
|
|
4878
|
+
}
|
|
4879
|
+
}
|
|
4704
4880
|
}
|
|
4705
4881
|
else {
|
|
4706
4882
|
console.log(` [dry-run] Would run: npm publish ${quiet ? '--quiet' : ''}`);
|