Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
kszucs committed Apr 8, 2021
1 parent df86909 commit da51297
Show file tree
Hide file tree
Showing 9 changed files with 153 additions and 139 deletions.
1 change: 0 additions & 1 deletion .github/workflows/comment_bot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ jobs:
archery trigger-bot \
--event-name ${{ github.event_name }} \
--event-payload ${{ github.event_path }}
ls -lah
autotune:
name: "Fix all the things"
Expand Down
91 changes: 4 additions & 87 deletions dev/archery/archery/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
# under the License.

import os
import operator
import shlex
from pathlib import Path
from functools import partial
Expand All @@ -27,7 +26,7 @@

from .utils.git import git
from .utils.logger import logger
from .crossbow import Repo, Queue, Config, Target, Job
from .crossbow import Repo, Queue, Config, Target, Job, CommentReport


class EventError(Exception):
Expand Down Expand Up @@ -83,86 +82,6 @@ def parse_args(self, ctx, args):
group = partial(click.group, cls=Group)


class CrossbowCommentFormatter:

_markdown_badge = '[![{title}]({badge})]({url})'

badges = {
'github': _markdown_badge.format(
title='Github Actions',
url='https://github.com/{repo}/actions?query=branch:{branch}',
badge=(
'https://github.com/{repo}/workflows/Crossbow/'
'badge.svg?branch={branch}'
),
),
'azure': _markdown_badge.format(
title='Azure',
url=(
'https://dev.azure.com/{repo}/_build/latest'
'?definitionId=1&branchName={branch}'
),
badge=(
'https://dev.azure.com/{repo}/_apis/build/status/'
'{repo_dotted}?branchName={branch}'
)
),
'travis': _markdown_badge.format(
title='TravisCI',
url='https://travis-ci.com/{repo}/branches',
badge='https://img.shields.io/travis/{repo}/{branch}.svg'
),
'circle': _markdown_badge.format(
title='CircleCI',
url='https://circleci.com/gh/{repo}/tree/{branch}',
badge=(
'https://img.shields.io/circleci/build/github'
'/{repo}/{branch}.svg'
)
),
'appveyor': _markdown_badge.format(
title='Appveyor',
url='https://ci.appveyor.com/project/{repo}/history',
badge='https://img.shields.io/appveyor/ci/{repo}/{branch}.svg'
),
'drone': _markdown_badge.format(
title='Drone',
url='https://cloud.drone.io/{repo}',
badge='https://img.shields.io/drone/build/{repo}/{branch}.svg'
),
}

def __init__(self, crossbow_repo):
self.crossbow_repo = crossbow_repo

def render(self, job):
url = 'https://github.com/{repo}/branches/all?query={branch}'
sha = job.target.head

msg = 'Revision: {}\n\n'.format(sha)
msg += 'Submitted crossbow builds: [{repo} @ {branch}]'
msg += '({})\n'.format(url)
msg += '\n|Task|Status|\n|----|------|'

tasks = sorted(job.tasks.items(), key=operator.itemgetter(0))
for key, task in tasks:
branch = task.branch

try:
template = self.badges[task.ci]
badge = template.format(
repo=self.crossbow_repo,
repo_dotted=self.crossbow_repo.replace('/', '.'),
branch=branch
)
except KeyError:
badge = 'unsupported CI service `{}`'.format(task.ci)

msg += '\n|{}|{}|'.format(key, badge)

return msg.format(repo=self.crossbow_repo, branch=job.branch)


class CommentBot:

def __init__(self, name, handler, token=None):
Expand Down Expand Up @@ -197,8 +116,7 @@ def handle(self, event, payload):
try:
command = self.parse_command(payload)
except EventError as e:
print(e)
# TODO(kszucs): log
logger.error(e)
# see the possible reasons in the validate method
return

Expand Down Expand Up @@ -336,8 +254,7 @@ def submit(obj, tasks, groups, params, arrow_version):
queue.push()

