CI/CD & GitHub Actions

Automate testing and validation of your Discord bot with CI/CD. Because every BotBox command has a headless mode, the CLI can run unattended inside a pipeline.


Installing BotBox in CI

Homebrew is the shortest path on a GitHub runner. go install works too if the job already needs Go.

- name: Install BotBox
  run: brew install choice404/tap/botbox

Checking Config Stays In Sync

A cog added by hand without updating botbox.conf will not load at runtime. This job catches that before it ships.

yaml
name: Validate BotBox Project

on:
  pull_request:

jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install BotBox
        run: brew install choice404/tap/botbox

      - name: Sync config
        run: botbox config sync --headless

      - name: Fail if botbox.conf changed
        run: git diff --exit-code botbox.conf

      - name: Print config
        run: botbox config --format json

Scaffolding a Project From a Workflow

Useful for template repos, or for testing the generator itself.

yaml
- name: Scaffold bot
  env:
    BOTBOX_TOKEN: ${{ secrets.DISCORD_TOKEN }}
  run: |
    botbox create --name MyBot \
      --description "Scaffolded in CI" \
      --author "ci" \
      --guild "${{ secrets.DISCORD_GUILD }}" \
      --force
⚠️ WARNING
Pass the token through BOTBOX_TOKEN rather than --token. Flags show up in the command echo of most CI logs, environment variables do not.

Testing Your Bot

yaml
name: Test Discord Bot

on:
  push:
    branches: [main]
  pull_request:

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      - name: Install dependencies
        run: python3 -m pip install -r requirements.txt

      - name: Import check
        env:
          DISCORD_TOKEN: ${{ secrets.DISCORD_TOKEN }}
          DISCORD_GUILD: ${{ secrets.DISCORD_GUILD }}
          ENVIRONMENTS: production
          LOG_LEVEL: DEBUG
        run: python3 -c "import sys; sys.path.insert(0, 'src'); import main"
📝 NOTE
Don't use a workflow to "deploy" by running python3 src/main.py. A Discord bot is a long lived process and a GitHub Actions job is not, so the runner kills it when the job hits its timeout. Deploy to a host that keeps the process alive instead, see Deploying Your Bot.

Tips

  • Store your token and guild ID in GitHub Actions secrets
  • Use Doppler for even more secure secret management
  • Set ENVIRONMENTS=production in CI so development-only cogs stay out of the run
  • Headless commands skip the update check, so pipelines never stall on the GitHub API

Next Steps