@codefresh-io/gitops-release 1.0.1 → 1.2.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.
Files changed (48) hide show
  1. package/README.md +74 -1
  2. package/dist/agent/hooks.d.ts +12 -0
  3. package/dist/agent/hooks.d.ts.map +1 -0
  4. package/dist/agent/hooks.js +181 -0
  5. package/dist/agent/hooks.js.map +1 -0
  6. package/dist/agent/index.d.ts +4 -0
  7. package/dist/agent/index.d.ts.map +1 -0
  8. package/dist/agent/index.js +6 -0
  9. package/dist/agent/index.js.map +1 -0
  10. package/dist/agent/prompts.d.ts +6 -0
  11. package/dist/agent/prompts.d.ts.map +1 -0
  12. package/dist/agent/prompts.js +105 -0
  13. package/dist/agent/prompts.js.map +1 -0
  14. package/dist/agent/repl.d.ts +14 -0
  15. package/dist/agent/repl.d.ts.map +1 -0
  16. package/dist/agent/repl.js +177 -0
  17. package/dist/agent/repl.js.map +1 -0
  18. package/dist/commands/chat.d.ts +14 -0
  19. package/dist/commands/chat.d.ts.map +1 -0
  20. package/dist/commands/chat.js +24 -0
  21. package/dist/commands/chat.js.map +1 -0
  22. package/dist/commands/create.d.ts +5 -0
  23. package/dist/commands/create.d.ts.map +1 -1
  24. package/dist/commands/create.js +50 -2
  25. package/dist/commands/create.js.map +1 -1
  26. package/dist/commands/notes.d.ts +5 -0
  27. package/dist/commands/notes.d.ts.map +1 -1
  28. package/dist/commands/notes.js +81 -9
  29. package/dist/commands/notes.js.map +1 -1
  30. package/dist/commands/publish.d.ts +5 -0
  31. package/dist/commands/publish.d.ts.map +1 -1
  32. package/dist/commands/publish.js +32 -2
  33. package/dist/commands/publish.js.map +1 -1
  34. package/dist/commands/status.d.ts.map +1 -1
  35. package/dist/commands/status.js +47 -8
  36. package/dist/commands/status.js.map +1 -1
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +48 -10
  39. package/dist/index.js.map +1 -1
  40. package/dist/output/formatter.d.ts +5 -0
  41. package/dist/output/formatter.d.ts.map +1 -1
  42. package/dist/output/formatter.js +1 -1
  43. package/dist/output/formatter.js.map +1 -1
  44. package/dist/services/version.d.ts +22 -0
  45. package/dist/services/version.d.ts.map +1 -1
  46. package/dist/services/version.js +49 -0
  47. package/dist/services/version.js.map +1 -1
  48. package/package.json +2 -1
