@argos-ci/core 5.3.1 → 6.0.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.mjs +110 -22
- package/package.json +6 -6
package/dist/index.mjs
CHANGED
|
@@ -1017,28 +1017,116 @@ const chunk = (collection, size) => {
|
|
|
1017
1017
|
return result;
|
|
1018
1018
|
};
|
|
1019
1019
|
//#endregion
|
|
1020
|
-
//#region src/
|
|
1020
|
+
//#region src/github-actions-oidc.ts
|
|
1021
|
+
/**
|
|
1022
|
+
* Check if GitHub Actions OIDC is available for auto-detection.
|
|
1023
|
+
*/
|
|
1024
|
+
function isGitHubActionsOidcAvailable() {
|
|
1025
|
+
return process.env.GITHUB_ACTIONS === "true" && Boolean(process.env.ACTIONS_ID_TOKEN_REQUEST_URL) && Boolean(process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN) && !process.env.ARGOS_TOKEN;
|
|
1026
|
+
}
|
|
1027
|
+
async function fetchOidcToken(args) {
|
|
1028
|
+
if (!process.env.ACTIONS_ID_TOKEN_REQUEST_URL) throw new Error(`ACTIONS_ID_TOKEN_REQUEST_URL not found`);
|
|
1029
|
+
if (!process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN) throw new Error(`ACTIONS_ID_TOKEN_REQUEST_TOKEN not found`);
|
|
1030
|
+
const url = new URL(process.env.ACTIONS_ID_TOKEN_REQUEST_URL);
|
|
1031
|
+
url.searchParams.set("audience", args.audience);
|
|
1032
|
+
const response = await fetch(url.toString(), { headers: {
|
|
1033
|
+
Authorization: `Bearer ${process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN}`,
|
|
1034
|
+
Accept: "application/json; api-version=2.0",
|
|
1035
|
+
"Content-Type": "application/json"
|
|
1036
|
+
} });
|
|
1037
|
+
if (!response.ok) throw new Error(`Failed to fetch GitHub Actions OIDC token: ${response.status} ${response.statusText}`);
|
|
1038
|
+
const data = await response.json();
|
|
1039
|
+
if (!data.value) throw new Error("Invalid GitHub Actions OIDC token response: missing 'value' field");
|
|
1040
|
+
return data.value;
|
|
1041
|
+
}
|
|
1042
|
+
/**
|
|
1043
|
+
* Exchange a GitHub Actions OIDC token for a short-lived Argos token.
|
|
1044
|
+
*/
|
|
1045
|
+
async function exchangeGitHubActionsOidcToken(args) {
|
|
1046
|
+
const { apiBaseUrl, config } = args;
|
|
1047
|
+
const audience = new URL(apiBaseUrl).origin;
|
|
1048
|
+
const oidcToken = await fetchOidcToken({ audience });
|
|
1049
|
+
const result = await createClient({ baseUrl: apiBaseUrl }).POST("/auth/github-actions/oidc/exchange", { body: {
|
|
1050
|
+
oidcToken,
|
|
1051
|
+
repository: config.originalRepository ?? void 0,
|
|
1052
|
+
commit: config.commit,
|
|
1053
|
+
branch: config.branch,
|
|
1054
|
+
pullRequestNumber: config.prNumber ?? void 0
|
|
1055
|
+
} });
|
|
1056
|
+
if (result.error) throwAPIError(result.error);
|
|
1057
|
+
return result.data.token;
|
|
1058
|
+
}
|
|
1059
|
+
//#endregion
|
|
1060
|
+
//#region src/github-actions-tokenless.ts
|
|
1021
1061
|
const base64Encode = (obj) => Buffer.from(JSON.stringify(obj), "utf8").toString("base64");
|
|
1022
1062
|
/**
|
|
1023
|
-
*
|
|
1063
|
+
* Check if GitHub Actions tokenless authentication is available for auto-detection.
|
|
1024
1064
|
*/
|
|
1025
|
-
function
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1065
|
+
function isGitHubActionsTokenlessAvailable(config) {
|
|
1066
|
+
return Boolean(config.ciProvider === "github-actions" && config.prHeadCommit && !process.env.ARGOS_TOKEN);
|
|
1067
|
+
}
|
|
1068
|
+
/**
|
|
1069
|
+
* Build a tokenless GitHub Actions bearer token from the CI environment.
|
|
1070
|
+
*/
|
|
1071
|
+
function getTokenlessBearerToken(config) {
|
|
1072
|
+
const { originalRepository: repository, jobId, runId, prNumber } = config;
|
|
1073
|
+
if (!repository || !jobId || !runId) throw new Error(`Automatic GitHub Actions variables detection failed. Please set ARGOS_TOKEN.`);
|
|
1074
|
+
const [owner, repo] = repository.split("/");
|
|
1075
|
+
return `tokenless-github-${base64Encode({
|
|
1076
|
+
owner,
|
|
1077
|
+
repository: repo,
|
|
1078
|
+
jobId,
|
|
1079
|
+
runId,
|
|
1080
|
+
prNumber: prNumber ?? void 0
|
|
1081
|
+
})}`;
|
|
1082
|
+
}
|
|
1083
|
+
/**
|
|
1084
|
+
* Exchange a tokenless GitHub Actions bearer token for a short-lived Argos token.
|
|
1085
|
+
*/
|
|
1086
|
+
async function exchangeGitHubActionsTokenlessToken(args) {
|
|
1087
|
+
const { apiBaseUrl, config } = args;
|
|
1088
|
+
if (!config.prHeadCommit) throw new Error(`GitHub PR head commit is required for tokenless authentication.`);
|
|
1089
|
+
const tokenlessToken = getTokenlessBearerToken(config);
|
|
1090
|
+
const result = await createClient({ baseUrl: apiBaseUrl }).POST("/auth/github-actions/tokenless/exchange", { body: {
|
|
1091
|
+
tokenlessToken,
|
|
1092
|
+
commit: config.prHeadCommit,
|
|
1093
|
+
branch: config.branch
|
|
1094
|
+
} });
|
|
1095
|
+
if (result.error) throwAPIError(result.error);
|
|
1096
|
+
return result.data.token;
|
|
1097
|
+
}
|
|
1098
|
+
//#endregion
|
|
1099
|
+
//#region src/auth.ts
|
|
1100
|
+
/**
|
|
1101
|
+
* Resolve the Argos authentication token.
|
|
1102
|
+
* Priority: ARGOS_TOKEN > GitHub Actions OIDC > GitHub Actions tokenless exchange.
|
|
1103
|
+
*/
|
|
1104
|
+
async function resolveArgosToken(config) {
|
|
1105
|
+
if (config.token) {
|
|
1106
|
+
debug("Authenticated with ARGOS_TOKEN.");
|
|
1107
|
+
return config.token;
|
|
1108
|
+
}
|
|
1109
|
+
if (isGitHubActionsOidcAvailable()) {
|
|
1110
|
+
const token = await exchangeGitHubActionsOidcToken({
|
|
1111
|
+
apiBaseUrl: config.apiBaseUrl,
|
|
1112
|
+
config
|
|
1113
|
+
});
|
|
1114
|
+
debug("Authenticated with GitHub Actions OIDC.");
|
|
1115
|
+
debug(`Repository: ${config.originalRepository}`);
|
|
1116
|
+
debug(`Run: ${config.runId}`);
|
|
1117
|
+
return token;
|
|
1118
|
+
}
|
|
1119
|
+
if (isGitHubActionsTokenlessAvailable(config)) {
|
|
1120
|
+
const token = await exchangeGitHubActionsTokenlessToken({
|
|
1121
|
+
apiBaseUrl: config.apiBaseUrl,
|
|
1122
|
+
config
|
|
1123
|
+
});
|
|
1124
|
+
debug("Authenticated with GitHub Actions tokenless exchange.");
|
|
1125
|
+
debug(`Repository: ${config.originalRepository}`);
|
|
1126
|
+
debug(`Run: ${config.runId}`);
|
|
1127
|
+
return token;
|
|
1041
1128
|
}
|
|
1129
|
+
throw new Error("Missing Argos repository token 'ARGOS_TOKEN'");
|
|
1042
1130
|
}
|
|
1043
1131
|
//#endregion
|
|
1044
1132
|
//#region src/deploy.ts
|
|
@@ -1053,7 +1141,7 @@ async function deploy(params) {
|
|
|
1053
1141
|
const { token: _token, ...debugParams } = params;
|
|
1054
1142
|
debug("Starting deploy with params", debugParams);
|
|
1055
1143
|
const config = await getConfigFromOptions(params);
|
|
1056
|
-
const authToken =
|
|
1144
|
+
const authToken = await resolveArgosToken(config);
|
|
1057
1145
|
const apiClient = createClient({
|
|
1058
1146
|
baseUrl: config.apiBaseUrl,
|
|
1059
1147
|
authToken
|
|
@@ -1125,7 +1213,7 @@ async function deploy(params) {
|
|
|
1125
1213
|
*/
|
|
1126
1214
|
async function finalize(params) {
|
|
1127
1215
|
const config = await readConfig({ parallelNonce: params.parallel?.nonce });
|
|
1128
|
-
const authToken =
|
|
1216
|
+
const authToken = await resolveArgosToken(config);
|
|
1129
1217
|
const apiClient = createClient({
|
|
1130
1218
|
baseUrl: config.apiBaseUrl,
|
|
1131
1219
|
authToken
|
|
@@ -1242,7 +1330,7 @@ function getSnapshotMimeType(filepath) {
|
|
|
1242
1330
|
*/
|
|
1243
1331
|
async function skip(params) {
|
|
1244
1332
|
const [config, argosSdk] = await Promise.all([getConfigFromOptions(params), getArgosCoreSDKIdentifier()]);
|
|
1245
|
-
const authToken =
|
|
1333
|
+
const authToken = await resolveArgosToken(config);
|
|
1246
1334
|
const createBuildResponse = await createClient({
|
|
1247
1335
|
baseUrl: config.apiBaseUrl,
|
|
1248
1336
|
authToken
|
|
@@ -1279,7 +1367,7 @@ const CHUNK_SIZE = 10;
|
|
|
1279
1367
|
async function upload(params) {
|
|
1280
1368
|
debug("Starting upload with params", params);
|
|
1281
1369
|
const [config, argosSdk] = await Promise.all([getConfigFromOptions(params), getArgosCoreSDKIdentifier()]);
|
|
1282
|
-
const authToken =
|
|
1370
|
+
const authToken = await resolveArgosToken(config);
|
|
1283
1371
|
const apiClient = createClient({
|
|
1284
1372
|
baseUrl: config.apiBaseUrl,
|
|
1285
1373
|
authToken
|
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
|
+
"version": "6.0.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
7
7
|
".": {
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"url": "https://github.com/argos-ci/argos-javascript/issues"
|
|
24
24
|
},
|
|
25
25
|
"engines": {
|
|
26
|
-
"node": ">=
|
|
26
|
+
"node": ">=22.0.0"
|
|
27
27
|
},
|
|
28
28
|
"license": "MIT",
|
|
29
29
|
"keywords": [
|
|
@@ -39,8 +39,8 @@
|
|
|
39
39
|
"access": "public"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@argos-ci/api-client": "0.
|
|
43
|
-
"@argos-ci/util": "
|
|
42
|
+
"@argos-ci/api-client": "0.20.0",
|
|
43
|
+
"@argos-ci/util": "4.0.0",
|
|
44
44
|
"convict": "^6.2.5",
|
|
45
45
|
"debug": "^4.4.3",
|
|
46
46
|
"fast-glob": "^3.3.3",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"@types/node": "catalog:",
|
|
57
57
|
"@types/tmp": "^0.2.6",
|
|
58
58
|
"@vercel/repository-dispatch": "^0.1.0",
|
|
59
|
-
"msw": "^2.
|
|
59
|
+
"msw": "^2.14.5",
|
|
60
60
|
"vitest": "catalog:"
|
|
61
61
|
},
|
|
62
62
|
"scripts": {
|
|
@@ -67,5 +67,5 @@
|
|
|
67
67
|
"lint": "eslint .",
|
|
68
68
|
"test": "vitest"
|
|
69
69
|
},
|
|
70
|
-
"gitHead": "
|
|
70
|
+
"gitHead": "357c71173989a18d98767bb8811272cb46ecf937"
|
|
71
71
|
}
|