Deployment uses dokku
and requires the environment variables defined
below.
It is deployed to our dokku3
instance automatically via GitHub actions.
It runs as a single dokku app named bennettbot
, with multiple processes for each
service (bot, dispatcher and webserver) as defined in the Procfile
.
(This should only need to be done once).
bennettbot needs a new-style Slack app and uses socket mode to listen for messages. To create one:
- visit https://api.slack.com/apps
- Click the "Create new app" button and choose the "From scratch" option
- Name the app and select the Bennett Institute workspace to develop it in. After creating the app, you'll be dropped into the app's page.
- Settings > Socket Mode
- Enable Socket Mode; this will create the app token. Give the token a name and accept
the default scope assigned (
connections:write
). - Go to Settings > Basic information, and under App Level Tokens you'll now see the token
you just created. This token starts
xapp-
and should be the value set for theSLACK_APP_TOKEN
environment variable
Add event subscriptions to allow the app to be notified of events in Slack/
- Features > Event subscriptions; toggle on
- In Subscribe to bot events, add the following events:
- message.channels
- message.groups
- message.im
- message.mpim
- channel_created
- app_mention
- Save changes
Adding the event subscriptions above automatically adds the required oauth scopes for the events. We need to add some more:
- Features > OAuth & Permissions: scroll down to Scopes
You should see the following Bot Token Scopes already assigned:
channels:history
groups:history
im:history
mpim:history
channels:read
app_mentions:read
- Add the following additional scopes:
channels:join
users:read
groups:read
mpim:read
im:read
reactions:write
chat:write
files:write
We need a User token for the app in order to search slack messages:
- Features > OAuth & Permissions: scroll down to Scopes. User Token Scopes are found after the Bot Token Scopes. By default the app has no user scopes.
- Add the following scopes:
search:read
- Features > App Home
- Under Messages Tabs, ensure the "Allow users to send Slash commands and messages from the messages tab" is ticked.
- Features > OAuth & Permissions
- Under "OAuth Tokens for Your Workspace", click "Install to Workspace"
- This will generate the bot token (starts
xoxb-
) and the user token (startsxoxp-
)
If you update any scopes after installing the app, you'll need to reinstall it (slack will usually prompt for this).
(This should only need to be done once).
$ dokku apps:create bennettbot
$ mkdir -p /var/lib/dokku/data/storage/bennettbot/logs
$ mkdir -p /var/lib/dokku/data/storage/bennettbot/workspace
$ dokku storage:mount bennettbot /var/lib/dokku/data/storage/bennettbot/:/storage
This is done using the ansible playbook in https://github.com/ebmdatalab/sysadmin/blob/main/infra
.
See https://github.com/ebmdatalab/sysadmin/blob/main/infra/README.md for more details.
To run just the bennettbot tasks:
just test dokku3 --tags bennettbot
And if all looks OK:
just apply dokku3 --tags bennettbot
This will create the bennettbot user on dokku3 and chown any mounted volumes.
Create an ssh key for the bennettbot user, in the usual $HOME/.ssh/ location.
Mount the user's home directory into the app.
$ dokku storage:mount bennettbot /home/bennettbot/:/home/bennettbot
Add the bennettbot user's key to any servers that it requires access to
(i.e. any jobs that run fab
commands).
See also comments in bennettbot/settings.py
.
The following slack environment variables need to be set:
SLACK_LOGS_CHANNEL
: channel where scheduled job notifications will be postedSLACK_BENNETT_ADMINS_CHANNEL
: channel where bennett-admins requests will be repostedSLACK_TECH_SUPPORT_CHANNEL
: channel where tech-support requests will be repostedSLACK_APP_TOKEN
: app-level token generated above (startsxapp-
); found on the app's Basic Information pageSLACK_BOT_TOKEN
: bot token generated above (startsxoxb-
); found on the app's Oauth and Permissions pageSLACK_BOT_USER_TOKEN
: user token generated above (startsxoxp-
); found on the app's Oauth and Permissions pageSLACK_SIGNING_SECRET
: Found on the app's Basic Information page, under App CredentialsSLACK_APP_USERNAME
: The app's default name (and the name users will refer to the Bot as in Slack); found under Features > App Home
The following webhook environment variables need to be set. These relate to callbacks from OpenPrescribing, and are configured at https://github.com/bennettoxford/openprescribing/settings/hooks/85994427.
GITHUB_WEBHOOK_SECRET
WEBHOOK_ORIGIN
The following environment variable allows the bot to authenticate with Github to retrieve project information.
DATA_TEAM_GITHUB_API_TOKEN
: Note that this must be a classic PAT (not fine-grained) and needs therepo
andread:project
scope
This is the path to credentials for the [email protected] service account:
GCP_CREDENTIALS_PATH
The path for logs; set this to a directory in the dokku mounted storage so the logs persist outside of the containers.
LOGS_DIR
Also set the alias for the logs dir to the location of the mounted volume on the host, for error reportingHOST_LOGS_DIR
The path for the sqlite db file; set this to a file in the dokku mounted storage
DB_PATH
A path to a directory that jobs can write files to. Set this to a directory in the dokku mounted storage that the docker user will have write access to.
WRITEABLE_DIR
Path for file created after bot startup (used in the bot healthcheck in app.json
).
BOT_CHECK_FILE
Set each env varible with:
$ dokku config:set bennettbot ENVVAR_NAME=value
e.g.
$ dokku config:set bennettbot LOGS_DIR=/storage/logs
$ dokku config:set bennettbot HOST_LOGS_DIR=/var/lib/dokku/data/storage/bennettbot/logs
$ dokku config:set bennettbot DB_PATH=/storage/bennettbot.db
$ dokku config:set bennettbot FAB_WORKSPACE_DIR=/storage/workspace
$ dokku config:set bennettbot BOT_CHECK_FILE=/storage/.bot_startup_check
https://dokku.com/docs/networking/port-management/
dokku ports:add bennettbot http:9999:9999
Merges to the main
branch will trigger an auto-deploy via GitHub actions.
Note this deploys by building the prod docker image (see docker/docker-compose.yaml
) and using the dokku git:from-image command.
To deploy manually:
# build prod image locally
just docker/build prod
# tag image and push
docker tag bennettbot ghcr.io/bennettoxford/bennettbot:latest
docker push ghcr.io/bennettoxford/bennettbot:latest
# get the SHA for the latest image
SHA=$(docker inspect --format='{{index .RepoDigests 0}}' ghcr.io/bennettoxford/bennettbot:latest)
On dokku3:
$ dokku git:from-image bennettbot <SHA>