Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 36 additions & 25 deletions .github/workflows/helm-chart-checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ jobs:
python -I -m pip install --only-binary :all: PyYAML==6.0.2
python scripts/ci/test_database_tls_chart.py

- name: Check that native 3.x images are refused
run: python scripts/ci/test_helm_native_image_guard.py
- name: Check what each runtime renders and refuses
run: python scripts/ci/test_helm_runtime_modes.py

- name: Render every CI fixture
run: |
Expand Down Expand Up @@ -228,33 +228,42 @@ jobs:
fi
scripts/helm-chart-kind-smoke.sh

- name: Run native kind smoke script
env:
K8S_HELM_SMOKE_CLUSTER: ${{ env.HELM_CT_CLUSTER_NAME }}
K8S_HELM_SMOKE_REUSE_CLUSTER: "1"
K8S_HELM_NATIVE_SMOKE_ARTIFACT_DIR: ${{ runner.temp }}/helm-native-smoke
run: scripts/helm-chart-native-kind-smoke.sh

- name: Print smoke diagnostics
if: failure()
run: |
artifact_dir="${{ runner.temp }}/helm-smoke"
if [ ! -d "${artifact_dir}" ]; then
echo "no smoke artifacts collected"
exit 0
fi

for file in \
helm-status.txt \
events.txt \
describe.txt \
resources.txt \
migration-job.log \
server.log \
worker.log \
mysql.log \
redis.log \
port-forward.log; do
path="${artifact_dir}/${file}"
if [ ! -f "${path}" ]; then
for artifact_dir in "${{ runner.temp }}/helm-smoke" "${{ runner.temp }}/helm-native-smoke"; do
if [ ! -d "${artifact_dir}" ]; then
echo "no smoke artifacts collected in ${artifact_dir}"
continue
fi
echo "::group::${file}"
tail -n 200 "${path}" || cat "${path}" || true
echo "::endgroup::"

for file in \
helm-status.txt \
events.txt \
describe.txt \
resources.txt \
migration-job.log \
schema-upgrade.log \
server.log \
worker.log \
mysql.log \
redis.log \
port-forward.log; do
path="${artifact_dir}/${file}"
if [ ! -f "${path}" ]; then
continue
fi
echo "::group::$(basename "${artifact_dir}")/${file}"
tail -n 200 "${path}" || cat "${path}" || true
echo "::endgroup::"
done
done

- name: Upload smoke artifacts
Expand All @@ -263,7 +272,9 @@ jobs:
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: helm-chart-kind-smoke
path: ${{ runner.temp }}/helm-smoke
path: |
${{ runner.temp }}/helm-smoke
${{ runner.temp }}/helm-native-smoke
if-no-files-found: ignore

