From 849d6ea55f1cb6e9185237c283436c55cbec25f0 Mon Sep 17 00:00:00 2001 From: Lukas Forst Date: Mon, 30 Aug 2021 23:05:32 +0200 Subject: [PATCH 1/6] update dependencies and readme --- Dockerfile | 4 +- Makefile | 18 +- README.md | 55 +++-- build.gradle.kts | 19 +- docker-compose.yml | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 207 +++++++++--------- .../bots/polls/setup/EnvConfigVariables.kt | 2 +- 8 files changed, 161 insertions(+), 148 deletions(-) diff --git a/Dockerfile b/Dockerfile index 9c81b8e..c6881c5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM adoptopenjdk/openjdk11:jdk-11.0.6_10-alpine AS build +FROM adoptopenjdk/openjdk11:alpine-jdk AS build LABEL description="Wire Poll Bot" LABEL project="wire-bots:polls" @@ -21,7 +21,7 @@ COPY . $PROJECT_ROOT RUN ./gradlew distTar --no-daemon # Runtime -FROM adoptopenjdk/openjdk11:jre-11.0.6_10-alpine +FROM adoptopenjdk/openjdk11:alpine-jre ENV APP_ROOT /app WORKDIR $APP_ROOT diff --git a/Makefile b/Makefile index 47696d3..ecbefc8 100644 --- a/Makefile +++ b/Makefile @@ -8,22 +8,10 @@ up: docker-compose up -d db && docker-compose up bot docker-run: - docker run --rm -p 8080:8080 lukaswire/polls + docker run --rm -p 8080:8080 quay.io/wire/poll-bot docker-build: - docker build -t lukaswire/polls:latest . + docker build -t quay.io/wire/poll-bot:latest . publish: docker-build - docker push lukaswire/polls:latest - -kube-deploy: - kubectl delete pod -l name=poll -n staging - -kube-logs: - kubectl logs --follow -l name=poll -n staging - -kube-describe: - kubectl describe pods -l name=poll -n staging - -kube-prod-logs: - kubectl logs --follow -l name=poll -n prod + docker push quay.io/wire/poll-bot:latest diff --git a/README.md b/README.md index 4a1b22f..3abf18f 100644 --- a/README.md +++ b/README.md @@ -14,33 +14,37 @@ Service code to enable Poll bot in your team: ## Commands Basic usage * `/poll "Question" "Option 1" "Option 2"` will create poll -* `/stats` will send result of the last poll in the conversation +* `/stats` will send result of the **last** poll in the conversation * `/help` to show help +* `/version` prints the current version of the poll bot - -## Dev Stack +## Technologies used * HTTP Server - [Ktor](https://ktor.io/) * HTTP Client - [Apache](https://ktor.io/clients/http-client/engines.html) under [Ktor](https://ktor.io/) * Dependency Injection - [Kodein](https://github.com/Kodein-Framework/Kodein-DI) * Build system - [Gradle](https://gradle.org/) * Communication with [Wire](https://wire.com/) - [Roman](https://github.com/dkovacevic/roman) -Bot can connect to web socket stream or can use webhook from Roman. +Bot is using webhooks coming from Roman, for that, the bot needs to have public URL or IP address. ## Usage -* To run the application simply execute `make run` or `./gradlew run`. -* To run the application inside the docker compose environment run `make up` -For more details see [Makefile](Makefile). +* The bot needs Postgres database up & running - we use one in [docker-compose.yml](docker-compose.yml), to start it up, you can use + command `make db`. +* To run the application execute `make run` or `./gradlew run`. +* To run the application inside the docker compose environment run `make up`. +For more details see [Makefile](Makefile). ## Docker Images -Poll bot has public [docker image](https://hub.docker.com/r/lukaswire/polls). + +Poll bot has public [docker image](https://quay.io/wire/poll-bot). ```bash -lukaswire/polls +quay.io/wire/poll-bot ``` -Tag `latest` is current master branch - each commit is build and tagged as `latest`. -[Releases](https://github.com/wireapp/poll-bot/releases) have then images with corresponding tag. + +Tag `latest` is the latest release. [Releases](https://github.com/wireapp/poll-bot/releases) have then images with corresponding tag, so you +can always roll back. Tag `staging` is build from the latest commit in `staging` branch. ## Bot configuration @@ -69,13 +73,10 @@ Configuration is currently being loaded from the environment variables. * Token which is used for the auth of proxy. */ const val SERVICE_TOKEN = "SERVICE_TOKEN" - /** - * Key for connecting to the web socket of the proxy. - */ - const val APP_KEY = "APP_KEY" - /** - * Domain used for sending the messages from the bot to proxy eg. "https://proxy.services.zinfra.io" - */ + +/** + * Domain used for sending the messages from the bot to proxy eg. "https://proxy.services.zinfra.io/api" + */ const val PROXY_DOMAIN = "PROXY_DOMAIN" ``` @@ -95,6 +96,22 @@ DB_USER= DB_PASSWORD= DB_URL= SERVICE_TOKEN= -APP_KEY= PROXY_DOMAIN= ``` + +Such configuration can look for example like that: + +```bash +# database +POSTGRES_USER=wire-poll-bot +POSTGRES_PASSWORD=super-secret-wire-pwd +POSTGRES_DB=poll-bot + +# application +DB_USER=wire-poll-bot +DB_PASSWORD=super-secret-wire-pwd +DB_URL=jdbc:postgresql://db:5432/poll-bot +SERVICE_TOKEN=x6jsd5vets967dsA01dz1cOl +APP_KEY=eyJhbGciOiJIUzM4NCJ9....... +PROXY_DOMAIN=https://proxy.services.zinfra.io/api +``` diff --git a/build.gradle.kts b/build.gradle.kts index 0d39b00..d63b606 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - kotlin("jvm") version "1.5.0" + kotlin("jvm") version "1.5.30" application distribution id("net.nemerosa.versioning") version "2.14.0" @@ -22,10 +22,10 @@ dependencies { // stdlib implementation(kotlin("stdlib-jdk8")) // extension functions - implementation("pw.forst", "katlib", "2.0.1") + implementation("pw.forst", "katlib", "2.0.3") // Ktor server dependencies - val ktorVersion = "1.5.4" + val ktorVersion = "1.6.3" implementation("io.ktor", "ktor-server-core", ktorVersion) implementation("io.ktor", "ktor-server-netty", ktorVersion) implementation("io.ktor", "ktor-jackson", ktorVersion) @@ -58,7 +58,7 @@ dependencies { // database implementation("org.postgresql", "postgresql", "42.2.20") - val exposedVersion = "0.31.1" + val exposedVersion = "0.33.1" implementation("org.jetbrains.exposed", "exposed-core", exposedVersion) implementation("org.jetbrains.exposed", "exposed-dao", exposedVersion) implementation("org.jetbrains.exposed", "exposed-jdbc", exposedVersion) @@ -70,11 +70,18 @@ dependencies { } tasks { + val jvmTarget = "1.8" compileKotlin { - kotlinOptions.jvmTarget = "1.8" + kotlinOptions.jvmTarget = jvmTarget + } + compileJava { + targetCompatibility = jvmTarget } compileTestKotlin { - kotlinOptions.jvmTarget = "1.8" + kotlinOptions.jvmTarget = jvmTarget + } + compileTestJava { + targetCompatibility = jvmTarget } distTar { diff --git a/docker-compose.yml b/docker-compose.yml index ba425ad..704ba61 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -15,7 +15,7 @@ services: - db db: - image: postgres:13.1 + image: postgres:13 container_name: poll-bot-db env_file: .env ports: diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0f80bbf..ffed3a2 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 43369d7..4f906e0 100755 --- a/gradlew +++ b/gradlew @@ -26,22 +26,22 @@ # Resolve links: $0 may be a link PRG="$0" # Need this for relative symlinks. -while [ -h "$PRG" ]; do - ls=$(ls -ld "$PRG") - link=$(expr "$ls" : '.*-> \(.*\)$') - if expr "$link" : '/.*' >/dev/null; then - PRG="$link" - else - PRG=$(dirname "$PRG")"/$link" - fi +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi done -SAVED="$(pwd)" -cd "$(dirname \"$PRG\")/" >/dev/null || true -APP_HOME="$(pwd -P)" +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" cd "$SAVED" >/dev/null APP_NAME="Gradle" -APP_BASE_NAME=$(basename "$0") +APP_BASE_NAME=`basename "$0"` # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' @@ -49,15 +49,15 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" -warn() { - echo "$*" +warn () { + echo "$*" } -die() { - echo - echo "$*" - echo - exit 1 +die () { + echo + echo "$*" + echo + exit 1 } # OS specific support (must be 'true' or 'false'). @@ -65,118 +65,119 @@ cygwin=false msys=false darwin=false nonstop=false -case "$(uname)" in -CYGWIN*) - cygwin=true - ;; -Darwin*) - darwin=true - ;; -MINGW*) - msys=true - ;; -NONSTOP*) - nonstop=true - ;; +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ]; then - if [ -x "$JAVA_HOME/jre/sh/java" ]; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ]; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME Please set the JAVA_HOME variable in your environment to match the location of your Java installation." - fi + fi else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ]; then - MAX_FD_LIMIT=$(ulimit -H -n) - if [ $? -eq 0 ]; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ]; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ]; then - warn "Could not set maximum file descriptor limit: $MAX_FD" +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi fi # For Darwin, add options to specify how the application appears in the dock if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi # For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ]; then - APP_HOME=$(cygpath --path --mixed "$APP_HOME") - CLASSPATH=$(cygpath --path --mixed "$CLASSPATH") - - JAVACMD=$(cygpath --unix "$JAVACMD") - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=$(find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null) - SEP="" - for dir in $ROOTDIRSRAW; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ]; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@"; do - CHECK=$(echo "$arg" | egrep -c "$OURCYGPATTERN" -) - CHECK2=$(echo "$arg" | egrep -c "^-") ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ]; then ### Added a condition - eval $(echo args$i)=$(cygpath --path --ignore --mixed "$arg") - else - eval $(echo args$i)="\"$arg\"" +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" fi - i=$(expr $i + 1) - done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac fi # Escape application args -save() { - for i; do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/"; done - echo " " +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " } -APP_ARGS=$(save "$@") +APP_ARGS=`save "$@"` # Collect all arguments for the java command, following the shell quoting and substitution rules eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" diff --git a/src/main/kotlin/com/wire/bots/polls/setup/EnvConfigVariables.kt b/src/main/kotlin/com/wire/bots/polls/setup/EnvConfigVariables.kt index f9bee7d..b3eee0a 100644 --- a/src/main/kotlin/com/wire/bots/polls/setup/EnvConfigVariables.kt +++ b/src/main/kotlin/com/wire/bots/polls/setup/EnvConfigVariables.kt @@ -28,7 +28,7 @@ object EnvConfigVariables { const val SERVICE_TOKEN = "SERVICE_TOKEN" /** - * Domain used for sending the messages from the bot to proxy eg. "https://proxy.services.zinfra.io" + * Domain used for sending the messages from the bot to proxy eg. "https://proxy.services.zinfra.io/api" */ const val PROXY_DOMAIN = "PROXY_DOMAIN" } From 8880aefcbae6678ab6852908321ed6780fd0835a Mon Sep 17 00:00:00 2001 From: Lukas Forst Date: Mon, 30 Aug 2021 23:08:02 +0200 Subject: [PATCH 2/6] fix docker image name --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index c6881c5..25d6a89 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM adoptopenjdk/openjdk11:alpine-jdk AS build +FROM adoptopenjdk/openjdk11:alpine AS build LABEL description="Wire Poll Bot" LABEL project="wire-bots:polls" From 195aa85edf392f8ba3c5593dc7a55694451caae8 Mon Sep 17 00:00:00 2001 From: Lukas Forst Date: Tue, 31 Aug 2021 09:53:08 +0200 Subject: [PATCH 3/6] fix spacing in readme --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3abf18f..43d5e6e 100644 --- a/README.md +++ b/README.md @@ -74,9 +74,9 @@ Configuration is currently being loaded from the environment variables. */ const val SERVICE_TOKEN = "SERVICE_TOKEN" -/** - * Domain used for sending the messages from the bot to proxy eg. "https://proxy.services.zinfra.io/api" - */ + /** + * Domain used for sending the messages from the bot to proxy eg. "https://proxy.services.zinfra.io/api" + */ const val PROXY_DOMAIN = "PROXY_DOMAIN" ``` From d42ba43c7ede810333f719c9398ce03f4e2638d1 Mon Sep 17 00:00:00 2001 From: Lukas Forst Date: Thu, 2 Dec 2021 16:57:06 +0100 Subject: [PATCH 4/6] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 43d5e6e..bb541c6 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Service code to enable Poll bot in your team: ## Commands Basic usage * `/poll "Question" "Option 1" "Option 2"` will create poll -* `/stats` will send result of the **last** poll in the conversation +* `/stats` will send result of the **latest** poll in the conversation * `/help` to show help * `/version` prints the current version of the poll bot From 49d41d1bd1d6f956637c89f861625034caccd484 Mon Sep 17 00:00:00 2001 From: Vitor Hugo Schwaab Date: Wed, 19 Oct 2022 17:26:27 +0200 Subject: [PATCH 5/6] feat: reduce amount of vote placeholders --- .../polls/services/StatsFormattingService.kt | 38 +++++++++++++++++-- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/com/wire/bots/polls/services/StatsFormattingService.kt b/src/main/kotlin/com/wire/bots/polls/services/StatsFormattingService.kt index 5f47230..b3d7e6a 100644 --- a/src/main/kotlin/com/wire/bots/polls/services/StatsFormattingService.kt +++ b/src/main/kotlin/com/wire/bots/polls/services/StatsFormattingService.kt @@ -6,12 +6,18 @@ import com.wire.bots.polls.dto.bot.statsMessage import mu.KLogging import pw.forst.katlib.newLine import pw.forst.katlib.whenNull +import kotlin.math.min class StatsFormattingService( private val repository: PollRepository ) { private companion object : KLogging() { const val titlePrefix = "**Results** for poll *\"" + + /** + * Maximum number of trailing vote slots to be displayed, considered the most voted option. + */ + const val MAX_VOTE_PLACEHOLDER_COUNT = 2 } /** @@ -37,14 +43,40 @@ class StatsFormattingService( ) } + /** + * Formats the vote results using the most voted option to determine the output size. + * Will add [MAX_VOTE_PLACEHOLDER_COUNT] number of trailing placeholders to + * until it reaches [conversationMembers]. + * + * Examples: + * With [MAX_VOTE_PLACEHOLDER_COUNT] = 2 and [conversationMembers] >= 5: + * - ⬛⬜⬜⬜⬜ A (1) + * - ⬛⬛⬛⬜⬜ B (3) + * - ⬛⬛⬜⬜⬜ C (2) + * + * With [MAX_VOTE_PLACEHOLDER_COUNT] = 2 and 4 [conversationMembers] = 4: + * - ⬜⬜⬜⬜ A (0) + * - ⬛⬛⬛⬜ B (3) + * - ⬛⬜⬜⬜ C (1) + * + * With [MAX_VOTE_PLACEHOLDER_COUNT] = 2 and 3 [conversationMembers] = 3: + * - ⬛⬛⬛ A (3) + * - ⬜⬜⬜ B (1) + */ private fun formatVotes(stats: Map, Int>, conversationMembers: Int?): String { // we can use assert as the result size is checked - val maxVotes = requireNotNull(stats.values.maxOrNull()) { "There were no stats!" } + val mostPopularOptionVoteCount = requireNotNull(stats.values.maxOrNull()) { "There were no stats!" } + + val maximumSize = min( + conversationMembers ?: Integer.MAX_VALUE, + mostPopularOptionVoteCount + MAX_VOTE_PLACEHOLDER_COUNT + ) + return stats .map { (option, votingUsers) -> - VotingOption(if (votingUsers == maxVotes) "**" else "*", option.second, votingUsers) + VotingOption(if (votingUsers == mostPopularOptionVoteCount) "**" else "*", option.second, votingUsers) }.let { votes -> - votes.joinToString(newLine) { it.toString(conversationMembers ?: maxVotes) } + votes.joinToString(newLine) { it.toString(maximumSize) } } } From cb73a5191a1a3d55700f0ac28a8b7cb61b0639d6 Mon Sep 17 00:00:00 2001 From: Lukas Forst Date: Thu, 20 Oct 2022 09:58:39 +0200 Subject: [PATCH 6/6] (hotfix): pipelines version fix --- .github/workflows/prod.yml | 2 +- .github/workflows/staging.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/prod.yml b/.github/workflows/prod.yml index 604b43e..c108ea5 100644 --- a/.github/workflows/prod.yml +++ b/.github/workflows/prod.yml @@ -79,7 +79,7 @@ jobs: # Setup gcloud CLI - name: Set up Cloud SDK - uses: google-github-actions/setup-gcloud@master + uses: google-github-actions/setup-gcloud@v0 with: service_account_email: kubernetes-deployment-agent@wire-bot.iam.gserviceaccount.com service_account_key: ${{ secrets.GKE_SA_KEY }} diff --git a/.github/workflows/staging.yml b/.github/workflows/staging.yml index f7fbc30..3e6a9cf 100644 --- a/.github/workflows/staging.yml +++ b/.github/workflows/staging.yml @@ -52,7 +52,7 @@ jobs: # Setup gcloud CLI - name: Set up Cloud SDK - uses: google-github-actions/setup-gcloud@master + uses: google-github-actions/setup-gcloud@v0 with: service_account_email: kubernetes-deployment-agent@wire-bot.iam.gserviceaccount.com service_account_key: ${{ secrets.GKE_SA_KEY }}