├── fedmsg_meta_fedora_infrastructure ├── conglomerators │ ├── __init__.py │ ├── ansible │ │ ├── __init__.py │ │ └── playbooks.py │ ├── bodhi │ │ ├── __init__.py │ │ ├── comments.py │ │ └── overrides.py │ ├── copr │ │ ├── __init__.py │ │ └── copr.py │ ├── mailman │ │ ├── __init__.py │ │ └── mailman.py │ ├── meetbot │ │ ├── __init__.py │ │ └── meetbot.py │ ├── pagure │ │ ├── __init__.py │ │ └── pagure.py │ ├── pkgdb │ │ ├── __init__.py │ │ └── acls.py │ └── tagger │ │ ├── __init__.py │ │ └── tags.py ├── tests │ ├── conglomerate │ │ ├── __init__.py │ │ ├── ansible │ │ │ └── __init__.py │ │ ├── bodhi │ │ │ └── __init__.py │ │ ├── copr │ │ │ └── __init__.py │ │ ├── mailman │ │ │ └── __init__.py │ │ ├── meetbot │ │ │ └── __init__.py │ │ ├── pagure │ │ │ └── __init__.py │ │ ├── pkgdb │ │ │ ├── __init__.py │ │ │ └── test_acls.py │ │ └── tagger │ │ │ └── __init__.py │ ├── common.py │ ├── base.py │ ├── example.patch │ ├── zanata.py │ ├── waiverdb.py │ ├── datanommer.py │ ├── mbs.py │ ├── koschei.py │ ├── ftpsync.py │ ├── odcs.py │ ├── faf.py │ ├── planet.py │ ├── taskotron.py │ └── pdc.py ├── __init__.py ├── datanommer.py ├── zanata.py ├── waiverdb.py ├── mbs.py ├── odcs.py ├── pdc.py ├── karma.py ├── releng.py ├── planet.py ├── fedoracollege.py ├── faf.py ├── mediawiki.py ├── infragit.py ├── greenwave.py ├── summershum.py ├── jenkins.py ├── fmn.py ├── badges.py ├── kerneltest.py ├── mm2.py ├── taskotron.py ├── ansible.py ├── nagios.py ├── nuancier.py ├── elections.py ├── fedimg.py ├── compose2.py ├── mdapi.py ├── mailman3.py ├── koschei.py ├── rats.py ├── askbot.py └── fas.py ├── doc ├── requirements.txt ├── _static │ ├── fedmsg.png │ ├── fedmsg.xcf │ └── site.css ├── index.rst ├── _templates │ ├── fedmsg-logo.html │ ├── page.html │ └── githubedit.html └── start.rst ├── MANIFEST.in ├── .gitignore ├── tox.ini ├── .travis.yml ├── CONTRIBUTING.rst ├── fedmsg.d ├── relay.py ├── base.py ├── endpoints.py └── ssl.py ├── RELEASE.rst └── README.rst /fedmsg_meta_fedora_infrastructure/conglomerators/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/conglomerators/ansible/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/conglomerators/bodhi/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/conglomerators/copr/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/conglomerators/mailman/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/conglomerators/meetbot/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/conglomerators/pagure/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/conglomerators/pkgdb/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/conglomerators/tagger/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/tests/conglomerate/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/tests/conglomerate/ansible/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/tests/conglomerate/bodhi/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/tests/conglomerate/copr/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/tests/conglomerate/mailman/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/tests/conglomerate/meetbot/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/tests/conglomerate/pagure/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/tests/conglomerate/pkgdb/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/tests/conglomerate/tagger/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /doc/requirements.txt: -------------------------------------------------------------------------------- 1 | cloud_sptheme 2 | pyzmq-static 3 | nose 4 | requests 5 | fedmsg>=0.10.0 6 | mako 7 | -------------------------------------------------------------------------------- /doc/_static/fedmsg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/fedmsg_meta_fedora_infrastructure/develop/doc/_static/fedmsg.png -------------------------------------------------------------------------------- /doc/_static/fedmsg.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/fedmsg_meta_fedora_infrastructure/develop/doc/_static/fedmsg.xcf -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include LICENSE 2 | include README.rst 3 | recursive-include fedmsg.d *.py 4 | include fedmsg_meta_fedora_infrastructure/tests/example.patch 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | dist 3 | *.egg* 4 | *.pyc 5 | *.pyo 6 | *.swp 7 | *.pdf 8 | _build 9 | html-output 10 | htmldoc 11 | _tweet-real.py 12 | html-docs 13 | doc/topics.rst 14 | .tox 15 | -------------------------------------------------------------------------------- /doc/index.rst: -------------------------------------------------------------------------------- 1 | Fedora Project fedmsg details 2 | ============================= 3 | 4 | Information specific to the Fedora Project deployment of `fedmsg 5 | `_. 6 | 7 | .. toctree:: 8 | :maxdepth: 0 9 | 10 | start 11 | topics 12 | -------------------------------------------------------------------------------- /doc/_templates/fedmsg-logo.html: -------------------------------------------------------------------------------- 1 |

fedmsg

2 | 4 | -------------------------------------------------------------------------------- /doc/_templates/page.html: -------------------------------------------------------------------------------- 1 | {% extends "!page.html" %} 2 | {% block footer -%} 3 | {{ super() }} 4 | 5 | Fork me on GitHub 8 | 9 | {%- endblock %} 10 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | envlist = py{27,36}-six{17,19} 3 | downloadcache = {toxworkdir}/_download/ 4 | 5 | [testenv] 6 | basepython = 7 | py27: python2.7 8 | py36: python3.6 9 | deps = 10 | six17: python-dateutil 11 | six17: six==1.7.3 12 | six19: python-dateutil 13 | six19: six>=1.9.0 14 | arrow 15 | fedmsg>=0.13.3 16 | python-fedora 17 | nose 18 | sitepackages = False 19 | commands = 20 | nosetests {posargs} 21 | -------------------------------------------------------------------------------- /doc/_templates/githubedit.html: -------------------------------------------------------------------------------- 1 |

Edit this document

2 | 3 |

Go to {{ title }} 4 | on GitHub. 5 |

6 |

Use the web interface to fork the repo, edit the file, and 7 | send a pull request.

8 |

Your changes will be queued for review under project's 9 | Pull requests tab on 10 | Github.