- name: Clean up kind infrastructure
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/helm-chart-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ on:
paths:
- "k8s/helm/**"
- "scripts/helm-chart-kind-smoke.sh"
- "scripts/helm-chart-native-kind-smoke.sh"
- "scripts/helm-chart-kind-fixtures.yaml"
- "scripts/ci/helm_chart_release.py"
- "scripts/ci/cleanup-kind-cluster.sh"
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/helm-chart-validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ on:
paths:
- "k8s/helm/**"
- "scripts/helm-chart-kind-smoke.sh"
- "scripts/helm-chart-native-kind-smoke.sh"
- "scripts/helm-chart-kind-fixtures.yaml"
- "scripts/ci/helm_chart_release.py"
- "scripts/ci/cleanup-kind-cluster.sh"
- "scripts/ci/test_helm_chart_release.py"
- "scripts/ci/test_database_tls_chart.py"
- "scripts/ci/test_helm_runtime_modes.py"
- "uv.toml"
- ".github/workflows/helm-chart-checks.yml"
- ".github/workflows/helm-chart-validation.yml"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ contract, so a workflow in one language can dispatch activities to another.
| SQLite containers | Local evaluation with minimal infrastructure | [Official image and SQLite](docs/server-reference.md#official-image--sqlite) |
| Compose with MySQL and Redis | Development and single-host production | [Compose deployment](docs/server-reference.md#official-image--compose) |
| Small cluster | Multiple API nodes with external persistence | [Small-cluster contract](docs/small-cluster-validation.md) |
| Kubernetes | Independently scalable API and worker pools | [Helm chart](k8s/helm/durable-workflow/README.md) |
| Kubernetes | Native API replicas on Kubernetes, or the PHP 2.x shape for existing installs | [Helm chart](k8s/helm/durable-workflow/README.md) |
| Active/passive regions | Operator-controlled regional failover | [Multi-region contract](docs/multi-region-validation.md) |

Server supports SQLite for a single-node runtime and MySQL or PostgreSQL for
Expand Down
34 changes: 29 additions & 5 deletions docs/helm-validation.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,17 +158,41 @@ touches `k8s/helm/**` or the chart smoke script. The harness has two jobs:
- runs `helm upgrade` in place and re-checks readiness;
- runs `helm uninstall` and asserts no chart-owned resources remain.

The CI fixtures intentionally cover four shapes:
The same job then runs `scripts/helm-chart-native-kind-smoke.sh`, which
installs the native Server from the chart's default published image
against a fresh in-cluster MySQL database and:
- waits for the single server Deployment to become ready and runs
`helm test`;
- asserts that no worker, scheduler, migration Job or Redis Secret exists;
- upgrades with an empty `runtime` and confirms the release stays native;
- confirms that the schema-upgrade hook refuses unless live state proves
every Server stopped (replicas above zero, a client-side render,
autoscaling in the values, a live autoscaler, a live server pod, an
unmarked or PHP-marked predecessor), then renders and runs it, and the
hook verifies the current schema;
- confirms that an upgrade of a release whose server Deployment lacks the
native runtime marker refuses an empty `runtime`;
- runs `helm uninstall` and asserts no chart-owned resources remain.

The CI fixtures intentionally cover six shapes:

| Fixture | Purpose |
| --- | --- |
| `ci/inline-secrets-values.yaml` | Smallest renderable chart — exercises secret rendering. |
| `ci/existing-secrets-values.yaml` | GitOps / externally-managed-secret path. The chart renders no Secret resources of its own. |
| `ci/ingress-and-hpa-values.yaml` | Optional templates: Ingress, HPA, NetworkPolicy, server + worker PDB. |
| `ci/database-tls-values.yaml` | External CA Secret, canonical TLS settings and read-only mounts in every PHP role. |

A chart change that affects rendered manifests must keep all four
fixtures green, and the kind smoke must end with a clean uninstall.
| `ci/database-tls-values.yaml` | External CA Secret, canonical TLS settings and read-only mounts. Renders native by default. The TLS test also renders it in PHP mode. |
| `ci/native-inline-secrets-values.yaml` | Native Server with inline secrets: one Deployment, no PHP roles. |
| `ci/native-ingress-and-hpa-values.yaml` | Native with Ingress, HPA, NetworkPolicy, PDB and the shared payload claim that more than one replica needs. |

The first three fixtures pin `runtime: php`. A chart change that affects
rendered manifests must keep every fixture green, and both kind smokes must
end with a clean uninstall.

`scripts/ci/test_helm_runtime_modes.py` checks what each runtime renders, that
a tag from the other runtime is refused, that an upgrade with an empty
`runtime` must find a native release, and the native render-time refusals
that mirror native startup refusals.

`scripts/ci/test_database_tls_chart.py` also checks both pre-install-hook and
ordinary bootstrap ordering, CA path/key consistency, and preservation of
Expand Down
10 changes: 6 additions & 4 deletions k8s/helm/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@ standalone server, together with the example values files and CI fixtures.
* `durable-workflow/` — the chart itself. See its
[README](durable-workflow/README.md) and
[UPGRADING guide](durable-workflow/docs/UPGRADING.md).
* `examples/` — copy-and-adapt values files for the most common shapes
(production with externally-managed secrets, dev, External Secrets
Operator companion, etc.).
* `examples/` — copy-and-adapt values files. `values-native-dev.yaml` runs
the native Server, the chart default. The others keep an existing PHP 2.x
installation (`runtime: php`): production with externally-managed secrets,
dev, and an External Secrets Operator companion.
* `durable-workflow/ci/` — minimum-viable values fixtures used by chart-CI
(`helm lint`, `helm template`, `ct lint-and-install`).

The chart is the supported Helm path for the deployment matrix at
<https://durable-workflow.github.io/docs/2.0/deployment>. The raw manifests
in [`../`](..) remain a supported, lower-level alternative; both share the
same external-persistence contract and the same singleton-scheduler
invariant. Pick one or the other per environment, not both.
invariant. The raw manifests run the PHP 2.x Server only. Pick one or the
other per environment, not both.
26 changes: 12 additions & 14 deletions k8s/helm/durable-workflow/Chart.yaml
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
apiVersion: v2
name: durable-workflow
description: Durable Workflow self-hosted server, worker, scheduler/maintenance runner, and bootstrap job for Kubernetes.
description: Durable Workflow self-hosted Server for Kubernetes. Runs the native 3.x Server by default, or the PHP 2.x Server with its worker, scheduler and bootstrap job for existing installs.
type: application
# The chart's own semver version. Bumped on every chart release; treated as
# independent of the server image version (appVersion). Breaking-change rules
# for this version live in docs/UPGRADING.md alongside the chart.
version: 0.3.9
# The immutable Durable Workflow Server identity this chart release packages.
version: 1.0.0
# The immutable native Durable Workflow Server this chart release packages.
# The onboarding default in values.yaml and appVersion are generated from the
# checked-in source release record.
appVersion: "2.11.8"
# checked-in source release record (helm_chart.app_version).
appVersion: "3.0.1"
kubeVersion: ">=1.27.0-0"
home: https://durable-workflow.github.io/docs/2.0/deployment
sources:
Expand All @@ -30,18 +30,16 @@ annotations:
# exact commit that most recently changed the packaged chart.
org.opencontainers.image.source: https://github.com/durable-workflow/server
dev.durable-workflow.source-revision: "unreleased"
dev.durable-workflow.image-reference: "docker.io/durableworkflow/server:2.11.8"
dev.durable-workflow.image-reference: "docker.io/durableworkflow/server:3.0.1"
artifacthub.io/license: MIT
artifacthub.io/category: integration-delivery
# Free-form changelog for the current chart release shown by Artifact Hub.
artifacthub.io/changes: |
- kind: fixed
description: Preserve duplicate bridge update receipts for SDK-worker workflows.
- kind: fixed
description: Include canonical failure storage, retention recovery and rejected-outcome history readers.
- kind: changed
description: Package Server 2.11 with capability-gated activity lease maintenance and configurable lease duration.
description: Run the native 3.x Server by default as one Deployment with no worker, scheduler, migration job or Redis.
- kind: added
description: Document compatible worker rollout and the distinction between leases and application deadlines.
- kind: fixed
description: Send application logs to container stderr by default and verify actual API, worker and scheduler logging before chart publication.
description: Add runtime=php so existing PHP 2.x installs keep their worker, scheduler and bootstrap job.
- kind: added
description: Add an opt-in pre-upgrade job that runs the native schema-upgrade command while every Server is stopped.
- kind: changed
description: Refuse to move an existing PHP release to native unless runtime is set explicitly.
Loading
Loading