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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
169 changes: 151 additions & 18 deletions .github/workflows/cloud-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ concurrency:
cancel-in-progress: false

jobs:
cloud-integration:
name: Cloud integration tests
plan:
name: Plan Cloud integration tests
if: >-
github.event_name == 'schedule' ||
github.event_name == 'workflow_dispatch' ||
Expand All @@ -40,6 +40,140 @@ jobs:
github.event.pull_request.head.repo.full_name == github.repository &&
github.event.pull_request.user.login != 'dependabot[bot]')
runs-on: ubuntu-latest
outputs:
service: ${{ steps.selection.outputs.service }}
postgres: ${{ steps.selection.outputs.postgres }}
organization: ${{ steps.selection.outputs.organization }}
clickpipes: ${{ steps.selection.outputs.clickpipes }}
test_sha: ${{ steps.selection.outputs.test_sha }}
requested_scope: ${{ steps.selection.outputs.requested_scope }}
selected_suites: ${{ steps.selection.outputs.selected_suites }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
fetch-depth: 0
persist-credentials: false

- name: Select suites and log plan
id: selection
env:
EVENT_NAME: ${{ github.event_name }}
EVENT_REF: ${{ github.ref }}
EVENT_SHA: ${{ github.sha }}
PR_BASE_SHA: ${{ github.event.pull_request.base.sha || 'n/a' }}
PR_HEAD_SHA: ${{ github.event.pull_request.head.sha || 'n/a' }}
DISPATCH_SCOPE: ${{ inputs.scope || '' }}
run: |
set -u
all_suites="service,postgres,organization,clickpipes"
test_sha="$EVENT_SHA"

case "$EVENT_NAME" in
pull_request)
test_sha="$PR_HEAD_SHA"
requested_scope="affected (PR merge-base diff)"
if git diff --quiet "$PR_BASE_SHA...$PR_HEAD_SHA" -- \
.github/workflows/cloud-integration.yml \
scripts/classify-cloud-integration.py \
scripts/tests/test_classify_cloud_integration.py; then
if selected="$(python3 scripts/classify-cloud-integration.py "$PR_BASE_SHA" "$PR_HEAD_SHA")"; then
:
else
echo "::warning::Classifier command failed; selecting all suites"
selected="$all_suites"
fi
else
guard_status=$?
if [[ "$guard_status" -eq 1 ]]; then
echo "::warning::Cloud integration selection logic changed; selecting all suites"
else
echo "::warning::Selection guard diff failed; selecting all suites"
fi
selected="$all_suites"
fi
Comment thread
cursor[bot] marked this conversation as resolved.
;;
workflow_dispatch)
requested_scope="$DISPATCH_SCOPE"
if [[ "$DISPATCH_SCOPE" == "all" ]]; then
selected="$all_suites"
else
selected="$DISPATCH_SCOPE"
fi
;;
schedule)
requested_scope="all (schedule)"
selected="$all_suites"
;;
*)
echo "::warning::Unexpected event; selecting all suites"
requested_scope="all (fallback)"
selected="$all_suites"
;;
esac

service=false
postgres=false
organization=false
clickpipes=false
[[ ",$selected," == *",service,"* ]] && service=true
[[ ",$selected," == *",postgres,"* ]] && postgres=true
[[ ",$selected," == *",organization,"* ]] && organization=true
[[ ",$selected," == *",clickpipes,"* ]] && clickpipes=true

canonical=""
[[ "$service" == true ]] && canonical="service"
[[ "$postgres" == true ]] && canonical="${canonical:+$canonical,}postgres"
[[ "$organization" == true ]] && canonical="${canonical:+$canonical,}organization"
[[ "$clickpipes" == true ]] && canonical="${canonical:+$canonical,}clickpipes"
canonical="${canonical:-none}"
if [[ "$selected" != "$canonical" ]]; then
echo "::warning::Classifier emitted invalid suite output; selecting all suites"
selected="$all_suites"
service=true
postgres=true
organization=true
clickpipes=true
fi

