Skip to content

[rust-guard] Rust Guard: Dedup governance_tools test array + add COMMENT_NODE_ID constant #12952

Description

@github-actions

🦀 Rust Guard Improvement Report

Improvement 1: Extract duplicated governance_tools test array into a shared constant

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

Problem

The four-element array ["repository_ruleset_read", "custom_properties_read", "custom_properties_write", "create_repository_ruleset"] is copy-pasted verbatim in three separate test functions:

  • apply_tool_labels_repo_governance_tools_are_scoped (line ~1718, as let governance_tools = [...])
  • apply_tool_labels_governance_tools_are_repo_scoped (line ~1950, as &[...] inline)
  • apply_tool_labels_governance_tools_are_org_and_enterprise_scoped (line ~1977, as &[...] inline)

This mirrors the exact pattern already fixed for the [labels, milestones, branches] method group on 2026-09-02 — the same duplication risk exists here: if a new governance tool (e.g. delete_repository_ruleset) is added to the production match arm at line 729/842, these three test lists must be updated in three places, and it's easy to miss one, silently leaving new tools untested.

Suggested Change

Add a pub(crate) const GOVERNANCE_TOOLS array (test-only, #[cfg(test)]) near the top of the mod tests block in tool_rules.rs, and reference it from all three test functions instead of repeating the literal array.

Before

    #[test]
    fn apply_tool_labels_repo_governance_tools_are_scoped() {
        // ...
        let governance_tools = [
            "repository_ruleset_read",
            "custom_properties_read",
            "custom_properties_write",
            "create_repository_ruleset",
        ];
        for tool in governance_tools {
        // ...

    #[test]
    fn apply_tool_labels_governance_tools_are_repo_scoped() {
        // ...
        for tool in &[
            "repository_ruleset_read",
            "custom_properties_read",
            "custom_properties_write",
            "create_repository_ruleset",
        ] {
        // ...

    #[test]
    fn apply_tool_labels_governance_tools_are_org_and_enterprise_scoped() {
        // ...
            for tool in &[
                "repository_ruleset_read",
                "custom_properties_read",
                "custom_properties_write",
                "create_repository_ruleset",
            ] {

After

#[cfg(test)]
mod tests {
    use super::*;
    // ... existing use statements ...

    /// Tools routed through `apply_governance_labels` (repo/org/enterprise-scoped
    /// governance metadata reads and writes). Shared across the three governance
    /// test functions below to avoid drift when a new governance tool is added.
    const GOVERNANCE_TOOLS: [&str; 4] = [
        "repository_ruleset_read",
        "custom_properties_read",
        "custom_properties_write",
        "create_repository_ruleset",
    ];

    #[test]
    fn apply_tool_labels_repo_governance_tools_are_scoped() {
        // ...
        for tool in GOVERNANCE_TOOLS {
        // ...

    #[test]
    fn apply_tool_labels_governance_tools_are_repo_scoped() {
        // ...
        for tool in &GOVERNANCE_TOOLS {
        // ...

    #[test]
    fn apply_tool_labels_governance_tools_are_org_and_enterprise_scoped() {
        // ...
            for tool in &GOVERNANCE_TOOLS {

Why This Matters

Eliminates a 3-way copy-pasted literal in test code. Future governance tools only need to be added to one array to get coverage in all three scope-variant tests (repo, org/enterprise, and public/private secrecy), removing a source of silent test-coverage gaps.


Improvement 2: Add field_names::COMMENT_NODE_ID constant for the raw "commentNodeID" literal

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

Problem

The raw string literal "commentNodeID" is used at 4 production sites (lines ~865, 875, 893, 903, all .get("commentNodeID") calls in the discussion_comment_write and pull_request_review_write match arms) and 4 more sites in tests (lines ~1392, 1424, 1448, 2964). This follows the same pattern already centralized for method, full_name, login, isError, etc. in field_names — a typo in any one copy (e.g. "commentNodeId" or "comment_node_id") would silently produce an empty node ID and mis-scope the secrecy/integrity labels for GraphQL-only discussion/PR-review mutations.

Suggested Change

Add pub const COMMENT_NODE_ID: &str = "commentNodeID"; to the field_names module in constants.rs, then replace all 4 production .get("commentNodeID") call sites in tool_rules.rs with .get(field_names::COMMENT_NODE_ID).

Before

// labels/constants.rs — field_names module
pub mod field_names {
    // ...
    pub const IS_ERROR: &str = "isError";
}
// labels/tool_rules.rs — discussion_comment_write arm
if repo_id.is_empty() {
    baseline_scope = Cow::Owned(format!(
        "node/{}",
        tool_args
            .get("commentNodeID")
            .and_then(|v| v.as_str())
            .unwrap_or("")
    ));
}
apply_dispatch_repo_labels(
    &owner,
    &repo,
    repo_id,
    tool_args
        .get("commentNodeID")
        .and_then(|v| v.as_str())
        .unwrap_or(""),
    &mut secrecy,
    &mut integrity,
    ctx,
);

After

// labels/constants.rs — field_names module
pub mod field_names {
    // ...
    pub const IS_ERROR: &str = "isError";
    pub const COMMENT_NODE_ID: &str = "commentNodeID";
}
// labels/tool_rules.rs — discussion_comment_write arm
if repo_id.is_empty() {
    baseline_scope = Cow::Owned(format!(
        "node/{}",
        tool_args
            .get(field_names::COMMENT_NODE_ID)
            .and_then(|v| v.as_str())
            .unwrap_or("")
    ));
}
apply_dispatch_repo_labels(
    &owner,
    &repo,
    repo_id,
    tool_args
        .get(field_names::COMMENT_NODE_ID)
        .and_then(|v| v.as_str())
        .unwrap_or(""),
    &mut secrecy,
    &mut integrity,
    ctx,
);

(Same replacement applies to the two .get("commentNodeID") calls in the pull_request_review_write arm just below.)

Why This Matters

Removes 4 duplicate raw-string field-name literals from production logic that directly drives DIFC label scoping for discussion/PR-review node-ID dispatch, matching the existing field_names centralization convention and eliminating a typo-based silent-failure risk.


Codebase Health Summary

  • Total Rust files: 9
  • Total lines: ~21,623 (lib.rs 1860, tools.rs 925, labels/mod.rs 6901, labels/backend.rs 1796, labels/helpers.rs 4739, labels/tool_rules.rs 3110, labels/response_items.rs 637, labels/response_paths.rs 1426, labels/constants.rs 229)
  • Areas analyzed: labels/tool_rules.rs (governance test duplication, commentNodeID literals), labels/constants.rs (field_names candidates), labels/backend.rs & labels/mod.rs (unwrap() usage — no new unsafe patterns found beyond previously-reviewed call sites), Cargo.toml (release profile — no issues)
  • Areas with no further improvements: none newly exhausted this run

Generated by Rust Guard Improver • Run: 34583399051

Generated by Rust Guard Improver · copilot · auto · 59.4 AIC · ⊞ 10.1K · ◷

  • expires on Sep 18, 2026, 9:21 AM UTC

Activity

  1. added a commit that references this issue on Sep 11, 2026
    e3ed75a
  2. github-actions commented on Sep 11, 2026

    @github-actions
    ContributorAuthor

    🤖 This is an automated response from Repo Assist.

    Implemented both suggested improvements in a draft PR: #aw_gov1

    • Added test-only GOVERNANCE_TOOLS const shared by the three governance test functions.
    • Added field_names::COMMENT_NODE_ID constant and replaced all 4 production .get("commentNodeID") call sites.

    cargo build/cargo test (666/666)/cargo clippy all pass clean.

    Generated by Repo Assist · copilot · auto · 120.5 AIC · ⊞ 16.4K · ◷
    Comment /repo-assist to run again

    Add this agentic workflow to your repo

    To install this agentic workflow, run

    gh aw add githubnext/agentics/workflows/repo-assist.md@851905c06e905bf362a9f6cc54f912e3df747d55
    
  3. added 2 commits that reference this issue on Sep 11, 2026
    0db9218
    276c5c5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions