From 2597b62f692aa9f21f92c903368bfef9b3088215 Mon Sep 17 00:00:00 2001 From: Karel Piwko Date: Wed, 2 Jul 2025 09:15:23 +0200 Subject: [PATCH 1/3] feat: dashboard urls and timeout updated to be able to fetch more dashboards --- logilica-cli.yaml | 100 +++++++++++++++++++++++++++++++-- logilica_cli/page_dashboard.py | 3 +- 2 files changed, 96 insertions(+), 7 deletions(-) diff --git a/logilica-cli.yaml b/logilica-cli.yaml index 4567e0c..a9de032 100644 --- a/logilica-cli.yaml +++ b/logilica-cli.yaml @@ -4,15 +4,105 @@ teams: team_dashboards: Developer Practices Dashboard: filename: DPROD_Report.pdf - url: https://logilica.io/dashboard/023e570d-1398-458b-88e2-2c83ac6ad5c6?variables=W3sidmFyIjoiVGltZSIsInZhbCI6eyJkaW1lbnNpb24iOiJUaW1lIiwiZGF0ZVJhbmdlIjoiZnJvbSA5MCBkYXlzIGFnbyB0byBub3cifX1d&workstream=00000000b5cc5d88 + url: https://logilica.io/dashboard/023e570d-1398-458b-88e2-2c83ac6ad5c6/view/ff871fb2c72a7f6893181ecfce648a337bcb3a2206507f1360311f181b40f028 Sandbox Team: team_dashboards: Sandbox Team Dashboard: filename: SANDBOX_Report.pdf - url: https://logilica.io/dashboard/d76c9434-148d-4152-b2dd-49e095519dfd/view/e53574be95eb5f1574764f7a98bcca12efe030932919233f606d546bcd92df91 + url: https://logilica.io/dashboard/c2205e85-034e-4209-b218-fcc37df00dea/view/f1765ec4d6f6b94e3d733a772734e6d9397a87d2236e8630d77a29fc258f3546 Coding Velocity: filename: sandbox-coding.velocity.pdf - url: https://logilica.io/dashboard/76538369-1f54-4c99-bcf2-a3ffcc9d3270?variables=W3sidmFyIjoiUHJvamVjdC5uYW1lIiwidmFsIjp7Im1lbWJlciI6IlByb2plY3QubmFtZSIsIm9wZXJhdG9yIjoiZXF1YWxzIiwidmFsdWVzIjpbImdpdGh1Yi5jb20vY29kZXJlYWR5LXRvb2xjaGFpbi9ob3N0LW9wZXJhdG9yIiwiZ2l0aHViLmNvbS9jb2RlcmVhZHktdG9vbGNoYWluL21lbWJlci1vcGVyYXRvciIsImdpdGh1Yi5jb20vY29kZXJlYWR5LXRvb2xjaGFpbi9yZWdpc3RyYXRpb24tc2VydmljZSJdfX0seyJ2YXIiOiJUaW1lIiwidmFsIjp7ImRpbWVuc2lvbiI6IlRpbWUiLCJkYXRlUmFuZ2UiOiJmcm9tIDkwIGRheXMgYWdvIHRvIG5vdyJ9fSx7InZhciI6IlRlYW0ubmFtZSIsInZhbCI6eyJtZW1iZXIiOiJUZWFtLm5hbWUiLCJvcGVyYXRvciI6ImVxdWFscyIsInZhbHVlcyI6WyJLdWJlc2F3IFRlYW0iLCJTYW5kYm94IFRlYW0iXX19XQ%3D%3D&workstream=1867839813 + url: https://logilica.io/dashboard/76538369-1f54-4c99-bcf2-a3ffcc9d3270/view/8c534ebaef3e65c99a6c0c8d314850624b72a0368c4cba4f0efc0e44498188ec + Kubesaw Team: + team_dashboards: + Sprint Planning Accuracy: + filename: KUBESAW_Report.pdf + url: https://logilica.io/dashboard/f42ddeac-8520-4709-bd36-5713c8e299d3/view/1a541be111c65d13e30b00b3d531b502e0376440b5f671dfdaafb633e44ce570 + OpenShift Builds Team: + team_dashboards: + Ticket Lead Time: + filename: openshift-builds-team-ticket-lead-time.pdf + url: https://logilica.io/dashboard/db6a9a52-11cf-4e70-9407-ccfbe4de9fa2/view/ccc34077802c0c46d3481de34a0bd1ea1e03bc34f2643d60d2ff22cc65621c60 + Ticket Velocity: + filename: openshift-builds-team-ticket-velocity.pdf + url: https://logilica.io/dashboard/e81ac5c1-7f8a-4583-81cc-341828b23c57/view/ccc34077802c0c46d3481de34a0bd1ea1e03bc34f2643d60d2ff22cc65621c60 + Ticket Overload: + filename: openshift-builds-team-ticket-overload.pdf + url: https://logilica.io/dashboard/a15855a7-b2b2-43c5-97c7-293d0308b7ec/view/720eb5ecb997123cf3865b283731fea40eea8335417c3b6b5a02df59e73c9fca + Sprint Health: + filename: openshift-builds-team-sprint-health.pdf + url: https://logilica.io/dashboard/4b33549c-b46a-4672-a923-b2cd51d77e93/view/33b4e3bb4712b0299ea4acfc16f4bec870923df7a65b3db2d002c764caa893e1 + Ticket Risks: + filename: openshift-builds-team-ticket-risks.pdf + url: https://logilica.io/pm_issues/view/729ca34f9cbaf181406d1845dc21921f0bea6eeec37ff85b857d4ef1a83286d6 + Code Cycle Time: + filename: openshift-builds-team-code-cycle-time.pdf + url: https://logilica.io/dashboard/43814594-4df8-417f-8c7c-e7f9613954a8/view/c1ffb35a59438b434c91f603c1584d37cad51d064d136024ded9ea2ba7b6fcf2 + Coding Velocity: + filename: openshift-builds-team-coding-velocity.pdf + url: https://logilica.io/dashboard/76538369-1f54-4c99-bcf2-a3ffcc9d3270/view/c1ffb35a59438b434c91f603c1584d37cad51d064d136024ded9ea2ba7b6fcf2 + Review Process: + filename: openshift-builds-team-review-process.pdf + url: https://logilica.io/dashboard/0ae659f2-6b40-4ad0-83aa-d570c164f8d0/view/c1ffb35a59438b434c91f603c1584d37cad51d064d136024ded9ea2ba7b6fcf2 + Developer Health: + filename: openshift-builds-team-developer-health.pdf + url: https://logilica.io/dashboard/e536ae85-448d-49b5-a8a2-6036de650182/view/c1ffb35a59438b434c91f603c1584d37cad51d064d136024ded9ea2ba7b6fcf2 + Code Risks: + filename: openshift-builds-team-code-risks.pdf + url: https://logilica.io/pull_request/view/5ce82166b5e80296a3c6d5ab7599a36ab9318820fed8e5c3b707ed4f08c95a38 + CI Overview: + filename: openshift-builds-team-ci-overview.pdf + url: https://logilica.io/dashboard/3f545f0f-a5d8-4771-a006-1c9a0cd05707/view/39e06a76252511d87923ddf8beb63a48277f873ae08027c6831db31361590b7c + Teams Overview: + filename: openshift-builds-team-teams-overview.pdf + url: https://logilica.io/dashboard/1fc86f71-779a-43f0-be24-a9b893981c30/view/a7576614518beefae93ebfb141d725e436b8146e36f96f28573667153f7c3d1c + Team Pulse: + filename: openshift-builds-team-team-pulse.pdf + url: https://logilica.io/dashboard/bd912ffc-564f-45b6-b7d9-393296320590/view/010c8cbc93850aac954f80ba945b34d0ee4df8930b75043dff1d0461f369f3a9 + Team Activity: + filename: openshift-builds-team-team-activity.pdf + url: https://logilica.io/standup/view/422b2e74d17ba0d748bfd1f7cc9fdf597e2a55ee87423cd8470baf4a09af1001 + Podman Desktop Team: + team_dashboards: + Ticket Lead Time: + filename: podman-desktop-team-ticket-lead-time.pd + url: https://logilica.io/dashboard/db6a9a52-11cf-4e70-9407-ccfbe4de9fa2/view/1f4e4967adae4ff43a2ef5fee4d065863987bc6e369042906247c6efd67fafdc + Ticket Velocity: + filename: podman-desktop-team-ticket-velocity.pdf + url: https://logilica.io/dashboard/db6a9a52-11cf-4e70-9407-ccfbe4de9fa2/view/1f4e4967adae4ff43a2ef5fee4d065863987bc6e369042906247c6efd67fafdc + Ticket Overload: + filename: podman-desktop-team-ticket-overload.pdf + url: https://logilica.io/dashboard/a15855a7-b2b2-43c5-97c7-293d0308b7ec/view/af97171d65568c0f386d858dce031f820c626fb2bf34a022064ecdcfc17ebd01 + Sprint Health: + filename: podman-desktop-team-sprint-health.pdf + url: https://logilica.io/dashboard/4b33549c-b46a-4672-a923-b2cd51d77e93/view/a9e98db1372c91102f15e5a9d47108e0b9740a420f6aba22134b1d09192bdef0 + Ticket Risks: + filename: podman-desktop-team-ticket-risks.pdf + url: https://logilica.io/pm_issues/view/eecab48933198eaca22c74b8376a93f994aa4326dd4049e2e08b5eb5a7640a5b + Code Cycle Time: + filename: podman-desktop-team-code-cycle-time.pdf + url: https://logilica.io/dashboard/43814594-4df8-417f-8c7c-e7f9613954a8/view/dbaeb584e4b86a3da6100901d9c94a29bf1cdd64d8dbcff0483b716cab66150a + Coding Velocity: + filename: podman-desktop-team-coding-velocity.pdf + url: https://logilica.io/dashboard/76538369-1f54-4c99-bcf2-a3ffcc9d3270/view/4174267319b3bac3ca5918fdf187297b2dd79cfb776a720f479ef65e1ec6956a + Review Process: + filename: podman-desktop-team-review-process.pdf + url: https://logilica.io/dashboard/0ae659f2-6b40-4ad0-83aa-d570c164f8d0/view/4174267319b3bac3ca5918fdf187297b2dd79cfb776a720f479ef65e1ec6956a + Developer Health: + filename: podman-desktop-team-developer-health.pdf + url: https://logilica.io/dashboard/e536ae85-448d-49b5-a8a2-6036de650182/view/4174267319b3bac3ca5918fdf187297b2dd79cfb776a720f479ef65e1ec6956a + Code Risks: + filename: podman-desktop-team-code-risks.pdf + url: https://logilica.io/pull_request/view/bbe8a4020c0b879f156900bb28c679575d40bdadcd8fb165da70cab8743ac8fa + CI Overview: + filename: podman-desktop-team-ci-overview.pdf + url: https://logilica.io/dashboard/3f545f0f-a5d8-4771-a006-1c9a0cd05707/view/26ab9b52736e6f3c1272627c19ceafaf1348d49b6a7e9968e9ea5318e0b5a83e + # Team Pulse: + # filename: podman-desktop-team-team-pulse.pdf + # url: https://logilica.io/dashboard/bd912ffc-564f-45b6-b7d9-393296320590/view/2d4dce7366a3aae2bee64133aea69d32168fc446f4e44f303faf92125d87eb93 + Team Activity: + filename: podman-desktop-team-team-activity.pdf + url: https://logilica.io/standup/view/c7b9374a51a176659e972c8060c0ef09f59d05f1a6f3f4802016a6e99e48d9df RHDH teams: team_dashboards: Ticket Lead Time: @@ -55,8 +145,8 @@ teams: filename: rhdh-team-activity.pdf url: https://logilica.io/standup?chartId=40f04dce-01fc-4d86-aebe-3d2be1a677ca&variables=W3sidmFyIjoiVGVhbS5uYW1lIiwidmFsIjp7Im1lbWJlciI6IlRlYW0ubmFtZSIsIm9wZXJhdG9yIjoiZXF1YWxzIiwidmFsdWVzIjpbIlJIREggQ29yZSBUZWFtIiwiUkhESCBEeW5hbWljIFBsdWdpbnMgVGVhbSIsIlJIREggSW5zdGFsbCBUZWFtIiwiUkhESCBQbHVnaW5zIFRlYW0iLCJSSERIIFBsdWdpbnMvQUkgLSBVSSBUZWFtIiwiUkhESCBTZWN1cml0eSBUZWFtIiwiUkhESCBVSSBUZWFtIl19fSx7InZhciI6IlRpbWUiLCJ2YWwiOnsiZGltZW5zaW9uIjoiVGltZSIsImRhdGVSYW5nZSI6ImZyb20gMzAgZGF5cyBhZ28gdG8gbm93In19XQ%3D%3D&workstream=00000000004efddf # RHDH Team Dashboard: - # filename: rhdh-teams-dashboard.pdf - # url: https://logilica.io/dashboard/69f12907-3d84-4e8e-9a2a-1d4b4f5aeafc?variables=W3sidmFyIjoiVGltZSIsInZhbCI6eyJkaW1lbnNpb24iOiJUaW1lIiwiZGF0ZVJhbmdlIjoiZnJvbSA5MCBkYXlzIGFnbyB0byBub3cifX0seyJ2YXIiOiJKaXJhUHJvamVjdC5uYW1lIiwidmFsIjp7Im1lbWJlciI6IkppcmFQcm9qZWN0Lm5hbWUiLCJvcGVyYXRvciI6ImVxdWFscyIsInZhbHVlcyI6WyJpc3N1ZXMucmVkaGF0LmNvbS9SSERIQlVHUyIsImlzc3Vlcy5yZWRoYXQuY29tL1JIREhQQUkiLCJpc3N1ZXMucmVkaGF0LmNvbS9SSElEUCJdfX0seyJ2YXIiOiJUZWFtLm5hbWUiLCJ2YWwiOnsibWVtYmVyIjoiVGVhbS5uYW1lIiwib3BlcmF0b3IiOiJlcXVhbHMiLCJ2YWx1ZXMiOlsiUkhESCBDb3JlIFRlYW0iLCJSSERIIER5bmFtaWMgUGx1Z2lucyBUZWFtIiwiUkhESCBJbnN0YWxsIFRlYW0iLCJSSERIIFBsdWdpbnMgVGVhbSIsIlJIREggUGx1Z2lucy9BSSAtIFVJIFRlYW0iLCJSSERIIFNlY3VyaXR5IFRlYW0iLCJSSERIIFVJIFRlYW0iXX19XQ%3D%3D + # filename: rhdh-teams-dashboard.pdf + # url: https://logilica.io/dashboard/69f12907-3d84-4e8e-9a2a-1d4b4f5aeafc/view/39fde27dbcd66ec590decc0a2dd7023bf83939341774812754c1790967b9e74f integrations: "Developer Productivity": connector: Jira diff --git a/logilica_cli/page_dashboard.py b/logilica_cli/page_dashboard.py index 0341531..4e9e9c9 100644 --- a/logilica_cli/page_dashboard.py +++ b/logilica_cli/page_dashboard.py @@ -6,8 +6,7 @@ class DashboardPage: - - PDF_EXPORT_TIMEOUT = 60000 + PDF_EXPORT_TIMEOUT = 120000 def __init__(self, page: Page): # PDF generation might take longer than default 30000 ms timeout, so modify for this page in global From bebf066e072d3024d5c9c3f0abdf552a8de58237 Mon Sep 17 00:00:00 2001 From: Karel Piwko Date: Wed, 2 Jul 2025 09:17:33 +0200 Subject: [PATCH 2/3] feat: pdf output capability --- README.md | 4 +++- logilica_cli/weekly_report.py | 6 ++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 66136ef..76c9cbf 100644 --- a/README.md +++ b/README.md @@ -100,10 +100,12 @@ Options: Use SSO/OAuth dialog instead of specifying a username and password for Logilica access [default: email] - -O, --output, --output-type [gdoc|console|images-only|markdown|html|markdown-with-refs|html-with-refs] + -O, --output, --output-type [pdf|gdoc|console|images-only|markdown|html|markdown-with-refs|html-with-refs] Output format of how individual PDF file is processed: + pdf: Don't process files, keep PDFs. + gdoc: HTML with an embedded image representing whole dashboard and stored as a Google Doc on Google Drive diff --git a/logilica_cli/weekly_report.py b/logilica_cli/weekly_report.py index be4a5f9..f1221d2 100644 --- a/logilica_cli/weekly_report.py +++ b/logilica_cli/weekly_report.py @@ -48,6 +48,7 @@ "-O", type=click.Choice( [ + "pdf", "gdoc", "console", "images-only", @@ -62,6 +63,8 @@ show_default=True, help="""Output format of how individual PDF file is processed: + pdf: Don't process files, keep PDFs. + gdoc: HTML with an embedded image representing whole dashboard and stored as a Google Doc on Google Drive @@ -167,6 +170,9 @@ def weekly_report( teams=configuration["teams"], base_dir_path=downloads_temp_dir ) + if output == "pdf": + return + converter = PDFConvert( output_dir_path=output_dir_path, download_dir_path=downloads_temp_dir, From ccdc5c4ecb8df70ec3679425fa5affe0a61a0801 Mon Sep 17 00:00:00 2001 From: Karel Piwko Date: Wed, 2 Jul 2025 09:20:34 +0200 Subject: [PATCH 3/3] feat: linting, formating and CI updates --- .github/workflows/ci.yaml | 2 +- .github/workflows/python_lint_and_test.yaml | 16 ++--- .github/workflows/requirements.txt | 7 +- .pre-commit-config.yaml | 50 ++++++++++++++ README.md | 76 ++++++++++++++------- logilica_cli/data_sources.py | 6 +- logilica_cli/page_dashboard.py | 5 +- logilica_cli/page_navigation.py | 3 +- logilica_cli/page_settings.py | 19 +++--- logilica_cli/pdf_convert.py | 1 - logilica_cli/pdf_extract.py | 1 - logilica_cli/update_gdoc.py | 4 +- logilica_cli/weekly_report.py | 13 +++- pyproject.toml | 33 ++++++--- tests/test_configuration_schema.py | 6 +- tests/test_update_gdoc.py | 5 +- 16 files changed, 170 insertions(+), 77 deletions(-) create mode 100644 .pre-commit-config.yaml diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index d395eb4..2d56fc6 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -4,7 +4,7 @@ on: branches: - main tags: - - '**' + - "**" release: types: - published diff --git a/.github/workflows/python_lint_and_test.yaml b/.github/workflows/python_lint_and_test.yaml index 24ed85b..b82cb2a 100644 --- a/.github/workflows/python_lint_and_test.yaml +++ b/.github/workflows/python_lint_and_test.yaml @@ -20,8 +20,8 @@ jobs: uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - cache: 'pip' - cache-dependency-path: '**/requirements.txt' + cache: "pip" + cache-dependency-path: "**/requirements.txt" # architecture: x64 - name: Install dependencies run: | @@ -32,16 +32,8 @@ jobs: - name: Run python style and linting tools run: | err=0 - echo autoflake: - autoflake --check-diff . || err=$? - echo black: - black --check . || err=$? - echo docformatter: - docformatter . || err=$? - echo flake8: - flake8 . || err=$? - echo isort: - isort --check . || err=$? + pre-commit install + pre-commit run --all-files --hook-stage pre-commit || err=$? exit $err - name: Run tests with coverage run: | diff --git a/.github/workflows/requirements.txt b/.github/workflows/requirements.txt index 20fbf16..f721d12 100644 --- a/.github/workflows/requirements.txt +++ b/.github/workflows/requirements.txt @@ -1,6 +1,3 @@ -autoflake -black coverage[toml] -docformatter -flake8 -isort +pre-commit + diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..e803fb5 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,50 @@ +# This file contains 2 stages +# pre-commit stage - runs by default pre-commit +# manual stage - runs the same tools but modifies files +# run as: pre-commit run --all-files --hook-stage manual +repos: + # See README.md for more information on this pre-commit hook + # Please uncomment this hook if you are a Red Hat employee, and make sure you don't commit it back upstream + # - repo: https://gitlab.cee.redhat.com/infosec-public/developer-workbench/tools.git + # rev: rh-pre-commit-2.3.0 + # hooks: + # # If you have not run this hook on your system before, it may prompt you to + # # log in for patterns, and you will need to try again. + # # + # # Docs: https://source.redhat.com/departments/it/it-information-security/leaktk/leaktk_components/rh_pre_commit + # - id: rh-pre-commit + # name: Red Hat pre-commit (check) + # # - id: rh-pre-commit.commit-msg # Optional for commit-msg attestation + - repo: https://github.com/PyCQA/docformatter + rev: v1.7.7 + hooks: + - id: docformatter + name: docformatter (check) + additional_dependencies: [tomli] + args: [--check, --config, ./pyproject.toml] + stages: [pre-commit] + - id: docformatter + name: docformatter (fix) + additional_dependencies: [tomli] + args: [--in-place, --config, ./pyproject.toml] + stages: [manual] + - repo: https://github.com/psf/black + rev: 25.1.0 + hooks: + - id: black + name: black (check) + args: [--check] + stages: [pre-commit] + - id: black + name: black (fix) + stages: [manual] + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.12.1 + hooks: + - id: ruff-check + name: ruff linter (check) + stages: [pre-commit] + - id: ruff-check + name: ruff linter (fix) + args: [--fix] + stages: [manual] diff --git a/README.md b/README.md index 76c9cbf..0dbd943 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,18 @@ # `logilica-cli` `logilica-cli` is a command-line tool which provides CLI access to the Logilica -UI. The tool currently provides two subcommands. The first exports charts and +UI. The tool currently provides two subcommands. The first exports charts and text from Logilica reports and makes them available in a variety of formats, -including HTML, Markdown, and as a Google Docs document. The second is used to +including HTML, Markdown, and as a Google Docs document. The second is used to configure Logilica integrations, supporting a "configuration as code" approach. The tool is configured via a YAML file which contains tool configuration -options as well as options for exporting data or configuring Logilica. By +options as well as options for exporting data or configuring Logilica. By default, the file `logica-cli.yaml` in the current directory is used, but an alternate path can be specified on the command line. -For export, the configuration includes a list of teams. For each team, it -specifies a list of Logilica dashboards and the team's Jira project. For each +For export, the configuration includes a list of teams. For each team, it +specifies a list of Logilica dashboards and the team's Jira project. For each dashboard, it specifies the name of an output file (which must not conflict with any other team's dashboards' output files) and possibly other attributes. @@ -29,32 +29,31 @@ the configuration file. Credentials for accessing Logilica are provided by command line options or by the environment variables, `LOGILICA_DOMAIN`, `LOGILICA_EMAIL`, and -`LOGILICA_PASSWORD`. (Note to the Developer Practices Team: the appropriate +`LOGILICA_PASSWORD`. (Note to the Developer Practices Team: the appropriate values for the bot accounts can be obtained from the Bitwarden vault; users with admin privileges can also create their own username/password credentials -using the Logilica UI.) For interactive use, OAuth or SSO credentials can be +using the Logilica UI.) For interactive use, OAuth or SSO credentials can be used. The tool normally runs in "headless" mode; however, in order to enable the user to perform an SSO login, the tool opens a browser window during the -run. (You should not interact with this window unless it prompts for your SSO +run. (You should not interact with this window unless it prompts for your SSO credentials; otherwise, you are likely to disrupt the functioning of the tool.) -To run the tool, check out the Git repo and run: -```pip install -r requirements.txt .``` +To install the tool, check out the Git repo and run: + +``` +pip install -r requirements.txt . +playwright install chromium +``` + We recommend doing this inside a [virtual environment](https://docs.python.org/3/library/venv.html), -which uses Python 3.12+. (If you are doing development on the tool, you may want -to specify `-e` in the `pip install` command.) After installing the tool, you also -need to install the browser which it uses to interact with the Logilica web UI: -```playwright install chromium``` (For details on debugging the web interactions, -see the `--pwdebug` option in the command help, below, and the -[Playwright documentation](https://playwright.dev/python/docs/running-tests).) +which uses Python 3.12+. The PDF files containing the downloaded Logilica reports are stored in a temporary directory which is created if it does not exist; if it was created by -the tool, the directory is deleted after execution is complete. By default, -the directory is named `lwr_downloaded_pdfs`, and it is created in the current -directory, but an alternate path can be specified on the command line. +the tool, the directory is deleted after execution is complete. Help is available on the command line: + ```text Usage: logilica-cli [OPTIONS] COMMAND [ARGS]... @@ -80,6 +79,7 @@ Commands: ``` ```text +logilica-cli weekly-report --help Usage: logilica-cli weekly-report [OPTIONS] Downloads and processes weekly report for teams specified in the @@ -90,9 +90,11 @@ Options: Name [env var: LOGILICA_DOMAIN; required] -t, --downloads-temp-dir DIRECTORY Path to a directory to receive downloaded - files (will be created if it doesn't exist; - will be deleted if created) [default: - ./lwr_downloaded_pdfs] + files (if unspecified, a temporary directory + will be used; otherwise, the specified + directory will be created if it doesn't + exist; if the directory is created by the + tool, it will be deleted after the run) -I, --input [logilica|local] Input source -- download from Logilica or use pre-downloaded files [default: logilica] @@ -161,7 +163,35 @@ Options: var: LOGILICA_EMAIL] --help Show this message and exit. ``` + Some dashboards can be quite slow to load into the UI, so, if you are running the tool interactively and wish to track its progress, add a `-v` to the command -line to see informational messages. (If you are debugging or just nosy, adding +line to see informational messages. (If you are debugging or just nosy, adding a _second_ `-v` will add debugging messages to the output.) + +## Development + +If you are doing development on the tool, you may want to specify `-e` in the `pip install` command to install it in editable mode. +This means that you can make changes to the package's source code and those changes will be reflected in your project without having to reinstall the package. + +For details on debugging the web interactions, see the `--pwdebug` option in the command help and the [Playwright documentation](https://playwright.dev/python/docs/running-tests). + +### Linting and formatting rules + +This project uses `pre-commit` to handle linting and formatting. The `pre-commit` tool reads its configuration from [`.pre-commit-config.yaml`](./.pre-commit-config.yaml) and the configuration options for the individual linters and formatters can be found in the [`pyproject.toml`](./pyproject.toml) file. +The same configuration is used in CI. + +To install and execute it locally, follow these steps: + +``` +pip install pre-commit +pre-commit install +pre-commit run --all-files --hook-stage [pre-commit|manual] +``` + +If you run `pre-commit` stage, you can check your files, if you run `manual` stage, it will modify your files to correct problems it finds. + +### Enabling Red Hat InfoSec plugin + +If you are developing locally within Red Hat, you should enable Red Hat InfoSec plugin. You can do that by uncommenting appropriate lines in `.pre-commit-config.yaml` file. +Make sure that you don't commit that change back upstream, as it would break the CI. diff --git a/logilica_cli/data_sources.py b/logilica_cli/data_sources.py index ad568dc..f832413 100644 --- a/logilica_cli/data_sources.py +++ b/logilica_cli/data_sources.py @@ -10,11 +10,7 @@ @common_options @click.pass_context def data_sources( - context: click.Context, - username: str, - password: str, - domain: str, - oauth: bool, + context: click.Context, username: str, password: str, domain: str, oauth: bool ) -> None: """Synchronizes configuration of integrations with the configuration file. diff --git a/logilica_cli/page_dashboard.py b/logilica_cli/page_dashboard.py index 4e9e9c9..5ab9435 100644 --- a/logilica_cli/page_dashboard.py +++ b/logilica_cli/page_dashboard.py @@ -9,8 +9,9 @@ class DashboardPage: PDF_EXPORT_TIMEOUT = 120000 def __init__(self, page: Page): - # PDF generation might take longer than default 30000 ms timeout, so modify for this page in global - # It can be export or download button that takes time to become visible + # PDF generation might take longer than default 30000 ms timeout, + # so modify for this page in global. + # It can be export or download button that takes time to become visible. page.set_default_timeout(self.PDF_EXPORT_TIMEOUT) self.page = page self.export_pdf_button = page.get_by_role("button", name="Export PDF") diff --git a/logilica_cli/page_navigation.py b/logilica_cli/page_navigation.py index ddc3d6f..c94a06f 100644 --- a/logilica_cli/page_navigation.py +++ b/logilica_cli/page_navigation.py @@ -26,7 +26,8 @@ def navigate(self, *, menu_dropdown: Optional[str], link_name: str) -> None: link_locator = self.page.get_by_role("link", name=link_name) - # if dropdown argument was provided, check if dropdown is open as it hides the link + # If dropdown argument was provided, check if dropdown is open as + # it hides the link if menu_dropdown: for first_try in (True, False): try: diff --git a/logilica_cli/page_settings.py b/logilica_cli/page_settings.py index 5453020..64d5747 100644 --- a/logilica_cli/page_settings.py +++ b/logilica_cli/page_settings.py @@ -26,7 +26,6 @@ class SettingsPage: AVAILABLE_LIST_TIMEOUT = 54000 def __init__(self, page: Page): - self.page = page # UI elements for public access self.add_public_repository_dialog_button = page.get_by_role( @@ -62,7 +61,9 @@ def open_integration_configuration( """ logging.debug( - "Opening integration '%s', connector type:'%s'", integration, connector + "Opening integration '%s', connector type:'%s'", + integration, + connector, ) self.page.locator("div.items-center").filter(has_text=connector).filter( has_text=integration @@ -78,7 +79,8 @@ def sync_integrations(self, integrations: dict[str, Any]) -> None: in integrations sections of the local configuration file. Raises: - RuntimeError: If any repositories could not have been added to the configuration. + RuntimeError: + If any repositories could not have been added to the configuration. """ sync_failures: IntegrationSyncFailures = defaultdict(list) @@ -278,7 +280,8 @@ def has_entity_imported( ) -> bool: search_field.fill(entity_id) - # here we need to find the innermost div element that exactly matches repository slug + # Here we need to find the innermost div element + # that exactly matches repository slug. found = self.page.get_by_text(text=entity_id, exact=True).nth(0).is_visible() if found: logging.debug("✅%s '%s' is imported", entity_type, entity_id) @@ -322,8 +325,8 @@ def add_public_repository( self.add_public_repository_dialog_button.click() self.add_public_repository_input.fill(f"{host}/{entity_id}.git") self.add_public_repository_confirm_button.click() - # as UI refresh is triggered independently of the click and there is no guarantee the repository will be added - # at the top of the page, we don't validate the action success here but later + # UI refresh is triggered independently of the click and there is no guarantee + # the repository will be added at the top of the page, we'll validate it later return True def add_membership_entity( @@ -373,8 +376,8 @@ def control_button(self, entity_id: str, *, order=0) -> Optional[Locator]: .get_by_role("button") ) - # there might be the same slug in both imported repositories and available repositories - # in that case, we want to be able to select one specifically + # There might be the same slug in both imported repositories and available + # repositories, in that case, we want to be able to select one specifically. count = locator.count() if count == 1: return locator diff --git a/logilica_cli/pdf_convert.py b/logilica_cli/pdf_convert.py index 0637c7b..3298c20 100644 --- a/logilica_cli/pdf_convert.py +++ b/logilica_cli/pdf_convert.py @@ -92,7 +92,6 @@ def to_format_multiple( teams: dict[str, dict[str, Any]], embed_images: bool = True, ) -> int: - total = 0 for team, dashboards in teams.items(): for dashboard, options in dashboards["team_dashboards"].items(): diff --git a/logilica_cli/pdf_extract.py b/logilica_cli/pdf_extract.py index 9be6aec..16678a9 100644 --- a/logilica_cli/pdf_extract.py +++ b/logilica_cli/pdf_extract.py @@ -10,7 +10,6 @@ class PDFExtract: - def __init__(self, scale: float = 1.0): """Encapsulation of PDF extraction.""" diff --git a/logilica_cli/update_gdoc.py b/logilica_cli/update_gdoc.py index 69f3402..f603abe 100644 --- a/logilica_cli/update_gdoc.py +++ b/logilica_cli/update_gdoc.py @@ -101,7 +101,9 @@ def upload_doc(doc: str, creds: Credentials, config: dict[str, any]) -> str: if status: logging.debug("Uploaded %d%%.", int(status.progress() * 100)) logging.debug( - 'File "%s" with ID "%s" has been uploaded.', filename, response.get("id") + 'File "%s" with ID "%s" has been uploaded.', + filename, + response.get("id"), ) except HttpError as error: diff --git a/logilica_cli/weekly_report.py b/logilica_cli/weekly_report.py index f1221d2..414323a 100644 --- a/logilica_cli/weekly_report.py +++ b/logilica_cli/weekly_report.py @@ -167,7 +167,8 @@ def weekly_report( with LogilicaSession(oauth, logilica_credentials) as page: dashboard_page = DashboardPage(page=page) dashboard_page.download_team_dashboards( - teams=configuration["teams"], base_dir_path=downloads_temp_dir + teams=configuration["teams"], + base_dir_path=downloads_temp_dir, ) if output == "pdf": @@ -178,7 +179,12 @@ def weekly_report( download_dir_path=downloads_temp_dir, scale=scale, ) - if output in ("markdown", "html", "markdown-with-refs", "html-with-refs"): + if output in ( + "markdown", + "html", + "markdown-with-refs", + "html-with-refs", + ): o_format = output.removesuffix("-with-refs") embed_images = not output.endswith("-with-refs") converter.to_format_multiple( @@ -188,7 +194,8 @@ def weekly_report( ) else: pdf_items = PDFExtract(scale=scale).get_pdf_objects( - teams=configuration["teams"], download_dir_path=downloads_temp_dir + teams=configuration["teams"], + download_dir_path=downloads_temp_dir, ) if output == "images-only": converter.to_images(pdf_items=pdf_items) diff --git a/pyproject.toml b/pyproject.toml index f6b7ed2..cb2b0e9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,13 +13,30 @@ license = {"text" = "Apache-2.0"} [project.scripts] logilica-cli = "logilica_cli.__main__:cli" -[tool.autoflake] -exclude = ["build"] -recursive = true -remove-all-unused-imports = true -remove-unused-variables = true +[tool.ruff] +line-length = 88 + +[tool.ruff.lint] +select = [ + "E", # pycodestyle (flake8) + "F", # pyflakes (flake8) + "I", # isort + "W505", # docstring line too long +] +ignore = ["E501"] # line length is covered by black + +# isort replacement +[tool.ruff.lint.isort] +known-first-party = ["logilica_cli"] # use separate section for project sources +force-sort-within-sections = true # don't separate import vs from +order-by-type = false # sort alphabetic regardless of case + +[tool.ruff.lint.pycodestyle] +max-doc-length = 88 + [tool.black] +line-length = 88 skip-string-normalization = false skip-magic-trailing-comma = false include = '\.pyi?$' @@ -60,12 +77,6 @@ skip_empty = true [tool.coverage.html] skip_empty = true -[tool.isort] -profile = "black" # black-compatible (e.g., trailing comma) -known_first_party = ["logilica_cli"] # use separate section for project sources -force_sort_within_sections = true # don't separate import vs from -order_by_type = false # sort alphabetic regardless of case - [tool.pytest.ini_options] filterwarnings = [ # note the use of single quote below to denote "raw" (regex) strings in TOML diff --git a/tests/test_configuration_schema.py b/tests/test_configuration_schema.py index 8833923..d9a5d56 100644 --- a/tests/test_configuration_schema.py +++ b/tests/test_configuration_schema.py @@ -133,7 +133,10 @@ def generate_extraneous_keys() -> Generator[dict[str, Any], None, None]: "integrations": { next(iter(FULL_CONFIG["integrations"])): {e_key: "extraneous_value"} }, - "config": {e_key: "extraneous_value", "google": {e_key: "extraneous_value"}}, + "config": { + e_key: "extraneous_value", + "google": {e_key: "extraneous_value"}, + }, } # Create a copy of the configuration which the inner function will modify @@ -335,7 +338,6 @@ def generate_bad_types() -> Generator[dict[str, Any], None, None]: class TestConfigurationSchema(unittest.TestCase): - def test_valid_configurations(self): count = 0 diff --git a/tests/test_update_gdoc.py b/tests/test_update_gdoc.py index 55b8e80..6267c95 100644 --- a/tests/test_update_gdoc.py +++ b/tests/test_update_gdoc.py @@ -120,7 +120,10 @@ def test_get_app_credentials_file_with_no_dir(self): def test_app_credentials_file_no_dir(self): for entry, expected_dir in ( ("./my_app_credentials.json", Path(".")), - ("partial_dir/my_app_credentials.json", platformdirs.user_config_path("")), + ( + "partial_dir/my_app_credentials.json", + platformdirs.user_config_path(""), + ), ("/opt/subdir/my_app_credentials.json", Path("")), ): config = {"google": {"app_credentials_file": entry}}