Skip to main content
Glama

gitea_workflow_check_blocked

Identify blocked issues and SLA violations in Gitea repositories by checking for stale items based on priority-specific time limits.

Instructions

Detect issues that are blocked or exceeding SLA. Checks for stale issues based on priority-specific time limits.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
ownerNoRepository owner. Uses context if not provided
repoNoRepository name. Uses context if not provided
threshold_hoursNoOverride default SLA hours threshold

Implementation Reference

  • Core handler function that detects blocked issues by checking if open issues exceed SLA time limits based on priority, or have stale 'needs-info'/'needs-review' labels. Loads config if needed, fetches open issues, computes hours since update, and collects issues needing attention.
    export async function workflowCheckBlocked(
      ctx: WorkflowToolsContext,
      args: {
        owner?: string;
        repo?: string;
        config?: WorkflowConfig;
        threshold_hours?: number;
      }
    ): Promise<{
      success: boolean;
      blocked_issues: Array<{
        number: number;
        title: string;
        priority: string | null;
        hours_since_update: number;
        sla_hours: number | null;
        reason: string;
      }>;
      error?: string;
    }> {
      logger.debug({ args: { ...args, config: args.config ? '[provided]' : undefined } }, 'Checking blocked issues');
    
      const { owner, repo } = ctx.contextManager.resolveOwnerRepo(args.owner, args.repo);
    
      // 获取配置
      let config = args.config;
      if (!config) {
        const loadResult = await workflowLoadConfig(ctx, { owner, repo });
        if (!loadResult.success || !loadResult.config) {
          return {
            success: false,
            blocked_issues: [],
            error: loadResult.error || '无法加载配置',
          };
        }
        config = loadResult.config;
      }
    
      const blockedIssues: Array<{
        number: number;
        title: string;
        priority: string | null;
        hours_since_update: number;
        sla_hours: number | null;
        reason: string;
      }> = [];
    
      try {
        // 获取开放的 Issue
        const issues = await ctx.client.get<Issue[]>(`/repos/${owner}/${repo}/issues?state=open&limit=100`);
    
        for (const issue of issues) {
          const priority = getIssuePriority(issue);
          const hoursSinceUpdate = calculateHoursSinceUpdate(issue);
          const slaHours = priority ? getSLAHours(config, priority) : null;
    
          // 检查是否已有阻塞标签
          const prefixes = getLabelPrefixes(config);
          const blockedLabel = buildLabel(prefixes.workflow, 'blocked');
          const alreadyBlocked = hasLabel(issue, blockedLabel);
    
          // 检查是否超过 SLA
          let isBlocked = false;
          let reason = '';
    
          if (args.threshold_hours && hoursSinceUpdate > args.threshold_hours) {
            isBlocked = true;
            reason = `超过指定阈值 ${args.threshold_hours} 小时未更新`;
          } else if (slaHours && hoursSinceUpdate > slaHours) {
            isBlocked = true;
            reason = `超过 SLA 时间 (${slaHours} 小时)`;
          } else if (hasLabel(issue, buildLabel(prefixes.workflow, 'needs-info')) && hoursSinceUpdate > 48) {
            isBlocked = true;
            reason = '标记为需要信息但超过 48 小时未响应';
          } else if (hasLabel(issue, buildLabel(prefixes.workflow, 'needs-review')) && hoursSinceUpdate > 72) {
            isBlocked = true;
            reason = '标记为需要审查但超过 72 小时未处理';
          }
    
          if (isBlocked && !alreadyBlocked) {
            blockedIssues.push({
              number: issue.number,
              title: issue.title,
              priority,
              hours_since_update: hoursSinceUpdate,
              sla_hours: slaHours ?? null,
              reason,
            });
          }
        }
    
        logger.info({ owner, repo, blocked: blockedIssues.length }, 'Blocked issues checked');
    
        return {
          success: true,
          blocked_issues: blockedIssues,
        };
      } catch (error) {
        const errorMessage = error instanceof Error ? error.message : String(error);
        logger.error({ owner, repo, error: errorMessage }, 'Failed to check blocked issues');
    
        return {
          success: false,
          blocked_issues: [],
          error: errorMessage,
        };
      }
    }
  • MCP tool registration for 'gitea_workflow_check_blocked', defining title, description, Zod input schema, and wrapper handler that invokes the core workflowCheckBlocked function from workflow.ts.
    mcpServer.registerTool(
      'gitea_workflow_check_blocked',
      {
        title: '检测阻塞 Issue',
        description:
          'Detect issues that are blocked or exceeding SLA. Checks for stale issues based on priority-specific time limits.',
        inputSchema: z.object({
          owner: z.string().optional().describe('Repository owner. Uses context if not provided'),
          repo: z.string().optional().describe('Repository name. Uses context if not provided'),
          threshold_hours: z.number().optional().describe('Override default SLA hours threshold'),
        }),
      },
      async (args) => {
        try {
          const result = await WorkflowTools.workflowCheckBlocked(
            { client: ctx.client, contextManager: ctx.contextManager },
            args
          );
          return {
            content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }],
            isError: !result.success,
          };
        } catch (error: unknown) {
          const errorMessage = error instanceof Error ? error.message : String(error);
          return {
            content: [{ type: 'text' as const, text: `Error: ${errorMessage}` }],
            isError: true,
          };
        }
      }
    );
  • Zod input schema validation for the tool parameters: optional owner/repo (resolved from context), and optional threshold_hours to override SLA.
      inputSchema: z.object({
        owner: z.string().optional().describe('Repository owner. Uses context if not provided'),
        repo: z.string().optional().describe('Repository name. Uses context if not provided'),
        threshold_hours: z.number().optional().describe('Override default SLA hours threshold'),
      }),
    },

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/SupenBysz/gitea-mcp-tool'

If you have feedback or need assistance with the MCP directory API, please join our Discord server