diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 20ca13d..921e11e 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -6,13 +6,37 @@ on: - main tags: - 'v*.*.*' + pull_request: permissions: contents: read packages: write jobs: + test: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.12' + + - name: Install dependencies + run: pip install --no-cache-dir -r requirements-dev.txt + + - name: Import smoke test (catch circular imports) + run: python -c "import hutbot, hutbot.state, hutbot.actions, hutbot.buttons, hutbot.scheduling, hutbot.routing, hutbot.commands.dispatch, hutbot.webui_backend" + + - name: Run tests + run: python -m pytest + build-and-push: + needs: test + if: github.event_name == 'push' runs-on: ubuntu-latest steps: @@ -36,4 +60,4 @@ jobs: push: true tags: | ghcr.io/mittwald/hutbot:latest - ghcr.io/mittwald/hutbot:${{ github.ref_name }} \ No newline at end of file + ghcr.io/mittwald/hutbot:${{ github.ref_name }} diff --git a/.gitignore b/.gitignore index 6ea8b91..f38c313 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ employees.json .env .codex scheduled_replies.json +button_states.json diff --git a/Dockerfile b/Dockerfile index 4375039..3f9bfd5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,4 +8,6 @@ RUN pip install --no-cache-dir -r requirements.txt COPY . . -ENTRYPOINT ["python", "bot.py"] +EXPOSE 8080 + +ENTRYPOINT ["python", "-m", "hutbot"] diff --git a/README.md b/README.md index 6a27b4c..d83d117 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,168 @@ Opsgenie alert priority defaults to `P4` and can be configured per channel confi /hutbot [config] set opsgenie-priority ``` +## Triggers, conditions, and actions + +Beyond the classic "reply if a message goes unanswered" behavior, each named config is a **rule** +with a `trigger`, an optional `condition`, and an `action`. The trigger defaults to `message`, so +existing configs keep working unchanged. + +- **Triggers** (`/hutbot [config] set trigger `) + - `message` — the classic behavior (matches channel messages by pattern/teams/hours). + - `schedule` — fires on a cron schedule. Set it with `set cron ""` (5-field cron, e.g. + `0 9 * * 1-5`) and optionally `set schedule-timezone `. + - `manual` — never fires on its own; used as the target of a button or a button timeout. + +- **Conditions** (`/hutbot [config] set condition `) gate a `schedule` trigger. + - `outlook` — matches Outlook calendar entries by `set outlook-subject ` / + `set outlook-body `. Use `enable negate` to fire when *no* matching entry exists. + **Note:** the Outlook integration is currently a stub (events come from the + `HUTBOT_OUTLOOK_STUB_EVENTS` env var); the real implementation lands in a later task. + +- **Actions** (`/hutbot [config] set action `) decide what the + rule does, using `reply_message` (with the usual `{{variables}}`) as the body. + - `reply` — post in the rule's channel. + - `dm-user` — DM a single user. Set the recipient with `set target <@user>`. + - `group-dm` — open one group DM (mpim) with all members of a Slack user group and post once. + Set the group with `set target <@usergroup>` (Slack caps a group DM at 8 members). + - `post-channel` — post to another channel. Set it with `set target <#channel>`. + +- **Buttons** attach interactive buttons to the message a rule sends (including the classic + unanswered-message reply). Each button is added incrementally with a typed action: + - `/hutbot [config] add button "