package/README.md CHANGED
@@ -21,6 +21,7 @@ If you prefer not to use this CLI (or don't have an Anthropic API key for AI rel
21
21
 
22
22
  - `GITHUB_TOKEN` environment variable with `repo` scope
23
23
  - `ANTHROPIC_API_KEY` environment variable (only for `notes` command)
24
+ - **Codefresh team:** Find this in 1Password under "Anthropic API Key - GitOps Release CLI"
24
25
 
25
26
  ## Usage
26
27
 
@@ -186,6 +187,57 @@ gitops-release cherry-pick 0.26 abc1234 --dry-run
186
187
  **Requirements:**
187
188
  - Must be run from within a local git checkout of the repository
188
189
 
190
+ ### `chat`
191
+
192
+ Start an interactive AI agent for release management. Instead of memorizing CLI commands, describe what you want in natural language.
193
+
194
+ ```bash
195
+ # Start the chat agent
196
+ gitops-release chat
197
+
198
+ # With verbose output (shows session info and costs)
199
+ gitops-release chat --verbose
200
+ ```
201
+
202
+ **Options:**
203
+ | Flag | Description |
204
+ |------|-------------|
205
+ | `-v, --verbose` | Show session details and API costs |
206
+
207
+ **Requirements:**
208
+ - `ANTHROPIC_API_KEY` environment variable
209
+ - Interactive terminal (TTY)
210
+
211
+ **Example session:**
212
+ ```
213
+ $ gitops-release chat
214
+ GitOps Release Agent [Experimental]
215
+
216
+ A conversational interface for managing GitOps runtime releases.
217
+ Ask questions like:
218
+ • "What releases are in progress?"
219
+ • "Show me the status of v0.27"
220
+ • "Generate release notes for 0.27.0"
221
+ • "Create a new release branch for 0.28"
222
+
223
+ Read operations auto-execute. Write operations require confirmation.
224
+ Type 'exit' to quit.
225
+
226
+ gitops> What's the current release status?
227
+ [Agent runs gitops-release status and explains the results]
228
+
229
+ gitops> Create a new release for 0.28
230
+ The agent wants to run:
231
+ gitops-release create 0.28
232
+
233
+ Allow this operation? (y/N)
234
+ ```
235
+
236
+ **Security:**
237
+ - Read-only commands (status, list, notes) execute automatically
238
+ - Write commands (create, publish, notes --apply) require explicit confirmation
239
+ - Only gitops-release CLI commands are allowed
240
+
189
241
  ### `completion <shell>`
190
242
 
191
243
  Generate shell completion script.
@@ -242,6 +294,21 @@ gitops-release status 0.26
242
294
  gitops-release publish 0.26.6
243
295
  ```
244
296
 
297
+ ### Using the Chat Agent
298
+
299
+ ```bash
300
+ # Start the interactive agent
301
+ gitops-release chat
302
+
303
+ # Then have a conversation:
304
+ # > "What releases are in progress?"
305
+ # > "Show me the status of 0.27"
306
+ # > "The PR looks good, let's publish it"
307
+ # > "exit"
308
+ ```
309
+
310
+ The agent understands context, so you can have natural conversations about releases without needing to remember exact command syntax.
311
+
245
312
  ### CI/Scripted Usage
246
313
 
247
314
  ```bash
@@ -269,7 +336,7 @@ gitops-release status 0.27 --json | jq '.ready_to_publish'
269
336
  | Variable | Required | Description |
270
337
  |----------|----------|-------------|
271
338
  | `GITHUB_TOKEN` | Yes | GitHub API token with `repo` scope |
272
- | `ANTHROPIC_API_KEY` | For `notes` | Anthropic API key for AI release notes |
339
+ | `ANTHROPIC_API_KEY` | For `notes`, `chat` | Anthropic API key for AI features |
273
340
  | `NO_COLOR` | No | Disable colors when set |
274
341
  | `EDITOR` | No | Editor for `notes --edit` (default: vim) |
275
342
 
@@ -325,7 +392,13 @@ src/
325
392
  │ ├── list.ts # List releases
326
393
  │ ├── notes.ts # AI-powered release notes
327
394
  │ ├── cherry-pick.ts # Cherry-pick commits
395
+ │ ├── chat.ts # Interactive AI agent
328
396
  │ └── completion.ts # Shell completion
397
+ ├── agent/
398
+ │ ├── index.ts # Agent module exports
399
+ │ ├── prompts.ts # System prompt for the agent
400
+ │ ├── hooks.ts # Permission control (canUseTool)
401
+ │ └── repl.ts # Interactive REPL implementation
329
402
  ├── services/
330
403
  │ ├── github.ts # GitHub API wrapper (Octokit)
331
404
  │ ├── version.ts # Version parsing/validation
@@ -0,0 +1,12 @@
1
+ import type { CanUseTool } from "@anthropic-ai/claude-agent-sdk";
2
+ /**
3
+ * Creates the canUseTool callback for permission control.
4
+ *
5
+ * This callback:
6
+ * - Handles AskUserQuestion tool for interactive user choices
7
+ * - Auto-allows only known read operations (gitops-release status, list, notes without --apply)
8
+ * - Prompts for confirmation on write operations and unknown commands
9
+ * - Denies all other tools
10
+ */
11
+ export declare function createPermissionHandler(): CanUseTool;
12
+ //# sourceMappingURL=hooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/agent/hooks.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAoB,MAAM,gCAAgC,CAAC;AA0LnF;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,IAAI,UAAU,CAgCpD"}
@@ -0,0 +1,181 @@
1
+ // ABOUTME: Permission control for the release management agent.
2
+ // ABOUTME: Implements canUseTool callback to auto-allow reads and confirm writes.
3
+ import { confirm, select, checkbox, input, Separator } from "@inquirer/prompts";
4
+ import { ExitPromptError } from "@inquirer/core";
5
+ import { getChalk } from "../output/formatter.js";
6
+ const c = getChalk({ noColor: process.env.NO_COLOR !== undefined });
7
+ /** Sentinel value to identify the "Other" option in select/checkbox prompts. */
8
+ const OTHER_OPTION = "__OTHER__";
9
+ /**
10
+ * Commands that are read-only and can be auto-executed.
11
+ */
12
+ const READ_COMMANDS = ["status", "list"];
13
+ /**
14
+ * Commands that modify state and require confirmation.
15
+ */
16
+ const WRITE_COMMANDS = ["create", "publish", "cherry-pick"];
17
+ /**
18
+ * Extracts the gitops-release subcommand from a bash command string.
19
+ * Returns null if not a gitops-release command.
20
+ *
21
+ * Handles various invocation methods:
22
+ * - gitops-release status
23
+ * - npx gitops-release status
24
+ * - npx @codefresh-io/gitops-release status
25
+ * - npx @codefresh-io/gitops-release@1.0.0 status
26
+ */
27
+ function extractGitopsCommand(bashCommand) {
28
+ const match = bashCommand.match(/gitops-release(?:@[\w.-]+)?\s+(\w+)/);
29
+ return match ? match[1] : null;
30
+ }
31
+ /**
32
+ * Classifies a bash command as read, write, or unknown.
33
+ * Consolidates all command classification logic in one place.
34
+ */
35
+ function classifyCommand(bashCommand) {
36
+ const command = extractGitopsCommand(bashCommand);
37
+ if (!command)
38
+ return "unknown";
39
+ if (WRITE_COMMANDS.includes(command))
40
+ return "write";
41
+ if (READ_COMMANDS.includes(command))
42
+ return "read";
43
+ // notes is a special case: read by default, write with --apply
44
+ if (command === "notes") {
45
+ return bashCommand.includes("--apply") ? "write" : "read";
46
+ }
47
+ return "unknown";
48
+ }
49
+ /** Messages returned when user declines or cancels an operation. */
50
+ const DENY_MESSAGES = {
51
+ declined: "User declined the operation. Ask what they would like to do instead.",
52
+ cancelled: "User cancelled the prompt. Ask what they would like to do instead.",
53
+ };
54
+ /**
55
+ * Builds choices array for select/checkbox prompts with an "Other" option.
56
+ */
57
+ function buildChoices(options) {
58
+ return [
59
+ ...options.map((opt) => ({
60
+ name: opt.description ? `${opt.label} ${c.dim(`- ${opt.description}`)}` : opt.label,
61
+ value: opt.label,
62
+ })),
63
+ new Separator(),
64
+ { name: "Other", value: OTHER_OPTION },
65
+ ];
66
+ }
67
+ /**
68
+ * Handles the AskUserQuestion tool with arrow-key navigation.
69
+ * Single-select: select prompt with "Other" option for custom input.
70
+ * Multi-select: checkbox prompt with "Other" option for custom input.
71
+ */
72
+ async function handleAskUserQuestion(questionInput) {
73
+ const answers = {};
74
+ try {
75
+ for (const q of questionInput.questions) {
76
+ if (q.multiSelect) {
77
+ // Multi-select: checkbox with "Other" option
78
+ const selected = await checkbox({
79
+ message: q.question,
80
+ choices: buildChoices(q.options),
81
+ loop: false,
82
+ });
83
+ let results = selected.filter((s) => s !== OTHER_OPTION);
84
+ // If "Other" was selected, prompt for custom value
85
+ if (selected.includes(OTHER_OPTION)) {
86
+ const custom = await input({ message: "Please specify:", required: true });
87
+ results.push(custom);
88
+ }
89
+ answers[q.question] = results.join(", ");
90
+ }
91
+ else {
92
+ // Single-select: select with "Other" option
93
+ const selected = await select({
94
+ message: q.question,
95
+ choices: buildChoices(q.options),
96
+ loop: false,
97
+ });
98
+ if (selected === OTHER_OPTION) {
99
+ answers[q.question] = await input({ message: "Please specify:", required: true });
100
+ }
101
+ else {
102
+ answers[q.question] = selected;
103
+ }
104
+ }
105
+ }
106
+ return {
107
+ behavior: "allow",
108
+ updatedInput: {
109
+ questions: questionInput.questions,
110
+ answers,
111
+ },
112
+ };
113
+ }
114
+ catch (error) {
115
+ if (error instanceof ExitPromptError) {
116
+ console.log();
117
+ return { behavior: "deny", message: DENY_MESSAGES.cancelled };
118
+ }
119
+ throw error;
120
+ }
121
+ }
122
+ /**
123
+ * Prompts the user for confirmation and returns the appropriate permission result.
124
+ * Handles Ctrl+C gracefully by treating it as a denial.
125
+ */
126
+ async function promptForConfirmation(inputData, label) {
127
+ const bashCommand = inputData.command ?? "";
128
+ console.log(c.yellow(`\n${label}:`));
129
+ console.log(c.cyan(` ${bashCommand}\n`));
130
+ try {
131
+ const approved = await confirm({
132
+ message: "Allow this operation?",
133
+ default: false,
134
+ });
135
+ return approved
136
+ ? { behavior: "allow", updatedInput: inputData }
137
+ : { behavior: "deny", message: DENY_MESSAGES.declined };
138
+ }
139
+ catch (error) {
140
+ if (error instanceof ExitPromptError) {
141
+ // User pressed Ctrl+C - treat as denial
142
+ console.log(); // Clean up the prompt line
143
+ return { behavior: "deny", message: DENY_MESSAGES.cancelled };
144
+ }
145
+ throw error;
146
+ }
147
+ }
148
+ /**
149
+ * Creates the canUseTool callback for permission control.
150
+ *
151
+ * This callback:
152
+ * - Handles AskUserQuestion tool for interactive user choices
153
+ * - Auto-allows only known read operations (gitops-release status, list, notes without --apply)
154
+ * - Prompts for confirmation on write operations and unknown commands
155
+ * - Denies all other tools
156
+ */
157
+ export function createPermissionHandler() {
158
+ return async (toolName, input, _options) => {
159
+ // Handle AskUserQuestion tool - let Claude ask the user questions
160
+ if (toolName === "AskUserQuestion") {
161
+ return handleAskUserQuestion(input);
162
+ }
163
+ // Only allow Bash tool - deny all other tools
164
+ if (toolName !== "Bash") {
165
+ return {
166
+ behavior: "deny",
167
+ message: `Tool "${toolName}" is not allowed. Use gitops-release CLI commands via Bash instead.`,
168
+ };
169
+ }
170
+ const bashCommand = input.command ?? "";
171
+ const commandType = classifyCommand(bashCommand);
172
+ // Auto-allow known safe gitops-release read operations
173
+ if (commandType === "read") {
174
+ return { behavior: "allow", updatedInput: input };
175
+ }
176
+ // Everything else (write or unknown) requires confirmation
177
+ const label = commandType === "write" ? "The agent wants to run" : "The agent wants to execute";
178
+ return promptForConfirmation(input, label);
179
+ };
180
+ }
181
+ //# sourceMappingURL=hooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../src/agent/hooks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export { RELEASE_AGENT_PROMPT } from "./prompts.js";
2
+ export { createPermissionHandler } from "./hooks.js";
3
+ export { runRepl, type ReplOptions } from "./repl.js";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/agent/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,6 @@
1
+ // ABOUTME: Agent module exports.
2
+ // ABOUTME: Provides public API for the release management agent.
3
+ export { RELEASE_AGENT_PROMPT } from "./prompts.js";
4
+ export { createPermissionHandler } from "./hooks.js";
5
+ export { runRepl } from "./repl.js";
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/agent/index.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,iEAAiE;AAEjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,OAAO,EAAoB,MAAM,WAAW,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * System prompt for the release management agent.
3
+ * Instructs Claude on available commands and how to use them.
4
+ */
5
+ export declare const RELEASE_AGENT_PROMPT = "You are a GitOps release management assistant.\n\nYou help manage releases for the gitops-runtime Helm chart by running CLI commands.\n\n## Available Commands\n\nRun these via the Bash tool:\n\n### Read-only (auto-execute)\n- `gitops-release status` - Show release overview (all versions)\n- `gitops-release status <version>` - Show specific version status (e.g., 0.27 or 0.27.0)\n- `gitops-release list` - List all releases\n- `gitops-release list -n 20` or `--limit 20` - List more releases\n- `gitops-release notes <version>` - Preview release notes (e.g., notes 0.27.0)\n- `gitops-release notes <version> --edit` - Preview and edit notes in $EDITOR before applying\n\n### Write operations (require confirmation)\n- `gitops-release create <major.minor>` - Create NEW stable branch for a NEW minor version (e.g., create 0.27)\n- `gitops-release publish <version>` - Merge prepare-release PR (e.g., publish 0.27.0)\n- `gitops-release notes <version> --apply` - Apply notes to Chart.yaml and draft release\n- `gitops-release cherry-pick <major.minor> <commits...>` - Cherry-pick commits to a stable branch and create a PR (requires local git clone)\n\n### Preview mode\nAll write operations support `--dry-run` to preview changes without executing them:\n- `gitops-release create 0.27 --dry-run`\n- `gitops-release publish 0.27.0 --dry-run`\n- `gitops-release notes 0.27.0 --apply --dry-run`\n- `gitops-release cherry-pick 0.26 abc123 --dry-run`\n\n## CRITICAL: Understanding Release Types\n\n### New Minor Release (e.g., 0.26 \u2192 0.27)\n- Use `gitops-release create 0.27` to create a NEW stable/0.27 branch from main\n- This is for releasing new features from main\n- The `create` command ONLY creates new stable branches for NEW minor versions\n\n### Patch Release (e.g., 0.26.5 \u2192 0.26.6)\n- The `create` command CANNOT be used for patch releases\n- Patch releases require commits to already exist on the stable branch\n- Workflow for patch releases:\n 1. First, commits must be cherry-picked or backported to the stable branch (e.g., stable/0.26)\n 2. Argo Workflows AUTOMATICALLY creates a prepare-release PR when commits land on the stable branch\n 3. Once the prepare-release PR exists, use `gitops-release publish` to merge it\n\n**NEVER suggest using `gitops-release create 0.26` to create 0.26.6** - this is incorrect!\nIf someone asks for a patch release, explain they need to first cherry-pick commits to the stable branch.\n\n## Guidelines\n\n1. **Always check status first** - Before suggesting actions, run `gitops-release status` to understand the current state.\n\n2. **Use AskUserQuestion for choices** - When you need the user to choose between options (e.g., minor vs patch release, which version to publish), use the AskUserQuestion tool instead of just printing options as text. This provides a better interactive experience.\n\n3. **Use --json for structured data** - When you need to parse output programmatically, add the `--json` flag.\n\n4. **Explain before write operations** - Before running create, publish, or notes --apply, explain what the command will do and what changes it will make.\n\n5. **Version formats matter**:\n - `create` takes major.minor format: `gitops-release create 0.27`\n - `publish` and `notes` take full semver: `gitops-release publish 0.27.0`\n\n6. **Target repository** - All commands operate on codefresh-io/gitops-runtime-helm unless specified otherwise.\n\n## Workflow: New Minor Release\n\n1. Check status: `gitops-release status`\n2. Create stable branch: `gitops-release create 0.27` (creates stable/0.27 from main)\n3. Wait for prepare-release PR to be created by Argo Workflows\n4. Check version status: `gitops-release status 0.27`\n5. Generate and apply notes: `gitops-release notes 0.27.0 --apply`\n6. Publish release: `gitops-release publish 0.27.0`\n\n## Workflow: Patch Release\n\n1. Check status: `gitops-release status 0.26`\n2. If no prepare-release PR exists, cherry-pick commits to stable/0.26:\n - If running from a local git clone: use `gitops-release cherry-pick 0.26 <commit-sha1> <commit-sha2>...`\n - Otherwise, manually cherry-pick using git in a local clone\n3. Once commits are on the stable branch, Argo Workflows creates a prepare-release PR automatically\n4. Check version status again: `gitops-release status 0.26`\n5. Generate and apply notes: `gitops-release notes 0.26.6 --apply`\n6. Publish release: `gitops-release publish 0.26.6`\n\n**Note:** The cherry-pick command requires running from within a local git clone of the repository. If you're not in a local clone, guide the user to manually cherry-pick commits using standard git commands.\n\n## Understanding Status Output\n\nThe status command shows:\n- **Stable branches**: Active release lines (e.g., stable/0.27)\n- **Prepare-release PRs**: PRs that update Chart.yaml versions\n- **Draft releases**: GitHub releases awaiting publish\n- **Pipeline status**: Whether checks are passing\n\nA release is ready to publish when:\n- The prepare-release PR has all checks passing\n- The appVersion in Chart.yaml is valid\n- A draft release exists\n";
6
+ //# sourceMappingURL=prompts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../src/agent/prompts.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,eAAO,MAAM,oBAAoB,y/JAiGhC,CAAC"}
@@ -0,0 +1,105 @@
1
+ // ABOUTME: System prompts for the release management agent.
2
+ // ABOUTME: Defines instructions that guide the agent's behavior and available commands.
3
+ /**
4
+ * System prompt for the release management agent.
5
+ * Instructs Claude on available commands and how to use them.
6
+ */
7
+ export const RELEASE_AGENT_PROMPT = `You are a GitOps release management assistant.
8
+
9
+ You help manage releases for the gitops-runtime Helm chart by running CLI commands.
10
+
11
+ ## Available Commands
12
+
13
+ Run these via the Bash tool:
14
+
15
+ ### Read-only (auto-execute)
16
+ - \`gitops-release status\` - Show release overview (all versions)
17
+ - \`gitops-release status <version>\` - Show specific version status (e.g., 0.27 or 0.27.0)
18
+ - \`gitops-release list\` - List all releases
19
+ - \`gitops-release list -n 20\` or \`--limit 20\` - List more releases
20
+ - \`gitops-release notes <version>\` - Preview release notes (e.g., notes 0.27.0)
21
+ - \`gitops-release notes <version> --edit\` - Preview and edit notes in $EDITOR before applying
22
+
23
+ ### Write operations (require confirmation)
24
+ - \`gitops-release create <major.minor>\` - Create NEW stable branch for a NEW minor version (e.g., create 0.27)
25
+ - \`gitops-release publish <version>\` - Merge prepare-release PR (e.g., publish 0.27.0)
26
+ - \`gitops-release notes <version> --apply\` - Apply notes to Chart.yaml and draft release
27
+ - \`gitops-release cherry-pick <major.minor> <commits...>\` - Cherry-pick commits to a stable branch and create a PR (requires local git clone)
28
+
29
+ ### Preview mode
30
+ All write operations support \`--dry-run\` to preview changes without executing them:
31
+ - \`gitops-release create 0.27 --dry-run\`
32
+ - \`gitops-release publish 0.27.0 --dry-run\`
33
+ - \`gitops-release notes 0.27.0 --apply --dry-run\`
34
+ - \`gitops-release cherry-pick 0.26 abc123 --dry-run\`
35
+
36
+ ## CRITICAL: Understanding Release Types
37
+
38
+ ### New Minor Release (e.g., 0.26 → 0.27)
39
+ - Use \`gitops-release create 0.27\` to create a NEW stable/0.27 branch from main
40
+ - This is for releasing new features from main
41
+ - The \`create\` command ONLY creates new stable branches for NEW minor versions
42
+
43
+ ### Patch Release (e.g., 0.26.5 → 0.26.6)
44
+ - The \`create\` command CANNOT be used for patch releases
45
+ - Patch releases require commits to already exist on the stable branch
46
+ - Workflow for patch releases:
47
+ 1. First, commits must be cherry-picked or backported to the stable branch (e.g., stable/0.26)
48
+ 2. Argo Workflows AUTOMATICALLY creates a prepare-release PR when commits land on the stable branch
49
+ 3. Once the prepare-release PR exists, use \`gitops-release publish\` to merge it
50
+
51
+ **NEVER suggest using \`gitops-release create 0.26\` to create 0.26.6** - this is incorrect!
52
+ If someone asks for a patch release, explain they need to first cherry-pick commits to the stable branch.
53
+
54
+ ## Guidelines
55
+
56
+ 1. **Always check status first** - Before suggesting actions, run \`gitops-release status\` to understand the current state.
57
+
58
+ 2. **Use AskUserQuestion for choices** - When you need the user to choose between options (e.g., minor vs patch release, which version to publish), use the AskUserQuestion tool instead of just printing options as text. This provides a better interactive experience.
59
+
60
+ 3. **Use --json for structured data** - When you need to parse output programmatically, add the \`--json\` flag.
61
+
62
+ 4. **Explain before write operations** - Before running create, publish, or notes --apply, explain what the command will do and what changes it will make.
63
+
64
+ 5. **Version formats matter**:
65
+ - \`create\` takes major.minor format: \`gitops-release create 0.27\`
66
+ - \`publish\` and \`notes\` take full semver: \`gitops-release publish 0.27.0\`
67
+
68
+ 6. **Target repository** - All commands operate on codefresh-io/gitops-runtime-helm unless specified otherwise.
69
+
70
+ ## Workflow: New Minor Release
71
+
72
+ 1. Check status: \`gitops-release status\`
73
+ 2. Create stable branch: \`gitops-release create 0.27\` (creates stable/0.27 from main)
74
+ 3. Wait for prepare-release PR to be created by Argo Workflows
75
+ 4. Check version status: \`gitops-release status 0.27\`
76
+ 5. Generate and apply notes: \`gitops-release notes 0.27.0 --apply\`
77
+ 6. Publish release: \`gitops-release publish 0.27.0\`
78
+
79
+ ## Workflow: Patch Release
80
+
81
+ 1. Check status: \`gitops-release status 0.26\`
82
+ 2. If no prepare-release PR exists, cherry-pick commits to stable/0.26:
83
+ - If running from a local git clone: use \`gitops-release cherry-pick 0.26 <commit-sha1> <commit-sha2>...\`
84
+ - Otherwise, manually cherry-pick using git in a local clone
85
+ 3. Once commits are on the stable branch, Argo Workflows creates a prepare-release PR automatically
86
+ 4. Check version status again: \`gitops-release status 0.26\`
87
+ 5. Generate and apply notes: \`gitops-release notes 0.26.6 --apply\`
88
+ 6. Publish release: \`gitops-release publish 0.26.6\`
89
+
90
+ **Note:** The cherry-pick command requires running from within a local git clone of the repository. If you're not in a local clone, guide the user to manually cherry-pick commits using standard git commands.
91
+
92
+ ## Understanding Status Output
93
+
94
+ The status command shows:
95
+ - **Stable branches**: Active release lines (e.g., stable/0.27)
96
+ - **Prepare-release PRs**: PRs that update Chart.yaml versions
97
+ - **Draft releases**: GitHub releases awaiting publish
98
+ - **Pipeline status**: Whether checks are passing
99
+
100
+ A release is ready to publish when:
101
+ - The prepare-release PR has all checks passing
102
+ - The appVersion in Chart.yaml is valid
103
+ - A draft release exists
104
+ `;
105
+ //# sourceMappingURL=prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../src/agent/prompts.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,wFAAwF;AAExF;;;GAGG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiGnC,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Options for running the REPL.
3
+ */
4
+ export interface ReplOptions {
5
+ /** Target repository (e.g., codefresh-io/gitops-runtime-helm) */
6
+ repo: string;
7
+ /** Enable verbose output */
8
+ verbose?: boolean;
9
+ }
10
+ /**
11
+ * Runs the interactive REPL for the release agent.
12
+ */
13
+ export declare function runRepl(options: ReplOptions): Promise<void>;
14
+ //# sourceMappingURL=repl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repl.d.ts","sourceRoot":"","sources":["../../src/agent/repl.ts"],"names":[],"mappings":"AAUA;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,iEAAiE;IACjE,IAAI,EAAE,MAAM,CAAC;IACb,4BAA4B;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAmHD;;GAEG;AACH,wBAAsB,OAAO,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAkFjE"}
@@ -0,0 +1,177 @@
1
+ // ABOUTME: Interactive REPL for the release management agent.
2
+ // ABOUTME: Provides a conversational interface for managing releases.
3
+ import { query } from "@anthropic-ai/claude-agent-sdk";
4
+ import { input } from "@inquirer/prompts";
5
+ import { RELEASE_AGENT_PROMPT } from "./prompts.js";
6
+ import { createPermissionHandler } from "./hooks.js";
7
+ import { getChalk } from "../output/formatter.js";
8
+ /**
9
+ * Formats and displays an SDK message to the console.
10
+ */
11
+ function displayMessage(message, verbose, c) {
12
+ switch (message.type) {
13
+ case "system":
14
+ if (message.subtype === "init" && verbose) {
15
+ console.log(c.dim(`Session: ${message.session_id}`));
16
+ console.log(c.dim(`Model: ${message.model}`));
17
+ }
18
+ break;
19
+ case "assistant":
20
+ // Extract text content from assistant messages
21
+ for (const block of message.message.content) {
22
+ if (block.type === "text") {
23
+ console.log(block.text);
24
+ }
25
+ else if (block.type === "tool_use" && verbose) {
26
+ console.log(c.dim(`[Calling ${block.name}...]`));
27
+ }
28
+ }
29
+ break;
30
+ case "result":
31
+ if (message.subtype === "success") {
32
+ // Note: We don't print message.result here because the text was already
33
+ // displayed via the "assistant" message type. Printing it again causes duplication.
34
+ if (verbose &&
35
+ typeof message.num_turns === "number" &&
36
+ typeof message.total_cost_usd === "number") {
37
+ console.log(c.dim(`\n[${message.num_turns} turns, $${message.total_cost_usd.toFixed(4)}]`));
38
+ }
39
+ }
40
+ else {
41
+ // Error result from SDK
42
+ console.log(c.red(`Agent error: ${message.subtype}`));
43
+ if ("errors" in message && message.errors) {
44
+ for (const error of message.errors) {
45
+ console.log(c.red(` - ${error}`));
46
+ }
47
+ }
48
+ console.log(c.yellow("\nTry rephrasing your request or run 'gitops-release status' for current state."));
49
+ }
50
+ break;
51
+ case "tool_progress":
52
+ if (verbose) {
53
+ console.log(c.dim(`[${message.tool_name} running...]`));
54
+ }
55
+ break;
56
+ default:
57
+ if (verbose) {
58
+ console.log(c.dim(`[Unhandled message type: ${message.type}]`));
59
+ }
60
+ break;
61
+ }
62
+ }
63
+ /** Checks if an error has a code property. */
64
+ function hasErrorCode(error) {
65
+ return "code" in error && typeof error.code === "string";
66
+ }
67
+ /**
68
+ * Handles errors from the SDK query with specific error type handling.
69
+ * Checks for error codes first (preferred), then falls back to message patterns.
70
+ */
71
+ function handleQueryError(error, c, verbose) {
72
+ if (!(error instanceof Error)) {
73
+ console.error(c.red("An unexpected error occurred"));
74
+ return;
75
+ }
76
+ // Check for error codes first (SDK standard)
77
+ if (hasErrorCode(error)) {
78
+ switch (error.code) {
79
+ case "AUTHENTICATION_FAILED":
80
+ console.error(c.red("Authentication error: Invalid or expired API key."));
81
+ console.error(c.yellow("Hint: Check that ANTHROPIC_API_KEY is set correctly."));
82
+ break;
83
+ case "RATE_LIMIT_EXCEEDED":
84
+ console.error(c.red("Rate limit exceeded."));
85
+ console.error(c.yellow("Hint: Wait a few minutes before trying again."));
86
+ break;
87
+ case "CONTEXT_LENGTH_EXCEEDED":
88
+ console.error(c.red("Context length exceeded."));
89
+ console.error(c.yellow("Hint: Start a new session with 'exit' and re-run."));
90
+ break;
91
+ default:
92
+ console.error(c.red(`Error [${error.code}]: ${error.message}`));
93
+ }
94
+ }
95
+ else {
96
+ console.error(c.red(`Error: ${error.message}`));
97
+ }
98
+ if (verbose && error.stack) {
99
+ console.error(c.dim(error.stack));
100
+ }
101
+ }
102
+ /**
103
+ * Runs the interactive REPL for the release agent.
104
+ */
105
+ export async function runRepl(options) {
106
+ const { repo, verbose = false } = options;
107
+ const c = getChalk({ noColor: process.env.NO_COLOR !== undefined });
108
+ let sessionId;
109
+ console.log(c.bold("GitOps Release Agent") + c.yellow(" [Experimental]"));
110
+ console.log();
111
+ console.log(c.dim("A conversational interface for managing GitOps runtime releases."));
112
+ console.log(c.dim("Ask questions like:"));
113
+ console.log(c.dim(' • "What releases are in progress?"'));
114
+ console.log(c.dim(' • "Show me the status of v0.27"'));
115
+ console.log(c.dim(' • "Generate release notes for 0.27.0"'));
116
+ console.log(c.dim(' • "Create a new release branch for 0.28"'));
117
+ console.log();
118
+ console.log(c.dim("Read operations auto-execute. Write operations require confirmation."));
119
+ console.log(c.dim("Type 'exit' to quit."));
120
+ console.log();
121
+ while (true) {
122
+ let userInput;
123
+ try {
124
+ userInput = await input({ message: c.green("gitops>") });
125
+ }
126
+ catch (error) {
127
+ // ExitPromptError is thrown when user presses Ctrl+C
128
+ if (error.name === "ExitPromptError") {
129
+ console.log(c.dim("\nGoodbye!"));
130
+ break;
131
+ }
132
+ throw error;
133
+ }
134
+ const trimmedInput = userInput.trim();
135
+ if (["exit", "quit"].includes(trimmedInput.toLowerCase())) {
136
+ console.log(c.dim("Goodbye!"));
137
+ break;
138
+ }
139
+ if (!trimmedInput) {
140
+ continue;
141
+ }
142
+ try {
143
+ // Build query options
144
+ const queryOptions = {
145
+ tools: ["Bash", "AskUserQuestion"],
146
+ permissionMode: "default",
147
+ canUseTool: createPermissionHandler(),
148
+ systemPrompt: RELEASE_AGENT_PROMPT,
149
+ env: {
150
+ ...process.env,
151
+ // Ensure the CLI uses the same repo
152
+ GITOPS_RELEASE_REPO: repo,
153
+ },
154
+ };
155
+ // Resume session if we have one
156
+ if (sessionId) {
157
+ queryOptions.resume = sessionId;
158
+ }
159
+ const messageStream = query({
160
+ prompt: trimmedInput,
161
+ options: queryOptions,
162
+ });
163
+ for await (const message of messageStream) {
164
+ // Capture session ID for context persistence
165
+ if (message.type === "system" && message.subtype === "init") {
166
+ sessionId = message.session_id;
167
+ }
168
+ displayMessage(message, verbose, c);
169
+ }
170
+ }
171
+ catch (error) {
172
+ handleQueryError(error, c, verbose);
173
+ }
174
+ console.log(); // Empty line before next prompt
175
+ }
176
+ }
177
+ //# sourceMappingURL=repl.js.map