diff --git a/.github/workflows/native-image-parity.yml b/.github/workflows/native-image-parity.yml index d28b8a992..878cbd0f0 100644 --- a/.github/workflows/native-image-parity.yml +++ b/.github/workflows/native-image-parity.yml @@ -47,7 +47,7 @@ jobs: run: | set -euo pipefail bash scripts/ci/pull-images.sh \ - "$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.7.json)" \ + "$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.8.json)" \ composer:2.10.3@sha256:da624c2c705d54e2f5a9bb77a5dc6c7d091711433ebefd7035672e84c2010fee - name: Set up Docker Buildx diff --git a/.github/workflows/server-parity.yml b/.github/workflows/server-parity.yml index bf6368a4f..45c7effa1 100644 --- a/.github/workflows/server-parity.yml +++ b/.github/workflows/server-parity.yml @@ -265,7 +265,7 @@ jobs: bash scripts/ci/pull-images.sh \ mirror.gcr.io/library/rust@sha256:300ec56abce8cc9448ddea2172747d048ed902a3090e6b57babb2bf19f754081 \ mirror.gcr.io/library/python@sha256:bf44cdfcb76cd3b41e879bc058fc37ec5872002ccfde7fcb765e218cde0cd79c \ - "$(baseline php-2.11.7)" + "$(baseline php-2.11.8)" # The adapters' pinned, --locked dependencies build the same way every # run. Restore their public Cargo registry data and build tree, keyed # by the toolchain image, the runner and every tracked adapter input. @@ -538,7 +538,7 @@ jobs: bash scripts/ci/pull-images.sh \ "${NATIVE_RUST_IMAGE}" \ "$MYSQL_IMAGE" \ - "$(baseline php-2.11.7)" \ + "$(baseline php-2.11.8)" \ "$(baseline php-2.5.14)" \ composer:2.10.3@sha256:da624c2c705d54e2f5a9bb77a5dc6c7d091711433ebefd7035672e84c2010fee - name: Fetch this run's published SDK adapters @@ -574,7 +574,7 @@ jobs: - name: Create TLS fixture certificates run: | set -euo pipefail - image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.7.json) + image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.8.json) mkdir -p mysql-tls parity-evidence chmod 0777 parity-evidence docker run --rm --user="$(id -u):$(id -g)" --network=none \ @@ -686,7 +686,7 @@ jobs: docker run --rm --user="$(id -u):$(id -g)" --network "$RESOURCE_SCOPE" --entrypoint mysql \ "$MYSQL_IMAGE" -h parity-mysql -uroot -pparity-disposable-password \ -e 'CREATE DATABASE native_ref CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci' - image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.7.json) + image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.8.json) # The physical layout stays the frozen published 2.5.14 one; behavior # runs on the current reference after migrating that database forward. layout=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.5.14.json) @@ -735,7 +735,7 @@ jobs: bash scripts/conformance/server-parity/container-log-tails.sh } trap container_log_tails ERR - image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.7.json) + image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.8.json) # Composer runs confined in the pinned image, never in the published image under test. bash scripts/ci/run-composer.sh --rm -v "$PWD:/source" -w /source -- \ install --working-dir=scripts/conformance/server-parity --no-interaction --no-progress @@ -812,7 +812,7 @@ jobs: bash scripts/conformance/server-parity/container-log-tails.sh } trap container_log_tails ERR - image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.7.json) + image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.8.json) export DW_PARITY_RUNNER_REVISION=$(git rev-parse HEAD) mkdir -p parity-consumers curl --fail --location --retry 3 --output parity-consumers/dw.phar https://github.com/durable-workflow/cli/releases/download/2.2.0/dw.phar @@ -878,7 +878,7 @@ jobs: bash scripts/conformance/server-parity/container-log-tails.sh } trap container_log_tails ERR - image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.7.json) + image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.8.json) bash scripts/conformance/server-parity/published-sdk-patch-profile.sh mysql http://parity-php:8080 http://parity-native-a:8080 bash scripts/conformance/server-parity/repeated-patch-profile.sh mysql http://parity-php:8080 http://parity-native-a:8080 bash scripts/conformance/server-parity/legacy-marker-profile.sh mysql http://parity-php:8080 http://parity-native-a:8080 @@ -958,7 +958,7 @@ jobs: bash scripts/conformance/server-parity/container-log-tails.sh } trap container_log_tails ERR - image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.7.json) + image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.8.json) bash scripts/ci/run-composer.sh --rm -v "$PWD:/source" -w /source -- \ install --working-dir=scripts/conformance/server-parity --no-interaction --no-progress # Each profile brings its own published PHP and embedded databases and @@ -1006,7 +1006,7 @@ jobs: if: ${{ matrix.part == 'cohorts' }} run: | set -euo pipefail - image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.7.json) + image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.8.json) bash scripts/ci/run-composer.sh --rm -v "$PWD:/source" -w /source -- \ install --working-dir=scripts/conformance/server-parity --no-interaction --no-progress docker run -d --name "$RESOURCE_SCOPE-native-b" --network "$RESOURCE_SCOPE" --network-alias=parity-native-b \ @@ -1122,7 +1122,7 @@ jobs: if: ${{ matrix.part == 'corrected-markers' }} run: | set -euo pipefail - image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.7.json) + image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.8.json) bash scripts/ci/run-composer.sh --rm -v "$PWD:/source" -w /source -- \ install --working-dir=scripts/conformance/server-parity --no-interaction --no-progress docker run -d --name "$RESOURCE_SCOPE-native-b" --network "$RESOURCE_SCOPE" --network-alias=parity-native-b \ @@ -1252,7 +1252,7 @@ jobs: run: | set -euo pipefail mkdir -p parity-evidence parity-summary - image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.7.json) + image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.8.json) docker run --rm --user="$(id -u):$(id -g)" --network=none --cpus=1 --memory=256m --memory-swap=256m \ --entrypoint node -e PARITY_JOB_OUTCOME -e GITHUB_SHA \ -v "$PWD:/source:ro" -v "$PWD/parity-evidence:/evidence:ro" -v "$PWD/parity-summary:/summary" \ @@ -1305,7 +1305,7 @@ jobs: bash scripts/ci/pull-images.sh \ "${NATIVE_RUST_IMAGE}" \ "$POSTGRES_IMAGE" \ - "$(baseline php-2.11.7)" \ + "$(baseline php-2.11.8)" \ "$(baseline php-2.5.14)" \ composer:2.10.3@sha256:da624c2c705d54e2f5a9bb77a5dc6c7d091711433ebefd7035672e84c2010fee - name: Fetch this run's published SDK adapters @@ -1428,7 +1428,7 @@ jobs: "$POSTGRES_IMAGE" --version > parity-evidence/postgres-version.txt docker run --rm --user="$(id -u):$(id -g)" --network "$RESOURCE_SCOPE" \ -e PGPASSWORD=parity-disposable-password --entrypoint createdb "$POSTGRES_IMAGE" -h parity-pg -U parity native_ref - image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.7.json) + image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.8.json) # The physical layout stays the frozen published 2.5.14 one; behavior # runs on the current reference after migrating that database forward. layout=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.5.14.json) @@ -1479,7 +1479,7 @@ jobs: bash scripts/conformance/server-parity/container-log-tails.sh } trap container_log_tails ERR - image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.7.json) + image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.8.json) # Composer runs confined in the pinned image, never in the published image under test. bash scripts/ci/run-composer.sh --rm -v "$PWD:/source" -w /source -- \ install --working-dir=scripts/conformance/server-parity --no-interaction --no-progress @@ -1557,7 +1557,7 @@ jobs: bash scripts/conformance/server-parity/container-log-tails.sh } trap container_log_tails ERR - image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.7.json) + image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.8.json) export DW_PARITY_RUNNER_REVISION=$(git rev-parse HEAD) mkdir -p parity-consumers curl --fail --location --retry 3 --output parity-consumers/dw.phar https://github.com/durable-workflow/cli/releases/download/2.2.0/dw.phar @@ -1625,7 +1625,7 @@ jobs: bash scripts/conformance/server-parity/container-log-tails.sh } trap container_log_tails ERR - image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.7.json) + image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.8.json) bash scripts/conformance/server-parity/published-sdk-patch-profile.sh pgsql http://parity-php:8080 http://parity-native-a:8080 bash scripts/conformance/server-parity/repeated-patch-profile.sh pgsql http://parity-php:8080 http://parity-native-a:8080 bash scripts/conformance/server-parity/legacy-marker-profile.sh pgsql http://parity-php:8080 http://parity-native-a:8080 @@ -1705,7 +1705,7 @@ jobs: bash scripts/conformance/server-parity/container-log-tails.sh } trap container_log_tails ERR - image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.7.json) + image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.8.json) bash scripts/ci/run-composer.sh --rm -v "$PWD:/source" -w /source -- \ install --working-dir=scripts/conformance/server-parity --no-interaction --no-progress # Each profile brings its own published PHP and embedded databases and @@ -1752,7 +1752,7 @@ jobs: if: ${{ matrix.part == 'cohorts' }} run: | set -euo pipefail - image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.7.json) + image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.8.json) bash scripts/ci/run-composer.sh --rm -v "$PWD:/source" -w /source -- \ install --working-dir=scripts/conformance/server-parity --no-interaction --no-progress docker run -d --name "$RESOURCE_SCOPE-native-b" --network "$RESOURCE_SCOPE" --network-alias=parity-native-b \ @@ -1870,7 +1870,7 @@ jobs: if: ${{ matrix.part == 'corrected-markers' }} run: | set -euo pipefail - image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.7.json) + image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.8.json) bash scripts/ci/run-composer.sh --rm -v "$PWD:/source" -w /source -- \ install --working-dir=scripts/conformance/server-parity --no-interaction --no-progress docker run -d --name "$RESOURCE_SCOPE-native-b" --network "$RESOURCE_SCOPE" --network-alias=parity-native-b \ @@ -2042,7 +2042,7 @@ jobs: run: | set -euo pipefail mkdir -p parity-evidence parity-summary - image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.7.json) + image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.8.json) docker run --rm --user="$(id -u):$(id -g)" --network=none --cpus=1 --memory=256m --memory-swap=256m \ --entrypoint node -e PARITY_JOB_OUTCOME -e GITHUB_SHA \ -v "$PWD:/source:ro" -v "$PWD/parity-evidence:/evidence:ro" -v "$PWD/parity-summary:/summary" \ @@ -2088,7 +2088,7 @@ jobs: } bash scripts/ci/pull-images.sh \ "${NATIVE_RUST_IMAGE}" \ - "$(baseline php-2.11.7)" \ + "$(baseline php-2.11.8)" \ "$(baseline php-2.5.14)" \ composer:2.10.3@sha256:da624c2c705d54e2f5a9bb77a5dc6c7d091711433ebefd7035672e84c2010fee - name: Fetch this run's published SDK adapters @@ -2198,7 +2198,7 @@ jobs: -v "$PWD/parity-evidence:/evidence" -w /source/rust --entrypoint bash \ "${NATIVE_RUST_IMAGE}" -c \ 'cargo test --locked --offline --all-targets > /evidence/rust-tests.txt && cargo build --locked --offline && cargo run --locked --offline --example codec-fixtures -- ../tests/Fixtures/ServerParity/Codec/v1.json > /evidence/rust-codec.json' - image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.7.json) + image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.8.json) docker run --rm --user="$(id -u):$(id -g)" --network=none --entrypoint php \ -v "$PWD:/source:ro" -v "$PWD/parity-evidence:/evidence" -w /source "$image" \ scripts/conformance/server-parity/codec.php tests/Fixtures/ServerParity/Codec/v1.json \ @@ -2222,7 +2222,7 @@ jobs: bash scripts/conformance/server-parity/container-log-tails.sh } trap container_log_tails ERR - image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.7.json) + image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.8.json) mkdir -p parity-state parity-evidence chmod 0777 parity-state parity-evidence touch parity-state/php.sqlite parity-state/embedded.sqlite parity-state/php-layout.sqlite @@ -2378,7 +2378,7 @@ jobs: bash scripts/conformance/server-parity/container-log-tails.sh } trap container_log_tails ERR - image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.7.json) + image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.8.json) export DW_PARITY_RUNNER_REVISION=$(git rev-parse HEAD) mkdir -p parity-consumers curl --fail --location --retry 3 --output parity-consumers/dw.phar https://github.com/durable-workflow/cli/releases/download/2.2.0/dw.phar @@ -2456,7 +2456,7 @@ jobs: bash scripts/conformance/server-parity/container-log-tails.sh } trap container_log_tails ERR - image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.7.json) + image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.8.json) bash scripts/conformance/server-parity/published-sdk-patch-profile.sh sqlite http://parity-server:8080 http://parity-rust:8080 bash scripts/conformance/server-parity/repeated-patch-profile.sh sqlite http://parity-server:8080 http://parity-rust:8080 bash scripts/conformance/server-parity/legacy-marker-profile.sh sqlite http://parity-server:8080 http://parity-rust:8080 @@ -2537,7 +2537,7 @@ jobs: bash scripts/conformance/server-parity/container-log-tails.sh } trap container_log_tails ERR - image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.7.json) + image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.8.json) bash scripts/ci/run-composer.sh --rm -v "$PWD:/source" -w /source -- \ install --working-dir=scripts/conformance/server-parity --no-interaction --no-progress mkdir -p parity-state parity-evidence @@ -2581,7 +2581,7 @@ jobs: RESOURCE_SCOPE: dw-parity-${{ github.run_id }}-${{ github.run_attempt }}-${{ github.job }} run: | set -euo pipefail - image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.7.json) + image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.8.json) bash scripts/ci/run-composer.sh --rm -v "$PWD:/source" -w /source -- \ install --working-dir=scripts/conformance/server-parity --no-interaction --no-progress mkdir -p parity-state parity-evidence @@ -2720,7 +2720,7 @@ jobs: RESOURCE_SCOPE: dw-parity-${{ github.run_id }}-${{ github.run_attempt }}-${{ github.job }} run: | set -euo pipefail - image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.7.json) + image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.8.json) bash scripts/ci/run-composer.sh --rm -v "$PWD:/source" -w /source -- \ install --working-dir=scripts/conformance/server-parity --no-interaction --no-progress mkdir -p parity-state parity-evidence @@ -2838,7 +2838,7 @@ jobs: run: | set -euo pipefail mkdir -p parity-evidence parity-summary - image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.7.json) + image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.8.json) docker run --rm --user="$(id -u):$(id -g)" --network=none --cpus=1 --memory=256m --memory-swap=256m \ --entrypoint node -e PARITY_JOB_OUTCOME -e GITHUB_SHA \ -v "$PWD:/source:ro" -v "$PWD/parity-evidence:/evidence:ro" -v "$PWD/parity-summary:/summary" \ diff --git a/docs/rust-server-port-checkpoints/2026-11-01-reference-2118.md b/docs/rust-server-port-checkpoints/2026-11-01-reference-2118.md new file mode 100644 index 000000000..55f9055e7 --- /dev/null +++ b/docs/rust-server-port-checkpoints/2026-11-01-reference-2118.md @@ -0,0 +1,54 @@ +# November 1, the parity reference moves to published 2.11.8 + +- **Before.** The Shared Server fixtures compared native and embedded + against published Server 2.11.7 (Core 2.15.7). +- **Reference.** Published Server 2.11.8, Core 2.15.12, as General + published it (Server #789 receipt 6558026433, #765 receipt 6558025643): + - source `fa3fc2f2f6b8935ea4a6eea47f6a9221e2adafff`; + - index `sha256:3848d5d5cd1b23bd2881e3fdecea64cc44b72e6fb812e577c2db6d0872d065dd`; + - linux/amd64 `sha256:980fe0a052089ced34ec3fcd2be2ea4e77436861d8fb537fb6654cb652a53e07`; + - linux/arm64 `sha256:cea163f8fcedf3a17302acf0141b073a85fbdb395ebbcd59e5af6f5fa9ad75e1`. + + `tests/Fixtures/ServerParityBaselines/php-2.11.8.json` records it. The + SDK, CLI, Waterline and sample-app pins are unchanged. The takeover + cohorts keep their own source images. +- **What changed on 2.11.8, and the answers recorded.** + - **Post-commit payload deletion counts** (#911). Every retention pass + and namespace delete answer carries `external_payload_cleanup`, and the + payload cleanup status and pass carry `retention_cleanup` + (`pending`, `failed`, `blocked`). Native added them only while a + deletion was pending (#914); it now always does. `namespace-delete`, + `payload-cleanup`, `retention-external-payloads` and + `namespace-delete-payloads` pin the counts. + - **A child resolved under a leased parent task** (workflow#962, Core + 2.15.10). `child-open-parent-task` gains a leased case: the parent's + resume task is claimed, the child completes, and the lease completes + with a timer and without the result. 2.11.8 then offers one follow-up + task that replays the child's result, as native does. Native left that + moment's run summary unprojected (a resolved child beside the timer); + it now describes it as 2.11.8 does: `timer_scheduled`, waiting for the + timer, no repair attention. + - **History import** (Core 2.15.8 to 2.15.12). The `workflow-import` + probe's run id conflict bundle renamed only `workflow.run_id`; 2.11.8 + checks each command's and signal's `resolved_run_id` first, so the + probe now renames every `*run_id` naming the original run, and the case + still answers `target.run_id_conflict`. The cross-namespace attach now + answers `target.instance_namespace_conflict` before writing, and a run + imported into another namespace answers as a conflict; native matches + both, and the fixture's published-defect allowances for 2.11.1 to + 2.11.7 are removed. + - **Embedded probes.** Core 2.15.12 resolves a run through its + instance's namespace and reserves a caller-named instance without + model events, so the probes' `creating` hooks left that instance's + namespace empty and every embedded recording failed to find its run. + The embedded probes now configure `workflows.v2.namespace`. A host + application without the hooks is unaffected. +- **Local checks before the pull request** (SQLite, this host): + - the four cleanup fixtures, `child-open-parent-task` and + `workflow-import` recorded against a fresh 2.11.8 harness pass, and + native built from this branch passes `child-open-parent-task` and + `workflow-import`; + - without the namespace setting every embedded recording fails on 2.11.8 + and passes on 2.11.7; with it, embedded recordings pass on 2.11.8; + - the native SQLite execution suite and the node unit suite (see the pull + request for counts and the full corpus run). diff --git a/docs/rust-server-port.md b/docs/rust-server-port.md index ec67ead0a..e3066d7d8 100644 --- a/docs/rust-server-port.md +++ b/docs/rust-server-port.md @@ -50,6 +50,11 @@ Updated October 27, 2026. - The parity reference moves to published 2.11.7 (#863), with native's v1 projection history bytes in Core's canonical unit (#770) ([checkpoint](rust-server-port-checkpoints/2026-10-29-reference-2117.md)). + - The parity reference moves to published 2.11.8 (Core 2.15.12): native + always reports post-commit payload deletion counts, and a child's + resolution under a leased parent task now gives PHP a follow-up task + (workflow#962) + ([checkpoint](rust-server-port-checkpoints/2026-11-01-reference-2118.md)). - [#814](https://github.com/durable-workflow/server/pull/814): the shared fixtures accept published PHP's typed `429 long_poll_capacity_exhausted` poll refusal, and retry a locked Composer install after a transient @@ -468,28 +473,45 @@ contract fixture before its correction. and a signal against published 2.11.7 ([checkpoint](rust-server-port-checkpoints/2026-11-01-key-order.md)). - **Child completion while the parent has an open workflow task** - (November 1; ready task closed, leased task decided; - [checkpoint](rust-server-port-checkpoints/2026-11-01-child-open-parent-task.md)). - Published PHP 2.11.7 records the child resolution and, while the parent - has a ready or leased workflow task, creates none and leaves that task's - payload as it is (`dispatchParentResumeTasks`). - - **Ready task.** Native now does the same: the ready task replays the - parent with the resolution in its history. An update task does not - replay the workflow, so beside one the resolution still gets its own - resume task. The `child-open-parent-task` fixture records it against - published 2.11.7. - - **Leased task.** On 2.11.7 a lease whose worker read history before the - resolution completes without it, and the parent is left with no task; - the repair pass does not recover it - ([workflow#962](https://github.com/durable-workflow/workflow/issues/962)). - Core 2.15.10, not yet in a published Server release, creates one child - resume task when such a lease completes. Native gives the resolution - its own resume task at once, as activity and timer resolutions do on - both servers. Compare again when the parity reference moves to a Server - release with Core 2.15.10. + (November 1, closed; + [checkpoint](rust-server-port-checkpoints/2026-11-01-child-open-parent-task.md), + [reference move](rust-server-port-checkpoints/2026-11-01-reference-2118.md)). + Published PHP records the child resolution and, while the parent has a + ready or leased workflow task, creates none and leaves that task's payload + as it is (`dispatchParentResumeTasks`). + - **Ready task.** Native does the same: the ready task replays the parent + with the resolution in its history. An update task does not replay the + workflow, so beside one the resolution still gets its own resume task. + - **Leased task.** A lease whose worker read history before the + resolution completes without it. Published 2.11.7 then left the parent + with no task ([workflow#962](https://github.com/durable-workflow/workflow/issues/962)); + 2.11.8 (Core 2.15.10 and later) gives it one follow-up task that + replays the child's result. Native gives the resolution its own resume + task at once, as activity and timer resolutions do, so after the lease + both servers offer exactly one task that replays the result. While the + lease's new timer is open beside that task, native now describes the + run as 2.11.8 does (`timer_scheduled`, waiting for the timer) instead of + leaving it unprojected. The `child-open-parent-task` fixture records + both cases against published 2.11.8. - A signal creates no resume while the parent waits only on a child, as on PHP: `PendingMessageTask::signalCanAdvanceRun` advances only signal and condition waits. +- **History import fences of Core 2.15.8 to 2.15.12** (November 1, + narrowed with the reference move to 2.11.8; + [checkpoint](rust-server-port-checkpoints/2026-11-01-reference-2118.md)). + Published 2.11.8 checks a bundle's internal references before its target: + each command's and signal's `resolved_run_id` must name the imported run, + messages must bind to the bundle's commands, and lineage must stay within + verified endpoints (`EmbeddedV2ImportReferences`, + `EmbeddedV2ImportMessageReferences`, `EmbeddedV2ImportLineage`). It also + refuses an instance of another namespace before writing + (`target.instance_namespace_conflict`), and a run already imported into + another namespace as a run id conflict. Native now gives both target + answers as 2.11.8 does, and the `workflow-import` fixture records them; + the published-defect allowances for 2.11.1 to 2.11.7 are gone. Native's + own reference fence (#765) runs after the run id check, and its rules and + rule names have not yet been compared with Core's for bundles whose + references are inconsistent; no fixture case sends such a bundle. - **Update delivery into a ready task** (November 1, decided: native keeps its behavior). Published PHP merges an accepted update into the run's ready workflow task (`ExternalWorkflowUpdateAdmission::wakeWorkflowTask`). @@ -544,14 +566,16 @@ contract fixture before its correction. the prune records the deletion in `dw_external_payload_deletions` (schema version 8), so a prune that fails later keeps the run, its registrations and every object. A provider failure after the commit leaves the deletion - pending, retried by the next pass. While one is pending the retention pass - reports `external_payload_cleanup`, the payload cleanup routes report - `retention_cleanup` (the pass answering 207), and namespace delete reports - `external_payload_cleanup` with 207; 2.11.8 adds those counts to clean - answers too, which native will do once CI's parity reference moves from - 2.11.7, whose clean answers lack them. An online-backup hold still fails the prune before it commits. The - `retention-external-payloads` fixture records it against published 2.11.7 - and passes unchanged against 2.11.8. + pending, retried by the next pass. As on 2.11.8, every answer carries the + counts (`pending`, `failed`, `blocked`): the retention pass and namespace + delete as `external_payload_cleanup`, the payload cleanup routes as + `retention_cleanup`. Namespace delete answers 207 while a deletion is + pending, and the cleanup pass also when it blocked a reference. An + online-backup hold still fails the prune before it commits. The + `retention-external-payloads`, `namespace-delete-payloads`, + `namespace-delete` and `payload-cleanup` fixtures pin the counts against + published 2.11.8 + ([checkpoint](rust-server-port-checkpoints/2026-11-01-reference-2118.md)). A run holding a reference native cannot settle (PHP's stored format from a workflow import, an envelope, or one on an inbound or durable stream) is still skipped with `external_payload_cleanup_unavailable`. Since November 1, diff --git a/rust/src/runtime/child_summary.rs b/rust/src/runtime/child_summary.rs index 65126f721..3421a22af 100644 --- a/rust/src/runtime/child_summary.rs +++ b/rust/src/runtime/child_summary.rs @@ -203,6 +203,16 @@ where { return Ok(true); } + // A resolved child beside an open timer, while a workflow task that + // will apply it carries the run (a lease that completed without the + // child's result, workflow#962): published 2.11.8 describes the + // timer and reports no problem (`child-open-parent-task`, leased). + if summary.wait.as_ref().is_some_and(|wait| wait.kind == "timer") + && summary.task_type.as_deref() == Some("workflow") + && rows.iter().all(|row| DB::string(row, "status").is_ok_and(|status| status != "open")) + { + return Ok(true); + } if summary .wait .as_ref() diff --git a/rust/src/runtime/execution.rs b/rust/src/runtime/execution.rs index d823e8895..319275a02 100644 --- a/rust/src/runtime/execution.rs +++ b/rust/src/runtime/execution.rs @@ -1800,6 +1800,7 @@ impl Runtime { delegate!(show_service_call(names: [&str; 3], id: &str) -> Result); delegate!(cancel_service_call(names: [&str; 3], id: &str, reason: Option) -> Result<(StatusCode, Value)>); delegate!(import_existing_run(run_id: &str) -> Result>); + delegate!(import_instance_namespace(instance_id: &str) -> Result>); delegate!(import_write(plan: &super::workflow_import::Plan) -> std::result::Result); delegate!(waterline_existing(workflow_id: &str, run_id: &str) -> Result); delegate!(projected_current_run(workflow_id: &str) -> Result>); diff --git a/rust/src/runtime/namespace_cleanup.rs b/rust/src/runtime/namespace_cleanup.rs index 750499c53..e5e9d3beb 100644 --- a/rust/src/runtime/namespace_cleanup.rs +++ b/rust/src/runtime/namespace_cleanup.rs @@ -10,8 +10,9 @@ //! `RuntimeExternalPayloadRegistry::deleteForNamespace` release them //! (`delete_namespace_payloads`). Their provider deletions are recorded in the //! delete's transaction and run only after it commits (`payload_deletions`), -//! so a failed delete keeps every object. While a deletion is still pending -//! the answer carries `external_payload_cleanup` and is 207. +//! so a failed delete keeps every object. The answer always carries their +//! `external_payload_cleanup` counts, as 2.11.8's does, and is 207 while a +//! deletion is still pending. //! A namespace holding a reference native cannot settle (PHP's stored //! format, an envelope, or one on a stream) refuses before changing anything, //! with PHP's answer for unavailable external payload storage. @@ -278,13 +279,12 @@ store_methods! { Self::query("DELETE FROM workflow_namespaces WHERE name=$1").bind(&name).execute(&mut *tx).await?; tx.commit().await?; // The delete has committed; only now may provider objects go. A - // deletion left pending answers 207 with its counts. + // deletion left pending answers 207. self.settle_payload_deletions(&staged).await; - let mut body = json!({"name": name, "status": "deleted", "deleted": deleted}); - if let Some(cleanup) = self.reported_payload_deletions(&name).await? { - body["external_payload_cleanup"] = cleanup; - } - Ok(body) + Ok(json!({ + "name": name, "status": "deleted", "deleted": deleted, + "external_payload_cleanup": self.payload_deletion_status(&name).await?, + })) } /// The namespace's external payloads, inside its delete's transaction: diff --git a/rust/src/runtime/operator_metrics.rs b/rust/src/runtime/operator_metrics.rs index 7807d2521..0529e2292 100644 --- a/rust/src/runtime/operator_metrics.rs +++ b/rust/src/runtime/operator_metrics.rs @@ -1256,9 +1256,7 @@ where let failed = report["failed"].as_i64().is_some_and(|failed| failed > 0); let mut fields = policy.fields(self.namespace.as_ref()); fields.extend(report); - if let Some(cleanup) = self.reported_payload_deletions(self.namespace.as_ref()).await? { - fields.insert("external_payload_cleanup".into(), cleanup); - } + fields.insert("external_payload_cleanup".into(), self.payload_deletion_status(self.namespace.as_ref()).await?); Ok((Value::Object(fields), failed)) } diff --git a/rust/src/runtime/payload_cleanup.rs b/rust/src/runtime/payload_cleanup.rs index ca164444b..54417321e 100644 --- a/rust/src/runtime/payload_cleanup.rs +++ b/rust/src/runtime/payload_cleanup.rs @@ -60,11 +60,11 @@ struct Report { store_methods! { /// `externalPayloadCleanupStatus`: the namespace's cleanup metrics. pub(crate) async fn payload_cleanup_status(&self, config: &super::operator_metrics::MetricsConfig) -> Result { - let mut status = json!({"namespace": self.namespace.as_ref(), "cleanup": self.external_payload_cleanup_metrics(config).await?}); - if let Some(cleanup) = self.reported_payload_deletions(self.namespace.as_ref()).await? { - status["retention_cleanup"] = cleanup; - } - Ok(status) + Ok(json!({ + "namespace": self.namespace.as_ref(), + "cleanup": self.external_payload_cleanup_metrics(config).await?, + "retention_cleanup": self.payload_deletion_status(self.namespace.as_ref()).await?, + })) } /// The pass's report; the caller answers 207 when it blocked anything or @@ -113,18 +113,15 @@ store_methods! { .bind(DB::bind_time(cutoff)) .fetch_one(&self.pool) .await?; - let mut body = json!({ + Ok(json!({ "processed": report.processed, "deleted_references": report.deleted_references, "deleted_backing_objects": report.deleted_backing_objects, "shared_objects_preserved": report.shared_objects_preserved, "skipped": report.skipped, "blocked": report.blocked, "storage_driver_failures": report.storage_driver_failures, "backlog": backlog, "scan_limit": limit, "scan_pressure": backlog > 0 && candidates.len() as i64 >= limit, - }); - if let Some(cleanup) = self.reported_payload_deletions(self.namespace.as_ref()).await? { - body["retention_cleanup"] = cleanup; - } - Ok(body) + "retention_cleanup": self.payload_deletion_status(self.namespace.as_ref()).await?, + })) } /// `RuntimePayloadCompletionUploads::cleanup`: an expired budget whose diff --git a/rust/src/runtime/payload_deletions.rs b/rust/src/runtime/payload_deletions.rs index c92f3ac4a..4f0bd50cb 100644 --- a/rust/src/runtime/payload_deletions.rs +++ b/rust/src/runtime/payload_deletions.rs @@ -221,12 +221,4 @@ store_methods! { Ok(json!({"pending": pending, "failed": failed, "blocked": blocked})) } - /// The status where a response reports it: 2.11.8 always adds the counts, - /// but CI's parity reference is still 2.11.7, whose clean answers have no - /// such member. Until the reference moves to 2.11.8 native adds them only - /// when a deletion is pending; a clean answer stays 2.11.7's. - pub(super) async fn reported_payload_deletions(&self, namespace: &str) -> Result> { - let status = self.payload_deletion_status(namespace).await?; - Ok((status["pending"].as_i64().unwrap_or(0) > 0).then_some(status)) - } } diff --git a/rust/src/runtime/workflow_import.rs b/rust/src/runtime/workflow_import.rs index 8c036d5a5..8772f38ec 100644 --- a/rust/src/runtime/workflow_import.rs +++ b/rust/src/runtime/workflow_import.rs @@ -1054,6 +1054,15 @@ impl Runtime { return Ok(answer("rejected", Some(prepared.eligibility.with_error("target.run_id_conflict", "A workflow run with this run_id already exists and was not imported from the same bundle.")), &empty, None)); } + // Core 2.15.12 (Server 2.11.8): an instance of another namespace is + // refused before a dry run or a write, not left to the write's failure. + let instance_id = prepared.summary.instance_id.clone().unwrap_or_default(); + if let Some(namespace) = self.import_instance_namespace(&instance_id).await? + && namespace != prepared.summary.namespace + { + return Ok(answer("rejected", Some(prepared.eligibility.with_error("target.instance_namespace_conflict", + "A workflow instance with this instance_id already exists outside the target namespace.")), &empty, None)); + } let root = Php::Array(prepared.bundle.clone()); // Native's reference fence (Server #765), after PHP's eligibility and // run checks so their answers stay PHP's, and before a dry run or a @@ -1133,6 +1142,18 @@ store_methods! { })) } + /// The namespace of an existing workflow instance, if there is one. + pub(crate) async fn import_instance_namespace(&self, instance_id: &str) -> Result> { + let Some(row) = Self::query("SELECT namespace FROM workflow_instances WHERE id=$1") + .bind(instance_id) + .fetch_optional(&self.pool) + .await? + else { + return Ok(None); + }; + Ok(Some(DB::optional_string(&row, "namespace")?.unwrap_or_default())) + } + pub(crate) fn namespace_name(&self) -> String { self.namespace.as_ref().to_owned() } diff --git a/rust/tests/execution/external_payloads/cleanup.rs b/rust/tests/execution/external_payloads/cleanup.rs index 4b4e32bb0..b8f3bf974 100644 --- a/rust/tests/execution/external_payloads/cleanup.rs +++ b/rust/tests/execution/external_payloads/cleanup.rs @@ -38,7 +38,9 @@ async fn status(router: &Router) -> Value { fn report(values: [i64; 7], backlog: i64, limit: i64, pressure: bool) -> Value { json!({"processed": values[0], "deleted_references": values[1], "deleted_backing_objects": values[2], "shared_objects_preserved": values[3], "skipped": values[4], "blocked": values[5], - "storage_driver_failures": values[6], "backlog": backlog, "scan_limit": limit, "scan_pressure": pressure}) + "storage_driver_failures": values[6], "backlog": backlog, "scan_limit": limit, "scan_pressure": pressure, + // 2.11.8 always reports committed retention deletions still pending. + "retention_cleanup": {"pending": 0, "failed": 0, "blocked": 0}}) } #[tokio::test] diff --git a/rust/tests/execution/external_payloads/namespace_delete.rs b/rust/tests/execution/external_payloads/namespace_delete.rs index cbf1a053b..307173a83 100644 --- a/rust/tests/execution/external_payloads/namespace_delete.rs +++ b/rust/tests/execution/external_payloads/namespace_delete.rs @@ -46,7 +46,7 @@ async fn namespace_delete_settles_its_external_payloads() { assert_eq!(body["deleted"]["external_payloads_deleted"], 1, "{body}"); assert_eq!(body["deleted"]["runtime_external_payload_references"], 2, "{body}"); // Nothing pending: the answer is 2.11.7's, without the cleanup counts. - assert!(body.get("external_payload_cleanup").is_none(), "{body}"); + assert_eq!(body["external_payload_cleanup"], json!({"pending": 0, "failed": 0, "blocked": 0}), "{body}"); assert!(!object(&root, &sole).exists()); assert!(!object(&root, &unused).exists()); assert!(object(&root, &theirs).exists()); diff --git a/rust/tests/execution/external_payloads/retention.rs b/rust/tests/execution/external_payloads/retention.rs index 74b03ad2c..9ee9d6cf3 100644 --- a/rust/tests/execution/external_payloads/retention.rs +++ b/rust/tests/execution/external_payloads/retention.rs @@ -187,7 +187,7 @@ async fn retention_without_storage_or_after_a_failed_delete_keeps_the_run() { std::fs::set_permissions(&directory, std::fs::Permissions::from_mode(0o755)).unwrap(); let (status, body) = cleanup_pass(&router).await; assert_eq!(status, StatusCode::OK, "{body}"); - assert!(body["cleanup"].get("retention_cleanup").is_none(), "{body}"); + assert_eq!(body["cleanup"]["retention_cleanup"], json!({"pending": 0, "failed": 0, "blocked": 0}), "{body}"); } else { std::fs::remove_file(directory.join("probe")).unwrap(); std::fs::set_permissions(&directory, std::fs::Permissions::from_mode(0o755)).unwrap(); @@ -199,7 +199,7 @@ async fn retention_without_storage_or_after_a_failed_delete_keeps_the_run() { let (status, body) = ns_request(&router, "POST", PASS, "default", json!({"run_ids": [second]})).await; assert_eq!(status, StatusCode::OK, "{body}"); pruned(&body["results"][0], 1); - assert!(body.get("external_payload_cleanup").is_none(), "nothing pending: {body}"); + assert_eq!(body["external_payload_cleanup"], json!({"pending": 0, "failed": 0, "blocked": 0}), "nothing pending: {body}"); assert!(!object(&root, &shared).exists()); } @@ -308,7 +308,7 @@ async fn pending_deletions_wait_out_a_backup_hold_and_yield_to_a_new_registratio database.execute("UPDATE runtime_external_payload_backup_hold SET expires_at='2000-01-01 00:00:00'").await; let (status, body) = cleanup_pass(&router).await; assert_eq!(status, StatusCode::OK, "{body}"); - assert!(body["cleanup"].get("retention_cleanup").is_none(), "{body}"); + assert_eq!(body["cleanup"]["retention_cleanup"], json!({"pending": 0, "failed": 0, "blocked": 0}), "{body}"); assert!(!object(&root, &held).exists()); assert!(object(&root, &again).exists()); assert_eq!(registered(&database, &again).await, 1); diff --git a/rust/tests/execution/namespaces.rs b/rust/tests/execution/namespaces.rs index 7849e0d3e..7c51a003b 100644 --- a/rust/tests/execution/namespaces.rs +++ b/rust/tests/execution/namespaces.rs @@ -797,8 +797,9 @@ async fn namespace_delete_removes_only_what_the_namespace_owns() { let (status, body) = scoped(&app, "default", "DELETE", "/api/namespaces/DOOMED", Value::Null).await; assert_eq!(status, StatusCode::OK, "{body}"); // What published PHP 2.5.14 reports for one started run and one search - // attribute definition. - assert_eq!(body, json!({"name":"doomed","status":"deleted","deleted":{ + // attribute definition, with 2.11.8's post-commit deletion counts. + assert_eq!(body, json!({"name":"doomed","status":"deleted", + "external_payload_cleanup":{"pending":0,"failed":0,"blocked":0},"deleted":{ "workflow_commands":1,"workflow_history_events":2,"workflow_tasks":1, "search_attribute_definitions":1,"workflow_run_summaries":1,"workflow_runs":1,"workflow_instances":1}})); for (method, uri) in [("GET", "/api/namespaces/doomed"), ("DELETE", "/api/namespaces/doomed")] { diff --git a/scripts/conformance/server-parity.mjs b/scripts/conformance/server-parity.mjs index c12e7148c..617d4a10a 100644 --- a/scripts/conformance/server-parity.mjs +++ b/scripts/conformance/server-parity.mjs @@ -44,7 +44,7 @@ Requires Node 20+ and PHP 8.3+ with the locked adapter installed. Each target must have its own isolated, already bootstrapped database. Set DW_PARITY_TOKEN for the HTTP target; it is never recorded. Use the same --prefix on all targets and a fresh database or prefix for a new run. --artifacts selects the exact -consumer tuple; the default is tests/Fixtures/ServerParityBaselines/php-2.11.7.json. +consumer tuple; the default is tests/Fixtures/ServerParityBaselines/php-2.11.8.json. Repeat --fixture PATH to record or compare an explicitly selected candidate set. --database-resource-limits accepts inspected memory_bytes and memory_swap_bytes as a JSON object; comparisons require equal effective @@ -81,7 +81,7 @@ try { } const record = { schema: 'durable-workflow.server-parity-record/v1', target: values.target, mode: values.mode, - runner_revision: values['runner-revision'], artifacts: json(values.artifacts ?? resolve(root, 'tests/Fixtures/ServerParityBaselines/php-2.11.7.json')), + runner_revision: values['runner-revision'], artifacts: json(values.artifacts ?? resolve(root, 'tests/Fixtures/ServerParityBaselines/php-2.11.8.json')), started_at: new Date().toISOString(), outcome: 'runner-blocked', fixture_hashes: hashes, cases: [], database_resource_limits: parseDatabaseResourceLimits(values['database-resource-limits']), }; diff --git a/scripts/conformance/server-parity/README.md b/scripts/conformance/server-parity/README.md index e6710ff1a..58c0521ad 100644 --- a/scripts/conformance/server-parity/README.md +++ b/scripts/conformance/server-parity/README.md @@ -287,7 +287,7 @@ Docker kill and verifies exit code 137 before restarting the native process. For an adapter installed elsewhere, set `DW_PARITY_SDK_AUTOLOAD` to its locked `vendor/autoload.php`. `--artifacts` selects a frozen tuple manifest. The default -is `tests/Fixtures/ServerParityBaselines/php-2.11.7.json`; its SDK version must match +is `tests/Fixtures/ServerParityBaselines/php-2.11.8.json`; its SDK version must match the installed lock. A frozen tuple does not prove every listed consumer ran. The original `tests/Fixtures/ServerParity/php-baseline.json` remains an immutable 2.5.13 / Workflow 2.5.4 reference, together with its known NUL reproducer outside diff --git a/scripts/conformance/server-parity/activity-deadline-embedded.php b/scripts/conformance/server-parity/activity-deadline-embedded.php index 293dd8323..94f7c434e 100644 --- a/scripts/conformance/server-parity/activity-deadline-embedded.php +++ b/scripts/conformance/server-parity/activity-deadline-embedded.php @@ -53,6 +53,9 @@ public function handle(mixed $value): mixed } config(['queue.default' => 'database', 'workflows.v2.task_dispatch_mode' => 'queue', + // Core 2.15.12 (Server 2.11.8) resolves a run through its instance's + // namespace, and reserves a caller-named instance without model events. + 'workflows.v2.namespace' => 'default', 'workflows.v2.types.workflows' => ['parity.v1.activity_deadline' => ParityDeadlineWorkflow::class], 'workflows.v2.types.activities' => ['parity.v1.deadline_activity' => ParityDeadlineActivity::class]]); foreach ([\Workflow\V2\Models\WorkflowInstance::class, \Workflow\V2\Models\WorkflowRun::class, diff --git a/scripts/conformance/server-parity/activity-deadline-receipts-embedded.php b/scripts/conformance/server-parity/activity-deadline-receipts-embedded.php index 2e68bbadd..064a238d4 100644 --- a/scripts/conformance/server-parity/activity-deadline-receipts-embedded.php +++ b/scripts/conformance/server-parity/activity-deadline-receipts-embedded.php @@ -51,6 +51,9 @@ public function handle(mixed $value): mixed } config(['queue.default' => 'database', 'workflows.v2.task_dispatch_mode' => 'queue', + // Core 2.15.12 (Server 2.11.8) resolves a run through its instance's + // namespace, and reserves a caller-named instance without model events. + 'workflows.v2.namespace' => 'default', 'workflows.v2.types.workflows' => [$fixture['workflow_type'] => ParityReceiptWorkflow::class], 'workflows.v2.types.activities' => ['parity.v1.deadline_activity' => ParityReceiptActivity::class]]); foreach ([\Workflow\V2\Models\WorkflowInstance::class, \Workflow\V2\Models\WorkflowRun::class, diff --git a/scripts/conformance/server-parity/cancellation-probe.php b/scripts/conformance/server-parity/cancellation-probe.php index df76cfece..df4e04b39 100644 --- a/scripts/conformance/server-parity/cancellation-probe.php +++ b/scripts/conformance/server-parity/cancellation-probe.php @@ -174,6 +174,9 @@ function embeddedCancellationObservation(array $fixture, string $workflowId, str $app->make(Kernel::class)->bootstrap(); require __DIR__.'/embedded-types.php'; config(['queue.default' => 'database', 'workflows.v2.task_dispatch_mode' => 'queue', + // Core 2.15.12 (Server 2.11.8) resolves a run through its instance's + // namespace, and reserves a caller-named instance without model events. + 'workflows.v2.namespace' => $namespace, 'workflows.v2.types.workflows' => [ 'parity.v1.cancel_before_claim' => \ServerParity\CancelBeforeClaimWorkflow::class, 'parity.v1.cancel_pending_timer' => \ServerParity\CancelPendingTimerWorkflow::class, diff --git a/scripts/conformance/server-parity/child-open-parent-task-probe.php b/scripts/conformance/server-parity/child-open-parent-task-probe.php index 0b4df8ab0..6dc45c8f5 100644 --- a/scripts/conformance/server-parity/child-open-parent-task-probe.php +++ b/scripts/conformance/server-parity/child-open-parent-task-probe.php @@ -13,6 +13,10 @@ // result leaves the parent a ready resume task; then the child completes. // Records the parent's description, every workflow task a worker can then // claim for the parent, and the run's close from the first of them. +// +// The leased case claims that resume task before the child completes, so the +// lease's history lacks the child's result, then completes the lease with a +// long timer (workflow#962: Core 2.15.10 gives the parent a follow-up task). function finishHttpChildOpenParentTask(Client $admin, array $fixture, string $workflowId, string $url): array { $definition = $fixture['child_open_parent_task']; @@ -66,51 +70,74 @@ function finishHttpChildOpenParentTask(Client $admin, array $fixture, string $wo ['lease_owner' => $task['lease_owner'], 'workflow_task_attempt' => $task['workflow_task_attempt'], 'commands' => $commands]); $answer = static fn (array $result): array => ['status' => $result['status'], 'reason' => $result['response']['reason'] ?? null, 'run_status' => $result['response']['run_status'] ?? null]; - $described = static fn (): array => array_intersect_key( - $raw('GET', 'workflows/'.rawurlencode($id))['response'], array_flip($definition['described_fields'])); - - $first = $poll('workflow', $worker, $queue, 5) ?? throw new RuntimeException('Child open parent task: no first task'); - $opened = $complete($first, [ - ['type' => 'start_child_workflow', 'workflow_type' => $definition['child_type'], 'arguments' => $empty, 'queue' => $childQueue], - ['type' => 'schedule_activity', 'activity_type' => $definition['activity_type'], 'arguments' => $empty], - ]); - $activity = $poll('activity', $worker, $queue, 5) ?? throw new RuntimeException('Child open parent task: no activity'); - $activityDone = $raw('POST', 'worker/activity-tasks/'.$activity['task_id'].'/complete', ['lease_owner' => $activity['lease_owner'], - 'activity_attempt_id' => $activity['activity_attempt_id'], 'result' => $empty]); - $child = $poll('workflow', $childWorker, $childQueue, 5) ?? throw new RuntimeException('Child open parent task: no child task'); - $childDone = $complete($child, [['type' => 'complete_workflow', 'result' => $empty]]); - $afterChild = $described(); - - // Every workflow task a worker can now claim for the parent. - $claimed = []; - for ($attempt = 0; $attempt < 3; $attempt++) { - $task = $poll('workflow', $worker, $queue, $attempt === 0 ? 5 : 1); - if ($task === null) { - break; + $claimable = static function (string $runId) use ($poll, $worker, $queue): array { + // Every workflow task a worker can now claim for the parent. + $claimed = []; + for ($attempt = 0; $attempt < 3; $attempt++) { + $task = $poll('workflow', $worker, $queue, $attempt === 0 ? 5 : 1); + if ($task === null) { + break; + } + if (isset($task['workflow_id']) && $task['workflow_id'] !== $runId) { + throw new RuntimeException('Child open parent task: a task for another run: '.json_encode($task['workflow_id'] ?? null)); + } + $claimed[] = $task; } - $claimed[] = $task; - } - $tasks = array_map(static fn (array $task): array => [ + + return $claimed; + }; + $shape = static fn (array $claimed): array => array_map(static fn (array $task): array => [ 'workflow_update_id' => $task['workflow_update_id'] ?? null, 'replays_child_result' => in_array('ChildRunCompleted', array_map( static fn (array $event): string => (string) ($event['event_type'] ?? ''), $task['history_events'] ?? []), true), ], $claimed); - $closed = $claimed === [] ? null : $answer($complete($claimed[0], [['type' => 'complete_workflow', 'result' => $empty]])); - $final = $described(); - if ($final['status'] !== 'completed') { - $raw('POST', 'workflows/'.rawurlencode($id).'/terminate', ['reason' => 'child open parent task recorded']); - } + $case = static function (string $runId, bool $leased, bool $start) use ($raw, $poll, $complete, $answer, $claimable, $shape, $definition, + $empty, $queue, $childQueue, $worker, $childWorker): array { + $described = static fn (): array => array_intersect_key( + $raw('GET', 'workflows/'.rawurlencode($runId))['response'], array_flip($definition['described_fields'])); + if ($start && $raw('POST', 'workflows', ['workflow_id' => $runId, 'workflow_type' => $definition['workflow_type'], + 'task_queue' => $queue, 'input' => $empty])['status'] !== 201) { + throw new RuntimeException('Child open parent task: start '.$runId); + } + $first = $poll('workflow', $worker, $queue, 5) ?? throw new RuntimeException('Child open parent task: no first task'); + $opened = $complete($first, [ + ['type' => 'start_child_workflow', 'workflow_type' => $definition['child_type'], 'arguments' => $empty, 'queue' => $childQueue], + ['type' => 'schedule_activity', 'activity_type' => $definition['activity_type'], 'arguments' => $empty], + ]); + $activity = $poll('activity', $worker, $queue, 5) ?? throw new RuntimeException('Child open parent task: no activity'); + $activityDone = $raw('POST', 'worker/activity-tasks/'.$activity['task_id'].'/complete', ['lease_owner' => $activity['lease_owner'], + 'activity_attempt_id' => $activity['activity_attempt_id'], 'result' => $empty]); + $lease = $leased ? ($poll('workflow', $worker, $queue, 5) ?? throw new RuntimeException('Child open parent task: no resume task')) : null; + $child = $poll('workflow', $childWorker, $childQueue, 5) ?? throw new RuntimeException('Child open parent task: no child task'); + $childDone = $complete($child, [['type' => 'complete_workflow', 'result' => $empty]]); + $afterChild = $described(); + // The lease's worker has not seen the child's result; it waits on a + // long timer instead, as a workflow body awaiting a timer would. + $leaseDone = $lease === null ? null : $answer($complete($lease, [['type' => 'start_timer', 'delay_seconds' => 3600]])); + $afterLease = $lease === null ? null : $described(); + $claimed = $claimable($runId); + $closed = $claimed === [] ? null : $answer($complete($claimed[0], [['type' => 'complete_workflow', 'result' => $empty]])); + $final = $described(); + if ($final['status'] !== 'completed') { + $raw('POST', 'workflows/'.rawurlencode($runId).'/terminate', ['reason' => 'child open parent task recorded']); + } - return [ - 'applicable' => true, - 'ready' => [ + return [ 'opened' => $answer($opened), 'activity_completed' => $activityDone['status'], + ...($lease === null ? [] : ['lease_replays_child_result' => $shape([$lease])[0]['replays_child_result']]), 'child_completed' => $answer($childDone), 'described_after_child' => $afterChild, - 'claimable_parent_tasks' => $tasks, + ...($lease === null ? [] : ['lease_completed' => $leaseDone, 'described_after_lease' => $afterLease]), + 'claimable_parent_tasks' => $shape($claimed), 'closed' => $closed, 'described_after_close' => $final, - ], + ]; + }; + + return [ + 'applicable' => true, + 'ready' => $case($id, false, false), + ...(isset($definition['expected']['leased']) ? ['leased' => $case($id.'-leased', true, true)] : []), ]; } diff --git a/scripts/conformance/server-parity/continue-embedded.php b/scripts/conformance/server-parity/continue-embedded.php index b67f07a71..cebc81d4f 100644 --- a/scripts/conformance/server-parity/continue-embedded.php +++ b/scripts/conformance/server-parity/continue-embedded.php @@ -69,6 +69,9 @@ public function handle(array $input): mixed } config(['queue.default' => 'database', 'workflows.v2.task_dispatch_mode' => 'queue', + // Core 2.15.12 (Server 2.11.8) resolves a run through its instance's + // namespace, and reserves a caller-named instance without model events. + 'workflows.v2.namespace' => 'default', 'workflows.v2.types.workflows' => [$fixture['workflow_type'] => ContinueEmbeddedWorkflow::class], 'workflows.v2.types.activities' => ['parity.v1.continue_echo' => ContinueEmbeddedActivity::class]]); foreach ([WorkflowInstance::class, WorkflowRun::class, \Workflow\V2\Models\WorkflowTask::class] as $model) { diff --git a/scripts/conformance/server-parity/cooperative-probe.php b/scripts/conformance/server-parity/cooperative-probe.php index 3a52e3ee4..4013998a7 100644 --- a/scripts/conformance/server-parity/cooperative-probe.php +++ b/scripts/conformance/server-parity/cooperative-probe.php @@ -184,6 +184,9 @@ function embeddedCooperativeObservation(array $fixture, string $workflowId, stri } require __DIR__.'/embedded-types.php'; config(['queue.default' => 'database', 'workflows.v2.task_dispatch_mode' => 'queue', + // Core 2.15.12 (Server 2.11.8) resolves a run through its instance's + // namespace, and reserves a caller-named instance without model events. + 'workflows.v2.namespace' => $namespace, 'workflows.v2.types.workflows' => ['parity.v1.cooperative_cleanup' => \ServerParity\CooperativeCleanupWorkflow::class], 'workflows.v2.types.activities' => ['parity.v1.cooperative_cleanup_activity' => \ServerParity\CooperativeCleanupActivity::class]]); foreach ([WorkflowInstance::class, WorkflowRun::class, WorkflowTask::class] as $model) { diff --git a/scripts/conformance/server-parity/memo-embedded.php b/scripts/conformance/server-parity/memo-embedded.php index ad4931e4d..a22eb092e 100644 --- a/scripts/conformance/server-parity/memo-embedded.php +++ b/scripts/conformance/server-parity/memo-embedded.php @@ -64,6 +64,9 @@ public function handle(mixed $value): mixed } config(['queue.default' => 'database', 'workflows.v2.task_dispatch_mode' => 'queue', + // Core 2.15.12 (Server 2.11.8) resolves a run through its instance's + // namespace, and reserves a caller-named instance without model events. + 'workflows.v2.namespace' => 'default', 'workflows.v2.types.workflows' => [$fixture['workflow_type'] => MemoEmbeddedWorkflow::class], 'workflows.v2.types.activities' => ['parity.v1.memo_echo' => MemoEmbeddedActivity::class]]); foreach ([\Workflow\V2\Models\WorkflowInstance::class, WorkflowRun::class, \Workflow\V2\Models\WorkflowTask::class] as $model) { diff --git a/scripts/conformance/server-parity/namespace-delete-contract.mjs b/scripts/conformance/server-parity/namespace-delete-contract.mjs index b7cb741e1..f6fcdd5f4 100644 --- a/scripts/conformance/server-parity/namespace-delete-contract.mjs +++ b/scripts/conformance/server-parity/namespace-delete-contract.mjs @@ -24,7 +24,9 @@ export function checkNamespaceDelete(fixture, observation, workflowId) { equal(state.deleted.status, 200, 'namespace deleted'); const {deleted, ...response} = state.deleted.response; - equal(response, {name: namespace, status: 'deleted'}, 'delete response'); + // 2.11.8 always reports its post-commit payload deletions (#911). + equal(response, {name: namespace, status: 'deleted', external_payload_cleanup: definition.external_payload_cleanup}, + 'delete response'); const exact = Object.fromEntries(Object.entries(deleted).filter(([key]) => !definition.asynchronous_projections.includes(key))); equal(exact, definition.deleted, 'each owned table deleted with its count'); for (const key of definition.asynchronous_projections) { diff --git a/scripts/conformance/server-parity/namespace-delete-payloads-probe.php b/scripts/conformance/server-parity/namespace-delete-payloads-probe.php index e7202376b..f97ca136d 100644 --- a/scripts/conformance/server-parity/namespace-delete-payloads-probe.php +++ b/scripts/conformance/server-parity/namespace-delete-payloads-probe.php @@ -86,7 +86,9 @@ function finishHttpNamespaceDeletePayloads(Client $admin, array $fixture, string $state['steps'][$step] = $status === 200 ? ['status' => 200, 'name_matches' => ($body['name'] ?? null) === $name, 'outcome' => $body['status'] ?? null, 'payloads' => array_intersect_key($body['deleted'] ?? [], - array_flip(['external_payloads_deleted', 'runtime_external_payload_references']))] + array_flip(['external_payloads_deleted', 'runtime_external_payload_references'])), + // 2.11.8's post-commit provider deletions still pending (#911). + 'cleanup' => $body['external_payload_cleanup'] ?? null] : ['status' => $status, 'body' => $body, ...$named]; }; $described = static function (string $step, string $name) use ($json, &$state): void { diff --git a/scripts/conformance/server-parity/native-image-corpus.sh b/scripts/conformance/server-parity/native-image-corpus.sh index 39b5d061e..d1f4512d0 100755 --- a/scripts/conformance/server-parity/native-image-corpus.sh +++ b/scripts/conformance/server-parity/native-image-corpus.sh @@ -27,7 +27,7 @@ scope="dw-parity-${GITHUB_RUN_ID:-local}-${GITHUB_RUN_ATTEMPT:-1}-${GITHUB_JOB:- export RESOURCE_SCOPE="$scope" export DW_PARITY_RUNNER_REVISION DW_PARITY_RUNNER_REVISION=$(git rev-parse HEAD) -image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.7.json) +image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.8.json) # CI's corpus selection: the reviewed corpus without service-calls, which # records separately below with PHP's maintenance loop stopped (Server #796), diff --git a/scripts/conformance/server-parity/patch-deployment-probe.php b/scripts/conformance/server-parity/patch-deployment-probe.php index e89a0cd8b..7c4dc84a4 100644 --- a/scripts/conformance/server-parity/patch-deployment-probe.php +++ b/scripts/conformance/server-parity/patch-deployment-probe.php @@ -319,6 +319,9 @@ function patchEmbeddedPhase(array $fixture, array $options): array $definition = ($fixture['patch_deployment']['original_patch'] ?? false) ? 'replacement' : $options['patch-phase']; require __DIR__.'/patch-deployment-'.$definition.'.php'; config(['queue.default' => 'database', 'workflows.v2.task_dispatch_mode' => 'queue', + // Core 2.15.12 (Server 2.11.8) resolves a run through its instance's + // namespace, and reserves a caller-named instance without model events. + 'workflows.v2.namespace' => 'default', 'workflows.v2.types.workflows' => [$fixture['workflow_type'] => \ServerParityPatch\DeploymentWorkflow::class], 'workflows.v2.types.activities' => ['parity.v1.echo_activity' => \ServerParity\EchoActivity::class]]); foreach ([WorkflowInstance::class, WorkflowRun::class, WorkflowTask::class] as $model) { diff --git a/scripts/conformance/server-parity/probe.php b/scripts/conformance/server-parity/probe.php index b09756f43..0727d3839 100644 --- a/scripts/conformance/server-parity/probe.php +++ b/scripts/conformance/server-parity/probe.php @@ -669,6 +669,9 @@ function embeddedObservation(array $fixture, string $workflowId, string $namespa config([ 'queue.default' => 'database', 'workflows.v2.task_dispatch_mode' => 'queue', + // Core 2.15.12 (Server 2.11.8) resolves a run through its instance's + // namespace, and reserves a caller-named instance without model events. + 'workflows.v2.namespace' => $namespace, 'workflows.v2.types.workflows' => [ 'parity.v1.echo' => EchoWorkflow::class, 'parity.v1.one_activity' => OneActivityWorkflow::class, diff --git a/scripts/conformance/server-parity/range-pending-probe.php b/scripts/conformance/server-parity/range-pending-probe.php index 35785ff3c..863084028 100644 --- a/scripts/conformance/server-parity/range-pending-probe.php +++ b/scripts/conformance/server-parity/range-pending-probe.php @@ -146,6 +146,9 @@ public function handle(array $value): array $definition = __DIR__.'/range-pending-embedded-'.($phase === 'incompatible' ? 'incompatible' : 'original').'.php'; require $definition; config(['queue.default' => 'database', 'workflows.v2.task_dispatch_mode' => 'queue', + // Core 2.15.12 (Server 2.11.8) resolves a run through its instance's + // namespace, and reserves a caller-named instance without model events. + 'workflows.v2.namespace' => 'default', 'workflows.v2.types.workflows' => [$fixture['workflow_type'] => RangeRepairWorkflow::class], 'workflows.v2.types.activities' => ['parity.v1.echo_activity' => RangeRepairActivity::class]]); foreach ([\Workflow\V2\Models\WorkflowInstance::class, \Workflow\V2\Models\WorkflowRun::class, diff --git a/scripts/conformance/server-parity/range-repair-probe.php b/scripts/conformance/server-parity/range-repair-probe.php index 0c78e45e5..35fb61207 100644 --- a/scripts/conformance/server-parity/range-repair-probe.php +++ b/scripts/conformance/server-parity/range-repair-probe.php @@ -187,6 +187,9 @@ public function handle(array $value): array $definition = __DIR__.'/range-repair-embedded-'.($phase === 'incompatible' ? 'incompatible' : 'original').'.php'; require $definition; config(['queue.default' => 'database', 'workflows.v2.task_dispatch_mode' => 'queue', + // Core 2.15.12 (Server 2.11.8) resolves a run through its instance's + // namespace, and reserves a caller-named instance without model events. + 'workflows.v2.namespace' => 'default', 'workflows.v2.types.workflows' => [$fixture['workflow_type'] => RangeRepairWorkflow::class], 'workflows.v2.types.activities' => ['parity.v1.echo_activity' => RangeRepairActivity::class]]); foreach ([\Workflow\V2\Models\WorkflowInstance::class, \Workflow\V2\Models\WorkflowRun::class, diff --git a/scripts/conformance/server-parity/retention-payloads-probe.php b/scripts/conformance/server-parity/retention-payloads-probe.php index 7dbd8b711..0ffee16d9 100644 --- a/scripts/conformance/server-parity/retention-payloads-probe.php +++ b/scripts/conformance/server-parity/retention-payloads-probe.php @@ -67,7 +67,9 @@ function finishHttpRetentionPayloads(Client $admin, array $fixture, string $work $result = $report['results'][0] ?? []; $state['steps'][$step] = ['status' => $status, 'processed' => $report['processed'] ?? null, 'run' => ($result['run_id'] ?? null) === $runId ? $label : ($result['run_id'] ?? null), - 'result' => array_intersect_key($result, array_flip(['outcome', 'reason', 'external_payloads_deleted']))]; + 'result' => array_intersect_key($result, array_flip(['outcome', 'reason', 'external_payloads_deleted'])), + // 2.11.8's post-commit provider deletions still pending (#911). + 'cleanup' => $report['external_payload_cleanup'] ?? null]; }; $fetch = static function (string $step, string $in, array $reference) use ($http, $headers, &$state): void { $response = $http->get('external-payloads/v1/'.rawurlencode((string) ($reference['reference_id'] ?? '')), [ diff --git a/scripts/conformance/server-parity/role-profile.sh b/scripts/conformance/server-parity/role-profile.sh index 49d645546..0c874b7ac 100644 --- a/scripts/conformance/server-parity/role-profile.sh +++ b/scripts/conformance/server-parity/role-profile.sh @@ -8,7 +8,7 @@ test -n "$RESOURCE_SCOPE" scope_identity="$GITHUB_RUN_ID-$GITHUB_RUN_ATTEMPT-$GITHUB_JOB" case "$RESOURCE_SCOPE" in *"$scope_identity"*) ;; *) exit 2 ;; esac backend="$1" -image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.7.json) +image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.8.json) rust_image=mirror.gcr.io/library/rust@sha256:ba81bc3eaa4422af576c0262515d96b0111a628a6ccc2c86557cf55c9a4bbee0 fixture=tests/Fixtures/ServerParityProfiles/role-tokens/admission-role-tokens.json credentials=(-e DW_AUTH_TOKEN=parity-role-legacy -e DW_WORKER_TOKEN=parity-role-worker diff --git a/scripts/conformance/server-parity/update-validation-sqlite.sh b/scripts/conformance/server-parity/update-validation-sqlite.sh index 15dd65c22..fbdebc5cf 100644 --- a/scripts/conformance/server-parity/update-validation-sqlite.sh +++ b/scripts/conformance/server-parity/update-validation-sqlite.sh @@ -37,7 +37,7 @@ name="${3:-update-validation}" [[ -n "$DW_PARITY_RUNNER_REVISION" ]] fixture="tests/Fixtures/ServerParity/$name.json" test -f "$fixture" -image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.7.json) +image=$(jq -r '.server.images["linux/amd64"] | sub("^durableworkflow/server@"; "ghcr.io/durable-workflow/server@")' tests/Fixtures/ServerParityBaselines/php-2.11.8.json) . scripts/conformance/server-parity/php-maintenance-window.sh prefix=parity-v1 diff --git a/scripts/conformance/server-parity/workflow-import-contract.mjs b/scripts/conformance/server-parity/workflow-import-contract.mjs index 02db4c5ac..12dc3eb47 100644 --- a/scripts/conformance/server-parity/workflow-import-contract.mjs +++ b/scripts/conformance/server-parity/workflow-import-contract.mjs @@ -1,18 +1,18 @@ import assert from 'node:assert/strict'; // Reviewed history import (EmbeddedV2ImportController), recorded against -// published Server 2.11.1. The fixture's `expected` holds the whole +// published Server 2.11.1 and moved to 2.11.8. The fixture's `expected` holds the whole // normalized observation, with the probe's workflow prefix as `{id}`, bundle // identities, checksums and signatures as `{