gitea support
This commit is contained in:
parent
2817c54db8
commit
3fcf15fd15
14
README.md
14
README.md
@ -4,6 +4,19 @@
|
||||
|
||||
A general-purpose [Claude Code](https://claude.ai/code) action for GitHub PRs and issues that can answer questions and implement code changes. This action intelligently detects when to activate based on your workflow context—whether responding to @claude mentions, issue assignments, or executing automation tasks with explicit prompts. It supports multiple authentication methods including Anthropic direct API, Amazon Bedrock, Google Vertex AI, and Microsoft Foundry.
|
||||
|
||||
## 🦊 Gitea Support
|
||||
|
||||
This action now supports Gitea through REST API(GITEA API) fallback . Key features:
|
||||
|
||||
**Configuration Example for Gitea:**
|
||||
```yaml
|
||||
env:
|
||||
GITHUB_TOKEN: "" # setup your gitea PAT
|
||||
GITHUB_API_URL: "https://gitea.example.com/api/v1"
|
||||
GITHUB_SERVER_URL: "https://gitea.example.com"
|
||||
GITEA_BOT_USERNAMES: "gitea-actions" # comma-separated
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
- 🎯 **Intelligent Mode Detection**: Automatically selects the appropriate execution mode based on your workflow context—no configuration needed
|
||||
@ -16,6 +29,7 @@ A general-purpose [Claude Code](https://claude.ai/code) action for GitHub PRs an
|
||||
- 📊 **Structured Outputs**: Get validated JSON results that automatically become GitHub Action outputs for complex automations
|
||||
- 🏃 **Runs on Your Infrastructure**: The action executes entirely on your own GitHub runner (Anthropic API calls go to your chosen provider)
|
||||
- ⚙️ **Simplified Configuration**: Unified `prompt` and `claude_args` inputs provide clean, powerful configuration aligned with Claude Code SDK
|
||||
- 🦊 **Gitea Support**: Support with Gitea through REST API(GITEA API) fallback when GraphQL is unavailable
|
||||
|
||||
## 📦 Upgrading from v0.x?
|
||||
|
||||
|
||||
@ -2,3 +2,5 @@ export const GITHUB_API_URL =
|
||||
process.env.GITHUB_API_URL || "https://api.github.com";
|
||||
export const GITHUB_SERVER_URL =
|
||||
process.env.GITHUB_SERVER_URL || "https://github.com";
|
||||
export const USE_GITEA_API = process.env.USE_GITEA_API === "true" || process.env.USE_GITEA_API === "1";
|
||||
export const GITEA_BOT_USERNAMES = (process.env.USE_GITEA_API || "").split(",")
|
||||
292
src/github/api/queries/gitea.ts
Normal file
292
src/github/api/queries/gitea.ts
Normal file
@ -0,0 +1,292 @@
|
||||
import type { Octokit } from "@octokit/rest";
|
||||
|
||||
// Type definitions for REST API responses
|
||||
type RestFile = Awaited<
|
||||
ReturnType<Octokit["rest"]["pulls"]["listFiles"]>
|
||||
>["data"][number];
|
||||
type RestComment = Awaited<
|
||||
ReturnType<Octokit["rest"]["issues"]["listComments"]>
|
||||
>["data"][number];
|
||||
type RestCommit = Awaited<
|
||||
ReturnType<Octokit["rest"]["pulls"]["listCommits"]>
|
||||
>["data"][number];
|
||||
type RestReview = Awaited<
|
||||
ReturnType<Octokit["rest"]["pulls"]["listReviews"]>
|
||||
>["data"][number];
|
||||
type RestReviewComment = Awaited<
|
||||
ReturnType<Octokit["rest"]["pulls"]["listReviewComments"]>
|
||||
>["data"][number];
|
||||
|
||||
/**
|
||||
* Fetch complete Pull Request data including commits, files, comments, and reviews
|
||||
*/
|
||||
export async function fetchPullRequest(
|
||||
octokit: Octokit,
|
||||
owner: string,
|
||||
repo: string,
|
||||
number: number,
|
||||
) {
|
||||
// Fetch all PR data in parallel for better performance
|
||||
const [prData, prFiles, prComments, prCommits, prReviews] = await Promise.all(
|
||||
[
|
||||
// Basic PR information
|
||||
octokit.rest.pulls.get({
|
||||
owner,
|
||||
repo,
|
||||
pull_number: number,
|
||||
}),
|
||||
// Changed files
|
||||
octokit.rest.pulls.listFiles({
|
||||
owner,
|
||||
repo,
|
||||
pull_number: number,
|
||||
per_page: 100,
|
||||
}),
|
||||
// Issue comments (PR general comments)
|
||||
octokit.rest.issues.listComments({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: number,
|
||||
per_page: 100,
|
||||
}),
|
||||
// PR commits
|
||||
octokit.rest.pulls.listCommits({
|
||||
owner,
|
||||
repo,
|
||||
pull_number: number,
|
||||
per_page: 100,
|
||||
}),
|
||||
// PR reviews
|
||||
octokit.rest.pulls.listReviews({
|
||||
owner,
|
||||
repo,
|
||||
pull_number: number,
|
||||
per_page: 100,
|
||||
}),
|
||||
],
|
||||
);
|
||||
|
||||
// Fetch review comments for each review using Gitea API
|
||||
// Gitea endpoint: GET /repos/{owner}/{repo}/pulls/{index}/reviews/{id}/comments
|
||||
const reviewsWithComments = await Promise.all(
|
||||
prReviews.data.map(async (review: RestReview) => {
|
||||
try {
|
||||
// Use Gitea-specific endpoint to get comments for each review
|
||||
const response = await octokit.request(
|
||||
"GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/comments",
|
||||
{
|
||||
owner,
|
||||
repo,
|
||||
pull_number: number,
|
||||
review_id: review.id,
|
||||
per_page: 100,
|
||||
},
|
||||
);
|
||||
|
||||
return {
|
||||
...review,
|
||||
comments: response.data,
|
||||
};
|
||||
} catch (error) {
|
||||
// If fetching comments fails, return review with empty comments
|
||||
// @ts-expect-error - console is available at runtime
|
||||
console.warn(
|
||||
`Failed to fetch comments for review ${review.id}:`,
|
||||
error,
|
||||
);
|
||||
return {
|
||||
...review,
|
||||
comments: [],
|
||||
};
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
// Transform REST API response to match GraphQL-like structure
|
||||
return {
|
||||
repository: {
|
||||
pullRequest: {
|
||||
title: prData.data.title,
|
||||
body: prData.data.body || "",
|
||||
author: {
|
||||
login: prData.data.user?.login || "",
|
||||
name: prData.data.user?.name || undefined,
|
||||
},
|
||||
baseRefName: prData.data.base.ref,
|
||||
headRefName: prData.data.head.ref,
|
||||
headRefOid: prData.data.head.sha,
|
||||
createdAt: prData.data.created_at,
|
||||
updatedAt: prData.data.updated_at,
|
||||
lastEditedAt: prData.data.updated_at, // Gitea may not have separate lastEditedAt
|
||||
additions: prData.data.additions || 0,
|
||||
deletions: prData.data.deletions || 0,
|
||||
state: prData.data.state.toUpperCase(), // "open" -> "OPEN"
|
||||
commits: {
|
||||
totalCount: prCommits.data.length,
|
||||
nodes: prCommits.data.map((commit: RestCommit) => ({
|
||||
commit: {
|
||||
oid: commit.sha,
|
||||
message: commit.commit.message,
|
||||
author: {
|
||||
name: commit.commit.author?.name || "",
|
||||
email: commit.commit.author?.email || "",
|
||||
},
|
||||
},
|
||||
})),
|
||||
},
|
||||
files: {
|
||||
nodes: prFiles.data.map((file: RestFile) => ({
|
||||
path: file.filename,
|
||||
additions: file.additions,
|
||||
deletions: file.deletions,
|
||||
changeType: mapFileStatus(file.status),
|
||||
})),
|
||||
},
|
||||
comments: {
|
||||
nodes: prComments.data.map((comment: RestComment) => ({
|
||||
id: `comment_${comment.id}`,
|
||||
databaseId: comment.id,
|
||||
body: comment.body || "",
|
||||
author: {
|
||||
login: comment.user?.login || "",
|
||||
},
|
||||
createdAt: comment.created_at,
|
||||
updatedAt: comment.updated_at,
|
||||
lastEditedAt: comment.updated_at,
|
||||
isMinimized: false, // Gitea may not support this
|
||||
})),
|
||||
},
|
||||
reviews: {
|
||||
nodes: reviewsWithComments.map(
|
||||
(review: RestReview & { comments: RestReviewComment[] }) => ({
|
||||
id: `review_${review.id}`,
|
||||
databaseId: review.id,
|
||||
author: {
|
||||
login: review.user?.login || "",
|
||||
},
|
||||
body: review.body || "",
|
||||
state: review.state.toUpperCase(), // "APPROVED", "CHANGES_REQUESTED", etc.
|
||||
submittedAt: review.submitted_at || review.created_at || "",
|
||||
updatedAt: review.submitted_at || review.created_at || "",
|
||||
lastEditedAt: review.submitted_at || review.created_at || "",
|
||||
comments: {
|
||||
nodes: review.comments.map((comment: RestReviewComment) => ({
|
||||
id: `review_comment_${comment.id}`,
|
||||
databaseId: comment.id,
|
||||
body: comment.body || "",
|
||||
path: comment.path,
|
||||
line: comment.line || comment.original_line || null,
|
||||
author: {
|
||||
login: comment.user?.login || "",
|
||||
},
|
||||
createdAt: comment.created_at,
|
||||
updatedAt: comment.updated_at,
|
||||
lastEditedAt: comment.updated_at,
|
||||
isMinimized: false,
|
||||
})),
|
||||
},
|
||||
}),
|
||||
),
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch complete Issue data including comments
|
||||
*/
|
||||
export async function fetchIssue(
|
||||
octokit: Octokit,
|
||||
owner: string,
|
||||
repo: string,
|
||||
number: number,
|
||||
) {
|
||||
// Fetch issue data and comments in parallel
|
||||
const [issueData, issueComments] = await Promise.all([
|
||||
octokit.rest.issues.get({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: number,
|
||||
}),
|
||||
octokit.rest.issues.listComments({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: number,
|
||||
per_page: 100,
|
||||
}),
|
||||
]);
|
||||
|
||||
// Transform REST API response to match GraphQL-like structure
|
||||
return {
|
||||
repository: {
|
||||
issue: {
|
||||
title: issueData.data.title,
|
||||
body: issueData.data.body || "",
|
||||
author: {
|
||||
login: issueData.data.user?.login || "",
|
||||
},
|
||||
createdAt: issueData.data.created_at,
|
||||
updatedAt: issueData.data.updated_at,
|
||||
lastEditedAt: issueData.data.updated_at,
|
||||
state: issueData.data.state.toUpperCase(),
|
||||
comments: {
|
||||
nodes: issueComments.data.map((comment: RestComment) => ({
|
||||
id: `comment_${comment.id}`,
|
||||
databaseId: comment.id,
|
||||
body: comment.body || "",
|
||||
author: {
|
||||
login: comment.user?.login || "",
|
||||
},
|
||||
createdAt: comment.created_at,
|
||||
updatedAt: comment.updated_at,
|
||||
lastEditedAt: comment.updated_at,
|
||||
isMinimized: false,
|
||||
})),
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch user display name
|
||||
*/
|
||||
export async function fetchUser(octokit: Octokit, login: string) {
|
||||
try {
|
||||
const userData = await octokit.rest.users.getByUsername({
|
||||
username: login,
|
||||
});
|
||||
|
||||
return {
|
||||
user: {
|
||||
name: userData.data.name || userData.data.full_name || null,
|
||||
},
|
||||
};
|
||||
} catch (error) {
|
||||
// Note: console is available at runtime in Node.js environment
|
||||
// @ts-expect-error - console is not in lib but available at runtime
|
||||
console.warn(`Failed to fetch user ${login}:`, error);
|
||||
return {
|
||||
user: {
|
||||
name: null,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Map Gitea file status to GraphQL changeType format
|
||||
*/
|
||||
function mapFileStatus(status: string): string {
|
||||
const statusMap: Record<string, string> = {
|
||||
added: "ADDED",
|
||||
modified: "MODIFIED",
|
||||
removed: "DELETED",
|
||||
renamed: "RENAMED",
|
||||
copied: "COPIED",
|
||||
changed: "MODIFIED",
|
||||
};
|
||||
|
||||
return statusMap[status] || status.toUpperCase();
|
||||
}
|
||||
@ -1,6 +1,8 @@
|
||||
import { execFileSync } from "child_process";
|
||||
import type { Octokits } from "../api/client";
|
||||
import { USE_GITEA_API } from "../api/config";
|
||||
import { ISSUE_QUERY, PR_QUERY, USER_QUERY } from "../api/queries/github";
|
||||
import { fetchPullRequest, fetchIssue, fetchUser } from "../api/queries/gitea";
|
||||
import {
|
||||
isIssueCommentEvent,
|
||||
isIssuesEvent,
|
||||
@ -249,12 +251,14 @@ export async function fetchGitHubData({
|
||||
try {
|
||||
if (isPR) {
|
||||
// Fetch PR data with all comments and file information
|
||||
const prResult = await octokits.graphql<PullRequestQueryResponse>(
|
||||
PR_QUERY,
|
||||
{
|
||||
owner,
|
||||
repo,
|
||||
number: parseInt(prNumber),
|
||||
const prResult = USE_GITEA_API
|
||||
? await fetchPullRequest(octokits.rest, owner, repo, parseInt(prNumber))
|
||||
: await octokits.graphql<PullRequestQueryResponse>(
|
||||
PR_QUERY,
|
||||
{
|
||||
owner,
|
||||
repo,
|
||||
number: parseInt(prNumber),
|
||||
},
|
||||
);
|
||||
|
||||
@ -264,13 +268,15 @@ export async function fetchGitHubData({
|
||||
changedFiles = pullRequest.files.nodes || [];
|
||||
comments = filterCommentsByActor(
|
||||
filterCommentsToTriggerTime(
|
||||
pullRequest.comments?.nodes || [],
|
||||
triggerTime,
|
||||
pullRequest.comments?.nodes || [],
|
||||
triggerTime,
|
||||
),
|
||||
includeCommentsByActor,
|
||||
excludeCommentsByActor,
|
||||
);
|
||||
reviewData = pullRequest.reviews || [];
|
||||
reviewData = USE_GITEA_API
|
||||
? pullRequest.reviews || null
|
||||
: pullRequest.reviews || [];
|
||||
|
||||
console.log(`Successfully fetched PR #${prNumber} data`);
|
||||
} else {
|
||||
@ -278,12 +284,14 @@ export async function fetchGitHubData({
|
||||
}
|
||||
} else {
|
||||
// Fetch issue data
|
||||
const issueResult = await octokits.graphql<IssueQueryResponse>(
|
||||
ISSUE_QUERY,
|
||||
{
|
||||
owner,
|
||||
repo,
|
||||
number: parseInt(prNumber),
|
||||
const issueResult = USE_GITEA_API
|
||||
? await fetchIssue(octokits.rest, owner, repo, parseInt(prNumber))
|
||||
: await octokits.graphql<IssueQueryResponse>(
|
||||
ISSUE_QUERY,
|
||||
{
|
||||
owner,
|
||||
repo,
|
||||
number: parseInt(prNumber),
|
||||
},
|
||||
);
|
||||
|
||||
@ -291,8 +299,8 @@ export async function fetchGitHubData({
|
||||
contextData = issueResult.repository.issue;
|
||||
comments = filterCommentsByActor(
|
||||
filterCommentsToTriggerTime(
|
||||
contextData?.comments?.nodes || [],
|
||||
triggerTime,
|
||||
contextData?.comments?.nodes || [],
|
||||
triggerTime,
|
||||
),
|
||||
includeCommentsByActor,
|
||||
excludeCommentsByActor,
|
||||
@ -475,9 +483,11 @@ export async function fetchUserDisplayName(
|
||||
login: string,
|
||||
): Promise<string | null> {
|
||||
try {
|
||||
const result = await octokits.graphql<UserQueryResponse>(USER_QUERY, {
|
||||
login,
|
||||
});
|
||||
const result = USE_GITEA_API
|
||||
? await fetchUser(octokits.rest, login)
|
||||
: await octokits.graphql<UserQueryResponse>(USER_QUERY, {
|
||||
login,
|
||||
});
|
||||
return result.user.name;
|
||||
} catch (error) {
|
||||
console.warn(`Failed to fetch user display name for ${login}:`, error);
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import type { Octokits } from "../api/client";
|
||||
import { GITHUB_SERVER_URL } from "../api/config";
|
||||
import { GITHUB_SERVER_URL, USE_GITEA_API } from "../api/config";
|
||||
import { createBranchUrl } from "./comments/common";
|
||||
import { $ } from "bun";
|
||||
|
||||
export async function checkAndCommitOrDeleteBranch(
|
||||
@ -80,7 +81,9 @@ export async function checkAndCommitOrDeleteBranch(
|
||||
);
|
||||
|
||||
// Set branch link since we now have commits
|
||||
const branchUrl = `${GITHUB_SERVER_URL}/${owner}/${repo}/tree/${claudeBranch}`;
|
||||
const branchUrl = USE_GITEA_API
|
||||
? createBranchUrl(owner, repo, claudeBranch)
|
||||
: `${GITHUB_SERVER_URL}/${owner}/${repo}/tree/${claudeBranch}`;
|
||||
branchLink = `\n[View branch](${branchUrl})`;
|
||||
} else {
|
||||
console.log(
|
||||
@ -91,7 +94,9 @@ export async function checkAndCommitOrDeleteBranch(
|
||||
} catch (gitError) {
|
||||
console.error("Error checking/committing changes:", gitError);
|
||||
// If we can't check git status, assume the branch might have changes
|
||||
const branchUrl = `${GITHUB_SERVER_URL}/${owner}/${repo}/tree/${claudeBranch}`;
|
||||
const branchUrl = USE_GITEA_API
|
||||
? createBranchUrl(owner, repo, claudeBranch)
|
||||
: `${GITHUB_SERVER_URL}/${owner}/${repo}/tree/${claudeBranch}`;
|
||||
branchLink = `\n[View branch](${branchUrl})`;
|
||||
}
|
||||
} else {
|
||||
@ -102,13 +107,17 @@ export async function checkAndCommitOrDeleteBranch(
|
||||
}
|
||||
} else {
|
||||
// Only add branch link if there are commits
|
||||
const branchUrl = `${GITHUB_SERVER_URL}/${owner}/${repo}/tree/${claudeBranch}`;
|
||||
const branchUrl = USE_GITEA_API
|
||||
? createBranchUrl(owner, repo, claudeBranch)
|
||||
: `${GITHUB_SERVER_URL}/${owner}/${repo}/tree/${claudeBranch}`;
|
||||
branchLink = `\n[View branch](${branchUrl})`;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error comparing commits on Claude branch:", error);
|
||||
// If we can't compare but the branch exists remotely, include the branch link
|
||||
const branchUrl = `${GITHUB_SERVER_URL}/${owner}/${repo}/tree/${claudeBranch}`;
|
||||
const branchUrl = USE_GITEA_API
|
||||
? createBranchUrl(owner, repo, claudeBranch)
|
||||
: `${GITHUB_SERVER_URL}/${owner}/${repo}/tree/${claudeBranch}`;
|
||||
branchLink = `\n[View branch](${branchUrl})`;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { GITHUB_SERVER_URL } from "../api/config";
|
||||
import { GITHUB_SERVER_URL, USE_GITEA_API } from "../api/config";
|
||||
import { createBranchUrl } from "./comments/common";
|
||||
|
||||
export type ExecutionDetails = {
|
||||
total_cost_usd?: number;
|
||||
@ -157,10 +158,14 @@ export function updateCommentBody(input: CommentUpdateInput): string {
|
||||
|
||||
// If we don't have a URL yet but have a branch name, construct it
|
||||
if (!branchUrl && finalBranchName) {
|
||||
// Extract owner/repo from jobUrl
|
||||
const repoMatch = jobUrl.match(/github\.com\/([^\/]+)\/([^\/]+)\//);
|
||||
// Extract owner/repo from jobUrl (works for both GitHub and Gitea URLs)
|
||||
const repoMatch = USE_GITEA_API
|
||||
? jobUrl.match(/\/([^\/]+)\/([^\/]+)\/(?:actions|tree|src)/)
|
||||
: jobUrl.match(/github\.com\/([^\/]+)\/([^\/]+)\//);
|
||||
if (repoMatch) {
|
||||
branchUrl = `${GITHUB_SERVER_URL}/${repoMatch[1]}/${repoMatch[2]}/tree/${finalBranchName}`;
|
||||
branchUrl = USE_GITEA_API
|
||||
? createBranchUrl(repoMatch[1], repoMatch[2], finalBranchName)
|
||||
: `${GITHUB_SERVER_URL}/${repoMatch[1]}/${repoMatch[2]}/tree/${finalBranchName}`;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { GITHUB_SERVER_URL } from "../../api/config";
|
||||
import { GITHUB_SERVER_URL, USE_GITEA_API } from "../../api/config";
|
||||
|
||||
export const SPINNER_HTML =
|
||||
'<img src="https://github.com/user-attachments/assets/5ac382c7-e004-429b-8e35-7feb3e8f9c6f" width="14px" height="14px" style="vertical-align: middle; margin-left: 4px;" />';
|
||||
@ -17,10 +17,31 @@ export function createBranchLink(
|
||||
repo: string,
|
||||
branchName: string,
|
||||
): string {
|
||||
const branchUrl = `${GITHUB_SERVER_URL}/${owner}/${repo}/tree/${branchName}`;
|
||||
const branchUrl = USE_GITEA_API
|
||||
? createBranchUrl(owner, repo, branchName)
|
||||
: `${GITHUB_SERVER_URL}/${owner}/${repo}/tree/${branchName}`;
|
||||
return `\n[View branch](${branchUrl})`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the branch URL path segment for the current platform
|
||||
* Gitea uses /src/branch/ while GitHub uses /tree/
|
||||
*/
|
||||
export function getBranchPath(): string {
|
||||
return USE_GITEA_API ? "src/branch" : "tree";
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a branch URL for the current platform
|
||||
*/
|
||||
export function createBranchUrl(
|
||||
owner: string,
|
||||
repo: string,
|
||||
branchName: string,
|
||||
): string {
|
||||
return `${GITHUB_SERVER_URL}/${owner}/${repo}/${getBranchPath()}/${branchName}`;
|
||||
}
|
||||
|
||||
export function createCommentBody(
|
||||
jobRunLink: string,
|
||||
branchLink: string = "",
|
||||
|
||||
@ -7,11 +7,24 @@
|
||||
|
||||
import type { Octokit } from "@octokit/rest";
|
||||
import type { GitHubContext } from "../context";
|
||||
import { GITEA_BOT_USERNAMES, USE_GITEA_API } from "../api/config.ts";
|
||||
|
||||
export async function checkHumanActor(
|
||||
octokit: Octokit,
|
||||
githubContext: GitHubContext,
|
||||
) {
|
||||
|
||||
|
||||
if (USE_GITEA_API) {
|
||||
if (!GITEA_BOT_USERNAMES.includes(githubContext.actor)) {
|
||||
throw new Error(
|
||||
`Workflow initiated by non-human actor: ${githubContext.actor}. Please add bot to GITEA_BOT_USERNAMES`,
|
||||
);
|
||||
}
|
||||
// For Gitea environments, skip the user type check if USE_GITEA_API is set
|
||||
return;
|
||||
}
|
||||
|
||||
// Fetch user information from GitHub API
|
||||
const { data: userData } = await octokit.users.getByUsername({
|
||||
username: githubContext.actor,
|
||||
|
||||
@ -59,7 +59,7 @@ export async function checkWritePermissions(
|
||||
const permissionLevel = response.data.permission;
|
||||
core.info(`Permission level retrieved: ${permissionLevel}`);
|
||||
|
||||
if (permissionLevel === "admin" || permissionLevel === "write") {
|
||||
if (permissionLevel === "admin" || permissionLevel === "write" || permissionLevel === "owner") {
|
||||
core.info(`Actor has write access: ${permissionLevel}`);
|
||||
return true;
|
||||
} else {
|
||||
|
||||
@ -65,6 +65,7 @@ export function detectMode(context: GitHubContext): AutoDetectedMode {
|
||||
const supportedActions = [
|
||||
"opened",
|
||||
"synchronize",
|
||||
"synchronized",
|
||||
"ready_for_review",
|
||||
"reopened",
|
||||
];
|
||||
@ -112,6 +113,7 @@ function validateTrackProgressEvent(context: GitHubContext): void {
|
||||
const validActions = [
|
||||
"opened",
|
||||
"synchronize",
|
||||
"synchronized",
|
||||
"ready_for_review",
|
||||
"reopened",
|
||||
];
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user