@forgehive/forge-cli 0.3.16 → 0.3.18
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 +3 -3
- package/dist/tasks/bundle/create.d.ts +7 -2
- package/dist/tasks/bundle/create.js +11 -3
- package/dist/tasks/bundle/fingerprint.js +4 -1
- package/dist/tasks/docs/download.js +2 -0
- package/dist/tasks/project/create.d.ts +1 -1
- package/dist/tasks/project/create.js +20 -24
- package/dist/tasks/project/sync.d.ts +2 -2
- package/dist/tasks/project/sync.js +7 -3
- package/dist/tasks/runner/bundle.js +4 -1
- package/dist/tasks/task/replay.d.ts +9 -2
- package/dist/tasks/task/replay.js +30 -20
- package/dist/tasks/task/run.d.ts +2 -2
- package/dist/tasks/task/run.js +16 -21
- package/dist/tasks/types.d.ts +4 -0
- package/package.json +6 -6
- package/src/runner.ts +3 -3
- package/src/tasks/bundle/create.ts +14 -3
- package/src/tasks/bundle/fingerprint.ts +5 -1
- package/src/tasks/docs/download.ts +3 -0
- package/src/tasks/project/create.ts +20 -26
- package/src/tasks/project/sync.ts +9 -1
- package/src/tasks/runner/bundle.ts +5 -1
- package/src/tasks/task/replay.ts +35 -21
- package/src/tasks/task/run.ts +17 -24
- package/src/tasks/types.ts +4 -0
package/dist/runner.js
CHANGED
|
@@ -92,7 +92,7 @@ runner.setHandler(async (data) => {
|
|
|
92
92
|
const commandsWithDescriptor = ['task:create', 'task:remove', 'task:publish', 'task:describe', 'task:fingerprint'];
|
|
93
93
|
const commandsWithRunner = ['runner:create', 'runner:remove'];
|
|
94
94
|
const commandsWithoutParams = ['project:unlink', 'project:sync', 'auth:clear'];
|
|
95
|
-
const silentCommands = ['task:describe', 'task:list', 'auth:list', 'info'];
|
|
95
|
+
const silentCommands = ['task:describe', 'task:list', 'auth:list', 'info', 'docs:download'];
|
|
96
96
|
if (commandsWithDescriptor.includes(taskName)) {
|
|
97
97
|
result = await task.run({ descriptorName: action });
|
|
98
98
|
}
|
|
@@ -170,9 +170,9 @@ runner.setHandler(async (data) => {
|
|
|
170
170
|
});
|
|
171
171
|
}
|
|
172
172
|
else if (taskName === 'project:create') {
|
|
173
|
-
const {
|
|
173
|
+
const { name, description } = args;
|
|
174
174
|
result = await task.run({
|
|
175
|
-
|
|
175
|
+
name,
|
|
176
176
|
description
|
|
177
177
|
});
|
|
178
178
|
}
|
|
@@ -1,6 +1,11 @@
|
|
|
1
|
+
import { type ForgeConf } from '../types';
|
|
1
2
|
export declare const create: import("@forgehive/task").TaskInstanceType<(argv: {
|
|
2
3
|
entryPoint: string;
|
|
3
4
|
outputFile: string;
|
|
4
|
-
}, boundaries: import("@forgehive/task").WrappedBoundaries<{
|
|
5
|
+
}, boundaries: import("@forgehive/task").WrappedBoundaries<{
|
|
6
|
+
loadConf: (args: {}) => Promise<Promise<ForgeConf>>;
|
|
7
|
+
}>) => Promise<{
|
|
5
8
|
outputFile: string;
|
|
6
|
-
}>, {
|
|
9
|
+
}>, {
|
|
10
|
+
loadConf: (args: {}) => Promise<Promise<ForgeConf>>;
|
|
11
|
+
}>;
|
|
@@ -10,15 +10,22 @@ exports.create = void 0;
|
|
|
10
10
|
const task_1 = require("@forgehive/task");
|
|
11
11
|
const schema_1 = require("@forgehive/schema");
|
|
12
12
|
const esbuild_1 = __importDefault(require("esbuild"));
|
|
13
|
+
const load_1 = require("../conf/load");
|
|
13
14
|
const schema = new schema_1.Schema({
|
|
14
15
|
entryPoint: schema_1.Schema.string(),
|
|
15
16
|
outputFile: schema_1.Schema.string()
|
|
16
17
|
});
|
|
17
|
-
const boundaries = {
|
|
18
|
+
const boundaries = {
|
|
19
|
+
loadConf: load_1.load.asBoundary()
|
|
20
|
+
};
|
|
18
21
|
exports.create = (0, task_1.createTask)({
|
|
19
22
|
schema,
|
|
20
23
|
boundaries,
|
|
21
|
-
fn: async function ({ entryPoint, outputFile }) {
|
|
24
|
+
fn: async function ({ entryPoint, outputFile }, { loadConf }) {
|
|
25
|
+
// Load forge configuration
|
|
26
|
+
const forge = await loadConf({});
|
|
27
|
+
// Get external packages from config, default to empty array
|
|
28
|
+
const externalPackages = forge.build?.externalPackages ?? [];
|
|
22
29
|
// Build using esbuild
|
|
23
30
|
await esbuild_1.default.build({
|
|
24
31
|
entryPoints: [entryPoint],
|
|
@@ -26,7 +33,8 @@ exports.create = (0, task_1.createTask)({
|
|
|
26
33
|
bundle: true,
|
|
27
34
|
minify: true,
|
|
28
35
|
platform: 'node',
|
|
29
|
-
sourcemap: true
|
|
36
|
+
sourcemap: true,
|
|
37
|
+
external: externalPackages
|
|
30
38
|
});
|
|
31
39
|
return { outputFile };
|
|
32
40
|
}
|
|
@@ -122,6 +122,8 @@ exports.fingerprint = (0, task_1.createTask)({
|
|
|
122
122
|
console.log(`Generating bundle with fingerprints for task: ${descriptorName}`);
|
|
123
123
|
console.log(`Entry point: ${entryPoint}`);
|
|
124
124
|
console.log(`Output: ${outputFile}`);
|
|
125
|
+
// Get external packages from config, default to empty array
|
|
126
|
+
const externalPackages = forgeJson.build?.externalPackages ?? [];
|
|
125
127
|
// Build with fingerprinting plugin
|
|
126
128
|
const result = await esbuild_1.default.build({
|
|
127
129
|
entryPoints: [entryPoint],
|
|
@@ -131,7 +133,8 @@ exports.fingerprint = (0, task_1.createTask)({
|
|
|
131
133
|
platform: 'node',
|
|
132
134
|
sourcemap: true,
|
|
133
135
|
plugins: [taskFingerprintPlugin()],
|
|
134
|
-
metafile: true
|
|
136
|
+
metafile: true,
|
|
137
|
+
external: externalPackages
|
|
135
138
|
});
|
|
136
139
|
// Extract fingerprints from build result
|
|
137
140
|
const taskFingerprints = result.fingerprints || [];
|
|
@@ -117,6 +117,7 @@ exports.download = (0, task_1.createTask)({
|
|
|
117
117
|
});
|
|
118
118
|
// Download Hive logging guide if --logs flag is provided
|
|
119
119
|
if (logs) {
|
|
120
|
+
console.log('===============================================');
|
|
120
121
|
const logsTargetPath = customPath
|
|
121
122
|
? path_1.default.join(path_1.default.dirname(customPath), 'hive-logging.md')
|
|
122
123
|
: 'docs/hive-logging.md';
|
|
@@ -142,6 +143,7 @@ exports.download = (0, task_1.createTask)({
|
|
|
142
143
|
size: logsContent.length
|
|
143
144
|
});
|
|
144
145
|
}
|
|
146
|
+
console.log('===============================================');
|
|
145
147
|
return {
|
|
146
148
|
success: true,
|
|
147
149
|
downloads: results,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type ForgeConf, type Profile } from '../types';
|
|
2
2
|
export declare const create: import("@forgehive/task").TaskInstanceType<(argv: {
|
|
3
|
+
name: string;
|
|
3
4
|
description?: string | undefined;
|
|
4
|
-
projectName?: string | undefined;
|
|
5
5
|
}, boundaries: import("@forgehive/task").WrappedBoundaries<{
|
|
6
6
|
loadConf: (args: {}) => Promise<Promise<ForgeConf>>;
|
|
7
7
|
loadCurrentProfile: (args: {}) => Promise<Promise<Profile>>;
|
|
@@ -14,10 +14,10 @@ const promises_1 = __importDefault(require("fs/promises"));
|
|
|
14
14
|
const path_1 = __importDefault(require("path"));
|
|
15
15
|
const load_1 = require("../conf/load");
|
|
16
16
|
const loadCurrent_1 = require("../auth/loadCurrent");
|
|
17
|
-
const
|
|
18
|
-
const
|
|
17
|
+
const taskName = 'project:create';
|
|
18
|
+
const taskDescription = 'Create a new project in ForgeHive';
|
|
19
19
|
const schema = new schema_1.Schema({
|
|
20
|
-
|
|
20
|
+
name: schema_1.Schema.string(),
|
|
21
21
|
description: schema_1.Schema.string().optional()
|
|
22
22
|
});
|
|
23
23
|
const boundaries = {
|
|
@@ -39,33 +39,29 @@ const boundaries = {
|
|
|
39
39
|
}
|
|
40
40
|
};
|
|
41
41
|
exports.create = (0, task_1.createTask)({
|
|
42
|
-
name,
|
|
43
|
-
description,
|
|
42
|
+
name: taskName,
|
|
43
|
+
description: taskDescription,
|
|
44
44
|
schema,
|
|
45
45
|
boundaries,
|
|
46
46
|
fn: async function (argv, { loadConf, loadCurrentProfile, writeFile, createProject }) {
|
|
47
|
-
const {
|
|
47
|
+
const { name: projectName, description } = argv;
|
|
48
48
|
// Load current configuration
|
|
49
49
|
const conf = await loadConf({});
|
|
50
|
-
// Use provided projectName or fall back to forge.json project name
|
|
51
|
-
const projectName = inputProjectName || conf.project.name;
|
|
52
|
-
if (!projectName) {
|
|
53
|
-
throw new Error('Project name is required. Provide --projectName or ensure forge.json has a project name.');
|
|
54
|
-
}
|
|
55
50
|
// Check if project already has a UUID, generate one if not
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
...conf,
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
51
|
+
const projectUuid = conf.project.uuid || (0, uuid_1.v4)();
|
|
52
|
+
// Update forge.json with the project name and UUID
|
|
53
|
+
const forgePath = path_1.default.join(process.cwd(), 'forge.json');
|
|
54
|
+
const updatedConf = {
|
|
55
|
+
...conf,
|
|
56
|
+
project: {
|
|
57
|
+
...conf.project,
|
|
58
|
+
name: projectName,
|
|
59
|
+
uuid: projectUuid
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
await writeFile(forgePath, JSON.stringify(updatedConf, null, 2));
|
|
63
|
+
console.log(`Updated forge.json with project name: ${projectName}`);
|
|
64
|
+
if (!conf.project.uuid) {
|
|
69
65
|
console.log(`Generated and saved project UUID: ${projectUuid}`);
|
|
70
66
|
}
|
|
71
67
|
// Load current profile for API authentication
|
|
@@ -4,7 +4,7 @@ export declare const sync: import("@forgehive/task").TaskInstanceType<(argv: {},
|
|
|
4
4
|
loadCurrentProfile: (args: {}) => Promise<Promise<import("../types").Profile>>;
|
|
5
5
|
getCwd: () => Promise<string>;
|
|
6
6
|
persistConf: (forge: ForgeConf, cwd: string) => Promise<void>;
|
|
7
|
-
syncTasksToHive: (projectUuid: string, tasks: Array<{
|
|
7
|
+
syncTasksToHive: (projectUuid: string, projectName: string, projectDescription: string | undefined, tasks: Array<{
|
|
8
8
|
uuid: string;
|
|
9
9
|
name: string;
|
|
10
10
|
}>, apiKey: string, apiSecret: string, baseUrl: string) => Promise<{
|
|
@@ -78,7 +78,7 @@ export declare const sync: import("@forgehive/task").TaskInstanceType<(argv: {},
|
|
|
78
78
|
loadCurrentProfile: (args: {}) => Promise<Promise<import("../types").Profile>>;
|
|
79
79
|
getCwd: () => Promise<string>;
|
|
80
80
|
persistConf: (forge: ForgeConf, cwd: string) => Promise<void>;
|
|
81
|
-
syncTasksToHive: (projectUuid: string, tasks: Array<{
|
|
81
|
+
syncTasksToHive: (projectUuid: string, projectName: string, projectDescription: string | undefined, tasks: Array<{
|
|
82
82
|
uuid: string;
|
|
83
83
|
name: string;
|
|
84
84
|
}>, apiKey: string, apiSecret: string, baseUrl: string) => Promise<{
|
|
@@ -25,7 +25,7 @@ const boundaries = {
|
|
|
25
25
|
const forgePath = path_1.default.join(cwd, 'forge.json');
|
|
26
26
|
await promises_1.default.writeFile(forgePath, JSON.stringify(forge, null, 2));
|
|
27
27
|
},
|
|
28
|
-
syncTasksToHive: async (projectUuid, tasks, apiKey, apiSecret, baseUrl) => {
|
|
28
|
+
syncTasksToHive: async (projectUuid, projectName, projectDescription, tasks, apiKey, apiSecret, baseUrl) => {
|
|
29
29
|
try {
|
|
30
30
|
const url = `${baseUrl}/api/projects/${projectUuid}/sync`;
|
|
31
31
|
const response = await fetch(url, {
|
|
@@ -34,7 +34,7 @@ const boundaries = {
|
|
|
34
34
|
'Content-Type': 'application/json',
|
|
35
35
|
'Authorization': `Bearer ${apiKey}:${apiSecret}`
|
|
36
36
|
},
|
|
37
|
-
body: JSON.stringify({ tasks })
|
|
37
|
+
body: JSON.stringify({ projectName, description: projectDescription, tasks })
|
|
38
38
|
});
|
|
39
39
|
if (response.ok) {
|
|
40
40
|
const data = await response.json();
|
|
@@ -96,9 +96,13 @@ exports.sync = (0, task_1.createTask)({
|
|
|
96
96
|
return { status: 'no-tasks', message: 'No tasks found in project' };
|
|
97
97
|
}
|
|
98
98
|
console.log(` 📊 Found ${tasksToSync.length} tasks to sync`);
|
|
99
|
+
console.log(` 📝 Project name: ${forge.project.name}`);
|
|
100
|
+
if (forge.project.description) {
|
|
101
|
+
console.log(` 📝 Project description: ${forge.project.description}`);
|
|
102
|
+
}
|
|
99
103
|
try {
|
|
100
104
|
const profile = await loadCurrentProfile({});
|
|
101
|
-
const result = await syncTasksToHive(forge.project.uuid, tasksToSync, profile.apiKey, profile.apiSecret, profile.url);
|
|
105
|
+
const result = await syncTasksToHive(forge.project.uuid, forge.project.name, forge.project.description, tasksToSync, profile.apiKey, profile.apiSecret, profile.url);
|
|
102
106
|
if (result.success && result.data) {
|
|
103
107
|
const { summary, results } = result.data;
|
|
104
108
|
console.log('\\n ✅ Sync completed successfully!');
|
|
@@ -56,6 +56,8 @@ exports.bundle = (0, task_1.createTask)({
|
|
|
56
56
|
`);
|
|
57
57
|
// Ensure target directory exists
|
|
58
58
|
await ensureDir(path_1.default.dirname(targetPath));
|
|
59
|
+
// Get external packages from config, default to empty array
|
|
60
|
+
const externalPackages = forge.build?.externalPackages ?? [];
|
|
59
61
|
// Build using esbuild
|
|
60
62
|
await esbuild_1.default.build({
|
|
61
63
|
entryPoints: [entryPoint],
|
|
@@ -63,7 +65,8 @@ exports.bundle = (0, task_1.createTask)({
|
|
|
63
65
|
bundle: true,
|
|
64
66
|
minify: true,
|
|
65
67
|
platform: 'node',
|
|
66
|
-
sourcemap: true
|
|
68
|
+
sourcemap: true,
|
|
69
|
+
external: externalPackages
|
|
67
70
|
});
|
|
68
71
|
return {
|
|
69
72
|
status: 'Success',
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type ExecutionRecord } from '@forgehive/hive-sdk';
|
|
1
2
|
import { type ForgeConf, type Profile } from '../types';
|
|
2
3
|
interface Fixture {
|
|
3
4
|
fixtureUUID: string;
|
|
@@ -28,7 +29,10 @@ export declare const replay: import("@forgehive/task").TaskInstanceType<(argv: {
|
|
|
28
29
|
}) => Promise<Promise<any>>;
|
|
29
30
|
ensureBuildsFolder: () => Promise<string>;
|
|
30
31
|
verifyLogFolder: (logsPath: string) => Promise<boolean>;
|
|
31
|
-
sendLogToAPI: (profile: Profile,
|
|
32
|
+
sendLogToAPI: (profile: Profile, record: ExecutionRecord, fixtureUUID: string) => Promise<{
|
|
33
|
+
success: boolean;
|
|
34
|
+
logUuid?: string;
|
|
35
|
+
}>;
|
|
32
36
|
}>) => Promise<any>, {
|
|
33
37
|
readFixture: (filePath: string) => Promise<Fixture>;
|
|
34
38
|
loadConf: (args: {}) => Promise<Promise<ForgeConf>>;
|
|
@@ -44,6 +48,9 @@ export declare const replay: import("@forgehive/task").TaskInstanceType<(argv: {
|
|
|
44
48
|
}) => Promise<Promise<any>>;
|
|
45
49
|
ensureBuildsFolder: () => Promise<string>;
|
|
46
50
|
verifyLogFolder: (logsPath: string) => Promise<boolean>;
|
|
47
|
-
sendLogToAPI: (profile: Profile,
|
|
51
|
+
sendLogToAPI: (profile: Profile, record: ExecutionRecord, fixtureUUID: string) => Promise<{
|
|
52
|
+
success: boolean;
|
|
53
|
+
logUuid?: string;
|
|
54
|
+
}>;
|
|
48
55
|
}>;
|
|
49
56
|
export {};
|
|
@@ -12,7 +12,7 @@ const schema_1 = require("@forgehive/schema");
|
|
|
12
12
|
const promises_1 = __importDefault(require("fs/promises"));
|
|
13
13
|
const path_1 = __importDefault(require("path"));
|
|
14
14
|
const os_1 = __importDefault(require("os"));
|
|
15
|
-
const
|
|
15
|
+
const hive_sdk_1 = require("@forgehive/hive-sdk");
|
|
16
16
|
const create_1 = require("../bundle/create");
|
|
17
17
|
const load_1 = require("../bundle/load");
|
|
18
18
|
const load_2 = require("../conf/load");
|
|
@@ -53,30 +53,41 @@ const boundaries = {
|
|
|
53
53
|
}
|
|
54
54
|
return true;
|
|
55
55
|
},
|
|
56
|
-
sendLogToAPI: async (profile,
|
|
56
|
+
sendLogToAPI: async (profile, record, fixtureUUID) => {
|
|
57
57
|
try {
|
|
58
|
-
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
headers: {
|
|
67
|
-
Authorization: `Bearer ${authToken}`,
|
|
68
|
-
'Content-Type': 'application/json'
|
|
58
|
+
// Use createClientFromForgeConf to automatically load forge.json with task UUIDs
|
|
59
|
+
const client = (0, hive_sdk_1.createClientFromForgeConf)('./forge.json', {
|
|
60
|
+
apiKey: profile.apiKey,
|
|
61
|
+
apiSecret: profile.apiSecret,
|
|
62
|
+
host: profile.url,
|
|
63
|
+
metadata: {
|
|
64
|
+
environment: 'cli',
|
|
65
|
+
replayFrom: fixtureUUID
|
|
69
66
|
}
|
|
70
67
|
});
|
|
71
68
|
console.log('===============================================');
|
|
72
|
-
console.log('
|
|
73
|
-
|
|
74
|
-
|
|
69
|
+
console.log('Sending replay log to Hive...');
|
|
70
|
+
const result = await client.sendLog(record);
|
|
71
|
+
if (result === 'success' || (typeof result === 'object' && 'uuid' in result)) {
|
|
72
|
+
console.log('✅ Log sent to API...', profile.name, profile.url);
|
|
73
|
+
console.log('Replay from fixture UUID:', fixtureUUID);
|
|
74
|
+
console.log('===============================================');
|
|
75
|
+
if (typeof result === 'object' && result && 'uuid' in result) {
|
|
76
|
+
return { success: true, logUuid: result.uuid };
|
|
77
|
+
}
|
|
78
|
+
return { success: true };
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
console.error('❌ Failed to send log to Hive');
|
|
82
|
+
console.log('===============================================');
|
|
83
|
+
return { success: false };
|
|
84
|
+
}
|
|
75
85
|
}
|
|
76
86
|
catch (e) {
|
|
77
87
|
const error = e;
|
|
78
|
-
console.error('Failed to send log to API:', error.message);
|
|
79
|
-
|
|
88
|
+
console.error('❌ Failed to send log to API:', error.message);
|
|
89
|
+
console.log('===============================================');
|
|
90
|
+
return { success: false };
|
|
80
91
|
}
|
|
81
92
|
}
|
|
82
93
|
};
|
|
@@ -90,7 +101,6 @@ exports.replay = (0, task_1.createTask)({
|
|
|
90
101
|
// Load forge configuration
|
|
91
102
|
const forge = await loadConf({});
|
|
92
103
|
const taskDescriptor = forge.tasks[descriptorName];
|
|
93
|
-
const projectName = forge.project.name;
|
|
94
104
|
if (taskDescriptor === undefined) {
|
|
95
105
|
throw new Error(`Task ${descriptorName} is not defined in forge.json`);
|
|
96
106
|
}
|
|
@@ -168,7 +178,7 @@ exports.replay = (0, task_1.createTask)({
|
|
|
168
178
|
// Send the log to API if profile is available
|
|
169
179
|
if (profile) {
|
|
170
180
|
try {
|
|
171
|
-
await sendLogToAPI(profile,
|
|
181
|
+
await sendLogToAPI(profile, record, fixture.fixtureUUID);
|
|
172
182
|
}
|
|
173
183
|
catch (e) {
|
|
174
184
|
console.error('Failed to send log to API:', e);
|
package/dist/tasks/task/run.d.ts
CHANGED
|
@@ -17,7 +17,7 @@ export declare const run: import("@forgehive/task").TaskInstanceType<(argv: {
|
|
|
17
17
|
}) => Promise<Promise<any>>;
|
|
18
18
|
ensureLogFolder: (logsPath: string) => Promise<void>;
|
|
19
19
|
ensureBuildsFolder: () => Promise<string>;
|
|
20
|
-
sendLogToAPI: (profile: Profile,
|
|
20
|
+
sendLogToAPI: (profile: Profile, record: ExecutionRecord, taskUuid?: string) => Promise<{
|
|
21
21
|
success: boolean;
|
|
22
22
|
logUuid?: string;
|
|
23
23
|
taskUuid?: string;
|
|
@@ -37,7 +37,7 @@ export declare const run: import("@forgehive/task").TaskInstanceType<(argv: {
|
|
|
37
37
|
}) => Promise<Promise<any>>;
|
|
38
38
|
ensureLogFolder: (logsPath: string) => Promise<void>;
|
|
39
39
|
ensureBuildsFolder: () => Promise<string>;
|
|
40
|
-
sendLogToAPI: (profile: Profile,
|
|
40
|
+
sendLogToAPI: (profile: Profile, record: ExecutionRecord, taskUuid?: string) => Promise<{
|
|
41
41
|
success: boolean;
|
|
42
42
|
logUuid?: string;
|
|
43
43
|
taskUuid?: string;
|
package/dist/tasks/task/run.js
CHANGED
|
@@ -50,39 +50,32 @@ const boundaries = {
|
|
|
50
50
|
}
|
|
51
51
|
return buildsPath;
|
|
52
52
|
},
|
|
53
|
-
sendLogToAPI: async (profile,
|
|
54
|
-
// Check if we have required
|
|
55
|
-
if (!
|
|
53
|
+
sendLogToAPI: async (profile, record, taskUuid) => {
|
|
54
|
+
// Check if we have required UUID for the task
|
|
55
|
+
if (!taskUuid) {
|
|
56
56
|
console.log('===============================================');
|
|
57
|
-
console.log('⚠️ Remote logging skipped - missing
|
|
57
|
+
console.log('⚠️ Remote logging skipped - missing task UUID');
|
|
58
58
|
console.log('');
|
|
59
59
|
console.log('To enable remote logging with enhanced features:');
|
|
60
|
-
|
|
61
|
-
console.log('• Use "forge project:create" to create a new project, or');
|
|
62
|
-
console.log('• Use "forge project:link" to connect to an existing project');
|
|
63
|
-
}
|
|
64
|
-
if (!taskUuid) {
|
|
65
|
-
console.log('• Use "forge project:sync" to get the task to have UUID');
|
|
66
|
-
}
|
|
60
|
+
console.log('• Use "forge project:sync" to sync tasks and get UUIDs');
|
|
67
61
|
console.log('===============================================');
|
|
68
62
|
return { success: true, skipRemoteLog: true };
|
|
69
63
|
}
|
|
70
64
|
try {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
projectUuid,
|
|
65
|
+
// Use createClientFromForgeConf to automatically load forge.json with task UUIDs
|
|
66
|
+
const client = (0, hive_sdk_1.createClientFromForgeConf)('./forge.json', {
|
|
74
67
|
apiKey: profile.apiKey,
|
|
75
68
|
apiSecret: profile.apiSecret,
|
|
76
69
|
host: profile.url,
|
|
77
70
|
metadata: {
|
|
78
71
|
environment: 'cli'
|
|
79
72
|
}
|
|
80
|
-
};
|
|
81
|
-
|
|
73
|
+
});
|
|
74
|
+
console.log('===============================================');
|
|
82
75
|
console.log('Sending execution log to Hive...');
|
|
83
|
-
const result = await client.
|
|
76
|
+
const result = await client.sendLog(record);
|
|
84
77
|
if (result === 'success' || (typeof result === 'object' && 'uuid' in result)) {
|
|
85
|
-
console.log('
|
|
78
|
+
console.log('');
|
|
86
79
|
console.log('✅ Log sent to Hive successfully');
|
|
87
80
|
console.log(` Profile: ${profile.name}`);
|
|
88
81
|
console.log(` Host: ${profile.url}`);
|
|
@@ -93,14 +86,18 @@ const boundaries = {
|
|
|
93
86
|
return { success: true, taskUuid };
|
|
94
87
|
}
|
|
95
88
|
else {
|
|
89
|
+
console.log('');
|
|
96
90
|
console.error('❌ Failed to send log to Hive:', profile.url);
|
|
91
|
+
console.log('===============================================');
|
|
97
92
|
return { success: false };
|
|
98
93
|
}
|
|
99
94
|
}
|
|
100
95
|
catch (e) {
|
|
96
|
+
console.log('===============================================');
|
|
101
97
|
console.error('❌ Failed to send log to Hive:', profile.url);
|
|
102
98
|
const error = e;
|
|
103
99
|
console.error('Error:', error.message);
|
|
100
|
+
console.log('===============================================');
|
|
104
101
|
return { success: false };
|
|
105
102
|
}
|
|
106
103
|
}
|
|
@@ -112,8 +109,6 @@ exports.run = (0, task_1.createTask)({
|
|
|
112
109
|
// Load forge configuration
|
|
113
110
|
const forge = await loadConf({});
|
|
114
111
|
const taskDescriptor = forge.tasks[descriptorName];
|
|
115
|
-
const projectName = forge.project.name;
|
|
116
|
-
const projectUuid = forge.project.uuid;
|
|
117
112
|
const taskUuid = taskDescriptor?.uuid;
|
|
118
113
|
if (taskDescriptor === undefined) {
|
|
119
114
|
throw new Error('Task is not defined on forge.json');
|
|
@@ -175,7 +170,7 @@ exports.run = (0, task_1.createTask)({
|
|
|
175
170
|
await tape.save();
|
|
176
171
|
if (profile) {
|
|
177
172
|
try {
|
|
178
|
-
const logResult = await sendLogToAPI(profile,
|
|
173
|
+
const logResult = await sendLogToAPI(profile, logItem, taskUuid);
|
|
179
174
|
if (logResult.success && !logResult.skipRemoteLog && taskUuid) {
|
|
180
175
|
console.log(`🔗 View execution logs: ${profile.url}/tasks/${taskUuid}?tab=logs`);
|
|
181
176
|
}
|
package/dist/tasks/types.d.ts
CHANGED
|
@@ -19,6 +19,7 @@ export interface ForgeConf {
|
|
|
19
19
|
project: {
|
|
20
20
|
name: string;
|
|
21
21
|
uuid?: string;
|
|
22
|
+
description?: string;
|
|
22
23
|
};
|
|
23
24
|
paths: {
|
|
24
25
|
logs: string;
|
|
@@ -31,6 +32,9 @@ export interface ForgeConf {
|
|
|
31
32
|
infra: Infra;
|
|
32
33
|
tasks: Record<string, TaskDescriptor>;
|
|
33
34
|
runners: Record<string, RunnerDescriptor>;
|
|
35
|
+
build?: {
|
|
36
|
+
externalPackages?: string[];
|
|
37
|
+
};
|
|
34
38
|
}
|
|
35
39
|
export interface TaskName {
|
|
36
40
|
descriptor: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forgehive/forge-cli",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.18",
|
|
4
4
|
"description": "TypeScript CLI application",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"publishConfig": {
|
|
11
11
|
"access": "public",
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@forgehive/hive-sdk": "^0.
|
|
13
|
+
"@forgehive/hive-sdk": "^0.2.0",
|
|
14
14
|
"@forgehive/record-tape": "^0.2.7",
|
|
15
15
|
"@forgehive/runner": "^0.2.7",
|
|
16
16
|
"@forgehive/schema": "^0.1.4",
|
|
@@ -30,11 +30,11 @@
|
|
|
30
30
|
"minimist": "^1.2.8",
|
|
31
31
|
"typescript": "^5.3.3",
|
|
32
32
|
"uuid": "^11.1.0",
|
|
33
|
-
"@forgehive/
|
|
33
|
+
"@forgehive/record-tape": "0.2.7",
|
|
34
34
|
"@forgehive/task": "0.2.7",
|
|
35
|
-
"@forgehive/hive-sdk": "0.
|
|
36
|
-
"@forgehive/
|
|
37
|
-
"@forgehive/
|
|
35
|
+
"@forgehive/hive-sdk": "0.2.0",
|
|
36
|
+
"@forgehive/schema": "0.1.4",
|
|
37
|
+
"@forgehive/runner": "0.2.7"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@types/archiver": "^6.0.3",
|
package/src/runner.ts
CHANGED
|
@@ -114,7 +114,7 @@ runner.setHandler(async (data: ParsedArgs): Promise<unknown> => {
|
|
|
114
114
|
const commandsWithDescriptor = ['task:create', 'task:remove', 'task:publish', 'task:describe', 'task:fingerprint']
|
|
115
115
|
const commandsWithRunner = ['runner:create', 'runner:remove']
|
|
116
116
|
const commandsWithoutParams = ['project:unlink', 'project:sync', 'auth:clear']
|
|
117
|
-
const silentCommands = ['task:describe', 'task:list', 'auth:list', 'info']
|
|
117
|
+
const silentCommands = ['task:describe', 'task:list', 'auth:list', 'info', 'docs:download']
|
|
118
118
|
|
|
119
119
|
if (commandsWithDescriptor.includes(taskName)) {
|
|
120
120
|
result = await task.run({ descriptorName: action })
|
|
@@ -191,10 +191,10 @@ runner.setHandler(async (data: ParsedArgs): Promise<unknown> => {
|
|
|
191
191
|
logs
|
|
192
192
|
})
|
|
193
193
|
} else if (taskName === 'project:create') {
|
|
194
|
-
const {
|
|
194
|
+
const { name, description } = args as { name: string, description?: string }
|
|
195
195
|
|
|
196
196
|
result = await task.run({
|
|
197
|
-
|
|
197
|
+
name,
|
|
198
198
|
description
|
|
199
199
|
})
|
|
200
200
|
} else if (taskName === 'project:link') {
|
|
@@ -5,18 +5,28 @@
|
|
|
5
5
|
import { createTask } from '@forgehive/task'
|
|
6
6
|
import { Schema } from '@forgehive/schema'
|
|
7
7
|
import esbuild from 'esbuild'
|
|
8
|
+
import { load as loadConf } from '../conf/load'
|
|
9
|
+
import { type ForgeConf } from '../types'
|
|
8
10
|
|
|
9
11
|
const schema = new Schema({
|
|
10
12
|
entryPoint: Schema.string(),
|
|
11
13
|
outputFile: Schema.string()
|
|
12
14
|
})
|
|
13
15
|
|
|
14
|
-
const boundaries = {
|
|
16
|
+
const boundaries = {
|
|
17
|
+
loadConf: loadConf.asBoundary()
|
|
18
|
+
}
|
|
15
19
|
|
|
16
20
|
export const create = createTask({
|
|
17
21
|
schema,
|
|
18
22
|
boundaries,
|
|
19
|
-
fn: async function ({ entryPoint, outputFile }) {
|
|
23
|
+
fn: async function ({ entryPoint, outputFile }, { loadConf }) {
|
|
24
|
+
// Load forge configuration
|
|
25
|
+
const forge: ForgeConf = await loadConf({})
|
|
26
|
+
|
|
27
|
+
// Get external packages from config, default to empty array
|
|
28
|
+
const externalPackages = forge.build?.externalPackages ?? []
|
|
29
|
+
|
|
20
30
|
// Build using esbuild
|
|
21
31
|
await esbuild.build({
|
|
22
32
|
entryPoints: [entryPoint],
|
|
@@ -24,7 +34,8 @@ export const create = createTask({
|
|
|
24
34
|
bundle: true,
|
|
25
35
|
minify: true,
|
|
26
36
|
platform: 'node',
|
|
27
|
-
sourcemap: true
|
|
37
|
+
sourcemap: true,
|
|
38
|
+
external: externalPackages
|
|
28
39
|
})
|
|
29
40
|
|
|
30
41
|
return { outputFile }
|
|
@@ -174,6 +174,9 @@ export const fingerprint = createTask({
|
|
|
174
174
|
console.log(`Entry point: ${entryPoint}`)
|
|
175
175
|
console.log(`Output: ${outputFile}`)
|
|
176
176
|
|
|
177
|
+
// Get external packages from config, default to empty array
|
|
178
|
+
const externalPackages = forgeJson.build?.externalPackages ?? []
|
|
179
|
+
|
|
177
180
|
// Build with fingerprinting plugin
|
|
178
181
|
const result = await esbuild.build({
|
|
179
182
|
entryPoints: [entryPoint],
|
|
@@ -183,7 +186,8 @@ export const fingerprint = createTask({
|
|
|
183
186
|
platform: 'node',
|
|
184
187
|
sourcemap: true,
|
|
185
188
|
plugins: [taskFingerprintPlugin()],
|
|
186
|
-
metafile: true
|
|
189
|
+
metafile: true,
|
|
190
|
+
external: externalPackages
|
|
187
191
|
})
|
|
188
192
|
|
|
189
193
|
// Extract fingerprints from build result
|
|
@@ -92,6 +92,7 @@ export const download = createTask({
|
|
|
92
92
|
|
|
93
93
|
// Download Hive logging guide if --logs flag is provided
|
|
94
94
|
if (logs) {
|
|
95
|
+
console.log('===============================================')
|
|
95
96
|
const logsTargetPath = customPath
|
|
96
97
|
? path.join(path.dirname(customPath), 'hive-logging.md')
|
|
97
98
|
: 'docs/hive-logging.md'
|
|
@@ -125,6 +126,8 @@ export const download = createTask({
|
|
|
125
126
|
})
|
|
126
127
|
}
|
|
127
128
|
|
|
129
|
+
console.log('===============================================')
|
|
130
|
+
|
|
128
131
|
return {
|
|
129
132
|
success: true,
|
|
130
133
|
downloads: results,
|
|
@@ -12,11 +12,11 @@ import { load as loadConf } from '../conf/load'
|
|
|
12
12
|
import { loadCurrent as loadCurrentProfile } from '../auth/loadCurrent'
|
|
13
13
|
import { type ForgeConf, type Profile } from '../types'
|
|
14
14
|
|
|
15
|
-
const
|
|
16
|
-
const
|
|
15
|
+
const taskName = 'project:create'
|
|
16
|
+
const taskDescription = 'Create a new project in ForgeHive'
|
|
17
17
|
|
|
18
18
|
const schema = new Schema({
|
|
19
|
-
|
|
19
|
+
name: Schema.string(),
|
|
20
20
|
description: Schema.string().optional()
|
|
21
21
|
})
|
|
22
22
|
|
|
@@ -40,39 +40,33 @@ const boundaries = {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
export const create = createTask({
|
|
43
|
-
name,
|
|
44
|
-
description,
|
|
43
|
+
name: taskName,
|
|
44
|
+
description: taskDescription,
|
|
45
45
|
schema,
|
|
46
46
|
boundaries,
|
|
47
47
|
fn: async function (argv, { loadConf, loadCurrentProfile, writeFile, createProject }) {
|
|
48
|
-
const {
|
|
48
|
+
const { name: projectName, description } = argv
|
|
49
49
|
|
|
50
50
|
// Load current configuration
|
|
51
51
|
const conf = await loadConf({})
|
|
52
52
|
|
|
53
|
-
// Use provided projectName or fall back to forge.json project name
|
|
54
|
-
const projectName = inputProjectName || conf.project.name
|
|
55
|
-
|
|
56
|
-
if (!projectName) {
|
|
57
|
-
throw new Error('Project name is required. Provide --projectName or ensure forge.json has a project name.')
|
|
58
|
-
}
|
|
59
|
-
|
|
60
53
|
// Check if project already has a UUID, generate one if not
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
...conf,
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
uuid: projectUuid
|
|
72
|
-
}
|
|
54
|
+
const projectUuid = conf.project.uuid || uuidv4()
|
|
55
|
+
|
|
56
|
+
// Update forge.json with the project name and UUID
|
|
57
|
+
const forgePath = path.join(process.cwd(), 'forge.json')
|
|
58
|
+
const updatedConf: ForgeConf = {
|
|
59
|
+
...conf,
|
|
60
|
+
project: {
|
|
61
|
+
...conf.project,
|
|
62
|
+
name: projectName,
|
|
63
|
+
uuid: projectUuid
|
|
73
64
|
}
|
|
65
|
+
}
|
|
74
66
|
|
|
75
|
-
|
|
67
|
+
await writeFile(forgePath, JSON.stringify(updatedConf, null, 2))
|
|
68
|
+
console.log(`Updated forge.json with project name: ${projectName}`)
|
|
69
|
+
if (!conf.project.uuid) {
|
|
76
70
|
console.log(`Generated and saved project UUID: ${projectUuid}`)
|
|
77
71
|
}
|
|
78
72
|
|
|
@@ -26,6 +26,8 @@ const boundaries = {
|
|
|
26
26
|
},
|
|
27
27
|
syncTasksToHive: async (
|
|
28
28
|
projectUuid: string,
|
|
29
|
+
projectName: string,
|
|
30
|
+
projectDescription: string | undefined,
|
|
29
31
|
tasks: Array<{ uuid: string; name: string }>,
|
|
30
32
|
apiKey: string,
|
|
31
33
|
apiSecret: string,
|
|
@@ -57,7 +59,7 @@ const boundaries = {
|
|
|
57
59
|
'Content-Type': 'application/json',
|
|
58
60
|
'Authorization': `Bearer ${apiKey}:${apiSecret}`
|
|
59
61
|
},
|
|
60
|
-
body: JSON.stringify({ tasks })
|
|
62
|
+
body: JSON.stringify({ projectName, description: projectDescription, tasks })
|
|
61
63
|
})
|
|
62
64
|
|
|
63
65
|
if (response.ok) {
|
|
@@ -134,11 +136,17 @@ export const sync = createTask({
|
|
|
134
136
|
}
|
|
135
137
|
|
|
136
138
|
console.log(` 📊 Found ${tasksToSync.length} tasks to sync`)
|
|
139
|
+
console.log(` 📝 Project name: ${forge.project.name}`)
|
|
140
|
+
if (forge.project.description) {
|
|
141
|
+
console.log(` 📝 Project description: ${forge.project.description}`)
|
|
142
|
+
}
|
|
137
143
|
|
|
138
144
|
try {
|
|
139
145
|
const profile = await loadCurrentProfile({})
|
|
140
146
|
const result = await syncTasksToHive(
|
|
141
147
|
forge.project.uuid,
|
|
148
|
+
forge.project.name,
|
|
149
|
+
forge.project.description,
|
|
142
150
|
tasksToSync,
|
|
143
151
|
profile.apiKey,
|
|
144
152
|
profile.apiSecret,
|
|
@@ -59,6 +59,9 @@ export const bundle = createTask({
|
|
|
59
59
|
// Ensure target directory exists
|
|
60
60
|
await ensureDir(path.dirname(targetPath))
|
|
61
61
|
|
|
62
|
+
// Get external packages from config, default to empty array
|
|
63
|
+
const externalPackages = forge.build?.externalPackages ?? []
|
|
64
|
+
|
|
62
65
|
// Build using esbuild
|
|
63
66
|
await esbuild.build({
|
|
64
67
|
entryPoints: [entryPoint],
|
|
@@ -66,7 +69,8 @@ export const bundle = createTask({
|
|
|
66
69
|
bundle: true,
|
|
67
70
|
minify: true,
|
|
68
71
|
platform: 'node',
|
|
69
|
-
sourcemap: true
|
|
72
|
+
sourcemap: true,
|
|
73
|
+
external: externalPackages
|
|
70
74
|
})
|
|
71
75
|
|
|
72
76
|
return {
|
package/src/tasks/task/replay.ts
CHANGED
|
@@ -7,8 +7,8 @@ import { Schema } from '@forgehive/schema'
|
|
|
7
7
|
import fs from 'fs/promises'
|
|
8
8
|
import path from 'path'
|
|
9
9
|
import os from 'os'
|
|
10
|
-
import axios from 'axios'
|
|
11
10
|
|
|
11
|
+
import { createClientFromForgeConf, type ExecutionRecord } from '@forgehive/hive-sdk'
|
|
12
12
|
import { create as bundleCreate } from '../bundle/create'
|
|
13
13
|
import { load as bundleLoad } from '../bundle/load'
|
|
14
14
|
import { load as loadConf } from '../conf/load'
|
|
@@ -66,32 +66,47 @@ const boundaries = {
|
|
|
66
66
|
|
|
67
67
|
return true
|
|
68
68
|
},
|
|
69
|
-
sendLogToAPI: async (
|
|
69
|
+
sendLogToAPI: async (
|
|
70
|
+
profile: Profile,
|
|
71
|
+
record: ExecutionRecord,
|
|
72
|
+
fixtureUUID: string
|
|
73
|
+
): Promise<{ success: boolean; logUuid?: string }> => {
|
|
70
74
|
try {
|
|
71
|
-
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}, {
|
|
80
|
-
headers: {
|
|
81
|
-
Authorization: `Bearer ${authToken}`,
|
|
82
|
-
'Content-Type': 'application/json'
|
|
75
|
+
// Use createClientFromForgeConf to automatically load forge.json with task UUIDs
|
|
76
|
+
const client = createClientFromForgeConf('./forge.json', {
|
|
77
|
+
apiKey: profile.apiKey,
|
|
78
|
+
apiSecret: profile.apiSecret,
|
|
79
|
+
host: profile.url,
|
|
80
|
+
metadata: {
|
|
81
|
+
environment: 'cli',
|
|
82
|
+
replayFrom: fixtureUUID
|
|
83
83
|
}
|
|
84
84
|
})
|
|
85
85
|
|
|
86
86
|
console.log('===============================================')
|
|
87
|
-
console.log('
|
|
88
|
-
|
|
87
|
+
console.log('Sending replay log to Hive...')
|
|
88
|
+
const result = await client.sendLog(record)
|
|
89
89
|
|
|
90
|
-
|
|
90
|
+
if (result === 'success' || (typeof result === 'object' && 'uuid' in result)) {
|
|
91
|
+
console.log('✅ Log sent to API...', profile.name, profile.url)
|
|
92
|
+
console.log('Replay from fixture UUID:', fixtureUUID)
|
|
93
|
+
console.log('===============================================')
|
|
94
|
+
|
|
95
|
+
if (typeof result === 'object' && result && 'uuid' in result) {
|
|
96
|
+
return { success: true, logUuid: result.uuid }
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return { success: true }
|
|
100
|
+
} else {
|
|
101
|
+
console.error('❌ Failed to send log to Hive')
|
|
102
|
+
console.log('===============================================')
|
|
103
|
+
return { success: false }
|
|
104
|
+
}
|
|
91
105
|
} catch (e) {
|
|
92
106
|
const error = e as Error
|
|
93
|
-
console.error('Failed to send log to API:', error.message)
|
|
94
|
-
|
|
107
|
+
console.error('❌ Failed to send log to API:', error.message)
|
|
108
|
+
console.log('===============================================')
|
|
109
|
+
return { success: false }
|
|
95
110
|
}
|
|
96
111
|
}
|
|
97
112
|
}
|
|
@@ -107,7 +122,6 @@ export const replay = createTask({
|
|
|
107
122
|
// Load forge configuration
|
|
108
123
|
const forge: ForgeConf = await loadConf({})
|
|
109
124
|
const taskDescriptor = forge.tasks[descriptorName as keyof typeof forge.tasks]
|
|
110
|
-
const projectName = forge.project.name
|
|
111
125
|
|
|
112
126
|
if (taskDescriptor === undefined) {
|
|
113
127
|
throw new Error(`Task ${descriptorName} is not defined in forge.json`)
|
|
@@ -203,7 +217,7 @@ export const replay = createTask({
|
|
|
203
217
|
// Send the log to API if profile is available
|
|
204
218
|
if (profile) {
|
|
205
219
|
try {
|
|
206
|
-
await sendLogToAPI(profile,
|
|
220
|
+
await sendLogToAPI(profile, record, fixture.fixtureUUID)
|
|
207
221
|
} catch (e) {
|
|
208
222
|
console.error('Failed to send log to API:', e)
|
|
209
223
|
}
|
package/src/tasks/task/run.ts
CHANGED
|
@@ -10,7 +10,7 @@ import os from 'os'
|
|
|
10
10
|
import { createTask } from '@forgehive/task'
|
|
11
11
|
import { Schema } from '@forgehive/schema'
|
|
12
12
|
import { RecordTape } from '@forgehive/record-tape'
|
|
13
|
-
import {
|
|
13
|
+
import { createClientFromForgeConf, type ExecutionRecord } from '@forgehive/hive-sdk'
|
|
14
14
|
|
|
15
15
|
import { create as bundleCreate } from '../bundle/create'
|
|
16
16
|
import { load as bundleLoad } from '../bundle/load'
|
|
@@ -51,46 +51,37 @@ const boundaries = {
|
|
|
51
51
|
},
|
|
52
52
|
sendLogToAPI: async (
|
|
53
53
|
profile: Profile,
|
|
54
|
-
projectName: string,
|
|
55
54
|
record: ExecutionRecord,
|
|
56
|
-
taskUuid?: string
|
|
57
|
-
projectUuid?: string
|
|
55
|
+
taskUuid?: string
|
|
58
56
|
): Promise<{ success: boolean; logUuid?: string; taskUuid?: string; skipRemoteLog?: boolean }> => {
|
|
59
|
-
// Check if we have required
|
|
60
|
-
if (!
|
|
57
|
+
// Check if we have required UUID for the task
|
|
58
|
+
if (!taskUuid) {
|
|
61
59
|
console.log('===============================================')
|
|
62
|
-
console.log('⚠️ Remote logging skipped - missing
|
|
60
|
+
console.log('⚠️ Remote logging skipped - missing task UUID')
|
|
63
61
|
console.log('')
|
|
64
62
|
console.log('To enable remote logging with enhanced features:')
|
|
65
|
-
|
|
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
|
-
}
|
|
63
|
+
console.log('• Use "forge project:sync" to sync tasks and get UUIDs')
|
|
72
64
|
console.log('===============================================')
|
|
73
65
|
return { success: true, skipRemoteLog: true }
|
|
74
66
|
}
|
|
75
67
|
|
|
76
68
|
try {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
projectUuid,
|
|
69
|
+
// Use createClientFromForgeConf to automatically load forge.json with task UUIDs
|
|
70
|
+
const client = createClientFromForgeConf('./forge.json', {
|
|
80
71
|
apiKey: profile.apiKey,
|
|
81
72
|
apiSecret: profile.apiSecret,
|
|
82
73
|
host: profile.url,
|
|
83
74
|
metadata: {
|
|
84
75
|
environment: 'cli'
|
|
85
76
|
}
|
|
86
|
-
}
|
|
77
|
+
})
|
|
87
78
|
|
|
88
|
-
|
|
79
|
+
console.log('===============================================')
|
|
89
80
|
console.log('Sending execution log to Hive...')
|
|
90
|
-
const result = await client.
|
|
81
|
+
const result = await client.sendLog(record)
|
|
91
82
|
|
|
92
83
|
if (result === 'success' || (typeof result === 'object' && 'uuid' in result)) {
|
|
93
|
-
console.log('
|
|
84
|
+
console.log('')
|
|
94
85
|
console.log('✅ Log sent to Hive successfully')
|
|
95
86
|
console.log(` Profile: ${profile.name}`)
|
|
96
87
|
console.log(` Host: ${profile.url}`)
|
|
@@ -102,13 +93,17 @@ const boundaries = {
|
|
|
102
93
|
|
|
103
94
|
return { success: true, taskUuid }
|
|
104
95
|
} else {
|
|
96
|
+
console.log('')
|
|
105
97
|
console.error('❌ Failed to send log to Hive:', profile.url)
|
|
98
|
+
console.log('===============================================')
|
|
106
99
|
return { success: false }
|
|
107
100
|
}
|
|
108
101
|
} catch (e) {
|
|
102
|
+
console.log('===============================================')
|
|
109
103
|
console.error('❌ Failed to send log to Hive:', profile.url)
|
|
110
104
|
const error = e as Error
|
|
111
105
|
console.error('Error:', error.message)
|
|
106
|
+
console.log('===============================================')
|
|
112
107
|
return { success: false }
|
|
113
108
|
}
|
|
114
109
|
}
|
|
@@ -129,8 +124,6 @@ export const run = createTask({
|
|
|
129
124
|
// Load forge configuration
|
|
130
125
|
const forge: ForgeConf = await loadConf({})
|
|
131
126
|
const taskDescriptor = forge.tasks[descriptorName as keyof typeof forge.tasks]
|
|
132
|
-
const projectName = forge.project.name
|
|
133
|
-
const projectUuid = forge.project.uuid
|
|
134
127
|
const taskUuid = taskDescriptor?.uuid
|
|
135
128
|
|
|
136
129
|
if (taskDescriptor === undefined) {
|
|
@@ -204,7 +197,7 @@ export const run = createTask({
|
|
|
204
197
|
|
|
205
198
|
if (profile) {
|
|
206
199
|
try {
|
|
207
|
-
const logResult = await sendLogToAPI(profile,
|
|
200
|
+
const logResult = await sendLogToAPI(profile, logItem, taskUuid)
|
|
208
201
|
|
|
209
202
|
if (logResult.success && !logResult.skipRemoteLog && taskUuid) {
|
|
210
203
|
console.log(`🔗 View execution logs: ${profile.url}/tasks/${taskUuid}?tab=logs`)
|
package/src/tasks/types.ts
CHANGED
|
@@ -22,6 +22,7 @@ export interface ForgeConf {
|
|
|
22
22
|
project: {
|
|
23
23
|
name: string
|
|
24
24
|
uuid?: string
|
|
25
|
+
description?: string
|
|
25
26
|
}
|
|
26
27
|
paths: {
|
|
27
28
|
logs: string
|
|
@@ -34,6 +35,9 @@ export interface ForgeConf {
|
|
|
34
35
|
infra: Infra
|
|
35
36
|
tasks: Record<string, TaskDescriptor>
|
|
36
37
|
runners: Record<string, RunnerDescriptor>
|
|
38
|
+
build?: {
|
|
39
|
+
externalPackages?: string[]
|
|
40
|
+
}
|
|
37
41
|
}
|
|
38
42
|
|
|
39
43
|
export interface TaskName {
|