checked_out_sha="$(git rev-parse HEAD)"
echo "Event: $EVENT_NAME"
echo "Event SHA: $EVENT_SHA"
echo "PR base SHA: $PR_BASE_SHA"
echo "PR head SHA: $PR_HEAD_SHA"
echo "Selected SHA: $test_sha"
echo "Checked-out SHA: $checked_out_sha"
echo "Event ref: $EVENT_REF"
echo "Requested scope: $requested_scope"
echo "Selected suites: $selected"

{
echo "service=$service"
echo "postgres=$postgres"
echo "organization=$organization"
echo "clickpipes=$clickpipes"
echo "test_sha=$test_sha"
echo "requested_scope=$requested_scope"
echo "selected_suites=$selected"
} >> "$GITHUB_OUTPUT"

if [[ "$checked_out_sha" != "$test_sha" ]]; then
echo "::error::Checked-out SHA does not match selected test SHA"
exit 1
fi

cloud-integration:
name: Cloud integration tests
needs: plan
if: >-
${{
needs.plan.result == 'success' &&
(needs.plan.outputs.service == 'true' ||
needs.plan.outputs.postgres == 'true' ||
needs.plan.outputs.organization == 'true' ||
needs.plan.outputs.clickpipes == 'true')
}}
runs-on: ubuntu-latest
environment: cloud-integration
env:
CLICKHOUSE_CLOUD_API_KEY: ${{ secrets.CLICKHOUSE_CLOUD_API_KEY }}
Expand All @@ -61,25 +195,29 @@ jobs:
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
ref: ${{ needs.plan.outputs.test_sha }}
persist-credentials: false

- name: Log revisions
env:
EVENT_NAME: ${{ github.event_name }}
EVENT_SHA: ${{ github.sha }}
PR_BASE_SHA: ${{ github.event.pull_request.base.sha || 'n/a' }}
PR_HEAD_SHA: ${{ github.event.pull_request.head.sha || 'n/a' }}
SELECTED_REF: ${{ github.ref }}
SELECTED_SHA: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
REQUESTED_SCOPE: ${{ github.event_name == 'workflow_dispatch' && inputs.scope || 'all (non-dispatch)' }}
EVENT_REF: ${{ github.ref }}
SELECTED_SHA: ${{ needs.plan.outputs.test_sha }}
REQUESTED_SCOPE: ${{ needs.plan.outputs.requested_scope }}
SELECTED_SUITES: ${{ needs.plan.outputs.selected_suites }}
run: |
echo "Event: $EVENT_NAME"
echo "Event SHA: $EVENT_SHA"
echo "PR base SHA: $PR_BASE_SHA"
echo "PR head SHA: $PR_HEAD_SHA"
echo "Selected ref: $SELECTED_REF"
echo "Selected SHA: $SELECTED_SHA"
echo "Requested scope: $REQUESTED_SCOPE"
echo "Checked-out SHA: $(git rev-parse HEAD)"
echo "Event ref: $EVENT_REF"
echo "Requested scope: $REQUESTED_SCOPE"
echo "Selected suites: $SELECTED_SUITES"

- name: Resolve test run label
run: |
Expand All @@ -101,29 +239,25 @@ jobs:
- name: Run cloud integration suite
if: >-
${{ !cancelled() &&
(github.event_name != 'workflow_dispatch' ||
inputs.scope == 'all' || inputs.scope == 'service') }}
needs.plan.outputs.service == 'true' }}
run: cargo test -p clickhouse-cloud-api --test integration_test -- --ignored --nocapture

- name: Run cloud Postgres integration suite
if: >-
${{ !cancelled() &&
(github.event_name != 'workflow_dispatch' ||
inputs.scope == 'all' || inputs.scope == 'postgres') }}
needs.plan.outputs.postgres == 'true' }}
run: cargo test -p clickhouse-cloud-api --test integration_postgres_test -- --ignored --nocapture

- name: Run cloud Org integration suite
if: >-
${{ !cancelled() &&
(github.event_name != 'workflow_dispatch' ||
inputs.scope == 'all' || inputs.scope == 'organization') }}
needs.plan.outputs.organization == 'true' }}
run: cargo test -p clickhouse-cloud-api --test integration_org_test -- --ignored --nocapture

- name: Run ClickPipe Postgres CDC integration test
if: >-
${{ !cancelled() &&
(github.event_name != 'workflow_dispatch' ||
inputs.scope == 'all' || inputs.scope == 'clickpipes') }}
needs.plan.outputs.clickpipes == 'true' }}
run: cargo test -p clickhouse-cloud-api --test clickpipe_postgres_cdc_test -- --ignored --nocapture

# ClickPipe create smoke tests run against a long-lived ClickHouse Cloud
Expand All @@ -134,7 +268,6 @@ jobs:
- name: Run ClickPipe create smoke suite
if: >-
${{ !cancelled() &&
(github.event_name != 'workflow_dispatch' ||
inputs.scope == 'all' || inputs.scope == 'clickpipes') &&
needs.plan.outputs.clickpipes == 'true' &&
vars.CLICKHOUSE_CLOUD_TEST_CLICKPIPE_SERVICE_ID != '' }}
run: cargo test -p clickhouse-cloud-api --test clickpipe_smoke_test -- --ignored --nocapture
1 change: 1 addition & 0 deletions .github/workflows/test-cloud-api.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ on:
- "crates/clickhouse-cloud-api/**"
- "crates/clickhouse-openapi-analyzer/**"
- "scripts/check-openapi-drift.py"
- "scripts/classify-cloud-integration.py"
- "scripts/tests/**"
- "Cargo.toml"
- "Cargo.lock"
Expand Down
2 changes: 1 addition & 1 deletion crates/clickhouse-cloud-api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ cargo test --test clickpipe_smoke_test -- --ignored --nocapture # creat

All require `CLICKHOUSE_CLOUD_API_KEY`, `CLICKHOUSE_CLOUD_API_SECRET`, `CLICKHOUSE_CLOUD_TEST_ORG_ID`, `CLICKHOUSE_CLOUD_TEST_PROVIDER`, and `CLICKHOUSE_CLOUD_TEST_REGION` in the environment, and are wired into the scheduled `Cloud Integration` GitHub Actions workflow. The ClickPipes E2E suites additionally need AWS credentials and an `eu-west-1` region quota; `clickpipe_smoke_test` reads a pre-provisioned service ID from `CLICKHOUSE_CLOUD_TEST_CLICKPIPE_SERVICE_ID`.

Manual `Cloud Integration` dispatches accept `scope=all`, `service`, `postgres`, `organization`, or `clickpipes`. The focused scopes run only their corresponding suite; `clickpipes` runs Postgres CDC plus the fixture-gated smoke test, while `all` runs all four mandatory suites plus that optional smoke test. For full-stack validation, manually run `scope=all` against the top stack branch.
Applying `run-cloud-integration` to an eligible PR selects suites from that PR's merge-base-to-head diff; known changes without a live suite finish without entering the environment-bearing job, while unknown API source or test paths select all suites. Changes to the classifier, its tests, or the workflow also select all suites through an independent workflow guard. Manual `Cloud Integration` dispatches accept `scope=all`, `service`, `postgres`, `organization`, or `clickpipes`. The focused scopes run only their corresponding suite; `clickpipes` runs Postgres CDC plus the fixture-gated smoke test, while `all` runs all four mandatory suites plus that optional smoke test. Because stacked-PR diffs exclude inherited changes, manually run `scope=all` against the top stack branch for full-stack validation.

`spec_coverage_test` sends the checked-in sources and snapshot through the
private `clickhouse-openapi-analyzer` crate. The analyzer recursively traverses
Expand Down
Loading