Repository navigation
agents: prepare the 0.6.5 change log #3856
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: Check Gate CI | |
| on: | |
| pull_request: | |
| # Adding or removing the ci:fast-merge label changes the required workflows. | |
| # edited re-runs the skills checks that read the pull request description. | |
| types: [opened, synchronize, reopened, edited, labeled, unlabeled] | |
| permissions: | |
| actions: read | |
| checks: read | |
| contents: read | |
| pull-requests: read | |
| # Only a new commit cancels a gate run; a cancelled run of the same commit fails the required check. | |
| concurrency: | |
| group: check-gate-${{ github.workflow }}-${{ github.ref }}-${{ github.event.action == 'synchronize' && 'commits' || github.run_id }} | |
| cancel-in-progress: ${{ github.event.action == 'synchronize' }} | |
| jobs: | |
| check-gate: | |
| name: Check Gate CI | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 90 | |
| steps: | |
| # Depth 2 includes the merge commit's first parent, the base the change-log check diffs against. | |
| - uses: actions/checkout@v7 | |
| with: | |
| fetch-depth: 2 | |
| - name: Validate CI runner policy | |
| run: make ci-runner-check | |
| # A filter that differs from its workflow's paths waits forever or never enforces a check. | |
| - name: Check that path filters match their workflows | |
| run: | | |
| python3 .github/scripts/workflow_paths_test.py | |
| python3 .github/scripts/workflow_paths.py check-paths | |
| - name: Reject agent attribution | |
| if: github.event_name == 'pull_request' | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| PR_NUMBER: ${{ github.event.pull_request.number }} | |
| PR_TITLE: ${{ github.event.pull_request.title }} | |
| PR_BODY: ${{ github.event.pull_request.body }} | |
| run: | | |
| { | |
| printf '%s\n%s\n' "$PR_TITLE" "$PR_BODY" | |
| gh api --paginate "repos/$GITHUB_REPOSITORY/pulls/$PR_NUMBER/commits" --jq '.[].commit.message' | |
| } | script/check-commit-attribution | |
| - uses: dorny/paths-filter@v3 | |
| id: filter | |
| if: github.event_name == 'pull_request' | |
| with: | |
| filters: | | |
| agents: | |
| - 'agents/**' | |
| - '.github/workflows/agents-ci.yml' | |
| - '.github/workflows/agents-python-publish.yml' | |
| - '.github/workflows/agents-typescript-publish.yml' | |
| agents_terminal_ui: | |
| - 'agents/cli/**' | |
| - 'agents/conformance/terminal_ui/**' | |
| - 'agents/python/core/**' | |
| - 'agents/typescript/core/**' | |
| - 'cli/cmd/**' | |
| - 'cli/internal/agentsterminal/**' | |
| - '.github/workflows/agents-terminal-ui-e2e-ci.yml' | |
| sdk_go: | |
| - 'sdk-go/**' | |
| - 'blob-cache-go/**' | |
| - 'protos/**' | |
| - 'server-zd/**' | |
| - 'sdk-rust/Cargo.toml' | |
| - 'sdk-rust/crates/dex-blob-cache/**' | |
| - 's3local/**' | |
| # The suites build dexcli and run dexcli dev; the agents terminal UI is not part of it. | |
| - 'cli/cmd/**' | |
| - 'cli/internal/command/**' | |
| - 'cli/internal/dev/**' | |
| - 'cli/internal/flowviz/**' | |
| - 'cli/internal/pointervalue/**' | |
| - 'cli/internal/update/**' | |
| - 'cli/schema/**' | |
| - 'cli/go.mod' | |
| - 'cli/go.sum' | |
| - 'cli/Makefile' | |
| - 'cli/SERVER_ZD_RELEASE' | |
| - 'web/**' | |
| - 'go.work' | |
| - 'go.work.sum' | |
| - 'codecov.yml' | |
| - '.github/workflows/sdk-go-ci.yml' | |
| sdk_rust: | |
| - 'sdk-rust/**' | |
| # The suites build dexcli and run dexcli dev; the agents terminal UI is not part of it. | |
| - 'cli/cmd/**' | |
| - 'cli/internal/command/**' | |
| - 'cli/internal/dev/**' | |
| - 'cli/internal/flowviz/**' | |
| - 'cli/internal/pointervalue/**' | |
| - 'cli/internal/update/**' | |
| - 'cli/schema/**' | |
| - 'cli/go.mod' | |
| - 'cli/go.sum' | |
| - 'cli/Makefile' | |
| - 'cli/SERVER_ZD_RELEASE' | |
| - 'server-zd/**' | |
| - 's3local/**' | |
| - 'protos/**' | |
| # The suites run the Web server inside dexcli dev but never load its pages. | |
| - 'web/**/*.go' | |
| - 'web/go.mod' | |
| - 'web/go.sum' | |
| - 'codecov.yml' | |
| - '.github/workflows/sdk-rust-ci.yml' | |
| sdk_java: | |
| - 'sdk-java/**' | |
| - 'sdk-rust/Cargo.lock' | |
| - 'sdk-rust/Cargo.toml' | |
| - 'sdk-rust/crates/dex-blob-cache/**' | |
| - 'sdk-rust/crates/dex-blob-cache-jni/**' | |
| # The suites build dexcli and run dexcli dev; the agents terminal UI is not part of it. | |
| - 'cli/cmd/**' | |
| - 'cli/internal/command/**' | |
| - 'cli/internal/dev/**' | |
| - 'cli/internal/flowviz/**' | |
| - 'cli/internal/pointervalue/**' | |
| - 'cli/internal/update/**' | |
| - 'cli/schema/**' | |
| - 'cli/go.mod' | |
| - 'cli/go.sum' | |
| - 'cli/Makefile' | |
| - 'cli/SERVER_ZD_RELEASE' | |
| # The suites run the Web server inside dexcli dev but never load its pages. | |
| - 'web/**/*.go' | |
| - 'web/go.mod' | |
| - 'web/go.sum' | |
| - 'server-zd/**' | |
| - 's3local/**' | |
| - 'protos/**' | |
| - 'codecov.yml' | |
| - '.github/workflows/sdk-java-ci.yml' | |
| - '.github/workflows/sdk-java-publish.yml' | |
| sdk_python: | |
| - 'sdk-python/**' | |
| - 'sdk-rust/Cargo.lock' | |
| - 'sdk-rust/Cargo.toml' | |
| - 'sdk-rust/crates/dex-blob-cache/**' | |
| - 'sdk-rust/crates/dex-blob-cache-python/**' | |
| # The suites build dexcli and run dexcli dev; the agents terminal UI is not part of it. | |
| - 'cli/cmd/**' | |
| - 'cli/internal/command/**' | |
| - 'cli/internal/dev/**' | |
| - 'cli/internal/flowviz/**' | |
| - 'cli/internal/pointervalue/**' | |
| - 'cli/internal/update/**' | |
| - 'cli/schema/**' | |
| - 'cli/go.mod' | |
| - 'cli/go.sum' | |
| - 'cli/Makefile' | |
| - 'cli/SERVER_ZD_RELEASE' | |
| - 'server-zd/**' | |
| - 's3local/**' | |
| # The suites run the Web server inside dexcli dev but never load its pages. | |
| - 'web/**/*.go' | |
| - 'web/go.mod' | |
| - 'web/go.sum' | |
| - 'protos/**' | |
| - 'codecov.yml' | |
| - '.github/workflows/sdk-python-ci.yml' | |
| sdk_typescript: | |
| - 'sdk-typescript/**' | |
| - 'examples/typescript/decorator-free-rpc/**' | |
| - 'sdk-rust/Cargo.lock' | |
| - 'sdk-rust/Cargo.toml' | |
| - 'sdk-rust/crates/dex-blob-cache/**' | |
| - 'sdk-rust/crates/dex-blob-cache-node/**' | |
| # The suites build dexcli and run dexcli dev; the agents terminal UI is not part of it. | |
| - 'cli/cmd/**' | |
| - 'cli/internal/command/**' | |
| - 'cli/internal/dev/**' | |
| - 'cli/internal/flowviz/**' | |
| - 'cli/internal/pointervalue/**' | |
| - 'cli/internal/update/**' | |
| - 'cli/schema/**' | |
| - 'cli/go.mod' | |
| - 'cli/go.sum' | |
| - 'cli/Makefile' | |
| - 'cli/SERVER_ZD_RELEASE' | |
| - 'server-zd/**' | |
| - 's3local/**' | |
| - 'protos/**' | |
| # The suites run the Web server inside dexcli dev but never load its pages. | |
| - 'web/**/*.go' | |
| - 'web/go.mod' | |
| - 'web/go.sum' | |
| - '.github/workflows/sdk-typescript-ci.yml' | |
| - '.github/workflows/sdk-typescript-publish.yml' | |
| rust_rules: | |
| - '**/*.rs' | |
| - '**/Cargo.toml' | |
| - '**/clippy.toml' | |
| - 'script/check-rust-rules.py' | |
| - 'script/check_rust_rules_test.py' | |
| - 'script/rust-crate-layers.json' | |
| - 'script/rust-rules-baseline.json' | |
| - 'Makefile' | |
| - '.github/workflows/rust-rules-ci.yml' | |
| web: | |
| - 'web/**' | |
| - 'packages/flow-definition-renderer/**' | |
| - 'docs/src/data/flow-definitions/**' | |
| - 'agents/conformance/session_graph.json' | |
| - 'protos/**' | |
| - 'sdk-go/**' | |
| - 'script/release/*embedded_web_module.py' | |
| - '.github/workflows/web-ci.yml' | |
| - '.github/workflows/web-embedded-module-release.yml' | |
| examples_go: | |
| - 'examples/go/**' | |
| - '.github/workflows/examples-go-ci.yml' | |
| - 'examples/entity-store/**' | |
| examples_java: | |
| - 'examples/java/**' | |
| - '.github/workflows/examples-java-ci.yml' | |
| - 'examples/entity-store/**' | |
| examples_python: | |
| - 'examples/python/**' | |
| - '.github/workflows/examples-python-ci.yml' | |
| - 'examples/entity-store/**' | |
| examples_rust: | |
| - 'examples/rust/**' | |
| - '.github/workflows/examples-rust-ci.yml' | |
| - 'examples/entity-store/**' | |
| s3local: | |
| - 's3local/**' | |
| - '.github/workflows/s3local-ci.yml' | |
| server_zd: | |
| - 'server-zd/**' | |
| - 's3local/**' | |
| - 'sdk-rust/Cargo.toml' | |
| - 'sdk-rust/crates/dex-blob-cache/**' | |
| - 'protos/**' | |
| - '.github/workflows/server-zd-ci.yml' | |
| server_zd_integ: | |
| - 'sdk-go/**' | |
| - 'server-zd/**' | |
| - 'sdk-rust/Cargo.toml' | |
| - 'sdk-rust/crates/dex-blob-cache/**' | |
| - 'protos/**' | |
| - '.github/workflows/server-zd-integ-ci.yml' | |
| server_zd_simulation_runner: | |
| - 'script/server-zd-simulation-run.py' | |
| - 'script/test_server_zd_simulation_run.py' | |
| - '.github/workflows/server-zd-simulation-nightly.yml' | |
| - '.github/workflows/server-zd-simulation-runner-ci.yml' | |
| - 'Makefile' | |
| server_zd_image: | |
| - 'server-zd/LICENSE.md' | |
| - 'server-zd/LEGACY_NOTICES.md' | |
| - 'server-zd/LICENSES/**' | |
| - 'server-zd/Dockerfile' | |
| - '.dockerignore' | |
| - '.github/workflows/server-zd-image-release.yml' | |
| - '.github/workflows/server-zd-image-main.yml' | |
| server_zd_binary: | |
| - 'server-zd/LICENSE.md' | |
| - 'server-zd/LEGACY_NOTICES.md' | |
| - 'server-zd/LICENSES/**' | |
| - '.github/workflows/server-zd-binary-release.yml' | |
| server_zd_minio: | |
| - '.github/workflows/server-zd-minio-nightly.yml' | |
| examples_typescript: | |
| - 'examples/typescript/**' | |
| - '.github/workflows/examples-typescript-ci.yml' | |
| - 'examples/entity-store/**' | |
| generated_code: | |
| - 'protos/**' | |
| - 'sdk-go/gen/dexpb/**' | |
| - 'sdk-java/src/main/java/io/superdurable/gen/**' | |
| - 'sdk-python/dex/dexpb/**' | |
| - 'sdk-python/pyproject.toml' | |
| - 'sdk-python/uv.lock' | |
| - 'sdk-typescript/src/gen/**' | |
| - 'sdk-typescript/scripts/generate-proto.mjs' | |
| - 'sdk-typescript/package.json' | |
| - 'sdk-typescript/package-lock.json' | |
| - 'Makefile' | |
| - '.github/workflows/generated-code-ci.yml' | |
| release_tooling: | |
| - 'script/release/**' | |
| - 'script/regenerate_derived.py' | |
| - 'script/regenerate_derived_integ_test.py' | |
| - 'Makefile' | |
| - 'skills/script/check-package.py' | |
| - 'docs/reference/*/changelog.mdx' | |
| - 'agents/CHANGELOG.md' | |
| - '.github/workflows/release-changed-components.yml' | |
| - '.github/workflows/cli-release.yml' | |
| - '.github/workflows/docker-image-web-release.yml' | |
| - '.github/workflows/release-tooling-ci.yml' | |
| - 'CONTRIBUTING.md' | |
| skills: | |
| - 'skills/**' | |
| - 'docs/content/concepts/**' | |
| - 'docs/content/components/**' | |
| - 'docs/content/design-patterns/**' | |
| - '.github/workflows/skills-ci.yml' | |
| copyright: | |
| - 'agents/**' | |
| - 'cli/**' | |
| - 'sdk-go/**' | |
| - 'blob-cache-go/**' | |
| - 'script/release/**' | |
| - 'sdk-java/**' | |
| - 'sdk-python/**' | |
| - 'sdk-rust/**' | |
| - 's3local/**' | |
| - 'server-zd/**' | |
| - 'web/**' | |
| - 'examples/go/**' | |
| - 'examples/java/**' | |
| - 'examples/python/**' | |
| - 'protos/**' | |
| - 'script/licenseheaders/**' | |
| - 'LICENSE' | |
| - 'LEGACY_NOTICES.md' | |
| - 'LICENSING.md' | |
| - 'CLA.md' | |
| - 'CLA-INDIVIDUAL.md' | |
| - 'CLA-CORPORATE.md' | |
| - 'Makefile' | |
| - '.github/workflows/copyright-ci.yml' | |
| # Releases assemble changelog.d fragments; this rejects hand edits to release files. | |
| - name: Check change-log fragments and release files against the current description | |
| if: github.event_name == 'pull_request' | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| PR_NUMBER: ${{ github.event.pull_request.number }} | |
| run: | | |
| set -euo pipefail | |
| pull_request_file="$RUNNER_TEMP/changelog-pull-request.json" | |
| body_file="$RUNNER_TEMP/changelog-pull-request-body.txt" | |
| gh api "repos/$GITHUB_REPOSITORY/pulls/$PR_NUMBER" > "$pull_request_file" | |
| jq -r '.body // ""' "$pull_request_file" > "$body_file" | |
| labels="$(jq -r '[.labels[].name] | join(",")' "$pull_request_file")" | |
| python3 script/release/changelog_fragments.py check-pr --base-ref HEAD^1 \ | |
| --pr-body-file "$body_file" --pr-number "$PR_NUMBER" --labels "$labels" | |
| - uses: actions/setup-python@v5 | |
| if: github.event_name == 'pull_request' && steps.filter.outputs.skills == 'true' | |
| with: | |
| python-version: '3.13' | |
| # The gate reads the current description itself, so no stale Skills CI run can approve it. | |
| - name: Check doc-map pairing against the current description | |
| if: github.event_name == 'pull_request' && steps.filter.outputs.skills == 'true' | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| PR_NUMBER: ${{ github.event.pull_request.number }} | |
| run: | | |
| set -euo pipefail | |
| pull_request_file="$RUNNER_TEMP/pull-request.json" | |
| body_file="$RUNNER_TEMP/pull-request-body.txt" | |
| gh api "repos/$GITHUB_REPOSITORY/pulls/$PR_NUMBER" > "$pull_request_file" | |
| jq -r '.body // ""' "$pull_request_file" > "$body_file" | |
| base_sha="$(jq -r '.base.sha' "$pull_request_file")" | |
| if [[ "$(git rev-parse --is-shallow-repository)" == "true" ]]; then | |
| git fetch --no-tags --unshallow origin | |
| fi | |
| git fetch --no-tags origin "$base_sha" | |
| cd skills | |
| python3 script/check-doc-map.py --base-ref "$base_sha" --pr-body-file "$body_file" | |
| - name: Wait for required workflows | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| REPO: ${{ github.repository }} | |
| HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }} | |
| EVENT_NAME: ${{ github.event_name }} | |
| FILTER_AGENTS: ${{ steps.filter.outputs.agents }} | |
| FILTER_AGENTS_TERMINAL_UI: ${{ steps.filter.outputs.agents_terminal_ui }} | |
| FILTER_SDK_GO: ${{ steps.filter.outputs.sdk_go }} | |
| FILTER_SDK_RUST: ${{ steps.filter.outputs.sdk_rust }} | |
| FILTER_SDK_JAVA: ${{ steps.filter.outputs.sdk_java }} | |
| FILTER_SDK_PYTHON: ${{ steps.filter.outputs.sdk_python }} | |
| FILTER_SDK_TYPESCRIPT: ${{ steps.filter.outputs.sdk_typescript }} | |
| FILTER_RUST_RULES: ${{ steps.filter.outputs.rust_rules }} | |
| FILTER_WEB: ${{ steps.filter.outputs.web }} | |
| FILTER_EXAMPLES_GO: ${{ steps.filter.outputs.examples_go }} | |
| FILTER_EXAMPLES_JAVA: ${{ steps.filter.outputs.examples_java }} | |
| FILTER_EXAMPLES_PYTHON: ${{ steps.filter.outputs.examples_python }} | |
| FILTER_EXAMPLES_RUST: ${{ steps.filter.outputs.examples_rust }} | |
| FILTER_S3LOCAL: ${{ steps.filter.outputs.s3local }} | |
| FILTER_SERVER_ZD: ${{ steps.filter.outputs.server_zd }} | |
| FILTER_SERVER_ZD_INTEG: ${{ steps.filter.outputs.server_zd_integ }} | |
| FILTER_SERVER_ZD_SIMULATION_RUNNER: ${{ steps.filter.outputs.server_zd_simulation_runner }} | |
| FILTER_SERVER_ZD_IMAGE: ${{ steps.filter.outputs.server_zd_image }} | |
| FILTER_SERVER_ZD_BINARY: ${{ steps.filter.outputs.server_zd_binary }} | |
| FILTER_SERVER_ZD_MINIO: ${{ steps.filter.outputs.server_zd_minio }} | |
| FILTER_EXAMPLES_TYPESCRIPT: ${{ steps.filter.outputs.examples_typescript }} | |
| FILTER_GENERATED_CODE: ${{ steps.filter.outputs.generated_code }} | |
| FILTER_RELEASE_TOOLING: ${{ steps.filter.outputs.release_tooling }} | |
| FILTER_SKILLS: ${{ steps.filter.outputs.skills }} | |
| FILTER_COPYRIGHT: ${{ steps.filter.outputs.copyright }} | |
| IS_FAST_MERGE: ${{ contains(github.event.pull_request.labels.*.name, 'ci:fast-merge') }} | |
| run: | | |
| set -euo pipefail | |
| # Main CI (all) checks main; this gate checks only pull requests. | |
| expected=("CLA") | |
| [[ "$FILTER_AGENTS" == "true" ]] && expected+=("Agents CI") | |
| [[ "$FILTER_AGENTS_TERMINAL_UI" == "true" ]] && expected+=("Agents terminal UI e2e CI") | |
| [[ "$FILTER_SDK_GO" == "true" ]] && expected+=("Go SDK CI") | |
| [[ "$FILTER_SDK_RUST" == "true" ]] && expected+=("Rust SDK CI") | |
| [[ "$FILTER_SDK_JAVA" == "true" ]] && expected+=("Java SDK CI") | |
| [[ "$FILTER_SDK_PYTHON" == "true" ]] && expected+=("Python SDK CI") | |
| [[ "$FILTER_SDK_TYPESCRIPT" == "true" ]] && expected+=("TypeScript SDK CI") | |
| [[ "$FILTER_RUST_RULES" == "true" ]] && expected+=("Rust Rules CI") | |
| [[ "$FILTER_WEB" == "true" ]] && expected+=("Web CI") | |
| [[ "$FILTER_EXAMPLES_GO" == "true" ]] && expected+=("Go examples CI") | |
| [[ "$FILTER_EXAMPLES_JAVA" == "true" ]] && expected+=("Java examples CI") | |
| [[ "$FILTER_EXAMPLES_PYTHON" == "true" ]] && expected+=("Python examples CI") | |
| [[ "$FILTER_EXAMPLES_RUST" == "true" ]] && expected+=("Rust examples CI") | |
| [[ "$FILTER_S3LOCAL" == "true" ]] && expected+=("S3local CI") | |
| [[ "$FILTER_SERVER_ZD" == "true" ]] && expected+=("Server ZD CI") | |
| [[ "$FILTER_SERVER_ZD_INTEG" == "true" ]] && expected+=("Server Integration against server-zd") | |
| [[ "$FILTER_SERVER_ZD_SIMULATION_RUNNER" == "true" ]] && expected+=("Server ZD Simulation Runner CI") | |
| [[ "$FILTER_SERVER_ZD_IMAGE" == "true" ]] && expected+=("Server ZD image release") | |
| [[ "$FILTER_SERVER_ZD_BINARY" == "true" ]] && expected+=("Server ZD binary release") | |
| [[ "$FILTER_SERVER_ZD_MINIO" == "true" ]] && expected+=("Server ZD MinIO Nightly") | |
| [[ "$FILTER_EXAMPLES_TYPESCRIPT" == "true" ]] && expected+=("TypeScript examples CI") | |
| [[ "$FILTER_GENERATED_CODE" == "true" ]] && expected+=("Generated Code CI") | |
| [[ "$FILTER_RELEASE_TOOLING" == "true" ]] && expected+=("Release Tooling CI") | |
| [[ "$FILTER_SKILLS" == "true" ]] && expected+=("Skills CI") | |
| [[ "$FILTER_COPYRIGHT" == "true" ]] && expected+=("Copyright") | |
| # ci:fast-merge stops the SDK, CLI, Web, examples, and agents | |
| # suites from blocking the merge. They still run on the pull request and in Main CI (all). | |
| # The SDK suites on server-zd are non-blocking too; Server ZD CI still blocks. | |
| if [[ "$EVENT_NAME" == "pull_request" && "$IS_FAST_MERGE" == "true" ]]; then | |
| non_blocking=( | |
| "Agents CI" | |
| "Agents terminal UI e2e CI" | |
| "Blob Cache Go CI" | |
| "Dex CLI CI" | |
| "Go SDK CI" | |
| "Java SDK CI" | |
| "Python SDK CI" | |
| "Rust SDK CI" | |
| "TypeScript SDK CI" | |
| "Web CI" | |
| "Go examples CI" | |
| "Java examples CI" | |
| "Python examples CI" | |
| "Rust examples CI" | |
| "TypeScript examples CI" | |
| ) | |
| blocking=() | |
| for name in "${expected[@]}"; do | |
| is_non_blocking=false | |
| for skipped in "${non_blocking[@]}"; do | |
| [[ "$name" == "$skipped" ]] && is_non_blocking=true | |
| done | |
| if [[ "$is_non_blocking" == "true" ]]; then | |
| echo "NOT WAITING $name (ci:fast-merge)" | |
| else | |
| blocking+=("$name") | |
| fi | |
| done | |
| expected=("${blocking[@]}") | |
| fi | |
| if [[ ${#expected[@]} -eq 0 ]]; then | |
| echo "No path-matched CI workflows; Check Gate CI succeeded." | |
| exit 0 | |
| fi | |
| echo "Waiting for workflows: ${expected[*]}" | |
| echo "head_sha=$HEAD_SHA" | |
| deadline=$((SECONDS + 85 * 60)) | |
| while (( SECONDS < deadline )); do | |
| runs_json="$(gh api \ | |
| "repos/${REPO}/actions/runs?head_sha=${HEAD_SHA}&per_page=100")" | |
| failed=0 | |
| pending=0 | |
| for name in "${expected[@]}"; do | |
| row="$(jq -c --arg name "$name" ' | |
| [.workflow_runs[] | select(.name == $name)] | |
| | sort_by(.id) | |
| | reverse | |
| | if length == 0 then empty | |
| else .[0] | {status, conclusion, html_url, id} | |
| end | |
| ' <<<"$runs_json")" | |
| if [[ -z "$row" ]]; then | |
| echo "PENDING $name (not started)" | |
| pending=1 | |
| continue | |
| fi | |
| status="$(jq -r '.status' <<<"$row")" | |
| conclusion="$(jq -r '.conclusion // empty' <<<"$row")" | |
| url="$(jq -r '.html_url' <<<"$row")" | |
| if [[ "$status" != "completed" ]]; then | |
| echo "PENDING $name ($status) $url" | |
| pending=1 | |
| continue | |
| fi | |
| if [[ "$conclusion" == "success" ]]; then | |
| echo "OK $name $url" | |
| continue | |
| fi | |
| echo "FAILED $name ($conclusion) $url" | |
| failed=1 | |
| done | |
| if (( failed )); then | |
| echo "One or more required workflows failed." | |
| exit 1 | |
| fi | |
| if (( pending == 0 )); then | |
| echo "All required workflows succeeded." | |
| exit 0 | |
| fi | |
| sleep 30 | |
| done | |
| echo "Timed out waiting for required workflows." | |
| exit 1 |