From acb48c74b479252510f543f9e53bf92073e37509 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Thu, 13 Aug 2026 23:04:58 +0100 Subject: [PATCH 1/3] chore: point this repo's own manifests and docs at the fork The compose stacks and helm chart still pulled grafana/oncall, and the quickstart installed grafana-oncall-app from the catalog. Following our own README therefore produced the archived engine paired with a plugin that crashes on Grafana 13. - compose (hobby and mysql/rabbitmq): engine images -> ghcr.io/appwrite/grafana-oncall:latest, and GF_INSTALL_PLUGINS points at the plugin archive from our release, overridable via ONCALL_PLUGIN_URL - developer stack: build cache -> our image, dropping the :dev tag we never publish - helm: image.repository -> ghcr.io/appwrite/grafana-oncall, with the test assertion and three rendered snapshots updated to match - helm README: the chart is not published to a helm repository any more, so install it from a checkout rather than grafana/oncall - README: rewrite the header as a list of differences from upstream, so the reason to use this fork is stated rather than implied; fix links that pointed into the archived repo; drop the stargazers chart, which renders a github api error GHCR visibility needed no change: the package is anonymously pullable, so compose works without credentials. Closes #10 Co-Authored-By: Claude Fable 5 --- README.md | 50 +++++++++++++------ docker-compose-developer.yml | 3 +- docker-compose-mysql-rabbitmq.yml | 10 ++-- docker-compose.yml | 10 ++-- helm/oncall/README.md | 22 ++++---- .../integrations_deployment_test.yaml.snap | 2 +- ...telegram_polling_deployment_test.yaml.snap | 2 +- .../__snapshot__/wait_for_db_test.yaml.snap | 12 ++--- helm/oncall/tests/image_deployments_test.yaml | 2 +- helm/oncall/values.yaml | 2 +- 10 files changed, 69 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index 20ba61d31e..c93ca4891a 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,33 @@ # Appwrite's fork of Grafana OnCall -Grafana archived OnCall OSS on 2026-03-24. [Appwrite](https://appwrite.io) maintains this -fork for its own use — we keep it working for our needs, but offer no support or -roadmap commitments. Engine images are published to -[`ghcr.io/appwrite/grafana-oncall`](https://github.com/appwrite/grafana-oncall/pkgs/container/grafana-oncall). +Grafana archived [OnCall OSS](https://github.com/grafana/oncall) on 2026-03-24 at v1.16.11. +[Appwrite](https://appwrite.io) maintains this fork for its own use. + +## What's different from upstream + +- **It runs on current Grafana.** Grafana 13 ships React 19, which removed `ReactDOM.findDOMNode`. + Upstream's plugin reaches it through three libraries, so escalation chains, notification policies + and the rotation modals crash on mount. Fixed by moving drag-and-drop to `@dnd-kit`, passing + `nodeRef` to `react-draggable`, and replacing `react-transition-group` with a CSS animation. +- **Insights renders.** Its `alert_groups_total` variable was seeded multi-valued and URL-synced, so + a restored value interpolated a regex where PromQL wants a metric name, breaking every panel. +- **End-to-end tests run against Grafana 12 and 13**, where upstream tested 10 and 11. +- **~290 security patches.** Dependabot alerts went from 309 to 18. +- **Django 5.2 LTS**, where upstream is on 4.2 — its extended support ended in April 2026. +- **`fcm-django` from PyPI** rather than a tarball of a now-archived fork. +- **Releases ship both halves**: multi-arch engine images to + [`ghcr.io/appwrite/grafana-oncall`](https://github.com/appwrite/grafana-oncall/pkgs/container/grafana-oncall) + and a plugin archive attached to each + [release](https://github.com/appwrite/grafana-oncall/releases). Upstream's catalog build is frozen + at 1.16.11. + +## What it does not offer + +- No support and no roadmap commitments. We keep it working for our needs. +- The plugin is unsigned, since signing needs a grafana.com access policy, so it needs + `GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS=grafana-oncall-app`. +- The helm chart is not published to a helm repository; install it from a checkout. +- The mobile app relied on Grafana Cloud's push relay, which went away with the archival. ## Grafana OnCall @@ -46,7 +70,7 @@ We prepared multiple environments: 1. Download [`docker-compose.yml`](docker-compose.yml): ```bash - curl -fsSL https://raw.githubusercontent.com/grafana/oncall/dev/docker-compose.yml -o docker-compose.yml + curl -fsSL https://raw.githubusercontent.com/appwrite/grafana-oncall/main/docker-compose.yml -o docker-compose.yml ``` 2. Set variables: @@ -138,26 +162,22 @@ docker-compose pull engine docker-compose up -d ``` -After updating the engine, you'll also need to click the "Update" button on the [plugin version page](http://localhost:3000/plugins/grafana-oncall-app?page=version-history). -See [Grafana docs](https://grafana.com/docs/grafana/latest/administration/plugin-management/#update-a-plugin) for more -info on updating Grafana plugins. +The plugin is not published to grafana.com, so it does not update through the plugin catalog. Point +`GF_INSTALL_PLUGINS` at the archive from the [release](https://github.com/appwrite/grafana-oncall/releases) +matching the engine tag and recreate the Grafana container. ## Join community [](https://slack.grafana.com/) [](https://community.grafana.com/) -Have a question, comment or feedback? Don't be afraid to [open an issue](https://github.com/grafana/oncall/issues/new/choose)! - -## Stargazers over time - -[![Stargazers over time](https://starchart.cc/grafana/oncall.svg)](https://starchart.cc/grafana/oncall) +Have a question, comment or feedback? Don't be afraid to [open an issue](https://github.com/appwrite/grafana-oncall/issues/new/choose)! ## Further Reading -- _Automated migration from other on-call tools_ - [Migrator](https://github.com/grafana/oncall/tree/dev/tools/migrators) +- _Automated migration from other on-call tools_ - [Migrator](https://github.com/appwrite/grafana-oncall/tree/main/tools/migrators) - _Documentation_ - [Grafana OnCall](https://grafana.com/docs/oncall/latest/) - _Overview Webinar_ - [YouTube](https://www.youtube.com/watch?v=7uSe1pulgs8) -- _How To Add Integration_ - [How to Add Integration](https://github.com/grafana/oncall/tree/dev/engine/config_integrations/README.md) +- _How To Add Integration_ - [How to Add Integration](https://github.com/appwrite/grafana-oncall/tree/main/engine/config_integrations/README.md) - _Blog Post_ - [Announcing Grafana OnCall, the easiest way to do on-call management](https://grafana.com/blog/2021/11/09/announcing-grafana-oncall/) - _Presentation_ - [Deep dive into the Grafana, Prometheus, and Alertmanager stack for alerting and on-call management](https://grafana.com/go/observabilitycon/2021/alerting/?pg=blog) diff --git a/docker-compose-developer.yml b/docker-compose-developer.yml index 7b4143f260..38aefd0cc8 100644 --- a/docker-compose-developer.yml +++ b/docker-compose-developer.yml @@ -8,8 +8,7 @@ x-oncall-build: &oncall-build-args target: ${ONCALL_IMAGE_TARGET:-dev} labels: *oncall-labels cache_from: - - grafana/oncall:latest - - grafana/oncall:dev + - ghcr.io/appwrite/grafana-oncall:latest x-oncall-volumes: &oncall-volumes - ./engine:/etc/app diff --git a/docker-compose-mysql-rabbitmq.yml b/docker-compose-mysql-rabbitmq.yml index a00d701672..6adb870d6c 100644 --- a/docker-compose-mysql-rabbitmq.yml +++ b/docker-compose-mysql-rabbitmq.yml @@ -22,7 +22,7 @@ x-environment: &oncall-environment services: engine: - image: grafana/oncall + image: ghcr.io/appwrite/grafana-oncall:latest restart: always ports: - "8080:8080" @@ -39,7 +39,7 @@ services: condition: service_started celery: - image: grafana/oncall + image: ghcr.io/appwrite/grafana-oncall:latest restart: always command: sh -c "./celery_with_exporter.sh" environment: *oncall-environment @@ -54,7 +54,7 @@ services: condition: service_started oncall_db_migration: - image: grafana/oncall + image: ghcr.io/appwrite/grafana-oncall:latest command: python manage.py migrate --noinput environment: *oncall-environment depends_on: @@ -143,7 +143,9 @@ services: GF_SECURITY_ADMIN_USER: ${GRAFANA_USER:-admin} GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_PASSWORD:-admin} GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS: grafana-oncall-app - GF_INSTALL_PLUGINS: grafana-oncall-app + # the catalog build is grafana's archived one, so install this fork's plugin archive + # yamllint disable-line rule:line-length + GF_INSTALL_PLUGINS: ${ONCALL_PLUGIN_URL:-https://github.com/appwrite/grafana-oncall/releases/download/v1.19.1/grafana-oncall-app-1.19.1.zip};grafana-oncall-app GF_AUTH_MANAGED_SERVICE_ACCOUNTS_ENABLED: true deploy: resources: diff --git a/docker-compose.yml b/docker-compose.yml index 3f6aecdbdb..c2435d19ae 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -16,7 +16,7 @@ x-environment: &oncall-environment services: engine: - image: grafana/oncall + image: ghcr.io/appwrite/grafana-oncall:latest restart: always ports: - "8080:8080" @@ -31,7 +31,7 @@ services: condition: service_healthy celery: - image: grafana/oncall + image: ghcr.io/appwrite/grafana-oncall:latest restart: always command: sh -c "./celery_with_exporter.sh" environment: *oncall-environment @@ -44,7 +44,7 @@ services: condition: service_healthy oncall_db_migration: - image: grafana/oncall + image: ghcr.io/appwrite/grafana-oncall:latest command: python manage.py migrate --noinput environment: *oncall-environment volumes: @@ -93,7 +93,9 @@ services: GF_SECURITY_ADMIN_USER: ${GRAFANA_USER:-admin} GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_PASSWORD:-admin} GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS: grafana-oncall-app - GF_INSTALL_PLUGINS: grafana-oncall-app + # the catalog build is grafana's archived one, so install this fork's plugin archive + # yamllint disable-line rule:line-length + GF_INSTALL_PLUGINS: ${ONCALL_PLUGIN_URL:-https://github.com/appwrite/grafana-oncall/releases/download/v1.19.1/grafana-oncall-app-1.19.1.zip};grafana-oncall-app GF_AUTH_MANAGED_SERVICE_ACCOUNTS_ENABLED: true volumes: - grafana_data:/var/lib/grafana diff --git a/helm/oncall/README.md b/helm/oncall/README.md index 993f0649e0..54072ba615 100644 --- a/helm/oncall/README.md +++ b/helm/oncall/README.md @@ -5,7 +5,7 @@ It will deploy Grafana OnCall engine and celery workers, along with RabbitMQ clu It will also deploy cert manager and nginx ingress controller, as Grafana OnCall backend might need to be externally available to receive alerts from other monitoring systems. Grafana OnCall engine acts as a backend and can be connected to the Grafana frontend plugin named Grafana OnCall. -Architecture diagram can be found [here](https://raw.githubusercontent.com/grafana/oncall/dev/docs/img/architecture_diagram.png) +Architecture diagram can be found [here](https://raw.githubusercontent.com/appwrite/grafana-oncall/main/docs/img/architecture_diagram.png) ## Production usage @@ -23,12 +23,13 @@ Here are the instructions on how to set up your own [ingress](#set-up-external-a ## Install -### Prepare the repo +### Prepare the chart + +This chart is not published to a helm repository, so install it from a checkout: ```bash -# Add the repository -helm repo add grafana https://grafana.github.io/helm-charts -helm repo update +git clone https://github.com/appwrite/grafana-oncall.git +cd grafana-oncall ``` ### Installing the helm chart @@ -40,7 +41,7 @@ helm install \ --set base_url=example.com \ --set grafana."grafana\.ini".server.domain=example.com \ release-oncall \ - grafana/oncall + ./helm/oncall ``` Follow the `helm install` output to finish setting up Grafana OnCall backend and Grafana OnCall frontend plugin e.g. @@ -83,7 +84,7 @@ helm upgrade \ --set base_url=example.com \ --set grafana."grafana\.ini".server.domain=example.com \ release-oncall \ - grafana/oncall + ./helm/oncall ``` ### Passwords and external secrets @@ -382,9 +383,8 @@ externalRedis: ## Update ```bash -# Add & upgrade the repository -helm repo add grafana https://grafana.github.io/helm-charts -helm repo update +# Pull the latest chart +git pull # Re-deploy helm upgrade \ @@ -393,7 +393,7 @@ helm upgrade \ --set base_url=example.com \ --set grafana."grafana\.ini".server.domain=example.com \ release-oncall \ - grafana/oncall + ./helm/oncall ``` After re-deploying, please also update the Grafana OnCall plugin on the plugin version page. diff --git a/helm/oncall/tests/__snapshot__/integrations_deployment_test.yaml.snap b/helm/oncall/tests/__snapshot__/integrations_deployment_test.yaml.snap index d055982f49..2e1f46d445 100644 --- a/helm/oncall/tests/__snapshot__/integrations_deployment_test.yaml.snap +++ b/helm/oncall/tests/__snapshot__/integrations_deployment_test.yaml.snap @@ -102,7 +102,7 @@ detached_integrations.enabled=true -> should create integrations deployment: value: "" - name: ROOT_URLCONF value: engine.integrations_urls - image: grafana/oncall:v1.3.39 + image: ghcr.io/appwrite/grafana-oncall:v1.3.39 imagePullPolicy: Always livenessProbe: httpGet: diff --git a/helm/oncall/tests/__snapshot__/telegram_polling_deployment_test.yaml.snap b/helm/oncall/tests/__snapshot__/telegram_polling_deployment_test.yaml.snap index b3eb11b572..ac411fdcc3 100644 --- a/helm/oncall/tests/__snapshot__/telegram_polling_deployment_test.yaml.snap +++ b/helm/oncall/tests/__snapshot__/telegram_polling_deployment_test.yaml.snap @@ -84,7 +84,7 @@ telegramPolling.enabled=true -> should create telegram polling deployment: value: amqp - name: RABBITMQ_VHOST value: "" - image: grafana/oncall:v1.2.36 + image: ghcr.io/appwrite/grafana-oncall:v1.2.36 imagePullPolicy: Always name: telegram-polling securityContext: {} diff --git a/helm/oncall/tests/__snapshot__/wait_for_db_test.yaml.snap b/helm/oncall/tests/__snapshot__/wait_for_db_test.yaml.snap index 5c6e4adb7e..02b62b9bd1 100644 --- a/helm/oncall/tests/__snapshot__/wait_for_db_test.yaml.snap +++ b/helm/oncall/tests/__snapshot__/wait_for_db_test.yaml.snap @@ -76,7 +76,7 @@ database.type=mysql -> should create initContainer for MySQL database (default): value: amqp - name: RABBITMQ_VHOST value: "" - image: grafana/oncall:v1.2.36 + image: ghcr.io/appwrite/grafana-oncall:v1.2.36 imagePullPolicy: Always name: wait-for-db resources: @@ -164,7 +164,7 @@ database.type=mysql -> should create initContainer for MySQL database (default): value: amqp - name: RABBITMQ_VHOST value: "" - image: grafana/oncall:v1.2.36 + image: ghcr.io/appwrite/grafana-oncall:v1.2.36 imagePullPolicy: Always name: wait-for-db resources: @@ -252,7 +252,7 @@ database.type=mysql -> should create initContainer for MySQL database (default): value: amqp - name: RABBITMQ_VHOST value: "" - image: grafana/oncall:v1.2.36 + image: ghcr.io/appwrite/grafana-oncall:v1.2.36 imagePullPolicy: Always name: wait-for-db resources: @@ -343,7 +343,7 @@ database.type=postgresql -> should create initContainer for PostgreSQL database: value: amqp - name: RABBITMQ_VHOST value: "" - image: grafana/oncall:v1.2.36 + image: ghcr.io/appwrite/grafana-oncall:v1.2.36 imagePullPolicy: Always name: wait-for-db resources: @@ -433,7 +433,7 @@ database.type=postgresql -> should create initContainer for PostgreSQL database: value: amqp - name: RABBITMQ_VHOST value: "" - image: grafana/oncall:v1.2.36 + image: ghcr.io/appwrite/grafana-oncall:v1.2.36 imagePullPolicy: Always name: wait-for-db resources: @@ -523,7 +523,7 @@ database.type=postgresql -> should create initContainer for PostgreSQL database: value: amqp - name: RABBITMQ_VHOST value: "" - image: grafana/oncall:v1.2.36 + image: ghcr.io/appwrite/grafana-oncall:v1.2.36 imagePullPolicy: Always name: wait-for-db resources: diff --git a/helm/oncall/tests/image_deployments_test.yaml b/helm/oncall/tests/image_deployments_test.yaml index c7a1ae0959..23ee0bfb96 100644 --- a/helm/oncall/tests/image_deployments_test.yaml +++ b/helm/oncall/tests/image_deployments_test.yaml @@ -15,7 +15,7 @@ tests: asserts: - equal: path: spec.template.spec.containers[0].image - value: grafana/oncall:1.2.36 + value: ghcr.io/appwrite/grafana-oncall:1.2.36 - equal: path: spec.template.spec.containers[0].imagePullPolicy value: Always diff --git a/helm/oncall/values.yaml b/helm/oncall/values.yaml index 826e0a5be3..43c431e39b 100644 --- a/helm/oncall/values.yaml +++ b/helm/oncall/values.yaml @@ -15,7 +15,7 @@ imagePullSecrets: [] image: # Grafana OnCall docker image repository - repository: grafana/oncall + repository: ghcr.io/appwrite/grafana-oncall tag: pullPolicy: Always From 919dc7fc2d83cbb71327f8374aad1755ef89d743 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Thu, 13 Aug 2026 23:13:44 +0100 Subject: [PATCH 2/3] fix: keep the engine and plugin versions in lockstep Pairing a moving :latest engine with a fixed plugin archive meant every release after v1.19.1 would combine a newer backend with the 1.19.1 frontend, which is exactly the mismatch this PR set out to remove. A single ONCALL_VERSION drives both the engine tag and the plugin archive URL in each compose stack, so they cannot drift; verified by rendering 'docker compose config' with the default and with an override. The chart had the same defect twice over: - appVersion was v1.15.6, which is what image.tag falls back to, so the default install asked our registry for a tag that does not exist. Chart version and appVersion now track the release. - grafana.plugins still listed the catalog id, installing grafana's archived build. It now installs the matching release archive, and the grafana subchart allows the unsigned plugin. Both update sections told users to update the plugin from grafana's plugin page, which cannot work for a plugin that is not in the catalog. They now move ONCALL_VERSION (or grafana.plugins) instead, and note that grafana skips a plugin that is already installed, so the old copy has to be cleared from the volume first. Co-Authored-By: Claude Fable 5 --- README.md | 20 +++++++++++++------- docker-compose-mysql-rabbitmq.yml | 12 +++++++----- docker-compose.yml | 12 +++++++----- helm/oncall/Chart.yaml | 4 ++-- helm/oncall/README.md | 15 ++++++++++++--- helm/oncall/values.yaml | 7 ++++++- 6 files changed, 47 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index c93ca4891a..ccf4d19a4e 100644 --- a/README.md +++ b/README.md @@ -152,19 +152,25 @@ Here are some API calls that can be made to help if you are having difficulty co ## Update version -To update your Grafana OnCall hobby environment: +The engine and plugin are released together and are not meant to be mixed across versions, so one +variable moves both. Set it to the [release](https://github.com/appwrite/grafana-oncall/releases) you +want in `.env`: ```shell -# Update Docker image -docker-compose pull engine +echo "ONCALL_VERSION=1.19.1" >> .env -# Re-deploy +docker-compose pull docker-compose up -d ``` -The plugin is not published to grafana.com, so it does not update through the plugin catalog. Point -`GF_INSTALL_PLUGINS` at the archive from the [release](https://github.com/appwrite/grafana-oncall/releases) -matching the engine tag and recreate the Grafana container. +The plugin is not in the grafana.com catalog, so it does not update through the plugin page. Grafana +only installs a plugin that is not already present, so to move the plugin you also have to clear the +old copy from its volume: + +```shell +docker-compose exec grafana rm -rf /var/lib/grafana/plugins/grafana-oncall-app +docker-compose restart grafana +``` ## Join community diff --git a/docker-compose-mysql-rabbitmq.yml b/docker-compose-mysql-rabbitmq.yml index 6adb870d6c..280c7563d2 100644 --- a/docker-compose-mysql-rabbitmq.yml +++ b/docker-compose-mysql-rabbitmq.yml @@ -22,7 +22,7 @@ x-environment: &oncall-environment services: engine: - image: ghcr.io/appwrite/grafana-oncall:latest + image: ghcr.io/appwrite/grafana-oncall:v${ONCALL_VERSION:-1.19.1} restart: always ports: - "8080:8080" @@ -39,7 +39,7 @@ services: condition: service_started celery: - image: ghcr.io/appwrite/grafana-oncall:latest + image: ghcr.io/appwrite/grafana-oncall:v${ONCALL_VERSION:-1.19.1} restart: always command: sh -c "./celery_with_exporter.sh" environment: *oncall-environment @@ -54,7 +54,7 @@ services: condition: service_started oncall_db_migration: - image: ghcr.io/appwrite/grafana-oncall:latest + image: ghcr.io/appwrite/grafana-oncall:v${ONCALL_VERSION:-1.19.1} command: python manage.py migrate --noinput environment: *oncall-environment depends_on: @@ -143,9 +143,11 @@ services: GF_SECURITY_ADMIN_USER: ${GRAFANA_USER:-admin} GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_PASSWORD:-admin} GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS: grafana-oncall-app - # the catalog build is grafana's archived one, so install this fork's plugin archive + # The catalog build is grafana's archived one, so install this fork's plugin archive. + # ONCALL_VERSION pins the engine too: the plugin and engine are released together + # and are not meant to be mixed across versions. # yamllint disable-line rule:line-length - GF_INSTALL_PLUGINS: ${ONCALL_PLUGIN_URL:-https://github.com/appwrite/grafana-oncall/releases/download/v1.19.1/grafana-oncall-app-1.19.1.zip};grafana-oncall-app + GF_INSTALL_PLUGINS: https://github.com/appwrite/grafana-oncall/releases/download/v${ONCALL_VERSION:-1.19.1}/grafana-oncall-app-${ONCALL_VERSION:-1.19.1}.zip;grafana-oncall-app GF_AUTH_MANAGED_SERVICE_ACCOUNTS_ENABLED: true deploy: resources: diff --git a/docker-compose.yml b/docker-compose.yml index c2435d19ae..4ded47cede 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -16,7 +16,7 @@ x-environment: &oncall-environment services: engine: - image: ghcr.io/appwrite/grafana-oncall:latest + image: ghcr.io/appwrite/grafana-oncall:v${ONCALL_VERSION:-1.19.1} restart: always ports: - "8080:8080" @@ -31,7 +31,7 @@ services: condition: service_healthy celery: - image: ghcr.io/appwrite/grafana-oncall:latest + image: ghcr.io/appwrite/grafana-oncall:v${ONCALL_VERSION:-1.19.1} restart: always command: sh -c "./celery_with_exporter.sh" environment: *oncall-environment @@ -44,7 +44,7 @@ services: condition: service_healthy oncall_db_migration: - image: ghcr.io/appwrite/grafana-oncall:latest + image: ghcr.io/appwrite/grafana-oncall:v${ONCALL_VERSION:-1.19.1} command: python manage.py migrate --noinput environment: *oncall-environment volumes: @@ -93,9 +93,11 @@ services: GF_SECURITY_ADMIN_USER: ${GRAFANA_USER:-admin} GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_PASSWORD:-admin} GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS: grafana-oncall-app - # the catalog build is grafana's archived one, so install this fork's plugin archive + # The catalog build is grafana's archived one, so install this fork's plugin archive. + # ONCALL_VERSION pins the engine too: the plugin and engine are released together + # and are not meant to be mixed across versions. # yamllint disable-line rule:line-length - GF_INSTALL_PLUGINS: ${ONCALL_PLUGIN_URL:-https://github.com/appwrite/grafana-oncall/releases/download/v1.19.1/grafana-oncall-app-1.19.1.zip};grafana-oncall-app + GF_INSTALL_PLUGINS: https://github.com/appwrite/grafana-oncall/releases/download/v${ONCALL_VERSION:-1.19.1}/grafana-oncall-app-${ONCALL_VERSION:-1.19.1}.zip;grafana-oncall-app GF_AUTH_MANAGED_SERVICE_ACCOUNTS_ENABLED: true volumes: - grafana_data:/var/lib/grafana diff --git a/helm/oncall/Chart.yaml b/helm/oncall/Chart.yaml index efa02053da..31afed1091 100644 --- a/helm/oncall/Chart.yaml +++ b/helm/oncall/Chart.yaml @@ -2,8 +2,8 @@ apiVersion: v2 name: oncall description: Developer-friendly incident response with brilliant Slack integration type: application -version: 1.15.6 -appVersion: v1.15.6 +version: 1.19.1 +appVersion: v1.19.1 dependencies: - name: cert-manager version: v1.8.0 diff --git a/helm/oncall/README.md b/helm/oncall/README.md index 54072ba615..65b2fae33b 100644 --- a/helm/oncall/README.md +++ b/helm/oncall/README.md @@ -396,9 +396,18 @@ helm upgrade \ ./helm/oncall ``` -After re-deploying, please also update the Grafana OnCall plugin on the plugin version page. -See [Grafana docs](https://grafana.com/docs/grafana/latest/administration/plugin-management/#update-a-plugin) for -more info on updating Grafana plugins. +The plugin is not in the grafana.com catalog, so it does not update through the plugin page. It is +installed from the archive in `grafana.plugins`, which has to be moved to the same version as +`image.tag`/`appVersion` — the engine and plugin are released together and are not meant to be mixed +across versions. + +Grafana only installs a plugin that is not already present, so with `grafana.persistence` enabled the +old copy has to be cleared before it will reinstall: + +```bash +kubectl exec deploy/release-oncall-grafana -- rm -rf /var/lib/grafana/plugins/grafana-oncall-app +kubectl rollout restart deploy/release-oncall-grafana +``` ## Uninstall diff --git a/helm/oncall/values.yaml b/helm/oncall/values.yaml index 43c431e39b..6a15e009e6 100644 --- a/helm/oncall/values.yaml +++ b/helm/oncall/values.yaml @@ -642,13 +642,18 @@ grafana: accessControlOnCall: false env: GF_AUTH_MANAGED_SERVICE_ACCOUNTS_ENABLED: true + # this fork's plugin carries no grafana.com signature + GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS: grafana-oncall-app persistence: enabled: true # Disable psp as PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+ rbac: pspEnabled: false plugins: - - grafana-oncall-app + # Not the catalog build, which is grafana's archived one. Keep this version in step with + # image.tag/appVersion above: the plugin and engine are released together. + # yamllint disable-line rule:line-length + - https://github.com/appwrite/grafana-oncall/releases/download/v1.19.1/grafana-oncall-app-1.19.1.zip;grafana-oncall-app extraVolumes: - name: provisioning configMap: From 286299e0550db4fbaa91b1c4b5e11404ad8d3a97 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Thu, 13 Aug 2026 23:24:11 +0100 Subject: [PATCH 3/3] fix: derive the chart's plugin version from the engine tag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hardcoding the archive URL in grafana.plugins meant overriding image.tag updated the engine while the plugin stayed on 1.19.1 — the same skew as the compose default, just moved into the chart. Subchart values cannot be templated, but the grafana chart runs tpl over envValueFrom, so it can reference a ConfigMap this chart renders. That ConfigMap builds GF_INSTALL_PLUGINS from the same expression the engine image uses, so one knob moves both halves: helm template --set image.tag=v1.20.0 engine ghcr.io/appwrite/grafana-oncall:v1.20.0 plugin .../download/v1.20.0/grafana-oncall-app-1.20.0.zip The archive name drops the leading v while the tag keeps it, hence the trimPrefix. The helm README no longer asks anyone to keep two versions in step by hand. Co-Authored-By: Claude Fable 5 --- helm/oncall/README.md | 8 ++++---- helm/oncall/templates/grafana-plugin-env.yaml | 19 +++++++++++++++++++ helm/oncall/values.yaml | 13 ++++++++----- 3 files changed, 31 insertions(+), 9 deletions(-) create mode 100644 helm/oncall/templates/grafana-plugin-env.yaml diff --git a/helm/oncall/README.md b/helm/oncall/README.md index 65b2fae33b..6405924682 100644 --- a/helm/oncall/README.md +++ b/helm/oncall/README.md @@ -396,10 +396,10 @@ helm upgrade \ ./helm/oncall ``` -The plugin is not in the grafana.com catalog, so it does not update through the plugin page. It is -installed from the archive in `grafana.plugins`, which has to be moved to the same version as -`image.tag`/`appVersion` — the engine and plugin are released together and are not meant to be mixed -across versions. +The plugin is not in the grafana.com catalog, so it does not update through the plugin page. The +bundled Grafana installs it from this fork's release archive, and the chart derives that version from +`image.tag` (falling back to the chart's `appVersion`) — so bumping the engine moves the plugin with +it, and the two cannot end up on different versions. Grafana only installs a plugin that is not already present, so with `grafana.persistence` enabled the old copy has to be cleared before it will reinstall: diff --git a/helm/oncall/templates/grafana-plugin-env.yaml b/helm/oncall/templates/grafana-plugin-env.yaml new file mode 100644 index 0000000000..5965aa485d --- /dev/null +++ b/helm/oncall/templates/grafana-plugin-env.yaml @@ -0,0 +1,19 @@ +{{- if .Values.grafana.enabled }} +{{/* + The plugin is not in the grafana.com catalog, so the bundled Grafana installs it from this fork's + release archive. The version is taken from the same expression as the engine image, so overriding + image.tag moves both halves: they are released together and are not meant to be mixed. + + This is a ConfigMap because subchart values cannot be templated — grafana.envValueFrom points at + it, and the grafana chart runs tpl over that block so it can resolve the release-scoped name. +*/}} +{{- $version := .Values.image.tag | default .Chart.AppVersion }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ .Release.Name }}-oncall-plugin + labels: + app: {{ include "oncall.name" . }} +data: + GF_INSTALL_PLUGINS: https://github.com/appwrite/grafana-oncall/releases/download/{{ $version }}/grafana-oncall-app-{{ trimPrefix "v" $version }}.zip;grafana-oncall-app +{{- end }} diff --git a/helm/oncall/values.yaml b/helm/oncall/values.yaml index 6a15e009e6..4a10edac63 100644 --- a/helm/oncall/values.yaml +++ b/helm/oncall/values.yaml @@ -649,11 +649,14 @@ grafana: # Disable psp as PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+ rbac: pspEnabled: false - plugins: - # Not the catalog build, which is grafana's archived one. Keep this version in step with - # image.tag/appVersion above: the plugin and engine are released together. - # yamllint disable-line rule:line-length - - https://github.com/appwrite/grafana-oncall/releases/download/v1.19.1/grafana-oncall-app-1.19.1.zip;grafana-oncall-app + # The plugin archive comes from the ConfigMap this chart renders, which derives the version from + # image.tag/appVersion — so the engine and plugin cannot end up on different versions. Setting + # grafana.plugins here instead would install the catalog build, which is grafana's archived one. + envValueFrom: + GF_INSTALL_PLUGINS: + configMapKeyRef: + name: '{{ .Release.Name }}-oncall-plugin' + key: GF_INSTALL_PLUGINS extraVolumes: - name: provisioning configMap: