def get_build_info(last_number=0): server = _get_server_instance() job = server.get_job('build') last_one_build = job.__dict__['_data']['builds'][last_number] url = last_one_build['url'] number = last_one_build['number'] obj = Build(url, number, job) para = obj.get_params() print(para) repo_name = para['REPO_NAME'] pjt_name = para['PROJECT_NAME'] status = obj.get_status() timestamp = obj.get_timestamp().strftime("%Y-%m-%d %H:%M:%S") return (timestamp, repo_name, pjt_name, number, status)
def get_build_result(name, url, number): server = get_server_instance() job = server.get_job(name) try: obj = Build(url, number, job) console = obj.get_console() if obj.is_running(): return console, False, '构建中' elif obj.is_good(): return console, True, '构建成功' else: return console, False, '构建失败' except: return '准备构建中,耐心等待', False, '准备构建中,耐心等待'
def test_build_depth(self, get_data_mock): Build('http://halob:8080/job/foo/98', 98, self.j, depth=0) get_data_mock.assert_called_with( 'http://halob:8080/job/foo/98/api/' 'python', tree=None, params={'depth': 0})
def get_build(self, buildnumber): assert isinstance(buildnumber, int) try: url = self.get_build_dict()[buildnumber] return Build(url, buildnumber, job=self) except KeyError: raise NotFound('Build #%s not found' % buildnumber)
def build(job, monkeypatch): def fake_poll(cls, tree=None): # pylint: disable=unused-argument return configs.BUILD_DATA monkeypatch.setattr(Build, '_poll', fake_poll) return Build('http://', 97, job)
def get_job_buildhistory(self, jobname): server = self.get_server_instance() job = server[jobname] data = job.__dict__['_data']['builds'] job_build_list = [] for i in data: job_build_dic = {} lll = Build(i['url'], i['number'], job) lll_dic = lll.get_data(i['url'] + 'api/python/') timest = lll_dic['timestamp'] / 1000 job_build_dic['buildtime'] = time.strftime("%Y-%m-%d", time.localtime(timest)) job_build_dic['status'] = lll_dic['result'] job_build_dic['buildnum'] = lll_dic['number'] job_build_list.append(job_build_dic) return job_build_list
def build(jenkins, job, monkeypatch): def fake_get_data(cls, url, params=None, tree=None): # pylint: disable=unused-argument return BUILD_DATA_FAIL monkeypatch.setattr(JenkinsBase, 'get_data', fake_get_data) return Build('http://localhost:800/view/Buildampel/job/Fahrzeug-Server/3119/', 3119, job)
def get_build_metadata(self, buildnumber): """ Get the build metadata for a given build number. For large builds with tons of tests, this method is faster than get_build by returning less data. """ assert type(buildnumber) == int url = self.get_build_dict()[buildnumber] return Build(url, buildnumber, job=self, depth=0)
class test_build(unittest.TestCase): DATA = { 'actions': [{'causes': [{'shortDescription': 'Started by user anonymous', 'userId': None, 'userName': '******'}]}], 'artifacts': [], 'building': False, 'builtOn': '', 'changeSet': {'items': [], 'kind': None}, 'culprits': [], 'description': None, 'duration': 106, 'estimatedDuration': 106, 'executor': None, 'fullDisplayName': 'foo #1', 'id': '2013-05-31_23-15-40', 'keepLog': False, 'number': 1, 'result': 'SUCCESS', 'timestamp': 1370042140000, 'url': 'http://*****:*****@mock.patch.object(Build, '_poll') def setUp(self, _poll): _poll.return_value = self.DATA self.j = mock.MagicMock() # Job self.j.name = 'FooJob' self.b = Build('http://', 97, self.j) def test_timestamp(self): self.assertIsInstance(self.b.get_timestamp(), datetime.datetime) expected = pytz.utc.localize( datetime.datetime(2013, 5, 31, 23, 15, 40)) self.assertEqual(self.b.get_timestamp(), expected) def testName(self): with self.assertRaises(AttributeError): _ = self.b.id() self.assertEquals(self.b.name, 'foo #1')
def get_build_metadata(self, buildnumber): """ Get the build metadata for a given build number. For large builds with tons of tests, this method is faster than get_build by returning less data. """ assert isinstance(buildnumber, int) try: url = self.get_build_dict()[buildnumber] return Build(url, buildnumber, job=self, depth=0) except KeyError: raise NotFound('Build #%s not found' % buildnumber)
class jobInfo(Job): def __init__(self, jobname, buildnum, **kwargs): super().__init__(**kwargs) for i in self.server[jobname].__dict__['_data']['builds']: if i['number'] == buildnum: self.obj = Build(i['url'], i['number'], self.server[jobname]) break def getBuildConsole(self): return json.dumps(self.obj.get_console()) def getDownstreamBuild(self): downstream = [] for i in self.obj.get_console().split('\n'): if "Starting building:" in i: print(i) downstream.append({ 'name': i.split(' ')[2], 'buildnum': i.split(' ')[3].strip('#') }) return json.dumps(downstream) def getUpstreamBuild(self): print(self.obj.get_upstream_build()) print(self.obj.get_upstream_build_number()) print(self.obj.get_upstream_job()) return json.dumps(self.obj.get_upstream_build_number())
def create_build_json(job, buildnumber, monkeypatch): def fake_get_data(cls, url, params=None, tree=None): # pylint: disable=unused-argument return { "_class": "org.jenkinsci.plugins.workflow.job.WorkflowRun", "actions": [], "artifacts": [], "building": False, "description": None, "displayName": "#3119", "duration": 1208714, "estimatedDuration": 749457, "executor": None, "fullDisplayName": "Fahrzeug-Server #3119", "id": "3119", "keepLog": False, "number": buildnumber, "queueId": 52737, "result": "UNSTABLE", "timestamp": 1583495750710, # 03/06/2020 @ 11:55am (UTC) "url": "http://localhost:800/view/Buildampel/job/Fahrzeug-Server/3119/", "changeSets": [], "culprits": [], "nextBuild": { "number": 3120, "url": "http://localhost:800/view/Buildampel/job/Fahrzeug-Server/3120/" }, "previousBuild": { "number": 3112, "url": "http://localhost:800/view/Buildampel/job/Fahrzeug-Server/3112/" } } monkeypatch.setattr(JenkinsBase, 'get_data', fake_get_data) #build.get_data = mock.MagicMock(return_value=fake_get_data) return Build( 'http://localhost:800/view/Buildampel/job/Fahrzeug-Server/3119/', buildnumber, job)
def test_poll_cache(self, _poll): # only gets called once in interval b = Build('http://', 97, self.j, poll_cache_timeout=1) for i in range(2): b.poll() self.assertEquals(_poll.call_count, 1) b.poll(True) # test force poll self.assertEquals(_poll.call_count, 2) # ensure it gets called again after cache timeout _poll.reset_mock() time.sleep(1.1) b.poll() self.assertTrue(_poll.called) # ensure it is disabled by default _poll.reset_mock() for i in range(2): self.b.poll() self.assertEquals(_poll.call_count, 2) self.assertIsNone(self.b.poll_cache_expires)
def __init__(self, build: Build) -> None: """ Creates a container class for a Jenkins Build object. Attributes: - timestamp: Build timestamp in UTC - number: Build number - failed: False if build was successful, True if not - failed_tests: List of failed test names :param build: A Build object from the Jenkins server """ self.timestamp = build.get_timestamp().strftime('%m-%d-%Y %I:%M %p') self.number = build.get_number() self.status = build.get_status() if self.status == 'SUCCESS': self.failed = False else: self.failed = True self.failed_tests = [] # type: List[str] self.test_count = 0 self.fail_count = 0 if self.status != 'ABORTED' and build.has_resultset(): self.test_count = build.get_actions()['totalCount'] self.fail_count = build.get_actions()['failCount'] result_set = build.get_resultset() for _, result in result_set.iteritems(): test_name = result.identifier() if result.status == 'FAILED' or result.status == 'REGRESSION': self.failed_tests.append(test_name)
def run_jenkins_job(phrase): job_name = JOBS_MAPPING.get(phrase, None) if job_name is None: return "任务不存在" try: server = Jenkins(JENKINS_URL, username=JENKINS_USER, password=JENKINS_PASS) except HTTPError as ex: return "jenkins连接出错: %s" % ex job = server[job_name] job_buildid = server.get_job(job_name).get_next_build_number() run_job = job.invoke() time.sleep(10) # 查看任务状态 url = f'''{job.baseurl}/{job_buildid}/''' obj = Build(url, job_buildid, job) obj.block() # obj 只是获取当时的任务状态,所以需要等待任务执行完,再获取一次状态 obj = Build(url, job_buildid, job) result = f'''{phrase}完成, 任务名称: {obj.name}, 执行结果:{obj.get_status()}, 耗时: {obj.get_duration().total_seconds()}秒''' return result
def setUp(self, _poll): _poll.return_value = self.DATA self.j = mock.MagicMock() # Job self.j.name = 'FooJob' self.b = Build('http://', 97, self.j)
def setUp(self, _poll): _poll.return_value = self.DATA self.j = mock.MagicMock() # Job self.j.name = "FooJob" self.b = Build("http://", 97, self.j)
class test_build(unittest.TestCase): DATA = { "actions": [ {"causes": [{"shortDescription": "Started by an SCM change"}]}, {}, { "buildsByBranchName": { "origin/HEAD": { "buildNumber": 2, "buildResult": None, "revision": { "SHA1": "d2a5d435fa2df3bff572bd06e43c86544749c5d2", "branch": [ {"SHA1": "d2a5d435fa2df3bff572bd06e43c86544749c5d2", "name": "origin/HEAD"}, {"SHA1": "d2a5d435fa2df3bff572bd06e43c86544749c5d2", "name": "origin/master"}, ], }, }, "origin/master": { "buildNumber": 2, "buildResult": None, "revision": { "SHA1": "d2a5d435fa2df3bff572bd06e43c86544749c5d2", "branch": [ {"SHA1": "d2a5d435fa2df3bff572bd06e43c86544749c5d2", "name": "origin/HEAD"}, {"SHA1": "d2a5d435fa2df3bff572bd06e43c86544749c5d2", "name": "origin/master"}, ], }, }, "origin/python_3_compatibility": { "buildNumber": 1, "buildResult": None, "revision": { "SHA1": "c9d1c96bc926ff63a5209c51b3ed537e62ea50e6", "branch": [ { "SHA1": "c9d1c96bc926ff63a5209c51b3ed537e62ea50e6", "name": "origin/python_3_compatibility", } ], }, }, "origin/unstable": { "buildNumber": 3, "buildResult": None, "revision": { "SHA1": "7def9ed6e92580f37d00e4980c36c4d36e68f702", "branch": [{"SHA1": "7def9ed6e92580f37d00e4980c36c4d36e68f702", "name": "origin/unstable"}], }, }, }, "lastBuiltRevision": { "SHA1": "7def9ed6e92580f37d00e4980c36c4d36e68f702", "branch": [{"SHA1": "7def9ed6e92580f37d00e4980c36c4d36e68f702", "name": "origin/unstable"}], }, "remoteUrls": ["https://github.com/salimfadhley/jenkinsapi.git"], "scmName": "", }, {}, {}, ], "artifacts": [], "building": False, "builtOn": "", "changeSet": {"items": [], "kind": "git"}, "culprits": [], "description": None, "duration": 1051, "estimatedDuration": 2260, "executor": None, "fullDisplayName": "git_yssrtigfds #3", "id": "2013-06-30_01-54-35", "keepLog": False, "number": 3, "result": "SUCCESS", "timestamp": 1372553675652, "url": "http://*****:*****@mock.patch.object(Build, "_poll") def setUp(self, _poll): _poll.return_value = self.DATA self.j = mock.MagicMock() # Job self.j.name = "FooJob" self.b = Build("http://", 97, self.j) def test_git_scm(self): """ Can we extract git build revision data from a build object? """ self.assertIsInstance(self.b.get_revision(), basestring) self.assertEquals(self.b.get_revision(), "7def9ed6e92580f37d00e4980c36c4d36e68f702")
class test_build(unittest.TestCase): DATA = { 'actions': [{ 'causes': [{ 'shortDescription': 'Started by user anonymous', 'userId': None, 'userName': '******' }] }], 'artifacts': [], 'building': False, 'builtOn': '', 'changeSet': { 'items': [], 'kind': None }, 'culprits': [], 'description': None, 'duration': 106, 'estimatedDuration': 106, 'executor': None, 'fullDisplayName': 'foo #1', 'id': '2013-05-31_23-15-40', 'keepLog': False, 'number': 1, 'result': 'SUCCESS', 'timestamp': 1370042140000, 'url': 'http://*****:*****@mock.patch.object(Build, '_poll') def setUp(self, _poll): _poll.return_value = self.DATA self.j = mock.MagicMock() # Job self.j.name = 'FooJob' self.b = Build('http://', 97, self.j) def test_timestamp(self): self.assertIsInstance(self.b.get_timestamp(), datetime.datetime) expected = pytz.utc.localize(datetime.datetime(2013, 5, 31, 23, 15, 40)) self.assertEqual(self.b.get_timestamp(), expected) def testName(self): with self.assertRaises(AttributeError): _ = self.b.id() self.assertEquals(self.b.name, 'foo #1')
class test_build(unittest.TestCase): DATA = { 'actions': [{ 'causes': [{ 'shortDescription': 'Started by user anonymous', 'userId': None, 'userName': '******' }] }], 'artifacts': [], 'building': False, 'builtOn': '', 'changeSet': { 'items': [], 'kind': None }, 'culprits': [], 'description': None, "duration": 5782, 'estimatedDuration': 106, 'executor': None, "fingerprint": [{ "fileName": "BuildId.json", "hash": "e3850a45ab64aa34c1aa66e30c1a8977", "original": { "name": "ArtifactGenerateJob", "number": 469 }, "timestamp": 1380270162488, "usage": [{ "name": "SingleJob", "ranges": { "ranges": [{ "end": 567, "start": 566 }] } }, { "name": "MultipleJobs", "ranges": { "ranges": [{ "end": 150, "start": 139 }] } }] }], 'fullDisplayName': 'foo #1', 'id': '2013-05-31_23-15-40', 'keepLog': False, 'number': 1, 'result': 'SUCCESS', 'timestamp': 1370042140000, 'url': 'http://*****:*****@mock.patch.object(Build, '_poll') def setUp(self, _poll): _poll.return_value = self.DATA self.j = mock.MagicMock() # Job self.j.name = 'FooJob' self.b = Build('http://', 97, self.j) def test_timestamp(self): self.assertIsInstance(self.b.get_timestamp(), datetime.datetime) expected = pytz.utc.localize(datetime.datetime(2013, 5, 31, 23, 15, 40)) self.assertEqual(self.b.get_timestamp(), expected) def testName(self): with self.assertRaises(AttributeError): self.b.id() self.assertEquals(self.b.name, 'foo #1') def test_duration(self): expected = datetime.timedelta(milliseconds=5782) self.assertEquals(self.b.get_duration(), expected) self.assertEquals(self.b.get_duration().seconds, 5) self.assertEquals(self.b.get_duration().microseconds, 782000) self.assertEquals(str(self.b.get_duration()), '0:00:05.782000') @mock.patch.object(Build, 'get_data') def test_build_depth(self, get_data_mock): build = Build('http://halob:8080/job/foo/98', 98, self.j, depth=0) get_data_mock.assert_called_with( 'http://halob:8080/job/foo/98/api/python?depth=0')
def test_build_depth(self, get_data_mock): build = Build('http://halob:8080/job/foo/98', 98, self.j, depth=0) get_data_mock.assert_called_with( 'http://halob:8080/job/foo/98/api/python?depth=0')
class test_build(unittest.TestCase): DATA = { 'actions': [ { 'causes': [{'shortDescription': 'Started by an SCM change'}] }, {}, { 'buildsByBranchName': { 'origin/HEAD': { 'buildNumber': 2, 'buildResult': None, 'revision': { 'SHA1': 'd2a5d435fa2df3bff572bd06e43c86544749c5d2', 'branch': [ {'SHA1': 'd2a5d435fa2df3bff572bd06e43c86544749c5d2', 'name': 'origin/HEAD'}, {'SHA1': 'd2a5d435fa2df3bff572bd06e43c86544749c5d2', 'name': 'origin/master'} ] } }, 'origin/master': { 'buildNumber': 2, 'buildResult': None, 'revision': { 'SHA1': 'd2a5d435fa2df3bff572bd06e43c86544749c5d2', 'branch': [ {'SHA1': 'd2a5d435fa2df3bff572bd06e43c86544749c5d2', 'name': 'origin/HEAD'}, {'SHA1': 'd2a5d435fa2df3bff572bd06e43c86544749c5d2', 'name': 'origin/master'} ] } }, 'origin/python_3_compatibility': { 'buildNumber': 1, 'buildResult': None, 'revision': { 'SHA1': 'c9d1c96bc926ff63a5209c51b3ed537e62ea50e6', 'branch': [ {'SHA1': 'c9d1c96bc926ff63a5209c51b3ed537e62ea50e6', 'name': 'origin/python_3_compatibility'} ] } }, 'origin/unstable': { 'buildNumber': 3, 'buildResult': None, 'revision': { 'SHA1': '7def9ed6e92580f37d00e4980c36c4d36e68f702', 'branch': [ {'SHA1': '7def9ed6e92580f37d00e4980c36c4d36e68f702', 'name': 'origin/unstable'} ] } } }, 'lastBuiltRevision': { 'SHA1': '7def9ed6e92580f37d00e4980c36c4d36e68f702', 'branch': [ {'SHA1': '7def9ed6e92580f37d00e4980c36c4d36e68f702', 'name': 'origin/unstable'} ] }, 'remoteUrls': ['https://github.com/salimfadhley/jenkinsapi.git'], 'scmName': '' }, {}, {} ], 'artifacts': [], 'building': False, 'builtOn': '', 'changeSet': {'items': [], 'kind': 'git'}, 'culprits': [], 'description': None, 'duration': 1051, 'estimatedDuration': 2260, 'executor': None, 'fullDisplayName': 'git_yssrtigfds #3', 'id': '2013-06-30_01-54-35', 'keepLog': False, 'number': 3, 'result': 'SUCCESS', 'timestamp': 1372553675652, 'url': 'http://*****:*****@mock.patch.object(Build, '_poll') def setUp(self, _poll): _poll.return_value = self.DATA self.j = mock.MagicMock() # Job self.j.name = 'FooJob' self.b = Build('http://', 97, self.j) def test_git_scm(self): """ Can we extract git build revision data from a build object? """ try: self.assertIsInstance(self.b.get_revision(), basestring) except NameError: # Python3 self.assertIsInstance(self.b.get_revision(), str) self.assertEquals(self.b.get_revision(), '7def9ed6e92580f37d00e4980c36c4d36e68f702') def test_git_revision_branch(self): """ Can we extract git build branch from a build object? """ self.assertIsInstance(self.b.get_revision_branch(), list) self.assertEquals(len(self.b.get_revision_branch()), 1) self.assertIsInstance(self.b.get_revision_branch()[0], dict) self.assertEquals(self.b.get_revision_branch()[0]['SHA1'], '7def9ed6e92580f37d00e4980c36c4d36e68f702') self.assertEquals(self.b.get_revision_branch()[0]['name'], 'origin/unstable')
class TestBuildCase(unittest.TestCase): DATA = { 'actions': [{ 'causes': [{ 'shortDescription': 'Started by user anonymous', 'userId': None, 'userName': '******' }] }, None, { 'causes': [] }], 'artifacts': [], 'building': False, 'builtOn': 'localhost', 'changeSet': { 'items': [], 'kind': None }, 'culprits': [], 'description': 'Best build ever!', "duration": 5782, 'estimatedDuration': 106, 'executor': None, "fingerprint": [{ "fileName": "BuildId.json", "hash": "e3850a45ab64aa34c1aa66e30c1a8977", "original": { "name": "ArtifactGenerateJob", "number": 469 }, "timestamp": 1380270162488, "usage": [{ "name": "SingleJob", "ranges": { "ranges": [{ "end": 567, "start": 566 }] } }, { "name": "MultipleJobs", "ranges": { "ranges": [{ "end": 150, "start": 139 }] } }] }], 'fullDisplayName': 'foo #1', 'id': '2013-05-31_23-15-40', 'keepLog': False, 'number': 1, 'result': 'SUCCESS', 'timestamp': 1370042140000, 'url': 'http://*****:*****@mock.patch.object(Build, '_poll') def setUp(self, _poll): _poll.return_value = self.DATA self.j = mock.MagicMock() # Job self.j.name = 'FooJob' self.b = Build('http://', 97, self.j) def test_timestamp(self): self.assertIsInstance(self.b.get_timestamp(), datetime.datetime) expected = pytz.utc.localize(datetime.datetime(2013, 5, 31, 23, 15, 40)) self.assertEqual(self.b.get_timestamp(), expected) def testName(self): with self.assertRaises(AttributeError): self.b.id() self.assertEquals(self.b.name, 'foo #1') def test_duration(self): expected = datetime.timedelta(milliseconds=5782) self.assertEquals(self.b.get_duration(), expected) self.assertEquals(self.b.get_duration().seconds, 5) self.assertEquals(self.b.get_duration().microseconds, 782000) self.assertEquals(str(self.b.get_duration()), '0:00:05.782000') def test_get_causes(self): self.assertEquals(self.b.get_causes(), [{ 'shortDescription': 'Started by user anonymous', 'userId': None, 'userName': '******' }]) def test_get_description(self): self.assertEquals(self.b.get_description(), 'Best build ever!') def test_get_slave(self): self.assertEquals(self.b.get_slave(), 'localhost') @mock.patch.object(Build, 'get_data') def test_build_depth(self, get_data_mock): Build('http://*****:*****@mock.patch.object(Build, '__init__') def test_get_matrix_runs(self, build_init_mock): build_init_mock.return_value = None for build in self.b.get_matrix_runs(): continue build_init_mock.assert_called_once_with( 'http//localhost:8080/job/foo/SHARD_NUM=1/1/', 1, self.j) def test_get_params(self): expected = { 'first_param': 'first_value', 'second_param': 'second_value', } self.b._data = { 'actions': [{ 'parameters': [ { 'name': 'first_param', 'value': 'first_value' }, { 'name': 'second_param', 'value': 'second_value' }, ] }] } params = self.b.get_params() self.assertDictEqual(params, expected) def test_get_params_different_order(self): """ Dictionary with `parameters` key is not always the first element in `actions` list, so we need to search through whole array. This test covers such a case """ expected = { 'first_param': 'first_value', 'second_param': 'second_value', } self.b._data = { 'actions': [{ 'not_parameters': 'some_data', }, { 'another_action': 'some_value', }, { 'parameters': [ { 'name': 'first_param', 'value': 'first_value' }, { 'name': 'second_param', 'value': 'second_value' }, ] }] } params = self.b.get_params() self.assertDictEqual(params, expected)
class test_build(unittest.TestCase): DATA = { 'actions': [{ 'causes': [{ 'shortDescription': 'Started by an SCM change' }] }, {}, { 'buildsByBranchName': { 'origin/HEAD': { 'buildNumber': 2, 'buildResult': None, 'revision': { 'SHA1': 'd2a5d435fa2df3bff572bd06e43c86544749c5d2', 'branch': [{ 'SHA1': 'd2a5d435fa2df3bff572bd06e43c86544749c5d2', 'name': 'origin/HEAD' }, { 'SHA1': 'd2a5d435fa2df3bff572bd06e43c86544749c5d2', 'name': 'origin/master' }] } }, 'origin/master': { 'buildNumber': 2, 'buildResult': None, 'revision': { 'SHA1': 'd2a5d435fa2df3bff572bd06e43c86544749c5d2', 'branch': [{ 'SHA1': 'd2a5d435fa2df3bff572bd06e43c86544749c5d2', 'name': 'origin/HEAD' }, { 'SHA1': 'd2a5d435fa2df3bff572bd06e43c86544749c5d2', 'name': 'origin/master' }] } }, 'origin/python_3_compatibility': { 'buildNumber': 1, 'buildResult': None, 'revision': { 'SHA1': 'c9d1c96bc926ff63a5209c51b3ed537e62ea50e6', 'branch': [{ 'SHA1': 'c9d1c96bc926ff63a5209c51b3ed537e62ea50e6', 'name': 'origin/python_3_compatibility' }] } }, 'origin/unstable': { 'buildNumber': 3, 'buildResult': None, 'revision': { 'SHA1': '7def9ed6e92580f37d00e4980c36c4d36e68f702', 'branch': [{ 'SHA1': '7def9ed6e92580f37d00e4980c36c4d36e68f702', 'name': 'origin/unstable' }] } } }, 'lastBuiltRevision': { 'SHA1': '7def9ed6e92580f37d00e4980c36c4d36e68f702', 'branch': [{ 'SHA1': '7def9ed6e92580f37d00e4980c36c4d36e68f702', 'name': 'origin/unstable' }] }, 'remoteUrls': ['https://github.com/salimfadhley/jenkinsapi.git'], 'scmName': '' }, {}, {}], 'artifacts': [], 'building': False, 'builtOn': '', 'changeSet': { 'items': [], 'kind': 'git' }, 'culprits': [], 'description': None, 'duration': 1051, 'estimatedDuration': 2260, 'executor': None, 'fullDisplayName': 'git_yssrtigfds #3', 'id': '2013-06-30_01-54-35', 'keepLog': False, 'number': 3, 'result': 'SUCCESS', 'timestamp': 1372553675652, 'url': 'http://*****:*****@mock.patch.object(Build, '_poll') def setUp(self, _poll): _poll.return_value = self.DATA self.j = mock.MagicMock() # Job self.j.name = 'FooJob' self.b = Build('http://', 97, self.j) def test_git_scm(self): """ Can we extract git build revision data from a build object? """ try: self.assertIsInstance(self.b.get_revision(), basestring) except NameError: # Python3 self.assertIsInstance(self.b.get_revision(), str) self.assertEquals(self.b.get_revision(), '7def9ed6e92580f37d00e4980c36c4d36e68f702') def test_git_revision_branch(self): """ Can we extract git build branch from a build object? """ self.assertIsInstance(self.b.get_revision_branch(), list) self.assertEquals(len(self.b.get_revision_branch()), 1) self.assertIsInstance(self.b.get_revision_branch()[0], dict) self.assertEquals(self.b.get_revision_branch()[0]['SHA1'], '7def9ed6e92580f37d00e4980c36c4d36e68f702') self.assertEquals(self.b.get_revision_branch()[0]['name'], 'origin/unstable')
def build_with_diff_baseurl(job_with_diff_baseurl, monkeypatch): def fake_poll(cls, tree=None): # pylint: disable=unused-argument return configs.BUILD_DATA monkeypatch.setattr(Build, '_poll', fake_poll) return Build('http://localhost', 97, job_with_diff_baseurl)
def get_last_build(self): """ Get the last build """ buildinfo = self._data["lastBuild"] return Build(buildinfo["url"], buildinfo["number"], job=self)
def __init__(self, jobname, buildnum, **kwargs): super().__init__(**kwargs) for i in self.server[jobname].__dict__['_data']['builds']: if i['number'] == buildnum: self.obj = Build(i['url'], i['number'], self.server[jobname]) break
class test_build(unittest.TestCase): DATA = { 'actions': [{'causes': [{'shortDescription': 'Started by user anonymous', 'userId': None, 'userName': '******'}]}], 'artifacts': [], 'building': False, 'builtOn': '', 'changeSet': {'items': [], 'kind': None}, 'culprits': [], 'description': None, "duration": 5782, 'estimatedDuration': 106, 'executor': None, "fingerprint": [{"fileName": "BuildId.json", "hash": "e3850a45ab64aa34c1aa66e30c1a8977", "original": {"name": "ArtifactGenerateJob", "number": 469}, "timestamp": 1380270162488, "usage": [{"name": "SingleJob", "ranges": {"ranges": [{"end": 567, "start": 566}]}}, {"name": "MultipleJobs", "ranges": {"ranges": [{"end": 150, "start": 139}]}}] }], 'fullDisplayName': 'foo #1', 'id': '2013-05-31_23-15-40', 'keepLog': False, 'number': 1, 'result': 'SUCCESS', 'timestamp': 1370042140000, 'url': 'http://*****:*****@mock.patch.object(Build, '_poll') def setUp(self, _poll): _poll.return_value = self.DATA self.j = mock.MagicMock() # Job self.j.name = 'FooJob' self.b = Build('http://', 97, self.j) def test_timestamp(self): self.assertIsInstance(self.b.get_timestamp(), datetime.datetime) expected = pytz.utc.localize( datetime.datetime(2013, 5, 31, 23, 15, 40)) self.assertEqual(self.b.get_timestamp(), expected) def testName(self): with self.assertRaises(AttributeError): self.b.id() self.assertEquals(self.b.name, 'foo #1') def test_duration(self): expected = datetime.timedelta(milliseconds=5782) self.assertEquals(self.b.get_duration(), expected) self.assertEquals(self.b.get_duration().seconds, 5) self.assertEquals(self.b.get_duration().microseconds, 782000) self.assertEquals(str(self.b.get_duration()), '0:00:05.782000') @mock.patch.object(Build, '_poll') def test_poll_cache(self, _poll): # only gets called once in interval b = Build('http://', 97, self.j, poll_cache_timeout=1) for i in range(2): b.poll() self.assertEquals(_poll.call_count, 1) b.poll(True) # test force poll self.assertEquals(_poll.call_count, 2) # ensure it gets called again after cache timeout _poll.reset_mock() time.sleep(1.1) b.poll() self.assertTrue(_poll.called) # ensure it is disabled by default _poll.reset_mock() for i in range(2): self.b.poll() self.assertEquals(_poll.call_count, 2) self.assertIsNone(self.b.poll_cache_expires)
class test_build(unittest.TestCase): DATA = { 'actions': [{'causes': [{'shortDescription': 'Started by user anonymous', 'userId': None, 'userName': '******'}]}, None, {'causes': []}], 'artifacts': [], 'building': False, 'builtOn': '', 'changeSet': {'items': [], 'kind': None}, 'culprits': [], 'description': None, "duration": 5782, 'estimatedDuration': 106, 'executor': None, "fingerprint": [{"fileName": "BuildId.json", "hash": "e3850a45ab64aa34c1aa66e30c1a8977", "original": {"name": "ArtifactGenerateJob", "number": 469}, "timestamp": 1380270162488, "usage": [{"name": "SingleJob", "ranges": {"ranges": [{"end": 567, "start": 566}]}}, {"name": "MultipleJobs", "ranges": {"ranges": [{"end": 150, "start": 139}]}}] }], 'fullDisplayName': 'foo #1', 'id': '2013-05-31_23-15-40', 'keepLog': False, 'number': 1, 'result': 'SUCCESS', 'timestamp': 1370042140000, 'url': 'http://*****:*****@mock.patch.object(Build, '_poll') def setUp(self, _poll): _poll.return_value = self.DATA self.j = mock.MagicMock() # Job self.j.name = 'FooJob' self.b = Build('http://', 97, self.j) def test_timestamp(self): self.assertIsInstance(self.b.get_timestamp(), datetime.datetime) expected = pytz.utc.localize( datetime.datetime(2013, 5, 31, 23, 15, 40)) self.assertEqual(self.b.get_timestamp(), expected) def testName(self): with self.assertRaises(AttributeError): self.b.id() self.assertEquals(self.b.name, 'foo #1') def test_duration(self): expected = datetime.timedelta(milliseconds=5782) self.assertEquals(self.b.get_duration(), expected) self.assertEquals(self.b.get_duration().seconds, 5) self.assertEquals(self.b.get_duration().microseconds, 782000) self.assertEquals(str(self.b.get_duration()), '0:00:05.782000') def test_get_causes(self): self.assertEquals(self.b.get_causes(), [{'shortDescription': 'Started by user anonymous', 'userId': None, 'userName': '******'}]) @mock.patch.object(Build, 'get_data') def test_build_depth(self, get_data_mock): build = Build('http://halob:8080/job/foo/98', 98, self.j, depth=0) get_data_mock.assert_called_with('http://halob:8080/job/foo/98/api/python?depth=0') def test_get_revision_no_scm(self): """ with no scm, get_revision should return None """ self.assertEqual(self.b.get_revision(), None)
def watch_jenkins_job(args, settings, **kwargs): from jenkinsapi.jenkins import Jenkins from jenkinsapi.jenkins import JenkinsBase from jenkinsapi.build import Build from jenkinsapi.utils.requester import Requester try: from urllib.parser import urlparse except ImportError: from urlparse import urlparse parser = argparse.ArgumentParser() parser.add_argument( 'url', type=str, nargs=1, help='Jenkins URL to watch' ) parser.add_argument( '--sleep-interval', dest='sleep_interval', default=30, type=int, help='Amount of time to sleep', ) parser.add_argument( '--retries', dest='retries', default=25, type=int, help='Number of times to re-poll Jenkins' ) options = parser.parse_args(args) class NoVerifyRequester(Requester): def get_request_dict(self, *args, **kwargs): request_dict = super(NoVerifyRequester, self).get_request_dict( *args, **kwargs ) request_dict['verify'] = False return request_dict def get_job_name_and_build_number(url): job_build_matcher = re.compile( ".*/job/(?P<job>[^/]+)/(?P<build_number>[^/]+)/.*" ) job, build_no = job_build_matcher.search(url).groups() return job, int(build_no) def get_formal_build_url(jenkins_url, job_name, build_no): return os.path.join( jenkins_url, 'job', job_name, str(build_no) ) def get_jenkins_base_url(url): parsed = urlparse(url) return parsed.scheme + '://' + parsed.netloc job_name, build_no = get_job_name_and_build_number(options.url[0]) jenkins_url = get_jenkins_base_url(options.url[0]) formal_build_url = get_formal_build_url( jenkins_url, job_name, build_no ) try: jenkins = Jenkins( jenkins_url, requester=NoVerifyRequester() ) job = jenkins[job_name] job.RETRY_ATTEMPTS = options.retries build = Build(formal_build_url, build_no, job) while True: if not build.is_running(): if build.is_good(): send_flash_message( settings.device_url, { 'message': 'Jenkins job %s:%s succeeded' % ( job_name, build_no, ), 'blink': [(0, 255, 0), (0, 0, 0)], 'timeout': 20, } ) logger.warn( 'Job %s succeeded', formal_build_url, ) else: send_flash_message( settings.device_url, { 'message': 'Jenkins job %s:%s failed (%s)' % ( job_name, build_no, build.get_status() ), 'blink': [(255, 0, 0), (0, 0, 0)], 'timeout': 20, } ) logger.warn( 'Job %s failed', formal_build_url, ) sys.exit(0) time.sleep(options.sleep_interval) except Exception as e: logger.exception(e)
def get_build(self, buildnumber): assert type(buildnumber) == int url = self.get_build_dict()[buildnumber] return Build(url, buildnumber, job=self)
class test_build(unittest.TestCase): DATA = { "actions": [ {"causes": [{"shortDescription": "Started by user anonymous", "userId": None, "userName": "******"}]} ], "artifacts": [], "building": False, "builtOn": "", "changeSet": {"items": [], "kind": None}, "culprits": [], "description": None, "duration": 5782, "estimatedDuration": 106, "executor": None, "fingerprint": [ { "fileName": "BuildId.json", "hash": "e3850a45ab64aa34c1aa66e30c1a8977", "original": {"name": "ArtifactGenerateJob", "number": 469}, "timestamp": 1380270162488, "usage": [ {"name": "SingleJob", "ranges": {"ranges": [{"end": 567, "start": 566}]}}, {"name": "MultipleJobs", "ranges": {"ranges": [{"end": 150, "start": 139}]}}, ], } ], "fullDisplayName": "foo #1", "id": "2013-05-31_23-15-40", "keepLog": False, "number": 1, "result": "SUCCESS", "timestamp": 1370042140000, "url": "http://*****:*****@mock.patch.object(Build, "_poll") # pylint: disable=W0221 def setUp(self, _poll): _poll.return_value = self.DATA self.j = mock.MagicMock() # Job self.j.name = "FooJob" self.b = Build("http://", 97, self.j) def test_timestamp(self): self.assertIsInstance(self.b.get_timestamp(), datetime.datetime) expected = pytz.utc.localize(datetime.datetime(2013, 5, 31, 23, 15, 40)) self.assertEqual(self.b.get_timestamp(), expected) def testName(self): with self.assertRaises(AttributeError): self.b.id() self.assertEquals(self.b.name, "foo #1") def test_duration(self): expected = datetime.timedelta(milliseconds=5782) self.assertEquals(self.b.get_duration(), expected) self.assertEquals(self.b.get_duration().seconds, 5) self.assertEquals(self.b.get_duration().microseconds, 782000) self.assertEquals(str(self.b.get_duration()), "0:00:05.782000")
def watch_jenkins_job(args, settings, **kwargs): from jenkinsapi.jenkins import Jenkins from jenkinsapi.jenkins import JenkinsBase from jenkinsapi.build import Build from jenkinsapi.utils.requester import Requester try: from urllib.parser import urlparse except ImportError: from urlparse import urlparse parser = argparse.ArgumentParser() parser.add_argument('url', type=str, nargs=1, help='Jenkins URL to watch') parser.add_argument( '--sleep-interval', dest='sleep_interval', default=30, type=int, help='Amount of time to sleep', ) parser.add_argument('--retries', dest='retries', default=25, type=int, help='Number of times to re-poll Jenkins') options = parser.parse_args(args) class NoVerifyRequester(Requester): def get_request_dict(self, *args, **kwargs): request_dict = super(NoVerifyRequester, self).get_request_dict(*args, **kwargs) request_dict['verify'] = False return request_dict def get_job_name_and_build_number(url): job_build_matcher = re.compile( ".*/job/(?P<job>[^/]+)/(?P<build_number>[^/]+)/.*") job, build_no = job_build_matcher.search(url).groups() return job, int(build_no) def get_formal_build_url(jenkins_url, job_name, build_no): return os.path.join(jenkins_url, 'job', job_name, str(build_no)) def get_jenkins_base_url(url): parsed = urlparse(url) return parsed.scheme + '://' + parsed.netloc job_name, build_no = get_job_name_and_build_number(options.url[0]) jenkins_url = get_jenkins_base_url(options.url[0]) formal_build_url = get_formal_build_url(jenkins_url, job_name, build_no) try: jenkins = Jenkins(jenkins_url, requester=NoVerifyRequester()) job = jenkins[job_name] job.RETRY_ATTEMPTS = options.retries build = Build(formal_build_url, build_no, job) while True: if not build.is_running(): if build.is_good(): send_flash_message( settings.device_url, { 'message': 'Jenkins job %s:%s succeeded' % ( job_name, build_no, ), 'blink': [(0, 255, 0), (0, 0, 0)], 'timeout': 20, }) logger.warn( 'Job %s succeeded', formal_build_url, ) else: send_flash_message( settings.device_url, { 'message': 'Jenkins job %s:%s failed (%s)' % (job_name, build_no, build.get_status()), 'blink': [(255, 0, 0), (0, 0, 0)], 'timeout': 20, }) logger.warn( 'Job %s failed', formal_build_url, ) sys.exit(0) time.sleep(options.sleep_interval) except Exception as e: logger.exception(e)
def get_build(self, buildnumber): assert isinstance(buildnumber, int) url = self.get_build_dict()[buildnumber] return Build(url, buildnumber, job=self)
class test_build(unittest.TestCase): DATA = { "actions": [ {"causes": [{"shortDescription": "Started by user anonymous", "userId": None, "userName": "******"}]}, None, {"causes": []}, ], "artifacts": [], "building": False, "builtOn": "", "changeSet": {"items": [], "kind": None}, "culprits": [], "description": None, "duration": 5782, "estimatedDuration": 106, "executor": None, "fingerprint": [ { "fileName": "BuildId.json", "hash": "e3850a45ab64aa34c1aa66e30c1a8977", "original": {"name": "ArtifactGenerateJob", "number": 469}, "timestamp": 1380270162488, "usage": [ {"name": "SingleJob", "ranges": {"ranges": [{"end": 567, "start": 566}]}}, {"name": "MultipleJobs", "ranges": {"ranges": [{"end": 150, "start": 139}]}}, ], } ], "fullDisplayName": "foo #1", "id": "2013-05-31_23-15-40", "keepLog": False, "number": 1, "result": "SUCCESS", "timestamp": 1370042140000, "url": "http://*****:*****@mock.patch.object(Build, "_poll") def setUp(self, _poll): _poll.return_value = self.DATA self.j = mock.MagicMock() # Job self.j.name = "FooJob" self.b = Build("http://", 97, self.j) def test_timestamp(self): self.assertIsInstance(self.b.get_timestamp(), datetime.datetime) expected = pytz.utc.localize(datetime.datetime(2013, 5, 31, 23, 15, 40)) self.assertEqual(self.b.get_timestamp(), expected) def testName(self): with self.assertRaises(AttributeError): self.b.id() self.assertEquals(self.b.name, "foo #1") def test_duration(self): expected = datetime.timedelta(milliseconds=5782) self.assertEquals(self.b.get_duration(), expected) self.assertEquals(self.b.get_duration().seconds, 5) self.assertEquals(self.b.get_duration().microseconds, 782000) self.assertEquals(str(self.b.get_duration()), "0:00:05.782000") def test_get_causes(self): self.assertEquals( self.b.get_causes(), [{"shortDescription": "Started by user anonymous", "userId": None, "userName": "******"}], ) @mock.patch.object(Build, "get_data") def test_build_depth(self, get_data_mock): Build("http://*****:*****@mock.patch.object(Build, "__init__") def test_get_matrix_runs(self, build_init_mock): build_init_mock.return_value = None for build in self.b.get_matrix_runs(): continue build_init_mock.assert_called_once_with("http//localhost:8080/job/foo/SHARD_NUM=1/1/", 1, self.j)