run-tests #717
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: run-tests | |
| on: | |
| push: | |
| branches: | |
| - main | |
| - feature/* | |
| tags: | |
| - v* | |
| pull_request: | |
| branches: | |
| - main | |
| - release-* | |
| - feature/* | |
| workflow_dispatch: | |
| inputs: | |
| daprdapr_commit: | |
| description: 'Dapr/Dapr commit to build custom daprd from' | |
| required: false | |
| default: '' | |
| daprcli_commit: | |
| description: 'Dapr/CLI commit to build custom dapr CLI from' | |
| required: false | |
| default: '' | |
| repository_dispatch: | |
| types: [validate-examples] | |
| merge_group: | |
| jobs: | |
| validate: | |
| runs-on: ubuntu-latest | |
| env: | |
| CHECKOUT_REPO: ${{ github.repository }} | |
| CHECKOUT_REF: ${{ github.ref }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| python_ver: ["3.10", "3.11", "3.12", "3.13", "3.14"] | |
| steps: | |
| - name: Parse repository_dispatch payload | |
| if: github.event_name == 'repository_dispatch' | |
| env: | |
| COMMAND: ${{ github.event.client_payload.command }} | |
| PULL_HEAD_REPO: ${{ github.event.client_payload.pull_head_repo }} | |
| PULL_HEAD_REF: ${{ github.event.client_payload.pull_head_ref }} | |
| run: | | |
| if [ "$COMMAND" = "ok-to-test" ]; then | |
| echo "CHECKOUT_REPO=$PULL_HEAD_REPO" >> "$GITHUB_ENV" | |
| echo "CHECKOUT_REF=$PULL_HEAD_REF" >> "$GITHUB_ENV" | |
| fi | |
| - name: Check out code onto GOPATH | |
| uses: actions/checkout@v7 | |
| with: | |
| repository: ${{ env.CHECKOUT_REPO }} | |
| ref: ${{ env.CHECKOUT_REF }} | |
| - name: Determine latest Dapr Runtime version | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| MIN_RUNTIME_VERSION="1.18.0" | |
| RUNTIME_VERSION=$(curl -fsS -H "Authorization: Bearer $GITHUB_TOKEN" \ | |
| "https://api.github.com/repos/dapr/dapr/releases?per_page=10" | \ | |
| jq -r 'map(select(.prerelease == false)) | sort_by(.created_at) | reverse | .[0].tag_name | ltrimstr("v")') | |
| if [ -z "$RUNTIME_VERSION" ] || [ "$RUNTIME_VERSION" = "null" ]; then | |
| echo "Failed to resolve Dapr Runtime version" && exit 1 | |
| fi | |
| if [ "$(printf '%s\n' "$MIN_RUNTIME_VERSION" "$RUNTIME_VERSION" | sort -V | head -n1)" != "$MIN_RUNTIME_VERSION" ]; then | |
| echo "Resolved runtime version $RUNTIME_VERSION is below minimum $MIN_RUNTIME_VERSION, using minimum instead" | |
| RUNTIME_VERSION="$MIN_RUNTIME_VERSION" | |
| fi | |
| echo "DAPR_RUNTIME_VER=$RUNTIME_VERSION" >> $GITHUB_ENV | |
| echo "Found $RUNTIME_VERSION" | |
| - name: Determine latest Dapr CLI version | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| CLI_VERSION=$(curl -fsS -H "Authorization: Bearer $GITHUB_TOKEN" \ | |
| "https://api.github.com/repos/dapr/cli/releases?per_page=10" | \ | |
| jq -r 'map(select(.prerelease == false)) | sort_by(.created_at) | reverse | .[0].tag_name | ltrimstr("v")') | |
| if [ -z "$CLI_VERSION" ] || [ "$CLI_VERSION" = "null" ]; then | |
| echo "Failed to resolve Dapr CLI version" && exit 1 | |
| fi | |
| echo "DAPR_CLI_VER=$CLI_VERSION" >> $GITHUB_ENV | |
| echo "Found $CLI_VERSION" | |
| - name: Set up Python ${{ matrix.python_ver }} | |
| uses: actions/setup-python@v7 | |
| with: | |
| python-version: ${{ matrix.python_ver }} | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v9.0.0 | |
| - name: Install dependencies | |
| run: uv sync --frozen --all-packages --group tests | |
| - name: Set up Dapr CLI | |
| uses: dapr/.github/.github/actions/setup-dapr-cli@main | |
| with: | |
| commit: ${{ github.event.inputs.daprcli_commit }} | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Set up Dapr runtime | |
| uses: dapr/.github/.github/actions/setup-dapr-runtime@main | |
| with: | |
| commit: ${{ github.event.inputs.daprdapr_commit }} | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| # The official install.sh spends ~1.5 minutes creating a system user and | |
| # a systemd service that CI does not need; extracting the tarball and | |
| # running `ollama serve` directly takes seconds. | |
| # The version is pinned so an upstream release cannot silently break CI. | |
| - name: Set up Llama | |
| run: | | |
| curl -fsSL https://github.com/ollama/ollama/releases/download/v0.32.0/ollama-linux-amd64.tar.zst | sudo tar --zstd -xf - -C /usr/local | |
| # TODO: temporary workaround — the Sapphire Rapids CPU backend | |
| # segfaults during first inference (ollama/ollama#17006, | |
| # ollama/ollama#17205); removing it makes ollama fall back to a | |
| # slower generic backend that works on every runner. Drop this line | |
| # once the pin moves to a release that fixes those issues. | |
| sudo rm -f /usr/local/lib/ollama/libggml-cpu-sapphirerapids.so | |
| nohup ollama serve > "$RUNNER_TEMP/ollama-serve.log" 2>&1 & | |
| timeout 60 bash -c 'until curl -fsS http://127.0.0.1:11434/api/tags > /dev/null; do sleep 1; done' | |
| ollama pull llama3.2:latest | |
| # `dapr_head` covers behavior that only exists in daprd built from master; | |
| # this job installs the latest release, so those tests run in | |
| # validate-dapr-head instead. | |
| - name: Run integration tests | |
| run: | | |
| uv run pytest tests/integration/ -m "not dapr_head" | |
| - name: Validate examples | |
| run: | | |
| uv run pytest tests/examples/ | |
| # The stateful-history delta path (dapr/durabletask-go#110, reaching dapr via | |
| # dapr/dapr#10142) is not in any release yet, so the matrix above cannot | |
| # exercise it. This job builds daprd from master and runs the workflow suites | |
| # against it. It also runs the vendored durabletask e2e tests, which nothing | |
| # else does: build.yaml deselects `-m e2e`, and the validate job above only | |
| # covers tests/integration and tests/examples. | |
| validate-dapr-head: | |
| runs-on: ubuntu-latest | |
| env: | |
| CHECKOUT_REPO: ${{ github.repository }} | |
| CHECKOUT_REF: ${{ github.ref }} | |
| # Distinct from the integration suite's 135xx block and the examples | |
| # suite's 136xx block, and below the OS ephemeral range. See the "Port | |
| # allocation" section in tests/integration/AGENTS.md. | |
| E2E_HTTP_PORT: 13700 | |
| E2E_GRPC_PORT: 13701 | |
| steps: | |
| - name: Parse repository_dispatch payload | |
| if: github.event_name == 'repository_dispatch' | |
| env: | |
| COMMAND: ${{ github.event.client_payload.command }} | |
| PULL_HEAD_REPO: ${{ github.event.client_payload.pull_head_repo }} | |
| PULL_HEAD_REF: ${{ github.event.client_payload.pull_head_ref }} | |
| run: | | |
| if [ "$COMMAND" = "ok-to-test" ]; then | |
| echo "CHECKOUT_REPO=$PULL_HEAD_REPO" >> "$GITHUB_ENV" | |
| echo "CHECKOUT_REF=$PULL_HEAD_REF" >> "$GITHUB_ENV" | |
| fi | |
| - name: Check out code | |
| uses: actions/checkout@v7 | |
| with: | |
| repository: ${{ env.CHECKOUT_REPO }} | |
| ref: ${{ env.CHECKOUT_REF }} | |
| - name: Set up Python | |
| uses: actions/setup-python@v7 | |
| with: | |
| python-version: "3.13" | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v9.0.0 | |
| - name: Install dependencies | |
| run: uv sync --frozen --all-packages --group tests | |
| # setup-dapr-runtime builds daprd inside its own clone of dapr/dapr, so the | |
| # toolchain has to satisfy that repo's `go` directive, not this one's. A | |
| # static pin is not enough: setup-go exports GOTOOLCHAIN=local, which stops | |
| # Go from auto-downloading a newer toolchain when dapr bumps the directive | |
| # (observed: go.mod required 1.26.6 while a '1.26' pin resolved to 1.26.5). | |
| # Read the exact requirement from the ref being built instead. | |
| # The file must be named exactly `go.mod`: setup-go's parseGoVersionFile | |
| # switches on `path.basename(...) === 'go.mod'` and otherwise treats the | |
| # whole file as a literal version string. | |
| - name: Fetch go.mod of the dapr ref under test | |
| env: | |
| DAPR_REF: ${{ github.event.inputs.daprdapr_commit || 'master' }} | |
| run: | | |
| mkdir -p "$RUNNER_TEMP/dapr-mod" | |
| curl -fsSL "https://raw.githubusercontent.com/dapr/dapr/$DAPR_REF/go.mod" \ | |
| -o "$RUNNER_TEMP/dapr-mod/go.mod" | |
| - name: Set up Go | |
| uses: actions/setup-go@v7 | |
| with: | |
| go-version-file: ${{ runner.temp }}/dapr-mod/go.mod | |
| # The Go build happens in the composite action's own clone; this repo | |
| # has no go.sum for setup-go's cache to key on. | |
| cache: false | |
| - name: Set up Dapr CLI | |
| uses: dapr/.github/.github/actions/setup-dapr-cli@main | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| # `dapr init` lays down the latest release, then the action overwrites | |
| # ~/.dapr/bin/daprd with a build of `commit`. Placement and scheduler stay | |
| # on release images, which is fine here: the whole server side of this | |
| # feature lives in daprd's embedded durabletask-go grpcExecutor. | |
| - name: Set up Dapr runtime from master | |
| uses: dapr/.github/.github/actions/setup-dapr-runtime@main | |
| with: | |
| commit: ${{ github.event.inputs.daprdapr_commit || 'master' }} | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Run stateful-history integration tests | |
| run: | | |
| uv run pytest tests/integration/ -m dapr_head -v | |
| # These drive a bare TaskHubGrpcWorker rather than the DaprTestEnvironment | |
| # fixture, so they need a sidecar of their own and take its address from | |
| # DAPR_GRPC_ENDPOINT. | |
| - name: Run vendored durabletask e2e tests | |
| env: | |
| DAPR_GRPC_ENDPOINT: 127.0.0.1:${{ env.E2E_GRPC_PORT }} | |
| run: | | |
| nohup dapr run --app-id dt-e2e \ | |
| --dapr-grpc-port "$E2E_GRPC_PORT" \ | |
| --dapr-http-port "$E2E_HTTP_PORT" \ | |
| --dapr-internal-grpc-port 13702 \ | |
| --metrics-port 13703 > "$RUNNER_TEMP/dt-e2e-sidecar.log" 2>&1 & | |
| timeout 90 bash -c \ | |
| 'until curl -fsS "http://127.0.0.1:$E2E_HTTP_PORT/v1.0/healthz/outbound" > /dev/null; do sleep 1; done' \ | |
| || { echo 'sidecar failed to become healthy'; cat "$RUNNER_TEMP/dt-e2e-sidecar.log"; exit 1; } | |
| uv run pytest tests/ext/workflow/durabletask -m e2e -v | |
| # A workflow test failing usually says more about the sidecar than the SDK, | |
| # and the log is otherwise lost with the runner. | |
| - name: Dump sidecar log on failure | |
| if: failure() | |
| run: cat "$RUNNER_TEMP/dt-e2e-sidecar.log" || true | |
| # Single stable check name to mark as required in branch protection, so the | |
| # required-checks list doesn't go stale when the Python version matrix | |
| # changes. Skipped required checks count as passing, hence `if: always()` | |
| # plus an explicit result check instead of relying on `needs` alone. | |
| validate-complete: | |
| needs: [validate, validate-dapr-head] | |
| if: always() | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Fail unless the whole validate matrix succeeded | |
| run: | | |
| if [ "${{ needs.validate.result }}" != "success" ]; then | |
| echo "validate matrix result: ${{ needs.validate.result }}" | |
| exit 1 | |
| fi | |
| - name: Fail unless the dapr-head job succeeded | |
| run: | | |
| if [ "${{ needs.validate-dapr-head.result }}" != "success" ]; then | |
| echo "validate-dapr-head result: ${{ needs.validate-dapr-head.result }}" | |
| exit 1 | |
| fi |