# render the response comment's content
formatter = CrossbowCommentFormatter(crossbow_repo)
response = formatter.render(job)
report = CommentReport(job, crossbow_repo=crossbow_repo)

# send the response
pull_request.create_issue_comment(response)
pull_request.create_issue_comment(report.show())
1 change: 1 addition & 0 deletions dev/archery/archery/crossbow/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@
# under the License.

from .core import Config, Repo, Queue, Target, Job # noqa
from .reports import CommentReport, ConsoleReport, EmailReport # noqa
82 changes: 82 additions & 0 deletions dev/archery/archery/crossbow/reports.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import click
import collections
import operator
import functools
from io import StringIO
import textwrap
Expand Down Expand Up @@ -218,3 +219,84 @@ def send(self, smtp_user, smtp_password, smtp_server, smtp_port):
server.login(smtp_user, smtp_password)
server.sendmail(smtp_user, self.recipient_email, email)
server.close()


class CommentReport(Report):

_markdown_badge = '[![{title}]({badge})]({url})'

badges = {
'github': _markdown_badge.format(
title='Github Actions',
url='https://github.com/{repo}/actions?query=branch:{branch}',
badge=(
'https://github.com/{repo}/workflows/crossbow.yml/'
'badge.svg?branch={branch}'
),
),
'azure': _markdown_badge.format(
title='Azure',
url=(
'https://dev.azure.com/{repo}/_build/latest'
'?definitionId=1&branchName={branch}'
),
badge=(
'https://dev.azure.com/{repo}/_apis/build/status/'
'{repo_dotted}?branchName={branch}'
)
),
'travis': _markdown_badge.format(
title='TravisCI',
url='https://travis-ci.com/{repo}/branches',
badge='https://img.shields.io/travis/{repo}/{branch}.svg'
),
'circle': _markdown_badge.format(
title='CircleCI',
url='https://circleci.com/gh/{repo}/tree/{branch}',
badge=(
'https://img.shields.io/circleci/build/github'
'/{repo}/{branch}.svg'
)
),
'appveyor': _markdown_badge.format(
title='Appveyor',
url='https://ci.appveyor.com/project/{repo}/history',
badge='https://img.shields.io/appveyor/ci/{repo}/{branch}.svg'
),
'drone': _markdown_badge.format(
title='Drone',
url='https://cloud.drone.io/{repo}',
badge='https://img.shields.io/drone/build/{repo}/{branch}.svg'
),
}

def __init__(self, job, crossbow_repo):
self.crossbow_repo = crossbow_repo
super().__init__(job)

def show(self):
url = 'https://github.com/{repo}/branches/all?query={branch}'
sha = self.job.target.head

msg = 'Revision: {}\n\n'.format(sha)
msg += 'Submitted crossbow builds: [{repo} @ {branch}]'
msg += '({})\n'.format(url)
msg += '\n|Task|Status|\n|----|------|'

tasks = sorted(self.job.tasks.items(), key=operator.itemgetter(0))
for key, task in tasks:
branch = task.branch

try:
template = self.badges[task.ci]
badge = template.format(
repo=self.crossbow_repo,
repo_dotted=self.crossbow_repo.replace('/', '.'),
branch=branch
)
except KeyError:
badge = 'unsupported CI service `{}`'.format(task.ci)

msg += '\n|{}|{}|'.format(key, badge)

return msg.format(repo=self.crossbow_repo, branch=self.job.branch)
35 changes: 35 additions & 0 deletions dev/archery/archery/crossbow/tests/test_reports.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

import textwrap

from archery.crossbow.core import yaml
from archery.crossbow.reports import CommentReport


def test_crossbow_comment_formatter(load_fixture):
msg = load_fixture('crossbow-success-message.md')
job = load_fixture('crossbow-job.yaml', decoder=yaml.load)

