1
0
mirror of https://github.com/Adam-Ant/drone-trigger synced 2024-06-14 04:57:24 +00:00
drone-trigger/main.py

171 lines
6.1 KiB
Python

#!/usr/bin/python3
import os
import time
import argparse
from configobj import ConfigObj
import requests
import json
defaultconfig = '''[Connection]
# Specify the URL to the drone server, including port and protocol
host = https://drone.example.org
# Auth key found on your Drone account page
auth_key = eyJEXAMPLE.AUTH.KEY
# Time to wait between checks. Note that too low may ban you from the api, especially on GitHub
# Specified in seconds (Default: 300)
#sleep_time = 300
#[ExampleGitHubBuild]
# Example shown uses githubs api to find and compare on the sha of the latest commit
# Name of the repo to trigger in drone
#drone_repo = Example/HelloWorld
# Branch to use for deciding which drone build to fork and trigger (Default: master)
#branch = master
# URL of the json structure to check against
#url = https://api.github.com/repos/Kaylee/ShinyRepo/git/refs/heads/master
# JSON Tree needed to resolve the value.
#structure = object.sha
#[ExampleGitHubRelease]
#drone_repo = Example/HelloRelease
#branch = release
#url = https://api.github.com/repos/Kaylee/ShinyRepo/releases/latest
#structure = name
'''
def runbuild(repo: str, branch: str):
url = drone_host + '/api/repos/' + repo
latest = json.loads(requests.get(url + '/builds/latest', headers={'Authorization': drone_auth_key}).text)
build_num = False
if (latest['branch'] != branch):
while not build_num:
latest = json.loads(requests.get(url + '/builds/' + str(latest['number'] - 1), headers={'Authorization': drone_auth_key}).text)
if (latest['branch'] == branch):
build_num = str(latest['number'])
else:
build_num = str(latest['number'])
buildurl = url + '/builds/' + build_num + '?fork=true'
# [[TODO]] Add functionality for checking if build was triggered successfully?
return (requests.post(buildurl, headers={'Authorization': drone_auth_key}))
def jsonVal(url, struct):
try:
r = requests.get(url)
r.raise_for_status()
jsondata = r.text
except requests.HTTPError as e:
print('[' + time.strftime("%d/%m/%Y %H:%M:%S") + '] ERROR: Got Response code ' + str(e.response.status_code) + ' for URL ' + str(url))
raise e
try:
dataDict = json.loads(jsondata)
except json.decoder.JSONDecodeError as e:
# Probably Not Valid JSON?
print('[' + time.strftime("%d/%m/%Y %H:%M:%S") + '] ERROR: Could not decode JSON: ')
print(jsondata)
raise e
try:
for i in struct.split('.'):
if i.isdigit():
dataDict = dataDict[int(i)]
else:
dataDict = dataDict[i]
return dataDict
except:
print('Error: Invalid structure: ' + struct)
print(dataDict)
raise
if __name__ == '__main__':
argparser = argparse.ArgumentParser(
prog='DroneTrigger.py', description='Drone Triggerer triggers drone builds based on updates to arbitrary GitHub repos.')
argparser.add_argument(
'-c', '--config', help='Specify directory for config file')
cmdargs = argparser.parse_args()
if not (cmdargs.config):
filepath = '.'
else:
filepath = cmdargs.config
if not (os.path.isdir(filepath)):
print('Error: Config directory does not exist. Exiting...')
exit(1)
if not (os.path.isfile(filepath + '/dronetrigger.cfg')):
print('Warn: Config file does not exist, writing example config. Please configure and try again.')
c = open(filepath + '/dronetrigger.cfg', 'w')
c.write(defaultconfig)
c.close()
exit(78) # 78 is the exit code for invalid config
config = ConfigObj(filepath + '/dronetrigger.cfg')
if not ('Connection' in config):
print('Error: Connection block not found, please check your config')
exit(78)
if not (config['Connection'].get('host', False)) or not (config['Connection'].get('auth_key', False)):
print('Error: Missing connection details. please check your config')
exit(78)
if (len(config) < 2):
print('Error: Please configure some monitoring blocks!')
exit(78)
# These can be assumed since we have verified
drone_host = config['Connection']['host']
drone_auth_key = config['Connection']['auth_key']
sleep_time = int(config['Connection'].get('sleep_time', 300))
for service in config:
if service == 'Connection':
continue
if not (config[service].get('url', False)) or not (config[service].get('structure', False)) or not(config[service].get('drone_repo'), False):
print('Error: Missing required value in status block ' + service)
exit(78)
if not (config[service].get('current_value', False)):
try:
curr_value = jsonVal(config[service].get('url'), config[service].get('structure'))
except:
print('Error: Could not get current value for ' + service)
exit(1)
print('Writing Initial value for ' + service + ': ' + curr_value)
config[service]['current_value'] = curr_value
config.write()
while(True):
for service in config:
if service == 'Connection':
continue
try:
new_value = jsonVal(config[service].get('url'), config[service].get('structure'))
except:
continue
if (new_value != config[service]['current_value']):
print('[' + time.strftime("%d/%m/%Y %H:%M:%S") + '] Got new build - ' + new_value)
if not (config[service].get('branch', False)):
branch = 'master'
else:
branch = config[service]['branch']
if (runbuild(config[service].get('drone_repo'), branch)):
config[service]['current_value'] = new_value
with open(filepath + '/dronetrigger.cfg', 'w') as configfile:
config.write()
print('[' + time.strftime("%d/%m/%Y %H:%M:%S") + '] Successfully sent new build for ' + service)
time.sleep(sleep_time)