Skip to content

Commit 18d53e2

Browse files
feat: Add support for harness CI
1 parent 2be4e29 commit 18d53e2

4 files changed

Lines changed: 151 additions & 0 deletions

File tree

codecov-cli/codecov_cli/helpers/ci_adapters/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from codecov_cli.helpers.ci_adapters.droneci import DroneCIAdapter
1515
from codecov_cli.helpers.ci_adapters.github_actions import GithubActionsCIAdapter
1616
from codecov_cli.helpers.ci_adapters.gitlab_ci import GitlabCIAdapter
17+
from codecov_cli.helpers.ci_adapters.harness import HarnessAdapter
1718
from codecov_cli.helpers.ci_adapters.heroku import HerokuCIAdapter
1819
from codecov_cli.helpers.ci_adapters.jenkins import JenkinsAdapter
1920
from codecov_cli.helpers.ci_adapters.local import LocalAdapter
@@ -48,6 +49,7 @@ def get_ci_providers_list():
4849
BitriseCIAdapter(),
4950
AppveyorCIAdapter(),
5051
WoodpeckerCIAdapter(),
52+
HarnessAdapter(),
5153
HerokuCIAdapter(),
5254
DroneCIAdapter(),
5355
BuildkiteAdapter(),
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import os
2+
3+
from codecov_cli.helpers.ci_adapters.base import CIAdapterBase
4+
5+
# https://developer.harness.io/docs/continuous-integration/troubleshoot-ci/ci-env-var/
6+
7+
# Uses CI_ prefixed environment variables variant if available and DRONE_ prefixed environment variables variant if not
8+
# The DRONE variables overlap with the Drone CI Adapter as Harness CI is built on top
9+
class HarnessAdapter(CIAdapterBase):
10+
def detect(self) -> bool:
11+
return os.getenv("DRONE") == "true"
12+
13+
def _get_branch(self):
14+
return os.getenv("DRONE_COMMIT_BRANCH")
15+
16+
def _get_commit_sha(self):
17+
return os.getenv("DRONE_COMMIT_SHA")
18+
19+
def _get_pull_request_number(self):
20+
return os.getenv("DRONE_PULL_REQUEST")
21+
22+
def _get_job_code(self):
23+
return None
24+
25+
def _get_build_code(self):
26+
return os.getenv("CI_BUILD_NUMBER")
27+
28+
def _get_build_url(self):
29+
return os.getenv("CI_BUILD_LINK")
30+
31+
def _get_slug(self):
32+
return os.getenv("CI_REPO")
33+
34+
def _get_service(self):
35+
return "harness"
36+
37+
def get_service_name(self):
38+
return "Harness"
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
import os
2+
from enum import Enum
3+
4+
import pytest
5+
6+
from codecov_cli.fallbacks import FallbackFieldEnum
7+
from codecov_cli.helpers.ci_adapters import HarnessAdapter
8+
9+
10+
class HarnessEnvEnum(str, Enum):
11+
CI_BUILD_LINK = "CI_BUILD_LINK"
12+
CI_BUILD_NUMBER = "CI_BUILD_NUMBER"
13+
CI_REPO = "CI_REPO"
14+
DRONE = "DRONE"
15+
DRONE_COMMIT_BRANCH = "DRONE_COMMIT_BRANCH"
16+
DRONE_COMMIT_SHA = "DRONE_COMMIT_SHA"
17+
DRONE_PULL_REQUEST = "DRONE_PULL_REQUEST"
18+
19+
class TestHarnessCI(object):
20+
@pytest.mark.parametrize(
21+
"env_dict,expected",
22+
[
23+
({}, False),
24+
({HarnessEnvEnum.DRONE: "true"}, True),
25+
],
26+
)
27+
def test_detect(self, env_dict, expected, mocker):
28+
mocker.patch.dict(os.environ, env_dict)
29+
actual = HarnessAdapter().detect()
30+
assert actual == expected
31+
32+
@pytest.mark.parametrize(
33+
"env_dict,expected",
34+
[
35+
({}, None),
36+
({HarnessEnvEnum.DRONE_COMMIT_BRANCH: "branch"}, "branch"),
37+
],
38+
)
39+
def test_branch(self, env_dict, expected, mocker):
40+
mocker.patch.dict(os.environ, env_dict)
41+
actual = HarnessAdapter().get_fallback_value(FallbackFieldEnum.branch)
42+
assert actual == expected
43+
44+
@pytest.mark.parametrize(
45+
"env_dict,expected",
46+
[
47+
({}, None),
48+
({HarnessEnvEnum.DRONE_COMMIT_SHA: "sha"}, "sha"),
49+
],
50+
)
51+
def test_commit_sha(self, env_dict, expected, mocker):
52+
mocker.patch.dict(os.environ, env_dict)
53+
actual = HarnessAdapter().get_fallback_value(FallbackFieldEnum.commit_sha)
54+
assert actual == expected
55+
56+
@pytest.mark.parametrize(
57+
"env_dict,expected",
58+
[
59+
({}, None),
60+
({HarnessEnvEnum.DRONE_PULL_REQUEST: "123"}, "123"),
61+
],
62+
)
63+
def test_pull_request_number(self, env_dict, expected, mocker):
64+
mocker.patch.dict(os.environ, env_dict)
65+
actual = HarnessAdapter().get_fallback_value(FallbackFieldEnum.pull_request_number)
66+
assert actual == expected
67+
68+
@pytest.mark.parametrize(
69+
"env_dict,expected",
70+
[
71+
({}, None),
72+
({HarnessEnvEnum.CI_BUILD_NUMBER: "123"}, "123"),
73+
],
74+
)
75+
def test_build_code(self, env_dict, expected, mocker):
76+
mocker.patch.dict(os.environ, env_dict)
77+
actual = HarnessAdapter().get_fallback_value(FallbackFieldEnum.build_code)
78+
assert actual == expected
79+
80+
@pytest.mark.parametrize(
81+
"env_dict,expected",
82+
[
83+
({}, None),
84+
({HarnessEnvEnum.CI_BUILD_LINK: "https://example.com"}, "https://example.com"),
85+
],
86+
)
87+
def test_build_url(self, env_dict, expected, mocker):
88+
mocker.patch.dict(os.environ, env_dict)
89+
actual = HarnessAdapter().get_fallback_value(FallbackFieldEnum.build_url)
90+
assert actual == expected
91+
92+
@pytest.mark.parametrize(
93+
"env_dict,expected",
94+
[
95+
({}, None),
96+
({HarnessEnvEnum.CI_REPO: "repo"}, "repo"),
97+
],
98+
)
99+
def test_slug(self, env_dict, expected, mocker):
100+
mocker.patch.dict(os.environ, env_dict)
101+
actual = HarnessAdapter().get_fallback_value(FallbackFieldEnum.slug)
102+
assert actual == expected
103+
104+
def test_service(self):
105+
assert (
106+
HarnessAdapter().get_fallback_value(FallbackFieldEnum.service) == "harness"
107+
)

codecov-cli/tests/helpers/test_ci_adapter_selection.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
DroneCIAdapter,
1313
GithubActionsCIAdapter,
1414
GitlabCIAdapter,
15+
HarnessAdapter,
1516
HerokuCIAdapter,
1617
JenkinsAdapter,
1718
LocalAdapter,
@@ -53,6 +54,9 @@ def test_returns_woodpecker(self):
5354
def test_returns_teamcity(self):
5455
assert isinstance(get_ci_adapter("teamcity"), TeamcityAdapter)
5556

57+
def test_returns_harness(self):
58+
assert isinstance(get_ci_adapter("harness"), HarnessAdapter)
59+
5660
def test_returns_herokuci(self):
5761
assert isinstance(get_ci_adapter("heroku"), HerokuCIAdapter)
5862

0 commit comments

Comments
 (0)