@forgehive/forge-cli 0.3.11 ā 0.3.13
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/runner.js +9 -6
- package/dist/tasks/auth/add.d.ts +16 -0
- package/dist/tasks/auth/add.js +56 -4
- package/dist/tasks/auth/clear.d.ts +16 -0
- package/dist/tasks/auth/clear.js +54 -0
- package/dist/tasks/auth/list.d.ts +2 -0
- package/dist/tasks/auth/list.js +10 -2
- package/dist/tasks/project/sync.d.ts +116 -0
- package/dist/tasks/project/sync.js +152 -0
- package/dist/tasks/task/createTask.d.ts +12 -0
- package/dist/tasks/task/createTask.js +51 -2
- package/dist/tasks/task/run.d.ts +12 -2
- package/dist/tasks/task/run.js +39 -10
- package/dist/tasks/types.d.ts +3 -0
- package/logs/task:list.log +1 -0
- package/logs/test:guidance.log +1 -0
- package/logs/test:uuid.log +1 -0
- package/logs/test:uuidCheck.log +1 -0
- package/package.json +10 -10
- package/src/runner.ts +9 -6
- package/src/tasks/auth/add.ts +66 -4
- package/src/tasks/auth/clear.ts +63 -0
- package/src/tasks/auth/list.ts +10 -2
- package/src/tasks/project/sync.ts +202 -0
- package/src/tasks/task/createTask.ts +68 -2
- package/src/tasks/task/run.ts +49 -10
- package/src/tasks/types.ts +3 -0
|
@@ -8,6 +8,7 @@ import fs from 'fs/promises'
|
|
|
8
8
|
import { camelCase } from '../../utils/camelCase'
|
|
9
9
|
|
|
10
10
|
import { load } from '../conf/load'
|
|
11
|
+
import { loadCurrent } from '../auth/loadCurrent'
|
|
11
12
|
import { type TaskName, type ForgeConf } from '../types'
|
|
12
13
|
|
|
13
14
|
// Define the template content directly in the code
|
|
@@ -55,6 +56,7 @@ const schema = new Schema({
|
|
|
55
56
|
const boundaries = {
|
|
56
57
|
// Load boundaries
|
|
57
58
|
loadConf: load.asBoundary(),
|
|
59
|
+
loadCurrentProfile: loadCurrent.asBoundary(),
|
|
58
60
|
loadTemplate: async (): Promise<string> => {
|
|
59
61
|
return TASK_TEMPLATE
|
|
60
62
|
},
|
|
@@ -106,6 +108,40 @@ const boundaries = {
|
|
|
106
108
|
persistConf: async (forge: ForgeConf, cwd: string): Promise<void> => {
|
|
107
109
|
const forgePath = path.join(cwd, 'forge.json')
|
|
108
110
|
await fs.writeFile(forgePath, JSON.stringify(forge, null, 2))
|
|
111
|
+
},
|
|
112
|
+
createTaskInHive: async (
|
|
113
|
+
projectUuid: string,
|
|
114
|
+
taskUuid: string,
|
|
115
|
+
taskName: string,
|
|
116
|
+
description: string,
|
|
117
|
+
apiKey: string,
|
|
118
|
+
apiSecret: string,
|
|
119
|
+
baseUrl: string
|
|
120
|
+
): Promise<{ success: boolean; taskUrl?: string; error?: string }> => {
|
|
121
|
+
try {
|
|
122
|
+
const url = `${baseUrl}/api/projects/${projectUuid}/tasks/${taskUuid}`
|
|
123
|
+
const response = await fetch(url, {
|
|
124
|
+
method: 'POST',
|
|
125
|
+
headers: {
|
|
126
|
+
'Content-Type': 'application/json',
|
|
127
|
+
'Authorization': `Bearer ${apiKey}:${apiSecret}`
|
|
128
|
+
},
|
|
129
|
+
body: JSON.stringify({
|
|
130
|
+
taskName,
|
|
131
|
+
description
|
|
132
|
+
})
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
if (response.ok) {
|
|
136
|
+
const taskUrl = `${baseUrl}/tasks/${taskUuid}`
|
|
137
|
+
return { success: true, taskUrl }
|
|
138
|
+
} else {
|
|
139
|
+
const errorData = await response.json().catch(() => ({ error: 'Unknown error' }))
|
|
140
|
+
return { success: false, error: errorData.error || `HTTP ${response.status}` }
|
|
141
|
+
}
|
|
142
|
+
} catch (error) {
|
|
143
|
+
return { success: false, error: error instanceof Error ? error.message : 'Network error' }
|
|
144
|
+
}
|
|
109
145
|
}
|
|
110
146
|
}
|
|
111
147
|
|
|
@@ -118,7 +154,9 @@ export const createTaskCommand = createTask({
|
|
|
118
154
|
loadConf,
|
|
119
155
|
persistConf,
|
|
120
156
|
parseTaskName,
|
|
121
|
-
getCwd
|
|
157
|
+
getCwd,
|
|
158
|
+
loadCurrentProfile,
|
|
159
|
+
createTaskInHive
|
|
122
160
|
}) {
|
|
123
161
|
const { taskName, fileName, descriptor, dir } = await parseTaskName(descriptorName)
|
|
124
162
|
const cwd = await getCwd()
|
|
@@ -153,14 +191,42 @@ export const createTaskCommand = createTask({
|
|
|
153
191
|
forge.tasks = {}
|
|
154
192
|
}
|
|
155
193
|
|
|
194
|
+
const taskUuid = uuidv4()
|
|
156
195
|
forge.tasks[descriptor] = {
|
|
157
196
|
path: `${taskPath}/${fileName}`,
|
|
158
197
|
handler: taskName,
|
|
159
|
-
uuid:
|
|
198
|
+
uuid: taskUuid
|
|
160
199
|
}
|
|
161
200
|
|
|
162
201
|
await persistConf(forge, cwd)
|
|
163
202
|
|
|
203
|
+
// Try to create task in Hive if user has profile and project UUID
|
|
204
|
+
if (forge.project.uuid) {
|
|
205
|
+
try {
|
|
206
|
+
const profile = await loadCurrentProfile({})
|
|
207
|
+
const result = await createTaskInHive(
|
|
208
|
+
forge.project.uuid,
|
|
209
|
+
taskUuid,
|
|
210
|
+
descriptor,
|
|
211
|
+
'Add task description here',
|
|
212
|
+
profile.apiKey,
|
|
213
|
+
profile.apiSecret,
|
|
214
|
+
profile.url
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
if (result.success && result.taskUrl) {
|
|
218
|
+
console.log('\\nā
Task created successfully in Hive!')
|
|
219
|
+
console.log(`š View your task: ${result.taskUrl}`)
|
|
220
|
+
} else {
|
|
221
|
+
console.log(`\nā ļø Task created locally but could not sync to Hive: ${result.error}`)
|
|
222
|
+
console.log(`š Host: ${profile.url}`)
|
|
223
|
+
}
|
|
224
|
+
} catch (error) {
|
|
225
|
+
// Silently continue if no profile is configured
|
|
226
|
+
console.log('\\nš Task created locally. Configure a profile with \'forge auth:add\' to sync with Hive.')
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
164
230
|
return { taskPath, fileName }
|
|
165
231
|
}
|
|
166
232
|
})
|
package/src/tasks/task/run.ts
CHANGED
|
@@ -49,10 +49,34 @@ const boundaries = {
|
|
|
49
49
|
|
|
50
50
|
return buildsPath
|
|
51
51
|
},
|
|
52
|
-
sendLogToAPI: async (
|
|
52
|
+
sendLogToAPI: async (
|
|
53
|
+
profile: Profile,
|
|
54
|
+
projectName: string,
|
|
55
|
+
record: ExecutionRecord,
|
|
56
|
+
taskUuid?: string,
|
|
57
|
+
projectUuid?: string
|
|
58
|
+
): Promise<{ success: boolean; logUuid?: string; taskUuid?: string; skipRemoteLog?: boolean }> => {
|
|
59
|
+
// Check if we have required UUIDs for the new endpoint
|
|
60
|
+
if (!projectUuid || !taskUuid) {
|
|
61
|
+
console.log('===============================================')
|
|
62
|
+
console.log('ā ļø Remote logging skipped - missing UUIDs')
|
|
63
|
+
console.log('')
|
|
64
|
+
console.log('To enable remote logging with enhanced features:')
|
|
65
|
+
if (!projectUuid) {
|
|
66
|
+
console.log('⢠Use "forge project:create" to create a new project, or')
|
|
67
|
+
console.log('⢠Use "forge project:link" to connect to an existing project')
|
|
68
|
+
}
|
|
69
|
+
if (!taskUuid) {
|
|
70
|
+
console.log('⢠Use "forge project:sync" to get the task to have UUID')
|
|
71
|
+
}
|
|
72
|
+
console.log('===============================================')
|
|
73
|
+
return { success: true, skipRemoteLog: true }
|
|
74
|
+
}
|
|
75
|
+
|
|
53
76
|
try {
|
|
54
77
|
const config = {
|
|
55
78
|
projectName,
|
|
79
|
+
projectUuid,
|
|
56
80
|
apiKey: profile.apiKey,
|
|
57
81
|
apiSecret: profile.apiSecret,
|
|
58
82
|
host: profile.url,
|
|
@@ -62,21 +86,30 @@ const boundaries = {
|
|
|
62
86
|
}
|
|
63
87
|
|
|
64
88
|
const client = new HiveLogClient(config)
|
|
65
|
-
|
|
89
|
+
console.log('Sending execution log to Hive...')
|
|
90
|
+
const result = await client.sendLogByUuid(record, taskUuid)
|
|
66
91
|
|
|
67
|
-
if (result === 'success') {
|
|
92
|
+
if (result === 'success' || (typeof result === 'object' && 'uuid' in result)) {
|
|
68
93
|
console.log('===============================================')
|
|
69
|
-
console.log('Log sent to
|
|
70
|
-
|
|
94
|
+
console.log('ā
Log sent to Hive successfully')
|
|
95
|
+
console.log(` Profile: ${profile.name}`)
|
|
96
|
+
console.log(` Host: ${profile.url}`)
|
|
97
|
+
|
|
98
|
+
if (typeof result === 'object' && result && 'uuid' in result) {
|
|
99
|
+
const logResponse = result as { uuid: string }
|
|
100
|
+
return { success: true, logUuid: logResponse.uuid, taskUuid }
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return { success: true, taskUuid }
|
|
71
104
|
} else {
|
|
72
|
-
console.error('Failed to send log to
|
|
73
|
-
return false
|
|
105
|
+
console.error('ā Failed to send log to Hive:', profile.url)
|
|
106
|
+
return { success: false }
|
|
74
107
|
}
|
|
75
108
|
} catch (e) {
|
|
76
|
-
console.error('Failed to send log to
|
|
109
|
+
console.error('ā Failed to send log to Hive:', profile.url)
|
|
77
110
|
const error = e as Error
|
|
78
111
|
console.error('Error:', error.message)
|
|
79
|
-
return false
|
|
112
|
+
return { success: false }
|
|
80
113
|
}
|
|
81
114
|
}
|
|
82
115
|
}
|
|
@@ -97,6 +130,8 @@ export const run = createTask({
|
|
|
97
130
|
const forge: ForgeConf = await loadConf({})
|
|
98
131
|
const taskDescriptor = forge.tasks[descriptorName as keyof typeof forge.tasks]
|
|
99
132
|
const projectName = forge.project.name
|
|
133
|
+
const projectUuid = forge.project.uuid
|
|
134
|
+
const taskUuid = taskDescriptor?.uuid
|
|
100
135
|
|
|
101
136
|
if (taskDescriptor === undefined) {
|
|
102
137
|
throw new Error('Task is not defined on forge.json')
|
|
@@ -169,7 +204,11 @@ export const run = createTask({
|
|
|
169
204
|
|
|
170
205
|
if (profile) {
|
|
171
206
|
try {
|
|
172
|
-
await sendLogToAPI(profile, projectName, logItem)
|
|
207
|
+
const logResult = await sendLogToAPI(profile, projectName, logItem, taskUuid, projectUuid)
|
|
208
|
+
|
|
209
|
+
if (logResult.success && !logResult.skipRemoteLog && taskUuid) {
|
|
210
|
+
console.log(`š View execution logs: ${profile.url}/tasks/${taskUuid}?tab=logs`)
|
|
211
|
+
}
|
|
173
212
|
} catch (e) {
|
|
174
213
|
console.error('Failed to send log to API:', e)
|
|
175
214
|
}
|