Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
bcc4c90
Move crossbow to archery
kszucs Apr 6, 2021
27d63f3
Enable using jinja in tasks.yml
kszucs Apr 6, 2021
43670b7
Rewrite more template
kszucs Apr 6, 2021
459c7c3
Rewrite more templates
kszucs Apr 6, 2021
121bd2d
Fix jinja errors
kszucs Apr 6, 2021
88dcc11
Remove all usage of crossbow.py
kszucs Apr 7, 2021
3ec8c1f
Locating archery command requires editable install
kszucs Apr 7, 2021
b7127c8
Fix tests and remove toolz dependency
kszucs Apr 7, 2021
438cdff
Missing newline
kszucs Apr 7, 2021
86165a5
Fix indentation for the arm64 wheel builds
kszucs Apr 7, 2021
5e5f98d
Fix indentation for the arm64 linux builds
kszucs Apr 7, 2021
29d06d2
Param conflict
kszucs Apr 7, 2021
3c1b203
Template fixes
kszucs Apr 7, 2021
0dbfe4b
Macro fixes
kszucs Apr 7, 2021
40bfa61
Debug
kszucs Apr 7, 2021
8c219f3
Additional templating
kszucs Apr 7, 2021
3d88117
Fix conda builds
kszucs Apr 7, 2021
7d44edc
Finalizing
kszucs Apr 7, 2021
982b4a4
Fix bot test case, flake8, RAT
kszucs Apr 7, 2021
bc3438c
Cleanup
kszucs Apr 8, 2021
57dc36b
Use bash on azure pipelines for uploading the release assets
kszucs Apr 8, 2021
30d6aca
Debug CI error
kszucs Apr 8, 2021
9bbb77b
Create empty git crossbow repo
kszucs Apr 8, 2021
e95e92d
Test crossbow submit
kszucs Apr 8, 2021
83e5d23
Run crossbow test case on gha
kszucs Apr 8, 2021
3b24b9d
Author information
kszucs Apr 8, 2021
fd7b098
Configure author from the CI yml
kszucs Apr 8, 2021
39c6a20
Debug test error
kszucs Apr 8, 2021
c43c87d
checkout
kszucs Apr 8, 2021
68b3005
Disable test
kszucs Apr 8, 2021
71d4e7c
Update check-config command
kszucs Apr 8, 2021
b525b51
WIP
kszucs Apr 8, 2021
6fc6b6c
WIP
kszucs Apr 8, 2021
a67c403
WIP
kszucs Apr 8, 2021
6246f1c
WIP
kszucs Apr 8, 2021
051f41e
WIP
kszucs Apr 8, 2021
abbce18
WIP
kszucs Apr 8, 2021
b5b4a9a
WIP
kszucs Apr 8, 2021
11cfd58
WIP
kszucs Apr 8, 2021
2033b64
WIP
kszucs Apr 8, 2021
0fa26f4
RAT
kszucs Apr 8, 2021
8d4de65
Fix import error
kszucs Apr 8, 2021
86640b1
Fix azure docker template
kszucs Apr 8, 2021
f41949b
Mark tasks without any builds scheduled as failed
kszucs Apr 9, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions .github/workflows/archery.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,12 @@ jobs:
with:
python-version: '3.6'
- name: Install Archery, Crossbow- and Test Dependencies
working-directory: dev/archery
run: pip install pytest responses toolz jinja2 -e .[all]
run: pip install pytest responses -e dev/archery[all]
- name: Archery Unittests
working-directory: dev/archery
run: pytest -v archery
- name: Archery Docker Validation
run: archery docker
- name: Crossbow Check Config
working-directory: dev/tasks
run: python crossbow.py check-config
run: archery crossbow check-config
230 changes: 81 additions & 149 deletions dev/archery/archery/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
# specific language governing permissions and limitations
# under the License.

import operator
import os
import shlex
from pathlib import Path
from functools import partial
Expand All @@ -24,8 +24,9 @@
import click
import github

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


class EventError(Exception):
Expand Down Expand Up @@ -81,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 @@ -195,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 All @@ -220,14 +140,13 @@ def handle_issue_comment(self, command, payload):

comment = pull.get_issue_comment(payload['comment']['id'])
try:
self.handler(command, issue=issue, pull=pull, comment=comment)
self.handler(command, issue=issue, pull_request=pull,
comment=comment)
except CommandError as e:
# TODO(kszucs): log
print(e)
logger.error(e)
pull.create_issue_comment("```\n{}\n```".format(e.message))
except Exception as e:
# TODO(kszucs): log
print(e)
logger.error(e)
comment.create_reaction('-1')
else:
comment.create_reaction('+1')
Expand All @@ -248,81 +167,94 @@ def actions(ctx):
help='Crossbow repository on github to use')
@click.pass_obj
def crossbow(obj, crossbow):
"""Trigger crossbow builds for this pull request"""
"""
Trigger crossbow builds for this pull request
"""
obj['crossbow_repo'] = crossbow


def _clone_arrow_and_crossbow(dest, crossbow_repo, pull_request):
"""
Clone the repositories and initialize crossbow objects.

Parameters
----------
dest : Path
Filesystem path to clone the repositories to.
crossbow_repo : str
Github repository name, like kszucs/crossbow.
pull_request : pygithub.PullRequest
Object containing information about the pull request the comment bot
was triggered from.
"""
arrow_path = dest / 'arrow'
queue_path = dest / 'crossbow'

