@garthub/gart-npm 0.1.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.
- package/LICENSE +188 -0
- package/README.md +395 -0
- package/package.json +41 -0
- package/src/archive.js +271 -0
- package/src/build-resources.js +150 -0
- package/src/cli.js +49 -0
- package/src/commands/build.js +19 -0
- package/src/commands/clean.js +147 -0
- package/src/commands/publish.js +15 -0
- package/src/commands/resolve.js +108 -0
- package/src/config.js +186 -0
- package/src/hash.js +47 -0
- package/src/http.js +146 -0
- package/src/managed-skills.js +365 -0
- package/src/maven.js +155 -0
- package/src/pom.js +64 -0
- package/src/publish-artifacts.js +275 -0
- package/src/resolve-artifacts.js +417 -0
- package/src/runtime.js +20 -0
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
const fs = require('node:fs');
|
|
2
|
+
const path = require('node:path');
|
|
3
|
+
const {
|
|
4
|
+
parseSkillCoordinates,
|
|
5
|
+
buildMavenRelativeArtifactPath,
|
|
6
|
+
buildMavenRelativePomPath,
|
|
7
|
+
buildMavenArtifactUrl,
|
|
8
|
+
buildMavenPomUrl,
|
|
9
|
+
buildRepositoryHeaders,
|
|
10
|
+
} = require('./maven');
|
|
11
|
+
const {buildSkillsArchive, readProjectInfo} = require('./build-resources');
|
|
12
|
+
const {computeFileSha256} = require('./hash');
|
|
13
|
+
const {uploadFile} = require('./http');
|
|
14
|
+
|
|
15
|
+
async function publishSkillsPackage(
|
|
16
|
+
config,
|
|
17
|
+
options = {},
|
|
18
|
+
) {
|
|
19
|
+
const repository = config.publishing.repository;
|
|
20
|
+
|
|
21
|
+
if (!repository) {
|
|
22
|
+
throw new Error('Publishing repository is not configured.');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (!['maven', 'mavenLocal'].includes(repository.type)) {
|
|
26
|
+
throw new Error(`Publishing repository type is not supported for skills: ${repository.type}.`);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const coordinates = resolvePublishingCoordinates(config);
|
|
30
|
+
const build = buildSkillsArchive(config, {archiver: options.archiver});
|
|
31
|
+
const pomContent = renderPom(coordinates, config.resolution.dependencies.exposedSkills);
|
|
32
|
+
const publishDirectory = path.join(config.buildDir, 'publish');
|
|
33
|
+
const publishManifestPath = path.join(config.buildDir, 'publish.json');
|
|
34
|
+
const localPomPath = path.join(publishDirectory, `${coordinates.artifactId}-${coordinates.version}.pom`);
|
|
35
|
+
const artifactRelativePath = buildMavenRelativeArtifactPath(coordinates);
|
|
36
|
+
const pomRelativePath = buildMavenRelativePomPath(coordinates);
|
|
37
|
+
|
|
38
|
+
fs.mkdirSync(publishDirectory, {recursive: true});
|
|
39
|
+
fs.writeFileSync(localPomPath, pomContent);
|
|
40
|
+
const pomSha256 = computeFileSha256(localPomPath);
|
|
41
|
+
|
|
42
|
+
let publication;
|
|
43
|
+
|
|
44
|
+
if (repository.type === 'mavenLocal') {
|
|
45
|
+
publication = publishToMavenLocal(
|
|
46
|
+
repository,
|
|
47
|
+
build.archivePath,
|
|
48
|
+
build.archiveSha256,
|
|
49
|
+
localPomPath,
|
|
50
|
+
pomSha256,
|
|
51
|
+
artifactRelativePath,
|
|
52
|
+
pomRelativePath,
|
|
53
|
+
);
|
|
54
|
+
} else {
|
|
55
|
+
publication = await publishToMavenRepository(
|
|
56
|
+
repository,
|
|
57
|
+
coordinates,
|
|
58
|
+
build.archivePath,
|
|
59
|
+
build.archiveSha256,
|
|
60
|
+
localPomPath,
|
|
61
|
+
pomSha256,
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const manifest = {
|
|
66
|
+
version: 1,
|
|
67
|
+
generatedAt: new Date().toISOString(),
|
|
68
|
+
coordinates: coordinates.coordinates,
|
|
69
|
+
repository: {
|
|
70
|
+
id: repository.id,
|
|
71
|
+
type: repository.type,
|
|
72
|
+
url: repository.url || null,
|
|
73
|
+
rootDir: repository.rootDir || null,
|
|
74
|
+
},
|
|
75
|
+
archivePath: build.archivePath,
|
|
76
|
+
archiveSha256: build.archiveSha256,
|
|
77
|
+
localPomPath,
|
|
78
|
+
pomSha256,
|
|
79
|
+
publishedArtifact: publication.publishedArtifact,
|
|
80
|
+
publishedPom: publication.publishedPom,
|
|
81
|
+
exposedSkills: config.resolution.dependencies.exposedSkills,
|
|
82
|
+
buildManifestPath: build.manifestPath,
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
fs.writeFileSync(publishManifestPath, JSON.stringify(manifest, null, 2));
|
|
86
|
+
|
|
87
|
+
return {
|
|
88
|
+
coordinates,
|
|
89
|
+
build,
|
|
90
|
+
localPomPath,
|
|
91
|
+
pomSha256,
|
|
92
|
+
publishManifestPath,
|
|
93
|
+
...publication,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function resolvePublishingCoordinates(config) {
|
|
98
|
+
if (config.publishing.coordinates) {
|
|
99
|
+
return parseSkillCoordinates(config.publishing.coordinates);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const projectInfo = readProjectInfo(config.cwd);
|
|
103
|
+
const groupId = config.publishing.groupId;
|
|
104
|
+
const artifactId = config.publishing.artifactId || projectInfo.artifactId;
|
|
105
|
+
const version = config.publishing.version || projectInfo.version;
|
|
106
|
+
|
|
107
|
+
if (!groupId || !artifactId || !version) {
|
|
108
|
+
throw new Error(
|
|
109
|
+
'Publishing coordinates are not fully configured. Define publishing.coordinates or publishing.groupId plus artifactId/version.',
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return parseSkillCoordinates(`${groupId}:${artifactId}:${version}`);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function renderPom(
|
|
117
|
+
coordinates,
|
|
118
|
+
exposedSkills,
|
|
119
|
+
) {
|
|
120
|
+
const dependencies = exposedSkills.map((dependencyCoordinates) => parseSkillCoordinates(dependencyCoordinates));
|
|
121
|
+
const dependencyXml = dependencies.length === 0
|
|
122
|
+
? ''
|
|
123
|
+
: [
|
|
124
|
+
' <dependencies>',
|
|
125
|
+
...dependencies.flatMap((dependency) => [
|
|
126
|
+
' <dependency>',
|
|
127
|
+
` <groupId>${escapeXml(dependency.groupId)}</groupId>`,
|
|
128
|
+
` <artifactId>${escapeXml(dependency.artifactId)}</artifactId>`,
|
|
129
|
+
` <version>${escapeXml(dependency.version)}</version>`,
|
|
130
|
+
' <classifier>skills</classifier>',
|
|
131
|
+
' <type>zip</type>',
|
|
132
|
+
' </dependency>',
|
|
133
|
+
]),
|
|
134
|
+
' </dependencies>',
|
|
135
|
+
].join('\n');
|
|
136
|
+
|
|
137
|
+
return [
|
|
138
|
+
'<?xml version="1.0" encoding="UTF-8"?>',
|
|
139
|
+
'<project>',
|
|
140
|
+
' <modelVersion>4.0.0</modelVersion>',
|
|
141
|
+
` <groupId>${escapeXml(coordinates.groupId)}</groupId>`,
|
|
142
|
+
` <artifactId>${escapeXml(coordinates.artifactId)}</artifactId>`,
|
|
143
|
+
` <version>${escapeXml(coordinates.version)}</version>`,
|
|
144
|
+
' <packaging>zip</packaging>',
|
|
145
|
+
dependencyXml,
|
|
146
|
+
'</project>',
|
|
147
|
+
].filter(Boolean).join('\n');
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function publishToMavenLocal(
|
|
151
|
+
repository,
|
|
152
|
+
archivePath,
|
|
153
|
+
archiveSha256,
|
|
154
|
+
localPomPath,
|
|
155
|
+
pomSha256,
|
|
156
|
+
artifactRelativePath,
|
|
157
|
+
pomRelativePath,
|
|
158
|
+
) {
|
|
159
|
+
const publishedArtifactPath = path.join(repository.rootDir, ...artifactRelativePath.split('/'));
|
|
160
|
+
const publishedPomPath = path.join(repository.rootDir, ...pomRelativePath.split('/'));
|
|
161
|
+
|
|
162
|
+
fs.mkdirSync(path.dirname(publishedArtifactPath), {recursive: true});
|
|
163
|
+
fs.mkdirSync(path.dirname(publishedPomPath), {recursive: true});
|
|
164
|
+
fs.copyFileSync(archivePath, publishedArtifactPath);
|
|
165
|
+
fs.copyFileSync(localPomPath, publishedPomPath);
|
|
166
|
+
verifyPublishedFileChecksum(publishedArtifactPath, archiveSha256, 'artifact');
|
|
167
|
+
verifyPublishedFileChecksum(publishedPomPath, pomSha256, 'pom');
|
|
168
|
+
|
|
169
|
+
return {
|
|
170
|
+
publishedArtifact: {
|
|
171
|
+
location: publishedArtifactPath,
|
|
172
|
+
relativePath: artifactRelativePath,
|
|
173
|
+
sha256: archiveSha256,
|
|
174
|
+
},
|
|
175
|
+
publishedPom: {
|
|
176
|
+
location: publishedPomPath,
|
|
177
|
+
relativePath: pomRelativePath,
|
|
178
|
+
sha256: pomSha256,
|
|
179
|
+
},
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
async function publishToMavenRepository(
|
|
184
|
+
repository,
|
|
185
|
+
coordinates,
|
|
186
|
+
archivePath,
|
|
187
|
+
archiveSha256,
|
|
188
|
+
localPomPath,
|
|
189
|
+
pomSha256,
|
|
190
|
+
) {
|
|
191
|
+
const headers = buildRepositoryHeaders(repository);
|
|
192
|
+
const artifactUrl = buildMavenArtifactUrl(repository, coordinates);
|
|
193
|
+
const pomUrl = buildMavenPomUrl(repository, coordinates);
|
|
194
|
+
|
|
195
|
+
const artifactUpload = await uploadFile(artifactUrl, archivePath, {
|
|
196
|
+
headers: {
|
|
197
|
+
'Content-Type': 'application/zip',
|
|
198
|
+
...headers,
|
|
199
|
+
},
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
if (!artifactUpload.ok) {
|
|
203
|
+
throw new Error(formatUploadFailure('artifact', artifactUrl, artifactUpload));
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const pomUpload = await uploadFile(pomUrl, localPomPath, {
|
|
207
|
+
headers: {
|
|
208
|
+
'Content-Type': 'application/xml',
|
|
209
|
+
...headers,
|
|
210
|
+
},
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
if (!pomUpload.ok) {
|
|
214
|
+
throw new Error(formatUploadFailure('pom', pomUrl, pomUpload));
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
return {
|
|
218
|
+
publishedArtifact: {
|
|
219
|
+
location: artifactUrl,
|
|
220
|
+
relativePath: buildMavenRelativeArtifactPath(coordinates),
|
|
221
|
+
statusCode: artifactUpload.statusCode,
|
|
222
|
+
sha256: archiveSha256,
|
|
223
|
+
},
|
|
224
|
+
publishedPom: {
|
|
225
|
+
location: pomUrl,
|
|
226
|
+
relativePath: buildMavenRelativePomPath(coordinates),
|
|
227
|
+
statusCode: pomUpload.statusCode,
|
|
228
|
+
sha256: pomSha256,
|
|
229
|
+
},
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function verifyPublishedFileChecksum(
|
|
234
|
+
filePath,
|
|
235
|
+
expectedSha256,
|
|
236
|
+
kind,
|
|
237
|
+
) {
|
|
238
|
+
if (!expectedSha256) {
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
const actualSha256 = computeFileSha256(filePath);
|
|
243
|
+
if (actualSha256 !== expectedSha256) {
|
|
244
|
+
throw new Error(
|
|
245
|
+
`Published ${kind} checksum mismatch at ${filePath}. Expected ${expectedSha256} but found ${actualSha256}.`,
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function formatUploadFailure(
|
|
251
|
+
phase,
|
|
252
|
+
location,
|
|
253
|
+
outcome,
|
|
254
|
+
) {
|
|
255
|
+
const body = outcome.body ? outcome.body.trim() : '';
|
|
256
|
+
const detail = body ? ` ${body}` : '';
|
|
257
|
+
return `Failed to publish ${phase} to ${location}: HTTP ${outcome.statusCode}.${detail}`.trim();
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function escapeXml(value) {
|
|
261
|
+
return String(value)
|
|
262
|
+
.replace(/&/g, '&')
|
|
263
|
+
.replace(/</g, '<')
|
|
264
|
+
.replace(/>/g, '>')
|
|
265
|
+
.replace(/"/g, '"')
|
|
266
|
+
.replace(/'/g, ''');
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
module.exports = {
|
|
270
|
+
publishSkillsPackage,
|
|
271
|
+
resolvePublishingCoordinates,
|
|
272
|
+
renderPom,
|
|
273
|
+
formatUploadFailure,
|
|
274
|
+
verifyPublishedFileChecksum,
|
|
275
|
+
};
|
|
@@ -0,0 +1,417 @@
|
|
|
1
|
+
const fs = require('node:fs');
|
|
2
|
+
const path = require('node:path');
|
|
3
|
+
const {
|
|
4
|
+
parseSkillCoordinates,
|
|
5
|
+
buildMavenRelativeArtifactPath,
|
|
6
|
+
buildMavenRelativePomPath,
|
|
7
|
+
buildMavenArtifactUrl,
|
|
8
|
+
buildMavenPomUrl,
|
|
9
|
+
buildRepositoryHeaders,
|
|
10
|
+
} = require('./maven');
|
|
11
|
+
const {downloadToFile} = require('./http');
|
|
12
|
+
const {parseTransitiveSkillDependenciesFromPom} = require('./pom');
|
|
13
|
+
|
|
14
|
+
function collectDependencyEntries(config) {
|
|
15
|
+
return [
|
|
16
|
+
...config.resolution.dependencies.skills.map((coordinates) => ({
|
|
17
|
+
kind: 'skill',
|
|
18
|
+
coordinates,
|
|
19
|
+
})),
|
|
20
|
+
...config.resolution.dependencies.exposedSkills.map((coordinates) => ({
|
|
21
|
+
kind: 'exposedSkill',
|
|
22
|
+
coordinates,
|
|
23
|
+
})),
|
|
24
|
+
];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async function resolveSkillArtifacts(config) {
|
|
28
|
+
const directDependencies = collectDependencyEntries(config);
|
|
29
|
+
const directCoordinates = new Set(directDependencies.map((dependency) => dependency.coordinates));
|
|
30
|
+
const resolvedArtifacts = [];
|
|
31
|
+
const unresolved = [];
|
|
32
|
+
const transitiveDependencies = [];
|
|
33
|
+
const queue = [...directDependencies];
|
|
34
|
+
const visited = new Set();
|
|
35
|
+
|
|
36
|
+
while (queue.length > 0) {
|
|
37
|
+
const dependency = queue.shift();
|
|
38
|
+
|
|
39
|
+
if (visited.has(dependency.coordinates)) {
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
visited.add(dependency.coordinates);
|
|
44
|
+
const outcome = await resolveSingleDependency(dependency, config);
|
|
45
|
+
|
|
46
|
+
if (outcome.resolvedArtifact) {
|
|
47
|
+
resolvedArtifacts.push(outcome.resolvedArtifact);
|
|
48
|
+
|
|
49
|
+
for (const transitiveDependency of outcome.resolvedArtifact.transitiveDependencies) {
|
|
50
|
+
const nextDependency = {
|
|
51
|
+
kind: 'transitiveSkill',
|
|
52
|
+
coordinates: transitiveDependency.coordinates,
|
|
53
|
+
parentCoordinates: dependency.coordinates,
|
|
54
|
+
depth: (dependency.depth || 0) + 1,
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
transitiveDependencies.push(nextDependency);
|
|
58
|
+
queue.push(nextDependency);
|
|
59
|
+
}
|
|
60
|
+
} else {
|
|
61
|
+
unresolved.push(outcome.unresolved);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
dependencies: directDependencies,
|
|
67
|
+
directDependencies,
|
|
68
|
+
transitiveDependencies: deduplicateDependencies(transitiveDependencies)
|
|
69
|
+
.filter((dependency) => !directCoordinates.has(dependency.coordinates)),
|
|
70
|
+
resolvedArtifacts,
|
|
71
|
+
unresolved,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
async function resolveSingleDependency(
|
|
76
|
+
dependency,
|
|
77
|
+
config,
|
|
78
|
+
) {
|
|
79
|
+
const repositories = config.resolution.repositories;
|
|
80
|
+
const parsedCoordinates = parseSkillCoordinates(dependency.coordinates);
|
|
81
|
+
const attempts = [];
|
|
82
|
+
|
|
83
|
+
if (repositories.length === 0) {
|
|
84
|
+
return {
|
|
85
|
+
unresolved: {
|
|
86
|
+
dependency,
|
|
87
|
+
parsedCoordinates,
|
|
88
|
+
attempts,
|
|
89
|
+
reason: 'No repositories configured for skill resolution.',
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
for (const repository of repositories) {
|
|
95
|
+
if (repository.type === 'mavenLocal') {
|
|
96
|
+
const artifactPath = path.join(repository.rootDir, ...buildMavenRelativeArtifactPath(parsedCoordinates).split('/'));
|
|
97
|
+
const found = fs.existsSync(artifactPath);
|
|
98
|
+
|
|
99
|
+
attempts.push({
|
|
100
|
+
repositoryId: repository.id,
|
|
101
|
+
repositoryType: repository.type,
|
|
102
|
+
phase: 'artifact',
|
|
103
|
+
location: artifactPath,
|
|
104
|
+
found,
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
if (found) {
|
|
108
|
+
const pomDescriptor = resolvePomDescriptorForArtifact(
|
|
109
|
+
config,
|
|
110
|
+
repository,
|
|
111
|
+
parsedCoordinates,
|
|
112
|
+
attempts,
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
if (!pomDescriptor.ok) {
|
|
116
|
+
return {
|
|
117
|
+
unresolved: {
|
|
118
|
+
dependency,
|
|
119
|
+
parsedCoordinates,
|
|
120
|
+
attempts,
|
|
121
|
+
reason: buildUnresolvedReason(attempts),
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return {
|
|
127
|
+
resolvedArtifact: {
|
|
128
|
+
dependency,
|
|
129
|
+
parsedCoordinates,
|
|
130
|
+
repositoryId: repository.id,
|
|
131
|
+
repositoryType: repository.type,
|
|
132
|
+
relativeArtifactPath: buildMavenRelativeArtifactPath(parsedCoordinates),
|
|
133
|
+
artifactPath,
|
|
134
|
+
source: 'local',
|
|
135
|
+
pomPath: pomDescriptor.pomPath,
|
|
136
|
+
pomSource: pomDescriptor.source,
|
|
137
|
+
transitiveDependencies: pomDescriptor.dependencies,
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (repository.type === 'maven') {
|
|
146
|
+
const artifactUrl = buildMavenArtifactUrl(repository, parsedCoordinates);
|
|
147
|
+
const cachePath = path.join(config.cacheDir, repository.id, ...buildMavenRelativeArtifactPath(parsedCoordinates).split('/'));
|
|
148
|
+
|
|
149
|
+
if (fs.existsSync(cachePath)) {
|
|
150
|
+
attempts.push({
|
|
151
|
+
repositoryId: repository.id,
|
|
152
|
+
repositoryType: repository.type,
|
|
153
|
+
phase: 'artifact',
|
|
154
|
+
location: artifactUrl,
|
|
155
|
+
found: true,
|
|
156
|
+
source: 'cache',
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
const pomDescriptor = await resolveRemotePomDescriptorForArtifact(
|
|
160
|
+
config,
|
|
161
|
+
repository,
|
|
162
|
+
parsedCoordinates,
|
|
163
|
+
attempts,
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
if (!pomDescriptor.ok) {
|
|
167
|
+
return {
|
|
168
|
+
unresolved: {
|
|
169
|
+
dependency,
|
|
170
|
+
parsedCoordinates,
|
|
171
|
+
attempts,
|
|
172
|
+
reason: buildUnresolvedReason(attempts),
|
|
173
|
+
},
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return {
|
|
178
|
+
resolvedArtifact: {
|
|
179
|
+
dependency,
|
|
180
|
+
parsedCoordinates,
|
|
181
|
+
repositoryId: repository.id,
|
|
182
|
+
repositoryType: repository.type,
|
|
183
|
+
relativeArtifactPath: buildMavenRelativeArtifactPath(parsedCoordinates),
|
|
184
|
+
artifactPath: cachePath,
|
|
185
|
+
source: 'cache',
|
|
186
|
+
sourceUrl: artifactUrl,
|
|
187
|
+
pomPath: pomDescriptor.pomPath,
|
|
188
|
+
pomSource: pomDescriptor.source,
|
|
189
|
+
transitiveDependencies: pomDescriptor.dependencies,
|
|
190
|
+
},
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
try {
|
|
195
|
+
const download = await downloadToFile(artifactUrl, cachePath, {
|
|
196
|
+
headers: buildRepositoryHeaders(repository),
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
attempts.push({
|
|
200
|
+
repositoryId: repository.id,
|
|
201
|
+
repositoryType: repository.type,
|
|
202
|
+
phase: 'artifact',
|
|
203
|
+
location: artifactUrl,
|
|
204
|
+
found: download.ok,
|
|
205
|
+
statusCode: download.statusCode,
|
|
206
|
+
source: download.ok ? 'remote' : 'remote-miss',
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
if (download.ok) {
|
|
210
|
+
const pomDescriptor = await resolveRemotePomDescriptorForArtifact(
|
|
211
|
+
config,
|
|
212
|
+
repository,
|
|
213
|
+
parsedCoordinates,
|
|
214
|
+
attempts,
|
|
215
|
+
);
|
|
216
|
+
|
|
217
|
+
if (!pomDescriptor.ok) {
|
|
218
|
+
return {
|
|
219
|
+
unresolved: {
|
|
220
|
+
dependency,
|
|
221
|
+
parsedCoordinates,
|
|
222
|
+
attempts,
|
|
223
|
+
reason: buildUnresolvedReason(attempts),
|
|
224
|
+
},
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return {
|
|
229
|
+
resolvedArtifact: {
|
|
230
|
+
dependency,
|
|
231
|
+
parsedCoordinates,
|
|
232
|
+
repositoryId: repository.id,
|
|
233
|
+
repositoryType: repository.type,
|
|
234
|
+
relativeArtifactPath: buildMavenRelativeArtifactPath(parsedCoordinates),
|
|
235
|
+
artifactPath: cachePath,
|
|
236
|
+
source: 'remote',
|
|
237
|
+
sourceUrl: artifactUrl,
|
|
238
|
+
pomPath: pomDescriptor.pomPath,
|
|
239
|
+
pomSource: pomDescriptor.source,
|
|
240
|
+
transitiveDependencies: pomDescriptor.dependencies,
|
|
241
|
+
},
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
} catch (error) {
|
|
245
|
+
attempts.push({
|
|
246
|
+
repositoryId: repository.id,
|
|
247
|
+
repositoryType: repository.type,
|
|
248
|
+
phase: 'artifact',
|
|
249
|
+
location: artifactUrl,
|
|
250
|
+
found: false,
|
|
251
|
+
error: error.message,
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
return {
|
|
258
|
+
unresolved: {
|
|
259
|
+
dependency,
|
|
260
|
+
parsedCoordinates,
|
|
261
|
+
attempts,
|
|
262
|
+
reason: buildUnresolvedReason(attempts),
|
|
263
|
+
},
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
function buildUnresolvedReason(attempts) {
|
|
268
|
+
const remoteAttemptsWithStatus = attempts.filter((attempt) => (
|
|
269
|
+
attempt.repositoryType === 'maven' &&
|
|
270
|
+
typeof attempt.statusCode === 'number' &&
|
|
271
|
+
attempt.found === false
|
|
272
|
+
));
|
|
273
|
+
|
|
274
|
+
if (remoteAttemptsWithStatus.length > 0) {
|
|
275
|
+
const statuses = [...new Set(remoteAttemptsWithStatus.map((attempt) => attempt.statusCode))];
|
|
276
|
+
|
|
277
|
+
if (statuses.length === 1) {
|
|
278
|
+
return `Skill artifact request failed with HTTP ${statuses[0]}.`;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
return `Skill artifact requests failed with HTTP statuses: ${statuses.join(', ')}.`;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const remoteAttemptsWithErrors = attempts.filter((attempt) => (
|
|
285
|
+
attempt.repositoryType === 'maven' &&
|
|
286
|
+
attempt.error
|
|
287
|
+
));
|
|
288
|
+
|
|
289
|
+
if (remoteAttemptsWithErrors.length > 0) {
|
|
290
|
+
return `Skill artifact request failed: ${remoteAttemptsWithErrors[0].error}`;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
return 'Skill artifact was not found in the configured repositories.';
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
function resolvePomDescriptorForArtifact(
|
|
297
|
+
config,
|
|
298
|
+
repository,
|
|
299
|
+
parsedCoordinates,
|
|
300
|
+
attempts,
|
|
301
|
+
) {
|
|
302
|
+
const pomPath = path.join(repository.rootDir, ...buildMavenRelativePomPath(parsedCoordinates).split('/'));
|
|
303
|
+
const found = fs.existsSync(pomPath);
|
|
304
|
+
|
|
305
|
+
attempts.push({
|
|
306
|
+
repositoryId: repository.id,
|
|
307
|
+
repositoryType: repository.type,
|
|
308
|
+
phase: 'pom',
|
|
309
|
+
location: pomPath,
|
|
310
|
+
found,
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
if (!found) {
|
|
314
|
+
return {ok: false};
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
return {
|
|
318
|
+
ok: true,
|
|
319
|
+
pomPath,
|
|
320
|
+
source: 'local',
|
|
321
|
+
dependencies: parsePomDependencies(pomPath),
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
async function resolveRemotePomDescriptorForArtifact(
|
|
326
|
+
config,
|
|
327
|
+
repository,
|
|
328
|
+
parsedCoordinates,
|
|
329
|
+
attempts,
|
|
330
|
+
) {
|
|
331
|
+
const pomUrl = buildMavenPomUrl(repository, parsedCoordinates);
|
|
332
|
+
const pomCachePath = path.join(config.cacheDir, repository.id, ...buildMavenRelativePomPath(parsedCoordinates).split('/'));
|
|
333
|
+
|
|
334
|
+
if (fs.existsSync(pomCachePath)) {
|
|
335
|
+
attempts.push({
|
|
336
|
+
repositoryId: repository.id,
|
|
337
|
+
repositoryType: repository.type,
|
|
338
|
+
phase: 'pom',
|
|
339
|
+
location: pomUrl,
|
|
340
|
+
found: true,
|
|
341
|
+
source: 'cache',
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
return {
|
|
345
|
+
ok: true,
|
|
346
|
+
pomPath: pomCachePath,
|
|
347
|
+
source: 'cache',
|
|
348
|
+
dependencies: parsePomDependencies(pomCachePath),
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
try {
|
|
353
|
+
const download = await downloadToFile(pomUrl, pomCachePath, {
|
|
354
|
+
headers: buildRepositoryHeaders(repository),
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
attempts.push({
|
|
358
|
+
repositoryId: repository.id,
|
|
359
|
+
repositoryType: repository.type,
|
|
360
|
+
phase: 'pom',
|
|
361
|
+
location: pomUrl,
|
|
362
|
+
found: download.ok,
|
|
363
|
+
statusCode: download.statusCode,
|
|
364
|
+
source: download.ok ? 'remote' : 'remote-miss',
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
if (!download.ok) {
|
|
368
|
+
return {ok: false};
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
return {
|
|
372
|
+
ok: true,
|
|
373
|
+
pomPath: pomCachePath,
|
|
374
|
+
source: 'remote',
|
|
375
|
+
dependencies: parsePomDependencies(pomCachePath),
|
|
376
|
+
};
|
|
377
|
+
} catch (error) {
|
|
378
|
+
attempts.push({
|
|
379
|
+
repositoryId: repository.id,
|
|
380
|
+
repositoryType: repository.type,
|
|
381
|
+
phase: 'pom',
|
|
382
|
+
location: pomUrl,
|
|
383
|
+
found: false,
|
|
384
|
+
error: error.message,
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
return {ok: false};
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
function parsePomDependencies(pomPath) {
|
|
392
|
+
return parseTransitiveSkillDependenciesFromPom(fs.readFileSync(pomPath, 'utf8'));
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
function deduplicateDependencies(dependencies) {
|
|
396
|
+
const seen = new Set();
|
|
397
|
+
const uniqueDependencies = [];
|
|
398
|
+
|
|
399
|
+
for (const dependency of dependencies) {
|
|
400
|
+
if (seen.has(dependency.coordinates)) {
|
|
401
|
+
continue;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
seen.add(dependency.coordinates);
|
|
405
|
+
uniqueDependencies.push(dependency);
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
return uniqueDependencies;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
module.exports = {
|
|
412
|
+
collectDependencyEntries,
|
|
413
|
+
resolveSkillArtifacts,
|
|
414
|
+
buildRepositoryHeaders,
|
|
415
|
+
buildUnresolvedReason,
|
|
416
|
+
deduplicateDependencies,
|
|
417
|
+
};
|
package/src/runtime.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
function resolveExecutionCwd(
|
|
2
|
+
commandName,
|
|
3
|
+
args,
|
|
4
|
+
environment,
|
|
5
|
+
defaultCwd,
|
|
6
|
+
) {
|
|
7
|
+
if (
|
|
8
|
+
commandName === 'resolve' &&
|
|
9
|
+
args.includes('--postinstall') &&
|
|
10
|
+
environment.INIT_CWD
|
|
11
|
+
) {
|
|
12
|
+
return environment.INIT_CWD;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return defaultCwd;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
module.exports = {
|
|
19
|
+
resolveExecutionCwd,
|
|
20
|
+
};
|