diff --git a/.github/workflows/workflows-queue-consistency.yaml b/.github/workflows/workflows-queue-consistency.yaml new file mode 100644 index 0000000..ccb4794 --- /dev/null +++ b/.github/workflows/workflows-queue-consistency.yaml @@ -0,0 +1,31 @@ +name: Workflows queue consistency + +# Fails the build if the analysis producer, the workflows engine and the stage +# workers would render onto different WORKFLOWS_QUEUE names — the silent +# producer/consumer queue-name drift that leaves runs piling up with no +# consumer. Pure `helm template` render check, no cluster required. +on: + workflow_dispatch: + pull_request: + paths: + - 'charts/hub/**' + - 'scripts/check-workflows-queue-consistency.sh' + - '.github/workflows/workflows-queue-consistency.yaml' + +permissions: + contents: read + +jobs: + check: + runs-on: ubuntu-24.04 + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Helm + uses: azure/setup-helm@v4 + with: + version: v3.16.2 + + - name: Check WORKFLOWS_QUEUE consistency + run: ./scripts/check-workflows-queue-consistency.sh charts/hub diff --git a/charts/hub/custom-layout/templates/share_case.html b/charts/hub/custom-layout/templates/share_case.html new file mode 100644 index 0000000..cfd790d --- /dev/null +++ b/charts/hub/custom-layout/templates/share_case.html @@ -0,0 +1,418 @@ + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
Kerberos.io +

Kerberos.io

+
+ +

{{tab1_title}}

+
+
+ +

{{tab2_title}}

+
+
+
+ + + + +
+ + + + + + + + +
+

A case has been shared with you

+

{{user}} shared a case with you

+
+
+ + + + +
+ + + + + + + + +
+

Open the shared case

+

{{user}} has shared a case with you. Click the button below to open it. You'll be asked to request a one-time verification code from the share page itself.

This link will expire in {{expiry}}.

+ + + +

Open case ->

+
+
+
+ + + + +
+ + + + + + + + + + + + + + + + + + +
+
+ + diff --git a/charts/hub/custom-layout/templates/share_case.txt b/charts/hub/custom-layout/templates/share_case.txt new file mode 100644 index 0000000..ce660dc --- /dev/null +++ b/charts/hub/custom-layout/templates/share_case.txt @@ -0,0 +1,21 @@ +Kerberos.io +------------ + +A case has been shared with you +{{user}} shared a case with you + +Open the shared case +{{user}} has shared a case with you. Open the link below to access it — you'll be asked to request a one-time verification code from the share page. +{{url}} + +This link will expire in {{expiry}}. + +Get in touch +------------ +support@kerberos.io +9000 Ghent, BE +https://kerberos.io + +About Kerberos +------------ +Welcome to the revolutionary video analytics and video management platform. Open, modular, and extensible for everyone, anywhere. diff --git a/charts/hub/custom-layout/templates/share_case_otp.html b/charts/hub/custom-layout/templates/share_case_otp.html new file mode 100644 index 0000000..52c0dbf --- /dev/null +++ b/charts/hub/custom-layout/templates/share_case_otp.html @@ -0,0 +1,425 @@ + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
Kerberos.io +

Kerberos.io

+
+ +

{{tab1_title}}

+
+
+ +

{{tab2_title}}

+
+
+
+ + + + +
+ + + + + + + + +
+

Verify your access

+

Use the code below to open the shared case

+
+
+ + + + +
+ + + + + + + + +
+

Your verification code

+

Enter the code below on the share page to access the case.

+ +

{{code}}

+ +

This code expires in {{expiry}}. If you didn't request this, you can safely ignore this email.

