diff --git a/playbooks/roles/flag_build_commits/files/flag_commit_build.py b/playbooks/roles/flag_build_commits/files/flag_commit_build.py new file mode 100644 index 0000000..c855815 --- /dev/null +++ b/playbooks/roles/flag_build_commits/files/flag_commit_build.py @@ -0,0 +1,184 @@ +# -*- coding: utf-8 -*- + +""" +This script takes as input the fedmsg messages published under the topic +``buildsys.build.state.change`` and flag the corresponding commit in pagure +if the build was successful. + +Authors: Pierre-Yves Chibon + +""" +from __future__ import unicode_literals + +import json +import logging +import sys + +import koji +import requests +from requests.packages.urllib3.util import retry + + +_log = logging.getLogger(__name__) + + +def _koji_hub_link(msg): + instance = msg['msg'].get('instance', 'primary') + if instance == 'primary': + base = "https://koji.fedoraproject.org/kojihub" + else: + raise NotImplementedError("Unhandled instance") + + # One last little switch-a-roo for stg + if '.stg.' in msg['topic']: + base = "https://koji.stg.fedoraproject.org/kojihub" + + return base + + +def _koji_link(msg): + instance = msg['msg'].get('instance', 'primary') + if instance == 'primary': + base = "https://koji.fedoraproject.org/koji" + else: + raise NotImplementedError("Unhandled instance") + + # One last little switch-a-roo for stg + if '.stg.' in msg['topic']: + base = "https://koji.stg.fedoraproject.org/koji" + + return base + "/taskinfo?taskID=%i" \ + % (msg['msg']['task_id']) + + +def main(msg): + """ Check if the build was successful and if so, flag the commit in + pagure. + """ + + timeout = (30, 30) + retries = 3 + requests_session = requests.Session() + retry_conf = retry.Retry( + total=retries, connect=retries, read=retries, backoff_factor=1) + retry_conf.BACKOFF_MAX = 5 + requests_session.mount( + 'http://', requests.adapters.HTTPAdapter(max_retries=retry_conf)) + requests_session.mount( + 'https://', requests.adapters.HTTPAdapter(max_retries=retry_conf)) + + topic, msg = msg['topic'], msg['body'] + _log.debug("Received %r" % msg.get('msg_id', None)) + + instance = msg['msg']['instance'] + if instance != 'primary': + _log.info("Ignoring secondary arch task...") + return + + _log.info("Handling koji msg %r" % msg.get('msg_id')) + + # see koji.TASK_STATES for all values + done_states = { + 1: 'completed', + 3: 'failed', + 4: 'canceled', + } + state = msg['msg']['new'] + if state not in done_states: + _log.info('Build is still in progress, let\'s come back later') + return + + koji_url = _koji_hub_link(msg) + _log.info('Talking to koji at: %s' % koji_url) + koji_client = koji.ClientSession(koji_url) + + build_id = msg['msg']['build_id'] + build = koji_client.getBuild(build_id) + git_url = ( + build.get('extra') or {}).get('source', {}).get('original_url') + + if not git_url: + _log.info( + 'No git url found in the extra information: %s', + build.get('extra')) + return 1 + + if '#' not in git_url: + _log.info('No # in the git_url: %s', git_url) + return 1 + + commit = git_url.rsplit('#', 1)[1] + + if state == 1: + status = 'success' + elif state == 3: + status = 'failure' + else: + status = 'canceled' + + version = msg['msg']['version'] + if msg['msg'].get('epoch'): + version = '%s:%s' % (msg['msg']['epoch'], version) + + nvr = '%s-%s-%s' % ( + msg['msg']['name'], + version, + msg['msg']['release'] + ) + data = { + 'username': 'Build %s' % (done_states[state]), + 'status': status, + 'comment': 'Built as %s' % (nvr), + 'url': _koji_link(msg), + } + + pagure_url = 'https://src.fedoraproject.org' + env_var = 'API_TOKEN' + if '.stg.' in msg['topic']: + pagure_url = 'https://src.stg.fedoraproject.org' + env_var = 'API_TOKEN_STG' + + target_url = '/'.join([ + 'api', + '0', + 'rpms', + msg['msg']['name'], + 'c', + commit, + 'flag' + ]) + flag_url = pagure_url + '/' + target_url + _log.info('Flagging commit at: %s' % flag_url) + + headers = { + "Authorization": "token " + os.environ.get(env_var), + 'User-Agent': 'loopabull@fedora-infr', + } + + _log.info('payload: %s' % data) + + req = self.requests_session.request( + method='POST', + url=flag_url, + headers=headers, + data=data, + ) + _log.info('Request to %s returned: %s' % (pagure_url, req.status_code)) + _log.debug(req.text) + if not req.ok: + _log.info(req.text) + return 1 + else: + _log.info('All clear') + _log.info('User-URL: %s' % pagure_url + '/' + '/'.join([ + 'rpms', + msg['msg']['name'], + 'c', + commit + ])) + + +if __name__ == '__main__': + msg = sys.argv[1] + msg = json.loads(msg) + sys.exit(main(msg)) diff --git a/playbooks/roles/flag_build_commits/tasks/main.yml b/playbooks/roles/flag_build_commits/tasks/main.yml new file mode 100644 index 0000000..c84df5a --- /dev/null +++ b/playbooks/roles/flag_build_commits/tasks/main.yml @@ -0,0 +1,16 @@ +- name: Install script flagging commits on dist-git upon successful build + copy: + src: files/flag_commit_build.py + dest: /usr/local/bin/flag_commit_build.py + mode: 0755 + +- name: Run the script + command: /usr/local/bin/flag_commit_build.py '{{ msg | to_json }}' + register: output + environment: + API_TOKEN: "{{ api_token_flag_commit_build }}" + API_TOKEN_STG: "{{ api_token_flag_commit_build_stg }}" + +- name: Show the output of the script + debug: + msg: "Output of the script: {{ output }}"