@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.
- package/README.md +74 -1
- package/dist/agent/hooks.d.ts +12 -0
- package/dist/agent/hooks.d.ts.map +1 -0
- package/dist/agent/hooks.js +181 -0
- package/dist/agent/hooks.js.map +1 -0
- package/dist/agent/index.d.ts +4 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +6 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/agent/prompts.d.ts +6 -0
- package/dist/agent/prompts.d.ts.map +1 -0
- package/dist/agent/prompts.js +105 -0
- package/dist/agent/prompts.js.map +1 -0
- package/dist/agent/repl.d.ts +14 -0
- package/dist/agent/repl.d.ts.map +1 -0
- package/dist/agent/repl.js +177 -0
- package/dist/agent/repl.js.map +1 -0
- package/dist/commands/chat.d.ts +14 -0
- package/dist/commands/chat.d.ts.map +1 -0
- package/dist/commands/chat.js +24 -0
- package/dist/commands/chat.js.map +1 -0
- package/dist/commands/create.d.ts +5 -0
- package/dist/commands/create.d.ts.map +1 -1
- package/dist/commands/create.js +50 -2
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/notes.d.ts +5 -0
- package/dist/commands/notes.d.ts.map +1 -1
- package/dist/commands/notes.js +81 -9
- package/dist/commands/notes.js.map +1 -1
- package/dist/commands/publish.d.ts +5 -0
- package/dist/commands/publish.d.ts.map +1 -1
- package/dist/commands/publish.js +32 -2
- package/dist/commands/publish.js.map +1 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +47 -8
- package/dist/commands/status.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +48 -10
- package/dist/index.js.map +1 -1
- package/dist/output/formatter.d.ts +5 -0
- package/dist/output/formatter.d.ts.map +1 -1
- package/dist/output/formatter.js +1 -1
- package/dist/output/formatter.js.map +1 -1
- package/dist/services/version.d.ts +22 -0
- package/dist/services/version.d.ts.map +1 -1
- package/dist/services/version.js +49 -0
- package/dist/services/version.js.map +1 -1
- 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
|
|
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 @@
|
|
|
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
|