From 4e5a200539ce55148bfcecf7a172016746ab9524 Mon Sep 17 00:00:00 2001 From: Luke Tainton Date: Sun, 10 Jul 2022 17:27:44 +0100 Subject: [PATCH 1/3] Add Sonar (#14) * Add Sonar * Fix code smells --- .../archive/.deepsource.toml | 0 codecov.yml => .github/archive/codecov.yml | 0 .github/workflows/merge-to-main.yml | 14 ++++++++------ .github/workflows/pull-request.yml | 16 +++++++++------- .gitignore | 2 ++ README.md | 2 +- app/_version.py | 2 +- app/args.py | 2 +- app/ip_info.py | 4 +++- app/print_table.py | 3 ++- sonar-project.properties | 8 ++++++++ 11 files changed, 35 insertions(+), 18 deletions(-) rename .deepsource.toml => .github/archive/.deepsource.toml (100%) rename codecov.yml => .github/archive/codecov.yml (100%) create mode 100644 sonar-project.properties diff --git a/.deepsource.toml b/.github/archive/.deepsource.toml similarity index 100% rename from .deepsource.toml rename to .github/archive/.deepsource.toml diff --git a/codecov.yml b/.github/archive/codecov.yml similarity index 100% rename from codecov.yml rename to .github/archive/codecov.yml diff --git a/.github/workflows/merge-to-main.yml b/.github/workflows/merge-to-main.yml index ed9402e..0aeea5a 100644 --- a/.github/workflows/merge-to-main.yml +++ b/.github/workflows/merge-to-main.yml @@ -18,14 +18,16 @@ jobs: run: pip install -r requirements.txt && pip install -r requirements-dev.txt - name: Run test suite run: | - coverage run -m py.test -v + coverage run -m py.test -v --junitxml=testresults.xml coverage xml - - name: Report results to DeepSource - run: | - curl https://deepsource.io/cli | sh - ./bin/deepsource report --analyzer test-coverage --key python --value-file ./coverage.xml + - uses: sonarsource/sonarqube-scan-action@master env: - DEEPSOURCE_DSN: ${{ secrets.DEEPSOURCE_DSN }} + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} + - uses: sonarsource/sonarqube-quality-gate-action@master + timeout-minutes: 5 + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} build: needs: coverage diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index f3f442f..e826674 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -23,14 +23,16 @@ jobs: - name: Install dependencies run: pip install -r requirements.txt && pip install -r requirements-dev.txt - name: Lint - run: pylint --recursive=yes . + run: pylint --recursive=yes --output-format=parseable --output=lintreport.txt . - name: Run test suite run: | - coverage run -m py.test -v + coverage run -m py.test -v --junitxml=testresults.xml coverage xml - - name: Report results to DeepSource - run: | - curl https://deepsource.io/cli | sh - ./bin/deepsource report --analyzer test-coverage --key python --value-file ./coverage.xml + - uses: sonarsource/sonarqube-scan-action@master env: - DEEPSOURCE_DSN: ${{ secrets.DEEPSOURCE_DSN }} + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} + - uses: sonarsource/sonarqube-quality-gate-action@master + timeout-minutes: 5 + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} diff --git a/.gitignore b/.gitignore index eb31eb4..7f4045e 100644 --- a/.gitignore +++ b/.gitignore @@ -38,6 +38,8 @@ pip-log.txt pip-delete-this-directory.txt # Unit test / coverage reports +lintreport.txt +testresults.xml htmlcov/ .tox/ .nox/ diff --git a/README.md b/README.md index dfe433e..d785025 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# iPilot [![CI](https://github.com/luketainton/pypilot/actions/workflows/ci-branch-main.yml/badge.svg)](https://github.com/luketainton/pypilot/actions/workflows/ci-branch-main.yml) [![DeepSource](https://deepsource.io/gh/luketainton/pypilot.svg/?label=active+issues&show_trend=true&token=8utkyLrh7RPelvS-BNX1O8hZ)](https://deepsource.io/gh/luketainton/pypilot/?ref=repository-badge) +# iPilot [![CI](https://github.com/luketainton/pypilot/actions/workflows/ci-branch-main.yml/badge.svg)](https://github.com/luketainton/pypilot/actions/workflows/ci-branch-main.yml) [![Quality Gate Status](https://sonarqube.tainton.uk/api/project_badges/measure?project=luketainton_pypilot_AYHo1eOKSbMjdyWLhHhP&metric=alert_status&token=squ_7c59ea8a624979cf8d8305ca4bbf18048df8145b)](https://sonarqube.tainton.uk/dashboard?id=luketainton_pypilot_AYHo1eOKSbMjdyWLhHhP) ## Description IP Information Lookup Tool diff --git a/app/_version.py b/app/_version.py index bb07901..fc0c99d 100644 --- a/app/_version.py +++ b/app/_version.py @@ -2,4 +2,4 @@ """MODULE: Specifies app version.""" -VERSION = "1.2" +VERSION = "1.2" # pragma: no cover diff --git a/app/args.py b/app/args.py index 400b448..1f07c3a 100644 --- a/app/args.py +++ b/app/args.py @@ -7,7 +7,7 @@ import argparse from app.query_normalisation import get_public_ip -def parse_args() -> argparse.Namespace: +def parse_args() -> argparse.Namespace: # pragma: no cover """Get arguments from user via the command line.""" parser = argparse.ArgumentParser( description="Query information about an IP address or domain name." diff --git a/app/ip_info.py b/app/ip_info.py index 9e41e1a..8084c12 100644 --- a/app/ip_info.py +++ b/app/ip_info.py @@ -2,6 +2,8 @@ """MODULE: Provides functions to call various APIs to retrieve IP/prefix information.""" +from typing import Union + import ipaddress import requests @@ -24,7 +26,7 @@ def get_autonomous_system_number(as_info: str) -> str: return as_number -def get_prefix_information(autonomous_system: int) -> list: +def get_prefix_information(autonomous_system: int) -> Union[list, None]: """Retrieves prefix information about a given autonomous system.""" api_endpoint = f"https://api.hackertarget.com/aslookup/?q={str(autonomous_system)}" try: diff --git a/app/print_table.py b/app/print_table.py index fd9f118..a4626f9 100644 --- a/app/print_table.py +++ b/app/print_table.py @@ -2,10 +2,11 @@ """MODULE: Provides functions for preparing, then printing, retrieved data.""" +from typing import Union from tabulate import tabulate -def generate_prefix_string(prefixes: list) -> str: +def generate_prefix_string(prefixes: list) -> Union[str, None]: """Generate a string that spilts prefixes into rows of 4.""" num_per_row = 4 try: diff --git a/sonar-project.properties b/sonar-project.properties new file mode 100644 index 0000000..d470a33 --- /dev/null +++ b/sonar-project.properties @@ -0,0 +1,8 @@ +sonar.projectKey=luketainton_pypilot_AYHo1eOKSbMjdyWLhHhP +sonar.python.version=3.10 +sonar.python.coverage.reportPaths=coverage.xml +sonar.python.pylint.reportPaths=lintreport.txt +sonar.python.xunit.reportPath=testresults.xml +sonar.sources=app +sonar.tests=tests +sonar.exclusions=,.github/**,.gitignore,CODEOWNERS,CHANGELOG.md,LICENSE.md,README.md,renovate.json,requirements-dev.txt,requirements.txt From 20c53576722a3f0c205658bb7417150b5560f655 Mon Sep 17 00:00:00 2001 From: Luke Tainton Date: Sun, 10 Jul 2022 17:30:41 +0100 Subject: [PATCH 2/3] Disable shallow clone --- .github/workflows/merge-to-main.yml | 2 ++ .github/workflows/pull-request.yml | 1 + 2 files changed, 3 insertions(+) diff --git a/.github/workflows/merge-to-main.yml b/.github/workflows/merge-to-main.yml index 0aeea5a..17b1399 100644 --- a/.github/workflows/merge-to-main.yml +++ b/.github/workflows/merge-to-main.yml @@ -10,6 +10,8 @@ jobs: steps: - name: Check out repository code uses: actions/checkout@v3 + with: + fetch-depth: 0 - name: Setup Python uses: actions/setup-python@v4 with: diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index e826674..43144b9 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -16,6 +16,7 @@ jobs: uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 0 - name: Setup Python uses: actions/setup-python@v4 with: From a4bfe8794155031b3c02f5e842a6b0fb7541ac88 Mon Sep 17 00:00:00 2001 From: Luke Tainton Date: Sun, 10 Jul 2022 18:29:55 +0100 Subject: [PATCH 3/3] Add tests for app/print_table.py (#15) * Add tests for app/print_table.py * Exclude app/version and app/args from coverage * Remove app/main from coverage (just uses other modules) --- app/main.py | 2 +- app/print_table.py | 2 +- sonar-project.properties | 1 + tests/test_print_table.py | 19 +++++++++++++++++++ 4 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 tests/test_print_table.py diff --git a/app/main.py b/app/main.py index 150ce2e..b91a625 100644 --- a/app/main.py +++ b/app/main.py @@ -7,7 +7,7 @@ import sys from app.args import parse_args from app.print_table import print_table, generate_prefix_string from app.query_normalisation import is_ip_address, resolve_domain_name -from app.ip_info import ( # pragma: no cover +from app.ip_info import ( get_ip_information, get_autonomous_system_number, get_prefix_information, diff --git a/app/print_table.py b/app/print_table.py index a4626f9..cbb8a74 100644 --- a/app/print_table.py +++ b/app/print_table.py @@ -18,6 +18,6 @@ def generate_prefix_string(prefixes: list) -> Union[str, None]: return None -def print_table(table_data) -> None: +def print_table(table_data) -> None: # pragma: no cover """Print table generated by tabulate.""" print(tabulate(table_data)) diff --git a/sonar-project.properties b/sonar-project.properties index d470a33..4ffb8ad 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -6,3 +6,4 @@ sonar.python.xunit.reportPath=testresults.xml sonar.sources=app sonar.tests=tests sonar.exclusions=,.github/**,.gitignore,CODEOWNERS,CHANGELOG.md,LICENSE.md,README.md,renovate.json,requirements-dev.txt,requirements.txt +sonar.coverage.exclusions=app/_version.py,app/args.py,app/main.py diff --git a/tests/test_print_table.py b/tests/test_print_table.py new file mode 100644 index 0000000..7610486 --- /dev/null +++ b/tests/test_print_table.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 + +"""MODULE: Provides test cases for app/print_table.py.""" + +from app.print_table import generate_prefix_string # pragma: no cover + + +def test_generate_prefix_string_small() -> None: + """TEST: Verifies if a small prefix list results in one line.""" + test_query = ["abc", "def"] + result = generate_prefix_string(prefixes=test_query) + assert result == "abc, def\n" + + +def test_generate_prefix_string_large() -> None: + """TEST: Verifies if a large prefix list results in multiple lines.""" + test_query = ["abc", "def", "ghi", "jkl", "mno", "pqr"] + result = generate_prefix_string(prefixes=test_query) + assert result == "abc, def, ghi, jkl\nmno, pqr\n"