Skip to content

Commit

Permalink
Set up the bot to user kubernetes deployment
Browse files Browse the repository at this point in the history
With kubernetes deployment, a restart script is in place. So, the twilio client is no longer needs to notify the maintainer when the bot fails

Bug: T221331
Change-Id: I4dd15462efb0548e7d59e08d10494e8ab445a9c4
  • Loading branch information
srish committed Oct 16, 2019
1 parent 65f5572 commit c36ed4a
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 29 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ $ become gerrit-newcomer-bot
$ cd /www/python/src
```

This bot uses Kubernetes deployment process detailed here https://wikitech.wikimedia.org/wiki/Help:Toolforge/Kubernetes#Kubernetes_continuous_jobs. To restart the bot, delete the failing kubernetes pod and create the deployment following the steps below:
```
$ kubectl delete deployment gerrit-newcomer-bot.bot
$ kubectl create -f /data/project/gerrit-newcomer-bot/etc/gerrit-newcomer-bot.yaml
```

Credits
-------
* [Gerrit bot](http://code.google.com/p/gerritbot/) for the initial source
Expand Down
80 changes: 80 additions & 0 deletions gerrit-newcomer-bot.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#!/usr/bin/env bash
#
# Management script for gerrit-newcomer-bot kubernetes processes
#
# This file should be placed in the tool directory:
# `/data/project/gerrit-newcomer-bot/bin`

set -e

DEPLOYMENT=gerrit-newcomer-bot.bot
POD_NAME=gerrit-newcomer-bot.bot

TOOL_DIR=$(cd $(dirname $0)/.. && pwd -P)
VENV=${TOOL_DIR}/www/python/venv/
if [[ -f ${VENV}/bin/activate ]]; then
# Enable virtualenv
echo "Setting up virtualenv..."
source ${VENV}/bin/activate
else
echo "Virtualenv not found!"
echo "Expected it to be in ${VENV}"
echo "I'm going to stop and let you fix that."
exit 1
fi
# Uncomment to debug packages installed in the venv
# which python3
# pip3 list
# exit

_get_pod() {
kubectl get pods \
--output=jsonpath={.items..metadata.name} \
--selector=name=${POD_NAME}
}

case "$1" in
start)
echo "Starting gerrit-newcomer-bot k8s deployment..."
kubectl create -f ${TOOL_DIR}/etc/gerrit-newcomer-bot.yaml
;;
run)
echo "Running gerrit-newcomer-bot..."
cd ${TOOL_DIR}/www/python/src/
exec ${VENV}/bin/python3 watch_newcomers.py
;;
stop)
echo "Stopping gerrit-newcomer-bot k8s deployment..."
kubectl delete deployment ${DEPLOYMENT}
;;
restart)
echo "Restarting gerrit-newcomer-bot k8s deployment..."
$0 stop &&
$0 start
;;
status)
echo "Active pods:"
kubectl get pods -l name=${POD_NAME}
;;
tail)
exec kubectl logs -f $(_get_pod)
;;
update)
echo "Updating git clone..."
cd ${TOOL_DIR}/www/python/src/
git fetch &&
git --no-pager log --stat HEAD..@{upstream} &&
git rebase @{upstream}
;;
attach)
echo "Attaching to pod..."
exec kubectl exec -i -t $(_get_pod) /bin/bash
;;
*)
echo "Usage: $0 {start|stop|restart|status|tail|update|attach}"
exit 1
;;
esac

exit 0
# vim:ft=sh:sw=4:ts=4:sts=4:et:
34 changes: 34 additions & 0 deletions gerrit-newcomer-bot.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
# Run gerrit-newcomer-bot on kubernetes
#
# This file should be placed in the tool directory:
# `/data/project/gerrit-newcomer-bot/etc`
#
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: gerrit-newcomer-bot.bot
namespace: gerrit-newcomer-bot
spec:
replicas: 1
template:
metadata:
labels:
name: gerrit-newcomer-bot.bot
spec:
containers:
- name: bot
image: docker-registry.tools.wmflabs.org/toollabs-python35-base:latest
command: [ "/data/project/gerrit-newcomer-bot/bin/gerrit-newcomer-bot.sh", "run" ]
workingDir: /data/project/gerrit-newcomer-bot
env:
- name: HOME
value: /data/project/gerrit-newcomer-bot
imagePullPolicy: Always
volumeMounts:
- name: home
mountPath: /data/project/gerrit-newcomer-bot/
volumes:
- name: home
hostPath:
path: /data/project/gerrit-newcomer-bot/
5 changes: 0 additions & 5 deletions gerrit.conf.example
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,3 @@ auth_username =
auth_password =
base_url = https://gerrit.git.wmflabs.org/r/

[Twilio]
account_sid =
auth_token =
from_num =
to_num =
30 changes: 6 additions & 24 deletions watch_newcomers.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import requests
from requests.auth import HTTPBasicAuth
from pygerrit2.rest import GerritRestAPI
from twilio.rest import TwilioRestClient

QUEUE = queue.Queue()

Expand All @@ -44,39 +43,30 @@

MISC = dict()
MISC.update(CONFIG.items('Misc'))

TWILIO = dict()
TWILIO.update(CONFIG.items('Twilio'))

# Paramiko client
SSH_CLIENT = paramiko.SSHClient()
HOSTKEY_PATH = os.path.join(DIR, 'ssh-host-key')
SSH_CLIENT.load_host_keys(HOSTKEY_PATH)
SSH_CLIENT.set_missing_host_key_policy(paramiko.AutoAddPolicy())
SSH_CLIENT.connect(**GERRIT_SSH)

# Rest client
REST_AUTH = HTTPBasicAuth(MISC['auth_username'], MISC['auth_password'])
REST_CLIENT = GerritRestAPI(url=MISC['base_url'], auth=REST_AUTH)

# Twilio client
TWILIO_CLIENT = TwilioRestClient(TWILIO['account_sid'], TWILIO['auth_token'])

class WatchPatchsets(threading.Thread):
"""This class watches gerrit stream event patchset-created
"""
def run(self):
while True:
SSH_CLIENT = paramiko.SSHClient()
SSH_CLIENT.load_host_keys(HOSTKEY_PATH)
SSH_CLIENT.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
SSH_CLIENT.connect(**GERRIT_SSH)
cmd_patchset_created = 'gerrit stream-events -s patchset-created'
_, stdout, _ = SSH_CLIENT.exec_command(cmd_patchset_created)
for line in stdout:
QUEUE.put(json.loads(line))
except BaseException as err:
e = 'Error occured while watching event: %s', err
logging.debug(e)
TWILIO_CLIENT.messages.create(from_=TWILIO['from_num'], to=TWILIO['to_num'], body='Error watching event')
sys.exit(1)
os.system("sh /data/project/gerrit-newcomer-bot/bin/gerrit-newcomer-bot.sh restart")
finally:
SSH_CLIENT.close()
time.sleep(5)
Expand Down Expand Up @@ -113,7 +103,6 @@ def identify(self, submitter):
except BaseException as err:
e = 'Error occured while identifying patch owner: %s', err
logging.debug(e)
TWILIO_CLIENT.messages.create(from_=TWILIO['from_num'], to=TWILIO['to_num'], body=e)

def is_first_time_contributor(self):
""" Returns first_time_contributor as boolean
Expand Down Expand Up @@ -143,7 +132,6 @@ def add_reviewer_and_comment(self, change_id, cur_rev):
except BaseException as err:
e = 'Error occured while adding reviewer and welcome comment: %s', err
logging.debug(e)
TWILIO_CLIENT.messages.create(from_=TWILIO['from_num'], to=TWILIO['to_num'], body=e)

def add_to_group(self, username):
""" Adds newcomer to a group
Expand All @@ -155,7 +143,6 @@ def add_to_group(self, username):
except BaseException as err:
e = 'Error occured while adding newcomer to group: %s', err
logging.debug(e)
TWILIO_CLIENT.messages.create(from_=TWILIO['from_num'], to=TWILIO['to_num'], body=e)

def remove_from_group(self, username):
""" Removes newcomer from a group
Expand All @@ -168,7 +155,6 @@ def remove_from_group(self, username):
except BaseException as err:
e = 'Error occured while removing newcomer from group: %s', err
logging.debug(e)
TWILIO_CLIENT.messages.create(from_=TWILIO['from_num'], to=TWILIO['to_num'], body=e)

def is_rising_contributor_in_group(self, username):
""" Check if rising contributor is member of newcomer group
Expand All @@ -186,7 +172,6 @@ def is_rising_contributor_in_group(self, username):
except BaseException as err:
e = 'Error listing members of newcomer group: %s', err
logging.debug(e)
TWILIO_CLIENT.messages.create(from_=TWILIO['from_num'], to=TWILIO['to_num'], body=e)

def is_reviewer_added_already(self, change_id):
""" Check if newcomer bot is already added as a reviewer to a patch
Expand All @@ -204,7 +189,6 @@ def is_reviewer_added_already(self, change_id):
except BaseException as err:
e = 'Error occured while querying change details: %s', err
logging.debug(e)
TWILIO_CLIENT.messages.create(from_=TWILIO['from_num'], to=TWILIO['to_num'], body=e)

def fetch_welcome_message(self):
""" Fetch welcome message from a remote wiki page
Expand All @@ -221,17 +205,15 @@ def fetch_welcome_message(self):
def main(event):
""" Invokes functions of class 'WelcomeNewcomersAndGroupThem'
"""
logging.info('Patch details: %s', event)

username = event['patchSet']['author']['username']
logging.info('Patch has been uploaded by user: %s', username)
change_id = event['change']['id']
revision = event['patchSet']['revision']

newcomer = WelcomeNewcomersAndGroupThem()
newcomer.identify(username)

logging.info('Patch has been uploaded by user: %s', username)

if newcomer.is_first_time_contributor():
logging.info('Patch owner is a first time contributor')
newcomer.add_reviewer_and_comment(change_id, revision)
Expand Down

0 comments on commit c36ed4a

Please sign in to comment.