11 | -------------------------------------------------------------------------------- /doc/_static/site.css: -------------------------------------------------------------------------------- 1 | @import url("cloud.css"); 2 | @import url("http://fonts.googleapis.com/css?family=Comfortaa"); 3 | 4 | .fedmsg-logo span { 5 | background: url("fedmsg.png") no-repeat scroll 0 0 transparent; 6 | background-size: 100% 100%; 7 | display: block; 8 | width: 134px; 9 | height: 44px; 10 | margin-bottom:1px; 11 | } 12 | 13 | h1.fedmsg-logo { 14 | font-family: 'Comfortaa', sans-serif; 15 | margin-top: -10px; 16 | margin-bottom: 12px; 17 | } 18 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/tests/common.py: -------------------------------------------------------------------------------- 1 | from fedmsg.tests.test_meta import Base 2 | 3 | 4 | def add_doc(objects): 5 | """ Given a dict of names and classes, reattach the docstring as 'doc'. 6 | 7 | The core fedmsg lib uses that 'doc' attribute to build its own docs for 8 | http://fedmsg.com/ 9 | 10 | This is needed as a workaround for this code: 11 | https://github.com/fedora-infra/fedmsg/blob/develop/fedmsg/doc_utilities.py 12 | """ 13 | 14 | for k, v in objects.items(): 15 | if 'Test' in k and issubclass(v, Base): 16 | v.doc = v.__doc__ 17 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | 3 | install: 4 | - pip install --upgrade setuptools pip 5 | - python setup.py install 6 | - pip install arrow 7 | 8 | script: python setup.py test -q 9 | 10 | env: 11 | global: 12 | - PYTHONWARNINGS=always::DeprecationWarning 13 | - TRAVIS_CI=True 14 | jobs: 15 | - TOXENV=lint 16 | 17 | notifications: 18 | email: false 19 | irc: 20 | - "irc.freenode.net#fedora-apps" 21 | on_success: change 22 | on_failure: change 23 | 24 | matrix: 25 | include: 26 | - python: "3.6" 27 | env: TOXENV=py36 28 | - python: "3.7" 29 | env: TOXENV=py37 30 | - python: "3.8" 31 | env: TOXENV=py38 32 | - python: "3.9" 33 | env: TOXENV=py39 34 | allow_failures: 35 | - python: 2.7 36 | 37 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/__init__.py: -------------------------------------------------------------------------------- 1 | #-*- coding: utf-8 -*- 2 | 3 | import fedora.client 4 | import fedmsg.meta.base 5 | 6 | 7 | class BaseProcessor(fedmsg.meta.base.BaseProcessor): 8 | topic_prefix_re = 'org\\.fedoraproject\\.(dev|stg|prod)' 9 | FAS = fedora.client.AccountSystem() 10 | 11 | def emails(self, msg, **config): 12 | usernames = self.usernames(msg, **config) 13 | emails = [name + "@fedoraproject.org" for name in usernames] 14 | return dict(zip(emails, usernames)) 15 | 16 | def avatars(self, msg, **config): 17 | usernames = self.usernames(msg, **config) 18 | kwargs = dict(lookup_email=False) 19 | lookup = lambda x: self.FAS.avatar_url(x, **kwargs) 20 | urls = map(lookup, usernames) 21 | return dict(zip(usernames, urls)) 22 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/tests/base.py: -------------------------------------------------------------------------------- 1 | from fedmsg.tests.test_meta import Base as _Base 2 | 3 | import fedmsg_meta_fedora_infrastructure.fasshim 4 | 5 | 6 | class Base(_Base): 7 | def setUp(self): 8 | # We don't want to actually query FAS during our test runs, 9 | # so mock out _fas_cache to contain a dummy cache. 10 | fedmsg_meta_fedora_infrastructure.fasshim._fas_cache = { 11 | 'threebean': 'ralph', 12 | 'rbean@redhat.com': 'ralph', 13 | 'puiterwijk@gmail.com': 'puiterwijk', 14 | 'nicolas.mailhot@laposte.net': 'nim', 15 | } 16 | super(Base, self).setUp() 17 | 18 | def tearDown(self): 19 | # At the end of each test, set things back to the way they were. 20 | fedmsg_meta_fedora_infrastructure.fasshim._fas_cache = {} 21 | super(Base, self).tearDown() 22 | -------------------------------------------------------------------------------- /CONTRIBUTING.rst: -------------------------------------------------------------------------------- 1 | Contributing 2 | ============ 3 | 4 | If you're submitting patches to fedmsg, please observe the following: 5 | 6 | - Check that your python code is `PEP8-compliant 7 | `_. There is a `pep8 tool 8 | `_ that can automatically check 9 | your source. Bind it to a key in vim? 10 | - Check that your code doesn't break the test suite. Instructions for running 11 | the test suite can be found in :doc:`development`. 12 | - If you are adding new code, please write tests for them in ``fedmsg/tests``. 13 | - If your change warrants a modification to the docs in ``doc/`` or any 14 | docstrings in ``fedmsg/`` please make that modification. 15 | 16 | I didn't sign up for this! 17 | -------------------------- 18 | 19 | :: 20 | 21 | ...all I wanted to do was submit a patch! 22 | 23 | 24 | Don't worry. If you have a contribution but the above guidelines are too 25 | much to handle, just stop by ``#fedora-apps`` on freenode and let us know. 26 | -------------------------------------------------------------------------------- /doc/start.rst: -------------------------------------------------------------------------------- 1 | Getting started with fedmsg_meta_fedora_infrastructure 2 | ====================================================== 3 | 4 | This project provides a mapping allowing to convert a specific `fedmsg 5 | `_ message into a single string of information describing the 6 | action of that lead to this message. 7 | 8 | 9 | Quick introduction to fedmsg_meta 10 | --------------------------------- 11 | 12 | Sometime an example is worth more than just words: 13 | 14 | :: 15 | 16 | import requests 17 | 18 | import fedmsg 19 | import fedmsg.meta 20 | config = fedmsg.config.load_config() 21 | fedmsg.meta.make_processors(**config) 22 | 23 | req = requests.get('https://apps.fedoraproject.org/datagrepper/raw/') 24 | data = req.json() 25 | 26 | for message in data['raw_messages']: 27 | print fedmsg.meta.msg2subtitle(message) 28 | print fedmsg.meta.msg2usernames(message) 29 | print fedmsg.meta.msg2packages(message) 30 | 31 | 32 | This simple script will retrieve recent messages from datagrepper and for 33 | each message returned will print a one-line description of the action as 34 | well as the persons and packages involved. 35 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/tests/example.patch: -------------------------------------------------------------------------------- 1 | From 66abdea4014eb2f0745fc38f86e20c7d7009237e Mon Sep 17 00:00:00 2001 2 | From: Ralph Bean 3 | Date: Oct 08 2012 17:25:49 +0000 4 | Subject: Try removing requirement on python-bunch. 5 | 6 | 7 | --- 8 | 9 | diff --git a/datanommer.spec b/datanommer.spec 10 | index c34b795..1db1d0a 100644 11 | --- a/datanommer.spec 12 | +++ b/datanommer.spec 13 | @@ -1,6 +1,6 @@ 14 | Name: datanommer 15 | Version: 0.1.8 16 | -Release: 1%{?dist} 17 | +Release: 2%{?dist} 18 | Summary: A storage consumer for the Fedora Message Bus (fedmsg) 19 | 20 | Group: Development/Libraries 21 | @@ -28,11 +28,6 @@ BuildRequires: python-sqlalchemy >= 0.7 22 | Requires: python-sqlalchemy >= 0.7 23 | %endif 24 | 25 | -# This is required due to a bug in moksha's packaging 26 | -# That is fixed in moksha-0.8.8-4 27 | -BuildRequires: python-bunch 28 | -Requires: python-bunch 29 | - 30 | 31 | %description 32 | This is datanommer. It is comprised of only a `fedmsg 33 | @@ -73,6 +68,9 @@ database. 34 | %{_bindir}/datanommer-dump 35 | 36 | %changelog 37 | +* Mon Oct 08 2012 Ralph Bean - 0.1.8-2 38 | +- Remove requirement on python-bunch. 39 | + 40 | * Thu Oct 04 2012 Ralph Bean - 0.1.8-1 41 | - More flexible database field types. 42 | * Fri Sep 28 2012 Ralph Bean - 0.1.7-1 43 | 44 | -------------------------------------------------------------------------------- /fedmsg.d/relay.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2012 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: Ralph Bean 19 | # 20 | 21 | config = dict( 22 | endpoints={ 23 | # This is the output side of the relay to which all other 24 | # services can listen. 25 | "relay_outbound": [ 26 | "tcp://127.0.0.1:4001", 27 | ], 28 | }, 29 | 30 | # This is the address of an active->passive relay. It is used for the 31 | # fedmsg-logger command which requires another service with a stable 32 | # listening address for it to send messages to. 33 | # It is also used by the git-hook, for the same reason. 34 | # It is also used by the mediawiki php plugin which, due to the oddities of 35 | # php, can't maintain a single passive-bind endpoint of it's own. 36 | relay_inbound=[ 37 | "tcp://127.0.0.1:2003", 38 | ], 39 | ) 40 | -------------------------------------------------------------------------------- /fedmsg.d/base.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2012 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: Ralph Bean 19 | # 20 | config = dict( 21 | # Set this to dev if you're hacking on fedmsg or an app. 22 | # Set to stg or prod if running in the Fedora Infrastructure 23 | environment="dev", 24 | 25 | # Default is 0 26 | high_water_mark=0, 27 | io_threads=1, 28 | 29 | ## For the fedmsg-hub and fedmsg-relay. ## 30 | 31 | # We almost always want the fedmsg-hub to be sending messages with zmq as 32 | # opposed to amqp or stomp. 33 | zmq_enabled=True, 34 | 35 | # When subscribing to messages, we want to allow splats ('*') so we tell 36 | # the hub to not be strict when comparing messages topics to subscription 37 | # topics. 38 | zmq_strict=False, 39 | 40 | # Number of seconds to sleep after initializing waiting for sockets to 41 | # sync. 42 | post_init_sleep=0.2, 43 | ) 44 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/datanommer.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2012 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: Ralph Bean 19 | # 20 | from fedmsg_meta_fedora_infrastructure import BaseProcessor 21 | 22 | 23 | class DatanommerProcessor(BaseProcessor): 24 | __name__ = "datanommer" 25 | __description__ = "Exceptional Datanommer Events" 26 | __link__ = "https://github.com/fedora-infra/datanommer" 27 | __docs__ = "https://github.com/fedora-infra/datanommer" 28 | __obj__ = "Datanommer Events" 29 | 30 | def subtitle(self, msg, **config): 31 | return "datanommer encountered a duplicate uuid" 32 | 33 | def icon(self, msg, **config): 34 | return "https://i.imgur.com/4g9NZu1.png" 35 | 36 | def secondary_icon(self, msg, **config): 37 | return "https://i.imgur.com/58oJkOr.gif" 38 | 39 | def link(self, msg, **config): 40 | return "https://www.destroyallsoftware.com/talks/wat" 41 | 42 | def usernames(self, msg, **config): 43 | return set() 44 | 45 | def packages(self, msg, **config): 46 | return set() 47 | 48 | def objects(self, msg, **config): 49 | return set(['wat']) 50 | -------------------------------------------------------------------------------- /RELEASE.rst: -------------------------------------------------------------------------------- 1 | Releasing fedmsg-met-fedora-infrastructure 2 | ========================================== 3 | 4 | This document describes the process to follow when making a new release of 5 | fedmsg-meta-fedora-infrastructure. 6 | 7 | This projects uses the git-flow development model and tooling. You can find some 8 | documentation about the model at the following URLs: 9 | 10 | * https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow 11 | * https://danielkummer.github.io/git-flow-cheatsheet/ 12 | 13 | Concretly: 14 | 15 | * Install gitflow 16 | :: 17 | sudo dnf install gitflow 18 | 19 | * Configure the git repo to follow the gitflow model (needed only once) 20 | :: 21 | git flow init 22 | 23 | Here are the information you want for it: 24 | - production release branch: `master` 25 | - development branch: `develop` 26 | - feature branch prefix: `feature/` 27 | - release branch prefix: `release/` 28 | - hotfix branch prefix: `hotfix/` 29 | - support branch prefix: `support/` 30 | - tag prefix: 31 | 32 | * Start the release process: 33 | :: 34 | git flow release start 35 | git flow release start 0.28.0 36 | 37 | * Update the `CHANGELOG.rst` file 38 | 39 | * Adjust the version in `setup.py` 40 | 41 | * Commit the resulting changes: 42 | :: 43 | git commit -asm "Release 44 | git commit -asm "Release 0.28.0" 45 | 46 | * Finish the release: 47 | :: 48 | git flow release finish 49 | git flow release finish 0.28.0 50 | 51 | * Write a message for the tag: 52 | :: 53 | Release 54 | Release 0.28.0 55 | 56 | * Build the tarball 57 | :: 58 | python setup.py sdist 59 | 60 | * Publish the tarball 61 | :: 62 | twine upload dist/ 63 | twine upload dist/fedmsg_meta_fedora_infrastructure-0.28.0.tar.gz 64 | 65 | * Push the changes in git 66 | :: 67 | git push && git push --tags 68 | 69 | * Push the changes in the master branch 70 | :: 71 | git checkout master 72 | git push 73 | 74 | * Update the RPM in Fedora 75 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/conglomerators/tagger/tags.py: -------------------------------------------------------------------------------- 1 | import fedmsg.meta.base 2 | from fedmsg_meta_fedora_infrastructure.fasshim import avatar_url 3 | 4 | class AbstractTaggerConglomerator(fedmsg.meta.base.BaseConglomerator): 5 | 6 | def merge(self, constituents, subject, **config): 7 | ms = constituents # shorthand 8 | 9 | user = ms[0]['msg']['user']['username'] 10 | tags = set([m['msg']['vote']['tag']['tag'] for m in ms]) 11 | pkgs = set([m['msg']['vote']['tag']['package'] for m in ms]) 12 | 13 | tags = self.list_to_series(tags) 14 | pkgs = self.list_to_series(pkgs) 15 | 16 | 17 | tmpl = self.produce_template(constituents, subject, **config) 18 | tmpl['subtitle'] = self.subtitle.format(user=user, tags=tags, pkgs=pkgs) 19 | tmpl['subjective'] = tmpl['subtitle'] 20 | 21 | default = tmpl['icon'] 22 | 23 | tmpl['secondary_icon'] = self.get_secondary_icon(constituents, default) 24 | tmpl['link'] = 'http://infrastructure.fedoraproject.org' + \ 25 | '/infra/ansible.git/' 26 | 27 | return tmpl 28 | 29 | def matches(self, a, b, **config): 30 | """ The changes must all be **to** the same pkgdb user """ 31 | a, b = a['msg'], b['msg'] 32 | if a['user']['username'] != b['user']['username']: 33 | return False 34 | return True 35 | 36 | def get_secondary_icon(self, constituents, default): 37 | userid = constituents[0]['msg']['user']['username'] 38 | return avatar_url(userid) 39 | 40 | def get_link(self, constituents): 41 | return '' 42 | 43 | 44 | class UpdateByUser(AbstractTaggerConglomerator): 45 | subtitle = '{user} voted on the tags: {tags} to the packages: {pkgs}' 46 | 47 | def can_handle(self, msg, **config): 48 | return 'fedoratagger.tag.update' in msg['topic'] 49 | 50 | 51 | class CreateByUser(AbstractTaggerConglomerator): 52 | subtitle = '{user} created new tags: {tags} on the packages: {pkgs}' 53 | 54 | def can_handle(self, msg, **config): 55 | return 'fedoratagger.tag.create' in msg['topic'] 56 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/conglomerators/meetbot/meetbot.py: -------------------------------------------------------------------------------- 1 | import fedmsg.meta.base 2 | from fedmsg_meta_fedora_infrastructure.fasshim import avatar_url 3 | 4 | 5 | class ByURL(fedmsg.meta.base.BaseConglomerator): 6 | def can_handle(self, msg, **config): 7 | return '.meetbot.' in msg['topic'] 8 | 9 | def get_title(self, ms): 10 | for msg in ms: 11 | title = msg['msg'].get('meeting_topic') 12 | if title: 13 | return title 14 | return None 15 | 16 | def merge(self, constituents, subject, **config): 17 | ms = constituents # shorthand 18 | usernames = self.list_to_series( 19 | sum([list(m['msg']['attendees'].keys()) for m in ms], []) 20 | ) 21 | channel = ms[0]['msg']['channel'] 22 | title = self.get_title(ms) 23 | 24 | if title: 25 | subtitle = self._('{usernames} participated in {title} in {channel}') 26 | else: 27 | subtitle = self._('{usernames} participated in a meeting in {channel}') 28 | 29 | tmpl = self.produce_template(constituents, subject, **config) 30 | tmpl['subtitle'] = subtitle.format( 31 | usernames=usernames, 32 | title=title, 33 | channel=channel, 34 | ) 35 | tmpl['subjective'] = tmpl['subtitle'] 36 | 37 | default = tmpl['icon'] 38 | 39 | # These are the only two keys that vary amongst our concrete children. 40 | tmpl['secondary_icon'] = self.get_secondary_icon(constituents, default) 41 | tmpl['link'] = self.get_link(constituents) 42 | 43 | return tmpl 44 | 45 | def matches(self, a, b, **config): 46 | """ The events must be all about the same meetbot """ 47 | a, b = a['msg'], b['msg'] 48 | if a['url'] != b['url']: 49 | return False 50 | return True 51 | 52 | def get_secondary_icon(self, constituents, default): 53 | username = constituents[0]['msg']['owner'] 54 | return avatar_url(username) 55 | 56 | def get_link(self, constituents): 57 | return constituents[0]['msg']['url'] 58 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | fedmsg_meta_fedora_infrastructure 2 | ================================= 3 | 4 | .. split here 5 | 6 | fedmsg metadata providers for Fedora Infrastructure's deployment 7 | ---------------------------------------------------------------- 8 | 9 | `fedmsg `_ is a set of tools for knitting together services 10 | and webapps into a realtime messaging net. This package contains metadata 11 | provider plugins for the primary deployment of that system: `Fedora 12 | Infrastructure `_. 13 | 14 | If you were to deploy fedmsg at another site, you would like want to write your 15 | own module like this one that could provide textual representations of *your* 16 | messages. 17 | 18 | Pop into ``#fedora-apps`` on freenode if you have questions or comments. 19 | 20 | Build Status 21 | ------------ 22 | 23 | .. |master| image:: https://secure.travis-ci.org/ralphbean/fedmsg_meta_fedora_infrastructure.png?branch=master 24 | :alt: Build Status - master branch 25 | :target: http://travis-ci.org/#!/ralphbean/fedmsg_meta_fedora_infrastructure 26 | 27 | .. |develop| image:: https://secure.travis-ci.org/ralphbean/fedmsg_meta_fedora_infrastructure.png?branch=develop 28 | :alt: Build Status - develop branch 29 | :target: http://travis-ci.org/#!/ralphbean/fedmsg_meta_fedora_infrastructure 30 | 31 | +----------+-----------+ 32 | | Branch | Status | 33 | +==========+===========+ 34 | | master | |master| | 35 | +----------+-----------+ 36 | | develop | |develop| | 37 | +----------+-----------+ 38 | 39 | Running the Tests 40 | ----------------- 41 | 42 | :: 43 | 44 | # Create a virtualenv and install deps 45 | $ sudo dnf install python-virtualenv libffi-devel 46 | $ virtualenv my-env 47 | $ source my-env/bin/activate 48 | 49 | # Install the dependencies 50 | $ python setup.py develop 51 | 52 | # Run the tests 53 | $ pip install nose 54 | $ $(which nosetests) 55 | 56 | Building the Docs 57 | ----------------- 58 | 59 | :: 60 | 61 | # Install additional dependencies 62 | $ pip install -r doc/requirements.txt 63 | $ sphinx-build doc/ htmldocs/ 64 | -------------------------------------------------------------------------------- /fedmsg.d/endpoints.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2012 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: Ralph Bean 19 | # 20 | import socket 21 | hostname = socket.gethostname() 22 | 23 | config = dict( 24 | # This is a dict of possible addresses from which fedmsg can send 25 | # messages. fedmsg.init(...) requires that a 'name' argument be passed 26 | # to it which corresponds with one of the keys in this dict. 27 | endpoints={ 28 | # These are here so your local box can listen to the upstream 29 | # infrastructure's bus. Cool, right? :) 30 | "fedora-infrastructure": [ 31 | #"tcp://hub.fedoraproject.org:9940", 32 | #"tcp://stg.fedoraproject.org:9940", 33 | ], 34 | 35 | # For other, more 'normal' services, fedmsg will try to guess the 36 | # name of it's calling module to determine which endpoint definition 37 | # to use. This can be overridden by explicitly providing the name in 38 | # the initial call to fedmsg.init(...). 39 | "bodhi.%s" % hostname: ["tcp://127.0.0.1:3001"], 40 | "fas.%s" % hostname: ["tcp://127.0.0.1:3002"], 41 | "fedoratagger.%s" % hostname: ["tcp://127.0.0.1:3003"], 42 | "mediawiki.%s" % hostname: ["tcp://127.0.0.1:3004"], 43 | "pkgdb.%s" % hostname: ["tcp://127.0.0.1:3005"], 44 | "busmon.%s" % hostname: ["tcp://127.0.0.1:3006"], 45 | }, 46 | ) 47 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/zanata.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2012-2015 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: Ralph Bean 19 | # 20 | from fedmsg_meta_fedora_infrastructure import BaseProcessor 21 | 22 | 23 | class ZanataProcessor(BaseProcessor): 24 | __name__ = "Zanata" 25 | __description__ = "translation events" 26 | __link__ = "https://fedora.zanata.org" 27 | __docs__ = "http://zanata.org/help/workflow-overview/" 28 | __obj__ = "Translation Events" 29 | __icon__ = "https://pbs.twimg.com/profile_images/" + \ 30 | "378800000417679469/47eb45c6205aa9f2cdb8705e6d46745c_normal.png" 31 | 32 | def subtitle(self, msg, **config): 33 | tmpl = self._( 34 | "{docId} from the {project} project " 35 | "is now {milestone} in the '{locale}' locale" 36 | ) 37 | return tmpl.format(**msg['msg']).lower() 38 | 39 | def secondary_icon(self, msg, **config): 40 | return self.__icon__ 41 | 42 | def _object(self, msg): 43 | return "/".join([ 44 | msg['msg']['project'], 45 | msg['msg']['version'], 46 | 'languages', 47 | msg['msg']['locale'], 48 | ]) 49 | 50 | def objects(self, msg, **config): 51 | return set([self._object(msg)]) 52 | 53 | def link(self, msg, **config): 54 | return "https://fedora.zanata.org/iteration/view/" + self._object(msg) 55 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/waiverdb.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2017 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: Ralph Bean 19 | 20 | from fedmsg_meta_fedora_infrastructure import BaseProcessor 21 | from fedmsg_meta_fedora_infrastructure.fasshim import avatar_url 22 | 23 | 24 | class WaiverDBProcessor(BaseProcessor): 25 | __name__ = "waiverdb" 26 | __description__ = "WaiverDB" 27 | __link__ = "https://pagure.io/waiverdb" 28 | __docs__ = ("https://fedoraproject.org/wiki/Infrastructure/" 29 | "Factory2/Focus/WaiverDB") 30 | __obj__ = "New result waivers" 31 | __icon__ = "https://apps.fedoraproject.org/img/icons/waiverdb.png" 32 | 33 | def subtitle(self, msg, **config): 34 | tmpl = self._('{username} waived result {result_id} ' 35 | '({product_version}): "{comment}"') 36 | return tmpl.format(**msg['msg']) 37 | 38 | def link(self, msg, **config): 39 | template = ('https://waiverdb-web-waiverdb.app.os.fedoraproject.org/' 40 | 'api/v1.0/waivers/{id}') 41 | return template.format(**msg['msg']) 42 | 43 | def agent(self, msg, **config): 44 | return msg['msg']['username'] 45 | 46 | def usernames(self, msg, **config): 47 | return set([self.agent(msg, **config)]) 48 | 49 | def secondary_icon(self, msg, **config): 50 | return avatar_url(username=self.agent(msg, **config)) 51 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/mbs.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2017 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: Ralph Bean 19 | # 20 | 21 | from fedmsg_meta_fedora_infrastructure.fasshim import avatar_url 22 | from fedmsg_meta_fedora_infrastructure import BaseProcessor 23 | 24 | class MBSProcessor(BaseProcessor): 25 | __name__ = "mbs" 26 | __description__ = "Module Build Service" 27 | __link__ = "https://mbs.fedoraproject.org" 28 | __docs__ = "https://fedoraproject.org/wiki/Changes/ModuleBuildService" 29 | __obj__ = "Module Builds" 30 | __icon__ = "https://apps.fedoraproject.org/img/icons/modularity.png" 31 | 32 | def link(self, msg, **config): 33 | tmpl = "https://mbs.fedoraproject.org/module-build-service/1/module-builds/{id}" 34 | return tmpl.format(**msg['msg']) 35 | 36 | def subtitle(self, msg, **config): 37 | tmpl = self._( 38 | "{owner}'s build of modules/{name} entered the {state_name} state." 39 | ) 40 | return tmpl.format(**msg['msg']) 41 | 42 | def secondary_icon(self, msg, **config): 43 | user = msg['msg']['owner'] 44 | return avatar_url(user) 45 | 46 | def usernames(self, msg, **config): 47 | user = msg['msg']['owner'] 48 | return set([user]) 49 | 50 | def objects(self, msg, **config): 51 | return set([msg['msg']['name']]) 52 | 53 | def packages(self, msg, **config): 54 | return set([]) # Not sure what to do with this yet... 55 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/odcs.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2020 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: Jan Kaluza 19 | # 20 | 21 | from fedmsg_meta_fedora_infrastructure.fasshim import avatar_url 22 | from fedmsg_meta_fedora_infrastructure import BaseProcessor 23 | 24 | class ODCSProcessor(BaseProcessor): 25 | __name__ = "odcs" 26 | __description__ = "On Demand Compose Service" 27 | __link__ = "https://odcs.engineering.redhat.com/api/1/composes/" 28 | __docs__ = "https://docs.pagure.org/odcs/" 29 | __obj__ = "ODCS Composes" 30 | __icon__ = "https://apps.fedoraproject.org/img/icons/odcs.png" 31 | 32 | def link(self, msg, **config): 33 | tmpl = "https://odcs.fedoraproject.org/api/1/composes/{id}" 34 | return tmpl.format(**msg['msg']['compose']) 35 | 36 | def subtitle(self, msg, **config): 37 | c = msg['msg']['compose'] 38 | tmpl = self._( 39 | "{owner}'s compose {compose_id} entered the {state_name} state." 40 | ) 41 | return tmpl.format( 42 | owner=c['owner'], 43 | compose_id=c['pungi_compose_id'] or c['id'], 44 | state_name=c['state_name'] 45 | ) 46 | 47 | def secondary_icon(self, msg, **config): 48 | user = msg['msg']['compose']['owner'] 49 | return avatar_url(user) 50 | 51 | def usernames(self, msg, **config): 52 | user = msg['msg']['compose']['owner'] 53 | return set([user]) 54 | 55 | def objects(self, msg, **config): 56 | return set([msg['msg']['compose']['id']]) 57 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/conglomerators/bodhi/comments.py: -------------------------------------------------------------------------------- 1 | import fedmsg.meta.base 2 | from fedmsg_meta_fedora_infrastructure.fasshim import avatar_url 3 | 4 | 5 | class ByUpdate(fedmsg.meta.base.BaseConglomerator): 6 | def can_handle(self, msg, **config): 7 | return 'bodhi.update.comment' in msg['topic'] 8 | 9 | def matches(self, a, b, **config): 10 | """ The comments must all be on the same bodhi update """ 11 | a, b = a['msg'], b['msg'] 12 | if a['comment']['update_title'] != b['comment']['update_title']: 13 | return False 14 | return True 15 | 16 | def merge(self, constituents, subject, **config): 17 | N = len(constituents) 18 | msg = constituents[0]['msg'] 19 | 20 | tmpl = self.produce_template(constituents, subject, **config) 21 | agents = self.list_to_series(list(tmpl['usernames'])) 22 | update = msg['comment']['update_title'] 23 | subtitle = '{agents} commented on {update}' 24 | tmpl['subtitle'] = subtitle.format(agents=agents, update=update) 25 | tmpl['subjective'] = tmpl['subtitle'] 26 | tmpl['secondary_icon'] = tmpl['icon'] 27 | base = 'https://bodhi.fedoraproject.org/updates/%s' 28 | tmpl['link'] = base % update 29 | return tmpl 30 | 31 | 32 | class ByUser(fedmsg.meta.base.BaseConglomerator): 33 | def can_handle(self, msg, **config): 34 | return 'bodhi.update.comment' in msg['topic'] 35 | 36 | def matches(self, a, b, **config): 37 | """ The comments must all be by the same user """ 38 | if a['msg']['agent'] != b['msg']['agent']: 39 | return False 40 | return True 41 | 42 | def merge(self, constituents, subject, **config): 43 | tmpl = self.produce_template(constituents, subject, **config) 44 | msg = constituents[0] 45 | agent = msg['msg']['agent'] 46 | updates = self.list_to_series([ 47 | msg['msg']['comment']['update_title'] for msg in constituents]) 48 | subtitle = '{agent} commented on {updates}' 49 | tmpl['subtitle'] = subtitle.format(agent=agent, updates=updates) 50 | tmpl['subjective'] = tmpl['subtitle'] 51 | tmpl['secondary_icon'] = avatar_url(agent) 52 | base = 'https://bodhi.fedoraproject.org/users/%s' 53 | tmpl['link'] = base % agent 54 | return tmpl 55 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/pdc.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2016 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: Ralph Bean 19 | # 20 | from fedmsg_meta_fedora_infrastructure import BaseProcessor 21 | 22 | 23 | class PDCProcessor(BaseProcessor): 24 | __name__ = "pdc" 25 | __description__ = "Product Definition Center" 26 | __link__ = "https://github.com/product-definition-center/product-definition-center" 27 | __docs__ = "https://github.com/product-definition-center/product-definition-center" 28 | __obj__ = "PDC Composes" 29 | 30 | def subtitle(self, msg, **config): 31 | tmpl = self._('Unhandled PDC message...') 32 | if msg['topic'].endswith('.pdc.rpms') or msg['topic'].endswith('.pdc.images'): 33 | tmpl = self._( 34 | 'PDC imported metadata for {count} {attribute} for ' 35 | 'the {compose_id} {compose_type} compose' 36 | ) 37 | elif msg['topic'].endswith('.pdc.compose'): 38 | tmpl = self._( 39 | 'An entry for the {compose_id} {compose_type} compose ' 40 | 'was created in the Product Definition Center' 41 | ) 42 | 43 | return tmpl.format(**msg['msg']) 44 | 45 | def link(self, msg, **config): 46 | idx = msg['msg']['compose_id'] 47 | tmpl = 'https://pdc.fedoraproject.org/rest_api/v1/composes/{idx}/' 48 | return tmpl.format(idx=idx) 49 | 50 | def objects(self, msg, **config): 51 | attr = msg['topic'].split('.')[-1] 52 | return set([ 53 | "{compose_id}/{action}/{attr}".format(attr=attr, **msg['msg']) 54 | ]) 55 | -------------------------------------------------------------------------------- /fedmsg.d/ssl.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2012 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: Ralph Bean 19 | # 20 | import os 21 | import socket 22 | 23 | SEP = os.path.sep 24 | here = os.getcwd() 25 | hostname = socket.gethostname() 26 | 27 | config = dict( 28 | sign_messages=False, 29 | validate_signatures=False, 30 | ssldir="/etc/pki/fedmsg", 31 | 32 | crl_location="https://fedoraproject.org/fedmsg/crl.pem", 33 | crl_cache="/tmp/crl.pem", 34 | crl_cache_expiry=10, 35 | 36 | certnames={ 37 | # In prod/stg, map hostname to the name of the cert in ssldir. 38 | # Unfortunately, we can't use socket.getfqdn() 39 | #"app01.stg": "app01.stg.phx2.fedoraproject.org", 40 | }, 41 | 42 | # A mapping of fully qualified topics to a list of cert names for which 43 | # a valid signature is to be considered authorized. Messages on topics not 44 | # listed here are considered automatically authorized. 45 | routing_policy={ 46 | # Only allow announcements from production if they're signed by a 47 | # certain certificate. 48 | "org.fedoraproject.prod.announce.announcement": [ 49 | "announce-lockbox.phx2.fedoraproject.org", 50 | ], 51 | }, 52 | 53 | # Set this to True if you want messages to be dropped that aren't 54 | # explicitly whitelisted in the routing_policy. 55 | # When this is False, only messages that have a topic in the routing_policy 56 | # but whose cert names aren't in the associated list are dropped; messages 57 | # whose topics do not appear in the routing_policy are not dropped. 58 | routing_nitpicky=False, 59 | ) 60 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/conglomerators/ansible/playbooks.py: -------------------------------------------------------------------------------- 1 | import fedmsg.meta.base 2 | from fedmsg_meta_fedora_infrastructure.fasshim import avatar_url 3 | 4 | 5 | class ByUser(fedmsg.meta.base.BaseConglomerator): 6 | def can_handle(self, msg, **config): 7 | return 'ansible.playbook' in msg['topic'] 8 | 9 | def possessive(self, name): 10 | """ Given a name, return the possessive form. """ 11 | return self._("{name}'s").format(name=name) 12 | 13 | def merge(self, constituents, subject, **config): 14 | ms = constituents # shorthand 15 | 16 | agent = ms[0]['msg']['userid'] 17 | playbooks = set([m['msg']['playbook'].split('/')[-1] for m in ms]) 18 | playbooks_text = self.list_to_series(playbooks) 19 | 20 | N = len([m for m in ms if m['topic'].endswith('start')]) 21 | if not N: 22 | N = len(ms) 23 | 24 | playbooks_predicate = 'playbooks' if len(playbooks) > 1 else 'playbook' 25 | times_predicate = 'times' if N > 1 else 'time' 26 | 27 | subtitle = '{agent} ran the {playbooks} ' + \ 28 | '{playbooks_predicate} {N} {times_predicate}' 29 | 30 | tmpl = self.produce_template(constituents, subject, **config) 31 | tmpl['subtitle'] = subtitle.format( 32 | agent=agent, playbooks=playbooks_text, N=N, 33 | playbooks_predicate=playbooks_predicate, 34 | times_predicate=times_predicate) 35 | 36 | subjective_agent = 'You' if agent == subject else agent 37 | tmpl['subjective'] = subtitle.format( 38 | agent=subjective_agent, playbooks=playbooks_text, N=N, 39 | playbooks_predicate=playbooks_predicate, 40 | times_predicate=times_predicate) 41 | 42 | default = tmpl['icon'] 43 | 44 | tmpl['secondary_icon'] = self.get_secondary_icon(constituents, default) 45 | tmpl['link'] = 'http://infrastructure.fedoraproject.org' + \ 46 | '/infra/ansible.git/' 47 | 48 | return tmpl 49 | 50 | def matches(self, a, b, **config): 51 | """ The changes must all be **to** the same pkgdb user """ 52 | a, b = a['msg'], b['msg'] 53 | if a['userid'] != b['userid']: 54 | return False 55 | return True 56 | 57 | def get_secondary_icon(self, constituents, default): 58 | userid = constituents[0]['msg']['userid'] 59 | return avatar_url(userid) 60 | 61 | def get_link(self, constituents): 62 | return '' 63 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/karma.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2012 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: Ralph Bean 19 | # 20 | 21 | from fedmsg_meta_fedora_infrastructure import BaseProcessor 22 | from fedmsg_meta_fedora_infrastructure.fasshim import avatar_url 23 | 24 | 25 | class KarmaProcessor(BaseProcessor): 26 | __name__ = "irc" 27 | __description__ = "IRC Karma" 28 | __link__ = "https://fedoraproject.org/wiki/Zodbot" 29 | __docs__ = "https://fedoraproject.org/wiki/Zodbot" 30 | __obj__ = "IRC Karma" 31 | __icon__ = "https://apps.fedoraproject.org/img/icons/meetbot.png" 32 | 33 | def subtitle(self, msg, **config): 34 | if msg['msg']['vote'] == 1: 35 | tmpl = self._('{agent} gave {recipient}({total}) ' 36 | 'a karma cookie in {channel}') 37 | else: 38 | tmpl = self._('{agent} gave {recipient}({total}) ' 39 | 'negative karma in {channel}') 40 | 41 | # Backwards compat 42 | if 'line' in msg['msg']: 43 | tmpl = tmpl + self._('. "{line}"') 44 | 45 | return tmpl.format(**msg['msg']) 46 | 47 | def link(self, msg, **config): 48 | user = msg['msg']['recipient'] 49 | return 'https://badges.fedoraproject.org/user/' + user 50 | 51 | def icon(self, msg, **config): 52 | return avatar_url(msg['msg']['agent']) 53 | 54 | def secondary_icon(self, msg, **config): 55 | return avatar_url(msg['msg']['recipient']) 56 | 57 | def usernames(self, msg, **config): 58 | return set([msg['msg']['agent'], msg['msg']['recipient']]) 59 | 60 | def objects(self, msg, **config): 61 | return set(['karma/' + msg['msg']['recipient']]) 62 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/tests/zanata.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2012-2015 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: Ralph Bean 19 | # 20 | """ Tests for fedmsg.meta """ 21 | 22 | import unittest 23 | 24 | from fedmsg_meta_fedora_infrastructure.tests.base import Base 25 | 26 | from fedmsg_meta_fedora_infrastructure.tests.common import add_doc 27 | 28 | 29 | class TestZanataMilestone(Base): 30 | """ Fedora uses `zanata `_ for translations and 31 | they can ping us back when documents reach various milestones. Here's 32 | an example of a document reaching 100% status: 33 | """ 34 | expected_title = "zanata.document.milestone.event" 35 | expected_subti = "foo.txt from the webhooks-dummy project is now " + \ 36 | "100% translated in the 'af' locale" 37 | expected_icon = 'https://pbs.twimg.com/profile_images/' + \ 38 | '378800000417679469/47eb45c6205aa9f2cdb8705e6d46745c_normal.png' 39 | expected_secondary_icon = expected_icon 40 | expected_link = 'https://fedora.zanata.org/' + \ 41 | 'iteration/view/webhooks-dummy/0.1/languages/af' 42 | expected_usernames = set([]) 43 | expected_packages = set([]) 44 | expected_objects = set([ 45 | 'webhooks-dummy/0.1/languages/af', 46 | ]) 47 | 48 | msg = { 49 | "i": 16, 50 | "msg": { 51 | "project": "webhooks-dummy", 52 | "version": "0.1", 53 | "docId": "foo.txt", 54 | "locale": "af", 55 | "milestone": "100% Translated", 56 | "eventType": "org.zanata.event.DocumentMilestoneEvent", 57 | }, 58 | "topic": "org.fedoraproject.dev.zanata.document.milestone.event", 59 | "timestamp": 1345572862.556145 60 | } 61 | 62 | 63 | add_doc(locals()) 64 | 65 | if __name__ == '__main__': 66 | unittest.main() 67 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/releng.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2015 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: Ralph Bean 19 | # 20 | from fedmsg_meta_fedora_infrastructure import BaseProcessor 21 | 22 | 23 | class RelengProcessor(BaseProcessor): 24 | __name__ = "releng" 25 | __description__ = "Fedora Release Engineering" 26 | __link__ = "https://git.fedorahosted.org/cgit/releng" 27 | __docs__ = "https://fedoraproject.org/wiki/ReleaseEngineering" 28 | __obj__ = "Releng Events" 29 | __icon__ = "https://apps.fedoraproject.org/img/icons/atomic.png" 30 | 31 | def subtitle(self, msg, **config): 32 | if 'x86_64' in msg['msg'].keys(): 33 | release = msg['msg']['x86_64']['atomic_raw'].get('release', '') 34 | else: 35 | release = msg['msg']['atomic_raw'].get('release', '') 36 | if msg['topic'].endswith('.releng.atomic.twoweek.begin'): 37 | tmpl = self._("Release engineering scripts started evaluating a " 38 | "new set of builds for a Fedora {release} Atomic " 39 | "Host release") 40 | return tmpl.format(release=release) 41 | elif msg['topic'].endswith('.releng.atomic.twoweek.complete'): 42 | tmpl = self._("A new release of Fedora {release} Atomic " 43 | "Host is ready") 44 | return tmpl.format(release=release) 45 | else: 46 | return None 47 | 48 | def link(self, msg, **config): 49 | return "https://download.fedoraproject.org/pub/alt/atomic/stable/" 50 | 51 | def secondary_icon(self, msg, **config): 52 | return self.__icon__ 53 | 54 | def objects(self, msg, **config): 55 | if 'x86_64' in msg['msg'].keys(): 56 | return set(msg['msg'].keys()) 57 | else: 58 | return set([ 59 | "%s/%s" % (msg['msg'][key]['release'], key) 60 | for key in msg['msg'] if key.startswith('atomic_') 61 | ]) 62 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/tests/waiverdb.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2017 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: Ralph Bean 19 | # 20 | """ Tests for waiverdb messages """ 21 | 22 | import unittest 23 | 24 | from fedmsg.tests.test_meta import Base 25 | 26 | from .common import add_doc 27 | 28 | 29 | class TestNewWaiver(Base): 30 | """ `WaiverDB 31 | `_ is 32 | a service that allows humans to override test failures and influence gating 33 | decisions made by `Greenwave 34 | `_. 35 | 36 | It publishes messages like this whenever someone **records a new waiver**. 37 | """ 38 | 39 | expected_title = "waiverdb.waiver.new" 40 | expected_subti = "ralph waived result 123 (fedora-26): \"This is fine.\"" 41 | expected_link = ( 42 | 'https://waiverdb-web-waiverdb.app.os.fedoraproject.org/' 43 | 'api/v1.0/waivers/8') 44 | expected_icon = 'https://apps.fedoraproject.org/img/icons/waiverdb.png' 45 | expected_secondary_icon = ( 46 | 'https://seccdn.libravatar.org/avatar/' 47 | '9c9f7784935381befc302fe3c814f9136e7a33953d0318761669b8643f4df55c' 48 | '?s=64&d=retro') 49 | expected_packages = set([]) 50 | expected_usernames = set(['ralph']) 51 | msg = { 52 | "username": "openshift", 53 | "i": 2, 54 | "timestamp": 1510020810.0, 55 | "msg_id": "2017-b173d0d1-a119-40e6-9e85-c6178468d9ff", 56 | "topic": "org.fedoraproject.stg.waiverdb.waiver.new", 57 | "headers": {}, 58 | "msg": { 59 | "comment": "This is fine.", 60 | "username": "ralph", 61 | "waived": True, 62 | "timestamp": "2017-11-07T02:13:30.466388", 63 | "product_version": "fedora-26", 64 | "result_id": 123, 65 | "id": 8 66 | } 67 | } 68 | 69 | 70 | add_doc(locals()) 71 | 72 | if __name__ == '__main__': 73 | unittest.main() 74 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/planet.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2012 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: Ralph Bean 19 | # 20 | from fedmsg_meta_fedora_infrastructure import BaseProcessor 21 | 22 | 23 | class PlanetProcessor(BaseProcessor): 24 | __name__ = "planet" 25 | __description__ = "the Fedora blog aggregator" 26 | __link__ = "http://planet.fedoraproject.org/" 27 | __docs__ = "https://fedoraproject.org/wiki/Planet" 28 | __icon__ = "https://apps.fedoraproject.org/img/icons/planet_logo.png" 29 | __obj__ = "Blog Posts" 30 | 31 | def link(self, msg, **config): 32 | return msg['msg']['post']['link'] 33 | 34 | def subtitle(self, msg, **config): 35 | title = msg['msg']['post'].get('title', '(no title found)') 36 | if 'username' in msg['msg']: 37 | tmpl = self._('{user} posted "{title}"') 38 | return tmpl.format(title=title, user=msg['msg']['username']) 39 | 40 | tmpl = self._('New post: "{title}"') 41 | return tmpl.format(title=title) 42 | 43 | def long_form(self, msg, **config): 44 | if 'summary' in msg['msg']['post']: 45 | return msg['msg']['post']['summary'] 46 | elif 'content' in msg['msg']['post']: 47 | if msg['msg']['post']['content']: 48 | return msg['msg']['post']['content'][0]['value'] 49 | 50 | def lexer(self, msg, **config): 51 | # Be explicit about returning None here. We don't want to lex the html 52 | # from their summary.. but we want to return it literally. So, don't 53 | # implement a lexer here, please. --ralph 54 | return None 55 | 56 | def secondary_icon(self, msg, **config): 57 | return msg['msg'].get('face', None) 58 | 59 | def usernames(self, msg, **config): 60 | if 'username' in msg['msg']: 61 | return set([msg['msg']['username']]) 62 | 63 | return set() 64 | 65 | def objects(self, msg, **config): 66 | link = self.link(msg, **config) 67 | link = link.replace('https://', '').replace('http://', '') 68 | return set([link]) 69 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/fedoracollege.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2014 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # 19 | # Authors: Hammad Haleem 20 | '''Preprocessor for fedora college''' 21 | 22 | from fedmsg_meta_fedora_infrastructure import BaseProcessor 23 | from fedmsg_meta_fedora_infrastructure.fasshim import avatar_url 24 | 25 | 26 | class FedoraCollegeProcessor(BaseProcessor): 27 | __name__ = "FedoraCollege" 28 | __description__ = "The virtual Classroom for new fedora contributors" 29 | __obj__ = "Delivering video tutorials" 30 | 31 | ''' 32 | currently not in production 33 | __link__ = "https://ask.fedoraproject.org" 34 | __docs__ = "https://askbot.com" 35 | __icon__ = "https://apps.fedoraproject.org/img/icons/ask_fedora.png" 36 | ''' 37 | 38 | def subtitle(self, msg, **config): 39 | 40 | username = msg['msg']['username'] 41 | title = msg['msg']['title'] 42 | 43 | if "fedoracollege.media.upload" in msg['topic']: 44 | tmpl = self._( 45 | '{username} uploaded a new file of type "{title}"') 46 | elif "fedoracollege.content.added" in msg['topic']: 47 | tmpl = self._( 48 | '{username} Created new content titled "{title}"') 49 | elif "fedoracollege.content.edit" in msg['topic']: 50 | tmpl = self._( 51 | '{username} Edited content titled "{title}"') 52 | else: 53 | raise NotImplementedError("%r" % msg) 54 | 55 | return tmpl.format(username=username, title=title) 56 | 57 | def secondary_icon(self, msg, **config): 58 | user = None 59 | 60 | try: 61 | user = msg['msg']['username'] 62 | except KeyError: 63 | pass 64 | 65 | if not user: 66 | return "" 67 | 68 | return avatar_url(username=user) 69 | 70 | def usernames(self, msg, **config): 71 | if 'username' in msg['msg']: 72 | return set([msg['msg']['username']]) 73 | 74 | return set() 75 | 76 | def link(self, msg, **config): 77 | return msg['msg']['link'] 78 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/tests/datanommer.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2012 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: Ralph Bean 19 | # 20 | """ Tests for that one datanommer message """ 21 | 22 | import unittest 23 | 24 | from fedmsg.tests.test_meta import Base 25 | 26 | from .common import add_doc 27 | 28 | 29 | class TestDatanommerWat(Base): 30 | """ Generally speaking, the `datanommer 31 | `_ consumer does not publish 32 | its own fedmsg messages. There is one exception to this rule. 33 | 34 | As of fedmsg-0.7.0, every fedmsg carries its own uuid, prefixed with the 35 | year it was published. There is a very low risk of creating a duplicate 36 | uuid. To quote wikipedia:: 37 | 38 | "The annual risk of someone being hit by a meteorite is estimated to be 39 | one chance in 17 billion, which means the probability is about 40 | ``0.00000000006 (6 * 10**-11)``, equivalent to the odds of creating a 41 | few tens of trillions of UUIDs in a year and having one duplicate" 42 | 43 | It is highly unlikely that datanommer will ever try to store a fedmsg 44 | message that carries a uuid that already exists in its database. In the 45 | event that it does, it will publish the following message; a momentous 46 | occasion. 47 | """ 48 | 49 | expected_title = "datanommer.wat" 50 | expected_subti = 'datanommer encountered a duplicate uuid' 51 | expected_link = "https://www.destroyallsoftware.com/talks/wat" 52 | expected_icon = "https://i.imgur.com/4g9NZu1.png" 53 | expected_secondary_icon = "https://i.imgur.com/58oJkOr.gif" 54 | expected_packages = set([]) 55 | expected_usernames = set([]) 56 | expected_objects = set(['wat']) 57 | msg = { 58 | "username": "fedmsg", 59 | "i": 1, 60 | "timestamp": 1375753735.32427, 61 | "topic": "org.fedoraproject.prod.datanommer.wat", 62 | "msg": { 63 | "uuid": "2013-3bf0ec8f-03d3-40be-9ad5-5effdc6e4c06", 64 | } 65 | } 66 | 67 | 68 | add_doc(locals()) 69 | 70 | if __name__ == '__main__': 71 | unittest.main() 72 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/faf.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2015 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: Marek Brysa 19 | 20 | from fedmsg_meta_fedora_infrastructure import BaseProcessor 21 | 22 | _long_template = """Packages: {components} 23 | Function: {function} 24 | First occurrence: {first_occurrence} 25 | Type: {type} 26 | Count: {count} 27 | URL: {url} 28 | """ 29 | 30 | 31 | class FAFProcessor(BaseProcessor): 32 | __name__ = "faf" 33 | __description__ = "ABRT crash analysis server" 34 | __link__ = "https://retrace.fedoraproject.org" 35 | __obj__ = "New and significant crashes" 36 | __docs__ = "https://github.com/abrt/faf/wiki" 37 | __icon__ = "https://apps.fedoraproject.org/packages/images/icons/abrt.png" 38 | 39 | def long_form(self, msg, **config): 40 | return _long_template.format(**{ 41 | "components": ", ".join(msg["msg"].get("components", [])), 42 | "first_occurrence": msg["msg"].get("first_occurrence"), 43 | "function": msg["msg"].get("function"), 44 | "type": msg["msg"].get("type"), 45 | "count": msg["msg"].get("count"), 46 | "url": msg["msg"].get("url"), 47 | }) 48 | 49 | def subtitle(self, msg, **config): 50 | obj_name = "report" 51 | if "problem.threshold" in msg["topic"]: 52 | obj_name = "problem" 53 | return ("ABRT {0} for package {1} has reached {2} occurrences" 54 | .format(obj_name, ", ".join(msg["msg"].get("components", [])), 55 | msg["msg"].get("count"))) 56 | 57 | def link(self, msg, **config): 58 | return msg["msg"].get("url") 59 | 60 | def usernames(self, msg, **config): 61 | return set(msg["msg"].get("maintainers", [])) 62 | 63 | def packages(self, msg, **config): 64 | return set(msg["msg"].get("components", [])) 65 | 66 | def secondary_icon(self, msg, **config): 67 | pkgs = msg["msg"].get("components", []) 68 | if not pkgs: 69 | return None 70 | return ("https://apps.fedoraproject.org/packages/images/icons/{0}.png" 71 | .format(pkgs[0])) 72 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/mediawiki.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2012 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: Ralph Bean 19 | # 20 | from fedmsg_meta_fedora_infrastructure import BaseProcessor 21 | from fedmsg_meta_fedora_infrastructure.fasshim import avatar_url 22 | 23 | 24 | class WikiProcessor(BaseProcessor): 25 | __name__ = "Wiki" 26 | __description__ = "the Fedora Wiki" 27 | __link__ = "https://fedoraproject.org/wiki" 28 | __docs__ = "https://fedoraproject.org/wiki" 29 | __obj__ = "Wiki Edits" 30 | __icon__ = "https://fedoraproject.org/w/skins/common/images/mediawiki.png" 31 | 32 | def subtitle(self, msg, **config): 33 | if 'wiki.article.edit' in msg['topic']: 34 | user = msg['msg']['user'] 35 | title = msg['msg']['title'] 36 | tmpl = self._('{user} made a wiki edit to "{title}"') 37 | return tmpl.format(user=user, title=title) 38 | elif 'wiki.upload.complete' in msg['topic']: 39 | user = msg['msg']['user_text'] 40 | filename = msg['msg']['title']['mPrefixedText'] 41 | description = msg['msg']['description'][:35] 42 | tmpl = self._( 43 | '{user} uploaded {filename} to the wiki: "{description}..."' 44 | ) 45 | return tmpl.format(user=user, filename=filename, 46 | description=description) 47 | 48 | def link(self, msg, **config): 49 | if 'wiki.article.edit' in msg['topic']: 50 | return msg['msg']['url'].replace('http://', 'https://') 51 | 52 | def secondary_icon(self, msg, **config): 53 | user = msg['msg'].get('user', msg['msg'].get('user_text', '')) 54 | return avatar_url(user.lower()) 55 | 56 | def usernames(self, msg, **config): 57 | user = msg['msg'].get('user', msg['msg'].get('user_text', '')) 58 | return set([user.lower()]) 59 | 60 | def objects(self, msg, **config): 61 | if 'wiki.article.edit' in msg['topic']: 62 | return set([msg['msg']['title'].strip('/') + '-page']) 63 | elif 'wiki.upload.complete' in msg['topic']: 64 | return set([msg['msg']['url'][1:]]) 65 | 66 | return set() 67 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/conglomerators/bodhi/overrides.py: -------------------------------------------------------------------------------- 1 | import fedmsg.meta.base 2 | from fedmsg_meta_fedora_infrastructure.fasshim import avatar_url 3 | 4 | 5 | class ByUserTag(fedmsg.meta.base.BaseConglomerator): 6 | def can_handle(self, msg, **config): 7 | return any([ 8 | 'bodhi.buildroot_override.tag' in msg['topic'], 9 | ]) 10 | 11 | def matches(self, a, b, **config): 12 | """ The message must match by username """ 13 | submitter_a = a['msg']['override']['submitter']['name'] 14 | submitter_b = b['msg']['override']['submitter']['name'] 15 | if submitter_a != submitter_b: 16 | return False 17 | return True 18 | 19 | def merge(self, constituents, subject, **config): 20 | N = len(constituents) 21 | msg = constituents[0]['msg'] 22 | agent = msg['override']['submitter']['name'] 23 | branches = self.list_to_series([ 24 | constituent['msg']['override']['nvr'].split('.')[-1] 25 | for constituent in constituents]) 26 | 27 | tmpl = self.produce_template(constituents, subject, **config) 28 | packages = self.list_to_series(list(tmpl['packages'])) 29 | subtitle = '{agent} submitted {N} overrides for {packages} ' + \ 30 | 'on {branches}' 31 | tmpl['subtitle'] = subtitle.format( 32 | agent=agent, packages=packages, N=N, branches=branches) 33 | tmpl['subjective'] = tmpl['subtitle'] 34 | tmpl['secondary_icon'] = avatar_url(agent) 35 | base = 'https://bodhi.fedoraproject.org/overrides/?user=%s' 36 | tmpl['link'] = base % agent 37 | return tmpl 38 | 39 | 40 | class ByUserUnTag(fedmsg.meta.base.BaseConglomerator): 41 | def can_handle(self, msg, **config): 42 | return any([ 43 | 'bodhi.buildroot_override.untag' in msg['topic'], 44 | ]) 45 | 46 | def matches(self, a, b, **config): 47 | """ The message must match by username """ 48 | submitter_a = a['msg']['override']['submitter']['name'] 49 | submitter_b = b['msg']['override']['submitter']['name'] 50 | if submitter_a != submitter_b: 51 | return False 52 | return True 53 | 54 | def merge(self, constituents, subject, **config): 55 | N = len(constituents) 56 | msg = constituents[0]['msg'] 57 | agent = msg['override']['submitter']['name'] 58 | branches = self.list_to_series([ 59 | constituent['msg']['override']['nvr'].split('.')[-1] 60 | for constituent in constituents]) 61 | 62 | tmpl = self.produce_template(constituents, subject, **config) 63 | packages = self.list_to_series(list(tmpl['packages'])) 64 | subtitle = '{agent} expired {N} overrides for {packages} ' + \ 65 | 'on {branches}' 66 | tmpl['subtitle'] = subtitle.format( 67 | agent=agent, packages=packages, N=N, branches=branches) 68 | tmpl['subjective'] = tmpl['subtitle'] 69 | tmpl['secondary_icon'] = avatar_url(agent) 70 | base = 'https://bodhi.fedoraproject.org/overrides/?user=%s' 71 | tmpl['link'] = base % agent 72 | return tmpl 73 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/conglomerators/mailman/mailman.py: -------------------------------------------------------------------------------- 1 | import fedmsg.meta.base 2 | from fedmsg_meta_fedora_infrastructure.fasshim import avatar_url_from_email 3 | 4 | 5 | class ByMessageId(fedmsg.meta.base.BaseConglomerator): 6 | def can_handle(self, msg, **config): 7 | return '.mailman.receive' in msg['topic'] 8 | 9 | def matches(self, a, b, **config): 10 | a, b = a['msg']['msg'], b['msg']['msg'] 11 | a_references, b_references = [], [] 12 | if a['references']: 13 | a_references = [r.strip() for r in a['references'].split('\n')] 14 | if b['references']: 15 | b_references = [r.strip() for r in b['references'].split('\n')] 16 | 17 | a_references = set(a_references + [a['message-id']]) 18 | b_references = set(b_references + [b['message-id']]) 19 | 20 | # Return True if the messages share some subset of references. 21 | return a_references & b_references 22 | 23 | def get_secondary_icon(self, constituents, default): 24 | agents = set([m['msg']['msg']['from'] for m in constituents]) 25 | 26 | # Just take the first. 27 | agent = sorted(agents)[0] 28 | 29 | email = agent.split('<')[-1].split('>')[0] 30 | 31 | return avatar_url_from_email(email) 32 | 33 | def get_link(self, constituents): 34 | links = set([m['msg']['msg']['archived-at'] for m in constituents]) 35 | 36 | # Just take the first. 37 | link = sorted(links)[0] 38 | 39 | link = link.split('<')[-1].split('>')[0] 40 | 41 | return link 42 | 43 | def merge(self, constituents, subject, **config): 44 | ms = constituents # shorthand 45 | 46 | subtitle = u'{people} wrote {N} replies to the ' + \ 47 | '"{subject}" thread on the {mlists} {predicate}' 48 | 49 | people = set([ 50 | m['msg']['msg']['from'].split('<')[-1].split('>')[0] 51 | for m in ms 52 | ]) 53 | mlists = set([m['msg']['mlist']['list_name'] for m in ms]) 54 | predicate = 'list' if len(mlists) == 1 else 'lists' 55 | people = self.list_to_series(people) 56 | mlists = self.list_to_series(mlists) 57 | 58 | # Build a set of subjects and strip off the leading 'Re: RE: re: ...' 59 | subjects = set() 60 | for m in ms: 61 | subject = m['msg']['msg']['subject'] 62 | if 're: ' in subject.lower(): 63 | index = subject.lower().rindex('re: ') + 4 64 | subject = subject[index:] 65 | subjects.add(subject) 66 | 67 | # Just take the first.... 68 | subject = sorted(subjects)[0] 69 | 70 | tmpl = self.produce_template(constituents, subject, **config) 71 | tmpl['subtitle'] = subtitle.format( 72 | people=people, 73 | N=len(ms), 74 | subject=subject, 75 | mlists=mlists, 76 | predicate=predicate, 77 | ) 78 | tmpl['subjective'] = tmpl['subtitle'] 79 | 80 | default = tmpl['icon'] 81 | 82 | tmpl['secondary_icon'] = self.get_secondary_icon(constituents, default) 83 | tmpl['link'] = self.get_link(constituents) 84 | 85 | return tmpl 86 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/conglomerators/copr/copr.py: -------------------------------------------------------------------------------- 1 | import fedmsg.meta.base 2 | from fedmsg_meta_fedora_infrastructure.fasshim import avatar_url 3 | 4 | 5 | class AbstractCoprConglomerator(fedmsg.meta.base.BaseConglomerator): 6 | def can_handle(self, msg, **config): 7 | return '.copr.' in msg['topic'] 8 | 9 | def merge(self, constituents, subject, **config): 10 | ms = constituents # shorthand 11 | 12 | agents = set([m['msg']['user'] for m in ms if m['msg']['user']]) 13 | coprs = set([m['msg']['copr'] for m in ms]) 14 | count = len([1 for m in ms 15 | if m['topic'].endswith('copr.build.start')]) 16 | 17 | if count > 0: 18 | subtitle = '{agents} kicked off {count} {rebuild_predicate} ' + \ 19 | 'of the {coprs} {copr_predicate}' 20 | else: 21 | # If count is zero, then there are zero start messages in the 22 | # constituents list, so change tack and render "finishes" instead 23 | # of "starts". 24 | count = len(ms) 25 | subtitle = 'The {coprs} {copr_predicate} finished ' + \ 26 | '{count} {rebuild_predicate} by {agents}' 27 | 28 | rebuild_predicate = 'rebuilds' if count > 1 else 'rebuild' 29 | copr_predicate = 'coprs' if len(coprs) > 1 else 'copr' 30 | 31 | agents = self.list_to_series(agents) 32 | coprs = self.list_to_series(coprs) 33 | 34 | tmpl = self.produce_template(constituents, subject, **config) 35 | tmpl['subtitle'] = subtitle.format( 36 | agents=agents, count=count, coprs=coprs, 37 | copr_predicate=copr_predicate, rebuild_predicate=rebuild_predicate) 38 | tmpl['subjective'] = tmpl['subtitle'] 39 | 40 | default = tmpl['icon'] 41 | 42 | tmpl['secondary_icon'] = self.get_secondary_icon(constituents, default) 43 | tmpl['link'] = self.get_link(constituents) 44 | 45 | return tmpl 46 | 47 | 48 | class ByCopr(AbstractCoprConglomerator): 49 | def matches(self, a, b, **config): 50 | a, b = a['msg'], b['msg'] 51 | if a['copr'] != b['copr']: 52 | return False 53 | return True 54 | 55 | def get_secondary_icon(self, constituents, default): 56 | agents = set([m['msg']['user'] for m in constituents]) 57 | if len(agents) == 1: 58 | user = constituents[0]['msg']['user'] 59 | return avatar_url(user) 60 | else: 61 | return 'https://apps.fedoraproject.org/img/icons/copr.png' 62 | 63 | def get_link(self, constituents): 64 | owner = constituents[0]['msg']['owner'] 65 | copr = constituents[0]['msg']['copr'] 66 | return 'https://copr.fedoraproject.org/coprs/%s/%s/' % (owner, copr) 67 | 68 | 69 | class ByUser(AbstractCoprConglomerator): 70 | def matches(self, a, b, **config): 71 | a, b = a['msg'], b['msg'] 72 | if a['user'] != b['user']: 73 | return False 74 | return True 75 | 76 | def get_secondary_icon(self, constituents, default): 77 | user = constituents[0]['msg']['user'] 78 | return avatar_url(user) 79 | 80 | def get_link(self, constituents): 81 | user = constituents[0]['msg']['user'] 82 | return 'https://copr.fedoraproject.org/coprs/' + user 83 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/infragit.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2015 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: Ralph Bean 19 | # 20 | from fedmsg_meta_fedora_infrastructure import BaseProcessor 21 | from fedmsg_meta_fedora_infrastructure.fasshim import avatar_url 22 | 23 | 24 | class InfraGitProcessor(BaseProcessor): 25 | __name__ = "infragit" 26 | __description__ = "Fedora Infrastructure repos" 27 | __link__ = "https://infrastructure.fedoraproject.org/cgit/" 28 | __docs__ = "https://fedoraproject.org/wiki/Using_Fedora_GIT" 29 | __docs__ = "https://infrastructure.fedoraproject.org/infra/" + \ 30 | "docs/infra-git-repo.rst" 31 | __obj__ = "Infrastructure Commits" 32 | __icon__ = "https://apps.fedoraproject.org/img/icons/git-logo.png" 33 | 34 | def _get_repo(self, msg): 35 | return msg['msg']['commit']['path'].split('/')[-1] 36 | 37 | def subtitle(self, msg, **config): 38 | repo = self._get_repo(msg) 39 | user = self.agent(msg, **config) 40 | 41 | summ = msg['msg']['commit']['summary'] 42 | whole = msg['msg']['commit']['message'] 43 | if summ.strip() != whole.strip(): 44 | summ += " (..more)" 45 | 46 | branch = msg['msg']['commit']['branch'] 47 | 48 | tmpl = self._('{user} pushed a commit to the fedora-infra {repo} repo ' 49 | '({branch}): "{summary}"') 50 | return tmpl.format(user=user, repo=repo, branch=branch, summary=summ) 51 | 52 | def link(self, msg, **config): 53 | prefix = "https://infrastructure.fedoraproject.org/cgit" 54 | repo = self._get_repo(msg) 55 | 56 | # We don't have public links to some old repos.. 57 | if repo in ['puppet']: 58 | return '' 59 | 60 | rev = msg['msg']['commit']['rev'] 61 | branch = msg['msg']['commit']['branch'] 62 | tmpl = "{prefix}/{repo}.git/commit/?h={branch}&id={rev}" 63 | return tmpl.format(prefix=prefix, repo=repo, branch=branch, rev=rev) 64 | 65 | def secondary_icon(self, msg, **config): 66 | return avatar_url(self.agent(msg, **config)) 67 | 68 | def usernames(self, msg, **config): 69 | return set([self.agent(msg, **config)]) 70 | 71 | def agent(self, msg, **config): 72 | return msg['msg']['commit']['username'] 73 | 74 | def objects(self, msg, **config): 75 | repo = self._get_repo(msg) 76 | return set([ 77 | repo + '/' + filename 78 | for filename in msg['msg']['commit']['stats']['files'] 79 | ]) 80 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/greenwave.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2017 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: Ralph Bean 19 | # 20 | 21 | from six.moves.urllib.parse import urlencode 22 | from fedmsg_meta_fedora_infrastructure import BaseProcessor 23 | 24 | 25 | class GreenwaveProcessor(BaseProcessor): 26 | __name__ = "greenwave" 27 | __description__ = "Greenwave Gating Service" 28 | __link__ = "greenwave-web-greenwave.app.os.fedoraproject.org/api/v1.0/policies" 29 | __docs__ = "https://fedoraproject.org/wiki/Infrastructure/Factory2/Focus/Greenwave" 30 | __obj__ = "Gating Decisions" 31 | __icon__ = "https://apps.fedoraproject.org/img/icons/greenwave.png" 32 | 33 | @staticmethod 34 | def satisfied(msg): 35 | try: 36 | # https://pagure.io/greenwave/pull-request/100 37 | return msg['msg']['policies_satisfied'] 38 | except KeyError: 39 | return msg['msg']['policies_satisified'] 40 | 41 | def link(self, msg, **config): 42 | subject = msg['msg']['subject'] 43 | if subject: 44 | base = "https://taskotron.fedoraproject.org/resultsdb/results" 45 | query = urlencode(sorted(subject[0].items())) 46 | return base + "?" + query 47 | 48 | def subtitle(self, msg, **config): 49 | if self.satisfied(msg): 50 | decision = self._("is a GO") 51 | else: 52 | decision = self._("says NO-GO") 53 | 54 | tmpl = self._( 55 | "greenwave {decision} on {item} for " 56 | "\"{decision_context}\" ({product_version})" 57 | ) 58 | msg_body = msg['msg'] 59 | item = msg_body.get('subject_identifier') 60 | if not item: 61 | subject = msg_body['subject'] 62 | items = [entry.get('item') for entry in subject if entry.get('item')] 63 | item = items[0] if items else "\"something\"" 64 | return tmpl.format(decision=decision, item=item, **msg['msg']) 65 | 66 | def secondary_icon(self, msg, **config): 67 | packages = self.packages(msg, **config) 68 | if packages: 69 | primary = sorted(packages)[0] 70 | base = 'https://apps.fedoraproject.org/packages/images/icons/' 71 | return base + primary + '.png' 72 | 73 | def packages(self, msg, **config): 74 | subject = msg['msg']['subject'] 75 | items = [ 76 | entry.get('item') for entry in subject 77 | if entry.get('item') and entry.get('type') == 'koji_build' 78 | ] 79 | return set([item.rsplit('-', 2)[0] for item in items]) 80 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/tests/mbs.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2017 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: Ralph Bean 19 | # 20 | """ Tests for MBS messages """ 21 | 22 | import unittest 23 | 24 | from fedmsg_meta_fedora_infrastructure.tests.base import Base 25 | 26 | from .common import add_doc 27 | 28 | 29 | class TestModuleBuildStateChange(Base): 30 | """ These messages are published by the `module build service 31 | `_ when a module 32 | build transitions between states (like starting, or completing). 33 | """ 34 | expected_title = "mbs.module.state.change" 35 | expected_subti = "ralph's build of modules/testmodule " + \ 36 | "entered the wait state." 37 | expected_link = "https://mbs.fedoraproject.org/module-build-service/1/module-builds/2" 38 | expected_icon = "https://apps.fedoraproject.org/img/icons/modularity.png" 39 | expected_secondary_icon = "https://seccdn.libravatar.org/avatar/" + \ 40 | "9c9f7784935381befc302fe3c814f9136e7a33953d0318761669b8643f4df55c" + \ 41 | "?s=64&d=retro" 42 | expected_packages = set([ 43 | # TODO -- we'll eventually have to think about how to show all relevant 44 | # packages here. Are "modules" really a package, from this PoV? 45 | ]) 46 | expected_usernames = set(['ralph']) 47 | expected_objects = set(['testmodule']) 48 | msg = { 49 | "source_name": "datanommer", 50 | "i": 1, 51 | "timestamp": 1487188431.0, 52 | "msg_id": "2017-859a8cfb-6d95-43f4-9c0b-897e833b06b5", 53 | "topic": "org.fedoraproject.stg.mbs.module.state.change", 54 | "source_version": "0.6.5", 55 | "msg": { 56 | "state_reason": None, 57 | "component_builds": [ 58 | 19, 59 | 20, 60 | 21 61 | ], 62 | "name": "testmodule", 63 | "stream": "master", 64 | "time_submitted": 1487178787.0, 65 | "state_url": "/module-build-service/1/module-builds/2", 66 | "time_modified": 1487188430.0, 67 | "scmurl": "git://pkgs.stg.fedoraproject.org/modules/testmodule.git?#620ec77", 68 | "state": 1, 69 | "modulemd": "full modulemd text goes here...", 70 | "time_completed": None, 71 | "version": "20161115001755", 72 | "owner": "ralph", 73 | "id": 2, 74 | "state_name": "wait" 75 | } 76 | } 77 | 78 | 79 | 80 | add_doc(locals()) 81 | 82 | if __name__ == '__main__': 83 | unittest.main() 84 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/summershum.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2014 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: Ralph Bean 19 | # 20 | from fedmsg_meta_fedora_infrastructure import BaseProcessor 21 | from fedmsg_meta_fedora_infrastructure.fasshim import avatar_url 22 | 23 | 24 | class SummerShumProcessor(BaseProcessor): 25 | __name__ = "summershum" 26 | __description__ = "a backend tool that extracts hashes of source files" 27 | __link__ = "https://github.com/fedora-infra/summershum" 28 | __docs__ = "https://github.com/fedora-infra/summershum" 29 | __obj__ = "Source File Hashes" 30 | __icon__ = "https://raw.githubusercontent.com/" + \ 31 | "fedora-infra/summershum/develop/summershum.png" 32 | 33 | def subtitle(self, msg, **config): 34 | if msg['topic'].endswith('fail'): 35 | tmpl = self._('yikes! summershum failed to process {filename} ' 36 | 'for {name}') 37 | elif msg['topic'].endswith('complete'): 38 | tmpl = self._('summershum ingested {filename} ' 39 | 'for {name}') 40 | elif msg['topic'].endswith('start'): 41 | tmpl = self._('summershum started working on {filename} ' 42 | 'for {name}') 43 | else: 44 | tmpl = self._('(unhandled)') 45 | 46 | return tmpl.format(**msg['msg']['original']) 47 | 48 | def secondary_icon(self, msg, **config): 49 | return avatar_url(msg['msg']['original']['agent']) 50 | 51 | def usernames(self, msg, **config): 52 | return set([msg['msg']['original']['agent']]) 53 | 54 | def packages(self, msg, **config): 55 | return set([msg['msg']['original']['name']]) 56 | 57 | def objects(self, msg, **config): 58 | original = msg['msg']['original'] 59 | return set(['/'.join([ 60 | 'digests', 61 | original['name'], 62 | original['filename'], 63 | original['md5sum'], 64 | ])]) 65 | 66 | def link(self, msg, **config): 67 | o = msg['msg']['original'] 68 | prefix = "http://pkgs.fedoraproject.org/lookaside/pkgs" 69 | 70 | if 'path' in o: 71 | path = o['path'] 72 | 73 | else: 74 | # Fallback to the old message format from the dark ages of MD5 75 | name = o['name'] 76 | md5sum = o['md5sum'] 77 | filename = o['filename'] 78 | tmpl = "{name}/{filename}/{md5sum}/{filename}" 79 | 80 | path = tmpl.format(name=name, md5sum=md5sum, filename=filename) 81 | 82 | return "{prefix}/{path}".format(prefix=prefix, path=path) 83 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/jenkins.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2014 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: Ricky Elrod 19 | 20 | from fedmsg_meta_fedora_infrastructure import BaseProcessor 21 | from fedmsg_meta_fedora_infrastructure.fasshim import avatar_url 22 | 23 | 24 | class JenkinsProcessor(BaseProcessor): 25 | __name__ = "Jenkins" 26 | __description__ = "Jenkins CI system" 27 | __link__ = "http://jenkins.cloud.fedoraproject.org/" 28 | __docs__ = "https://fedoraproject.org/wiki/Jenkins@infra" 29 | __obj__ = "Jenkins build status" 30 | __icon__ = ("https://wiki.jenkins-ci.org/download/attachments/" 31 | "2916393/logo.png?version=1") 32 | 33 | def subtitle(self, msg, **config): 34 | project = msg['msg'].get('project') 35 | 36 | if 'jenkins.build.failed' in msg['topic']: 37 | tmpl = self._("Jenkins project '{project}' failed to build") 38 | elif 'jenkins.build.passed' in msg['topic']: 39 | tmpl = self._("Jenkins project '{project}' built successfully") 40 | elif 'jenkins.build.unstable' in msg['topic']: 41 | tmpl = self._("Jenkins project '{project}' built with warnings") 42 | elif 'jenkins.build.notbuilt' in msg['topic']: 43 | tmpl = self._("Jenkins project '{project}' did not build") 44 | elif 'jenkins.build.aborted' in msg['topic']: 45 | tmpl = self._("Jenkins project '{project}' build aborted") 46 | elif 'jenkins.build.start' in msg['topic']: 47 | tmpl = self._("Jenkins project '{project}' started building") 48 | elif 'jenkins.build.unknown' in msg['topic']: 49 | tmpl = self._("Jenkins project '{project}' " 50 | "entered an unknown state") 51 | else: 52 | raise NotImplementedError(msg['topic']) 53 | 54 | return tmpl.format(project=project) 55 | 56 | def link(self, msg, **config): 57 | build_id = msg['msg'].get('build') 58 | project = msg['msg'].get('project') 59 | 60 | if build_id is not None and project is not None: 61 | tmpl = ("http://jenkins.cloud.fedoraproject.org/job/{project}/" 62 | "{build_id}/") 63 | return tmpl.format(build_id=build_id, project=project) 64 | else: 65 | return None 66 | 67 | def secondary_icon(self, msg, **config): 68 | return '' 69 | 70 | def usernames(self, msg, **config): 71 | return set() 72 | 73 | def objects(self, msg, **config): 74 | items = ['jenkins', msg['msg']['project']] 75 | items.append('.'.join(msg['topic'].split('.')[-2:])) 76 | return set(['/'.join(items)]) 77 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/fmn.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2014 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: Ralph Bean 19 | 20 | import six 21 | 22 | from fedmsg_meta_fedora_infrastructure.fasshim import avatar_url 23 | from fedmsg_meta_fedora_infrastructure import BaseProcessor 24 | 25 | 26 | class FMNProcessor(BaseProcessor): 27 | __name__ = "FMN" 28 | __description__ = "the Fedora Notifications System" 29 | __link__ = "https://apps.fedoraproject.org/notifications/" 30 | __icon__ = "https://apps.fedoraproject.org/img/icons/fedmsg.png" 31 | __docs__ = "https://github.com/fedora-infra/fmn" 32 | __obj__ = "Notification Preference Updates" 33 | 34 | def subtitle(self, msg, **config): 35 | kwargs = dict( 36 | user=self.username(msg), 37 | ctx=msg['msg']['context'], 38 | obj=msg['topic'].split('.')[-2], 39 | changed=msg['msg']['changed'], 40 | ) 41 | 42 | if 'fmn.confirmation.update' in msg['topic']: 43 | tmpl = self._("the {changed} of one of {user}'s " 44 | "pending confirmations changed") 45 | elif 'fmn.rule.update' in msg['topic']: 46 | tmpl = self._("{user} updated the {changed} on a fmn {ctx} rule") 47 | elif 'fmn.filter.update' in msg['topic']: 48 | tmpl = self._("{user} updated the {changed} on a fmn {ctx} filter") 49 | elif 'fmn.preference.update' in msg['topic']: 50 | if 'enabled' == kwargs['changed']: 51 | tmpl = self._("{user} toggled their flow of {ctx} messages") 52 | else: 53 | swaps = { 54 | 'batch_values': self._('digest options'), 55 | 'details': self._('delivery details'), 56 | } 57 | changed = kwargs['changed'] 58 | kwargs['changed'] = swaps.get(changed, changed) 59 | tmpl = self._("{user} updated their {ctx} {changed}") 60 | else: 61 | tmpl = '' 62 | 63 | return tmpl.format(**kwargs) 64 | 65 | def link(self, msg, **config): 66 | return self.__link__ 67 | 68 | def secondary_icon(self, msg, **config): 69 | return avatar_url(self.username(msg)) 70 | 71 | def usernames(self, msg, **config): 72 | return set([self.username(msg)]) 73 | 74 | def username(self, msg): 75 | return msg['msg']['openid'].split('.')[0] 76 | 77 | def objects(self, msg, **config): 78 | user = self.username(msg) 79 | ctx = msg['msg']['context'] 80 | obj = msg['topic'].split('.')[-2] 81 | changed = msg['msg']['changed'] 82 | tokens = [user, ctx, obj, changed] 83 | return set(['/'.join(map(six.text_type, tokens))]) 84 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/badges.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2012, 2013 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: Ralph Bean 19 | # Luke Macken 20 | 21 | from fedmsg_meta_fedora_infrastructure.fasshim import avatar_url 22 | from fedmsg_meta_fedora_infrastructure import BaseProcessor 23 | 24 | 25 | class BadgesProcessor(BaseProcessor): 26 | __name__ = "fedbadges" 27 | __description__ = "the Fedora Open Badges System" 28 | __link__ = "https://badges.fedoraproject.org/" 29 | __icon__ = "https://apps.fedoraproject.org/img/icons/badges.png" 30 | __docs__ = "https://fedoraproject.org/wiki/Open_Badges" 31 | __obj__ = "New Badges" 32 | 33 | def _get_user(self, msg): 34 | # Handle the difference between badge.award and person.rank.advance. 35 | if 'user' in msg['msg']: 36 | return msg['msg']['user']['username'] 37 | else: 38 | return msg['msg']['person']['nickname'] 39 | 40 | def link(self, msg, **config): 41 | username = self._get_user(msg) 42 | return "https://badges.fedoraproject.org/user/%s" % username 43 | 44 | def long_form(self, msg, **config): 45 | if 'badge.award' in msg['topic']: 46 | return msg['msg']['badge']['description'] 47 | 48 | def subtitle(self, msg, **config): 49 | user = self._get_user(msg) 50 | if 'badge.award' in msg['topic']: 51 | name = msg['msg']['badge']['name'] 52 | tmpl = self._('{user} has been awarded the "{name}" badge') 53 | return tmpl.format(user=user, name=name) 54 | elif 'person.rank.advance' in msg['topic']: 55 | rank = msg['msg']['person']['rank'] 56 | tmpl = self._('{user} moved to position {rank} ' 57 | 'on the badges leaderboard') 58 | return tmpl.format(user=user, rank=rank) 59 | elif 'person.login.first' in msg['topic']: 60 | tmpl = self._('{user} logged in to badges.fedoraproject.org ' 61 | 'for the first time') 62 | return tmpl.format(user=user) 63 | else: 64 | pass 65 | 66 | def icon(self, msg, **config): 67 | if 'badge.award' in msg['topic']: 68 | return msg['msg']['badge']['image_url'] 69 | else: 70 | return super(BadgesProcessor, self).icon(msg, **config) 71 | 72 | def secondary_icon(self, msg, **config): 73 | return avatar_url(self._get_user(msg)) 74 | 75 | def usernames(self, msg, **config): 76 | return set([self._get_user(msg)]) 77 | 78 | def objects(self, msg, **config): 79 | if 'badge.award' in msg['topic']: 80 | return set([msg['msg']['badge']['name'].lower().replace(' ', '-')]) 81 | else: 82 | return set([]) 83 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/tests/koschei.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2014 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: Michael Simacek 19 | # 20 | """ Tests for Koschei messages """ 21 | 22 | from fedmsg_meta_fedora_infrastructure.tests.base import Base 23 | 24 | from .common import add_doc 25 | 26 | 27 | class TestKoscheiPackageStateChange(Base): 28 | """ Koschei is a continuous integration system for RPM packages. It tracks 29 | dependency changes done in Koji repositories and rebuilds packages whose 30 | build dependencies change too much. 31 | 32 | This message type is published by Koschei when package's build or resolution 33 | state changes. 34 | """ 35 | 36 | expected_title = "koschei.package.state.change" 37 | expected_subti = "rnv's builds started to fail in Fedora 22 (arm)" 38 | expected_link = 'https://apps.fedoraproject.org/koschei/package/rnv?collection=f22' 39 | expected_secondary_icon = \ 40 | 'https://apps.fedoraproject.org/packages/images/icons/rnv.png' 41 | expected_packages = set(['rnv']) 42 | 43 | msg = { 44 | "username": "msimacek", 45 | "i": 2, 46 | "timestamp": 1412260063, 47 | "msg_id": "2014-45d99116-f93e-45ef-8611-04fa2eabbb82", 48 | "topic": "org.fedoraproject.dev.koschei.package.state.change", 49 | "msg": { 50 | "name": "rnv", 51 | "old": "ok", 52 | "new": "failing", 53 | "koji_instance": "arm", 54 | "repo": "f22", 55 | "collection": "f22", 56 | "collection_name": "Fedora 22", 57 | "groups": ["c", "xml"] 58 | } 59 | } 60 | 61 | 62 | class TestKoscheiCollectionStateChange(Base): 63 | """ Koschei is a continuous integration system for RPM packages. It tracks 64 | dependency changes done in Koji repositories and rebuilds packages whose 65 | build dependencies change too much. 66 | 67 | This message type is published by Koschei when collection resolution 68 | state changes. 69 | """ 70 | 71 | expected_title = "koschei.collection.state.change" 72 | expected_subti = "Fedora 26 buildroot was broken" 73 | expected_link = 'https://apps.fedoraproject.org/koschei/collection/f26' 74 | 75 | msg = { 76 | "username": "msimacek", 77 | "i": 2, 78 | "timestamp": 1412260063, 79 | "msg_id": "2014-45d99116-f93e-45ef-8611-04fa2eabbb82", 80 | "topic": "org.fedoraproject.dev.koschei.collection.state.change", 81 | "msg": { 82 | "name": "rnv", 83 | "old": "ok", 84 | "new": "unresolved", 85 | "koji_instance": "primary", 86 | "collection": "f26", 87 | "collection_name": "Fedora 26" 88 | } 89 | } 90 | 91 | 92 | add_doc(locals()) 93 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/kerneltest.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2012-2014 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: Ralph Bean 19 | 20 | from fedmsg_meta_fedora_infrastructure.fasshim import avatar_url 21 | from fedmsg_meta_fedora_infrastructure import BaseProcessor 22 | 23 | 24 | class KernelTestProcessor(BaseProcessor): 25 | __name__ = "kerneltest" 26 | __description__ = "Kernel Testing Initiative" 27 | __link__ = "https://apps.fedoraproject.org/kerneltest" 28 | __icon__ = "https://apps.fedoraproject.org/img/icons/tux.png" 29 | __docs__ = "https://fedoraproject.org/wiki/KernelTestingInitiative" 30 | __obj__ = "Kernel Tests" 31 | 32 | def link(self, msg, **config): 33 | if 'test' in msg['msg']: 34 | vers = msg['msg']['test']['kernel_version'] 35 | return 'https://apps.fedoraproject.org/kerneltest/kernel/' + vers 36 | return 'https://apps.fedoraproject.org/kerneltest/stats' 37 | 38 | def subtitle(self, msg, **config): 39 | user = msg['msg']['agent'] 40 | 41 | if 'test' in msg['msg']: 42 | tmpl = self._('{user} ran a test of {version} ({result})') 43 | version = msg['msg']['test']['kernel_version'] 44 | result = msg['msg']['test']['result'] 45 | return tmpl.format(user=user, version=version, result=result) 46 | elif 'release.edit' in msg['topic']: 47 | tmpl = self._( 48 | '{user} edited the {release}-{support} ' 49 | 'release for kerneltest') 50 | release = msg['msg']['release']['releasenum'] 51 | support = msg['msg']['release']['support'] 52 | return tmpl.format(user=user, release=release, support=support) 53 | elif 'release.new' in msg['topic']: 54 | tmpl = self._( 55 | '{user} added a new release for kerneltest: ' 56 | '{release} {support}') 57 | release = msg['msg']['release']['releasenum'] 58 | support = msg['msg']['release']['support'] 59 | return tmpl.format(user=user, release=release, support=support) 60 | 61 | def secondary_icon(self, msg, **config): 62 | return avatar_url(msg['msg']['agent']) 63 | 64 | def usernames(self, msg, **config): 65 | return set([msg['msg']['agent']]) 66 | 67 | def packages(self, msg, **config): 68 | return set(['kernel']) 69 | 70 | def objects(self, msg, **config): 71 | if 'test' in msg['msg']: 72 | vers = msg['msg']['test']['kernel_version'] 73 | return set(['kernel/' + vers]) 74 | elif 'release' in msg['msg']: 75 | releasenum = msg['msg']['release']['releasenum'] 76 | support = msg['msg']['release']['support'] 77 | return set(['release/{releasenum}/{support}'.format( 78 | releasenum=releasenum, support=support)]) 79 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/mm2.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2013, 2014 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: Ralph Bean 19 | # 20 | 21 | from fedmsg_meta_fedora_infrastructure import BaseProcessor 22 | 23 | 24 | class MirrorManagerProcessor(BaseProcessor): 25 | __name__ = "mirrormanager" 26 | __description__ = "Mirror Manager activity" 27 | __link__ = "https://mirrors.fedoraproject.org" 28 | __docs__ = "https://github.com/fedora-infra/mirrormanager2" 29 | __obj__ = "Mirror Updates" 30 | __icon__ = "https://apps.fedoraproject.org/img/icons/downloads.png" 31 | 32 | def link(self, msg, **config): 33 | return self.__link__ 34 | 35 | def subtitle(self, msg, **config): 36 | topic, msg = msg['topic'], msg['msg'] 37 | if 'mirrormanager.crawler.complete' in topic: 38 | results = msg['results'] 39 | total = len(results) 40 | succeeded = len([1 for r in results if r['rc'] == 0]) 41 | failed = len([1 for r in results if r['rc'] != 0]) 42 | tmpl = self._( 43 | "mirrormanager's crawler finished a crawl of {total} mirrors " 44 | "({succeeded} succeeded, {failed} failed)" 45 | ) 46 | return tmpl.format(total=total, succeeded=succeeded, failed=failed) 47 | elif 'mirrormanager.crawler.start' in topic: 48 | total = len(msg['hosts']) 49 | tmpl = self._( 50 | "mirrormanager's crawler started a crawl of {total} mirrors") 51 | return tmpl.format(total=total) 52 | elif 'mirrormanager.netblocks.get' in topic: 53 | type = msg['type'] 54 | 55 | if msg['success']: 56 | status = self._("successfully updated") 57 | else: 58 | status = self._("failed to update") 59 | 60 | tmpl = self._( 61 | "mirrormanager's backend {status} its {type} netblocks file") 62 | return tmpl.format(status=status, type=type) 63 | 64 | def secondary_icon(self, msg, **config): 65 | return self.icon(msg, **config) 66 | 67 | def usernames(self, msg, **config): 68 | return set() 69 | 70 | def packages(self, msg, **config): 71 | return set() 72 | 73 | def objects(self, msg, **config): 74 | if 'mirrormanager.crawler' in msg['topic']: 75 | if 'hosts' in msg['msg']: 76 | return set([ 77 | 'mirrors/%s' % host.get('host', host.get('name')) 78 | for host in msg['msg']['hosts'] 79 | ]) 80 | else: 81 | return set([ 82 | 'mirrors/%s' % result['host']['name'] 83 | for result in msg['msg']['results'] 84 | ]) 85 | if 'mirrormanager.netblocks' in msg['topic']: 86 | return set([ 87 | 'netblocks/' + msg['msg']['type'] 88 | ]) 89 | 90 | return set([]) 91 | 92 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/tests/ftpsync.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2014 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: Ralph Bean 19 | # 20 | """ Tests for ftpsync messages """ 21 | 22 | from fedmsg_meta_fedora_infrastructure.tests.base import Base 23 | 24 | from .common import add_doc 25 | 26 | 27 | class TestFTPSyncAtomic(Base): 28 | """ These messages are published when a new compose of Fedora Atomic 29 | is synced out to the master mirror. 30 | """ 31 | expected_title = "bodhi.updates.fedora.sync" 32 | expected_subti = "New Fedora 21 atomic content synced out " + \ 33 | "(60.38M changed with 0 files deleted)" 34 | expected_link = \ 35 | "https://download.fedoraproject.org/pub/fedora/linux/atomic/21/" 36 | expected_objects = set(['fedora/atomic/21']) 37 | 38 | msg = { 39 | "i": 1, 40 | "timestamp": 1344447839.891876, 41 | "topic": "org.fedoraproject.prod.bodhi.updates.fedora.sync", 42 | "msg": { 43 | "bytes": "60.38M", 44 | "deleted": "0", 45 | "repo": "atomic", 46 | "release": "21", 47 | }, 48 | } 49 | 50 | 51 | class TestFTPSyncFedora(Base): 52 | """ These messages are published when new updates (fresh out of the "mash" 53 | process) are synced out to the master mirror. 54 | 55 | Here's an example for the fedora 20 stable repos: 56 | """ 57 | expected_title = "bodhi.updates.fedora.sync" 58 | expected_subti = "New Fedora 20 updates content synced out " + \ 59 | "(2.8M changed with 0 files deleted)" 60 | expected_link = \ 61 | "https://download.fedoraproject.org/pub/fedora/linux/updates/20/" 62 | expected_objects = set(['fedora/updates/20']) 63 | 64 | msg = { 65 | "i": 1, 66 | "timestamp": 1344447839.891876, 67 | "topic": "org.fedoraproject.prod.bodhi.updates.fedora.sync", 68 | "msg": { 69 | "bytes": "2.8M", 70 | "deleted": "0", 71 | "repo": "updates", 72 | "release": "20", 73 | }, 74 | } 75 | 76 | 77 | class TestFTPSyncEPELTesting(Base): 78 | """ These messages are published when new updates (fresh out of the "mash" 79 | process) are synced out to the master mirror. 80 | 81 | Here's an example for the epel 6 testing repos: 82 | """ 83 | expected_title = "bodhi.updates.epel.sync" 84 | expected_subti = "New EPEL 6 epel-testing content synced out " + \ 85 | "(28493k changed with 0 files deleted)" 86 | expected_link = \ 87 | "https://download.fedoraproject.org/pub/epel/testing/6/" 88 | expected_objects = set(['epel/epel-testing/6']) 89 | 90 | msg = { 91 | "i": 1, 92 | "timestamp": 1344447839.891876, 93 | "topic": "org.fedoraproject.prod.bodhi.updates.epel.sync", 94 | "msg": { 95 | "bytes": "28493k", 96 | "deleted": "0", 97 | "repo": "epel-testing", 98 | "release": "6", 99 | }, 100 | } 101 | 102 | 103 | add_doc(locals()) 104 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/taskotron.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2015 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: Martin Krizek 19 | # Ralph Bean 20 | 21 | import logging 22 | 23 | import requests 24 | 25 | from fedmsg_meta_fedora_infrastructure import BaseProcessor 26 | 27 | log = logging.getLogger('fedmsg.meta') 28 | 29 | 30 | class TaskotronProcessor(BaseProcessor): 31 | __name__ = "taskotron" 32 | __description__ = "Framework for automated task execution" 33 | __link__ = "https://taskotron.fedoraproject.org/" 34 | __docs__ = "https://docs.qadevel.cloud.fedoraproject.org/libtaskotron/latest/" 35 | __obj__ = "Automated task results" 36 | __icon__ = "https://apps.fedoraproject.org/img/icons/taskotron.png" 37 | 38 | def subtitle(self, msg, **config): 39 | if msg['topic'].endswith('taskotron.result.new'): 40 | taskname = msg['msg']['task'].get('name', '') 41 | outcome = msg['msg']['result'].get('outcome', '') 42 | taskitem = msg['msg']['task'].get('item', '') 43 | return '%s %s for %s' % (taskname, outcome, taskitem) 44 | 45 | def link(self, msg, **config): 46 | if msg['topic'].endswith('taskotron.result.new'): 47 | return msg['msg']['result'].get('log_url', '') 48 | 49 | def objects(self, msg, **config): 50 | packages = self.packages(msg, **config) 51 | return set([ 52 | '/'.join([ 53 | msg['msg']['task'].get('name', ''), 54 | package, 55 | msg['msg']['result'].get('outcome', '') 56 | ]) 57 | for package in packages 58 | ]) 59 | 60 | def packages(self, msg, **config): 61 | type = msg['msg']['task']['type'] 62 | if type == 'koji_build': 63 | nvr = msg['msg']['task']['item'] 64 | name, version, release = nvr.rsplit('-', 2) 65 | return set([name]) 66 | elif type == 'bodhi_update': 67 | alias = msg['msg']['task']['item'] 68 | default_url = 'https://bodhi.fedoraproject.org' 69 | bodhi_url = config.get('bodhi_url', default_url) 70 | resp = requests.get(bodhi_url + '/updates/' + alias) 71 | if not bool(resp): 72 | log.warn("Failed to talk to bodhi %r %r" % (resp, resp.url)) 73 | return set() 74 | data = resp.json() 75 | builds = data['update']['builds'] 76 | nvrs = [build['nvr'] for build in builds] 77 | packages = [nvr.rsplit('-', 2)[0] for nvr in nvrs] 78 | return set(packages) 79 | 80 | log.warn('Unhandled taskotron type %r' % type) 81 | return set() 82 | 83 | def secondary_icon(self, msg, **config): 84 | packages = self.packages(msg, **config) 85 | if len(packages) != 1: 86 | # If it is 0 or greater than 1, just use the taskotron icon. 87 | return self.__icon__ 88 | else: 89 | url = 'https://apps.fedoraproject.org/packages/images/icons/%s.png' 90 | package = list(packages)[0] 91 | return url % package 92 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/ansible.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2012 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: Ralph Bean 19 | # 20 | from fedmsg_meta_fedora_infrastructure import BaseProcessor 21 | 22 | from fedmsg_meta_fedora_infrastructure.fasshim import avatar_url 23 | 24 | from fedmsg_meta_fedora_infrastructure.conglomerators.ansible import \ 25 | playbooks as ansible_playbooks 26 | 27 | fs_prefix = "/srv/web/infra/ansible/" 28 | 29 | 30 | def relative_playbook(playbook): 31 | """ Returns a tuple (controlled, playbook). 32 | 33 | - controlled is a boolean indicating whether or not we think that the 34 | playbook being run was checked in to our ansible git repo. 35 | - playbook is the relative file path of the playbook. 36 | """ 37 | if playbook.startswith(fs_prefix): 38 | return True, playbook[len(fs_prefix):] 39 | else: 40 | return False, playbook.split('/')[-1] 41 | 42 | 43 | class AnsibleProcessor(BaseProcessor): 44 | __name__ = "ansible" 45 | __description__ = "Fedora Infrastructure Ansible Runs" 46 | __link__ = "http://infrastructure.fedoraproject.org/cgit/ansible.git" 47 | __icon__ = "https://apps.fedoraproject.org/img/icons/ansible.png" 48 | __docs__ = \ 49 | "https://fedoraproject.org/wiki/Infrastructure_ansible_migration" 50 | __obj__ = "Ansible Runs" 51 | 52 | conglomerators = [ 53 | ansible_playbooks.ByUser, 54 | ] 55 | 56 | def subtitle(self, msg, **config): 57 | user = msg['msg'].get('userid', '(no user specified)') 58 | controlled, playbook = relative_playbook(msg['msg']['playbook']) 59 | 60 | if 'ansible.playbook.start' in msg['topic']: 61 | tmpl = self._("{user} started an ansible run of {playbook}") 62 | return tmpl.format(user=user, playbook=playbook) 63 | elif 'ansible.playbook.complete' in msg['topic']: 64 | tmpl = self._("{user}'s {playbook} playbook run completed") 65 | return tmpl.format(user=user, playbook=playbook) 66 | return "" 67 | 68 | def secondary_icon(self, msg, **config): 69 | user = msg['msg'].get('userid') 70 | if user: 71 | return avatar_url(user) 72 | 73 | def link(self, msg, **config): 74 | base = "http://infrastructure.fedoraproject.org/cgit/ansible.git/tree/" 75 | controlled, playbook = relative_playbook(msg['msg']['playbook']) 76 | if not controlled: 77 | return None 78 | else: 79 | return base + playbook 80 | 81 | def usernames(self, msg, **config): 82 | user = msg['msg'].get('userid') 83 | if user: 84 | return set([user]) 85 | return set() 86 | 87 | def objects(self, msg, **config): 88 | controlled, playbook = relative_playbook(msg['msg']['playbook']) 89 | 90 | if not controlled: 91 | playbook = "uncontrolled-playbooks/" + playbook 92 | 93 | if 'results' in msg['msg']: 94 | return set([playbook] + [ 95 | "inventory/" + host for host in msg['msg']['results'].keys() 96 | ]) 97 | else: 98 | return set([playbook]) 99 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/nagios.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2015 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: Ralph Bean 19 | 20 | from fedmsg_meta_fedora_infrastructure import BaseProcessor 21 | from fedmsg_meta_fedora_infrastructure.fasshim import avatar_url 22 | 23 | 24 | class NagiosProcessor(BaseProcessor): 25 | __name__ = "Nagios" 26 | __description__ = "Fedora Infra Service Monitoring" 27 | __link__ = "https://admin.fedoraproject.org/nagios" 28 | __docs__ = "https://infrastructure.fedoraproject.org/infra/docs/nagios.rst" 29 | __obj__ = "Service Outage Alerts" 30 | __icon__ = "https://apps.fedoraproject.org/img/icons/nagios-logo.png" 31 | 32 | def subtitle(self, msg, **config): 33 | states = { 34 | 'CRITICAL': self._('down'), 35 | 'WARNING': self._('having problems'), 36 | 'OK': self._('back up'), 37 | } 38 | state = msg['msg']['state'] 39 | state = states.get(state, self._('in an unknown state')) 40 | host = msg['msg']['host'] 41 | 42 | result = None 43 | if msg['topic'].endswith('host.state.change'): 44 | tmpl = self._('{host} is {state}') 45 | result = tmpl.format(host=host, state=state) 46 | elif msg['topic'].endswith('service.state.change'): 47 | service = msg['msg'].get('service', 'some service') 48 | tmpl = self._('{service} is {state} on {host}') 49 | result = tmpl.format(service=service, host=host, state=state) 50 | 51 | if msg['msg']['type'] == 'ACKNOWLEDGEMENT': 52 | users = self.usernames(msg, **config) 53 | agent = 'somebody' 54 | if users: 55 | agent = list(users)[0] 56 | prefix = self._('{agent} acknowledged that ').format(agent=agent) 57 | result = prefix + result 58 | 59 | if result and 'output' in msg['msg']: 60 | result += ': "{output}"'.format(output=msg['msg']['output']) 61 | 62 | return result 63 | 64 | def link(self, msg, **config): 65 | base = 'https://admin.fedoraproject.org/nagios/cgi-bin/status.cgi' 66 | query = '?navbarsearch=1&host=' 67 | host = msg['msg']['host'] 68 | return base + query + host 69 | 70 | def secondary_icon(self, msg, **config): 71 | users = self.usernames(msg, **config) 72 | if users: 73 | return avatar_url(list(users)[0]) 74 | return self.__icon__ 75 | 76 | def usernames(self, msg, **config): 77 | users = set() 78 | service_ack = msg['msg']['service_ack_author'] 79 | if service_ack: 80 | users.add(service_ack.split('://')[-1].split('.')[0]) 81 | 82 | host_ack = msg['msg']['host_ack_author'] 83 | if host_ack: 84 | users.add(host_ack.split('://')[-1].split('.')[0]) 85 | 86 | return users 87 | 88 | def objects(self, msg, **config): 89 | host = msg['msg']['host'] 90 | service = msg['msg'].get('service', 'unknown') 91 | if msg['topic'].endswith('host.state.change'): 92 | service = 'state' 93 | return set([ 94 | '/'.join([host, service]), 95 | ]) 96 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/tests/odcs.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2020 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: Jan Kaluza 19 | # 20 | """ Tests for ODCS messages """ 21 | 22 | import unittest 23 | 24 | from fedmsg_meta_fedora_infrastructure.tests.base import Base 25 | 26 | from .common import add_doc 27 | 28 | 29 | class TestComposeStateChanged(Base): 30 | """ These messages are published by the `module build service 31 | `_ when a module 32 | build transitions between states (like starting, or completing). 33 | """ 34 | expected_title = "odcs.compose.state-changed" 35 | expected_subti = "jkaluza's compose 378 " + \ 36 | "entered the generating state." 37 | expected_link = "https://odcs.fedoraproject.org/api/1/composes/378" 38 | expected_icon = "https://apps.fedoraproject.org/img/icons/odcs.png" 39 | expected_secondary_icon = "https://seccdn.libravatar.org/avatar/" + \ 40 | "1ecc757d81ddcab5c53f2d5741595dece34d1e6519a39d57a8fa4af6b8b12b11" + \ 41 | "?s=64&d=retro" 42 | expected_usernames = set(['jkaluza']) 43 | expected_objects = set([378]) 44 | msg = { 45 | "username": "amqp-bridge", 46 | "source_name": "datanommer", 47 | "i": 1, 48 | "timestamp": 1587619319.0, 49 | "msg_id": "2020-e857c141-3a16-411c-932c-bd16fc354e7a", 50 | "crypto": "x509", 51 | "topic": "org.fedoraproject.stg.odcs.compose.state-changed", 52 | "source_version": "0.9.0", 53 | "msg": { 54 | "compose": { 55 | "state_name": "generating", 56 | "sigkeys": "", 57 | "target_dir": "default", 58 | "results": [ 59 | "repository" 60 | ], 61 | "time_removed": None, 62 | "owner": "jkaluza", 63 | "toplevel_url": "https://odcs.stg.fedoraproject.org/composes/odcs-378", 64 | "id": 378, 65 | "state_reason": "Compose thread started", 66 | "multilib_method": 0, 67 | "multilib_arches": "", 68 | "modular_koji_tags": None, 69 | "lookaside_repos": "", 70 | "label": None, 71 | "source": "eln#eln", 72 | "state": 1, 73 | "compose_type": "test", 74 | "flags": [], 75 | "module_defaults_url": None, 76 | "koji_event": None, 77 | "source_type": 5, 78 | "koji_task_id": None, 79 | "packages": None, 80 | "time_started": "2020-04-23T05:21:58Z", 81 | "builds": None, 82 | "time_submitted": "2020-04-23T05:21:58Z", 83 | "arches": "x86_64", 84 | "time_to_expire": "2020-04-24T05:21:58Z", 85 | "pungi_compose_id": None, 86 | "time_done": None, 87 | "removed_by": None, 88 | }, 89 | "event": "state-changed" 90 | } 91 | } 92 | 93 | 94 | 95 | add_doc(locals()) 96 | 97 | if __name__ == '__main__': 98 | unittest.main() 99 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/conglomerators/pkgdb/acls.py: -------------------------------------------------------------------------------- 1 | import fedmsg.meta.base 2 | from fedmsg_meta_fedora_infrastructure.fasshim import avatar_url 3 | 4 | 5 | class AbstractPkgdbACLsConglomerator(fedmsg.meta.base.BaseConglomerator): 6 | def can_handle(self, msg, **config): 7 | return 'pkgdb.acl.update' in msg['topic'] 8 | 9 | def possessive(self, name): 10 | """ Given a name, return the possessive form. """ 11 | return self._("{name}'s").format(name=name) 12 | 13 | def merge(self, constituents, subject, **config): 14 | ms = constituents # shorthand 15 | agents = self.list_to_series([m['msg']['agent'] for m in ms]) 16 | usernames = self.list_to_series([ 17 | self.possessive(m['msg']['username']) for m in ms 18 | ]) 19 | acls = self.list_to_series([m['msg']['acl'] for m in ms]) 20 | packages = self.list_to_series([m['msg']['package_name'] for m in ms]) 21 | statuses = self.list_to_series([m['msg']['status'] for m in ms]) 22 | branches = self.list_to_series([ 23 | m['msg']['package_listing']['collection']['branchname'] 24 | for m in ms]) 25 | 26 | subtitle = '{agents} changed {usernames} {acls} permissions on ' + \ 27 | '{packages} ({branches}) to {statuses}.' 28 | 29 | tmpl = self.produce_template(constituents, subject, **config) 30 | tmpl['subtitle'] = subtitle.format( 31 | agents=agents, 32 | usernames=usernames, 33 | acls=acls, 34 | packages=packages, 35 | branches=branches, 36 | statuses=statuses, 37 | ) 38 | tmpl['subjective'] = tmpl['subtitle'] 39 | 40 | default = tmpl['icon'] 41 | 42 | # These are the only two keys that vary amongst our concrete children. 43 | tmpl['secondary_icon'] = self.get_secondary_icon(constituents, default) 44 | tmpl['link'] = self.get_link(constituents) 45 | 46 | return tmpl 47 | 48 | 49 | class BySubject(AbstractPkgdbACLsConglomerator): 50 | def matches(self, a, b, **config): 51 | """ The changes must all be **to** the same pkgdb user """ 52 | a, b = a['msg'], b['msg'] 53 | if a['username'] != b['username']: 54 | return False 55 | return True 56 | 57 | def get_secondary_icon(self, constituents, default): 58 | username = constituents[0]['msg']['username'] 59 | return avatar_url(username) 60 | 61 | def get_link(self, constituents): 62 | username = constituents[0]['msg']['username'] 63 | base = 'https://admin.fedoraproject.org/pkgdb/packager/%s/' 64 | return base % username 65 | 66 | 67 | class ByAgent(AbstractPkgdbACLsConglomerator): 68 | def matches(self, a, b, **config): 69 | """ The changes must all be **by** the same pkgdb user """ 70 | a, b = a['msg'], b['msg'] 71 | if a['agent'] != b['agent']: 72 | return False 73 | return True 74 | 75 | def get_secondary_icon(self, constituents, default): 76 | username = constituents[0]['msg']['agent'] 77 | return avatar_url(username) 78 | 79 | def get_link(self, constituents): 80 | username = constituents[0]['msg']['agent'] 81 | base = 'https://admin.fedoraproject.org/pkgdb/packager/%s/' 82 | return base % username 83 | 84 | 85 | class ByPackage(AbstractPkgdbACLsConglomerator): 86 | def matches(self, a, b, **config): 87 | """ The changes must all be **on** the same package """ 88 | a, b = a['msg'], b['msg'] 89 | if a['package_name'] != b['package_name']: 90 | return False 91 | return True 92 | 93 | def get_secondary_icon(self, constituents, default): 94 | return default 95 | 96 | def get_link(self, constituents): 97 | package = constituents[0]['msg']['package_name'] 98 | base = 'https://admin.fedoraproject.org/pkgdb/package/%s/' 99 | return base % package 100 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/tests/faf.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2015 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: Marek Brysa 19 | # 20 | """ Tests for FAF (ABRT server) messages """ 21 | 22 | import unittest 23 | 24 | from fedmsg.tests.test_meta import Base 25 | 26 | from .common import add_doc 27 | 28 | 29 | class TestFAFReport1(Base): 30 | """ `ABRT server `_ notifies about a crash report 31 | """ 32 | expected_title = "faf.report.threshold1" 33 | expected_subti = "ABRT report for package evolution has reached 7 occurrences" 34 | expected_packages = set(["evolution"]) 35 | expected_usernames = set() 36 | expected_objects = set() 37 | expected_link = "http://example.org/faf/reports/1234/" 38 | expected_secondary_icon = "https://apps.fedoraproject.org/packages/images/icons/evolution.png" 39 | expected_long_form = """Packages: evolution 40 | Function: main 41 | First occurrence: 2015-04-10 42 | Type: core 43 | Count: 7 44 | URL: http://example.org/faf/reports/1234/ 45 | """ 46 | msg = { 47 | u"username": u"faf", 48 | u"i": 1, 49 | u"timestamp": 1429777247, 50 | u"msg_id": u"2015-0284a675-995a-4942-bc59-2a5384e892b7", 51 | u"topic": u"org.fedoraproject.prod.faf.report.threshold1", 52 | u"msg": { 53 | u"count": 7, 54 | u"function": u"main", 55 | u"level": 1, 56 | u"url": u"http://example.org/faf/reports/1234/", 57 | u"components": [u"evolution"], 58 | u"type": u"core", 59 | u"first_occurrence": u"2015-04-10", 60 | u"report_id": 1234, 61 | u"problem_id": 4321 62 | } 63 | } 64 | 65 | 66 | class TestFAFProblem10(Base): 67 | """ `ABRT server `_ notifies about a problem 68 | """ 69 | expected_title = "faf.problem.threshold10" 70 | expected_subti = "ABRT problem for package evolution, thunderbird has reached 77 occurrences" 71 | expected_packages = set(["evolution", "thunderbird"]) 72 | expected_usernames = set() 73 | expected_objects = set() 74 | expected_link = "http://example.org/faf/problems/4321/" 75 | expected_secondary_icon = "https://apps.fedoraproject.org/packages/images/icons/evolution.png" 76 | expected_long_form = """Packages: evolution, thunderbird 77 | Function: main 78 | First occurrence: 2015-04-10 79 | Type: core 80 | Count: 77 81 | URL: http://example.org/faf/problems/4321/ 82 | """ 83 | msg = { 84 | u"username": u"faf", 85 | u"i": 1, 86 | u"timestamp": 1429777247, 87 | u"msg_id": u"2015-0284a675-995a-4942-bc59-2a5384e892b7", 88 | u"topic": u"org.fedoraproject.prod.faf.problem.threshold10", 89 | u"msg": { 90 | u"count": 77, 91 | u"function": u"main", 92 | u"level": 1, 93 | u"url": u"http://example.org/faf/problems/4321/", 94 | u"components": [u"evolution", u"thunderbird"], 95 | u"type": u"core", 96 | u"first_occurrence": u"2015-04-10", 97 | u"problem_id": 4321 98 | } 99 | } 100 | 101 | 102 | add_doc(locals()) 103 | 104 | if __name__ == '__main__': 105 | unittest.main() 106 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/nuancier.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2012, 2013 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: Ralph Bean 19 | # Luke Macken 20 | 21 | from fedmsg_meta_fedora_infrastructure.fasshim import avatar_url 22 | from fedmsg_meta_fedora_infrastructure import BaseProcessor 23 | 24 | 25 | class NuancierProcessor(BaseProcessor): 26 | __name__ = "nuancier" 27 | __description__ = "the supplemental wallpaper voting system" 28 | __link__ = "https://apps.fedoraproject.org/nuancier/" 29 | __icon__ = "https://apps.fedoraproject.org/img/icons/nuancier.png" 30 | __docs__ = "https://github.com/fedora-infra/nuancier-lite" 31 | __obj__ = "Wallpaper Elections" 32 | 33 | def link(self, msg, **config): 34 | 35 | if 'original_url' in msg['msg'].get('candidate', {}): 36 | return msg['msg']['candidate']['original_url'] 37 | 38 | kind = msg['topic'].split('.')[4] 39 | item = msg['msg']['election']['id'] 40 | return "https://apps.fedoraproject.org/nuancier/%s/%s" % (kind, item) 41 | 42 | def subtitle(self, msg, **config): 43 | kwargs = dict( 44 | agent=msg['msg']['agent'], 45 | name=msg['msg']['election']['name'], 46 | ) 47 | if 'election.update' in msg['topic']: 48 | tmpl = self._( 49 | '{agent} changed the following details ' 50 | 'on the "{name}" election: {details}') 51 | kwargs['details'] = ', '.join(msg['msg']['updated']) 52 | elif 'election.new' in msg['topic']: 53 | tmpl = self._( 54 | '{agent} created a new election "{name}"') 55 | elif 'candidate.new' in msg['topic']: 56 | tmpl = self._( 57 | '{agent} uploaded a new candidate for the ' 58 | '"{name}" wallpaper election') 59 | elif 'candidate.denied' in msg['topic']: 60 | tmpl = self._( 61 | '{agent} denied {author}\'s "{candidate}" submission to the ' 62 | '"{name}" wallpaper election') 63 | kwargs['author'] = msg['msg']['candidate']['submitter'] 64 | kwargs['candidate'] = msg['msg']['candidate']['name'] 65 | elif 'candidate.approved' in msg['topic']: 66 | tmpl = self._( 67 | '{agent} approved {author}\'s "{candidate}" submission to the ' 68 | '"{name}" wallpaper election') 69 | kwargs['author'] = msg['msg']['candidate']['submitter'] 70 | kwargs['candidate'] = msg['msg']['candidate']['name'] 71 | else: 72 | tmpl = '' 73 | 74 | return tmpl.format(**kwargs) 75 | 76 | def secondary_icon(self, msg, **config): 77 | return avatar_url(msg['msg']['agent']) 78 | 79 | def usernames(self, msg, **config): 80 | users = [msg['msg']['agent']] 81 | 82 | if 'candidate' in msg['msg']: 83 | users.append(msg['msg']['candidate']['submitter']) 84 | 85 | return set(users) 86 | 87 | def objects(self, msg, **config): 88 | kind = msg['topic'].split('.')[-2] 89 | action = msg['topic'].split('.')[-1] 90 | year = msg['msg']['election']['year'] 91 | name = msg['msg']['election']['name'] 92 | candidate = msg['msg'].get('candidate', {}).get('name') 93 | tokens = [year, name, kind, action] 94 | if candidate: 95 | tokens.insert(2, candidate) 96 | return set(['/'.join(map(str, tokens))]) 97 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/elections.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2014 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: Pierre-Yves Chibon 19 | # Ralph Bean 20 | 21 | from fedmsg_meta_fedora_infrastructure.fasshim import avatar_url 22 | from fedmsg_meta_fedora_infrastructure import BaseProcessor 23 | 24 | 25 | class ElectionsProcessor(BaseProcessor): 26 | __name__ = "fedora_elections" 27 | __description__ = "the fedora voting system" 28 | __link__ = "https://admin.fedoraproject.org/voting/" 29 | __docs__ = "https://github.com/fedora-infra/elections" 30 | __obj__ = "Fedora Elections" 31 | 32 | def link(self, msg, **config): 33 | msg = msg['msg'] 34 | if 'election' in msg: 35 | msg = msg['election'] 36 | name = msg['alias'] 37 | return "https://admin.fedoraproject.org/voting/about/%s" % (name) 38 | 39 | def subtitle(self, msg, **config): 40 | if 'election' in msg['msg']: 41 | name = msg['msg']['election']['alias'] # Old style 42 | else: 43 | name = msg['msg']['alias'] # New style 44 | 45 | if 'agent' in msg['msg']: 46 | agent = msg['msg']['agent'] # Old style 47 | else: 48 | agent = msg['msg']['fas_user'] # New style 49 | 50 | kwargs = dict(name=name, agent=agent) 51 | 52 | if 'election.new' in msg['topic']: 53 | tmpl = self._( 54 | '{agent} created election "{name}"') 55 | elif 'election.edit' in msg['topic']: 56 | tmpl = self._( 57 | '{agent} edited election "{name}"') 58 | elif 'candidate.new' in msg['topic']: 59 | tmpl = self._( 60 | '{agent} added candidate "{cand_name}" to ' 61 | 'election "{name}"') 62 | kwargs['cand_name'] = msg['msg']['candidate']['name'] 63 | elif 'candidate.edit' in msg['topic']: 64 | tmpl = self._( 65 | '{agent} edited candidate "{cand_name}" of ' 66 | 'election "{name}"') 67 | kwargs['cand_name'] = msg['msg']['candidate']['name'] 68 | elif 'candidate.delete' in msg['topic']: 69 | tmpl = self._( 70 | '{agent} deleted candidate "{cand_name}" of ' 71 | 'election "{name}"') 72 | kwargs['cand_name'] = msg['msg']['candidate']['name'] 73 | else: 74 | tmpl = '' 75 | 76 | return tmpl.format(**kwargs) 77 | 78 | def secondary_icon(self, msg, **config): 79 | if 'agent' in msg['msg']: 80 | agent = msg['msg']['agent'] # Old style 81 | else: 82 | agent = msg['msg']['fas_user'] # New style 83 | return avatar_url(agent) 84 | 85 | def usernames(self, msg, **config): 86 | try: 87 | if 'agent' in msg['msg']: 88 | agent = msg['msg']['agent'] # Old style 89 | else: 90 | agent = msg['msg']['fas_user'] # New style 91 | return set([agent]) 92 | except KeyError: 93 | return set() 94 | 95 | def objects(self, msg, **config): 96 | kind = msg['topic'].split('.')[-2] 97 | action = msg['topic'].split('.')[-1] 98 | 99 | if 'election' in msg['msg']: 100 | name = msg['msg']['election']['alias'] # Old style 101 | else: 102 | name = msg['msg']['alias'] # New style 103 | 104 | tokens = [name, kind, action] 105 | return set(['/'.join(map(str, tokens))]) 106 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/fedimg.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2014 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: David Gay 19 | # 20 | """ Tests for planet messages """ 21 | 22 | import unittest 23 | 24 | from fedmsg.tests.test_meta import Base 25 | 26 | from .common import add_doc 27 | 28 | 29 | class TestPlanetNewPost(Base): 30 | """ The `Fedora Planet `_ publishes 31 | messages of this topic whenever a new blog post is found. Cool! 32 | """ 33 | 34 | expected_title = "planet.post.new" 35 | expected_subti = 'ralph posted "Test Post 6"' 36 | expected_long_form = 'Test Post 6' 37 | expected_link = "http://threebean.org/blog/test-post-6" 38 | expected_icon = 'https://apps.fedoraproject.org/img/icons/planet_logo.png' 39 | expected_secondary_icon = ("https://secure.gravatar.com/avatar/" 40 | "ba940b433c2695635d32d2c4aec00540?s=140") 41 | expected_packages = set([]) 42 | expected_usernames = set(['ralph']) 43 | expected_objects = set(['threebean.org/blog/test-post-6']) 44 | msg = { 45 | "username": "planet-user", 46 | "i": 1, 47 | "timestamp": 1359579067.6178019, 48 | "topic": "org.fedoraproject.prod.planet.post.new", 49 | "msg": { 50 | "username": "ralph", 51 | "post": { 52 | "summary_detail": { 53 | "base": "http://threebean.org/blog/category/" 54 | "fedora/feed/index.xml", 55 | "type": "text/html", 56 | "value": "Test Post 6", 57 | "language": None 58 | }, 59 | "updated_parsed": 1359576000.0, 60 | "links": [ 61 | { 62 | "href": "http://threebean.org/blog/test-post-6", 63 | "type": "text/html", 64 | "rel": "alternate" 65 | } 66 | ], 67 | "tags": [ 68 | { 69 | "term": "fedora", 70 | "scheme": None, 71 | "label": None 72 | } 73 | ], 74 | "title": "Test Post 6", 75 | "updated": "Wed, 30 Jan 2013 15:00:00 EST", 76 | "summary": "Test Post 6", 77 | "content": [ 78 | { 79 | "base": "http://threebean.org/blog/category/" 80 | "fedora/feed/index.xml", 81 | "type": "text/html", 82 | "value": "
\n

