-
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: split tracer setup code in its own part (#25)
This will allow to replace the MergifyTracer dynamically in tests for easier scenario testing.
- Loading branch information
Showing
7 changed files
with
271 additions
and
131 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
import dataclasses | ||
import os | ||
|
||
import opentelemetry.sdk.resources | ||
from opentelemetry.sdk.trace import export | ||
from opentelemetry import context | ||
from opentelemetry.sdk.trace import TracerProvider, SpanProcessor, Span | ||
from opentelemetry.exporter.otlp.proto.http import Compression | ||
from opentelemetry.exporter.otlp.proto.http.trace_exporter import ( | ||
OTLPSpanExporter, | ||
) | ||
|
||
from pytest_mergify import utils | ||
|
||
import pytest_opentelemetry.instrumentation | ||
import pytest_mergify.resources.ci as resources_ci | ||
import pytest_mergify.resources.github_actions as resources_gha | ||
|
||
|
||
class InterceptingSpanProcessor(SpanProcessor): | ||
trace_id: None | int | ||
|
||
def __init__(self) -> None: | ||
self.trace_id = None | ||
|
||
def on_start( | ||
self, span: Span, parent_context: context.Context | None = None | ||
) -> None: | ||
if span.attributes is not None and any( | ||
"pytest" in attr for attr in span.attributes | ||
): | ||
self.trace_id = span.context.trace_id | ||
|
||
|
||
@dataclasses.dataclass | ||
class MergifyTracer: | ||
token: str | None = dataclasses.field( | ||
default_factory=lambda: os.environ.get("MERGIFY_TOKEN") | ||
) | ||
repo_name: str | None = dataclasses.field(default_factory=utils.get_repository_name) | ||
interceptor: InterceptingSpanProcessor | None = None | ||
api_url: str = dataclasses.field( | ||
default_factory=lambda: os.environ.get( | ||
"MERGIFY_API_URL", "https://api.mergify.com" | ||
) | ||
) | ||
exporter: export.SpanExporter | None = dataclasses.field(init=False, default=None) | ||
tracer: opentelemetry.trace.Tracer | None = dataclasses.field( | ||
init=False, default=None | ||
) | ||
tracer_provider: opentelemetry.sdk.trace.TracerProvider | None = dataclasses.field( | ||
init=False, default=None | ||
) | ||
|
||
def __post_init__(self) -> None: | ||
span_processor: SpanProcessor | ||
|
||
if os.environ.get("PYTEST_MERGIFY_DEBUG"): | ||
self.exporter = export.ConsoleSpanExporter() | ||
span_processor = export.SimpleSpanProcessor(self.exporter) | ||
elif utils.strtobool(os.environ.get("_PYTEST_MERGIFY_TEST", "false")): | ||
from opentelemetry.sdk.trace.export.in_memory_span_exporter import ( | ||
InMemorySpanExporter, | ||
) | ||
|
||
self.exporter = InMemorySpanExporter() | ||
span_processor = export.SimpleSpanProcessor(self.exporter) | ||
elif self.token: | ||
if self.repo_name is None: | ||
return | ||
|
||
self.exporter = OTLPSpanExporter( | ||
endpoint=f"{self.api_url}/v1/repos/{self.repo_name}/ci/traces", | ||
headers={"Authorization": f"Bearer {self.token}"}, | ||
compression=Compression.Gzip, | ||
) | ||
span_processor = export.BatchSpanProcessor(self.exporter) | ||
else: | ||
return | ||
|
||
resources_gha.GitHubActionsResourceDetector().detect() | ||
resource = opentelemetry.sdk.resources.get_aggregated_resources( | ||
[ | ||
resources_ci.CIResourceDetector(), | ||
resources_gha.GitHubActionsResourceDetector(), | ||
] | ||
) | ||
|
||
self.tracer_provider = TracerProvider(resource=resource) | ||
|
||
self.tracer_provider.add_span_processor(span_processor) | ||
|
||
if self.ci_supports_trace_interception(): | ||
self.interceptor = InterceptingSpanProcessor() | ||
self.tracer_provider.add_span_processor(self.interceptor) | ||
|
||
self.tracer = self.tracer_provider.get_tracer("pytest-mergify") | ||
|
||
# Replace tracer of pytest-opentelemetry | ||
pytest_opentelemetry.instrumentation.tracer = self.tracer | ||
|
||
def ci_supports_trace_interception(self) -> bool: | ||
return utils.get_ci_provider() == "github_actions" |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,46 @@ | ||
import os | ||
import collections.abc | ||
import typing | ||
|
||
import pytest | ||
|
||
# Set this before we call any part of our plugin | ||
def pytest_cmdline_main() -> None: | ||
os.environ["CI"] = "1" | ||
os.environ["_PYTEST_MERGIFY_TEST"] = "1" | ||
os.environ["MERGIFY_API_URL"] = "https://localhost/v1/ci/traces" | ||
import _pytest.config | ||
|
||
from pytest_mergify import tracer | ||
|
||
pytest_plugins = ["pytester"] | ||
|
||
|
||
ReconfigureT = typing.Callable[[dict[str, str]], None] | ||
|
||
|
||
@pytest.fixture | ||
def reconfigure_mergify_tracer( | ||
pytestconfig: _pytest.config.Config, | ||
monkeypatch: pytest.MonkeyPatch, | ||
) -> collections.abc.Generator[ReconfigureT, None, None]: | ||
# Always override API | ||
monkeypatch.setenv("MERGIFY_API_URL", "http://localhost:9999") | ||
|
||
plugin = pytestconfig.pluginmanager.get_plugin("PytestMergify") | ||
assert plugin is not None | ||
old_tracer: tracer.MergifyTracer = plugin.mergify_tracer | ||
|
||
def _reconfigure(env: dict[str, str]) -> None: | ||
# Set environment variables | ||
for key, value in env.items(): | ||
monkeypatch.setenv(key, value) | ||
plugin.reconfigure() | ||
|
||
yield _reconfigure | ||
if plugin.mergify_tracer.tracer_provider is not None: | ||
plugin.mergify_tracer.tracer_provider.shutdown() | ||
plugin.mergify_tracer = old_tracer | ||
|
||
|
||
@pytest.fixture | ||
def reconfigure_mergify_tracer_gha( | ||
reconfigure_mergify_tracer: ReconfigureT, | ||
) -> None: | ||
reconfigure_mergify_tracer( | ||
{"GITHUB_ACTIONS": "true", "GITHUB_REPOSITORY": "Mergifyio/pytest-mergify"} | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.