git-vibe-setup 3.1.1 → 4.0.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 +3 -3
- package/dist/install.d.ts +2 -1
- package/dist/install.js +56 -4
- package/dist/instructions.js +2 -3
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -5,7 +5,7 @@ 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,
|
|
8
|
+
import { blockingInstallPaths, buildInstallFiles, buildUpdateFiles, existingFilesError, installFiles, 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:
|
|
@@ -40,12 +40,12 @@ export async function runUpdate(runtime = {}) {
|
|
|
40
40
|
const githubToken = runtime.githubToken || githubTokenFromEnvironment();
|
|
41
41
|
const releaseTag = await resolveReleaseTag(runtime, fetchImpl, githubToken);
|
|
42
42
|
const sourceFiles = await fetchConsumerStarterFiles({ fetchImpl, githubToken, releaseTag });
|
|
43
|
-
const files =
|
|
43
|
+
const files = buildUpdateFiles({ cwd, releaseTag, sourceFiles });
|
|
44
44
|
const unmanagedPaths = unmanagedWorkflowUpdatePaths(files);
|
|
45
45
|
if (unmanagedPaths.length > 0)
|
|
46
46
|
throw unmanagedWorkflowUpdateError(unmanagedPaths, cwd);
|
|
47
47
|
updateFiles(files);
|
|
48
|
-
(runtime.log || console.log)(`GitVibe workflow files updated with reusable workflows pinned to ${releaseTag}.`);
|
|
48
|
+
(runtime.log || console.log)(`GitVibe config and workflow files updated with reusable workflows pinned to ${releaseTag}.`);
|
|
49
49
|
}
|
|
50
50
|
export async function setupCli(runtime = {}) {
|
|
51
51
|
const argv = runtime.argv || process.argv.slice(2);
|
package/dist/install.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export declare function buildInstallFiles(options: {
|
|
|
9
9
|
releaseTag: string;
|
|
10
10
|
sourceFiles: ConsumerStarterFile[];
|
|
11
11
|
}): InstallFile[];
|
|
12
|
-
export declare function
|
|
12
|
+
export declare function buildUpdateFiles(options: {
|
|
13
13
|
cwd: string;
|
|
14
14
|
releaseTag: string;
|
|
15
15
|
sourceFiles: ConsumerStarterFile[];
|
|
@@ -21,3 +21,4 @@ export declare function updateFiles(files: InstallFile[]): void;
|
|
|
21
21
|
export declare function existingFilesError(paths: string[], cwd: string): Error;
|
|
22
22
|
export declare function unmanagedWorkflowUpdateError(paths: string[], cwd: string): Error;
|
|
23
23
|
export declare function pinWorkflowReleaseRefs(content: string, releaseTag: string): string;
|
|
24
|
+
export declare function migrateGitVibeConfigContent(content: string): string;
|
package/dist/install.js
CHANGED
|
@@ -13,17 +13,18 @@ const requiredInstallSourcePaths = [
|
|
|
13
13
|
".git-vibe/role-group/security.md",
|
|
14
14
|
];
|
|
15
15
|
const requiredWorkflowSourcePaths = requiredInstallSourcePaths.filter(isWorkflowSourcePath);
|
|
16
|
+
const requiredUpdateSourcePaths = [".github/git-vibe.yml", ...requiredWorkflowSourcePaths];
|
|
16
17
|
export function buildInstallFiles(options) {
|
|
17
18
|
requireSourcePaths(options.sourceFiles, requiredInstallSourcePaths, options.releaseTag);
|
|
18
19
|
return options.sourceFiles
|
|
19
20
|
.filter((file) => isInstallSourcePath(file.relativePath))
|
|
20
21
|
.map((file) => buildInstallFile(file, options.cwd, options.releaseTag));
|
|
21
22
|
}
|
|
22
|
-
export function
|
|
23
|
-
requireSourcePaths(options.sourceFiles,
|
|
23
|
+
export function buildUpdateFiles(options) {
|
|
24
|
+
requireSourcePaths(options.sourceFiles, requiredUpdateSourcePaths, options.releaseTag);
|
|
24
25
|
return options.sourceFiles
|
|
25
|
-
.filter((file) =>
|
|
26
|
-
.map((file) =>
|
|
26
|
+
.filter((file) => isUpdateSourcePath(file.relativePath))
|
|
27
|
+
.map((file) => buildUpdateFile(file, options.cwd, options.releaseTag));
|
|
27
28
|
}
|
|
28
29
|
export function blockingInstallPaths(files) {
|
|
29
30
|
return files
|
|
@@ -33,6 +34,7 @@ export function blockingInstallPaths(files) {
|
|
|
33
34
|
}
|
|
34
35
|
export function unmanagedWorkflowUpdatePaths(files) {
|
|
35
36
|
return files
|
|
37
|
+
.filter(isWorkflowInstallFile)
|
|
36
38
|
.filter((file) => existsSync(file.targetPath) && !isManagedWorkflowTarget(file))
|
|
37
39
|
.map((file) => file.targetPath)
|
|
38
40
|
.sort();
|
|
@@ -78,6 +80,10 @@ export function unmanagedWorkflowUpdateError(paths, cwd) {
|
|
|
78
80
|
export function pinWorkflowReleaseRefs(content, releaseTag) {
|
|
79
81
|
return content.replace(/(uses:\s*markhuangai\/git-vibe\/\.github\/workflows\/[^\s@]+)@[^\s]+/g, (_match, workflowReference) => `${workflowReference}@${releaseTag}`);
|
|
80
82
|
}
|
|
83
|
+
export function migrateGitVibeConfigContent(content) {
|
|
84
|
+
const migratedComments = migrateLegacyEventDeliveryComments(content);
|
|
85
|
+
return ensureTrailingNewline(migrateGithubAuthConfig(migratedComments));
|
|
86
|
+
}
|
|
81
87
|
function isManagedWorkflowTarget(file) {
|
|
82
88
|
try {
|
|
83
89
|
const workflowName = basename(file.targetPath);
|
|
@@ -150,6 +156,22 @@ function buildInstallFile(sourceFile, cwd, releaseTag) {
|
|
|
150
156
|
targetPath: join(cwd, safeRelativePath(sourceFile.relativePath)),
|
|
151
157
|
};
|
|
152
158
|
}
|
|
159
|
+
function buildUpdateFile(sourceFile, cwd, releaseTag) {
|
|
160
|
+
const targetPath = join(cwd, safeRelativePath(sourceFile.relativePath));
|
|
161
|
+
const existingContent = fileContentIfExists(targetPath);
|
|
162
|
+
let content = pinWorkflowReleaseRefs(sourceFile.content, releaseTag);
|
|
163
|
+
if (sourceFile.relativePath === ".github/git-vibe.yml" && existingContent !== undefined) {
|
|
164
|
+
content = migrateGitVibeConfigContent(existingContent);
|
|
165
|
+
}
|
|
166
|
+
else if (isWorkflowSourcePath(sourceFile.relativePath) && existingContent !== undefined) {
|
|
167
|
+
content = preserveWorkflowRunner(content, existingContent);
|
|
168
|
+
}
|
|
169
|
+
return {
|
|
170
|
+
content,
|
|
171
|
+
sourcePath: sourceFile.sourcePath,
|
|
172
|
+
targetPath,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
153
175
|
function requireSourcePaths(sourceFiles, requiredPaths, releaseTag) {
|
|
154
176
|
const sourcePaths = new Set(sourceFiles.map((file) => file.relativePath));
|
|
155
177
|
const missingPaths = requiredPaths.filter((path) => !sourcePaths.has(path));
|
|
@@ -161,9 +183,15 @@ function requireSourcePaths(sourceFiles, requiredPaths, releaseTag) {
|
|
|
161
183
|
function isInstallSourcePath(relativePath) {
|
|
162
184
|
return relativePath.startsWith(".github/") || relativePath.startsWith(".git-vibe/");
|
|
163
185
|
}
|
|
186
|
+
function isUpdateSourcePath(relativePath) {
|
|
187
|
+
return relativePath === ".github/git-vibe.yml" || isWorkflowSourcePath(relativePath);
|
|
188
|
+
}
|
|
164
189
|
function isWorkflowSourcePath(relativePath) {
|
|
165
190
|
return relativePath.startsWith(".github/workflows/") && relativePath.endsWith(".yml");
|
|
166
191
|
}
|
|
192
|
+
function isWorkflowInstallFile(file) {
|
|
193
|
+
return file.sourcePath.includes(".github/workflows/") && file.sourcePath.endsWith(".yml");
|
|
194
|
+
}
|
|
167
195
|
function safeRelativePath(relativePath) {
|
|
168
196
|
const segments = relativePath.split("/");
|
|
169
197
|
const isSafe = relativePath.length > 0 &&
|
|
@@ -174,3 +202,27 @@ function safeRelativePath(relativePath) {
|
|
|
174
202
|
return relativePath;
|
|
175
203
|
throw new Error(`git-vibe-setup found an unsafe starter file path: ${relativePath}`);
|
|
176
204
|
}
|
|
205
|
+
function fileContentIfExists(targetPath) {
|
|
206
|
+
if (!existsSync(targetPath))
|
|
207
|
+
return undefined;
|
|
208
|
+
return readFileSync(targetPath, "utf8");
|
|
209
|
+
}
|
|
210
|
+
function preserveWorkflowRunner(generatedContent, existingContent) {
|
|
211
|
+
const runner = /^\s+runner:\s*(.+)$/m.exec(existingContent)?.[1];
|
|
212
|
+
if (!runner)
|
|
213
|
+
return generatedContent;
|
|
214
|
+
return generatedContent.replace(/^(\s+runner:\s*).+$/m, `$1${runner}`);
|
|
215
|
+
}
|
|
216
|
+
function migrateLegacyEventDeliveryComments(content) {
|
|
217
|
+
return content.replace(/^event_delivery:\n # webhook: repository webhook points at the self-hosted GitVibe server\.\n # relay: webhook proxy\/tunnel such as Smee, Hookdeck, Cloudflare Tunnel, or ngrok\.\n # actions: no-server receiver workflows in the consumer repository\.\n # polling: local\/scheduled worker polls GitHub APIs with cursors\/ETags\.\n/m, "event_delivery:\n # Hosted GitHub App installs configure webhooks centrally; repositories do not create hooks.\n");
|
|
218
|
+
}
|
|
219
|
+
function migrateGithubAuthConfig(content) {
|
|
220
|
+
const githubAppAuth = "github_auth:\n mode: github-app\n";
|
|
221
|
+
if (/^github_auth:\n/m.test(content)) {
|
|
222
|
+
return content.replace(/^github_auth:\n(?:[ \t]+.*(?:\n|$))*/m, githubAppAuth);
|
|
223
|
+
}
|
|
224
|
+
return `${content.trimEnd()}\n\n${githubAppAuth}`;
|
|
225
|
+
}
|
|
226
|
+
function ensureTrailingNewline(content) {
|
|
227
|
+
return content.endsWith("\n") ? content : `${content}\n`;
|
|
228
|
+
}
|
package/dist/instructions.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
const requiredSecrets = [
|
|
2
2
|
["GITVIBE_AI_ENV_JSON", "JSON env bundle for AI provider config and CLI auth."],
|
|
3
|
-
["GITVIBE_GITHUB_TOKEN", "Fine-grained PAT for GitVibe workflow and server writes."],
|
|
4
|
-
["WEBHOOK_SECRET", "Webhook shared secret mapped to GITHUB_WEBHOOK_SECRET in deployment."],
|
|
5
3
|
];
|
|
6
4
|
const usefulVariables = [
|
|
7
5
|
"GITVIBE_BASE_BRANCH",
|
|
@@ -13,8 +11,9 @@ export function renderManualSetupInstructions(releaseTag) {
|
|
|
13
11
|
const lines = [
|
|
14
12
|
`GitVibe starter files installed with reusable workflows pinned to ${releaseTag}.`,
|
|
15
13
|
"",
|
|
16
|
-
"Configure
|
|
14
|
+
"Configure this GitHub secret manually before running the workflows:",
|
|
17
15
|
...requiredSecrets.map(([name, description]) => `- ${name}: ${description}`),
|
|
16
|
+
"- GITVIBE_MCP_ENV_JSON: optional JSON env bundle for MCP credentials.",
|
|
18
17
|
"",
|
|
19
18
|
"Optional repository variables:",
|
|
20
19
|
...usefulVariables.map((name) => `- ${name}`),
|