report = CommentReport(job, crossbow_repo='ursa-labs/crossbow')
expected = msg.format(
repo='ursa-labs/crossbow',
branch='ursabot-1',
revision='f766a1d615dd1b7ee706d05102e579195951a61c',
status='has been succeeded.'
)
assert report.show() == textwrap.dedent(expected).strip()
58 changes: 7 additions & 51 deletions dev/archery/archery/tests/test_bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,13 @@
# under the License.

import json
from pathlib import Path
from unittest.mock import Mock

import click
import pytest
import textwrap
import responses as rsps
import click

from archery.crossbow.core import yaml
from archery.bot import (
CommentBot, CommandError, CrossbowCommentFormatter, group
)
from archery.bot import CommentBot, CommandError, group


@pytest.fixture
Expand All @@ -36,21 +31,6 @@ def responses():
yield mock


def fixture_path(name):
return Path(__file__).parent / 'fixtures' / name


def load_fixture(name):
path = fixture_path(name)
with path.open('r') as fp:
if name.endswith('.json'):
return json.load(fp)
elif name.endswith('.yaml'):
return yaml.load(fp)
else:
return fp.read()


def github_url(path):
return 'https://api.github.com:443/{}'.format(path.strip('/'))

Expand Down Expand Up @@ -89,21 +69,6 @@ def test_click_based_commands():
assert custom_handler('extra', extra='data') == {'extra': 'data'}


def test_crossbow_comment_formatter():
msg = load_fixture('crossbow-success-message.md')
job = load_fixture('crossbow-job.yaml')

formatter = CrossbowCommentFormatter(crossbow_repo='ursa-labs/crossbow')
response = formatter.render(job)
expected = msg.format(
repo='ursa-labs/crossbow',
branch='ursabot-1',
revision='f766a1d615dd1b7ee706d05102e579195951a61c',
status='has been succeeded.'
)
assert response == textwrap.dedent(expected).strip()


@pytest.mark.parametrize('fixture_name', [
# the bot is not mentioned, nothing to do
'event-issue-comment-not-mentioning-ursabot.json',
Expand All @@ -112,7 +77,7 @@ def test_crossbow_comment_formatter():
# non-authorized user sent the comment, do not respond
'event-issue-comment-by-non-authorized-user.json',
])
def test_noop_events(fixture_name):
def test_noop_events(load_fixture, fixture_name):
payload = load_fixture(fixture_name)

handler = Mock()
Expand All @@ -122,7 +87,7 @@ def test_noop_events(fixture_name):
handler.assert_not_called()


def test_issue_comment_without_pull_request(responses):
def test_issue_comment_without_pull_request(load_fixture, responses):
responses.add(
responses.GET,
github_url('/repositories/169101701/issues/19'),
Expand Down Expand Up @@ -154,7 +119,7 @@ def handler(command, **kwargs):
}


def test_respond_with_usage(responses):
def test_respond_with_usage(load_fixture, responses):
responses.add(
responses.GET,
github_url('/repositories/169101701/issues/26'),
Expand Down Expand Up @@ -193,7 +158,8 @@ def handler(command, **kwargs):
('@ursabot build', '+1'),
('@ursabot listen', '-1'),
])
def test_issue_comment_with_commands(responses, command, reaction):
def test_issue_comment_with_commands(load_fixture, responses, command,
reaction):
responses.add(
responses.GET,
github_url('/repositories/169101701/issues/26'),
Expand Down Expand Up @@ -233,13 +199,3 @@ def handler(command, **kwargs):

post = responses.calls[3]
assert json.loads(post.request.body) == {'content': reaction}


# TODO(kszucs): properly mock it
# def test_crossbow_submit():
# from click.testing import CliRunner
# runner = CliRunner()
# result = runner.invoke(
# bot, ['crossbow', 'submit', '-g', 'wheel', '--dry-run']
# )
# assert result.exit_code == 0
Loading

0 comments on commit da51297

Please sign in to comment.