From 8b61a08b2e081e6ace1e577d70c62a42002f7b6a Mon Sep 17 00:00:00 2001 From: olalekan odukoya Date: Mon, 23 Mar 2026 19:38:00 +0100 Subject: [PATCH] prepare for release v3.7.6 --- .github/workflows/lint-test.yml | 14 ++- .gitignore | 1 - .helmignore | 1 + Chart.lock | 10 +- Chart.yaml | 13 ++- Makefile | 8 +- README.md | 4 +- README.md.gotmpl | 47 +++++++++ charts/agent/Chart.yaml | 2 +- charts/agent/values.yaml | 2 +- charts/server/Chart.yaml | 2 +- charts/server/values.yaml | 2 +- ci/integration-kind-values.yaml | 32 ++++++ ci/redis-sentinel-values.yaml | 13 +++ scripts/integration-kind-verify.sh | 115 ++++++++++++++++++++++ scripts/verify-redis-sentinel-template.sh | 41 ++++++++ values.yaml | 10 +- 17 files changed, 302 insertions(+), 15 deletions(-) create mode 100644 README.md.gotmpl create mode 100644 ci/integration-kind-values.yaml create mode 100644 ci/redis-sentinel-values.yaml create mode 100755 scripts/integration-kind-verify.sh create mode 100755 scripts/verify-redis-sentinel-template.sh diff --git a/.github/workflows/lint-test.yml b/.github/workflows/lint-test.yml index 623dbc0..e241510 100755 --- a/.github/workflows/lint-test.yml +++ b/.github/workflows/lint-test.yml @@ -34,6 +34,11 @@ jobs: - name: Run chart-testing (lint) run: ct lint --config ct.yaml --all + - name: Verify Redis Sentinel values render (helm template) + run: | + chmod +x scripts/verify-redis-sentinel-template.sh + ./scripts/verify-redis-sentinel-template.sh + - name: Create kind cluster uses: helm/kind-action@v1.12.0 if: steps.list-changed.outputs.changed == 'true' @@ -41,8 +46,13 @@ jobs: - name: Test main convoy chart installation if: steps.list-changed.outputs.changed == 'true' run: | - echo "Testing main convoy chart with root values..." + echo "Testing main convoy chart (Redis Sentinel + Postgres, Kind integration)..." helm dependency build . - helm install convoy-test . --values values.yaml --timeout 300s --wait --wait-for-jobs --debug + helm install convoy-test . \ + --values values.yaml \ + --values ci/integration-kind-values.yaml \ + --timeout 900s --wait --wait-for-jobs --debug helm test convoy-test + chmod +x scripts/integration-kind-verify.sh + ./scripts/integration-kind-verify.sh helm uninstall convoy-test diff --git a/.gitignore b/.gitignore index 249888c..92a43e0 100755 --- a/.gitignore +++ b/.gitignore @@ -35,4 +35,3 @@ Session.vim **/charts/*.tgz .history -README.md.gotmpl diff --git a/.helmignore b/.helmignore index cbfeaac..50a0767 100755 --- a/.helmignore +++ b/.helmignore @@ -24,6 +24,7 @@ # GitHub workflows and CI/CD .github/ +ci/ scripts/ .helmdocsignore diff --git a/Chart.lock b/Chart.lock index cad841f..049efa3 100644 --- a/Chart.lock +++ b/Chart.lock @@ -5,5 +5,11 @@ dependencies: - name: redis repository: oci://registry-1.docker.io/bitnamicharts version: 17.11.3 -digest: sha256:b4b067f4aef7360d36c1d36fb970183aafb7ecae01fbfcd09892a6e277874765 -generated: "2025-11-14T17:29:01.591698+01:00" +- name: agent + repository: "" + version: 3.7.6 +- name: server + repository: "" + version: 3.7.6 +digest: sha256:25afc9b03cd96a3fa18053eedbf24f0a47747536278a093c7918d6a46ddaa9e3 +generated: "2026-03-23T21:35:32.093441+01:00" diff --git a/Chart.yaml b/Chart.yaml index e0535a4..5473a55 100755 --- a/Chart.yaml +++ b/Chart.yaml @@ -3,7 +3,7 @@ name: convoy description: Open Source Webhooks Gateway type: application version: "3.7.6" -appVersion: "v26.1.4" +appVersion: "v26.3.5" keywords: - Webhooks - Kubernetes @@ -23,3 +23,14 @@ dependencies: version: 17.11.3 repository: oci://registry-1.docker.io/bitnamicharts condition: redis.enabled + + # Vendored subcharts under charts/agent and charts/server (see charts/ directory). + - name: agent + version: 3.7.6 + repository: "" + condition: agent.enabled + + - name: server + version: 3.7.6 + repository: "" + condition: server.enabled diff --git a/Makefile b/Makefile index a6569e6..6d97689 100644 --- a/Makefile +++ b/Makefile @@ -4,4 +4,10 @@ ct: docs: helm-docs -.PHONY: ct docs +test-sentinel-template: + ./scripts/verify-redis-sentinel-template.sh + +integration-kind-verify: + ./scripts/integration-kind-verify.sh + +.PHONY: ct docs test-sentinel-template integration-kind-verify diff --git a/README.md b/README.md index 48afe22..9058561 100755 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # convoy -![Version: 3.7.5](https://img.shields.io/badge/Version-3.7.5-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v26.1.4](https://img.shields.io/badge/AppVersion-v26.1.4-informational?style=flat-square) +![Version: 3.7.6](https://img.shields.io/badge/Version-3.7.6-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v26.3.5](https://img.shields.io/badge/AppVersion-v26.3.5-informational?style=flat-square) Open Source Webhooks Gateway @@ -152,7 +152,7 @@ helm install convoy . | global.convoy.sentry_dsn | string | `""` | Sentry DSN | | global.convoy.sentry_environment | string | `"oss"` | Sentry environment | | global.convoy.sentry_sample_rate | float | `1` | Sentry sample rate for error sampling (0.0 to 1.0) | -| global.convoy.tag | string | `"v26.1.4"` | Docker image tags for all convoy components | +| global.convoy.tag | string | `"v26.3.5"` | Docker image tags for all convoy components | | global.convoy.tracer_enabled | bool | `false` | Tracing config for all convoy services | | global.convoy.tracer_type | string | `"otel"` | Tracing provider type | | global.externalDatabase.database | string | `"convoy"` | Database name for the external database | diff --git a/README.md.gotmpl b/README.md.gotmpl new file mode 100644 index 0000000..df8dd3b --- /dev/null +++ b/README.md.gotmpl @@ -0,0 +1,47 @@ +{{ template "chart.header" . }} +{{ template "chart.deprecationWarning" . }} + +{{ template "chart.badgesSection" . }} + +{{ template "chart.description" . }} + +{{ template "chart.homepageLine" . }} + +{{ template "chart.maintainersSection" . }} + +{{ template "chart.sourcesSection" . }} + +{{ template "chart.requirementsSection" . }} + +## Installation + +### Add the Helm repository + +```bash +helm repo add convoy https://frain-dev.github.io/helm-charts +helm repo update +``` + +### Install the chart + +```bash +helm install convoy convoy/convoy +``` + +### Install with custom values + +```bash +helm install convoy convoy/convoy --values values.yaml +``` + +### Install from local chart + +```bash +helm install convoy . +``` + +{{ template "chart.valuesSection" . }} + +{{- if not .SkipVersionFooter }} +{{ template "helm-docs.versionFooter" . }} +{{- end }} diff --git a/charts/agent/Chart.yaml b/charts/agent/Chart.yaml index 40852e6..40e81ad 100755 --- a/charts/agent/Chart.yaml +++ b/charts/agent/Chart.yaml @@ -3,7 +3,7 @@ name: agent description: Convoy Agent Chart type: application version: "3.7.6" -appVersion: "v26.1.4" +appVersion: "v26.3.5" maintainers: - name: Convoy Engineering Team email: engineering@getconvoy.io diff --git a/charts/agent/values.yaml b/charts/agent/values.yaml index 576f5b9..5e283cc 100755 --- a/charts/agent/values.yaml +++ b/charts/agent/values.yaml @@ -154,7 +154,7 @@ env: image: repository: getconvoy/convoy pullPolicy: IfNotPresent - tag: v26.1.4 + tag: v26.3.5 nameOverride: "convoy-agent" fullNameOverride: "convoy-agent" diff --git a/charts/server/Chart.yaml b/charts/server/Chart.yaml index d75927e..fee5335 100755 --- a/charts/server/Chart.yaml +++ b/charts/server/Chart.yaml @@ -21,7 +21,7 @@ version: "3.7.6" # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: "v26.1.4" +appVersion: "v26.3.5" maintainers: - name: Convoy Engineering Team diff --git a/charts/server/values.yaml b/charts/server/values.yaml index df4b56d..568cf5e 100755 --- a/charts/server/values.yaml +++ b/charts/server/values.yaml @@ -157,7 +157,7 @@ env: image: repository: getconvoy/convoy pullPolicy: Always - tag: v26.1.4 + tag: v26.3.5 nameOverride: "convoy-server" fullNameOverride: "convoy-server" diff --git a/ci/integration-kind-values.yaml b/ci/integration-kind-values.yaml new file mode 100644 index 0000000..5e654ab --- /dev/null +++ b/ci/integration-kind-values.yaml @@ -0,0 +1,32 @@ +global: + nativeRedis: + enabled: false + externalRedis: + enabled: true + host: redis + port: "26379" + scheme: redis-sentinel + sentinelMasterName: mymaster + sentinelPassword: convoy + password: convoy + +redis: + architecture: replication + sentinel: + enabled: true + masterSet: mymaster + quorum: 2 + replica: + replicaCount: 2 + persistence: + enabled: false + master: + persistence: + enabled: false + auth: + sentinel: true + +postgresql: + primary: + persistence: + enabled: false diff --git a/ci/redis-sentinel-values.yaml b/ci/redis-sentinel-values.yaml new file mode 100644 index 0000000..a41e328 --- /dev/null +++ b/ci/redis-sentinel-values.yaml @@ -0,0 +1,13 @@ +# Overlay for agent/server subcharts: external Redis via Sentinel (helm template checks). +# Used by scripts/verify-redis-sentinel-template.sh +global: + nativeRedis: + enabled: false + externalRedis: + enabled: true + host: redis + port: "26379" + scheme: redis-sentinel + sentinelMasterName: mymaster + sentinelPassword: convoy + password: convoy diff --git a/scripts/integration-kind-verify.sh b/scripts/integration-kind-verify.sh new file mode 100755 index 0000000..5e2b852 --- /dev/null +++ b/scripts/integration-kind-verify.sh @@ -0,0 +1,115 @@ +#!/usr/bin/env bash +# This script verifies: +# - Redis Sentinel responds and reports a master; SET/GET on the master +# - PostgreSQL accepts a query on the convoy database +set -euo pipefail + +NS="${1:-default}" +REDIS_SVC="${REDIS_SVC:-redis}" +REDIS_SENTINEL_PORT="${REDIS_SENTINEL_PORT:-26379}" +PG_SVC="${PG_SVC:-postgresql}" +PG_DB="${PG_DB:-convoy}" +PG_USER="${PG_USER:-postgres}" +MASTER_SET="${MASTER_SET:-mymaster}" +VERIFY_KEY="${VERIFY_KEY:-convoy_ci_verify}" + +wait_terminal_phase() { + local pod=$1 + local start now + start=$(date +%s) + while :; do + now=$(date +%s) + if [ $((now - start)) -ge 240 ]; then + echo "Timeout" + return 1 + fi + local phase + phase=$(kubectl get pod "$pod" -n "$NS" -o jsonpath='{.status.phase}' 2>/dev/null || echo Pending) + if [ "$phase" = Succeeded ] || [ "$phase" = Failed ]; then + echo "$phase" + return 0 + fi + sleep 2 + done +} + +echo "Waiting for Redis Sentinel nodes (statefulset/redis-node)..." +kubectl rollout status "statefulset/redis-node" -n "$NS" --timeout=400s + +echo "Waiting for PostgreSQL primary..." +kubectl rollout status "statefulset/postgresql" -n "$NS" --timeout=400s + +REDIS_PASS=$(kubectl get secret redis -n "$NS" -o jsonpath='{.data.redis-password}' | base64 -d) +PG_PASS=$(kubectl get secret postgresql -n "$NS" -o jsonpath='{.data.postgres-password}' | base64 -d) + +POD_REDIS="convoy-ci-redis-verify-$$" +POD_PG="convoy-ci-pg-verify-$$" + +cleanup() { + kubectl delete pod -n "$NS" "$POD_REDIS" --ignore-not-found=true --wait=false 2>/dev/null || true + kubectl delete pod -n "$NS" "$POD_PG" --ignore-not-found=true --wait=false 2>/dev/null || true +} +trap cleanup EXIT + +echo "Verifying Redis via Sentinel (${REDIS_SVC}:${REDIS_SENTINEL_PORT})..." +kubectl run "$POD_REDIS" -n "$NS" --restart=Never \ + --image=docker.io/library/redis:7-alpine \ + --env="REDISCLI_AUTH=${REDIS_PASS}" \ + --env="R_SVC=${REDIS_SVC}" \ + --env="R_SENT_PORT=${REDIS_SENTINEL_PORT}" \ + --env="R_MASTER_SET=${MASTER_SET}" \ + --env="R_KEY=${VERIFY_KEY}" \ + --command -- sh -ec ' +set -euo pipefail +redis-cli -h "$R_SVC" -p "$R_SENT_PORT" --no-auth-warning PING | grep -qx PONG +OUT=$(redis-cli -h "$R_SVC" -p "$R_SENT_PORT" --no-auth-warning --raw SENTINEL get-master-addr-by-name "$R_MASTER_SET" || true) +if [ -z "$OUT" ]; then + echo "SENTINEL get-master-addr-by-name failed or empty" + exit 1 +fi +MASTER_HOST=$(printf "%s\n" "$OUT" | sed -n "1p") +MASTER_PORT=$(printf "%s\n" "$OUT" | sed -n "2p") +if [ -z "$MASTER_HOST" ] || [ -z "$MASTER_PORT" ]; then + MASTER_HOST=$(printf "%s\n" "$OUT" | awk "{print \$1}") + MASTER_PORT=$(printf "%s\n" "$OUT" | awk "{print \$2}") +fi +if [ -z "$MASTER_HOST" ] || [ -z "$MASTER_PORT" ]; then + echo "Could not parse master host/port from sentinel output: $OUT" + exit 1 +fi +redis-cli -h "$MASTER_HOST" -p "$MASTER_PORT" --no-auth-warning SET "$R_KEY" ok +test "$(redis-cli -h "$MASTER_HOST" -p "$MASTER_PORT" --no-auth-warning GET "$R_KEY")" = ok +echo "Redis Sentinel + master read/write OK" +' + +phase_r=$(wait_terminal_phase "$POD_REDIS") || true +if [ "$phase_r" != Succeeded ]; then + echo "--- Redis verify pod logs ---" + kubectl logs "$POD_REDIS" -n "$NS" 2>/dev/null || true + echo "Redis verify failed: phase=${phase_r}" + exit 1 +fi + +echo "Verifying PostgreSQL (${PG_SVC}, db=${PG_DB})..." +kubectl run "$POD_PG" -n "$NS" --restart=Never \ + --image=docker.io/library/postgres:17-alpine \ + --env="PGPASS=${PG_PASS}" \ + --env="PG_SVC=${PG_SVC}" \ + --env="PG_DB=${PG_DB}" \ + --env="PG_USER=${PG_USER}" \ + --command -- sh -ec ' +set -euo pipefail +export PGPASSWORD="$PGPASS" +psql -h "$PG_SVC" -U "$PG_USER" -d "$PG_DB" -v ON_ERROR_STOP=1 -c "SELECT 1 AS ok;" +echo "PostgreSQL query OK" +' + +phase_p=$(wait_terminal_phase "$POD_PG") || true +if [ "$phase_p" != Succeeded ]; then + echo "--- Postgres verify pod logs ---" + kubectl logs "$POD_PG" -n "$NS" 2>/dev/null || true + echo "PostgreSQL verify failed: phase=${phase_p}" + exit 1 +fi + +echo "Integration checks passed." diff --git a/scripts/verify-redis-sentinel-template.sh b/scripts/verify-redis-sentinel-template.sh new file mode 100755 index 0000000..c144ba2 --- /dev/null +++ b/scripts/verify-redis-sentinel-template.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash +# Render agent and server subcharts with Sentinel values; assert expected env vars. +set -euo pipefail + +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +cd "$ROOT" + +OVERLAY="${ROOT}/ci/redis-sentinel-values.yaml" + +fail() { + echo "verify-redis-sentinel-template: $*" >&2 + exit 1 +} + +assert_sentinel_env() { + local name="$1" + local out="$2" + + local n_scheme + n_scheme="$(echo "$out" | grep -cE 'value: "?redis-sentinel"?' || true)" + [[ "${n_scheme}" -ge 1 ]] || fail "${name}: expected CONVOY_REDIS_SCHEME=redis-sentinel (got ${n_scheme})" + + echo "$out" | grep -q 'name: CONVOY_REDIS_SENTINEL_MASTER_NAME' || fail "${name}: missing CONVOY_REDIS_SENTINEL_MASTER_NAME" + echo "$out" | grep -qE 'value: "?mymaster"?' || fail "${name}: missing sentinel master name mymaster" + + echo "$out" | grep -qE 'name[[:space:]]*:[[:space:]]*CONVOY_REDIS_PORT' || fail "${name}: missing CONVOY_REDIS_PORT" + echo "$out" | grep -qE 'value: "?26379"?$' || fail "${name}: missing CONVOY_REDIS_PORT 26379" + + echo "$out" | grep -q 'name: CONVOY_REDIS_TYPE' || fail "${name}: missing CONVOY_REDIS_TYPE" + echo "$out" | grep -qE 'value: "?EXTERNAL"?' || fail "${name}: missing CONVOY_REDIS_TYPE EXTERNAL" + + echo "$out" | grep -q 'name: CONVOY_REDIS_SENTINEL_PASSWORD' || fail "${name}: missing CONVOY_REDIS_SENTINEL_PASSWORD" +} + +OUT_AGENT="$(helm template sentinel-agent-test ./charts/agent -f charts/agent/values.yaml -f "${OVERLAY}")" +assert_sentinel_env "charts/agent" "${OUT_AGENT}" + +OUT_SERVER="$(helm template sentinel-server-test ./charts/server -f charts/server/values.yaml -f "${OVERLAY}")" +assert_sentinel_env "charts/server" "${OUT_SERVER}" + +echo "verify-redis-sentinel-template: OK (agent + server)" diff --git a/values.yaml b/values.yaml index f3b3435..f87a9bc 100755 --- a/values.yaml +++ b/values.yaml @@ -3,7 +3,7 @@ global: # -- Docker image tags for all convoy components image: &image "getconvoy/convoy" # -- Docker image tags for all convoy components - tag: &tag "v26.1.4" + tag: &tag "v26.3.5" # -- Logger Level for all convoy components log_level: &logLevel "error" # -- Convoy Environment @@ -158,8 +158,14 @@ redis: image: registry: docker.io repository: bitnamilegacy/redis - tag: 8.2.1-debian-12-r0 + tag: &redisImageTag 8.2.1-debian-12-r0 pullPolicy: IfNotPresent + sentinel: + image: + registry: docker.io + repository: bitnamilegacy/redis-sentinel + tag: *redisImageTag + pullPolicy: IfNotPresent architecture: standalone fullnameOverride: "redis" auth: