git-vibe-setup 4.0.0 → 4.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/dist/cli.js +13 -3
- package/dist/install.d.ts +1 -0
- package/dist/install.js +42 -5
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { realpathSync } from "node:fs";
|
|
3
|
-
import { resolve } from "node:path";
|
|
3
|
+
import { relative, resolve } from "node:path";
|
|
4
4
|
import { pathToFileURL } from "node:url";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import { fetchConsumerStarterFiles } from "./consumer-starter.js";
|
|
7
7
|
import { githubTokenFromEnvironment } from "./github-api.js";
|
|
8
|
-
import { blockingInstallPaths, buildInstallFiles, buildUpdateFiles, existingFilesError, installFiles, unmanagedWorkflowUpdateError, unmanagedWorkflowUpdatePaths, updateFiles, } from "./install.js";
|
|
8
|
+
import { blockingInstallPaths, buildInstallFiles, buildUpdateFiles, existingFilesError, installFiles, obsoleteWorkflowCleanupPaths, unmanagedWorkflowUpdateError, unmanagedWorkflowUpdatePaths, updateFiles, } from "./install.js";
|
|
9
9
|
import { renderManualSetupInstructions } from "./instructions.js";
|
|
10
10
|
import { latestReleaseTag } from "./releases.js";
|
|
11
11
|
const usage = `Usage:
|
|
@@ -42,10 +42,11 @@ export async function runUpdate(runtime = {}) {
|
|
|
42
42
|
const sourceFiles = await fetchConsumerStarterFiles({ fetchImpl, githubToken, releaseTag });
|
|
43
43
|
const files = buildUpdateFiles({ cwd, releaseTag, sourceFiles });
|
|
44
44
|
const unmanagedPaths = unmanagedWorkflowUpdatePaths(files);
|
|
45
|
+
const cleanupPaths = obsoleteWorkflowCleanupPaths(files);
|
|
45
46
|
if (unmanagedPaths.length > 0)
|
|
46
47
|
throw unmanagedWorkflowUpdateError(unmanagedPaths, cwd);
|
|
47
48
|
updateFiles(files);
|
|
48
|
-
(runtime.log || console.log)(
|
|
49
|
+
(runtime.log || console.log)(updateSuccessMessage({ cleanupPaths, cwd, releaseTag }));
|
|
49
50
|
}
|
|
50
51
|
export async function setupCli(runtime = {}) {
|
|
51
52
|
const argv = runtime.argv || process.argv.slice(2);
|
|
@@ -149,6 +150,15 @@ function validateReleaseTag(releaseTag) {
|
|
|
149
150
|
}
|
|
150
151
|
throw new Error(`Invalid release tag: ${releaseTag}. Release tags must look like v3.0.4 or v3.0.4-rc.1.`);
|
|
151
152
|
}
|
|
153
|
+
function updateSuccessMessage(options) {
|
|
154
|
+
const message = `GitVibe config and workflow files updated with reusable workflows pinned to ${options.releaseTag}.`;
|
|
155
|
+
if (options.cleanupPaths.length === 0)
|
|
156
|
+
return message;
|
|
157
|
+
const listed = options.cleanupPaths
|
|
158
|
+
.map((path) => `- ${relative(options.cwd, path) || path}`)
|
|
159
|
+
.join("\n");
|
|
160
|
+
return `${message}\nObsolete workflow files were left in place for manual review:\n${listed}`;
|
|
161
|
+
}
|
|
152
162
|
/* c8 ignore start */
|
|
153
163
|
if (isDirectRun(import.meta.url)) {
|
|
154
164
|
const exitCode = await setupCli();
|
package/dist/install.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ export declare function buildUpdateFiles(options: {
|
|
|
16
16
|
}): InstallFile[];
|
|
17
17
|
export declare function blockingInstallPaths(files: InstallFile[]): string[];
|
|
18
18
|
export declare function unmanagedWorkflowUpdatePaths(files: InstallFile[]): string[];
|
|
19
|
+
export declare function obsoleteWorkflowCleanupPaths(files: InstallFile[]): string[];
|
|
19
20
|
export declare function installFiles(files: InstallFile[]): void;
|
|
20
21
|
export declare function updateFiles(files: InstallFile[]): void;
|
|
21
22
|
export declare function existingFilesError(paths: string[], cwd: string): Error;
|
package/dist/install.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
1
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { basename, dirname, join, relative } from "node:path";
|
|
3
3
|
const requiredInstallSourcePaths = [
|
|
4
4
|
".github/git-vibe.yml",
|
|
5
|
-
".github/workflows/address-feedback.yml",
|
|
6
|
-
".github/workflows/develop.yml",
|
|
7
5
|
".github/workflows/investigate.yml",
|
|
8
6
|
".github/workflows/materialize.yml",
|
|
9
7
|
".github/workflows/review.yml",
|
|
@@ -14,6 +12,7 @@ const requiredInstallSourcePaths = [
|
|
|
14
12
|
];
|
|
15
13
|
const requiredWorkflowSourcePaths = requiredInstallSourcePaths.filter(isWorkflowSourcePath);
|
|
16
14
|
const requiredUpdateSourcePaths = [".github/git-vibe.yml", ...requiredWorkflowSourcePaths];
|
|
15
|
+
const managedWorkflowMarker = "# GitVibe managed workflow wrapper";
|
|
17
16
|
export function buildInstallFiles(options) {
|
|
18
17
|
requireSourcePaths(options.sourceFiles, requiredInstallSourcePaths, options.releaseTag);
|
|
19
18
|
return options.sourceFiles
|
|
@@ -39,6 +38,12 @@ export function unmanagedWorkflowUpdatePaths(files) {
|
|
|
39
38
|
.map((file) => file.targetPath)
|
|
40
39
|
.sort();
|
|
41
40
|
}
|
|
41
|
+
export function obsoleteWorkflowCleanupPaths(files) {
|
|
42
|
+
return obsoleteWorkflowPaths(files)
|
|
43
|
+
.filter((targetPath) => !isMarkedManagedWorkflowFile(targetPath, basename(targetPath)))
|
|
44
|
+
.filter((targetPath) => isManagedWorkflowFile(targetPath, basename(targetPath)))
|
|
45
|
+
.sort();
|
|
46
|
+
}
|
|
42
47
|
export function installFiles(files) {
|
|
43
48
|
const createdDirectories = [];
|
|
44
49
|
const createdFiles = [];
|
|
@@ -63,6 +68,10 @@ export function updateFiles(files) {
|
|
|
63
68
|
snapshots.push(snapshotFile(file.targetPath));
|
|
64
69
|
writeFileSync(file.targetPath, file.content);
|
|
65
70
|
}
|
|
71
|
+
for (const targetPath of obsoleteManagedWorkflowPaths(files)) {
|
|
72
|
+
snapshots.push(snapshotFile(targetPath));
|
|
73
|
+
rmSync(targetPath, { force: true });
|
|
74
|
+
}
|
|
66
75
|
}
|
|
67
76
|
catch (error) {
|
|
68
77
|
rollbackUpdate(snapshots, createdDirectories);
|
|
@@ -85,9 +94,37 @@ export function migrateGitVibeConfigContent(content) {
|
|
|
85
94
|
return ensureTrailingNewline(migrateGithubAuthConfig(migratedComments));
|
|
86
95
|
}
|
|
87
96
|
function isManagedWorkflowTarget(file) {
|
|
97
|
+
return isManagedWorkflowFile(file.targetPath, basename(file.targetPath));
|
|
98
|
+
}
|
|
99
|
+
function isManagedWorkflowFile(targetPath, workflowName) {
|
|
100
|
+
try {
|
|
101
|
+
return managedWorkflowPattern(workflowName).test(readFileSync(targetPath, "utf8"));
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function obsoleteManagedWorkflowPaths(files) {
|
|
108
|
+
return obsoleteWorkflowPaths(files)
|
|
109
|
+
.filter((targetPath) => isMarkedManagedWorkflowFile(targetPath, basename(targetPath)))
|
|
110
|
+
.sort();
|
|
111
|
+
}
|
|
112
|
+
function obsoleteWorkflowPaths(files) {
|
|
113
|
+
const workflowDirectory = dirname(files.find(isWorkflowInstallFile)?.targetPath || "");
|
|
114
|
+
if (!workflowDirectory || workflowDirectory === ".")
|
|
115
|
+
return [];
|
|
116
|
+
if (!existsSync(workflowDirectory))
|
|
117
|
+
return [];
|
|
118
|
+
const currentWorkflowNames = new Set(files.filter(isWorkflowInstallFile).map((file) => basename(file.targetPath)));
|
|
119
|
+
return readdirSync(workflowDirectory, { withFileTypes: true })
|
|
120
|
+
.filter((entry) => entry.isFile() && !currentWorkflowNames.has(entry.name))
|
|
121
|
+
.map((entry) => join(workflowDirectory, entry.name));
|
|
122
|
+
}
|
|
123
|
+
function isMarkedManagedWorkflowFile(targetPath, workflowName) {
|
|
88
124
|
try {
|
|
89
|
-
const
|
|
90
|
-
return
|
|
125
|
+
const content = readFileSync(targetPath, "utf8");
|
|
126
|
+
return (content.startsWith(`${managedWorkflowMarker}\n`) &&
|
|
127
|
+
managedWorkflowPattern(workflowName).test(content));
|
|
91
128
|
}
|
|
92
129
|
catch {
|
|
93
130
|
return false;
|