Skip to content

[rust-guard] Rust Guard: Consolidate 11 identical repo-scoped writer arms in tool_rules.rs #2501

@github-actions

Description

@github-actions

🦀 Rust Guard Improvement Report

Improvement 1: Consolidate 11 Identical Match Arms in tool_rules.rs

Category: Duplication
File(s): guards/github-guard/rust-guard/src/labels/tool_rules.rs
Effort: Small (< 15 min)
Risk: Low

Problem

Eleven separate match arms (covering 17 distinct tool names) in apply_tool_labels all share an identical two-line body:

secrecy = apply_repo_visibility_secrecy(&owner, &repo, repo_id, secrecy, ctx);
integrity = writer_integrity(repo_id, ctx);

The arms are scattered across the file (lines 317–537), separated by unrelated arms, making the match statement ~90 lines longer than necessary. Each arm has its own comment block restating the same pattern ("S = inherits from repo visibility, I = approved").

The 11 arms in question:

Line Tool names
317 actions_get, actions_list
383 get_repository
390 list_branches, list_tags, get_tag
399 list_releases, get_latest_release, get_release_by_tag
408 get_label
448 get_job_logs
456 list_discussions, get_discussion
464 get_discussion_comments
472 list_discussion_categories
521 get_repository_tree
530 list_label

Suggested Change

Remove all 11 arms and replace them with a single consolidated arm. The resulting code is easier to scan, and adding a new tool with this pattern becomes a one-line change.

Before

        // === GitHub Actions ===
        "actions_get" | "actions_list" => {
            secrecy = apply_repo_visibility_secrecy(&owner, &repo, repo_id, secrecy, ctx);
            integrity = writer_integrity(repo_id, ctx);
        }

        // ... (many arms omitted) ...

        // === Repository Metadata ===
        "get_repository" => {
            secrecy = apply_repo_visibility_secrecy(&owner, &repo, repo_id, secrecy, ctx);
            integrity = writer_integrity(repo_id, ctx);
        }

        // === Branches & Tags ===
        "list_branches" | "list_tags" | "get_tag" => {
            secrecy = apply_repo_visibility_secrecy(&owner, &repo, repo_id, secrecy, ctx);
            integrity = writer_integrity(repo_id, ctx);
        }

        // ... 8 more identical arms ...

After

        // === Repo-scoped resources: visibility-inherited secrecy, approved integrity ===
        // S = inherits from repo visibility; I = approved (writer-level)
        "actions_get"
        | "actions_list"
        | "get_discussion"
        | "get_discussion_comments"
        | "get_job_logs"
        | "get_label"
        | "get_repository"
        | "get_repository_tree"
        | "get_tag"
        | "list_branches"
        | "list_discussion_categories"
        | "list_discussions"
        | "list_label"
        | "list_releases"
        | "get_latest_release"
        | "get_release_by_tag"
        | "list_tags" => {
            secrecy = apply_repo_visibility_secrecy(&owner, &repo, repo_id, secrecy, ctx);
            integrity = writer_integrity(repo_id, ctx);
        }

Why This Matters

  • Reduces ~90 lines to ~22 lines with no behavior change
  • Makes the distinction between "trivial" and "complex" tool arms instantly visible
  • Eliminates the risk of subtle drift if one arm's body is accidentally changed
  • Adding a new tool with this policy only requires one line in the combined arm

Improvement 2: Extract apply_approval_label_promotion Helper in helpers.rs

Category: Duplication
File(s): guards/github-guard/rust-guard/src/labels/helpers.rs
Effort: Small (< 15 min)
Risk: Low

Problem

Both pr_integrity and issue_integrity end with an identical 13-line block (Step 2: approval-labels promotion). The only difference is the resource-type prefix in the log message ("pr:" vs "issue:"):

// pr_integrity, lines ~1130–1146:
if let Some(label) = first_matching_approval_label(item, ctx) {
    let number = item.get("number").and_then(|v| v.as_u64()).unwrap_or(0);
    crate::log_info(&format!(
        "[integrity] pr:{}#{} promoted to approved (label '{}' in approval-labels)",
        repo_full_name, number, label
    ));
    max_integrity(repo_full_name, integrity, writer_integrity(repo_full_name, ctx), ctx)
} else {
    integrity
}

// issue_integrity, lines ~1221–1237: identical except "issue:" prefix

Suggested Change

Extract a private helper function that takes resource_type: &str as the discriminating parameter:

Before

// (repeated verbatim in both pr_integrity and issue_integrity)
if let Some(label) = first_matching_approval_label(item, ctx) {
    let number = item.get("number").and_then(|v| v.as_u64()).unwrap_or(0);
    crate::log_info(&format!(
        "[integrity] pr:{}#{} promoted to approved (label '{}' in approval-labels)",
        repo_full_name, number, label
    ));
    max_integrity(
        repo_full_name,
        integrity,
        writer_integrity(repo_full_name, ctx),
        ctx,
    )
} else {
    integrity
}

After

/// Apply approval-label promotion: if the item carries a configured approval label,
/// raise integrity to at least writer (approved) level.
fn apply_approval_label_promotion(
    item: &Value,
    resource_type: &str,
    repo_full_name: &str,
    integrity: Vec<String>,
    ctx: &PolicyContext,
) -> Vec<String> {
    if let Some(label) = first_matching_approval_label(item, ctx) {
        let number = item.get("number").and_then(|v| v.as_u64()).unwrap_or(0);
        crate::log_info(&format!(
            "[integrity] {}:{}#{} promoted to approved (label '{}' in approval-labels)",
            resource_type, repo_full_name, number, label
        ));
        max_integrity(repo_full_name, integrity, writer_integrity(repo_full_name, ctx), ctx)
    } else {
        integrity
    }
}

// In pr_integrity (replace the duplicated block):
apply_approval_label_promotion(item, "pr", repo_full_name, integrity, ctx)

// In issue_integrity (replace the duplicated block):
apply_approval_label_promotion(item, "issue", repo_full_name, integrity, ctx)

Why This Matters

  • Eliminates 26 lines of duplicated logic (13 per function)
  • Any future change to the approval-label promotion logic (e.g. adding commit_integrity support later) only requires one edit
  • Makes the overall structure of pr_integrity and issue_integrity more readable by reducing the closing block to a single function call

Codebase Health Summary

  • Total Rust files: 10
  • Total lines: 9,673
  • Areas analyzed: lib.rs, labels/tool_rules.rs, labels/helpers.rs, labels/backend.rs, labels/response_items.rs, labels/response_paths.rs, labels/mod.rs, labels/constants.rs, permissions.rs, tools.rs
  • Areas with no further improvements: labels/constants.rs (clean), tools.rs (clean), labels/mod.rs (clean)

Generated by Rust Guard Improver • Run: §23533837043

Generated by Rust Guard Improver ·

  • expires on Apr 1, 2026, 9:32 AM UTC

Metadata

Metadata

Assignees

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions