Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gitlab Code Quality report #1116

Open
bhirsz opened this issue Sep 26, 2024 · 1 comment
Open

Gitlab Code Quality report #1116

bhirsz opened this issue Sep 26, 2024 · 1 comment

Comments

@bhirsz
Copy link
Member

bhirsz commented Sep 26, 2024

Add new report that supports Gitlab code quality artifacts: https://docs.gitlab.com/ee/ci/testing/code_quality.html#implement-a-custom-tool

@mathieugouin
Copy link

If it can help, here is how I manually did it:

    # Run robocop linter
    - |
        python -m robocop `
        --configure return_status:quality_gates:E=0:W=-1:I=-1 `
        --reports sarif `
        --configure sarif:report_filename:robocop-report-sarif.json `

Then (I'm on Windows based runner, so you might have to adjust accordingly):

    # Run an inline Python script to format robocop report into gitlab format
    - |
        $pythonCode = @"
        import json
        import hashlib

        # Local functions:
        def read_file_line(filepath: str, line_number: int) -> str:
            try:
                with open(filepath, 'r', encoding='utf-8') as file:
                    for current_line_number, line in enumerate(file, start=1):
                        if current_line_number == line_number:
                            return line.strip('\n\r')
                    # Special case for robocop last line issue
                    if current_line_number + 1 == line_number:
                        return line.strip('\n\r')
                # If the loop completes without finding the line
                raise AssertionError(f'Line {line_number} not found in {filepath}')
            except FileNotFoundError:
                raise FileNotFoundError(f'File not found: {filepath}')
            except Exception as e:
                raise Exception(f'An error occurred: {e}')


        def get_issue_line_content(issue: dict) -> str:
            return read_file_line(
                issue['location']['path'],
                issue['location']['lines']['begin']
                )

        def get_fingerprint(original_issue: dict, line_content: str, differentiator_id: int) -> str:
            issue = {
                'description': original_issue['description'],
                'check_name': original_issue['check_name'],
                # 'fingerprint': original_issue['fingerprint'],  # We don't want this one.
                'severity': original_issue['severity'],
                'location':
                    {
                        'path': original_issue['location']['path'],
                        # 'lines': {'begin': original_issue['location']['lines']['begin']},  # We don't want this one.
                    },
                'line_content': line_content,
                'differentiator_id': differentiator_id,
            }
            return hashlib.sha1(bytes(str(issue), 'utf-8')).hexdigest()

        # Read original sarif report
        report = None
        with open('robocop-report-sarif.json', 'r', encoding='utf-8') as f:
            report = json.load(f)

        fingerprint_list = []
        results = []
        for issue in report['runs'][0]['results']:

            result = {
                'description': issue['message']['text'],
                'check_name': 'robocop:' + issue['ruleId'],
                'severity': issue['level'],
                'location': {
                    'path': issue['locations'][0]['physicalLocation']['artifactLocation']['uri'],
                    'lines': {'begin': issue['locations'][0]['physicalLocation']['region']['startLine']}
                    },
                'fingerprint': 'x',
            }

            line_content = get_issue_line_content(result)
            for i in range(int(1e6)):
                fingerprint = get_fingerprint(result, line_content, i)
                if fingerprint not in fingerprint_list:
                    fingerprint_list.append(fingerprint)
                    result['fingerprint'] = fingerprint  # Overwrite the fingerprint with the one we computed
                    break

            results.append(result)

        with open('robot-gl-codequality.json', 'w', encoding='utf-8') as outfile:
            json.dump(results, outfile, indent=4)
        "@
        python -c $pythonCode

I made it as inline script so I can easily re-use this as a gitlab pipeline template:

include:
  - project: 'xxx/devops/pipeline-templates'
    file: 'robot-lint.yml'
    ref: '1.0.0'  # tag

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants