Page MenuHomePhabricator

Create gerrit bot for git pushes to specific repo from prod machines
Closed, ResolvedPublic

Description

I need a bot account that can push changes without review to performance/docroot.

Similar idea to some CI bots we have, but from a prod (stat) box on a cron instead. I need a simple way to get the git credentials installed on the machines I need.

This should be done in a reusable way, since @Joe has a similar need for docker images.

Event Timeline

Gilles triaged this task as Medium priority.Jan 17 2019, 9:15 AM
Gilles created this task.

We should probably follow a similar pattern to localisation bot and libraryupgrade-bot.

Specifically, we'd grant the bot account CR+2 permissions in the Gerrit admin for this repo, and the bot would submit the patch to Gerrit and self CR+2 (but not self V+2). It then automatically lands after Jenkins verifies it, and automatically gets deployed (by Puppet ensure-latest).

While self-reviews can be done via the Gerrit API, the API isn't very convenient imho. I learned from @Legoktm that there is a special way via ssh+git that you can submit a commit to Gerrit in a way that caries the self-review with it as .. part of the push! That's the easiest way I've seen so far.

Basically, the bot would fetch+reset+clean, update files, run the build, commit, and push at once to Gerrit under refs/for/master with CR+2 already attached. That's more or less what localisation and libraryupgrade bots do currently.

I've figured out how to do that locally with the API using the pygerrit2 python library and it's fairly straightforward. Unfortunately that library is only available in buster, dammit, I will have to backport it.

Here's how simple the code is for publishing the change to gerrit with that library:

auth = HTTPBasicAuth(username, password)
gerrit_api = GerritRestAPI(url='https://gerrit.wikimedia.org/r/', auth=auth)


def create_change(project, subject, branch, topic):
    changeinput = {'project': project, 'subject': subject, 'branch': branch, 'topic': topic}
    result = gerrit_api.post('/changes/', data=changeinput)
    return result['id']


def add_file_to_change_edit(changeid, filepath, contents):
    gerrit_api.put('/changes/%s/edit/%s' % (changeid, filepath), data=contents)


def publish_change_edit(changeid):
    gerrit_api.post('/changes/%s/edit:publish' % changeid)


def plus_two(changeid):
    review = GerritReview()
    review.add_labels({'Code-Review': 1})
    gerrit_api.review(changeid, 'current', review)


def publish_asreport(date, contents):
    changeid = create_change('performance/docroot', 'Autonomous System Report monthly update: %s' % date, 'master', 'asreport/%s' % date)
    add_file_to_change_edit(changeid, urllib.quote_plus('src/_data/asreport.tsv'), contents)
    add_file_to_change_edit(changeid, urllib.quote_plus('src/asreport/tsv/%s.tsv' % date), contents)
    publish_change_edit(changeid)
    plus_two(changeid)

Alright, I think that answers it, it's more straightforward than I anticipated. The bot needs I have are actually much smaller than I first thought, and I'll probably be running it off of WMCS.