-
Notifications
You must be signed in to change notification settings - Fork 0
Added checkstyle configuration generator as an option to config generator #36
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -2,33 +2,58 @@ | |||||||||||||
| import argparse | ||||||||||||||
| import requests | ||||||||||||||
| import json | ||||||||||||||
| import re | ||||||||||||||
| from pprint import pprint | ||||||||||||||
| import yaml | ||||||||||||||
| import xml.etree.ElementTree as ET | ||||||||||||||
|
Check failure on line 6 in config_file_generator.py
|
||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The issue identified by the Prospector linter relates to the use of the To address this security concern, you can replace the import statement of
Suggested change
This comment was generated by an experimental AI tool. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ❌ Codacy found a critical Security issue: The Python documentation recommends using The issue identified by the Semgrep linter pertains to the use of the To fix the issue, you should replace the import statement for the standard XML library with the import statement for the
Suggested change
This comment was generated by an experimental AI tool. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The issue identified by the Bandit linter is related to the use of the To fix the issue, you can replace the import statement for
Suggested change
This comment was generated by an experimental AI tool. |
||||||||||||||
| from xml.dom import minidom | ||||||||||||||
|
Check failure on line 7 in config_file_generator.py
|
||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The issue identified by the Prospector linter is related to the use of the To mitigate this risk, the recommended approach is to use the To address this, we can replace the import statement for
Suggested change
This comment was generated by an experimental AI tool. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ❌ Codacy found a critical Security issue: The Python documentation recommends using The issue identified by the Semgrep linter pertains to the potential vulnerability of the native Python To fix the issue, you should replace the import statement for the
Suggested change
This comment was generated by an experimental AI tool. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The issue identified by the Bandit linter is related to the use of the To fix the issue, you can replace the import of Here's the suggested single line change:
Suggested change
This comment was generated by an experimental AI tool. |
||||||||||||||
| import sys | ||||||||||||||
|
|
||||||||||||||
| def get_repositories(baseurl, provider, organization, token): | ||||||||||||||
| headers = { | ||||||||||||||
| 'Accept': 'application/json', | ||||||||||||||
| 'api-token': token | ||||||||||||||
| } | ||||||||||||||
| url = f'{baseurl}/api/v3/organizations/{provider}/{organization}/repositories' | ||||||||||||||
| r = requests.get(url, headers=headers) | ||||||||||||||
|
Check warning on line 16 in config_file_generator.py
|
||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The issue identified by the Semgrep linter is that the To address this issue, you should specify a timeout value in the Here is the code suggestion to fix the issue:
Suggested change
This comment was generated by an experimental AI tool. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The issue identified by the Bandit linter is that the To fix this issue, you can add a
Suggested change
In this example, a timeout of 10 seconds is specified, but you can adjust this value as needed based on your application's requirements. This comment was generated by an experimental AI tool. |
||||||||||||||
| r.raise_for_status() | ||||||||||||||
| repositories = r.json() | ||||||||||||||
| if len(repositories['data']) == 0: | ||||||||||||||
| raise Exception(f'No repositories found for org {organization}') | ||||||||||||||
| return repositories['data'] | ||||||||||||||
|
|
||||||||||||||
| def select_repository(repositories): | ||||||||||||||
| print("\nAvailable repositories:") | ||||||||||||||
| for i, repo in enumerate(repositories, 1): | ||||||||||||||
| print(f"{i}. {repo['name']}") | ||||||||||||||
|
|
||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ℹ️ Codacy found a minor CodeStyle issue: Trailing whitespace The issue identified by Pylint is a "Trailing whitespace" problem, which means that there is unnecessary whitespace (spaces or tabs) at the end of a line. This can lead to inconsistent formatting and is generally discouraged in Python code as it can affect readability and maintainability. To fix the issue, you should remove any trailing whitespace from the line in question. Assuming the line with trailing whitespace is the last line of the provided code fragment, the suggested change would be:
Suggested change
This comment was generated by an experimental AI tool. |
||||||||||||||
| while True: | ||||||||||||||
| try: | ||||||||||||||
| choice = int(input("\nEnter the number of the repository you want to use: ")) | ||||||||||||||
| if 1 <= choice <= len(repositories): | ||||||||||||||
| return repositories[choice - 1] | ||||||||||||||
| else: | ||||||||||||||
| print("Invalid selection. Please try again.") | ||||||||||||||
| except ValueError: | ||||||||||||||
| print("Please enter a valid number.") | ||||||||||||||
|
|
||||||||||||||
| #TODO: only returns the first one | ||||||||||||||
| def getCodingStandards(baseurl, provider, organization, token): | ||||||||||||||
| def list_tools(baseurl, token): | ||||||||||||||
| headers = { | ||||||||||||||
| 'Accept': 'application/json', | ||||||||||||||
| 'api-token': token | ||||||||||||||
| } | ||||||||||||||
| url = f'{baseurl}/api/v3/organizations/{provider}/{organization}/coding-standards' | ||||||||||||||
| url = f'{baseurl}/api/v3/tools' | ||||||||||||||
| r = requests.get(url, headers=headers) | ||||||||||||||
| codingStandards = json.loads(r.text) | ||||||||||||||
| if len(codingStandards['data']) == 0: | ||||||||||||||
| raise Exception(f'No Coding Standards for org {organization}') | ||||||||||||||
| return codingStandards['data'][0] | ||||||||||||||
| r.raise_for_status() | ||||||||||||||
| return r.json() | ||||||||||||||
|
|
||||||||||||||
| def getCodePatternsForTool(baseurl, provider, organization,codingStandardId, toolUuid, token): | ||||||||||||||
| def getCodePatternsForTool(baseurl, provider, organization, repository, toolUuid, token): | ||||||||||||||
| headers = { | ||||||||||||||
| 'Accept': 'application/json', | ||||||||||||||
| 'api-token': token | ||||||||||||||
| } | ||||||||||||||
| url = f'{baseurl}/api/v3/organizations/{provider}/{organization}/coding-standards/{codingStandardId}/tools/{toolUuid}/patterns?limit=1000' | ||||||||||||||
| url = f'{baseurl}/api/v3/analysis/organizations/{provider}/{organization}/repositories/{repository}/tools/{toolUuid}/patterns' | ||||||||||||||
| r = requests.get(url, headers=headers) | ||||||||||||||
| patterns = json.loads(r.text)["data"] | ||||||||||||||
| return patterns | ||||||||||||||
| r.raise_for_status() | ||||||||||||||
| return r.json() | ||||||||||||||
|
|
||||||||||||||
| def generateFileForPMD(patterns): | ||||||||||||||
| rules = [] | ||||||||||||||
|
|
@@ -57,29 +82,130 @@ | |||||||||||||
| </description> | ||||||||||||||
| {rules} | ||||||||||||||
| </ruleset>'''.format(rules=''.join(rules)) | ||||||||||||||
| f = open("ruleset.xml", "a") | ||||||||||||||
| f.write(document) | ||||||||||||||
| f.close() | ||||||||||||||
| with open("pmd_ruleset.xml", "w") as f: | ||||||||||||||
| f.write(document) | ||||||||||||||
| print("PMD configuration has been saved to pmd_ruleset.xml") | ||||||||||||||
|
|
||||||||||||||
| def generateFileForSemgrep(patterns): | ||||||||||||||
| rules = [] | ||||||||||||||
| for p in patterns: | ||||||||||||||
| if p['enabled']: | ||||||||||||||
| pattern = p['patternDefinition'] | ||||||||||||||
| rule = { | ||||||||||||||
| "id": f"Semgrep_codacy.{pattern['id']}", | ||||||||||||||
| "pattern": pattern.get('pattern', ''), | ||||||||||||||
| "message": pattern.get('description', ''), | ||||||||||||||
| "severity": p.get('severity', 'WARNING').lower(), | ||||||||||||||
| "languages": pattern.get('languages', []), | ||||||||||||||
| } | ||||||||||||||
| if p["parameters"]: | ||||||||||||||
| rule["parameters"] = p["parameters"] | ||||||||||||||
| rules.append(rule) | ||||||||||||||
|
|
||||||||||||||
| config = {"rules": rules} | ||||||||||||||
| with open("semgrep_config.yaml", "w") as f: | ||||||||||||||
| yaml.dump(config, f, default_flow_style=False) | ||||||||||||||
| print("Semgrep configuration has been saved to semgrep_config.yaml") | ||||||||||||||
|
|
||||||||||||||
| def generateFileForCheckstyle(patterns): | ||||||||||||||
| root = ET.Element("module", name="Checker") | ||||||||||||||
| tree_walker = ET.SubElement(root, "module", name="TreeWalker") | ||||||||||||||
|
|
||||||||||||||
| for p in patterns: | ||||||||||||||
| if p['enabled']: | ||||||||||||||
| pattern = p['patternDefinition'] | ||||||||||||||
| module = ET.SubElement(tree_walker, "module", name=pattern['id'].replace('Checkstyle_', '')) | ||||||||||||||
| ET.SubElement(module, "property", name="severity", value=p.get('severity', 'warning')) | ||||||||||||||
| for param in p["parameters"]: | ||||||||||||||
| ET.SubElement(module, "property", name=param["name"], value=str(param["value"])) | ||||||||||||||
|
|
||||||||||||||
| xml_declaration = '<?xml version="1.0"?>' | ||||||||||||||
| doctype = '<!DOCTYPE module PUBLIC "-//Checkstyle//DTD Checkstyle Configuration 1.3//EN" "https://checkstyle.org/dtds/configuration_1_3.dtd">' | ||||||||||||||
|
|
||||||||||||||
| rough_string = ET.tostring(root, 'unicode') | ||||||||||||||
| reparsed = minidom.parseString(rough_string) | ||||||||||||||
|
Check warning on line 126 in config_file_generator.py
|
||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The issue identified by the Prospector linter is related to the use of To fix the issue, you can replace the Here is the suggested code change:
Suggested change
This comment was generated by an experimental AI tool. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The issue identified by the Semgrep linter relates to the use of the To address this security concern, it is recommended to use a more secure XML parsing library, such as Here’s the suggested change to replace
Suggested change
This change assumes you have imported This comment was generated by an experimental AI tool. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The issue identified by the Bandit linter pertains to the use of To mitigate this risk, it is recommended to use the To fix the issue, you can replace the Here's the single line change needed:
Suggested change
This comment was generated by an experimental AI tool. |
||||||||||||||
| pretty_xml = reparsed.toprettyxml(indent=" ") | ||||||||||||||
|
|
||||||||||||||
| # Remove the XML declaration from the pretty-printed XML | ||||||||||||||
| pretty_xml_lines = pretty_xml.splitlines(True) | ||||||||||||||
| pretty_xml_without_declaration = ''.join(pretty_xml_lines[1:]) | ||||||||||||||
|
|
||||||||||||||
| with open("checkstyle_config.xml", "w", encoding="utf-8") as f: | ||||||||||||||
| f.write(f"{xml_declaration}{doctype}\n{pretty_xml_without_declaration}") | ||||||||||||||
|
|
||||||||||||||
| print("Checkstyle configuration has been saved to checkstyle_config.xml") | ||||||||||||||
|
|
||||||||||||||
| def main(): | ||||||||||||||
| print('Welcome to Codacy Config File Generator - A temporary solution') | ||||||||||||||
| print('!!!!!! CURRENTLY ONLY WORKS FOR PMD !!!!!!') | ||||||||||||||
| print('Welcome to Codacy Config File Generator') | ||||||||||||||
| parser = argparse.ArgumentParser(description='Codacy Engine Helper') | ||||||||||||||
| parser.add_argument('--token', dest='token', default=None, | ||||||||||||||
| parser.add_argument('--token', dest='token', required=True, | ||||||||||||||
| help='the api-token to be used on the REST API') | ||||||||||||||
| parser.add_argument('--provider', dest='provider', | ||||||||||||||
| default=None, help='git provider') | ||||||||||||||
| parser.add_argument('--organization', dest='organization', | ||||||||||||||
| default=None, help='organization id') | ||||||||||||||
| parser.add_argument('--tooluuid', dest='toolUuid', | ||||||||||||||
| default=None, help='Tool Uuid') | ||||||||||||||
| parser.add_argument('--provider', dest='provider', required=True, | ||||||||||||||
| help='git provider') | ||||||||||||||
| parser.add_argument('--organization', dest='organization', required=True, | ||||||||||||||
| help='organization id') | ||||||||||||||
| parser.add_argument('--baseurl', dest='baseurl', default='https://app.codacy.com', | ||||||||||||||
| help='codacy server address (ignore if cloud)') | ||||||||||||||
| args = parser.parse_args() | ||||||||||||||
| cs = getCodingStandards(args.baseurl, args.provider, args.organization, args.token) | ||||||||||||||
| patterns = getCodePatternsForTool(args.baseurl, args.provider, args.organization, cs["id"], args.toolUuid, args.token) | ||||||||||||||
|
|
||||||||||||||
| #TODO: decide what's the tool, currently only pmd | ||||||||||||||
| generateFileForPMD(patterns) | ||||||||||||||
| main() | ||||||||||||||
| try: | ||||||||||||||
| repositories = get_repositories(args.baseurl, args.provider, args.organization, args.token) | ||||||||||||||
| selected_repo = select_repository(repositories) | ||||||||||||||
| print(f"Selected repository: {selected_repo['name']}") | ||||||||||||||
|
|
||||||||||||||
| tools = list_tools(args.baseurl, args.token) | ||||||||||||||
| tool_uuids = {tool['name'].lower(): tool['uuid'] for tool in tools['data']} | ||||||||||||||
|
|
||||||||||||||
| except requests.exceptions.RequestException as e: | ||||||||||||||
| print(f"Error fetching data: {e}") | ||||||||||||||
| sys.exit(1) | ||||||||||||||
| except Exception as e: | ||||||||||||||
| print(f"Unexpected error: {e}") | ||||||||||||||
| sys.exit(1) | ||||||||||||||
|
|
||||||||||||||
| print("\nSelect an option:") | ||||||||||||||
| print("1. Generate PMD Config") | ||||||||||||||
| print("2. Generate Semgrep Config") | ||||||||||||||
| print("3. Generate Checkstyle Config") | ||||||||||||||
| print("4. Generate all config files") | ||||||||||||||
| print("5. Exit") | ||||||||||||||
|
|
||||||||||||||
| choice = input("Enter your choice (1-5): ") | ||||||||||||||
|
|
||||||||||||||
| try: | ||||||||||||||
| if choice == '1': | ||||||||||||||
| patterns = getCodePatternsForTool(args.baseurl, args.provider, args.organization, selected_repo['name'], tool_uuids['pmd'], args.token) | ||||||||||||||
| generateFileForPMD(patterns['data']) | ||||||||||||||
| elif choice == '2': | ||||||||||||||
| patterns = getCodePatternsForTool(args.baseurl, args.provider, args.organization, selected_repo['name'], tool_uuids['semgrep'], args.token) | ||||||||||||||
| generateFileForSemgrep(patterns['data']) | ||||||||||||||
| elif choice == '3': | ||||||||||||||
| patterns = getCodePatternsForTool(args.baseurl, args.provider, args.organization, selected_repo['name'], tool_uuids['checkstyle'], args.token) | ||||||||||||||
| generateFileForCheckstyle(patterns['data']) | ||||||||||||||
| elif choice == '4': | ||||||||||||||
| for tool, uuid in tool_uuids.items(): | ||||||||||||||
| if tool in ['pmd', 'semgrep', 'checkstyle']: | ||||||||||||||
| patterns = getCodePatternsForTool(args.baseurl, args.provider, args.organization, selected_repo['name'], uuid, args.token) | ||||||||||||||
| if tool == "pmd": | ||||||||||||||
| generateFileForPMD(patterns['data']) | ||||||||||||||
| elif tool == "semgrep": | ||||||||||||||
| generateFileForSemgrep(patterns['data']) | ||||||||||||||
| elif tool == "checkstyle": | ||||||||||||||
| generateFileForCheckstyle(patterns['data']) | ||||||||||||||
| elif choice == '5': | ||||||||||||||
| print("Exiting the program.") | ||||||||||||||
| sys.exit(0) | ||||||||||||||
| else: | ||||||||||||||
| print("Invalid choice. Exiting the program.") | ||||||||||||||
| sys.exit(1) | ||||||||||||||
| except requests.exceptions.RequestException as e: | ||||||||||||||
| print(f"Error fetching patterns: {e}") | ||||||||||||||
| sys.exit(1) | ||||||||||||||
| except Exception as e: | ||||||||||||||
| print(f"Unexpected error: {e}") | ||||||||||||||
| sys.exit(1) | ||||||||||||||
|
|
||||||||||||||
| print("Config file(s) generated successfully. Exiting the program.") | ||||||||||||||
|
|
||||||||||||||
| if __name__ == "__main__": | ||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ℹ️ Codacy found a minor CodeStyle issue: expected 2 blank lines after class or function definition, found 1 (E305) The issue reported by the Prospector linter is related to the PEP 8 style guide, which recommends having two blank lines after the definition of a function or class. In this case, the line To fix this issue, you should add an additional blank line before the Here's the code suggestion to fix the issue: print("Config file(s) generated successfully. Exiting the program.")
if __name__ == "__main__":This comment was generated by an experimental AI tool. |
||||||||||||||
| main() | ||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ℹ️ Codacy found a minor CodeStyle issue: camelcase 'xml.etree.ElementTree' imported as acronym 'ET' (N817)
The issue reported by the Prospector linter is that the module
xml.etree.ElementTreeis being imported and aliased as the acronymET, which is in camel case. According to PEP 8, module names should be in lowercase, and acronyms should not be capitalized. Therefore, the aliasETis not compliant with the style guide.To fix this issue, you can change the alias to be fully lowercase. Here’s the suggested change:
This comment was generated by an experimental AI tool.