77 lines
3.2 KiB
Python
Executable file
77 lines
3.2 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
|
|
import argparse
|
|
import sys
|
|
|
|
sys.dont_write_bytecode = True
|
|
|
|
from task import github
|
|
|
|
def trigger_pull(api, opts):
|
|
pull = api.get("pulls/" + opts.pull)
|
|
|
|
if not pull:
|
|
sys.stderr.write("{0} is not a pull request.\n".format(opts.pull))
|
|
return 1
|
|
|
|
# triggering is manual, so don't prevent triggering a user that isn't on the whitelist
|
|
# but issue a warning in case of an oversight
|
|
login = pull["head"]["user"]["login"]
|
|
if not opts.allow and not login in api.whitelist():
|
|
sys.stderr.write("Pull request author '{0}' isn't whitelisted. Override with --allow.\n".format(login))
|
|
return 1
|
|
|
|
revision = pull['head']['sha']
|
|
statuses = api.statuses(revision)
|
|
if opts.context:
|
|
contexts = [cntx for cntx in opts.context if github.known_context(cntx)]
|
|
all = False
|
|
else:
|
|
contexts = set(statuses.keys())
|
|
all = True
|
|
|
|
ret = 0
|
|
for context in contexts:
|
|
status = statuses.get(context, { })
|
|
current_status = status.get("state", all and "unknown" or "empty")
|
|
|
|
if current_status not in ["empty", "error", "failure"]:
|
|
# allow changing if manual testing required, otherwise "pending" state indicates that testing is in progress
|
|
manual_testing = current_status == "pending" and status.get("description", None) == github.NO_TESTING
|
|
queued = current_status == "pending" and status.get("description", None) == github.NOT_TESTED_DIRECT
|
|
# also allow override with --force or --requeue
|
|
if not (manual_testing or opts.force) and not (queued and opts.requeue):
|
|
if not all:
|
|
sys.stderr.write("{0}: isn't in triggerable state (is: {1})\n".format(context, status["state"]))
|
|
ret = 1
|
|
continue
|
|
sys.stderr.write("{0}: triggering on pull request {1}\n".format(context, opts.pull))
|
|
changes = { "state": "pending", "description": github.NOT_TESTED_DIRECT, "context": context }
|
|
|
|
# Keep the old link for reference, until testing starts again
|
|
link = status.get("target_url", None)
|
|
if link:
|
|
changes["target_url"] = link
|
|
|
|
api.post("statuses/" + revision, changes)
|
|
|
|
return ret
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description='Manually trigger CI Robots')
|
|
parser.add_argument('-f', '--force', action="store_true",
|
|
help='Force setting the status even if the program logic thinks it shouldn''t be done')
|
|
parser.add_argument('-a', '--allow', action='store_true', dest='allow',
|
|
help="Allow triggering for users that aren't whitelisted")
|
|
parser.add_argument('--requeue', action="store_true",
|
|
help='Re-queue pending test requests (workaround for occasionally ignored webhook events)')
|
|
parser.add_argument('--repo', help="The repository to trigger the robots in", default=None)
|
|
parser.add_argument('pull', help='The pull request to trigger')
|
|
parser.add_argument('context', nargs='*', help='The github task context(s) to trigger')
|
|
opts = parser.parse_args()
|
|
|
|
api = github.GitHub(repo=opts.repo)
|
|
return trigger_pull(api, opts)
|
|
|
|
if __name__ == '__main__':
|
|
sys.exit(main())
|