This bot is a Python based Discord bot built on top of the
discord.py
library.
It uses poetry
to manage dependencies. To install development
dependencies use: poetry install
. This will allow you to run
PyTest and the included scripts.
You can install poetry
with the script install-poetry.py
:
curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/install-poetry.py | python -
The easiest thing to do is to set up a virtual python environment specifically for spellbot.
python -m venv .venv
Then you can install poetry
into this environment with:
.venv/bin/pip install --upgrade pip
.venv/bin/pip install poetry
Now configure poetry
to use in the virtual environment we already created:
.venv/bin/poetry config virtualenvs.create false
.venv/bin/poetry env use .venv/bin/python
To make this easier I've also included a scripts/setup.sh
to do this automatically.
Install in development mode via poetry
:
source .venv/bin/activate
poetry install
Note: On some systems such as most Linux ones you may also need to install
python3-venv
using your system's package manager aspoetry
depends on it.
SpellBot requires a database to run properly. The connection string for the
database you want to use must be stored in the environment variable DATABASE_URL
.
You can start a local database via Docker by running:
docker run -i --rm -p 5432:5432 -e POSTGRES_HOST_AUTH_METHOD=trust postgres:15
Using this locally will allow you to use the default value for DATABASE_URL
without having to manually set it to anything.
Make sure that you have set up your environmental variables.
If you wish, you can use a .env file. Copy the .env.example
file to get started.
When your environmental variables are set, run:
source .venv/bin/activate
poetry run spellbot --help
This will list some useful flags you can provide to run SpellBot. To get started developing, run:
source .venv/bin/activate
poetry run spellbot --dev
This will start SpellBot and reload it whenever the source code changes.
source .venv/bin/activate
poetry run pytest --cov --cov-report=html
open coverage/index.html
Codebase consistency is maintained by ruff.
source .venv/bin/activate
poetry run pytest -k codebase
An interactive shell using IPyhton can be started by running:
poetry run python shell.py
From this shell you will be able to interact with the database using SpellBot models and code. For example:
$ poetry run python shell.py
In [1]: DatabaseSession.query(User).all()
Out[1]: []
There's two methods for doing a release. You can use a script to handle everything for you automatically, or you can basically do every step in that script manually. Both methods are described below but I recommend the script.
To do a release automatically there is a *NIX script available in the scripts
directory to help. To use it you will need to have non-interactive
poetry publish
enabled by running:
source .venv/bin/activate
poetry config pypi-token.pypi "YOUR-PYPI-TOKEN-GOES-HERE"
If you don't have one, you can create your PyPI token for this command by going
to the
PyPI settings for spellbot
and clicking on the Create a token for spellbot
button there. Of course you
will have to be a collaborator for this project on PyPI to be able to do this.
Contact spellbot@lexicalunit.com to be added
to the project.
Once you have that set up, you can release a new version by running:
scripts/publish.sh <major | minor | patch>
You must select either major
, minor
, or patch
as the release kind. Please
follow semver for guidance on what kind of release to
make. But basically:
- Major: Breaking changes.
- Minor: New features.
- Patch: Bug fixes.
To release a new version of spellbot
, use poetry
:
source .venv/bin/activate
poetry version [major|minor|patch]
poetry run pytest # verify that all tests pass
# edit the CHANGELOG.md file to promote all unlreased changes to the new version
poetry build
git commit -am "Release vM.N.P"
poetry publish
git tag 'vM.N.P'
git push --tags origin main
Note: The reason you should run
pytest
after running thepoetry version
command is to ensure that all test still pass after the version is updated.
You can get the M.N.P
version numbers from pyproject.toml
after you've run
the poetry version
command. On a *NIX shell you could also get it automatically like so:
grep "^version" < pyproject.toml | cut -d= -f2 | sed 's/"//g;s/ //g;s/^/v/;'
When you use the poetry publish
command you will be prompted for your
PyPI credentials.
After publishing you can view the package at its pypi.org project page to see that everything looks good.
We use alembic for database migrations. It can detect changes you've made compared to an existing database and generate migration scripts necessary to apply and reverse those changes. First, make the changes to the data models. Alembic can detect differences between an existing database and changes made to the models. To autogenerate migration scripts that will bring the database inline with the changes you've made to the models, run:
poetry run scripts/create_db_revision.py \
"<your-sqlalchemy-database-url>" \
"<Some description of your changes>"
Note: An example database url: postgresql://postgres@localhost:5432/postgres
This will create a revision script in the src/spellbot/versions/versions
directory with a name like REVISIONID_some_description_of_your_changes.py
.
You may have to edit this script manually to ensure that it is correct as
the autogenerate facility of alembic revision
is not perfect.
Another migration script is scripts/downgrade.py
which allows you to pass
a revision string to downgrade to. For example, to undo the last migration
you could run something like:
poetry run scripts/downgrade.py postgresql://postgres@localhost:5432/postgres "-1"
SpellBot is set up to integrate with DataDog for system and service metrics. This requires a few things:
-
In the container, we install and configure to run the following services:
-
A source dependency on the python Datadog APM Client: ddtrace.
-
Instrumentation of code using the
ddtrace
tracer interface. -
A deployment with the correct environment variables to configure
dd-agent
.DD_API_KEY
= Your DataDog API key.DD_APP_KEY
= Your DataDog application key.DD_AGENT_MAJOR_VERSION
= "7"DD_HOSTNAME
= "spellbot"DD_ENV
= "dev", "stage", or "prod"
-
A
datadog.yaml
file including the following configuration:apm_config: enabled: true apm_non_local_traffic: true
-
When starting the
spellbot
process, start it viaddtrace-run spellbot
so that the APM client hooks are properly installed.
Locally in development you can use the following invocation to quickly spin
up a dd-agent
. And to set up your environment you should use the .env
file.
docker run --rm \
--name dd-agent \
-p8125:8125 \
-p8126:8126 \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
-v /proc/:/host/proc/:ro \
-v /sys/fs/cgroup/:/host/sys/fs/cgroup:ro \
-e DD_API_KEY="Your DataDog API key" \
-e DD_APP_KEY="Your DataDog application key" \
-e DD_AGENT_MAJOR_VERSION="7" \
-e DD_SERVICE="spellbot" \
-e DD_HOSTNAME="localhost" \
-e DD_ENV="dev" \
gcr.io/datadoghq/agent:7