@profoundlogic/coderflow-cli 0.2.1

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.
@@ -0,0 +1,237 @@
1
+ /**
2
+ * Command: coder run - Create and run a task
3
+ */
4
+
5
+ import { request } from '../http-client.js';
6
+ import { getDefaultEnvironment } from '../config.js';
7
+
8
+ /**
9
+ * Parse command line arguments for task parameters
10
+ * @param {Array} args - Command line arguments
11
+ * @returns {Object} { taskType, environment, parameters }
12
+ */
13
+ function parseKeyValue(pair) {
14
+ const [rawKey, ...rest] = pair.split('=');
15
+ if (!rawKey || rest.length === 0) {
16
+ return null;
17
+ }
18
+ const key = rawKey.trim();
19
+ const value = rest.join('=').trim();
20
+ if (!key || !value) {
21
+ return null;
22
+ }
23
+ return { key, value };
24
+ }
25
+
26
+ function parseTaskArgs(args) {
27
+ let taskType = null;
28
+ let environment = null;
29
+ let jiraIssueKey = null;
30
+ let withLocalState = false;
31
+ const parameters = {};
32
+ const envVars = {};
33
+ const branches = {};
34
+
35
+ for (let index = 0; index < args.length; index += 1) {
36
+ const arg = args[index];
37
+
38
+ if (arg === '--branch') {
39
+ const next = args[index + 1];
40
+ if (!next) {
41
+ console.error('Error: --branch requires REPO=BRANCH or BRANCH');
42
+ process.exit(1);
43
+ }
44
+ const parsed = parseKeyValue(next);
45
+ if (parsed) {
46
+ // Format: --branch profoundjs=feature-xyz
47
+ branches[parsed.key] = parsed.value;
48
+ } else {
49
+ // Format: --branch feature-xyz (will be applied to first selectable repo)
50
+ branches._default = next.trim();
51
+ }
52
+ index += 1; // Skip value token
53
+ continue;
54
+ }
55
+
56
+ if (arg.startsWith('--branch=')) {
57
+ const pair = arg.substring('--branch='.length);
58
+ const parsed = parseKeyValue(pair);
59
+ if (parsed) {
60
+ // Format: --branch=profoundjs=feature-xyz
61
+ branches[parsed.key] = parsed.value;
62
+ } else {
63
+ // Format: --branch=feature-xyz (will be applied to first selectable repo)
64
+ branches._default = pair.trim();
65
+ }
66
+ continue;
67
+ }
68
+
69
+ if (arg === '--env') {
70
+ const next = args[index + 1];
71
+ if (!next) {
72
+ console.error('Error: --env requires KEY=VALUE');
73
+ process.exit(1);
74
+ }
75
+ const parsed = parseKeyValue(next);
76
+ if (!parsed) {
77
+ console.error(`Error: Invalid --env value: ${next}`);
78
+ console.error('Expected format: --env KEY=VALUE');
79
+ process.exit(1);
80
+ }
81
+ envVars[parsed.key] = parsed.value;
82
+ index += 1; // Skip value token
83
+ continue;
84
+ }
85
+
86
+ if (arg.startsWith('--env=')) {
87
+ const pair = arg.substring('--env='.length);
88
+ const parsed = parseKeyValue(pair);
89
+ if (!parsed) {
90
+ console.error(`Error: Invalid --env value: ${pair}`);
91
+ console.error('Expected format: --env KEY=VALUE');
92
+ process.exit(1);
93
+ }
94
+ envVars[parsed.key] = parsed.value;
95
+ continue;
96
+ }
97
+
98
+ if (arg === '--environment') {
99
+ const next = args[index + 1];
100
+ if (!next) {
101
+ console.error('Error: --environment requires a value');
102
+ process.exit(1);
103
+ }
104
+ environment = next;
105
+ index += 1;
106
+ continue;
107
+ }
108
+
109
+ if (arg.startsWith('--environment=')) {
110
+ environment = arg.substring('--environment='.length);
111
+ continue;
112
+ }
113
+
114
+ if (arg === '--jira') {
115
+ const next = args[index + 1];
116
+ if (!next) {
117
+ console.error('Error: --jira requires an issue key (e.g., PROJ-123)');
118
+ process.exit(1);
119
+ }
120
+ jiraIssueKey = next.trim().toUpperCase();
121
+ index += 1;
122
+ continue;
123
+ }
124
+
125
+ if (arg.startsWith('--jira=')) {
126
+ jiraIssueKey = arg.substring('--jira='.length).trim().toUpperCase();
127
+ continue;
128
+ }
129
+
130
+ if (arg === '--with-local-state') {
131
+ withLocalState = true;
132
+ continue;
133
+ }
134
+
135
+ if (arg.startsWith('--')) {
136
+ const match = arg.match(/^--([^=]+)=(.+)$/);
137
+ if (match) {
138
+ const [, key, value] = match;
139
+ parameters[key] = value;
140
+ } else {
141
+ console.error(`Error: Unrecognized option: ${arg}`);
142
+ process.exit(1);
143
+ }
144
+ continue;
145
+ }
146
+
147
+ if (!taskType) {
148
+ taskType = arg;
149
+ continue;
150
+ }
151
+
152
+ console.error(`Error: Unexpected argument: ${arg}`);
153
+ process.exit(1);
154
+ }
155
+
156
+ return { taskType, environment, parameters, envVars, branches, jiraIssueKey, withLocalState };
157
+ }
158
+
159
+ export async function runTask(args = []) {
160
+ const { taskType, environment, parameters, envVars, branches, jiraIssueKey, withLocalState } = parseTaskArgs(args);
161
+ let resolvedEnvironment = environment;
162
+
163
+ if (!resolvedEnvironment) {
164
+ resolvedEnvironment = await getDefaultEnvironment();
165
+ }
166
+
167
+ if (jiraIssueKey) {
168
+ console.log(`Creating task from Jira issue: ${jiraIssueKey}`);
169
+ if (resolvedEnvironment) {
170
+ console.log(`Environment: ${resolvedEnvironment}`);
171
+ }
172
+ } else if (taskType) {
173
+ console.log(`Creating task: ${taskType}`);
174
+ if (resolvedEnvironment) {
175
+ console.log(`Environment: ${resolvedEnvironment}`);
176
+ }
177
+ if (Object.keys(parameters).length > 0) {
178
+ console.log(`Parameters: ${JSON.stringify(parameters, null, 2)}`);
179
+ }
180
+ if (Object.keys(envVars).length > 0) {
181
+ console.log(`Environment variables: ${JSON.stringify(envVars, null, 2)}`);
182
+ }
183
+ if (Object.keys(branches).length > 0) {
184
+ console.log(`Branches: ${JSON.stringify(branches, null, 2)}`);
185
+ }
186
+ } else {
187
+ console.log(`Creating new task...`);
188
+ }
189
+
190
+ const requestBody = {};
191
+ if (taskType) {
192
+ requestBody.task_type = taskType;
193
+ }
194
+ if (resolvedEnvironment) {
195
+ requestBody.environment = resolvedEnvironment;
196
+ }
197
+ if (Object.keys(parameters).length > 0) {
198
+ requestBody.parameters = parameters;
199
+ }
200
+ if (Object.keys(envVars).length > 0) {
201
+ requestBody.env_vars = envVars;
202
+ }
203
+ if (Object.keys(branches).length > 0) {
204
+ requestBody.branches = branches;
205
+ }
206
+ if (jiraIssueKey) {
207
+ requestBody.jira_issue_key = jiraIssueKey;
208
+ }
209
+
210
+ // Capture local repository state if requested
211
+ if (withLocalState) {
212
+ console.log('\n🔍 Capturing local repository state...');
213
+ requestBody.capture_local_state = true;
214
+ requestBody.source_path = process.cwd();
215
+ }
216
+
217
+ const data = await request('/tasks', {
218
+ method: 'POST',
219
+ body: JSON.stringify(requestBody)
220
+ });
221
+
222
+ console.log(`\n✓ Task created successfully`);
223
+ console.log(` Task ID: ${data.taskId}`);
224
+ console.log(` Container ID: ${data.containerId}`);
225
+ console.log(` Status: ${data.status}`);
226
+ if (data.environment) {
227
+ console.log(` Environment: ${data.environment}`);
228
+ }
229
+ if (data.taskType) {
230
+ console.log(` Task Type: ${data.taskType}`);
231
+ }
232
+ if (data.jira) {
233
+ console.log(` Jira Issue: ${data.jira.key} - ${data.jira.summary}`);
234
+ }
235
+ console.log(`\nUse "coder status ${data.taskId}" to check progress`);
236
+ console.log(`Use "coder results ${data.taskId}" to get results`);
237
+ }