@argos-ci/core 4.4.0 → 4.5.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/dist/index.d.ts +3 -0
- package/dist/index.js +82 -48
- package/package.json +6 -4
package/dist/index.d.ts
CHANGED
|
@@ -145,6 +145,7 @@ interface components {
|
|
|
145
145
|
key: string;
|
|
146
146
|
name: string;
|
|
147
147
|
baseName?: string | null;
|
|
148
|
+
parentName?: string | null;
|
|
148
149
|
metadata?: {
|
|
149
150
|
/**
|
|
150
151
|
* @description Ignored. Can be set to get completions, validations and documentation in some editors.
|
|
@@ -227,6 +228,8 @@ interface components {
|
|
|
227
228
|
} | null;
|
|
228
229
|
pwTraceKey?: string | null;
|
|
229
230
|
threshold?: number | null;
|
|
231
|
+
/** @default image/png */
|
|
232
|
+
contentType: string;
|
|
230
233
|
};
|
|
231
234
|
/** @description Build metadata */
|
|
232
235
|
BuildMetadata: {
|
package/dist/index.js
CHANGED
|
@@ -66,7 +66,7 @@ function gitMergeBase(input) {
|
|
|
66
66
|
}
|
|
67
67
|
function gitFetch(input) {
|
|
68
68
|
execSync(
|
|
69
|
-
`git fetch --update-head-ok --depth ${input.depth} origin ${input.ref}:${input.
|
|
69
|
+
`git fetch --force --update-head-ok --depth ${input.depth} origin ${input.ref}:${input.target}`
|
|
70
70
|
);
|
|
71
71
|
}
|
|
72
72
|
function checkIsExecError(error) {
|
|
@@ -74,18 +74,23 @@ function checkIsExecError(error) {
|
|
|
74
74
|
}
|
|
75
75
|
function getMergeBaseCommitSha(input) {
|
|
76
76
|
let depth = 200;
|
|
77
|
+
const argosBaseRef = `argos/${input.base}`;
|
|
78
|
+
const argosHeadRef = `argos/${input.head}`;
|
|
77
79
|
while (depth < 1e3) {
|
|
78
|
-
gitFetch({ ref: input.head, depth });
|
|
79
|
-
gitFetch({ ref: input.base, depth });
|
|
80
|
-
const mergeBase = gitMergeBase(
|
|
80
|
+
gitFetch({ ref: input.head, depth, target: argosHeadRef });
|
|
81
|
+
gitFetch({ ref: input.base, depth, target: argosBaseRef });
|
|
82
|
+
const mergeBase = gitMergeBase({
|
|
83
|
+
base: argosBaseRef,
|
|
84
|
+
head: argosHeadRef
|
|
85
|
+
});
|
|
81
86
|
if (mergeBase) {
|
|
82
87
|
return mergeBase;
|
|
83
88
|
}
|
|
84
89
|
depth += 200;
|
|
85
90
|
}
|
|
86
91
|
if (isDebugEnabled) {
|
|
87
|
-
const headShas = listShas(
|
|
88
|
-
const baseShas = listShas(
|
|
92
|
+
const headShas = listShas(argosHeadRef);
|
|
93
|
+
const baseShas = listShas(argosBaseRef);
|
|
89
94
|
debug(
|
|
90
95
|
`No merge base found for ${input.head} and ${input.base} with depth ${depth}`
|
|
91
96
|
);
|
|
@@ -106,7 +111,13 @@ function listShas(path, maxCount) {
|
|
|
106
111
|
}
|
|
107
112
|
function listParentCommits(input) {
|
|
108
113
|
const limit = 200;
|
|
109
|
-
|
|
114
|
+
try {
|
|
115
|
+
execSync(`git fetch --depth=${limit} origin ${input.sha}`);
|
|
116
|
+
} catch (error) {
|
|
117
|
+
if (error instanceof Error && error.message.includes("not our ref")) {
|
|
118
|
+
return [];
|
|
119
|
+
}
|
|
120
|
+
}
|
|
110
121
|
return listShas(input.sha, limit);
|
|
111
122
|
}
|
|
112
123
|
|
|
@@ -929,11 +940,11 @@ async function finalize(params) {
|
|
|
929
940
|
import { createClient as createClient2, throwAPIError as throwAPIError2 } from "@argos-ci/api-client";
|
|
930
941
|
|
|
931
942
|
// src/discovery.ts
|
|
932
|
-
import { resolve } from "path";
|
|
943
|
+
import { extname, resolve } from "path";
|
|
933
944
|
import glob from "fast-glob";
|
|
934
|
-
|
|
945
|
+
async function discoverSnapshots(patterns, { root = process.cwd(), ignore } = {}) {
|
|
935
946
|
debug(
|
|
936
|
-
`Discovering
|
|
947
|
+
`Discovering snapshots with patterns: ${Array.isArray(patterns) ? patterns.join(", ") : patterns} in ${root}`
|
|
937
948
|
);
|
|
938
949
|
const matches = await glob(patterns, { onlyFiles: true, ignore, cwd: root });
|
|
939
950
|
return matches.map((match) => {
|
|
@@ -944,7 +955,11 @@ var discoverScreenshots = async (patterns, { root = process.cwd(), ignore } = {}
|
|
|
944
955
|
path
|
|
945
956
|
};
|
|
946
957
|
});
|
|
947
|
-
}
|
|
958
|
+
}
|
|
959
|
+
function checkIsValidImageFile(filename) {
|
|
960
|
+
const lowerFilename = extname(filename).toLowerCase();
|
|
961
|
+
return lowerFilename === ".png" || lowerFilename === ".jpg" || lowerFilename === ".jpeg";
|
|
962
|
+
}
|
|
948
963
|
|
|
949
964
|
// src/optimize.ts
|
|
950
965
|
import { promisify } from "util";
|
|
@@ -954,7 +969,10 @@ import tmp from "tmp";
|
|
|
954
969
|
var tmpFile = promisify(tmp.file);
|
|
955
970
|
var MAX_PIXELS = 8e7;
|
|
956
971
|
var DEFAULT_MAX_WIDTH = 2048;
|
|
957
|
-
|
|
972
|
+
async function optimizeScreenshot(filepath) {
|
|
973
|
+
if (!checkIsValidImageFile(filepath)) {
|
|
974
|
+
return filepath;
|
|
975
|
+
}
|
|
958
976
|
try {
|
|
959
977
|
const [resultFilePath, metadata] = await Promise.all([
|
|
960
978
|
tmpFile(),
|
|
@@ -1010,7 +1028,7 @@ var optimizeScreenshot = async (filepath) => {
|
|
|
1010
1028
|
cause: error
|
|
1011
1029
|
});
|
|
1012
1030
|
}
|
|
1013
|
-
}
|
|
1031
|
+
}
|
|
1014
1032
|
|
|
1015
1033
|
// src/hashing.ts
|
|
1016
1034
|
import { createReadStream } from "fs";
|
|
@@ -1074,6 +1092,16 @@ async function getArgosCoreSDKIdentifier() {
|
|
|
1074
1092
|
return `@argos-ci/core@${version}`;
|
|
1075
1093
|
}
|
|
1076
1094
|
|
|
1095
|
+
// src/mime-type.ts
|
|
1096
|
+
import mime from "mime-types";
|
|
1097
|
+
function getSnapshotMimeType(filepath) {
|
|
1098
|
+
const type = mime.lookup(filepath);
|
|
1099
|
+
if (!type) {
|
|
1100
|
+
throw new Error(`Unable to determine snapshot file type for: ${filepath}`);
|
|
1101
|
+
}
|
|
1102
|
+
return type;
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1077
1105
|
// src/upload.ts
|
|
1078
1106
|
var CHUNK_SIZE = 10;
|
|
1079
1107
|
async function upload(params) {
|
|
@@ -1116,19 +1144,20 @@ async function upload(params) {
|
|
|
1116
1144
|
return { build: createBuildResponse2.data.build, screenshots: [] };
|
|
1117
1145
|
}
|
|
1118
1146
|
const previewUrlFormatter = params.previewUrl ?? (config.previewBaseUrl ? { baseUrl: config.previewBaseUrl } : void 0);
|
|
1119
|
-
const
|
|
1120
|
-
debug("Using config and files", config,
|
|
1121
|
-
const
|
|
1147
|
+
const globs = params.files ?? ["**/*.{png,jpg,jpeg}"];
|
|
1148
|
+
debug("Using config and files", config, globs);
|
|
1149
|
+
const files = await discoverSnapshots(globs, {
|
|
1122
1150
|
root: params.root,
|
|
1123
1151
|
ignore: params.ignore
|
|
1124
1152
|
});
|
|
1125
|
-
debug("Found
|
|
1126
|
-
const
|
|
1127
|
-
|
|
1153
|
+
debug("Found snapshots", files);
|
|
1154
|
+
const snapshots = await Promise.all(
|
|
1155
|
+
files.map(async (snapshot) => {
|
|
1156
|
+
const contentType = getSnapshotMimeType(snapshot.path);
|
|
1128
1157
|
const [metadata, pwTracePath, optimizedPath] = await Promise.all([
|
|
1129
|
-
readMetadata(
|
|
1130
|
-
getPlaywrightTracePath(
|
|
1131
|
-
optimizeScreenshot(
|
|
1158
|
+
readMetadata(snapshot.path),
|
|
1159
|
+
getPlaywrightTracePath(snapshot.path),
|
|
1160
|
+
contentType.startsWith("image/") ? optimizeScreenshot(snapshot.path) : snapshot.path
|
|
1132
1161
|
]);
|
|
1133
1162
|
const [hash, pwTraceHash] = await Promise.all([
|
|
1134
1163
|
hashFile(optimizedPath),
|
|
@@ -1136,6 +1165,7 @@ async function upload(params) {
|
|
|
1136
1165
|
]);
|
|
1137
1166
|
const threshold = metadata?.transient?.threshold ?? null;
|
|
1138
1167
|
const baseName = metadata?.transient?.baseName ?? null;
|
|
1168
|
+
const parentName = metadata?.transient?.parentName ?? null;
|
|
1139
1169
|
if (metadata) {
|
|
1140
1170
|
delete metadata.transient;
|
|
1141
1171
|
if (metadata.url && previewUrlFormatter) {
|
|
@@ -1146,13 +1176,15 @@ async function upload(params) {
|
|
|
1146
1176
|
}
|
|
1147
1177
|
}
|
|
1148
1178
|
return {
|
|
1149
|
-
...
|
|
1179
|
+
...snapshot,
|
|
1150
1180
|
hash,
|
|
1151
1181
|
optimizedPath,
|
|
1152
1182
|
metadata,
|
|
1153
1183
|
threshold,
|
|
1154
1184
|
baseName,
|
|
1155
|
-
|
|
1185
|
+
parentName,
|
|
1186
|
+
pwTrace: pwTracePath && pwTraceHash ? { path: pwTracePath, hash: pwTraceHash } : null,
|
|
1187
|
+
contentType
|
|
1156
1188
|
};
|
|
1157
1189
|
})
|
|
1158
1190
|
);
|
|
@@ -1196,15 +1228,15 @@ async function upload(params) {
|
|
|
1196
1228
|
return null;
|
|
1197
1229
|
})();
|
|
1198
1230
|
debug("Creating build");
|
|
1199
|
-
const [pwTraceKeys,
|
|
1200
|
-
([pwTraceKeys2,
|
|
1201
|
-
if (
|
|
1202
|
-
pwTraceKeys2.push(
|
|
1231
|
+
const [pwTraceKeys, snapshotKeys] = snapshots.reduce(
|
|
1232
|
+
([pwTraceKeys2, snapshotKeys2], snapshot) => {
|
|
1233
|
+
if (snapshot.pwTrace && !pwTraceKeys2.includes(snapshot.pwTrace.hash)) {
|
|
1234
|
+
pwTraceKeys2.push(snapshot.pwTrace.hash);
|
|
1203
1235
|
}
|
|
1204
|
-
if (!
|
|
1205
|
-
|
|
1236
|
+
if (!snapshotKeys2.includes(snapshot.hash)) {
|
|
1237
|
+
snapshotKeys2.push(snapshot.hash);
|
|
1206
1238
|
}
|
|
1207
|
-
return [pwTraceKeys2,
|
|
1239
|
+
return [pwTraceKeys2, snapshotKeys2];
|
|
1208
1240
|
},
|
|
1209
1241
|
[[], []]
|
|
1210
1242
|
);
|
|
@@ -1216,7 +1248,7 @@ async function upload(params) {
|
|
|
1216
1248
|
mode: config.mode,
|
|
1217
1249
|
parallel: config.parallel,
|
|
1218
1250
|
parallelNonce: config.parallelNonce,
|
|
1219
|
-
screenshotKeys,
|
|
1251
|
+
screenshotKeys: snapshotKeys,
|
|
1220
1252
|
pwTraceKeys,
|
|
1221
1253
|
prNumber: config.prNumber,
|
|
1222
1254
|
prHeadCommit: config.prHeadCommit,
|
|
@@ -1236,26 +1268,26 @@ async function upload(params) {
|
|
|
1236
1268
|
debug("Got uploads url", result);
|
|
1237
1269
|
const uploadFiles = [
|
|
1238
1270
|
...result.screenshots.map(({ key, putUrl }) => {
|
|
1239
|
-
const
|
|
1240
|
-
if (!
|
|
1241
|
-
throw new Error(`Invariant:
|
|
1271
|
+
const snapshot = snapshots.find((s) => s.hash === key);
|
|
1272
|
+
if (!snapshot) {
|
|
1273
|
+
throw new Error(`Invariant: snapshot with hash ${key} not found`);
|
|
1242
1274
|
}
|
|
1243
1275
|
return {
|
|
1244
1276
|
url: putUrl,
|
|
1245
|
-
path:
|
|
1246
|
-
contentType:
|
|
1277
|
+
path: snapshot.optimizedPath,
|
|
1278
|
+
contentType: snapshot.contentType
|
|
1247
1279
|
};
|
|
1248
1280
|
}),
|
|
1249
1281
|
...result.pwTraces?.map(({ key, putUrl }) => {
|
|
1250
|
-
const
|
|
1282
|
+
const snapshot = snapshots.find(
|
|
1251
1283
|
(s) => s.pwTrace && s.pwTrace.hash === key
|
|
1252
1284
|
);
|
|
1253
|
-
if (!
|
|
1285
|
+
if (!snapshot || !snapshot.pwTrace) {
|
|
1254
1286
|
throw new Error(`Invariant: trace with ${key} not found`);
|
|
1255
1287
|
}
|
|
1256
1288
|
return {
|
|
1257
1289
|
url: putUrl,
|
|
1258
|
-
path:
|
|
1290
|
+
path: snapshot.pwTrace.path,
|
|
1259
1291
|
contentType: "application/json"
|
|
1260
1292
|
};
|
|
1261
1293
|
}) ?? []
|
|
@@ -1269,13 +1301,15 @@ async function upload(params) {
|
|
|
1269
1301
|
}
|
|
1270
1302
|
},
|
|
1271
1303
|
body: {
|
|
1272
|
-
screenshots:
|
|
1273
|
-
key:
|
|
1274
|
-
name:
|
|
1275
|
-
metadata:
|
|
1276
|
-
pwTraceKey:
|
|
1277
|
-
threshold:
|
|
1278
|
-
baseName:
|
|
1304
|
+
screenshots: snapshots.map((snapshot) => ({
|
|
1305
|
+
key: snapshot.hash,
|
|
1306
|
+
name: snapshot.name,
|
|
1307
|
+
metadata: snapshot.metadata,
|
|
1308
|
+
pwTraceKey: snapshot.pwTrace?.hash ?? null,
|
|
1309
|
+
threshold: snapshot.threshold ?? config?.threshold ?? null,
|
|
1310
|
+
baseName: snapshot.baseName,
|
|
1311
|
+
parentName: snapshot.parentName,
|
|
1312
|
+
contentType: snapshot.contentType
|
|
1279
1313
|
})),
|
|
1280
1314
|
parallel: config.parallel,
|
|
1281
1315
|
parallelTotal: config.parallelTotal,
|
|
@@ -1286,7 +1320,7 @@ async function upload(params) {
|
|
|
1286
1320
|
if (uploadBuildResponse.error) {
|
|
1287
1321
|
throwAPIError2(uploadBuildResponse.error);
|
|
1288
1322
|
}
|
|
1289
|
-
return { build: uploadBuildResponse.data.build, screenshots };
|
|
1323
|
+
return { build: uploadBuildResponse.data.build, screenshots: snapshots };
|
|
1290
1324
|
}
|
|
1291
1325
|
async function uploadFilesToS3(files) {
|
|
1292
1326
|
debug(`Split files in chunks of ${CHUNK_SIZE}`);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@argos-ci/core",
|
|
3
3
|
"description": "Node.js SDK for visual testing with Argos.",
|
|
4
|
-
"version": "4.
|
|
4
|
+
"version": "4.5.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
7
7
|
"exports": {
|
|
@@ -40,11 +40,12 @@
|
|
|
40
40
|
"access": "public"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@argos-ci/api-client": "0.
|
|
44
|
-
"@argos-ci/util": "3.
|
|
43
|
+
"@argos-ci/api-client": "0.14.0",
|
|
44
|
+
"@argos-ci/util": "3.2.0",
|
|
45
45
|
"convict": "^6.2.4",
|
|
46
46
|
"debug": "^4.4.3",
|
|
47
47
|
"fast-glob": "^3.3.3",
|
|
48
|
+
"mime-types": "^3.0.1",
|
|
48
49
|
"sharp": "^0.34.4",
|
|
49
50
|
"tmp": "^0.2.5"
|
|
50
51
|
},
|
|
@@ -52,6 +53,7 @@
|
|
|
52
53
|
"@octokit/webhooks": "^14.1.3",
|
|
53
54
|
"@types/convict": "^6.1.6",
|
|
54
55
|
"@types/debug": "^4.1.12",
|
|
56
|
+
"@types/mime-types": "^3.0.1",
|
|
55
57
|
"@types/tmp": "^0.2.6",
|
|
56
58
|
"@vercel/repository-dispatch": "^0.1.0",
|
|
57
59
|
"msw": "^2.11.6",
|
|
@@ -65,5 +67,5 @@
|
|
|
65
67
|
"lint": "eslint .",
|
|
66
68
|
"test": "vitest"
|
|
67
69
|
},
|
|
68
|
-
"gitHead": "
|
|
70
|
+
"gitHead": "fb54cf311b705f214041f18443352577be01e822"
|
|
69
71
|
}
|