diff --git a/composer.json b/composer.json index 674e5d072..ec912de86 100644 --- a/composer.json +++ b/composer.json @@ -6,7 +6,7 @@ "require": { "php": "^8.2", "apache/avro": "^1.12", - "durable-workflow/workflow": "2.11.4", + "durable-workflow/workflow": "2.13.1", "laravel/framework": "^13.30", "laravel/tinker": "^3.0", "league/flysystem-aws-s3-v3": "^3.35.3" @@ -48,7 +48,7 @@ }, "extra": { "durable-workflow": { - "product-train": "2.11.2" + "product-train": "2.11.3" }, "laravel": { "dont-discover": [] diff --git a/composer.lock b/composer.lock index d2aaed51b..aae870640 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "d99dd86d09e048c04ae6a4edff646739", + "content-hash": "2e60ebd4e4219304b0287bb1c5215a43", "packages": [ { "name": "apache/avro", @@ -655,21 +655,21 @@ }, { "name": "durable-workflow/workflow", - "version": "2.11.4", + "version": "2.13.1", "source": { "type": "git", "url": "https://github.com/durable-workflow/workflow.git", - "reference": "ae6bf6c8a7c4b9597ee4eecb15ecd786e78b0430" + "reference": "b2a3369110b8cbdf060802ff91e475110e66e333" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/durable-workflow/workflow/zipball/ae6bf6c8a7c4b9597ee4eecb15ecd786e78b0430", - "reference": "ae6bf6c8a7c4b9597ee4eecb15ecd786e78b0430", + "url": "https://api.github.com/repos/durable-workflow/workflow/zipball/b2a3369110b8cbdf060802ff91e475110e66e333", + "reference": "b2a3369110b8cbdf060802ff91e475110e66e333", "shasum": "" }, "require": { "apache/avro": "^1.12", - "laravel/framework": "^9.52.17|^10.48.29|^11.44.1|^12.69.0|^13.30.0", + "laravel/framework": "^9.52.17|^10.48.29|^11.56.1|^12.69.0|^13.30.0", "php": "^8.1", "react/promise": "^2.9|^3.0", "symfony/yaml": "^6.0|^7.0|^8.0" @@ -705,7 +705,7 @@ "dev-main": "2.0.x-dev" }, "durable-workflow": { - "product-train": "2.11.4", + "product-train": "2.13.1", "laravel-embedded-upgrade-contract": "resources/laravel-embedded-upgrade-contract.json", "laravel-dependency-security-policy": "resources/laravel-dependency-security-policy.json" } @@ -732,9 +732,9 @@ "description": "Embedded durable workflow runtime and orchestration engine for Laravel applications.", "support": { "issues": "https://github.com/durable-workflow/workflow/issues", - "source": "https://github.com/durable-workflow/workflow/tree/2.11.4" + "source": "https://github.com/durable-workflow/workflow/tree/2.13.1" }, - "time": "2026-10-23T11:36:13+00:00" + "time": "2026-10-24T14:18:09+00:00" }, { "name": "egulias/email-validator", diff --git a/docker-compose.dedicated-matching.yml b/docker-compose.dedicated-matching.yml index 999e33a5b..91e556b45 100644 --- a/docker-compose.dedicated-matching.yml +++ b/docker-compose.dedicated-matching.yml @@ -32,13 +32,13 @@ name: durable-workflow-server # daemon reports `shape: dedicated`. # Generated by scripts/ci/sync-source-release.mjs. Do not edit the fallback. -x-server-image: &server-image ${DW_SERVER_IMAGE:-durableworkflow/server:${DW_SERVER_TAG:-2.11.2}} +x-server-image: &server-image ${DW_SERVER_IMAGE:-durableworkflow/server:${DW_SERVER_TAG:-2.11.3}} x-server-environment: &server-environment APP_NAME: "Durable Workflow Server" APP_ENV: ${APP_ENV:-local} DW_SERVER_KEY: ${DW_SERVER_KEY:-} - APP_VERSION: ${APP_VERSION:-${DW_SERVER_TAG:-2.11.2}} + APP_VERSION: ${APP_VERSION:-${DW_SERVER_TAG:-2.11.3}} APP_DEBUG: ${APP_DEBUG:-false} DB_CONNECTION: mysql DB_HOST: mysql diff --git a/docker-compose.memo-rolling.yml b/docker-compose.memo-rolling.yml index e4a616b93..4a805dcc8 100644 --- a/docker-compose.memo-rolling.yml +++ b/docker-compose.memo-rolling.yml @@ -49,14 +49,14 @@ services: command: ["server-bootstrap"] environment: <<: *runtime-environment - APP_VERSION: ${APP_VERSION:-2.11.2} + APP_VERSION: ${APP_VERSION:-2.11.3} successor: image: ${DW_MEMO_SUCCESSOR_IMAGE:-durable-workflow/server-memo-rolling:local} ports: !override [] environment: <<: *runtime-environment - APP_VERSION: ${APP_VERSION:-2.11.2} + APP_VERSION: ${APP_VERSION:-2.11.3} DW_SERVER_ID: memo-successor DW_SERVER_TOPOLOGY_SHAPE: standalone_server DW_SERVER_PROCESS_CLASS: server_http_node diff --git a/docker-compose.published.yml b/docker-compose.published.yml index 4234aaa43..d237aa576 100644 --- a/docker-compose.published.yml +++ b/docker-compose.published.yml @@ -1,13 +1,13 @@ name: durable-workflow-server # Generated by scripts/ci/sync-source-release.mjs. Do not edit the fallback. -x-server-image: &server-image ${DW_SERVER_IMAGE:-durableworkflow/server:${DW_SERVER_TAG:-2.11.2}} +x-server-image: &server-image ${DW_SERVER_IMAGE:-durableworkflow/server:${DW_SERVER_TAG:-2.11.3}} x-server-environment: &server-environment APP_NAME: "Durable Workflow Server" APP_ENV: ${APP_ENV:-local} DW_SERVER_KEY: ${DW_SERVER_KEY:-} - APP_VERSION: ${APP_VERSION:-${DW_SERVER_TAG:-2.11.2}} + APP_VERSION: ${APP_VERSION:-${DW_SERVER_TAG:-2.11.3}} APP_DEBUG: ${APP_DEBUG:-false} LOG_CHANNEL: ${LOG_CHANNEL:-stderr} LOG_LEVEL: ${LOG_LEVEL:-info} diff --git a/docker-compose.small-cluster.yml b/docker-compose.small-cluster.yml index 081fcc172..29cfad2f3 100644 --- a/docker-compose.small-cluster.yml +++ b/docker-compose.small-cluster.yml @@ -12,7 +12,7 @@ x-server-build: &server-build x-server-environment: &server-environment APP_NAME: "Durable Workflow Server" APP_ENV: testing - APP_VERSION: ${APP_VERSION:-2.11.2} + APP_VERSION: ${APP_VERSION:-2.11.3} APP_DEBUG: "false" DW_SERVER_KEY: ${DW_SERVER_KEY:-base64:5Zt4nUhlCm3DD0nLXZJQdHiwPfb56yGo9gNV/g3jYbY=} DB_CONNECTION: ${DW_SMALL_CLUSTER_DB:-mysql} diff --git a/docker-compose.yml b/docker-compose.yml index 8fa6287b6..2ae745ef0 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -15,7 +15,7 @@ services: DW_SERVER_KEY: "${DW_SERVER_KEY:-}" DW_SERVER_TOPOLOGY_SHAPE: standalone_server DW_SERVER_PROCESS_CLASS: server_http_node - APP_VERSION: "${APP_VERSION:-2.11.2}" + APP_VERSION: "${APP_VERSION:-2.11.3}" APP_DEBUG: "false" DB_CONNECTION: mysql DB_HOST: mysql @@ -62,7 +62,7 @@ services: APP_NAME: "Durable Workflow Server" APP_ENV: local DW_SERVER_KEY: "${DW_SERVER_KEY:-}" - APP_VERSION: "${APP_VERSION:-2.11.2}" + APP_VERSION: "${APP_VERSION:-2.11.3}" APP_DEBUG: "false" DB_CONNECTION: mysql DB_HOST: mysql @@ -124,7 +124,7 @@ services: DW_SERVER_KEY: "${DW_SERVER_KEY:-}" DW_SERVER_TOPOLOGY_SHAPE: standalone_server DW_SERVER_PROCESS_CLASS: worker_node - APP_VERSION: "${APP_VERSION:-2.11.2}" + APP_VERSION: "${APP_VERSION:-2.11.3}" DB_CONNECTION: mysql DB_HOST: mysql DB_PORT: 3306 @@ -178,7 +178,7 @@ services: DW_SERVER_KEY: "${DW_SERVER_KEY:-}" DW_SERVER_TOPOLOGY_SHAPE: standalone_server DW_SERVER_PROCESS_CLASS: scheduler_node - APP_VERSION: "${APP_VERSION:-2.11.2}" + APP_VERSION: "${APP_VERSION:-2.11.3}" DB_CONNECTION: mysql DB_HOST: mysql DB_PORT: 3306 diff --git a/k8s/README.md b/k8s/README.md index 92692c837..bc91fe759 100644 --- a/k8s/README.md +++ b/k8s/README.md @@ -13,7 +13,7 @@ The checked-in manifests are synchronized with the repository's stable source release and pin its Docker Hub tag: ```text -durableworkflow/server:2.11.2 +durableworkflow/server:2.11.3 ``` ## Application logs @@ -42,15 +42,15 @@ digest you intend to run: ```bash kubectl set image -n durable-workflow deploy/durable-workflow-server \ - server=durableworkflow/server:2.11.2 + server=durableworkflow/server:2.11.3 kubectl set image -n durable-workflow deploy/durable-workflow-worker \ - worker=durableworkflow/server:2.11.2 + worker=durableworkflow/server:2.11.3 kubectl set image -n durable-workflow cronjob/durable-workflow-scheduler \ - scheduler=durableworkflow/server:2.11.2 + scheduler=durableworkflow/server:2.11.3 ``` GitHub Container Registry publishes the same release line at -`ghcr.io/durable-workflow/server:2.11.2`. Digest pinning is preferred for strict +`ghcr.io/durable-workflow/server:2.11.3`. Digest pinning is preferred for strict change control. The manifests expect you to provide: diff --git a/k8s/helm/durable-workflow/Chart.yaml b/k8s/helm/durable-workflow/Chart.yaml index 275daf869..ca24a6238 100644 --- a/k8s/helm/durable-workflow/Chart.yaml +++ b/k8s/helm/durable-workflow/Chart.yaml @@ -5,11 +5,11 @@ 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.2 +version: 0.3.3 # The immutable Durable Workflow Server identity this chart release packages. # The onboarding default in values.yaml and appVersion are generated from the # checked-in source release record. -appVersion: "2.11.2" +appVersion: "2.11.3" kubeVersion: ">=1.27.0-0" home: https://durable-workflow.github.io/docs/2.0/deployment sources: @@ -30,11 +30,13 @@ 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.2" + dev.durable-workflow.image-reference: "docker.io/durableworkflow/server:2.11.3" 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: 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. - kind: added diff --git a/k8s/helm/durable-workflow/README.md b/k8s/helm/durable-workflow/README.md index 3dfc2d8bf..91bcc4dd8 100644 --- a/k8s/helm/durable-workflow/README.md +++ b/k8s/helm/durable-workflow/README.md @@ -63,7 +63,7 @@ helm install durable-workflow ./k8s/helm/durable-workflow \ ```yaml image: - tag: "2.11.2" + tag: "2.11.3" # Pin a digest in production: # digest: "sha256:abc123..." # memoPayloadStorage: "raw-json-v1" # Required for a digest or custom image. diff --git a/k8s/helm/durable-workflow/ci/existing-secrets-values.yaml b/k8s/helm/durable-workflow/ci/existing-secrets-values.yaml index 8b83c7dfd..2627767ef 100644 --- a/k8s/helm/durable-workflow/ci/existing-secrets-values.yaml +++ b/k8s/helm/durable-workflow/ci/existing-secrets-values.yaml @@ -1,7 +1,7 @@ # CI fixture: GitOps / externally-managed-secret path. The chart consumes # existing Secrets and renders no Secret resources of its own. image: - tag: "2.11.2" + tag: "2.11.3" externalDatabase: connection: pgsql diff --git a/k8s/helm/durable-workflow/ci/ingress-and-hpa-values.yaml b/k8s/helm/durable-workflow/ci/ingress-and-hpa-values.yaml index b9f98a16f..70793a40a 100644 --- a/k8s/helm/durable-workflow/ci/ingress-and-hpa-values.yaml +++ b/k8s/helm/durable-workflow/ci/ingress-and-hpa-values.yaml @@ -1,6 +1,6 @@ # CI fixture: ingress + autoscaling enabled. Exercises optional templates. image: - tag: "2.11.2" + tag: "2.11.3" externalDatabase: connection: mysql diff --git a/k8s/helm/durable-workflow/ci/inline-secrets-values.yaml b/k8s/helm/durable-workflow/ci/inline-secrets-values.yaml index 0acc006fb..d8cce1473 100644 --- a/k8s/helm/durable-workflow/ci/inline-secrets-values.yaml +++ b/k8s/helm/durable-workflow/ci/inline-secrets-values.yaml @@ -2,7 +2,7 @@ # chart's render path is exercised end-to-end. Real deployments should use # existingSecret instead. image: - tag: "2.11.2" + tag: "2.11.3" externalDatabase: connection: mysql diff --git a/k8s/helm/durable-workflow/templates/_helpers.tpl b/k8s/helm/durable-workflow/templates/_helpers.tpl index 91af55fce..6ed87100b 100644 --- a/k8s/helm/durable-workflow/templates/_helpers.tpl +++ b/k8s/helm/durable-workflow/templates/_helpers.tpl @@ -88,7 +88,7 @@ resolved by an explicit capability declaration or an existing workload marker. {{- define "durable-workflow.memoPayloadStorageForImage" -}} {{- $image := toString . -}} {{- $normalized := regexReplaceAll "^index\\.docker\\.io/" $image "docker.io/" -}} -{{- if eq $normalized "docker.io/durableworkflow/server:2.11.2" -}} +{{- if eq $normalized "docker.io/durableworkflow/server:2.11.3" -}} dual-v1 {{- else if regexMatch "^docker\\.io/durableworkflow/server:2\\.0\\.0-rc\\.[0-9]+$" $normalized -}} {{- $releaseCandidate := atoi (regexFind "[0-9]+$" $normalized) -}} diff --git a/k8s/helm/durable-workflow/values.yaml b/k8s/helm/durable-workflow/values.yaml index fcc1c2239..0c260b24c 100644 --- a/k8s/helm/durable-workflow/values.yaml +++ b/k8s/helm/durable-workflow/values.yaml @@ -21,7 +21,7 @@ image: registry: docker.io repository: durableworkflow/server # Generated by scripts/ci/sync-source-release.mjs. Do not edit this default. - tag: "2.11.2" + tag: "2.11.3" # Optional digest pin. When set, takes precedence over tag for change control. # Example: "sha256:abc123..." digest: "" diff --git a/k8s/helm/examples/values-dev.yaml b/k8s/helm/examples/values-dev.yaml index 57e2a544d..29fc715f9 100644 --- a/k8s/helm/examples/values-dev.yaml +++ b/k8s/helm/examples/values-dev.yaml @@ -3,7 +3,7 @@ # shape in production. image: - tag: "2.11.2" + tag: "2.11.3" externalDatabase: connection: mysql diff --git a/k8s/helm/examples/values-external-secrets-operator.yaml b/k8s/helm/examples/values-external-secrets-operator.yaml index 4d6adf089..16dd021bd 100644 --- a/k8s/helm/examples/values-external-secrets-operator.yaml +++ b/k8s/helm/examples/values-external-secrets-operator.yaml @@ -5,7 +5,7 @@ # concern. image: - tag: "2.11.2" + tag: "2.11.3" externalDatabase: connection: pgsql diff --git a/k8s/helm/examples/values-production-existing-secrets.yaml b/k8s/helm/examples/values-production-existing-secrets.yaml index e38494739..f2bb7981b 100644 --- a/k8s/helm/examples/values-production-existing-secrets.yaml +++ b/k8s/helm/examples/values-production-existing-secrets.yaml @@ -10,7 +10,7 @@ image: repository: durable-workflow/server # Pin a digest in production for change-control auditability. digest: "" # e.g. "sha256:abc123..." - tag: "2.11.2" + tag: "2.11.3" externalDatabase: connection: pgsql diff --git a/k8s/migration-job.yaml b/k8s/migration-job.yaml index b843742bb..095b2c5db 100644 --- a/k8s/migration-job.yaml +++ b/k8s/migration-job.yaml @@ -13,7 +13,7 @@ spec: restartPolicy: OnFailure containers: - name: migrate - image: durableworkflow/server:2.11.2 + image: durableworkflow/server:2.11.3 command: ["server-entrypoint"] args: ["server-bootstrap"] envFrom: diff --git a/k8s/scheduler-cronjob.yaml b/k8s/scheduler-cronjob.yaml index 390a8a255..bd60a1120 100644 --- a/k8s/scheduler-cronjob.yaml +++ b/k8s/scheduler-cronjob.yaml @@ -24,7 +24,7 @@ spec: restartPolicy: Never containers: - name: scheduler - image: durableworkflow/server:2.11.2 + image: durableworkflow/server:2.11.3 command: ["server-entrypoint"] args: - sh diff --git a/k8s/secret.yaml b/k8s/secret.yaml index bb80cb253..c96c8c4b4 100644 --- a/k8s/secret.yaml +++ b/k8s/secret.yaml @@ -12,7 +12,7 @@ metadata: app.kubernetes.io/name: durable-workflow data: APP_NAME: "Durable Workflow Server" - APP_VERSION: "2.11.2" + APP_VERSION: "2.11.3" APP_ENV: production APP_DEBUG: "false" LOG_CHANNEL: "stderr" diff --git a/k8s/server-deployment.yaml b/k8s/server-deployment.yaml index 88c49fcc8..67065963a 100644 --- a/k8s/server-deployment.yaml +++ b/k8s/server-deployment.yaml @@ -23,7 +23,7 @@ spec: spec: containers: - name: server - image: durableworkflow/server:2.11.2 + image: durableworkflow/server:2.11.3 ports: - containerPort: 8080 name: http diff --git a/k8s/worker-deployment.yaml b/k8s/worker-deployment.yaml index 2c956b1c5..b19470f0f 100644 --- a/k8s/worker-deployment.yaml +++ b/k8s/worker-deployment.yaml @@ -19,7 +19,7 @@ spec: spec: containers: - name: worker - image: durableworkflow/server:2.11.2 + image: durableworkflow/server:2.11.3 command: ["server-entrypoint"] args: ["php", "artisan", "queue:work", "--sleep=1", "--tries=3", "--max-time=3600"] envFrom: diff --git a/resources/release/source-release.json b/resources/release/source-release.json index b9d2868a6..67b6b1bde 100644 --- a/resources/release/source-release.json +++ b/resources/release/source-release.json @@ -1,9 +1,9 @@ { "schema": "durable-workflow.server.source-release/v1", "server": { - "version": "2.11.2" + "version": "2.11.3" }, "helm_chart": { - "version": "0.3.2" + "version": "0.3.3" } } diff --git a/scripts/k8s-kind-smoke.sh b/scripts/k8s-kind-smoke.sh index 18b0dbd98..69924f803 100755 --- a/scripts/k8s-kind-smoke.sh +++ b/scripts/k8s-kind-smoke.sh @@ -7,7 +7,7 @@ cluster="${K8S_SMOKE_CLUSTER:-durable-workflow-server-smoke}" image="${K8S_SMOKE_IMAGE:-durableworkflow/server:k8s-smoke}" # Generated by scripts/ci/sync-source-release.mjs so the smoke replaces the # same default shipped by the public manifests. -manifest_image="durableworkflow/server:2.11.2" +manifest_image="durableworkflow/server:2.11.3" kind_node_image="${K8S_SMOKE_KIND_NODE_IMAGE:-kindest/node:v1.29.4}" artifact_dir="${K8S_SMOKE_ARTIFACT_DIR:-/tmp/durable-workflow-k8s-kind-smoke-artifacts}" rendered_dir="${artifact_dir}/rendered-manifests" diff --git a/tests/Feature/HistoryControllerTest.php b/tests/Feature/HistoryControllerTest.php index 70269acb0..b476789bd 100644 --- a/tests/Feature/HistoryControllerTest.php +++ b/tests/Feature/HistoryControllerTest.php @@ -2,12 +2,15 @@ namespace Tests\Feature; +use App\Support\HistoryPageToken; use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Support\Facades\Queue; +use Illuminate\Support\Str; use Tests\Feature\Concerns\ServerTestHelpers; use Tests\Fixtures\ExternalGreetingWorkflow; use Tests\TestCase; use Workflow\V2\Models\WorkflowHistoryEvent; +use Workflow\V2\Models\WorkflowRun; class HistoryControllerTest extends TestCase { @@ -70,6 +73,62 @@ public function test_it_returns_history_events_for_a_workflow_run(): void ); } + public function test_history_and_export_read_a_stored_rejected_outcome_without_mutating_the_run(): void + { + Queue::fake(); + $this->createNamespace('default'); + $start = $this->postJson('/api/workflows', [ + 'workflow_id' => 'wf-history-rejected-outcome', + 'workflow_type' => 'tests.external-greeting-workflow', + 'input' => ['Ada'], + ], $this->apiHeaders())->assertCreated(); + $runId = (string) $start->json('run_id'); + $sequence = (int) WorkflowHistoryEvent::query()->where('workflow_run_id', $runId)->max('sequence') + 1; + $payload = [ + 'activity_execution_id' => 'activity-reader', + 'activity_attempt_id' => 'attempt-reader', + 'attempt_number' => 2, + 'lease_owner' => 'old-worker', + 'outcome' => 'completed', + 'reason' => 'lease_expired', + 'observed_at' => now()->toIso8601String(), + ]; + + // Seed an existing fact directly. Reader adoption does not enable its producer. + WorkflowHistoryEvent::query()->insert([ + 'id' => (string) Str::ulid(), + 'workflow_run_id' => $runId, + 'sequence' => $sequence, + 'event_type' => 'ActivityOutcomeRejected', + 'payload' => json_encode($payload, JSON_THROW_ON_ERROR), + 'recorded_at' => now(), + 'created_at' => now(), + 'updated_at' => now(), + ]); + WorkflowRun::query()->whereKey($runId)->update(['last_history_sequence' => $sequence]); + $before = WorkflowRun::query()->findOrFail($runId)->getRawOriginal(); + $eventCount = WorkflowHistoryEvent::query()->where('workflow_run_id', $runId)->count(); + $historyUrl = "/api/workflows/wf-history-rejected-outcome/runs/{$runId}/history"; + $pageToken = HistoryPageToken::encode($sequence - 1); + + $this->getJson($historyUrl.'?page_size=1&next_page_token='.$pageToken, $this->apiHeaders()) + ->assertOk() + ->assertJsonCount(1, 'events') + ->assertJsonPath('events.0.sequence', $sequence) + ->assertJsonPath('events.0.event_type', 'ActivityOutcomeRejected') + ->assertJsonPath('events.0.payload', $payload) + ->assertJsonPath('next_page_token', null); + $export = $this->getJson($historyUrl.'/export', $this->apiHeaders())->assertOk(); + $event = collect($export->json('history_events'))->firstWhere('sequence', $sequence); + $this->assertSame('ActivityOutcomeRejected', $event['type'] ?? null); + $this->assertSame($payload, $event['payload'] ?? null); + $timelineEntry = collect($export->json('timeline'))->firstWhere('sequence', $sequence); + $this->assertSame('ActivityOutcomeRejected', $timelineEntry['type'] ?? null); + $this->assertSame('Rejected completed outcome from activity attempt 2: lease_expired.', $timelineEntry['summary'] ?? null); + $this->assertSame($before, WorkflowRun::query()->findOrFail($runId)->getRawOriginal()); + $this->assertSame($eventCount, WorkflowHistoryEvent::query()->where('workflow_run_id', $runId)->count()); + } + public function test_it_surfaces_run_compatibility_on_history_response_and_start_event(): void { Queue::fake(); diff --git a/tests/Unit/HelmMemoPayloadTransitionContractTest.php b/tests/Unit/HelmMemoPayloadTransitionContractTest.php index e930a771b..70dec58a3 100644 --- a/tests/Unit/HelmMemoPayloadTransitionContractTest.php +++ b/tests/Unit/HelmMemoPayloadTransitionContractTest.php @@ -27,7 +27,9 @@ public function test_chart_fails_closed_for_active_envelope_only_workloads(): vo $this->assertStringContainsString('(not (has $phase (list "Succeeded" "Failed")))', $helpers); $this->assertStringContainsString('(not $terminal)', $helpers); $this->assertStringContainsString('$pod.metadata.deletionTimestamp', $helpers); - $this->assertStringContainsString('docker.io/durableworkflow/server:2.0.0', $helpers); + $release = json_decode($this->read('resources/release/source-release.json'), true, flags: JSON_THROW_ON_ERROR); + $this->assertIsString($release['server']['version'] ?? null); + $this->assertStringContainsString('docker.io/durableworkflow/server:'.$release['server']['version'], $helpers); $this->assertStringNotContainsString('get $labels "app.kubernetes.io/version"', $helpers); $this->assertStringContainsString('fail (printf "memo payload transition', $helpers); }