Skip to content

Commit

Permalink
(#50) fix: do not prepend full build urls with jenkins base
Browse files Browse the repository at this point in the history
  • Loading branch information
Artalus authored Jul 26, 2022
2 parents 4fddce8 + a6fd209 commit 2e6adc9
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 25 deletions.
27 changes: 10 additions & 17 deletions src/jenot/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@
import json
import platform
import time
from typing import Literal, NamedTuple, Optional
from typing import Literal, NamedTuple, Optional, cast

from meiga import Error, Success, Failure, Result
import requests
from requests.exceptions import ConnectionError, Timeout
import yaml

from . import log

from jenot import log
from jenot.url import normalize_build_url

class PollResult(NamedTuple):
result: str
Expand All @@ -29,18 +31,6 @@ class IterateDecision(Enum):
INTERNAL_ERROR = autoenum()


def normalize_build_url(url: str, jenkins_base: str) -> str:
if not jenkins_base.endswith('/'):
jenkins_base += '/'
if not url.startswith(jenkins_base):
url = jenkins_base+url
if url.endswith('/consoleFull'):
url = url[:-len('/consoleFull')]
if url.endswith('/console'):
url = url[:-len('/console')]
return url


def iterate(url: str, user: Optional[str], token: Optional[str]) -> tuple[IterateDecision, Optional[PollResult], str]:
url_to_get = f'{url}/api/json'
try:
Expand Down Expand Up @@ -68,7 +58,10 @@ def iterate(url: str, user: Optional[str], token: Optional[str]) -> tuple[Iterat


def run_poll(JENKINS: str, USER: str, TOKEN: str, url: str) -> tuple[Result[PollResult, Error], str]:
url = normalize_build_url(url, JENKINS)
normalized = normalize_build_url(url, JENKINS)
if normalized.is_failure:
return Failure(normalized.value), url
url = cast(str, normalized.unwrap())

conn_errors = 0
MAX_CONN_ERRORS = 5
Expand All @@ -87,10 +80,10 @@ def run_poll(JENKINS: str, USER: str, TOKEN: str, url: str) -> tuple[Result[Poll
if conn_errors < MAX_CONN_ERRORS:
time.sleep(60 * conn_errors)
else:
return Failure(), refined_url
raise NotImplementedError(f'unknown decision {decision}')
else:
log.error(f'Too many ({MAX_CONN_ERRORS}) connection errors, aborting')
return Failure(), refined_url
return Failure('Too many connection errors'), refined_url


def logo(ext: Literal['auto', 'ico', 'png']) -> str:
Expand Down
36 changes: 36 additions & 0 deletions src/jenot/url.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from typing import cast
from urllib.parse import urlparse

from meiga import Result, Error

def validate_jenkins_base(jenkins_base: str) -> Result[str, Error]:
base = urlparse(jenkins_base)
if not base.scheme:
return Result(failure=Error('jenkins base should have scheme'))
if not base.netloc:
return Result(failure=Error('jenkins base should have domain'))
return Result(success=jenkins_base)


def normalize_build_url(url: str, jenkins_base: str) -> Result[str, Error]:
parsed = urlparse(url)
if parsed.scheme:
# got full http://other.jenkins/x, possibly on different domain than `jenkins_base``
url = parsed.geturl()
else:
validation = validate_jenkins_base(jenkins_base)
if validation.is_failure:
return validation
base = cast(str, validation.unwrap())

if not base.endswith('/'):
base += '/'
url = base + url
# TODO: strip all suffixes with regexp or something...
# or make sure that jenkins can handle build/1337/junit/api/json and drop this altogether
url = (url
.rstrip('/consoleFull')
.rstrip('/console')
.rstrip('/')
)
return Result(success=url)
48 changes: 40 additions & 8 deletions test/unit/test_jenot_utils.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,42 @@
from jenot import normalize_build_url
import pytest

def test__normalize_build_url() -> None:
JENKINS = 'http://jenkins'
from jenot.url import normalize_build_url

@pytest.mark.parametrize('host', ['http://jenkins.local'])
@pytest.mark.parametrize('port', ['', ':8080'])
@pytest.mark.parametrize('prefix', ['', '/jenkins'])
def test__normalize_build_url__concat(host: str, port: str, prefix: str) -> None:
JENKINS = f'{host}{port}{prefix}'
BUILD = 'job/kek/123'
RESULT = f'{JENKINS}/{BUILD}'
assert normalize_build_url(f'{BUILD}', JENKINS).unwrap() == RESULT
assert normalize_build_url(f'{BUILD}/', JENKINS).unwrap() == RESULT
assert normalize_build_url(f'{BUILD}/console', JENKINS).unwrap() == RESULT


@pytest.mark.parametrize('host', ['http://jenkins.local'])
@pytest.mark.parametrize('port', ['', ':8080'])
@pytest.mark.parametrize('prefix', ['', '/jenkins'])
def test__normalize_build_url__same_domain(host: str, port: str, prefix: str) -> None:
JENKINS = f'{host}{port}{prefix}'
BUILD = 'job/kek/123'
RESULT = f'{JENKINS}/{BUILD}'
assert normalize_build_url(f'{JENKINS}/{BUILD}', JENKINS).unwrap() == RESULT
assert normalize_build_url(f'{JENKINS}/{BUILD}/', JENKINS).unwrap() == RESULT
assert normalize_build_url(f'{JENKINS}/{BUILD}/console', JENKINS).unwrap() == RESULT


@pytest.mark.parametrize('host', ['http://jenkins.local'])
@pytest.mark.parametrize('port', ['', ':8080'])
@pytest.mark.parametrize('prefix', ['', '/jenkins'])
@pytest.mark.parametrize('other_host', ['http://company'])
@pytest.mark.parametrize('other_port', ['', ':8081'])
@pytest.mark.parametrize('other_prefix', ['', '/other'])
def test__normalize_build_url__different_domain(host: str, port: str, prefix: str, other_host: str, other_port: str, other_prefix: str) -> None:
JENKINS = f'{host}{port}{prefix}'
OTHER = f'{other_host}{other_port}{other_prefix}'
BUILD = 'job/kek/123'
assert normalize_build_url(f'{BUILD}', JENKINS) == f'{JENKINS}/{BUILD}'
assert normalize_build_url(f'{BUILD}/consoleFull', JENKINS) == f'{JENKINS}/{BUILD}'
assert normalize_build_url(f'{BUILD}/console', JENKINS) == f'{JENKINS}/{BUILD}'
assert normalize_build_url(f'{JENKINS}/{BUILD}/console', JENKINS) == f'{JENKINS}/{BUILD}'
assert normalize_build_url(f'{JENKINS}/{BUILD}', JENKINS) == f'{JENKINS}/{BUILD}'
RESULT = f'{OTHER}/{BUILD}'
assert normalize_build_url(f'{OTHER}/{BUILD}', JENKINS).unwrap() == RESULT
assert normalize_build_url(f'{OTHER}/{BUILD}/', JENKINS).unwrap() == RESULT
assert normalize_build_url(f'{OTHER}/{BUILD}/console', JENKINS).unwrap() == RESULT

0 comments on commit 2e6adc9

Please sign in to comment.