{"id":21035286,"url":"https://github.com/skellla/mr-poke","last_synced_at":"2025-04-12T14:22:44.973Z","repository":{"id":198031251,"uuid":"699260181","full_name":"SkeLLLa/mr-poke","owner":"SkeLLLa","description":null,"archived":false,"fork":false,"pushed_at":"2024-03-16T18:45:25.000Z","size":411,"stargazers_count":4,"open_issues_count":2,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-23T16:46:52.200Z","etag":null,"topics":["gitlab","merge-request","notifications","slack"],"latest_commit_sha":null,"homepage":"https://savelife.in.ua/en/donate-en/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SkeLLLa.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-10-02T09:19:14.000Z","updated_at":"2023-12-01T12:46:59.000Z","dependencies_parsed_at":"2023-10-04T05:10:40.737Z","dependency_job_id":"89619930-bc88-4e8b-a04f-aab5d259be71","html_url":"https://github.com/SkeLLLa/mr-poke","commit_stats":null,"previous_names":["skellla/gitlab-slack-mr"],"tags_count":22,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SkeLLLa%2Fmr-poke","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SkeLLLa%2Fmr-poke/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SkeLLLa%2Fmr-poke/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SkeLLLa%2Fmr-poke/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SkeLLLa","download_url":"https://codeload.github.com/SkeLLLa/mr-poke/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248578920,"owners_count":21127725,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["gitlab","merge-request","notifications","slack"],"created_at":"2024-11-19T13:14:27.943Z","updated_at":"2025-04-12T14:22:44.937Z","avatar_url":"https://github.com/SkeLLLa.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Mr. Poke\n\nPokes lazy people to review their Gitlab MRs.\n\n## ToC\n\n- [Mr. Poke](#mr-poke)\n  - [ToC](#toc)\n  - [Description](#description)\n  - [Setup](#setup)\n    - [Prerequisites](#prerequisites)\n      - [Postgres database](#postgres-database)\n      - [Slack App](#slack-app)\n      - [GitLab App](#gitlab-app)\n      - [GitLab group webhook](#gitlab-group-webhook)\n      - [Mr. Poke service deployment](#mr-poke-service-deployment)\n        - [Bare metal](#bare-metal)\n        - [Docker](#docker)\n        - [Helm chart](#helm-chart)\n        - [Terraform](#terraform)\n  - [TODOs](#todos)\n\n## Description\n\nThe service allows to setup plain and simple slack notifications for GitLab. It doesn't annoy you with creating channels per MR, all notifications go to the slack app messages.\n\nWhat does it do:\n\n- Notifies MR authors when they forgot to put assignees and reviewers.\n- Notifies reviewers when MR is opened (or updated from Draft state).\n- Notifies asignees when MR was approved and became ready to merge.\n\nIn the same time it's 100% secure, since your data stays in your organisation and is not sent to any 3rd parties.\n\n## Setup\n\n### Prerequisites\n\n#### Postgres database\n\nBackend uses [prisma](https://www.prisma.io/) to connect to database. For now it's set to postgres. But you may adjust it to your needs by changing datasource provider in [prisma/schema.prisma](https://github.com/SkeLLLa/mr-poke/blob/master/prisma/schema.prisma).\n\n#### Slack App\n\n1. Create app in [slack](https://api.slack.com/apps/).\n2. Go to \"OAuth \u0026 Permissions\" and add scopes. For now it's enough `chat:write`, `users.profile:read`, `users:read`, `users:read.email`. In future it may evolve with adding new functions.\n3. Install your app into workspace.\n4. Save your `Bot User OAuth Token` for later.\n\n#### GitLab App\n\n1. Go to your [GitLab](https://gitlab.com) and create an app with scopes `read_user`, `openid`, `profile`, `email`.\n2. Optionally add redirect URI, if you already know the domain where it will be hosted (example: `https://mr-poke.example.com/login/gitlab/callback`).\n3. Save `Application ID` and `Secret` for later.\n\n#### GitLab group webhook\n\n1. Go to your [GitLab](https://gitlab.com) and create an create groop webhook.\n2. Put your url, for example `https://mr-poke.example.com/hooks/gitlab` and select \"Merge request events\".\n3. Create \"Secret token\" for webhook and save it.\n\n#### Mr. Poke service deployment\n\n##### Bare metal\n\nTo run the service locally or on bare metal you need [node.js](https://nodejs.org/en) version 18+ and [pnpm](https://pnpm.io/).\n\n1. Clone the repo\n2. Install dependencies via `pnpm i`\n3. Setup needed environment variables (see [docker](#docker) for the list)\n4. Run via `pnpm run start:prod`\n\n##### Docker\n\nDocker images are available in repo: [SkeLLLa/mr-poke](https://github.com/SkeLLLa/mr-poke/pkgs/container/mr-poke)\n\n```shell\ndocker pull ghcr.io/skellla/mr-poke:latest\n```\n\nAvailable environment variables:\n\n```shell\n  DATABASE_URL=\"\u003cpostgres connection string\u003e\"\n  GL_HOOK_TOKEN=\"\u003cgitlab webhook secret token for request validation\u003e\"\n  GL_CLIENT_ID=\"\u003cgitlab application id\u003e\"\n  GL_CLIENT_SECRET=\"\u003cgitlab application secret\u003e\"\n  OAUTH2_CALLBACK_URI=\"\u003cgitlab oaut2 callback uri\u003e\"\n  GL_ACCESS_TOKEN=\"\u003cgitlab access token\u003e\"\n  SLACK_TOKEN=\"\u003cslack bot token\u003e\"\n```\n\nFor other env variables see [config](https://github.com/SkeLLLa/mr-poke/blob/master/src/config/index.ts).\n\nExample:\n\n```shell\n  GL_CLIENT_ID=\"01.....\"\n  GL_CLIENT_SECRET=\"gloas-....\"\n  OAUTH2_CALLBACK_URI=\"https://mr-poke.example.com/login/gitlab/callback\"\n  GL_ACCESS_TOKEN=\"glpat-....\"\n  SLACK_TOKEN=\"xoxb-...-...-...\"\n  GL_HOOK_TOKEN=\"super-secret\"\n  DATABASE_URL=\"postgresql://user:password@127.0.0.1:5432/mr-poke-db\"\n  SLACK_EMAIL_DOMAINS=\"example.com\"\n  PG_BOUNCER_ENABLED=false\n  PG_SSL_MODE=disable\n  LOG_LEVEL=debug\n  SERVER_PORT=3000\n```\n\n##### Helm chart\n\nHelm chart is available via OCI [repo](https://github.com/SkeLLLa/mr-poke/pkgs/container/charts%2Fmr-poke)\n\nTo see available versions and default values use command:\n\n```shell\n helm show all oci://ghcr.io/skellla/charts/mr-poke\n```\n\nTo install app you can use helm command as well, but don't forget to create your `values.yaml` and pass env variables mentioned in [docker](#docker) section.\n\nExample:\n\n```yaml\nenv:\n  PG_BOUNCER_ENABLED: 'true'\n  PG_SSL_MODE: 'require'\n  ENV: 'production'\n  NODE_ENV: 'production'\n  LOG_LEVEL: 'debug'\n  GL_CLIENT_ID: '01.....'\n  GL_CLIENT_SECRET: 'gloas-....'\n  OAUTH2_CALLBACK_URI: 'https://mr-poke.example.com/login/gitlab/callback'\n  GL_ACCESS_TOKEN: 'glpat-....'\n  SLACK_TOKEN: 'xoxb-...-...-...'\n  GL_HOOK_TOKEN: 'super-secret'\n  DATABASE_URL: 'postgresql://user:password@127.0.0.1:5432/mr-poke-db'\n  SLACK_EMAIL_DOMAINS: 'example.com'\n\nservice:\n  type: ClusterIP\n  port: 80\n\ningress:\n  enabled: true\n  annotations:\n    kubernetes.io/ingress.class: nginx\n    nginx.org/mergeable-ingress-type: minion\n    kubernetes.io/tls-acme: 'true'\n    nginx.ingress.kubernetes.io/jaeger-service-name: 'ingress-service-mr-poke'\n    nginx.ingress.kubernetes.io/configuration-snippet: |\n      more_set_headers \"server: testing\";\n      more_set_headers \"X-Content-Type-Options: nosniff\";\n      more_set_headers \"X-Frame-Options: DENY\";\n      more_set_headers \"X-Xss-Protection: 1\";\n      more_set_headers \"X-Robots-Tag: noindex, nofollow, nosnippet, noarchive\";\n  hosts:\n    - host: ''\n      paths:\n        - /\n\naffinity:\n  podAntiAffinity:\n    requiredDuringSchedulingIgnoredDuringExecution:\n      - labelSelector:\n          matchExpressions:\n            - key: app.kubernetes.io/instance\n              operator: In\n              values:\n                - service-mr-poke\n        topologyKey: 'kubernetes.io/hostname'\n\nserviceMonitor:\n  enabled: true\n  labels:\n    prometheus: monitoring\n    release: prometheus\n  interval: 1m\n  scrapeTimeout: 30s\n```\n\n```shell\n helm install mr-poke oci://ghcr.io/skellla/charts/mr-poke -f my-values.yaml\n```\n\n##### Terraform\n\nInstall using terraform and helm release provider. Example config:\n\n```tf\nvariable \"host\" {\n  type = string\n}\n\nvariable \"slack_notifications_db_uri\" {\n  sensitive = true\n  type      = string\n}\n\nvariable \"gitlab_webhook_token\" {\n  sensitive = true\n  type      = string\n}\n\nvariable \"gitlab_app_id\" {\n  sensitive = true\n  type      = string\n}\n\nvariable \"gitlab_app_secret\" {\n  sensitive = true\n  type      = string\n}\n\nvariable \"gitlab_oauth_callback_uri\" {\n  type = string\n}\n\nvariable \"slack_token\" {\n  type      = string\n  sensitive = true\n}\n\nvariable \"gitlab_access_token\" {\n  type      = string\n  sensitive = true\n}\n\nresource \"helm_release\" \"mr_poke\" {\n  name             = \"mr-poke\"\n  create_namespace = true\n  cleanup_on_fail  = true\n  namespace        = \"default\"\n  repository       = \"oci://ghcr.io/skellla/charts\"\n  chart            = \"mr-poke\"\n  version          = \"1.0.0\"\n  values = [\n    \"${file(\"${path.module}/mr-poke.values.yaml\")}\"\n  ]\n\n  set {\n    name  = \"ingress.hosts[0].host\"\n    value = var.host\n  }\n\n  set {\n    name  = \"ingress.tls[0].hosts[0]\"\n    value = var.host\n  }\n\n  set {\n    name  = \"env.DATABASE_URL\"\n    value = var.slack_notifications_db_uri\n  }\n\n  set {\n    name  = \"env.GL_HOOK_TOKEN\"\n    value = var.gitlab_webhook_token\n  }\n\n  set {\n    name  = \"env.GL_CLIENT_ID\"\n    value = var.gitlab_app_id\n  }\n\n  set {\n    name  = \"env.GL_CLIENT_SECRET\"\n    value = var.gitlab_app_secret\n  }\n\n  set {\n    name  = \"env.OAUTH2_CALLBACK_URI\"\n    value = var.gitlab_oauth_callback_uri\n  }\n\n  set {\n    name  = \"env.GL_ACCESS_TOKEN\"\n    value = var.gitlab_access_token\n  }\n\n  set {\n    name  = \"env.SLACK_TOKEN\"\n    value = var.slack_token\n  }\n}\n```\n\n## TODOs\n\nThere are lot's of thing could be done. But hopefully GitLab team after years of development will make their slack app usable.\n\nHere's a small list of possible improvements, so PRs welcome:\n\n- [] Add periodic notification to reviewers if MR is not ready to merge (not enough approvals).\n- [] Integrate `i18next` to localize slack messages based on user locale.\n- [] Add application homepage with list of unreviewed MRs.\n- [] Add npm binary package for those who don't want installing gitlab webhooks.\n- [] You tell me.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskellla%2Fmr-poke","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fskellla%2Fmr-poke","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskellla%2Fmr-poke/lists"}