Starting Captain Hook
NOTE: Captain Hook can be run by itself, but is designed to run as part of the pod-webhooks docker pod. Instructions below are not guaranteed to work outside of the docker pod.
Captain Hook Docker "Pod"
To run Captain Hook, we utilize a Docker compose file to run the container that runs Captain Hook and mounts the correct directories in the correct locations.
See docker-compose.yml in the Captain Hook repository.
This is a one-container pod.
To start/stop/build it,
docker-compose up -d # start in background docker-compose down docker-compose build
To rebuild from scratch,
docker-compose build --no-cache
Startup Service: Captain Hook Docker Pod
In order to start the Captain Hook docker pod automatically
at startup, and automatically restart the pod if it crashes or
is stopped, we install a startup service called
[Unit] Description=captain hook webhook server docker pod Requires=docker.service After=docker.service [Service] Restart=always ExecStart=/usr/local/bin/docker-compose -f /home/charles/codes/bots/b-captain-hook/docker-compose.yml up ExecStop=/usr/local/bin/docker-compose -f /home/charles/codes/bots/b-captain-hook/docker-compose.yml down [Install] WantedBy=default.target
This startup service runs
docker-compose with the
-f flag to specify
an absolute path to the Captain Hook
Startup Service: Captain Hook Canary
Captain Hook listens for incoming web hooks and (optionally) runs a script in the
folder, based on the type of action, the name of the repository, and the
name of the branch.
However, there is one tricky task: Captain Hook must be able update itself when there are changes pushed to the Captain Hook repository.
To resolve this, we run a "canary" startup service for Captain Hook.
This canary startup service runs a shell script that checks (every 10 seconds)
for the presence of a file at
/tmp/triggers/. If this file is present, the
host copy of Captain Hook is updated, the Captain Hook docker pod is restarted,
and the trigger file is removed.
This allows webhooks received by Captain Hook (which occur inside of a Docker
container) to trigger an event on the host machine by bind-mounting
/tmp/triggers/ and adding a file to this directory.
[Unit] Description=captain hook canary script Requires=dockerpod-captainhook.service After=dockerpod-captainhook.service [Service] Restart=always ExecStart=/home/charles/blackbeard_scripts/captain_hook_canary.sh ExecStop=/usr/bin/pgrep -f captain_hook_canary | /usr/bin/xargs /bin/kill [Install] WantedBy=default.target
This script calls the Captain Hook canary script, which is given below:
#!/bin/bash : ' Captain Hook Canary Script Note: this needs an associated systemd service. See the services directory of the dotfiles repo. (snip comments) ' while true do # bootstrap-pull captain hook if [ -f "/tmp/triggers/push-b-captain-hook-master" ]; then echo "CAPTAIN HOOK'S CANARY:" echo "Running trigger to update Captain Hook on the host machine (user charles)" sudo -H -u charles python /home/charles/blackbeard_scripts/captain_hook_pull_host.py echo "All done." rm -f "/tmp/triggers/push-b-captain-hook-master" fi sleep 10; done
When this canary script for Captain Hook is triggered by the presence of
a file at
/tmp/triggers/push-b-captain-hook-master (which is mounted
inside the container at th same location as outside the container), it will
run a script to pull Captain Hook:
#!/usr/bin/env python3 import subprocess import os import time """ Captain Hook: Pull Captain Hook on the Host This script is called by the host machine (blackbeard) running the Captain Hook container. This is triggered by push actions to the master branch of b-captain-hook. The action is to update (git pull) the copy of captain hook running on the host, and restart the container pod. """ work_dir = os.path.join('/home','charles','codes','bots','b-captain-hook') # Step 1: # Update Captain Hook pull_cmd = ['git','pull','origin','master'] subprocess.call(pull_cmd, cwd=work_dir) time.sleep(5) # Step 2: # Restart Captain Hook pod pod_restart = ['docker-compose','restart'] subprocess.call(pod_restart, cwd=work_dir)