fix(prd-1): skip actor check on Forgejo (no bot accounts, avoids read:user scope)
This commit is contained in:
1 parent
6eb2e41510
commit
ead98f44f9
2 files changed
+72
-7
No files matched your search
@@ -7,11 +7,21 @@
|
|||||||
|
|
||||||
import type { Octokit } from "@octokit/rest";
|
import type { Octokit } from "@octokit/rest";
|
||||||
import type { GitHubContext } from "../context";
|
import type { GitHubContext } from "../context";
|
||||||
|
import { detectPlatform } from "../../platform/detector";
|
||||||
|
|
||||||
export async function checkHumanActor(
|
export async function checkHumanActor(
|
||||||
octokit: Octokit,
|
octokit: Octokit,
|
||||||
githubContext: GitHubContext,
|
githubContext: GitHubContext,
|
||||||
) {
|
) {
|
||||||
|
// Forgejo doesn't have GitHub-style bot/app accounts, and the user API
|
||||||
|
// requires read:user scope which may not be available. Skip entirely.
|
||||||
|
if (detectPlatform() === "forgejo") {
|
||||||
|
console.log(
|
||||||
|
`Skipping human actor check on Forgejo for: ${githubContext.actor}`,
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Fetch user information from GitHub API
|
// Fetch user information from GitHub API
|
||||||
const { data: userData } = await octokit.users.getByUsername({
|
const { data: userData } = await octokit.users.getByUsername({
|
||||||
username: githubContext.actor,
|
username: githubContext.actor,
|
||||||
@@ -21,9 +31,6 @@ export async function checkHumanActor(
|
|||||||
|
|
||||||
console.log(`Actor type: ${actorType}`);
|
console.log(`Actor type: ${actorType}`);
|
||||||
|
|
||||||
// On Forgejo, the user API doesn't return a `type` field (undefined).
|
|
||||||
// Treat undefined/empty type as a human user — Forgejo doesn't have
|
|
||||||
// GitHub-style bot/app accounts.
|
|
||||||
if (actorType && actorType !== "User") {
|
if (actorType && actorType !== "User") {
|
||||||
const allowedBots = githubContext.inputs.allowedBots;
|
const allowedBots = githubContext.inputs.allowedBots;
|
||||||
|
|
||||||
|
|||||||
+62
-4
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env bun
|
#!/usr/bin/env bun
|
||||||
|
|
||||||
import { describe, test, expect } from "bun:test";
|
import { describe, test, expect, beforeEach, afterEach } from "bun:test";
|
||||||
import { checkHumanActor } from "../src/github/validation/actor";
|
import { checkHumanActor } from "../src/github/validation/actor";
|
||||||
import type { Octokit } from "@octokit/rest";
|
import type { Octokit } from "@octokit/rest";
|
||||||
import { createMockContext } from "./mockContext";
|
import { createMockContext } from "./mockContext";
|
||||||
@@ -94,8 +94,8 @@ describe("checkHumanActor", () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should treat undefined actor type as human (Forgejo compatibility)", async () => {
|
test("should treat undefined actor type as human (GitHub compatibility)", async () => {
|
||||||
// Forgejo's user API doesn't return a `type` field
|
// Edge case: GitHub API returns no `type` field
|
||||||
const mockOctokit = {
|
const mockOctokit = {
|
||||||
users: {
|
users: {
|
||||||
getByUsername: async () => ({
|
getByUsername: async () => ({
|
||||||
@@ -104,10 +104,68 @@ describe("checkHumanActor", () => {
|
|||||||
},
|
},
|
||||||
} as unknown as Octokit;
|
} as unknown as Octokit;
|
||||||
const context = createMockContext();
|
const context = createMockContext();
|
||||||
context.actor = "forgejo-user";
|
context.actor = "unknown-user";
|
||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
checkHumanActor(mockOctokit, context),
|
checkHumanActor(mockOctokit, context),
|
||||||
).resolves.toBeUndefined();
|
).resolves.toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("Forgejo platform", () => {
|
||||||
|
let savedPlatform: string | undefined;
|
||||||
|
let savedServerUrl: string | undefined;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
savedPlatform = process.env.PLATFORM;
|
||||||
|
savedServerUrl = process.env.GITHUB_SERVER_URL;
|
||||||
|
process.env.PLATFORM = "forgejo";
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
if (savedPlatform !== undefined) process.env.PLATFORM = savedPlatform;
|
||||||
|
else delete process.env.PLATFORM;
|
||||||
|
if (savedServerUrl !== undefined)
|
||||||
|
process.env.GITHUB_SERVER_URL = savedServerUrl;
|
||||||
|
else delete process.env.GITHUB_SERVER_URL;
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should skip actor check entirely on Forgejo", async () => {
|
||||||
|
let apiCalled = false;
|
||||||
|
const mockOctokit = {
|
||||||
|
users: {
|
||||||
|
getByUsername: async () => {
|
||||||
|
apiCalled = true;
|
||||||
|
return { data: {} };
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as unknown as Octokit;
|
||||||
|
const context = createMockContext();
|
||||||
|
context.actor = "forgejo-user";
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
checkHumanActor(mockOctokit, context),
|
||||||
|
).resolves.toBeUndefined();
|
||||||
|
expect(apiCalled).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should skip actor check for bot-like names on Forgejo", async () => {
|
||||||
|
let apiCalled = false;
|
||||||
|
const mockOctokit = {
|
||||||
|
users: {
|
||||||
|
getByUsername: async () => {
|
||||||
|
apiCalled = true;
|
||||||
|
return { data: { type: "Bot" } };
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as unknown as Octokit;
|
||||||
|
const context = createMockContext();
|
||||||
|
context.actor = "some-bot[bot]";
|
||||||
|
context.inputs.allowedBots = "";
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
checkHumanActor(mockOctokit, context),
|
||||||
|
).resolves.toBeUndefined();
|
||||||
|
expect(apiCalled).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
Reference in new issue
Block a user