From b2e4a60b2b2f6a9f888761935bbd5808e636f467 Mon Sep 17 00:00:00 2001 From: Stephane Geneix Date: Tue, 13 Feb 2024 15:58:23 -0800 Subject: [PATCH 1/6] make airbyte-ci pass a parameter to the java connectors to the location of the logs --- airbyte-ci/connectors/pipelines/README.md | 3 +- .../airbyte_ci/connectors/reports.py | 56 +++++++-- .../connectors/test/steps/java_connectors.py | 4 +- .../test/steps/templates/test_report.html.j2 | 21 ++-- .../pipelines/airbyte_ci/steps/gradle.py | 115 ++++++++---------- .../pipelines/pipelines/models/reports.py | 13 +- .../pipelines/pipelines/models/steps.py | 1 + .../connectors/pipelines/pyproject.toml | 2 +- 8 files changed, 125 insertions(+), 90 deletions(-) diff --git a/airbyte-ci/connectors/pipelines/README.md b/airbyte-ci/connectors/pipelines/README.md index e63b59c46136..7d92fc08cad2 100644 --- a/airbyte-ci/connectors/pipelines/README.md +++ b/airbyte-ci/connectors/pipelines/README.md @@ -644,7 +644,8 @@ E.G.: running Poe tasks on the modified internal packages of the current branch: | Version | PR | Description | | ------- | ---------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | -| 4.3.2 | [#35536](https://github.com/airbytehq/airbyte/pull/35536) | Make QA checks run correctly on `*-strict-encrypt` connectors. | +| 4.4.0 | [#35317](https://github.com/airbytehq/airbyte/pull/35317) | Augment java connector reports to include full logs and junit test results | +| 4.3.2 | [#35536](https://github.com/airbytehq/airbyte/pull/35536) | Make QA checks run correctly on `*-strict-encrypt` connectors. | | 4.3.1 | [#35437](https://github.com/airbytehq/airbyte/pull/35437) | Do not run QA checks on publish, just MetadataValidation. | | 4.3.0 | [#35438](https://github.com/airbytehq/airbyte/pull/35438) | Optionally disable telemetry with environment variable. | | 4.2.4 | [#35325](https://github.com/airbytehq/airbyte/pull/35325) | Use `connectors_qa` for QA checks and remove redundant checks. | diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/reports.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/reports.py index b8265c4385a1..e85e306f50e8 100644 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/reports.py +++ b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/reports.py @@ -4,11 +4,14 @@ from __future__ import annotations import json +import os import webbrowser from dataclasses import dataclass -from typing import TYPE_CHECKING +from pathlib import Path +from types import MappingProxyType +from typing import TYPE_CHECKING, Optional +from zipfile import ZIP_DEFLATED, ZipFile -from anyio import Path from connector_ops.utils import console # type: ignore from jinja2 import Environment, PackageLoader, select_autoescape from pipelines.consts import GCS_PUBLIC_DOMAIN @@ -42,13 +45,19 @@ def report_output_prefix(self) -> str: def html_report_file_name(self) -> str: return self.filename + ".html" + def file_remote_storage_key(self, file_name: str) -> str: + return f"{self.report_output_prefix}/{file_name}" + @property def html_report_remote_storage_key(self) -> str: - return f"{self.report_output_prefix}/{self.html_report_file_name}" + return self.file_remote_storage_key(self.html_report_file_name) + + def file_url(self, file_name: str) -> str: + return f"{GCS_PUBLIC_DOMAIN}/{self.pipeline_context.ci_report_bucket}/{self.file_remote_storage_key(file_name)}" @property def html_report_url(self) -> str: - return f"{GCS_PUBLIC_DOMAIN}/{self.pipeline_context.ci_report_bucket}/{self.html_report_remote_storage_key}" + return self.file_url(self.html_report_file_name) def to_json(self) -> str: """Create a JSON representation of the connector test report. @@ -91,7 +100,11 @@ async def to_html(self) -> str: template = env.get_template("test_report.html.j2") template.globals["StepStatus"] = StepStatus template.globals["format_duration"] = format_duration - local_icon_path = await Path(f"{self.pipeline_context.connector.code_directory}/icon.svg").resolve() + local_icon_path = Path(f"{self.pipeline_context.connector.code_directory}/icon.svg").resolve() + step_result_to_artifact_link = {} + for step_result in self.steps_results: + if test_artifacts_link := await self.upload_path(step_result.test_artifacts_path): + step_result_to_artifact_link[step_result.step.title] = test_artifacts_link template_context = { "connector_name": self.pipeline_context.connector.technical_name, "step_results": self.steps_results, @@ -104,6 +117,8 @@ async def to_html(self) -> str: "git_revision": self.pipeline_context.git_revision, "commit_url": None, "icon_url": local_icon_path.as_uri(), + "report": self, + "step_result_to_artifact_link": MappingProxyType(step_result_to_artifact_link), } if self.pipeline_context.is_ci: @@ -118,7 +133,7 @@ async def to_html(self) -> str: async def save(self) -> None: local_html_path = await self.save_local(self.html_report_file_name, await self.to_html()) - absolute_path = await local_html_path.resolve() + absolute_path = local_html_path.resolve() if self.pipeline_context.enable_report_auto_open: self.pipeline_context.logger.info(f"HTML report saved locally: {absolute_path}") if self.pipeline_context.enable_report_auto_open: @@ -126,7 +141,6 @@ async def save(self) -> None: webbrowser.open(absolute_path.as_uri()) if self.remote_storage_enabled: await self.save_remote(local_html_path, self.html_report_remote_storage_key, "text/html") - self.pipeline_context.logger.info(f"HTML report uploaded to {self.html_report_url}") await super().save() def print(self) -> None: @@ -155,3 +169,31 @@ def print(self) -> None: main_panel = Panel(Group(*to_render), title=main_panel_title, subtitle=duration_subtitle) console.print(main_panel) + + async def upload_path(self, path: Optional[Path]) -> Optional[str]: + if not path or not path.exists(): + return None + if self.pipeline_context.is_local: + return str(path.resolve()) + + zip_file_path = Path(str(path) + ".zip") + with ZipFile(zip_file_path, mode="w") as zip_file: + # lifted from https://github.com/python/cpython/blob/3.12/Lib/zipfile/__init__.py#L2277C9-L2295C44 + def add_to_zip(zf: ZipFile, path_to_zip: str, zippath: str) -> None: + if os.path.isfile(path_to_zip): + zf.write(path_to_zip, zippath, ZIP_DEFLATED) + elif os.path.isdir(path_to_zip): + if zippath: + zf.write(path_to_zip, zippath) + for nm in sorted(os.listdir(path_to_zip)): + add_to_zip(zf, os.path.join(path_to_zip, nm), os.path.join(zippath, nm)) + + add_to_zip(zip_file, str(path), "") + + if not self.remote_storage_enabled: + self.pipeline_context.logger.info(f"remote storage is disable. zip file is at {zip_file_path.resolve()}") + return str(zip_file_path.resolve()) + else: + await self.save_remote(zip_file_path, self.file_remote_storage_key(zip_file_path.name), "application/zip") + self.pipeline_context.logger.info(f"zip file uploaded to {self.file_url(str(zip_file_path))}") + return self.file_url(zip_file_path.name) diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/java_connectors.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/java_connectors.py index c69a0ac4fb42..3143870f7fc8 100644 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/java_connectors.py +++ b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/java_connectors.py @@ -38,7 +38,7 @@ class IntegrationTests(GradleTask): gradle_task_name = "integrationTestJava" mount_connector_secrets = True bind_to_docker_host = True - with_test_report = True + with_test_artifacts = True @property def default_params(self) -> STEP_PARAMS: @@ -80,7 +80,7 @@ class UnitTests(GradleTask): title = "Java Connector Unit Tests" gradle_task_name = "test" bind_to_docker_host = True - with_test_report = True + with_test_artifacts = True def _create_integration_step_args_factory(context: ConnectorContext) -> Callable: diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/templates/test_report.html.j2 b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/templates/test_report.html.j2 index 7835305a7535..bd58b8776e2b 100644 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/templates/test_report.html.j2 +++ b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/templates/test_report.html.j2 @@ -82,7 +82,7 @@ transition: max-height .25s ease-in-out; } .toggle:checked + .lbl-toggle + .collapsible-content { - max-height: 100vh; + max-height: 70vh; } .toggle:checked + .lbl-toggle { border-bottom-right-radius: 0; @@ -110,6 +110,14 @@ } +

{{ connector_name }} test report