@biffo/cli 0.223.2 → 0.223.3
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.js +33 -11
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -965,10 +965,10 @@ var GitAdapter = class {
|
|
|
965
965
|
* `token`, when given, authenticates the clone against a private repo by
|
|
966
966
|
* embedding it in the URL's userinfo (`https://x-access-token:<token>@...`
|
|
967
967
|
* — the standard scheme for a GitHub PAT/App token over HTTPS) before
|
|
968
|
-
* handing it to `git clone`. The
|
|
969
|
-
* `
|
|
970
|
-
*
|
|
971
|
-
*
|
|
968
|
+
* handing it to `git clone`. The failure path runs the underlying error
|
|
969
|
+
* through `redactSecrets` before reporting it: `execa` echoes the argv it
|
|
970
|
+
* ran, so the tokenized URL *is* present in that message and interpolating
|
|
971
|
+
* it raw leaked the token into CLI output and CI logs (#1169).
|
|
972
972
|
*/
|
|
973
973
|
async cloneToTemp(repoUrl, namePrefix, token) {
|
|
974
974
|
const dir = mkdtempSync2(join6(tmpdir2(), `${namePrefix}-${randomUUID().slice(0, 8)}-`));
|
|
@@ -977,7 +977,7 @@ var GitAdapter = class {
|
|
|
977
977
|
await execa2("git", ["clone", "--depth", "1", cloneUrl, dir]);
|
|
978
978
|
} catch (err) {
|
|
979
979
|
rmSync2(dir, { recursive: true, force: true });
|
|
980
|
-
throw
|
|
980
|
+
throw gitFailure(`Failed to clone ${repoUrl}`, err, [token]);
|
|
981
981
|
}
|
|
982
982
|
const gitDir = join6(dir, ".git");
|
|
983
983
|
if (existsSync6(gitDir)) rmSync2(gitDir, { recursive: true, force: true });
|
|
@@ -1000,7 +1000,7 @@ var GitAdapter = class {
|
|
|
1000
1000
|
await execa2("git", ["clone", cloneUrl, dir]);
|
|
1001
1001
|
} catch (err) {
|
|
1002
1002
|
rmSync2(dir, { recursive: true, force: true });
|
|
1003
|
-
throw
|
|
1003
|
+
throw gitFailure(`Failed to clone ${repoUrl}`, err, [token]);
|
|
1004
1004
|
}
|
|
1005
1005
|
return dir;
|
|
1006
1006
|
}
|
|
@@ -1182,9 +1182,15 @@ var GitAdapter = class {
|
|
|
1182
1182
|
/**
|
|
1183
1183
|
* Push the current HEAD to `branch` on the remote. When `token` is given and
|
|
1184
1184
|
* the remote is HTTPS, it's embedded in the push URL for auth (SSH/file
|
|
1185
|
-
* remotes push with ambient credentials).
|
|
1186
|
-
*
|
|
1187
|
-
*
|
|
1185
|
+
* remotes push with ambient credentials).
|
|
1186
|
+
*
|
|
1187
|
+
* The failure path reports git's own error, redacted (#1135). It previously
|
|
1188
|
+
* discarded it entirely — a defensible-looking choice, since the argv `execa`
|
|
1189
|
+
* echoes contains the tokenized URL, but it made **every** push failure in
|
|
1190
|
+
* the CLI indistinguishable: a rejected pre-push hook, an unresolvable
|
|
1191
|
+
* remote and a bad token all produced the same sentence. That is why #1040
|
|
1192
|
+
* ("`core upgrade --apply` aborts at the push step") survived two sessions of
|
|
1193
|
+
* diagnosis without its cause ever being established.
|
|
1188
1194
|
*/
|
|
1189
1195
|
async push(cwd, branch, opts = {}) {
|
|
1190
1196
|
const remote = opts.remote ?? "origin";
|
|
@@ -1196,8 +1202,8 @@ var GitAdapter = class {
|
|
|
1196
1202
|
}
|
|
1197
1203
|
try {
|
|
1198
1204
|
await execa2("git", ["push", target, `HEAD:refs/heads/${branch}`], { cwd });
|
|
1199
|
-
} catch {
|
|
1200
|
-
throw
|
|
1205
|
+
} catch (err) {
|
|
1206
|
+
throw gitFailure(`Failed to push branch '${branch}' to remote '${remote}'`, err, [opts.token]);
|
|
1201
1207
|
}
|
|
1202
1208
|
await this.setUpstreamAfterPush(cwd, branch, remote);
|
|
1203
1209
|
}
|
|
@@ -1263,6 +1269,22 @@ function injectToken(repoUrl, token) {
|
|
|
1263
1269
|
parsed.password = token;
|
|
1264
1270
|
return parsed.toString();
|
|
1265
1271
|
}
|
|
1272
|
+
var REDACTED = "***";
|
|
1273
|
+
var MIN_REDACTABLE = 8;
|
|
1274
|
+
function redactSecrets(text, secrets) {
|
|
1275
|
+
let out = text;
|
|
1276
|
+
for (const secret of secrets) {
|
|
1277
|
+
if (secret === void 0 || secret.length < MIN_REDACTABLE) continue;
|
|
1278
|
+
for (const form of /* @__PURE__ */ new Set([secret, encodeURIComponent(secret)])) {
|
|
1279
|
+
out = out.split(form).join(REDACTED);
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
return out;
|
|
1283
|
+
}
|
|
1284
|
+
function gitFailure(summary, err, secrets) {
|
|
1285
|
+
const detail = redactSecrets(err.message, secrets);
|
|
1286
|
+
return new Error(`${summary}: ${detail}`);
|
|
1287
|
+
}
|
|
1266
1288
|
|
|
1267
1289
|
// src/adapters/source-control/github/index.ts
|
|
1268
1290
|
import { execSync } from "child_process";
|