2021-02-16 21:21:46 +01:00
|
|
|
import os
|
|
|
|
from typing import Optional
|
2021-05-04 09:58:49 +02:00
|
|
|
from pathlib import Path
|
2021-02-16 21:21:46 +01:00
|
|
|
|
2021-01-29 16:05:22 +01:00
|
|
|
import click
|
2021-02-16 21:21:46 +01:00
|
|
|
from rspec_tools.checklinks import check_html_links
|
2021-06-10 11:03:05 +02:00
|
|
|
from rspec_tools.errors import RuleNotFoundError, RuleValidationError
|
2021-09-30 17:47:25 +02:00
|
|
|
from rspec_tools.create_rule import create_new_rule, add_language_to_rule
|
2022-02-04 17:28:24 +01:00
|
|
|
from rspec_tools.rules import RulesRepository, LanguageSpecificRule
|
2022-01-28 09:51:13 +01:00
|
|
|
from rspec_tools.validation.metadata import validate_rule_metadata
|
2022-02-04 17:28:24 +01:00
|
|
|
from rspec_tools.validation.description import validate_section_names, validate_section_levels, validate_parameters, validate_source_language
|
2021-10-01 14:52:12 +02:00
|
|
|
from rspec_tools.coverage import update_coverage_for_all_repos, update_coverage_for_repo, update_coverage_for_repo_version
|
|
|
|
|
|
|
|
from rspec_tools.notify_failure_on_slack import notify_slack
|
2021-01-29 16:05:22 +01:00
|
|
|
|
|
|
|
@click.group()
|
|
|
|
@click.option('--debug/--no-debug', default=False)
|
|
|
|
def cli(debug):
|
|
|
|
'Tools automating RSPEC workflows.'
|
|
|
|
|
|
|
|
@cli.command()
|
|
|
|
@click.option('--rule', help='Validate only the rule matching the provided ID.')
|
|
|
|
def validate(rule):
|
2021-02-12 15:18:24 +01:00
|
|
|
'''Validate rules.'''
|
|
|
|
# TODO
|
|
|
|
if rule == '42':
|
|
|
|
raise RuleNotFoundError(rule)
|
2021-01-29 16:05:22 +01:00
|
|
|
|
2021-02-12 15:18:24 +01:00
|
|
|
@cli.command()
|
|
|
|
@click.option('--d', required=True)
|
|
|
|
def check_links(d):
|
|
|
|
'''Check links in html.'''
|
|
|
|
check_html_links(d)
|
2021-02-16 21:21:46 +01:00
|
|
|
|
|
|
|
@cli.command()
|
|
|
|
@click.option('--languages', required=True)
|
|
|
|
@click.option('--user', required=False)
|
|
|
|
def create_rule(languages: str, user: Optional[str]):
|
|
|
|
'''Create a new rule.'''
|
|
|
|
token = os.environ.get('GITHUB_TOKEN')
|
2021-06-10 11:03:05 +02:00
|
|
|
create_new_rule(languages, token, user)
|
2021-02-16 21:21:46 +01:00
|
|
|
|
2021-09-30 17:47:25 +02:00
|
|
|
@cli.command()
|
|
|
|
@click.option('--language', required=True)
|
|
|
|
@click.option('--rule', required=True)
|
|
|
|
@click.option('--user', required=False)
|
|
|
|
def add_lang_to_rule(language: str, rule: str, user: Optional[str]):
|
|
|
|
'''Add a new language to rule.'''
|
|
|
|
token = os.environ.get('GITHUB_TOKEN')
|
|
|
|
add_language_to_rule(language, rule, token, user)
|
|
|
|
|
2021-02-23 20:41:11 +01:00
|
|
|
@cli.command()
|
2022-01-28 09:51:13 +01:00
|
|
|
@click.argument('rules', nargs=-1, required=True)
|
2021-02-23 20:41:11 +01:00
|
|
|
def validate_rules_metadata(rules):
|
|
|
|
'''Validate rules metadata.'''
|
|
|
|
rule_repository = RulesRepository()
|
|
|
|
error_counter = 0
|
|
|
|
|
2022-01-28 09:51:13 +01:00
|
|
|
for rule_id in rules:
|
|
|
|
try:
|
|
|
|
rule = rule_repository.get_rule(rule_id)
|
|
|
|
validate_rule_metadata(rule)
|
|
|
|
except RuleValidationError as e:
|
|
|
|
click.echo(e.message, err=True)
|
|
|
|
error_counter += 1
|
2021-02-23 20:41:11 +01:00
|
|
|
|
|
|
|
if error_counter > 0:
|
2022-01-28 09:51:13 +01:00
|
|
|
fatal_error(f"Validation failed due to {error_counter} errors out of {len(rules)} analyzed rules")
|
2021-02-23 20:41:11 +01:00
|
|
|
|
2022-02-04 17:28:24 +01:00
|
|
|
|
|
|
|
VALIDATORS = [validate_section_names,
|
|
|
|
validate_section_levels,
|
|
|
|
validate_parameters,
|
|
|
|
validate_source_language,
|
|
|
|
]
|
|
|
|
def validate_rule_specialization(lang_spec_rule: LanguageSpecificRule):
|
|
|
|
error_counter = 0
|
|
|
|
for validator in VALIDATORS:
|
|
|
|
try:
|
|
|
|
validator(lang_spec_rule)
|
|
|
|
except RuleValidationError as e:
|
|
|
|
click.echo(e.message, err=True)
|
|
|
|
error_counter += 1
|
|
|
|
return error_counter
|
|
|
|
|
2021-05-04 09:58:49 +02:00
|
|
|
@cli.command()
|
|
|
|
@click.option('--d', required=True)
|
|
|
|
@click.argument('rules', nargs=-1)
|
2022-02-01 13:25:23 +01:00
|
|
|
def check_description(d, rules):
|
|
|
|
'''Validate the rule.adoc description.'''
|
2021-05-04 09:58:49 +02:00
|
|
|
out_dir = Path(__file__).parent.parent.joinpath(d)
|
|
|
|
rule_repository = RulesRepository(rules_path=out_dir)
|
|
|
|
error_counter = 0
|
|
|
|
for rule in rule_repository.rules:
|
2022-02-01 13:25:23 +01:00
|
|
|
if rules and rule.id not in rules:
|
2021-05-04 09:58:49 +02:00
|
|
|
continue
|
|
|
|
for lang_spec_rule in rule.specializations:
|
2022-02-04 17:28:24 +01:00
|
|
|
error_counter += validate_rule_specialization(lang_spec_rule)
|
2021-05-04 09:58:49 +02:00
|
|
|
if error_counter > 0:
|
2022-01-28 09:51:13 +01:00
|
|
|
fatal_error(f"Validation failed due to {error_counter} errors")
|
2021-01-29 16:05:22 +01:00
|
|
|
|
2021-10-01 14:52:12 +02:00
|
|
|
@cli.command()
|
|
|
|
@click.option('--repository', required=False)
|
|
|
|
@click.option('--version', required=False)
|
|
|
|
def update_coverage(repository: Optional[str], version: Optional[str]):
|
|
|
|
'''Update rule coverage by adding rules implemented in the {version} of {repository}.'''
|
|
|
|
if repository is None:
|
|
|
|
update_coverage_for_all_repos()
|
|
|
|
elif version is None:
|
|
|
|
update_coverage_for_repo(repository)
|
|
|
|
else:
|
|
|
|
update_coverage_for_repo_version(repository, version)
|
|
|
|
|
|
|
|
@cli.command()
|
|
|
|
@click.option('--message', required=True)
|
|
|
|
@click.option('--channel', required=True)
|
|
|
|
def notify_failure_on_slack(message: str, channel: str):
|
|
|
|
notify_slack(message, channel)
|
|
|
|
|
2021-01-29 16:05:22 +01:00
|
|
|
__all__=['cli']
|
2022-01-28 09:51:13 +01:00
|
|
|
|
|
|
|
def fatal_error(message: str):
|
|
|
|
click.echo(message, err=True)
|
|
|
|
raise click.Abort(message)
|