Skip to content

Commit 8f34277

Browse files
committed
make updating rules files idempotent
1 parent 6b8704b commit 8f34277

File tree

3 files changed

+67
-46
lines changed

3 files changed

+67
-46
lines changed

packages/cli-v3/src/commands/install-rules.ts

Lines changed: 65 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
1-
import { confirm, intro, isCancel, log, multiselect, outro, select, spinner } from "@clack/prompts";
1+
import { confirm, intro, isCancel, log, multiselect, outro } from "@clack/prompts";
2+
import { ResolvedConfig } from "@trigger.dev/core/v3/build";
23
import chalk from "chalk";
34
import { Command, Option as CommandOption } from "commander";
5+
import { join } from "node:path";
6+
import * as semver from "semver";
47
import { z } from "zod";
58
import { OutroCommandError, wrapCommandAction } from "../cli/common.js";
6-
import {
7-
readConfigHasSeenRulesInstallPrompt,
8-
readConfigLastRulesInstallPromptVersion,
9-
writeConfigHasSeenRulesInstallPrompt,
10-
writeConfigLastRulesInstallPromptVersion,
11-
} from "../utilities/configFiles.js";
12-
import { printStandloneInitialBanner } from "../utilities/initialBanner.js";
9+
import { loadConfig } from "../config.js";
1310
import {
1411
GithubRulesManifestLoader,
1512
loadRulesManifest,
@@ -18,13 +15,16 @@ import {
1815
RulesManifest,
1916
RulesManifestVersionOption,
2017
} from "../rules/manifest.js";
21-
import { logger } from "../utilities/logger.js";
22-
import { join } from "node:path";
23-
import { writeToFile } from "../utilities/fileSystem.js";
24-
import * as semver from "semver";
25-
import { loadConfig } from "../config.js";
26-
import { ResolvedConfig } from "@trigger.dev/core/v3/build";
2718
import { cliLink } from "../utilities/cliOutput.js";
19+
import {
20+
readConfigHasSeenRulesInstallPrompt,
21+
readConfigLastRulesInstallPromptVersion,
22+
writeConfigHasSeenRulesInstallPrompt,
23+
writeConfigLastRulesInstallPromptVersion,
24+
} from "../utilities/configFiles.js";
25+
import { pathExists, readFile, safeWriteFile } from "../utilities/fileSystem.js";
26+
import { printStandloneInitialBanner } from "../utilities/initialBanner.js";
27+
import { logger } from "../utilities/logger.js";
2828

2929
const clients = [
3030
"claude-code",
@@ -372,16 +372,58 @@ async function performInstallDefaultOptionForClient(
372372

373373
// Try and read the existing rules file
374374
const rulesFileAbsolutePath = join(process.cwd(), rulesFilePath);
375-
await writeToFile(rulesFileAbsolutePath, rulesFileContents, mergeStrategy);
375+
await writeToFile(rulesFileAbsolutePath, rulesFileContents, mergeStrategy, option.name);
376376

377377
return { option, location: rulesFilePath };
378378
}
379379

380+
async function writeToFile(
381+
path: string,
382+
contents: string,
383+
mergeStrategy: "overwrite" | "replace" = "overwrite",
384+
sectionName: string
385+
) {
386+
const exists = await pathExists(path);
387+
388+
if (exists) {
389+
switch (mergeStrategy) {
390+
case "overwrite": {
391+
await safeWriteFile(path, contents);
392+
break;
393+
}
394+
case "replace": {
395+
const existingContents = await readFile(path);
396+
397+
const pattern = new RegExp(
398+
`<!-- TRIGGER.DEV ${sectionName} START -->.*?<!-- TRIGGER.DEV ${sectionName} END -->`,
399+
"gs"
400+
);
401+
402+
// If the section name is not found, just append the new content
403+
if (!pattern.test(existingContents)) {
404+
await safeWriteFile(path, existingContents + "\n\n" + contents);
405+
break;
406+
}
407+
408+
const updatedContent = existingContents.replace(pattern, contents);
409+
410+
await safeWriteFile(path, updatedContent);
411+
break;
412+
}
413+
default: {
414+
throw new Error(`Unknown merge strategy: ${mergeStrategy}`);
415+
}
416+
}
417+
} else {
418+
await safeWriteFile(path, contents);
419+
}
420+
}
421+
380422
async function performInstallClaudeCodeSubagentOptionForClient(option: RulesManifestVersionOption) {
381423
const rulesFilePath = ".claude/agents/trigger-dev-task-writer.md";
382-
const rulesFileContents = `# ${option.title}\n\n${option.contents}`;
424+
const rulesFileContents = option.contents;
383425

384-
await writeToFile(rulesFilePath, rulesFileContents, "overwrite");
426+
await writeToFile(rulesFilePath, rulesFileContents, "overwrite", option.name);
385427

386428
return { option, location: rulesFilePath };
387429
}
@@ -437,7 +479,7 @@ async function resolveRulesFileMergeStrategyForClient(clientName: (typeof client
437479
case "agents.md":
438480
case "gemini-cli":
439481
case "claude-code": {
440-
return "append";
482+
return "replace";
441483
}
442484
default: {
443485
return "overwrite";
@@ -478,7 +520,11 @@ async function resolveRulesFileContentsForClient(
478520
);
479521
}
480522
default: {
481-
return option.contents;
523+
return $output(
524+
`<!-- TRIGGER.DEV ${option.name} START -->`,
525+
option.contents,
526+
`<!-- TRIGGER.DEV ${option.name} END -->`
527+
);
482528
}
483529
}
484530
}

packages/cli-v3/src/utilities/fileSystem.ts

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -103,33 +103,6 @@ export function readJSONFileSync(path: string) {
103103
return JSON.parse(fileContents);
104104
}
105105

106-
export async function writeToFile(
107-
path: string,
108-
contents: string,
109-
mergeStrategy: "overwrite" | "append" = "overwrite"
110-
) {
111-
const exists = await pathExists(path);
112-
113-
if (exists) {
114-
switch (mergeStrategy) {
115-
case "overwrite": {
116-
await safeWriteFile(path, contents);
117-
break;
118-
}
119-
case "append": {
120-
const existingContents = await readFile(path);
121-
await safeWriteFile(path, existingContents + "\n\n" + contents);
122-
break;
123-
}
124-
default: {
125-
throw new Error(`Unknown merge strategy: ${mergeStrategy}`);
126-
}
127-
}
128-
} else {
129-
await safeWriteFile(path, contents);
130-
}
131-
}
132-
133106
export function safeDeleteFileSync(path: string) {
134107
try {
135108
fs.unlinkSync(path);

rules/4.0.0/basic-tasks.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,5 @@
55
# Triggering
66

77
# Waits
8+
9+
Now this is here

0 commit comments

Comments
 (0)