+
+
+ + + + +
+ + + + + + + + + + + + + + + + + + +
+
+ + diff --git a/charts/hub/custom-layout/templates/share_case_otp.txt b/charts/hub/custom-layout/templates/share_case_otp.txt new file mode 100644 index 0000000..46b46b0 --- /dev/null +++ b/charts/hub/custom-layout/templates/share_case_otp.txt @@ -0,0 +1,21 @@ +Kerberos.io +------------ + +Verify your access +Use the code below to open the shared case + +Your verification code +{{code}} + +Enter this code on the share page to access the case. This code expires in {{expiry}}. +If you didn't request this, you can safely ignore this email. + +Get in touch +------------ +support@kerberos.io +9000 Ghent, BE +https://kerberos.io + +About Kerberos +------------ +Welcome to the revolutionary video analytics and video management platform. Open, modular, and extensible for everyone, anywhere. diff --git a/charts/hub/templates/kerberos-hub/hub-api.yaml b/charts/hub/templates/kerberos-hub/hub-api.yaml index 77140b8..59bfc48 100644 --- a/charts/hub/templates/kerberos-hub/hub-api.yaml +++ b/charts/hub/templates/kerberos-hub/hub-api.yaml @@ -353,6 +353,14 @@ spec: value: "{{ .Values.email.templates.share }}" - name: SHARE_TITLE value: "{{ .Values.email.templates.shareTitle }}" + - name: CASE_SHARE_TEMPLATE + value: "{{ .Values.email.templates.caseShare }}" + - name: CASE_SHARE_TITLE + value: "{{ .Values.email.templates.caseShareTitle }}" + - name: CASE_SHARE_OTP_TEMPLATE + value: "{{ .Values.email.templates.caseShareOtp }}" + - name: CASE_SHARE_OTP_TITLE + value: "{{ .Values.email.templates.caseShareOtpTitle }}" - name: ASSIGN_TASK_TEMPLATE value: "{{ .Values.email.templates.assignTask }}" - name: ASSIGN_TASK_TITLE diff --git a/charts/hub/values.yaml b/charts/hub/values.yaml index 216313b..05b579c 100644 --- a/charts/hub/values.yaml +++ b/charts/hub/values.yaml @@ -1119,6 +1119,10 @@ email: forgotTitle: "Password reset Kerberos Hub. You forgot your password" share: "share" shareTitle: "[Action] You received a recording from Kerberos Hub" + caseShare: "share_case" + caseShareTitle: "[Action] A case has been shared with you on Kerberos Hub" + caseShareOtp: "share_case_otp" + caseShareOtpTitle: "Your Kerberos Hub verification code" assignTask: "assign_task" assignTaskTitle: "[Action] You've been assigned to a task" detection: "detection" diff --git a/scripts/check-workflows-queue-consistency.sh b/scripts/check-workflows-queue-consistency.sh new file mode 100755 index 0000000..687d7a6 --- /dev/null +++ b/scripts/check-workflows-queue-consistency.sh @@ -0,0 +1,89 @@ +#!/usr/bin/env bash +# +# Render the hub chart and assert that every deployment which carries the +# workflows hand-off queue (the WORKFLOWS_QUEUE env var) resolves to the SAME, +# non-empty value. +# +# Why: the analysis pipeline (pipe-analysis) publishes opened workflow runs to +# WORKFLOWS_QUEUE, the workflows engine (hub-workflows) consumes it, and every +# stage worker (hub-stage) routes its result back to it. All three templates +# read the single key `kerberoshub.services.workflows.queue`. If a future edit +# hardcodes a value, reads the wrong key, or drops the env on one of them, the +# producer and consumer silently drift onto different queue names and messages +# pile up with no consumer. This check fails the build before that can ship. +# +# Usage: scripts/check-workflows-queue-consistency.sh [chart-dir] +# (chart-dir defaults to charts/hub, relative to the repo root) + +set -euo pipefail + +CHART_DIR="${1:-charts/hub}" +PROBE="drift-probe-queue-name" + +# Flags that force all three deployment kinds (analysis, engine and one stage +# worker) to render, so the check actually has something to compare. anpr is a +# stage/worker shipped in the chart's default values. +RENDER_FLAGS=( + --set mode=all + --set kerberoshub.workflows.enabled=true + --set kerberoshub.workflows.stages.anpr.enabled=true + --set kerberoshub.services.anpr.enabled=true +) + +# Read `helm template` output on stdin and print one WORKFLOWS_QUEUE value per +# line. Matches the `- name: WORKFLOWS_QUEUE` env entry and captures the value +# from the following `value:` line, skipping blank/comment lines in between. +extract_workflows_queue() { + awk ' + /^[[:space:]]*-[[:space:]]*name:[[:space:]]*WORKFLOWS_QUEUE[[:space:]]*$/ { want=1; next } + want==1 { + if ($0 ~ /^[[:space:]]*#/ || $0 ~ /^[[:space:]]*$/) next + v=$0 + sub(/^[[:space:]]*value:[[:space:]]*/, "", v) + sub(/^"/, "", v); sub(/"[[:space:]]*$/, "", v) + sub(/[[:space:]]+$/, "", v) + print v + want=0 + } + ' +} + +assert_all_equal() { + local expected="$1"; shift + local label="$1"; shift + local -a vals=("$@") + + if [ "${#vals[@]}" -lt 2 ]; then + echo "FAIL (${label}): expected at least 2 WORKFLOWS_QUEUE values (analysis + engine), found ${#vals[@]}" >&2 + return 1 + fi + + local v + for v in "${vals[@]}"; do + if [ -z "${v}" ]; then + echo "FAIL (${label}): a deployment rendered an empty WORKFLOWS_QUEUE value" >&2 + return 1 + fi + if [ "${v}" != "${expected}" ]; then + echo "FAIL (${label}): WORKFLOWS_QUEUE drift detected — expected '${expected}' but a deployment rendered '${v}'" >&2 + printf ' rendered values: %s\n' "${vals[*]}" >&2 + return 1 + fi + done + + echo "OK (${label}): ${#vals[@]} deployments all use WORKFLOWS_QUEUE='${expected}'" +} + +echo "== Rendering ${CHART_DIR} with the chart's default workflows queue ==" +default_out="$(helm template hub "${CHART_DIR}" "${RENDER_FLAGS[@]}")" +mapfile -t default_vals < <(printf '%s\n' "${default_out}" | extract_workflows_queue) +default_queue="${default_vals[0]:-}" +assert_all_equal "${default_queue}" "default values" "${default_vals[@]}" || exit 1 + +echo "== Rendering ${CHART_DIR} with an overridden workflows queue (-> ${PROBE}) ==" +probe_out="$(helm template hub "${CHART_DIR}" "${RENDER_FLAGS[@]}" \ + --set kerberoshub.services.workflows.queue="${PROBE}")" +mapfile -t probe_vals < <(printf '%s\n' "${probe_out}" | extract_workflows_queue) +assert_all_equal "${PROBE}" "override probe" "${probe_vals[@]}" || exit 1 + +echo "All WORKFLOWS_QUEUE consistency checks passed."