Skip to content

Commit

Permalink
Update rotation (#70)
Browse files Browse the repository at this point in the history
  • Loading branch information
pilosus committed Jun 3, 2023
1 parent 4f83b02 commit 090938e
Show file tree
Hide file tree
Showing 15 changed files with 387 additions and 107 deletions.
15 changes: 14 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,18 @@ file. This change log follows the conventions of

## [Unreleased]

## [0.4.0] - 2023-06-03
### Added
- `update` command to update rotation's list of mentions and
description. Watch out! The command overrides current on-call person
even if the new list of mentions is the same as in original
rotation. Consider the command to be a shortcut to a sequence of
`delete` and `create` commands for the same rotation name.
([#66](https://github.com/pilosus/dienstplan/issues/66))

### Changed
- Local development migrated to `docker-compose` v2.

## [0.3.0] - 2022-10-30
### Changed
- Base docker images for production and testing moved to Linux
Expand Down Expand Up @@ -162,7 +174,8 @@ file. This change log follows the conventions of
### Added
- Bot app MVP

[Unreleased]: https://github.com/pilosus/dienstplan/compare/0.3.0...HEAD
[Unreleased]: https://github.com/pilosus/dienstplan/compare/0.4.0...HEAD
[0.4.0]: https://github.com/pilosus/dienstplan/compare/0.3.0...0.4.0
[0.3.0]: https://github.com/pilosus/dienstplan/compare/0.2.12...0.3.0
[0.2.12]: https://github.com/pilosus/dienstplan/compare/0.2.11...0.2.12
[0.2.11]: https://github.com/pilosus/dienstplan/compare/0.2.10...0.2.11
Expand Down
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
### Build stage ###
###################

FROM clojure:temurin-17-lein-alpine@sha256:37968e7afb62937499c3773e9b713400da4abb358e6beb0ec9bae41a59715111 AS build
FROM clojure:temurin-17-lein-alpine AS build

# Create a working directory
RUN mkdir -p /usr/src/app
Expand All @@ -28,7 +28,7 @@ RUN mv "$(lein uberjar | sed -n 's/^Created \(.*standalone\.jar\)/\1/p')" app.ja
### Run stage ###
#################

FROM eclipse-temurin:17-jre-alpine@sha256:e1506ba20f0cb2af6f23e24c7f8855b417f0b085708acd9b85344a884ba77767 AS run
FROM eclipse-temurin:17-jre-alpine AS run

# Create app directory for unpriviledged user
RUN mkdir -p /usr/src/app
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile-test
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM clojure:temurin-17-lein-alpine@sha256:37968e7afb62937499c3773e9b713400da4abb358e6beb0ec9bae41a59715111
FROM clojure:temurin-17-lein-alpine
RUN mkdir -p /usr/src/app
COPY project.clj /usr/src/app/
WORKDIR /usr/src/app
Expand Down
16 changes: 8 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,25 @@
all: build up migrate lint test

build:
docker-compose build
docker compose build

up:
docker-compose up -d
docker compose up -d

down:
docker-compose down
docker compose down

lint:
docker-compose run --rm dienstplan lein cljfmt fix
docker compose run --rm dienstplan lein cljfmt fix

test:
docker-compose run --rm --no-deps dienstplan lein test ${TEST_ARGS}
docker compose run --rm --no-deps dienstplan lein test ${TEST_ARGS}

cloverage:
docker-compose run --rm dienstplan lein cloverage ${TEST_ARGS}
docker compose run --rm dienstplan lein cloverage ${TEST_ARGS}

migrate:
docker-compose run --rm --no-deps dienstplan lein run --mode migrate
docker compose run --rm --no-deps dienstplan lein run --mode migrate

rollback:
docker-compose run --rm --no-deps dienstplan lein run --mode rollback
docker compose run --rm --no-deps dienstplan lein run --mode rollback
13 changes: 9 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,17 @@ Commands:
@dienstplan delete <rotation name>
```

8. List channel's rotations
8. Update a rotation
```
@dienstplan update <rotation name> <list of user mentions> <duties description>
```

9. List channel's rotations
```
@dienstplan list
```

9. Show a help message
10. Show a help message
```
@dienstplan help
```
Expand All @@ -127,8 +132,8 @@ Commands:

### Server requirements

- Any server with Java 17 or higher (tested with [Eclipse Temurin 17.0.4.1](https://whichjdk.com/#adoptium-eclipse-temurin))
- PostgreSQL 9.4 to 14.5 (as of 2022-10-29 PostgreSQL 15 is not tested yet)
- Any server with Java 17 or higher
- PostgreSQL 9.4 to 15.3
- (Optionally) [Sentry account](https://sentry.io/) for error tracking

### Environment variables
Expand Down
4 changes: 3 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
version: "3.9"
services:
postgres:
image: postgres:14.5-alpine3.16@sha256:db802f226b620fc0b8adbeca7859eb203c8d3c9ce5d84870fadee05dea8f50ce
image: postgres:15.3-alpine3.18
ports:
- "15432:5432"
volumes:
- "/tmp/diestplan-db-data:/var/lib/postgresql/data"
env_file:
Expand Down
38 changes: 22 additions & 16 deletions project.clj
Original file line number Diff line number Diff line change
@@ -1,50 +1,56 @@
(defproject dienstplan "0.3.0"
(defproject dienstplan "0.4.0"
:description "Duty rotation slack bot"
:url "https://github.com/pilosus/dienstplan"
:license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0"
:url "https://www.eclipse.org/legal/epl-2.0/"}
:dependencies [
;; Clojure
[org.clojure/clojure "1.10.3"]
[org.clojure/tools.cli "1.0.206"]
[org.clojure/clojure "1.11.1"]
[org.clojure/tools.cli "1.0.219"]

;; Web Framework
[ring/ring-core "1.9.4"]
[ring/ring-jetty-adapter "1.9.4"]
[ring/ring-core "1.10.0"]
[ring/ring-jetty-adapter "1.10.0"]
[ring/ring-json "0.5.1"]

;; Routing
[bidi "2.1.6"]

;; Logging
[org.clojure/tools.logging "1.2.1"]
[ch.qos.logback/logback-classic "1.2.6"]
[org.clojure/tools.logging "1.2.4"]
[ch.qos.logback/logback-classic "1.4.7"]

;; Alerts
[io.sentry/sentry-clj "5.2.158"]
;; FIXME version 6 and its underlying Java SDK seem to rely on jdk.unsupported
;; that aren't in temurin JRE 17
[io.sentry/sentry-clj "5.7.180"]
;; In sentry-clj 5.5.165 dsn string must be non-blank
;; in the presense of context map:
;; https://github.com/getsentry/sentry-clj/compare/5.5.164...5.5.165#diff-e3b4ff05b98b80c7fa2082652c8510acf99a4bbf293d3e035b703b9720f4ca90R253
;; [io.sentry/sentry-clj "5.5.164"]

;; Validation
[expound "0.8.10"]
[expound "0.9.0"]

;; Config managements
[exoscale/yummy "0.2.11"]
[mount "0.1.16"]
[mount "0.1.17"]

;; HTTP client
[clj-http "3.12.3"]

;; JSON parsing
[cheshire "5.10.1"]
[cheshire "5.11.0"]

;; DB
[org.clojure/java.jdbc "0.7.12"]
[org.postgresql/postgresql "42.2.20.jre7"]
[hikari-cp "2.13.0"]
[dev.weavejester/ragtime "0.9.0"]
[com.github.seancorfield/honeysql "2.2.861"]
[org.postgresql/postgresql "42.6.0"]
[hikari-cp "3.0.1"]
[dev.weavejester/ragtime "0.9.3"]
[com.github.seancorfield/honeysql "2.4.1026"]

;; Cryptography
[buddy/buddy-core "1.10.1"]]
[buddy/buddy-core "1.11.418"]]
:plugins [[lein-cljfmt "0.8.0"]
[lein-cloverage "1.2.2"]
[lein-licenses "0.2.2"]
Expand Down
66 changes: 59 additions & 7 deletions src/dienstplan/commands.clj
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,17 @@ Commands:
@dienstplan delete <rotation name>
```
8. List channel's rotations
8. Update a rotation
```
@dienstplan update <rotation name> <list of user mentions> <duties description>
```
9. List channel's rotations
```
@dienstplan list
```
9. Show a help message
10. Show a help message
```
@dienstplan help
```
Expand Down Expand Up @@ -127,6 +132,17 @@ On-call engineer's duties:
- Follow the boy scout rule: always leave the campground cleaner than you found it
```")

(def help-cmd-update
"Usage:
```
@dienstplan update <rotation name> <list of user mentions> <duties description>
```
Example:
```
@dienstplan update my-rota @user1 @user2 @user3 My updated description of the existing rota
```")

(def help-cmd-rotate
"Usage:
```
Expand Down Expand Up @@ -214,8 +230,10 @@ Example:
#"^[^<@]*(?s)(?<userid><@[^>]+>)[\u00A0|\u2007|\u202F|\s]+(?<command>\w+)[\u00A0|\u2007|\u202F|\s]*(?<rest>.*)")

(def commands->data
{:create {:spec ::spec/bot-cmd-create
{:create {:spec ::spec/bot-cmd-create-or-update
:help help-cmd-create}
:update {:spec ::spec/bot-cmd-create-or-update
:help help-cmd-update}
:rotate {:spec ::spec/bot-cmd-default
:help help-cmd-rotate}
:assign {:spec ::spec/bot-cmd-assign
Expand Down Expand Up @@ -350,19 +368,29 @@ Example:
"Parse command arguments for app mention"
(fn [command-parsed] (get command-parsed :command)))

(defmethod parse-args :create [command-parsed]
(defn parse-args-create-or-update-cmd
[command-parsed]
(let [args (get-command-args command-parsed)
splitted (string/split args regex-user-mention)
rotation (->
(first splitted)
str-trim
nilify)
description (->> (last splitted) str-trim)
users (parse-user-mentions args)]
users (parse-user-mentions args)
;; without user mentions description will be erroneously
;; matched against rota name.
;; description without mentions doesn't make any sense
description (when users (->> (last splitted) str-trim))]
{:rotation rotation
:users users
:description description}))

(defmethod parse-args :create [command-parsed]
(parse-args-create-or-update-cmd command-parsed))

(defmethod parse-args :update [command-parsed]
(parse-args-create-or-update-cmd command-parsed))

(defmethod parse-args :assign [command-parsed]
(let [args (get-command-args command-parsed)
splitted (string/split args regex-user-mention)
Expand Down Expand Up @@ -442,7 +470,7 @@ Example:
(defmethod command-exec! :shout [command-map]
(let [{:keys [channel rotation]} (get-channel-rotation command-map)
rota (first (db/duty-get channel rotation))
{:keys [duty description]} rota
{:keys [duty]} rota
text
(or
duty
Expand Down Expand Up @@ -512,6 +540,30 @@ Example:
rotation channel-formatted))]
result))

(defmethod command-exec! :update [command-map]
(let [now (get-now-ts)
{:keys [channel rotation]} (get-channel-rotation command-map)
channel-formatted (slack-mention-channel channel)
users (get-in command-map [:args :users])
mentions (users->mention-table-rows users)
rota-params {:channel channel
:name rotation
:description (get-in command-map [:args :description])
:updated_on now}
updated (db/rota-update! {:rota rota-params :mention mentions})
error-msg (get-in updated [:error :message])
result
(if (:ok updated)
(format
"Rotation `%s` for channel %s updated successfully"
rotation channel-formatted)
(do
(log/error error-msg)
(format
"Cannot update rotation `%s` for channel %s: %s"
rotation channel-formatted error-msg)))]
result))

(defmethod command-exec! :list [command-map]
(let [{:keys [channel _]} (get-channel-rotation command-map)
channel-formatted (slack-mention-channel channel)
Expand Down
3 changes: 2 additions & 1 deletion src/dienstplan/core.clj
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@
app-name (get-in config [:application :name])
version (get-in config [:application :version])
release (format "%s:%s" app-name version)]
(sentry/init! dsn {:environment env :debug debug :release release}))
(when (not debug)
(sentry/init! dsn {:environment env :debug debug :release release})))
:stop (sentry/close!))

(defstate server
Expand Down
26 changes: 26 additions & 0 deletions src/dienstplan/db.clj
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,32 @@
error)))]
result)))

(defn rota-update!
[params]
(jdbc/with-db-transaction [conn db]
(try
(let
[rota
(jdbc/query
conn
(sql/format
{:select [[:r/id :rota_id]]
:from [[:rota :r]]
:where [:and
[:= :r/channel (get-in params [:rota :channel])]
[:= :r/name (get-in params [:rota :name])]]
:for [:update]}
sql-params))
rota-id (-> rota first :rota_id)
mention-params (map #(assoc % :rota_id rota-id) (:mention params))]
(when (not rota-id) (throw (ex-info "Rotation not found" {})))
(jdbc/update! conn :rota (:rota params) ["id = ?" rota-id])
(jdbc/delete! db :mention ["rota_id = ?" rota-id])
(jdbc/insert-multi! conn :mention mention-params)
{:ok true})
(catch Exception e
{:ok false :error {:message (.getMessage e)}}))))

(defn- assign
[users next-duty]
(if (not (some #{next-duty} users))
Expand Down
Loading

0 comments on commit 090938e

Please sign in to comment.