# clone arrow and checkout the pull request's branch
pull_request_ref = 'pull/{}/head:{}'.format(
pull_request.number, pull_request.head.ref
)
git.clone(pull_request.base.repo.clone_url, str(arrow_path))
git.fetch('origin', pull_request_ref, git_dir=arrow_path)
git.checkout(pull_request.head.ref, git_dir=arrow_path)

# clone crossbow repository
crossbow_url = 'https://github.com/{}'.format(crossbow_repo)
git.clone(crossbow_url, str(queue_path))

# initialize crossbow objects
github_token = os.environ['CROSSBOW_GITHUB_TOKEN']
arrow = Repo(arrow_path)
queue = Queue(queue_path, github_token=github_token, require_https=True)

return (arrow, queue)


@crossbow.command()
@click.argument('tasks', nargs=-1, required=False)
@click.option('--group', '-g', 'groups', multiple=True,
help='Submit task groups as defined in tests.yml')
@click.option('--param', '-p', 'params', multiple=True,
help='Additional task parameters for rendering the CI templates')
@click.option('--dry-run/--push', default=False,
help='Just display the new changelog, don\'t write it')
@click.option('--arrow-version', '-v', default=None,
help='Set target version explicitly.')
@click.pass_obj
def submit(obj, tasks, groups, params, dry_run):
"""Submit crossbow testing tasks.
def submit(obj, tasks, groups, params, arrow_version):
"""
Submit crossbow testing tasks.

See groups defined in arrow/dev/tasks/tests.yml
"""
from ruamel.yaml import YAML

git = Git()

# construct crossbow arguments
args = []
if dry_run:
args.append('--dry-run')

for p in params:
args.extend(['-p', p])
for g in groups:
args.extend(['-g', g])
for t in tasks:
args.append(t)

# pygithub pull request object
pr = obj['pull']
crossbow_url = 'https://github.com/{}'.format(obj['crossbow_repo'])

crossbow_repo = obj['crossbow_repo']
pull_request = obj['pull_request']
with tempfile.TemporaryDirectory() as tmpdir:
tmpdir = Path(tmpdir)
arrow = tmpdir / 'arrow'
queue = tmpdir / 'crossbow'

# clone arrow and checkout the pull request's branch
git.clone(pr.base.repo.clone_url, str(arrow))
git.fetch('origin', 'pull/{}/head:{}'.format(pr.number, pr.head.ref),
git_dir=str(arrow))
git.checkout(pr.head.ref, git_dir=str(arrow))

# clone crossbow
git.clone(crossbow_url, str(queue))

# submit the crossbow tasks
result = Path('result.yml').resolve()
xbow = Crossbow(str(arrow / 'dev' / 'tasks' / 'crossbow.py'))
xbow.run(
'--queue-path', str(queue),
'--output-file', str(result),
'submit',
'--job-prefix', 'actions',
# don't rely on crossbow's remote and branch detection, because
# it doesn't work without a tracking upstream branch
'--arrow-remote', pr.head.repo.clone_url,
'--arrow-branch', pr.head.ref,
*args
arrow, queue = _clone_arrow_and_crossbow(
dest=Path(tmpdir),
crossbow_repo=crossbow_repo,
pull_request=pull_request,
)
# load available tasks configuration and groups from yaml
config = Config.load_yaml(arrow.path / "dev" / "tasks" / "tasks.yml")
config.validate()

# initialize the crossbow build's target repository
target = Target.from_repo(arrow, version=arrow_version,
remote=pull_request.base.repo.clone_url)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that pull_request.base always refers apache/arrow not ${USER}/arrow: #9977 (comment)
Should w use pull_request.head here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kszucs

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should, sorry about that! The fix is at #9978

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!
It works now!


# parse additional job parameters
params = dict([p.split("=") for p in params])

# instantiate the job object
job = Job.from_config(config=config, target=target, tasks=tasks,
groups=groups, params=params)

# parse the result yml describing the submitted job
yaml = YAML()
with result.open() as fp:
job = yaml.load(fp)
# add the job to the crossbow queue and push to the remote repository
queue.put(job, prefix="actions")
queue.push()

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

# send the response
pr.create_issue_comment(response)
# send the response
pull_request.create_issue_comment(report.show())
18 changes: 18 additions & 0 deletions dev/archery/archery/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -1069,5 +1069,23 @@ def release_cherry_pick(obj, version, dry_run, recreate):
click.echo('git cherry-pick {}'.format(commit.hexsha))


try:
from .crossbow.cli import crossbow # noqa
except ImportError as exc:
missing_package = exc.name

@archery.command(
'crossbow',
context_settings={"ignore_unknown_options": True}
)
def crossbow():
raise click.ClickException(
"Couldn't import crossbow because of missing dependency: {}"
.format(missing_package)
)
else:
archery.add_command(crossbow)


if __name__ == "__main__":
archery(obj={})
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,5 @@
# specific language governing permissions and limitations
# under the License.

from .command import Command, default_bin


class Crossbow(Command):
def __init__(self, crossbow_bin=None):
self.bin = default_bin(crossbow_bin, "arrow/dev/tasks/crossbow.py")
from .core import Config, Repo, Queue, Target, Job # noqa
from .reports import CommentReport, ConsoleReport, EmailReport # noqa
Loading