Another " 83 | "test post for fedmsg+fedoraplanet.

\n
", 84 | "language": None 85 | } 86 | ], 87 | "guidislink": False, 88 | "title_detail": { 89 | "base": "http://threebean.org/blog/category/" 90 | "fedora/feed/index.xml", 91 | "type": "text/html", 92 | "value": "Test Post 6", 93 | "language": None 94 | }, 95 | "link": "http://threebean.org/blog/test-post-6", 96 | "id": "http://threebean.org/blog/test-post-6" 97 | }, 98 | "name": "Ralph Bean", 99 | "face": "https://secure.gravatar.com/avatar/" 100 | "ba940b433c2695635d32d2c4aec00540?s=140" 101 | } 102 | } 103 | 104 | 105 | add_doc(locals()) 106 | 107 | if __name__ == '__main__': 108 | unittest.main() 109 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/compose2.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2015 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: Ralph Bean 19 | # 20 | from fedmsg_meta_fedora_infrastructure import BaseProcessor 21 | 22 | 23 | class PungiKojiProcessor(BaseProcessor): 24 | __name__ = "pungi" 25 | __description__ = "Fedora Release Engineering" 26 | __link__ = "https://pagure.io/releng" 27 | __docs__ = "https://pagure.io/docs/releng" 28 | __icon__ = "https://apps.fedoraproject.org/img/icons/pungi.png" 29 | __obj__ = "Composes" 30 | 31 | def subtitle(self, msg, **config): 32 | compose = msg['msg'].get('compose_id') 33 | if msg['topic'].endswith('pungi.compose.status.change'): 34 | statuses = { 35 | 'STARTED': self._('started'), 36 | 'FINISHED': self._('just finished'), 37 | 'DOOMED': self._('failed in a horrible fire'), 38 | 'TERMINATED': self._('was terminated'), 39 | } 40 | status = statuses.get(msg['msg']['status'], msg['msg']['status']) 41 | tmpl = self._("pungi-koji compose of {compose} {status}") 42 | return tmpl.format(compose=compose, status=status) 43 | elif msg['topic'].endswith('pungi.compose.phase.start'): 44 | phase = msg['msg']['phase_name'] 45 | tmpl = self._("pungi-koji started the {phase} phase " 46 | "of the {compose} compose") 47 | return tmpl.format(compose=compose, phase=phase) 48 | elif msg['topic'].endswith('pungi.compose.phase.stop'): 49 | phase = msg['msg']['phase_name'] 50 | tmpl = self._("pungi-koji finished the {phase} phase " 51 | "of the {compose} compose") 52 | return tmpl.format(compose=compose, phase=phase) 53 | elif msg['topic'].endswith('pungi.compose.createiso.imagedone'): 54 | image = msg['msg']['file'].split('compose/')[-1] 55 | tmpl = self._("pungi-koji finished createiso for {image}") 56 | return tmpl.format(image=image) 57 | elif msg['topic'].endswith('pungi.compose.createiso.imagefail'): 58 | image = msg['msg']['file'].split('compose/')[-1] 59 | tmpl = self._("pungi-koji createiso for {image} failed!") 60 | return tmpl.format(image=image) 61 | elif msg['topic'].endswith('pungi.compose.createiso.targets'): 62 | N = len(msg['msg']['deliverables']) 63 | tmpl = self._("pungi-koji assigned {N} createiso targets") 64 | return tmpl.format(N=N) 65 | elif msg['topic'].endswith('pungi.compose.ostree'): 66 | ref = msg['msg']['ref'] 67 | arch = msg['msg']['arch'] 68 | commitid = msg['msg']['commitid'] 69 | tmpl = self._('pungi-koji ostree compose {compose} produced ' 70 | 'ostree commit {commitid} for {arch} {ref}') 71 | return tmpl.format(compose=compose, arch=arch, commitid=commitid, 72 | ref=ref) 73 | elif msg['topic'].endswith('pungi.compose.fail.to.start'): 74 | config = msg['msg'].get('config') 75 | detail = msg['msg'].get('detail') 76 | tmpl = self._('failed to compose from {config}: "{detail}"') 77 | return tmpl.format(config=config, detail=detail) 78 | 79 | def link(self, msg, **config): 80 | if 'location' in msg['msg']: 81 | return msg['msg']['location'].strip('/').strip('/compose') 82 | 83 | def objects(self, msg, **config): 84 | if 'deliverables' in msg['msg']: 85 | return set([d.strip('/') for d in msg['msg']['deliverables']]) 86 | elif 'file' in msg['msg']: 87 | return set([msg['msg']['file'].strip('/')]) 88 | elif 'compose_id' in msg['msg']: 89 | compose = msg['msg']['compose_id'] 90 | return set(["rawhide/" + "/".join(compose.split('.'))]) 91 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/tests/taskotron.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2015 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: Martin Krizek 19 | # Ralph Bean 20 | # 21 | """ Tests for taskotron messages """ 22 | 23 | import os 24 | import unittest 25 | 26 | from fedmsg.tests.test_meta import Base 27 | 28 | from .common import add_doc 29 | 30 | 31 | class TestTaskotronResultNew(Base): 32 | """ Taskotron emits messages on this topic anytime a task finishes. 33 | 34 | Here's an example message of a new **taskotron result** published about a 35 | **koji build**. 36 | """ 37 | expected_title = "taskotron.result.new" 38 | expected_subti = "fedoratest PASSED for foobar-1.0-1.fc99" 39 | expected_link = ("https://taskotron.fedoraproject.org/taskmaster/" 40 | "/builders/x86_64/builds/1/steps/runtask/logs/stdio") 41 | expected_secondary_icon = ("https://apps.fedoraproject.org/packages/" 42 | "images/icons/foobar.png") 43 | expected_packages = set(['foobar']) 44 | expected_objects = set(['fedoratest/foobar/PASSED']) 45 | msg = { 46 | u'username': u'taskotron', 47 | u'i': 1, 48 | u'timestamp': 1389298195, 49 | u'msg_id': u'2014-10b5b1b6-42c7-4d64-aeae-5029b9515d47', 50 | u'topic': u'org.fedoraproject.stg.taskotron.result.new', 51 | u'msg': { 52 | u'task': { 53 | 'name': 'fedoratest', 54 | 'type': 'koji_build', 55 | 'item': 'foobar-1.0-1.fc99', 56 | }, 57 | u'result': { 58 | 'id': '1', 59 | 'submit_time': '2015-01-30 13:11:35.366862', 60 | 'outcome': 'PASSED', 61 | 'job_url': 'https://taskotron.fedoraproject.org/resultsdb/jobs/1', 62 | 'log_url': ('https://taskotron.fedoraproject.org/taskmaster/' 63 | '/builders/x86_64/builds/1/steps/runtask/logs/stdio'), 64 | }, 65 | } 66 | } 67 | 68 | 69 | class TestTaskotronBodhiUpdate(Base): 70 | """ Taskotron emits messages on this topic anytime a task finishes. 71 | 72 | Here's an example message of a new **taskotron result** published about a 73 | **bodhi update**. 74 | """ 75 | expected_title = "taskotron.result.new" 76 | expected_subti = "upgradepath PASSED for FEDORA-2015-2f6c7508b7" 77 | expected_link = ("https://taskotron.fedoraproject.org/artifacts/" 78 | "all/64981220-a418-11e5-91ee-52540053ee00/" 79 | "task_output/FEDORA-2015-2f6c7508b7.log") 80 | msg = { 81 | "i": 177, 82 | "timestamp": 1450286061.0, 83 | "msg_id": "2015-2ff9d8af-8263-4886-8e3d-61cc7a5eeeb4", 84 | "topic": "org.fedoraproject.prod.taskotron.result.new", 85 | "msg": { 86 | "task": { 87 | "item": "FEDORA-2015-2f6c7508b7", 88 | "type": "bodhi_update", 89 | "name": "upgradepath" 90 | }, 91 | "result": { 92 | "job_url": ("https://taskotron.fedoraproject.org/execdb/" 93 | "/jobs/64981220-a418-11e5-91ee-52540053ee00"), 94 | "submit_time": "2015-12-16 17:14:21 UTC", 95 | "outcome": "PASSED", 96 | "id": 5202575, 97 | "log_url": ("https://taskotron.fedoraproject.org/artifacts/" 98 | "all/64981220-a418-11e5-91ee-52540053ee00/" 99 | "task_output/FEDORA-2015-2f6c7508b7.log"), 100 | } 101 | } 102 | } 103 | 104 | 105 | # only run these two tests if we have network connectivity. 106 | # (they'll fail in koji) 107 | if not 'FEDMSG_META_NO_NETWORK' in os.environ: 108 | TestTaskotronBodhiUpdate.expected_secondary_icon = ( 109 | "https://apps.fedoraproject.org/packages/" 110 | "images/icons/copy-jdk-configs.png") 111 | TestTaskotronBodhiUpdate.expected_packages = set(['copy-jdk-configs']) 112 | TestTaskotronBodhiUpdate.expected_objects = set([ 113 | 'upgradepath/copy-jdk-configs/PASSED']) 114 | 115 | 116 | add_doc(locals()) 117 | 118 | if __name__ == '__main__': 119 | unittest.main() 120 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/mdapi.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2015 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: Pierre-Yves Chibon 19 | # Ralph Bean 20 | # 21 | 22 | from fedmsg_meta_fedora_infrastructure import BaseProcessor 23 | 24 | import fedmsg.meta.base 25 | 26 | 27 | def get_packages(message): 28 | ''' Returns the list of all the packages mentionned in the message. ''' 29 | if 'differences' in message['msg']: 30 | return _get_packages_oldschool(message) 31 | else: 32 | return _get_packages_newschool(message) 33 | 34 | def _get_packages_oldschool(message): 35 | pkgs = set() 36 | for category in message['msg']['differences']: 37 | for action in message['msg']['differences'][category]: 38 | for details in message['msg']['differences'][category][action]: 39 | if '/' in details[0]: 40 | name = details[-1] 41 | else: 42 | name = details[0] 43 | name = name.split('(')[0] 44 | pkgs.add(name) 45 | return pkgs 46 | 47 | 48 | def _get_packages_newschool(message): 49 | return message['msg']['packages'] 50 | 51 | 52 | def get_objects(message): 53 | if 'differences' in message['msg']: 54 | return _get_objects_oldschool(message) 55 | else: 56 | return _get_objects_newschool(message) 57 | 58 | def _get_objects_oldschool(message): 59 | repo = message['msg']['name'] 60 | for category in message['msg']['differences']: 61 | for action in message['msg']['differences'][category]: 62 | for details in message['msg']['differences'][category][action]: 63 | if '/' in details[0]: 64 | name = details[-1] 65 | else: 66 | name = details[0] 67 | yield '%s/%s/%s/%s' % (repo, category, action, name) 68 | 69 | 70 | def _get_objects_newschool(message): 71 | repo = message['msg']['name'] 72 | for name in message['msg']['packages']: 73 | yield '%s/%s' % (repo, name) 74 | 75 | 76 | def get_summary(message): 77 | ''' Returns a summary of the addition/deletion for each category in 78 | the specified message. 79 | ''' 80 | if 'differences' in message['msg']: 81 | return ', '.join(_get_summary_oldschool(message)) 82 | else: 83 | return _get_summary_newschool(message) 84 | 85 | def _get_summary_oldschool(message): 86 | summary = list() 87 | for category in sorted(message['msg']['differences']): 88 | count_a = len(message['msg']['differences'][category]['added']) 89 | count_b = len(message['msg']['differences'][category]['removed']) 90 | if not count_a and not count_b: 91 | continue 92 | summary.append('{0}: +{1}/-{2}'.format(category, count_a, count_b)) 93 | return summary 94 | 95 | def _get_summary_newschool(message): 96 | packages = message['msg']['packages'] 97 | return fedmsg.meta.base.BaseConglomerator.list_to_series(packages) 98 | 99 | class MdapiProcessor(BaseProcessor): 100 | __name__ = "mdapi" 101 | __description__ = "the Fedora repository meta-data API" 102 | __link__ = "https://apps.fedoraproject.org/mdapi" 103 | __docs__ = "https://apps.fedoraproject.org/mdapi" 104 | __obj__ = "Medata API update" 105 | __icon__ = ("https://apps.fedoraproject.org/packages/" 106 | "images/icons/package_128x128.png") 107 | 108 | def subtitle(self, msg, **config): 109 | if 'mdapi.repo.update' in msg['topic']: 110 | tmpl = self._( 111 | u"mdapi noticed a {repo} repomd change: {summary}" 112 | ) 113 | repo = msg['msg']['name'] 114 | summary = get_summary(msg) 115 | return tmpl.format(repo=repo, summary=summary) 116 | else: 117 | raise NotImplementedError("%r" % msg) 118 | 119 | def secondary_icon(self, msg, **config): 120 | return self.__icon__ 121 | 122 | def link(self, msg, **config): 123 | url = msg['msg']['url'] 124 | if url.startswith('http'): 125 | return url 126 | else: 127 | return 'https://download.fedoraproject.org/pub/' + url 128 | 129 | def objects(self, msg, **config): 130 | return set(get_objects(msg)) 131 | 132 | def packages(self, msg, **config): 133 | return set(get_packages(msg)) 134 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/mailman3.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2012 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: Ralph Bean 19 | # 20 | from fedmsg_meta_fedora_infrastructure import BaseProcessor 21 | from fedmsg_meta_fedora_infrastructure.fasshim import \ 22 | avatar_url_from_email, avatar_url_from_openid, email2fas 23 | 24 | from fedmsg_meta_fedora_infrastructure.conglomerators.mailman import \ 25 | mailman as mailman_conglomerator 26 | 27 | import email.utils 28 | import warnings 29 | 30 | import fedmsg.config 31 | config = fedmsg.config.load_config() 32 | 33 | 34 | def _full_email_to_email(full_from): 35 | return email.utils.parseaddr(full_from)[1] 36 | 37 | 38 | def _email_to_username(email): 39 | return email2fas(email, **config) 40 | 41 | 42 | class MailmanProcessor(BaseProcessor): 43 | __name__ = "Mailman" 44 | __description__ = "mailing list messages" 45 | __link__ = "https://lists.fedoraproject.org" 46 | __docs__ = ("https://fedoraproject.org/wiki/" 47 | "Communicating_and_getting_help#Mailing_Lists") 48 | __obj__ = "Mailing List Messages" 49 | __icon__ = "https://apps.fedoraproject.org/img/icons/hyperkitty.png" 50 | 51 | conglomerators = [ 52 | mailman_conglomerator.ByMessageId, 53 | ] 54 | 55 | def subtitle(self, msg, **config): 56 | if 'receive' in msg['topic']: 57 | lst = msg['msg']['mlist']['list_name'] 58 | subject = msg['msg']['msg']['subject'].replace('\n', ' ') 59 | 60 | full_from = msg['msg']['msg']['from'] 61 | user = _email_to_username(_full_email_to_email(full_from)) 62 | if not user: 63 | user = "someone" 64 | 65 | d = msg['msg']['msg'] 66 | if d['references'] or d['in-reply-to']: 67 | tmpl = self._( 68 | "On the {lst} list, {user} replied to '{subject}'") 69 | else: 70 | tmpl = self._("{user} wrote '{subject}' to the {lst} list") 71 | 72 | return tmpl.format(lst=lst, user=user, subject=subject) 73 | else: 74 | warnings.warn("mailman3 message *must* have 'receive' in topic") 75 | 76 | def secondary_icon(self, msg, **config): 77 | full_from = msg['msg']['msg']['from'] 78 | email = _full_email_to_email(full_from) 79 | 80 | # Can we find this person in FAS? 81 | username = email2fas(email, **config) 82 | 83 | if '@' in username: 84 | # No? Then use their email for libravatar 85 | return avatar_url_from_email(email) 86 | else: 87 | # Yes? Then use their openid like everywhere else. 88 | return avatar_url_from_openid(username) 89 | 90 | def link(self, msg, **config): 91 | base_url = 'https://lists.fedoraproject.org/archives' 92 | archived_at = msg['msg']['msg']['archived-at'] 93 | if archived_at and archived_at.startswith('<'): 94 | archived_at = archived_at[1:] 95 | if archived_at and archived_at.endswith('>'): 96 | archived_at = archived_at[:-1] 97 | if archived_at and archived_at.startswith('http'): 98 | return archived_at 99 | elif archived_at: 100 | return base_url + archived_at 101 | else: 102 | return None 103 | 104 | def usernames(self, msg, **config): 105 | full_from = msg['msg']['msg']['from'] 106 | user = _email_to_username(_full_email_to_email(full_from)) 107 | if user and '@' not in user: 108 | return set([user]) 109 | else: 110 | return set() 111 | 112 | def objects(self, msg, **config): 113 | 114 | # Build a repr of all the messages in this thread 115 | references = msg['msg']['msg']['references'] 116 | 117 | # Fall back to this header if there's nothing in the first. 118 | if not references: 119 | references = msg['msg']['msg']['in-reply-to'] 120 | 121 | references = references and references.split() or [] 122 | references = [r[1:-1] for r in references] 123 | message_id = msg['msg']['msg']['message-id'][1:-1] 124 | 125 | if references: 126 | tokens = ['/'.join(references), message_id, 'message'] 127 | else: 128 | tokens = [message_id, 'message'] 129 | 130 | lst = msg['msg']['mlist']['list_name'] 131 | tokens = [lst] + tokens 132 | 133 | return set(['/'.join(tokens)]) 134 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/conglomerators/pagure/pagure.py: -------------------------------------------------------------------------------- 1 | import fedmsg.meta.base 2 | from fedmsg_meta_fedora_infrastructure.fasshim import avatar_url, email2fas 3 | 4 | 5 | class AbstractPagureTicketConglomerator(fedmsg.meta.base.BaseConglomerator): 6 | 7 | def can_handle(self, msg, **config): 8 | target = 'pagure.{entity_name}.'.format(entity_name=self.entity_name) 9 | return target in msg['topic'] 10 | 11 | def merge(self, constituents, subject, **config): 12 | ms = constituents # shorthand 13 | 14 | count = len(ms) 15 | agents = set([m['msg']['agent'] for m in ms]) 16 | idx = ms[0]['msg'][self.entity_key]['id'] 17 | repo = self.get_repo(ms[0]) 18 | subtitle = '{agents} interacted with {entity_name} #{idx} of project "{repo}" {count} times' 19 | 20 | agents = self.list_to_series(agents) 21 | 22 | tmpl = self.produce_template(constituents, subject, **config) 23 | tmpl['subtitle'] = subtitle.format( 24 | agents=agents, 25 | entity_name=self.entity_name, 26 | repo=repo, 27 | idx=idx, 28 | count=count, 29 | ) 30 | tmpl['subjective'] = tmpl['subtitle'] 31 | 32 | tmpl['secondary_icon'] = avatar_url(ms[0]['msg']['agent']) 33 | link_template = 'https://pagure.io/{repo}/{entity_name}/{idx}' 34 | tmpl['link'] = link_template.format( 35 | repo=repo, 36 | entity_name=self.entity_name, 37 | idx=idx, 38 | ) 39 | 40 | return tmpl 41 | 42 | 43 | class ByPR(AbstractPagureTicketConglomerator): 44 | entity_key = 'pullrequest' 45 | entity_name = 'pull-request' 46 | 47 | def matches(self, a, b, **config): 48 | a, b = a['msg'][self.entity_key], b['msg'][self.entity_key] 49 | return ( 50 | a['id'] == b['id'] 51 | and a['project']['name'] == b['project']['name'] 52 | ) 53 | 54 | def get_repo(self, msg): 55 | return msg['msg']['pullrequest']['project']['name'] 56 | 57 | 58 | class ByIssue(AbstractPagureTicketConglomerator): 59 | entity_key = 'issue' 60 | entity_name = 'issue' 61 | 62 | def matches(self, a, b, **config): 63 | a, b = a['msg'], b['msg'] 64 | return ( 65 | a[self.entity_key]['id'] == b[self.entity_key]['id'] 66 | and a['project']['name'] == b['project']['name'] 67 | ) 68 | 69 | def get_repo(self, msg): 70 | return msg['msg']['project']['name'] 71 | 72 | 73 | class ByNewStyleCommit(fedmsg.meta.base.BaseConglomerator): 74 | def can_handle(self, msg, **config): 75 | return '.pagure.git.receive' in msg['topic'] and 'commit' not in msg['msg'] 76 | 77 | def matches(self, a, b, **config): 78 | a, b = a['msg'], b['msg'] 79 | return a['repo']['name'] == b['repo']['name'] 80 | 81 | def merge(self, constituents, subject, **config): 82 | ms = constituents # shorthand 83 | 84 | count = sum([m['msg']['total_commits'] for m in ms]) 85 | agents = set([m['msg']['agent'] for m in ms]) 86 | branches = [m['msg']['branch'].replace('refs/heads/', '') for m in ms] 87 | repo = ms[0]['msg']['repo']['name'] 88 | subtitle = '{agents} pushed {count} commits to {repo} ({branches})' 89 | agents = self.list_to_series(agents) 90 | branches = self.list_to_series(branches) 91 | 92 | tmpl = self.produce_template(constituents, subject, **config) 93 | tmpl['subtitle'] = subtitle.format( 94 | agents=agents, 95 | repo=repo, 96 | count=count, 97 | branches=branches, 98 | ) 99 | tmpl['subjective'] = tmpl['subtitle'] 100 | 101 | tmpl['secondary_icon'] = avatar_url(ms[0]['msg']['agent']) 102 | link_template = 'https://pagure.io/{repo}/commits' 103 | tmpl['link'] = link_template.format(repo=repo) 104 | 105 | return tmpl 106 | 107 | 108 | class ByOldStyleCommit(fedmsg.meta.base.BaseConglomerator): 109 | def can_handle(self, msg, **config): 110 | return '.pagure.git.receive' in msg['topic'] and 'commit' in msg['msg'] 111 | 112 | def matches(self, a, b, **config): 113 | a, b = a['msg'], b['msg'] 114 | return a['commit']['path'] == b['commit']['path'] 115 | 116 | def merge(self, constituents, subject, **config): 117 | ms = constituents # shorthand 118 | 119 | count = len(ms) 120 | agents = set([ 121 | email2fas(m['msg']['commit']['email'], **config) for m in ms 122 | ]) 123 | repo = ms[0]['msg']['commit']['repo']['name'] 124 | subtitle = '{agents} pushed {count} commits to the {repo} project' 125 | agents = self.list_to_series(agents) 126 | 127 | tmpl = self.produce_template(constituents, subject, **config) 128 | tmpl['subtitle'] = subtitle.format( 129 | agents=agents, 130 | repo=repo, 131 | count=count, 132 | ) 133 | tmpl['subjective'] = tmpl['subtitle'] 134 | 135 | tmpl['secondary_icon'] = avatar_url(list(agents)[0]) 136 | link_template = 'https://pagure.io/{repo}/commits' 137 | tmpl['link'] = link_template.format(repo=repo) 138 | 139 | return tmpl 140 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/tests/conglomerate/pkgdb/test_acls.py: -------------------------------------------------------------------------------- 1 | import fedmsg.tests.test_meta 2 | import arrow 3 | 4 | class TestPkgdbConglomerateCommentSubject( 5 | fedmsg.tests.test_meta.ConglomerateBase): 6 | originals = [{ 7 | "source_name": "datanommer", 8 | "i": 25, 9 | "timestamp": 1416428310.0, 10 | "msg_id": "2014-9e46f5ce-4881-4497-aec4-89cf83332b2d", 11 | "topic": "org.fedoraproject.prod.pkgdb.acl.update", 12 | "source_version": "0.6.4", 13 | "msg": { 14 | "status": "Approved", 15 | "username": "mcepl", 16 | "package_listing": { 17 | "status": "Approved", 18 | "point_of_contact": "mcepl", 19 | "package": { 20 | "status": "Approved", 21 | "upstream_url": "https://cryptography.io/", 22 | "description": "", 23 | "creation_date": 1416428295.0, 24 | "acls": [], 25 | "summary": "PyCA's cryptography library", 26 | "review_url": "https://bugzilla.redhat.com/1114267", 27 | "name": "python-cryptography" 28 | }, 29 | "collection": { 30 | "status": "Under Development", 31 | "dist_tag": ".fc22", 32 | "koji_name": "rawhide", 33 | "name": "Fedora", 34 | "version": "devel", 35 | "branchname": "master" 36 | }, 37 | "critpath": False, 38 | "status_change": 1416428298.0 39 | }, 40 | "package_name": "python-cryptography", 41 | "agent": "limb", 42 | "previous_status": "", 43 | "acl": "approveacls" 44 | } 45 | }, 46 | { 47 | "source_name": "datanommer", 48 | "i": 20, 49 | "timestamp": 1416428307.0, 50 | "msg_id": "2014-06ef29dd-adb5-47d8-92aa-f1ead0c4d8f1", 51 | "topic": "org.fedoraproject.prod.pkgdb.acl.update", 52 | "source_version": "0.6.4", 53 | "msg": { 54 | "status": "Approved", 55 | "username": "mcepl", 56 | "package_listing": { 57 | "status": "Approved", 58 | "point_of_contact": "mcepl", 59 | "package": { 60 | "status": "Approved", 61 | "upstream_url": "https://cryptography.io/", 62 | "description": "", 63 | "creation_date": 1416428295.0, 64 | "acls": [], 65 | "summary": "PyCA's cryptography library", 66 | "review_url": "https://bugzilla.redhat.com/1114267", 67 | "name": "python-cryptography" 68 | }, 69 | "collection": { 70 | "status": "Under Development", 71 | "dist_tag": ".el7", 72 | "koji_name": "epel7", 73 | "name": "Fedora EPEL", 74 | "version": "7", 75 | "branchname": "epel7" 76 | }, 77 | "acls": [ { 78 | "fas_name": "mcepl", 79 | "status": "Approved", 80 | "acl": "commit" 81 | }, { 82 | "fas_name": "mcepl", 83 | "status": "Approved", 84 | "acl": "watchbugzilla" 85 | }, { 86 | "fas_name": "mcepl", 87 | "status": "Approved", 88 | "acl": "watchcommits" 89 | } ], 90 | "critpath": False, 91 | "status_change": 1416428298.0 92 | }, 93 | "package_name": "python-cryptography", 94 | "agent": "limb", 95 | "previous_status": "", 96 | "acl": "watchcommits" 97 | } 98 | }, 99 | ] 100 | expected = [{ 101 | 'subtitle': 'limb changed mcepl\'s approveacls and watchcommits ' 102 | 'permissions on python-cryptography (epel7 and master) ' 103 | 'to Approved.', 104 | 'subjective': 'limb changed mcepl\'s approveacls and watchcommits ' 105 | 'permissions on python-cryptography (epel7 and master) ' 106 | 'to Approved.', 107 | 'link': 'https://admin.fedoraproject.org/pkgdb/packager/mcepl/', 108 | 109 | 'icon': 'https://apps.fedoraproject.org/packages/images/' 110 | 'icons/package_128x128.png', 111 | 'secondary_icon': 'https://seccdn.libravatar.org/avatar/' 112 | 'f0496e0b40a4e1e780cb09ee8a89870aa0f90643fa36b095a9057be4c61ec3b6' 113 | '?s=64&d=retro', 114 | 115 | 'start_time': 1416428307.0, 116 | 'end_time': 1416428310.0, 117 | 'timestamp': 1416428308.5, 118 | 119 | 'human_time': arrow.get(1416428308.5).humanize(), 120 | 121 | 'usernames': set(['mcepl', 'limb']), 122 | 'packages': set(['python-cryptography']), 123 | 'topics': set(['org.fedoraproject.prod.pkgdb.acl.update']), 124 | 'categories': set(['pkgdb']), 125 | 'msg_ids': [ 126 | '2014-9e46f5ce-4881-4497-aec4-89cf83332b2d', 127 | '2014-06ef29dd-adb5-47d8-92aa-f1ead0c4d8f1', 128 | ], 129 | }] 130 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/tests/pdc.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2016 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: Ralph Bean 19 | # 20 | """ Tests for PDC messages. """ 21 | 22 | import unittest 23 | 24 | from fedmsg_meta_fedora_infrastructure.tests.base import Base 25 | 26 | from fedmsg_meta_fedora_infrastructure.tests.common import add_doc 27 | 28 | 29 | class TestPDCComposeImport(Base): 30 | """ The `Product Definition Center `_ 31 | publishes messages on this topic whenever a new compose entry is created. 32 | This message comes early, when *we first begin to import the compose*. 33 | There are other messages that come after, when the images and rpms for the 34 | compose finish being imported. 35 | """ 36 | expected_title = "pdc.compose" 37 | expected_subti = ("An entry for the Fedora-Rawhide-20160331.n.0 nightly " 38 | "compose was created in the Product Definition Center") 39 | expected_link = ("https://pdc.fedoraproject.org/rest_api/v1/" 40 | "composes/Fedora-Rawhide-20160331.n.0/") 41 | expected_objects = set(['Fedora-Rawhide-20160331.n.0/create/compose']) 42 | msg = { 43 | "timestamp": 1459420734.0, 44 | "msg_id": "2016-e9ec264b-ce44-4260-8641-e385e71da171", 45 | "topic": "org.fedoraproject.prod.pdc.compose", 46 | "source_version": "0.6.5", 47 | "msg": { 48 | "action": "create", 49 | "compose_respin": 0, 50 | "compose_date": "2016-03-31", 51 | "compose_id": "Fedora-Rawhide-20160331.n.0", 52 | "compose_type": "nightly" 53 | } 54 | } 55 | 56 | 57 | class TestPDCImagesImport(Base): 58 | """ The `Product Definition Center `_ 59 | publishes messages on this topic whenever a set of images are uploaded for 60 | a new compose entry. This message doesn't necessarily signify that the 61 | compose is fully imported. The `pdc-updater 62 | `_ project typically import 63 | the images first and the rpms second, but it could be that an admin 64 | manually imports a compose in which case the order is not guaranteed. 65 | """ 66 | expected_title = "pdc.images" 67 | expected_subti = ("PDC imported metadata for 3 images for " 68 | "the Fedora-Rawhide-20160331.n.0 nightly compose") 69 | expected_link = ("https://pdc.fedoraproject.org/rest_api/v1/" 70 | "composes/Fedora-Rawhide-20160331.n.0/") 71 | expected_objects = set(['Fedora-Rawhide-20160331.n.0/import/images']) 72 | msg = { 73 | "timestamp": 1459420734.0, 74 | "topic": "org.fedoraproject.prod.pdc.images", 75 | "source_version": "0.6.5", 76 | "msg": { 77 | "action": "import", 78 | "attribute": "images", 79 | "count": 3, 80 | "compose_respin": 0, 81 | "compose_date": "2016-03-31", 82 | "compose_id": "Fedora-Rawhide-20160331.n.0", 83 | "compose_type": "nightly" 84 | } 85 | } 86 | 87 | 88 | class TestPDCRPMsImport(Base): 89 | """ The `Product Definition Center `_ 90 | publishes messages on this topic whenever a set of rpms are uploaded for 91 | a new compose entry. This message doesn't necessarily signify that the 92 | compose is fully imported. The `pdc-updater 93 | `_ project typically import 94 | the images first and the rpms second, but it could be that an admin 95 | manually imports a compose in which case the order is not guaranteed. 96 | """ 97 | expected_title = "pdc.rpms" 98 | expected_subti = ("PDC imported metadata for 207 rpms for " 99 | "the Fedora-Rawhide-20160331.n.0 nightly compose") 100 | expected_link = ("https://pdc.fedoraproject.org/rest_api/v1/" 101 | "composes/Fedora-Rawhide-20160331.n.0/") 102 | expected_objects = set(['Fedora-Rawhide-20160331.n.0/import/rpms']) 103 | msg = { 104 | "timestamp": 1459420734.0, 105 | "topic": "org.fedoraproject.prod.pdc.rpms", 106 | "source_version": "0.6.5", 107 | "msg": { 108 | "action": "import", 109 | "attribute": "rpms", 110 | "count": 207, 111 | "compose_respin": 0, 112 | "compose_date": "2016-03-31", 113 | "compose_id": "Fedora-Rawhide-20160331.n.0", 114 | "compose_type": "nightly" 115 | } 116 | } 117 | 118 | 119 | add_doc(locals()) 120 | 121 | if __name__ == '__main__': 122 | unittest.main() 123 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/koschei.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2014 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: Michael Simacek 19 | 20 | from fedmsg_meta_fedora_infrastructure import BaseProcessor 21 | 22 | 23 | class KoscheiProcessor(BaseProcessor): 24 | __name__ = 'koschei' 25 | __description__ = "Continuous integration for Fedora packages" 26 | __link__ = "https://apps.fedoraproject.org/koschei" 27 | __docs__ = "https://apps.fedoraproject.org/koschei/documentation" 28 | __obj__ = "Watched packages" 29 | __icon__ = ("https://fedoraproject.org/w/uploads/e/e9/Koschei.png") 30 | 31 | def subtitle(self, msg, **config): 32 | # Emitted by Koschei whenever state of package changes, for 33 | # example when package starts to fail to build, package 34 | # dependencies become unresolved or when package is fixed. 35 | if 'koschei.package.state.change' in msg['topic']: 36 | content = msg['msg'] 37 | if content['new'] == 'ok' and content['old'] == 'ignored': 38 | info = "{name} added to Koschei" 39 | else: 40 | info = { 41 | 'failing': "{name}'s builds started to fail", 42 | 'ok': "{name}'s builds are back to normal", 43 | 'ignored': "{name} became retired or ignored", 44 | 'unresolved': "{name}'s dependencies failed to resolve", 45 | }[content['new']] 46 | info += ' in {collection}' 47 | if content['koji_instance'] != 'primary': 48 | info += ' ({koji_instance})' 49 | collection = content.get('collection_name', content.get('repo')) 50 | return info.format(name=content['name'], 51 | collection=collection, 52 | koji_instance=content['koji_instance']) 53 | # Emitted by Koschei whenever state of collection changes, for 54 | # example when collection buildroot becomes unresolvable 55 | # (broken) or when it is fixed. 56 | elif 'koschei.collection.state.change' in msg['topic']: 57 | content = msg['msg'] 58 | if content['new'] == 'ok' and content['old'] == 'unknown': 59 | info = "{collection} added to Koschei" 60 | else: 61 | info = { 62 | 'ok': "{collection} buildroot was fixed", 63 | 'unresolved': "{collection} buildroot was broken", 64 | }[content['new']] 65 | if content['koji_instance'] != 'primary': 66 | info += ' ({koji_instance})' 67 | collection = content['collection_name'] 68 | return info.format(collection=collection, 69 | koji_instance=content['koji_instance']) 70 | else: 71 | raise NotImplementedError("%r" % msg) 72 | 73 | def secondary_icon(self, msg, **config): 74 | tmpl = 'https://apps.fedoraproject.org/packages/images/icons/%s.png' 75 | # Emitted by Koschei whenever state of package changes, for 76 | # example when package starts to fail to build, package 77 | # dependencies become unresolved or when package is fixed. 78 | if 'koschei.package.state.change' in msg['topic']: 79 | return tmpl % msg['msg']['name'] 80 | 81 | def link(self, msg, **config): 82 | baseurl = 'https://apps.fedoraproject.org/koschei' 83 | # Emitted by Koschei whenever state of package changes, for 84 | # example when package starts to fail to build, package 85 | # dependencies become unresolved or when package is fixed. 86 | if 'koschei.package.state.change' in msg['topic']: 87 | url = '{baseurl}/package/{name}'.format(baseurl=baseurl, 88 | name=msg['msg']['name']) 89 | if 'collection' in msg['msg']: 90 | url += '?collection=' + msg['msg']['collection'] 91 | return url 92 | # Emitted by Koschei whenever state of collection changes, for 93 | # example when collection buildroot becomes unresolvable 94 | # (broken) or when it is fixed. 95 | elif 'koschei.collection.state.change' in msg['topic']: 96 | url = '{baseurl}/collection/{name}'.format(baseurl=baseurl, 97 | name=msg['msg']['collection']) 98 | return url 99 | else: 100 | raise NotImplementedError("%r" % msg) 101 | 102 | def packages(self, msg, **config): 103 | if 'koschei.package.state.change' in msg['topic']: 104 | return set([msg['msg']['name']]) 105 | else: 106 | raise NotImplementedError("%r" % msg) 107 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/rats.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2018 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: Pierre-Yves Chibon 19 | # 20 | 21 | from fedmsg_meta_fedora_infrastructure.fasshim import avatar_url, email2fas 22 | from fedmsg_meta_fedora_infrastructure import BaseProcessor 23 | from fedmsg_meta_fedora_infrastructure.pagure import ( 24 | _get_project, DistGitPagureProcessor) 25 | 26 | 27 | import fedmsg.meta.base 28 | 29 | 30 | class RatsProcessor(BaseProcessor): 31 | topic_prefix_re = 'org\\.fedoraproject\\.(dev|stg|prod)' 32 | 33 | __name__ = "rats" 34 | __description__ = "Run Another Test System" 35 | __link__ = "https://pagure.io/rats" 36 | __docs__ = "https://pagure.io/rats" 37 | __obj__ = "RATS" 38 | __icon__ = ("https://apps.fedoraproject.org/packages/" 39 | "images/icons/package_128x128.png") 40 | 41 | def link(self, msg, **config): 42 | if 'test.simple-koji-ci' in msg['topic']: 43 | msg2 = msg.copy() 44 | msg2['topic'] = msg2['topic'].replace( 45 | 'rats.test.simple-koji-ci', 'pagure.pull-request.new') 46 | msg2['msg']['pullrequest'] = msg2['msg']['pull_request'] 47 | return DistGitPagureProcessor(self._, **config).link(msg2, **config) 48 | 49 | def subtitle(self, msg, **config): 50 | user = msg['msg'].get('agent') 51 | 52 | if 'test.simple-koji-ci' in msg['topic']: 53 | project = _get_project(msg['msg']['pull_request']) 54 | prid = prid = msg['msg']['pull_request']['id'] 55 | tmpl = self._( 56 | '{user} requested a run of simple-koji-ci on ' 57 | '"{project}/pull-request/{prid}"' 58 | ) 59 | return tmpl.format(user=user, project=project, prid=prid) 60 | 61 | elif 'test.taskotron' in msg['topic']: 62 | test = msg['msg']['test'] 63 | target = msg['msg']['identifier'] 64 | rdbid = msg['msg']['result_id'] 65 | if target: 66 | tmpl = self._( 67 | '{user} requested a run of taskotron\'s {test} on ' 68 | '"{target}"' 69 | ) 70 | else: 71 | tmpl = self._( 72 | '{user} requested a run of taskotron on ' 73 | 'resultsdb\'s result id: "{rdbid}"' 74 | ) 75 | return tmpl.format( 76 | user=user, test=test, target=target, rdbid=rdbid) 77 | 78 | elif 'test.atomic-ci' in msg['topic']: 79 | test = msg['msg']['test'] 80 | target = msg['msg']['identifier'] 81 | rdbid = msg['msg']['result_id'] 82 | if target: 83 | tmpl = self._( 84 | '{user} requested a run of atomic-ci on ' 85 | '"{target}"' 86 | ) 87 | else: 88 | tmpl = self._( 89 | '{user} requested a run of atomic-ci on ' 90 | 'resultsdb\'s result id: "{rdbid}"' 91 | ) 92 | return tmpl.format( 93 | user=user, test=test, target=target, rdbid=rdbid) 94 | 95 | def secondary_icon(self, msg, **config): 96 | username = msg['msg'].get('agent') 97 | if username: 98 | return avatar_url(username) 99 | 100 | def usernames(self, msg, **config): 101 | username = msg['msg'].get('agent') 102 | if username: 103 | return set([username]) 104 | else: 105 | return set([]) 106 | 107 | def objects(self, msg, **config): 108 | if 'test.simple-koji-ci' in msg['topic']: 109 | project = _get_project(msg['msg']['pull_request']).strip() 110 | prid = msg['msg']['pull_request']['id'] 111 | return set([ 112 | 'simple-koji-ci/%s/pull-request/%s' % (project, prid) 113 | ]) 114 | elif 'test.taskotron' in msg['topic']: 115 | test = msg['msg']['test'] 116 | target = msg['msg']['identifier'] 117 | rdbid = msg['msg']['result_id'] 118 | if target: 119 | return set([ 120 | 'taskotron/%s/%s' % (test, target) 121 | ]) 122 | else: 123 | return set([ 124 | 'taskotron/resultsdb/%s' % (rdbid) 125 | ]) 126 | 127 | elif 'test.atomic-ci' in msg['topic']: 128 | test = msg['msg']['test'] 129 | target = msg['msg']['identifier'] 130 | rdbid = msg['msg']['result_id'] 131 | if target: 132 | return set([ 133 | 'AtomicCI/%s' % (target) 134 | ]) 135 | else: 136 | return set([ 137 | 'AtomicCI/resultsdb/%s' % (rdbid) 138 | ]) 139 | 140 | return set([]) 141 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/askbot.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2012 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: Ralph Bean 19 | # 20 | from fedmsg_meta_fedora_infrastructure import BaseProcessor 21 | from fedmsg_meta_fedora_infrastructure.fasshim import avatar_url 22 | 23 | 24 | class AskbotProcessor(BaseProcessor): 25 | __name__ = "Askbot" 26 | __description__ = "the Fedora 'Ask' Forum" 27 | __link__ = "https://ask.fedoraproject.org" 28 | __docs__ = "https://askbot.com" 29 | __icon__ = "https://apps.fedoraproject.org/img/icons/ask_fedora.png" 30 | __obj__ = "Ask Fedora Qs & As" 31 | 32 | # No icon that I can find.. 33 | #__icon__ = "https://apps.fedoraproject.org/packages/" + \ 34 | # "images/icons/package_128x128.png" 35 | 36 | def subtitle(self, msg, **config): 37 | user = msg['msg']['agent'] 38 | title = "" 39 | if 'askbot.post.edit' in msg['topic']: 40 | title = msg['msg']['thread']['title'] 41 | if msg['msg']['created']: 42 | if msg['msg']['post']['post_type'] == 'question': 43 | tmpl = self._("{user} asked the question '{title}'") 44 | else: 45 | tmpl = self._( 46 | "{user} suggested an answer to the question '{title}'") 47 | else: 48 | if msg['msg']['post']['post_type'] == 'question': 49 | tmpl = self._("{user} updated the question '{title}'") 50 | else: 51 | tmpl = self._( 52 | "{user} updated an answer to the question '{title}'") 53 | elif 'askbot.tag.update' in msg['topic']: 54 | title = msg['msg']['thread']['title'] 55 | tmpl = self._("{user} altered tags on askbot question '{title}'") 56 | elif 'askbot.post.flag_offensive.add' in msg['topic']: 57 | title = msg['msg']['thread']['title'] 58 | if msg['msg']['instance']['post_type'] == 'question': 59 | tmpl = self._("{user} flagged a question as offensive!") 60 | else: 61 | tmpl = self._("{user} flagged an answer as offensive!") 62 | elif 'askbot.post.flag_offensive.delete' in msg['topic']: 63 | if msg['msg']['instance']['post_type'] == 'question': 64 | tmpl = self._("{user} unflagged a question as offensive...") 65 | else: 66 | tmpl = self._("{user} unflagged an answer as offensive...") 67 | elif 'askbot.post.delete' in msg['topic']: 68 | title = msg['msg']['thread']['title'] 69 | if msg['msg']['instance']['post_type'] == 'question': 70 | tmpl = self._("{user} deleted the question '{title}'") 71 | else: 72 | tmpl = self._("{user} deleted an answer on '{title}'") 73 | else: 74 | raise NotImplementedError("%r" % msg) 75 | 76 | return tmpl.format(user=user, title=title) 77 | 78 | def secondary_icon(self, msg, **config): 79 | user = None 80 | 81 | try: 82 | user = msg['msg']['agent'] 83 | except KeyError: 84 | pass 85 | 86 | if not user: 87 | return "" 88 | 89 | return avatar_url(username=user) 90 | 91 | def usernames(self, msg, **config): 92 | users = set() 93 | 94 | try: 95 | users.add(msg['msg']['agent']) 96 | except KeyError: 97 | pass 98 | 99 | for user in msg['msg'].get('newly_mentioned_users', []): 100 | users.add(user) 101 | 102 | return users 103 | 104 | def objects(self, msg, **config): 105 | objs = set() 106 | 107 | if 'tags' in msg['msg']: 108 | for tag in msg['msg']['tags']: 109 | if not tag: 110 | continue 111 | objs.add('tags/{tag}'.format(tag=tag)) 112 | elif 'thread' in msg['msg']: 113 | for tag in msg['msg']['thread']['tagnames']: 114 | if not tag: 115 | continue 116 | objs.add('tags/{tag}'.format(tag=tag)) 117 | 118 | if 'thread' in msg['msg']: 119 | objs.add('threads/{pk}'.format( 120 | pk=msg['msg']['thread']['pk'])) 121 | 122 | return objs 123 | 124 | def link(self, msg, **config): 125 | if 'stg' in msg['topic']: 126 | tmpl = "https://ask.stg.fedoraproject.org/question/{pk}/" 127 | else: 128 | tmpl = "https://ask.fedoraproject.org/question/{pk}/" 129 | 130 | pk = msg['msg']['topmost_post_id'] 131 | post = "" 132 | 133 | if 'post' in msg['msg']: 134 | post = msg['msg']['post']['pk'] 135 | #tmpl += "?answer={post}#post-id-{post}" 136 | elif 'instance' in msg['msg']: 137 | post = msg['msg']['instance']['pk'] 138 | #tmpl += "?answer={post}#post-id-{post}" 139 | else: 140 | pass 141 | 142 | return tmpl.format(pk=pk, post=post) 143 | -------------------------------------------------------------------------------- /fedmsg_meta_fedora_infrastructure/fas.py: -------------------------------------------------------------------------------- 1 | # This file is part of fedmsg. 2 | # Copyright (C) 2012 Red Hat, Inc. 3 | # 4 | # fedmsg is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) any later version. 8 | # 9 | # fedmsg is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with fedmsg; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # Authors: Ralph Bean 19 | # 20 | import six 21 | 22 | from fedmsg_meta_fedora_infrastructure import BaseProcessor 23 | from fedmsg_meta_fedora_infrastructure.fasshim import avatar_url 24 | 25 | 26 | def string_or_dict(msg, key): 27 | if isinstance(msg[key], six.text_type): 28 | return msg[key] 29 | else: 30 | if 'username' in msg[key]: 31 | return msg[key]['username'] 32 | else: 33 | return msg[key]['name'] 34 | 35 | 36 | class FASProcessor(BaseProcessor): 37 | __name__ = "FAS" 38 | __description__ = "the Fedora Account System" 39 | __link__ = "https://admin.fedoraproject.org/accounts" 40 | __docs__ = "https://fedoraproject.org/wiki/Account_System" 41 | __obj__ = "Account Changes" 42 | __icon__ = ("https://admin.fedoraproject.org/accounts/static/" 43 | "theme/fas/images/account.png") 44 | 45 | def subtitle(self, msg, **config): 46 | if 'fas.user.create' in msg['topic']: 47 | agent = string_or_dict(msg['msg'], 'agent') 48 | user = string_or_dict(msg['msg'], 'user') 49 | tmpl = self._( 50 | "New FAS account: '{user}' (created by '{agent}')" 51 | ) 52 | return tmpl.format(agent=agent, user=user) 53 | elif 'fas.user.update' in msg['topic']: 54 | agent = string_or_dict(msg['msg'], 'agent') 55 | user = string_or_dict(msg['msg'], 'user') 56 | fields = ", ".join(msg['msg']['fields']) 57 | tmpl = self._( 58 | "{agent} edited the following fields of " + 59 | "{user}'s FAS profile: {fields}" 60 | ) 61 | return tmpl.format(agent=agent, user=user, fields=fields) 62 | elif 'fas.group.member.' in msg['topic']: 63 | action = msg['topic'].split('.')[-1] 64 | agent = string_or_dict(msg['msg'], 'agent') 65 | user = string_or_dict(msg['msg'], 'user') 66 | group = string_or_dict(msg['msg'], 'group') 67 | tmpls = { 68 | 'apply': self._( 69 | "{agent} applied for {user}'s membership " + 70 | "in the {group} group" 71 | ), 72 | 'sponsor': self._( 73 | "{agent} sponsored {user}'s membership " + 74 | "in the {group} group" 75 | ), 76 | 'remove': self._( 77 | "{agent} removed {user} from " + 78 | "the {group} group" 79 | ), 80 | } 81 | tmpl = tmpls.get(action, self._( 82 | '' 83 | )) 84 | return tmpl.format(agent=agent, user=user, group=group) 85 | elif 'fas.group.create' in msg['topic']: 86 | agent = string_or_dict(msg['msg'], 'agent') 87 | group = string_or_dict(msg['msg'], 'group') 88 | tmpl = self._("{agent} created new FAS group {group}") 89 | return tmpl.format(agent=agent, group=group) 90 | elif 'fas.group.update' in msg['topic']: 91 | agent = string_or_dict(msg['msg'], 'agent') 92 | group = string_or_dict(msg['msg'], 'group') 93 | fields = ", ".join(msg['msg']['fields']) 94 | tmpl = self._( 95 | "{agent} edited the following fields of the {group} " + 96 | "FAS group: {fields}" 97 | ) 98 | return tmpl.format(agent=agent, group=group, fields=fields) 99 | elif 'fas.role.update' in msg['topic']: 100 | tmpl = self._( 101 | "{agent} changed {user}'s role in the {group} group" 102 | ) 103 | agent = string_or_dict(msg['msg'], 'agent') 104 | user = string_or_dict(msg['msg'], 'user') 105 | group = string_or_dict(msg['msg'], 'group') 106 | if 'status' in msg['msg']: 107 | status = string_or_dict(msg['msg'], 'status') 108 | tmpl += self._(' to {status}') 109 | else: 110 | status = None 111 | return tmpl.format(agent=agent, 112 | group=group, 113 | user=user, 114 | status=status) 115 | else: 116 | raise NotImplementedError("%r" % msg) 117 | 118 | def secondary_icon(self, msg, **config): 119 | # Every fas fedmsg message has an "agent" field.. "whodunnit" 120 | return avatar_url(username=string_or_dict(msg['msg'], 'agent')) 121 | 122 | def usernames(self, msg, **config): 123 | users = [] 124 | 125 | try: 126 | users.append(string_or_dict(msg['msg'], 'agent')) 127 | except KeyError: 128 | pass 129 | 130 | try: 131 | users.append(string_or_dict(msg['msg'], 'user')) 132 | except KeyError: 133 | pass 134 | 135 | return set(users) 136 | 137 | def objects(self, msg, **config): 138 | objs = set() 139 | 140 | if 'user' in msg['msg']: 141 | objs.add('users/' + string_or_dict(msg['msg'], 'user')) 142 | 143 | if 'group' in msg['msg']: 144 | objs.add('groups/' + string_or_dict(msg['msg'], 'group')) 145 | 146 | return objs 147 | --------------------------------------------------------------------------------