From 5049be494d73e4c6a53a37be80503ba2ab98bbc8 Mon Sep 17 00:00:00 2001 From: philluiz2323 Date: Sun, 7 Jun 2026 06:15:38 -0700 Subject: [PATCH 1/2] fix(settings): require issues:write for detected comment mode independent of sample writesPrPublicSurface checked comment capability with shouldPublishPrComment(settings) (default minerStatus not_checked), so for the default detected_contributors_only comment mode it returned false unless the previewed sample was a confirmed miner -- dropping issues:write from required/missing install permissions for non-confirmed samples even though the repo comments for confirmed miners. Check with the maximal confirmed status, matching the label path. --- src/signals/settings-preview.ts | 2 +- test/unit/settings-preview.test.ts | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/signals/settings-preview.ts b/src/signals/settings-preview.ts index 5d466f2c1c..0a5774b499 100644 --- a/src/signals/settings-preview.ts +++ b/src/signals/settings-preview.ts @@ -477,7 +477,7 @@ function buildRepoInstallPreview(args: { } function writesPrPublicSurface(settings: RepositorySettings, decision: PublicSurfaceDecision): boolean { - return decision.willComment || decision.willLabel || shouldPublishPrComment(settings) || shouldApplyPrLabel(settings, "confirmed"); + return decision.willComment || decision.willLabel || shouldPublishPrComment(settings, "confirmed") || shouldApplyPrLabel(settings, "confirmed"); } function requiredInstallPermissions(settings: RepositorySettings, decision: PublicSurfaceDecision): string[] { diff --git a/test/unit/settings-preview.test.ts b/test/unit/settings-preview.test.ts index 5bc74b2069..e11a15d127 100644 --- a/test/unit/settings-preview.test.ts +++ b/test/unit/settings-preview.test.ts @@ -200,6 +200,21 @@ describe("buildRepoSettingsPreview", () => { expect(withoutChecks.warnings.some((warning) => /Checks: write/.test(warning))).toBe(false); }); + it("requires Issues: write for detected-contributors comment mode even when previewing a non-confirmed sample", () => { + // detected_contributors_only + comment_only comments for confirmed miners, so the repo needs + // issues:write regardless of the previewed sample's miner status. Previewing a non-confirmed + // author must not drop the required (and missing) issues permission. + const preview = buildRepoSettingsPreview({ + ...base, + settings: settings({ publicSurface: "comment_only", commentMode: "detected_contributors_only", autoLabelEnabled: false, publicAudienceMode: "oss_maintainer" }), + installation: { ...healthyInstall, status: "needs_attention", missingPermissions: ["issues"] }, + sample: { authorLogin: "contributor", minerStatus: "not_found" }, + }); + expect(preview.decision).toMatchObject({ skipped: false, willComment: false, willLabel: false }); + expect(preview.installPreview.permissions.required).toContain("issues: write"); + expect(preview.installPreview.permissions.missing).toContain("issues"); + }); + it("explains a missing Checks: write permission when the opt-in gate is enabled", () => { const preview = buildRepoSettingsPreview({ ...base, From f3e16bf12725ac18b6fbe692988c5b0006dc34d0 Mon Sep 17 00:00:00 2001 From: galuis116 Date: Mon, 8 Jun 2026 01:34:44 -0700 Subject: [PATCH 2/2] ci: retry actionlint binary downloads --- scripts/actionlint.mjs | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/scripts/actionlint.mjs b/scripts/actionlint.mjs index 17952e8bc6..37be25ec92 100644 --- a/scripts/actionlint.mjs +++ b/scripts/actionlint.mjs @@ -1,4 +1,4 @@ -import { execFileSync } from "node:child_process"; +import { spawnSync } from "node:child_process"; import { readdirSync } from "node:fs"; import { join } from "node:path"; @@ -13,4 +13,33 @@ if (files.length === 0) { } const bin = process.platform === "win32" ? "github-actionlint.cmd" : "github-actionlint"; -execFileSync(bin, files, { stdio: "inherit", shell: process.platform === "win32" }); +const maxAttempts = Number.parseInt(process.env.ACTIONLINT_ATTEMPTS ?? "3", 10); +const retryDelayMs = Number.parseInt(process.env.ACTIONLINT_RETRY_DELAY_MS ?? "1000", 10); + +for (let attempt = 1; attempt <= maxAttempts; attempt += 1) { + const result = spawnSync(bin, files, { + encoding: "utf8", + shell: process.platform === "win32", + }); + + if (result.stdout) { + process.stdout.write(result.stdout); + } + + if (result.stderr) { + process.stderr.write(result.stderr); + } + + if (result.status === 0) { + process.exit(0); + } + + const output = `${result.stdout ?? ""}${result.stderr ?? ""}`; + const downloadFailed = output.includes("github-actionlint: Download failed:"); + if (!downloadFailed || attempt === maxAttempts) { + process.exit(result.status ?? 1); + } + + console.error(`actionlint download failed; retrying (${attempt + 1}/${maxAttempts})...`); + Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, retryDelayMs); +}