Skip to content

chnsz/checkdeleted-input-errors-formating

Use this GitHub action with your project
Add this Action to an existing workflow or create a new one
View on Marketplace

Repository files navigation

Error Format Tracing Tool

A tool for checking whether the error argument passed to CheckDeletedDiag method in Terraform Provider code has been formatted. Formatting errors corrupts the original error type, preventing effective error recognition.

Project Structure

checkdeleted-input-errors-formating/
├── check_error_format.py     # Main entry point
├── README.md                 # Documentation
├── LICENSE                   # License
├── .github/                  # GitHub Actions workflows
│   └── workflows/
│       └── check-error-format.yml
├── tools/                    # Tool scripts directory
│   ├── en-us/                # English tool scripts
│   │   └── quick_install.sh  # Quick install script (English)
│   └── zh-cn/                # Chinese tool scripts
│       └── quick_install.sh  # Quick install script (Chinese)
└── rules/                    # Rules directory
    ├── __init__.py
    ├── base_rule.py          # Base rule class
    └── cq_rules/             # Code quality rules
        ├── __init__.py
        ├── rule_001.py       # CQ.001 rule implementation
        ├── go_ast_parser.go  # Go AST parser source code
        └── go_ast_parser     # Compiled Go AST parser executable

Rule System

The project adopts a rule-based architecture, where each code quality rule is an independent class:

  • Base Rule Class (rules/base_rule.py): Defines the interface that all rules must implement
  • CQ.001 Rule (rules/cq_rules/rule_001.py): Checks whether the error parameter of the CheckDeletedDiag method is formatted

Current Rules

CQ.001: Prohibiting Formatting of the error Argument of the CheckDeletedDiag Method

This rule checks whether the error parameter used by the common.CheckDeletedDiag method in Terraform Provider code is formatted. If the error parameter is formatted (e.g., using fmt.Errorf), it will corrupt the original error type, causing the method to fail to effectively recognize the error content.

Detection Scope:

  • Only checks CheckDeletedDiag calls within ReadContext methods (functions matching resourceXXXRead or dataSourceXXXRead pattern)
  • Ignores calls in other methods like DeleteContext, CreateContext, etc.

Detection Logic:

  • Traces the error variable from CheckDeletedDiag call back to its source function
  • Verifies that the error actually reaches CheckDeletedDiag (not handled via diag.FromErr or diag.Errorf earlier)
  • Checks if the source function formats the error using fmt.Errorf or similar patterns

Problem Description

In Terraform Provider code, the common.CheckDeletedDiag method is used to check whether a resource has been deleted. If the error parameter passed in is formatted (e.g., using fmt.Errorf), it will corrupt the original error type, causing the method to fail to effectively recognize the error content (e.g., 404 errors).

Features

The tool provides:

  1. Accurate Function Extraction: Uses Go AST parser for robust function definition extraction
  2. Error Flow Tracing: Traces error variables from CheckDeletedDiag calls back to their source functions
  3. False Positive Prevention: Verifies errors actually reach CheckDeletedDiag and filters out errors handled earlier
  4. Context-Aware Detection: Only checks ReadContext methods, ignoring other contexts
  5. High Performance: Parallel processing with file caching for fast analysis of large codebases
  6. Progress Control: Optional progress output for debugging and monitoring

Usage

Command-Line Options

error-format-check -d <directory_or_file> [-p <true|false>]
  • -d, --directory <directory_or_file>: Target directory or Go file to check (required)
  • -p, --process <true|false>: Whether to show progress information (default: false)
  • -h, --help: Show help message and exit

Quick Installation (Recommended)

Use the one-click installation script to quickly deploy the tool locally:

English Version:

curl -fsSL https://raw.githubusercontent.com/chnsz/checkdeleted-input-errors-formating/master/tools/en-us/quick_install.sh | bash

Chinese Version:

curl -fsSL https://raw.githubusercontent.com/chnsz/checkdeleted-input-errors-formating/master/tools/zh-cn/quick_install.sh | bash

After installation, the tool will be installed to ~/.local/bin/error-format-check and the PATH environment variable will be automatically configured.

Note: If the command is not available after installation, run source ~/.bashrc (or source ~/.zshrc) to refresh the environment variables, or reopen the terminal.

Usage Examples

Basic usage (silent mode, default):

error-format-check -d /path/to/terraform-provider-huaweicloud
error-format-check -d ./huaweicloud/services/fgs
error-format-check -d /path/to/file.go

With progress output:

error-format-check -d /path/to/dir -p true

Show help:

error-format-check --help

Manual Installation

If you need to install manually:

  1. Clone the repository:
git clone https://github.com/chnsz/checkdeleted-input-errors-formating.git
cd checkdeleted-input-errors-formating
  1. Build Go AST parser (optional but recommended):
cd rules/cq_rules
go build -o go_ast_parser go_ast_parser.go
cd ../..
  1. Run the tool:
python3 check_error_format.py -d <directory_or_file> [-p <true|false>]

Note: If the Go AST parser is not available, the tool will automatically fall back to regex-based function extraction.

GitHub Actions

The tool can be run in GitHub Actions workflows.

For integrating this tool into other repositories, see:

For publishing to GitHub Actions Marketplace, see:

For examples in this repository, see .github/workflows/check-error-format.yml.

Using as a GitHub Action (once published to Marketplace):

- name: Check Error Format
  uses: chnsz/[email protected]
  with:
    directory: '.'
    show-progress: 'false'

The workflow:

  • Automatically builds the Go AST parser
  • Runs the check on the target repository
  • Only fails if there are tool execution errors (compilation/syntax errors)
  • Succeeds even if issues are found (displays results without failing the workflow)

Output Format

When issues are found, the tool will output:

================================================================================
ERROR - Issues found:
================================================================================
Error - <relative_file_path> (line <line_number>): Formatting the `error` argument of the `CheckDeleted` method is prohibited. It will corrupt the original error type, causing the method to fail to effectively recognize the error content.

Total: <count> issue(s) found

When no issues are found (with -p true):

✓ No issues found!

Detection Rules

The tool detects the following formatting patterns in source functions:

  • fmt.Errorf(...) used in return statements
  • fmt.Sprintf(...) + errors.New(...) combinations
  • Other error formatting patterns

Important: The tool only checks functions that provide errors to CheckDeletedDiag calls within ReadContext methods. Errors handled via diag.FromErr or diag.Errorf before reaching CheckDeletedDiag are ignored.

Technical Details

Function Extraction

The tool uses Go's AST parser (go/parser and go/ast) for accurate function definition extraction:

  • Advantages: Handles complex Go syntax correctly (nested functions, string literals, etc.)
  • Fallback: Automatically falls back to regex-based extraction if AST parser is unavailable
  • Performance: Compiled Go binary provides fast parsing

Performance Optimizations

  • Parallel Processing: Uses ThreadPoolExecutor for concurrent file processing
  • File Caching: Caches file contents to avoid redundant I/O operations
  • Optimized Lookups: Efficient function lookup algorithms
  • Result: Processes 3,340+ files in ~13.6 seconds

Error Tracing Logic

  1. Finds all CheckDeletedDiag calls in ReadContext methods
  2. Traces the error variable back to its source function
  3. Verifies the error actually reaches CheckDeletedDiag (not handled earlier)
  4. Checks if the source function formats the error
  5. Reports issues with accurate line numbers

Examples

Problematic Code

func GetV2AlarmRule(client *golangsdk.ServiceClient, alarmRuleId string) (interface{}, error) {
    getResp, err := client.Request("GET", getPath, &getOpt)
    if err != nil {
        return nil, fmt.Errorf("error getting the alarm rule: %s", err)  // ❌ Error formatted
    }
    // ...
}

func resourceAlarmRuleRead(_ context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
    // ...
    alarmRule, err := GetV2AlarmRule(client, d.Id())
    if err != nil {
        return common.CheckDeletedDiag(d, err, "alarm rule")  // Error from GetV2AlarmRule is formatted
    }
    // ...
}

The above code will be detected as problematic because the GetV2AlarmRule function uses fmt.Errorf to format the error before it's passed to CheckDeletedDiag.

Correct Code

func GetV2AlarmRule(client *golangsdk.ServiceClient, alarmRuleId string) (interface{}, error) {
    getResp, err := client.Request("GET", getPath, &getOpt)
    if err != nil {
        return nil, err  // ✅ Return the original error directly without formatting
    }
    // ...
}

Code That Won't Be Detected

func bindAclPolicyToApis(client *golangsdk.ServiceClient, policyId string, apiIds []string) error {
    // ...
    if err != nil {
        return fmt.Errorf("error binding ACL policy: %s", err)  // This won't be detected
    }
    // ...
}

func resourceAclPolicyAssociateCreate(_ context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
    // ...
    err := bindAclPolicyToApis(client, policyId, apiIds)
    if err != nil {
        return diag.FromErr(err)  // Error is handled here, not passed to CheckDeletedDiag
    }
    // ...
}

The above code won't be detected because the error is handled via diag.FromErr before it could reach CheckDeletedDiag.

Adding New Rules

To add a new code quality rule:

  1. Create a new rule file in the rules/cq_rules/ directory (e.g., rule_002.py)
  2. Inherit the BaseRule class and implement the check() method
  3. Register the new rule in check_error_format.py

Example:

from rules.base_rule import BaseRule, Issue
from pathlib import Path
from typing import List

class Rule002(BaseRule):
    def __init__(self, show_progress: bool = False):
        super().__init__(
            rule_id="CQ.002",
            rule_name="Rule Name",
            description="Rule Description"
        )
        self.show_progress = show_progress
    
    def check(self, root_dir: Path) -> List[Issue]:
        # Implement check logic
        # Use self.add_issue() to add issues
        return self.get_issues()

Then register it in check_error_format.py:

rules = [
    Rule001(show_progress=show_progress),
    Rule002(show_progress=show_progress),  # Add new rule
]

Dependencies

  • Python: 3.10+ (uses only Python standard library)
  • Go: 1.19+ (optional, for building Go AST parser)

The tool uses only Python standard library modules:

  • argparse - Command-line argument parsing
  • concurrent.futures - Parallel processing
  • pathlib - Path handling
  • subprocess - Calling Go AST parser
  • json - Parsing AST parser output
  • re - Regular expressions (fallback mode)

License

See LICENSE file.

About

Detects formatted errors passed to CheckDeletedDiag in Terraform Provider code to prevent error type corruption.

Resources

License

Stars

Watchers

Forks

Packages

No packages published