|
54 | 54 | run: docker compose down |
55 | 55 |
|
56 | 56 | unit: |
57 | | - runs-on: ubicloud-standard-4 |
| 57 | + runs-on: ubicloud-standard-8 |
58 | 58 | steps: |
59 | 59 | - uses: actions/checkout@v6 |
60 | 60 | - name: Setup Go |
|
72 | 72 | run: go test $(go list ./... | grep -v "quickstart") -v -failfast |
73 | 73 |
|
74 | 74 | integration: |
75 | | - runs-on: ubicloud-standard-4 |
| 75 | + runs-on: ubicloud-standard-8 |
76 | 76 | env: |
77 | 77 | DATABASE_URL: postgresql://hatchet:hatchet@127.0.0.1:5431/hatchet?sslmode=disable |
78 | 78 |
|
@@ -117,7 +117,7 @@ jobs: |
117 | 117 | run: docker compose down |
118 | 118 |
|
119 | 119 | e2e: |
120 | | - runs-on: ubicloud-standard-4 |
| 120 | + runs-on: ubicloud-standard-8 |
121 | 121 | timeout-minutes: 30 |
122 | 122 | env: |
123 | 123 | DATABASE_URL: postgresql://hatchet:hatchet@127.0.0.1:5431/hatchet?sslmode=disable |
@@ -206,7 +206,7 @@ jobs: |
206 | 206 | run: docker compose down |
207 | 207 |
|
208 | 208 | e2e-pgmq: |
209 | | - runs-on: ubicloud-standard-4 |
| 209 | + runs-on: ubicloud-standard-8 |
210 | 210 | timeout-minutes: 30 |
211 | 211 | env: |
212 | 212 | DATABASE_URL: postgresql://hatchet:hatchet@127.0.0.1:5431/hatchet?sslmode=disable |
@@ -297,7 +297,7 @@ jobs: |
297 | 297 | run: docker compose down |
298 | 298 |
|
299 | 299 | load: |
300 | | - runs-on: ubicloud-standard-4 |
| 300 | + runs-on: ubicloud-standard-8 |
301 | 301 | timeout-minutes: 30 |
302 | 302 | strategy: |
303 | 303 | matrix: |
@@ -339,8 +339,213 @@ jobs: |
339 | 339 | TESTING_MATRIX_PG_VERSION: ${{ matrix.pg-version }} |
340 | 340 | TESTING_MATRIX_OPTIMISTIC_SCHEDULING: ${{ matrix.optimistic-scheduling }} |
341 | 341 |
|
| 342 | + load-online-migrate: |
| 343 | + runs-on: ubicloud-standard-8 |
| 344 | + timeout-minutes: 30 |
| 345 | + env: |
| 346 | + DATABASE_URL: postgresql://hatchet:hatchet@127.0.0.1:5431/hatchet?sslmode=disable |
| 347 | + |
| 348 | + steps: |
| 349 | + - uses: actions/checkout@v6 |
| 350 | + with: |
| 351 | + fetch-depth: 0 |
| 352 | + fetch-tags: true |
| 353 | + |
| 354 | + - name: Setup Go |
| 355 | + uses: actions/setup-go@v6 |
| 356 | + with: |
| 357 | + go-version: "1.25" |
| 358 | + |
| 359 | + - name: Compose |
| 360 | + run: docker compose up -d |
| 361 | + |
| 362 | + - name: Determine latest stable release tag |
| 363 | + run: | |
| 364 | + LATEST_TAG=$(git tag --sort=-v:refname | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | head -1) |
| 365 | + if [ -z "$LATEST_TAG" ]; then |
| 366 | + echo "ERROR: No stable release tag found" |
| 367 | + exit 1 |
| 368 | + fi |
| 369 | + echo "Latest stable tag: $LATEST_TAG" |
| 370 | + echo "LATEST_TAG=$LATEST_TAG" >> $GITHUB_ENV |
| 371 | +
|
| 372 | + - name: Pull old release images |
| 373 | + run: | |
| 374 | + docker pull ghcr.io/hatchet-dev/hatchet/hatchet-migrate:${{ env.LATEST_TAG }} |
| 375 | + docker pull ghcr.io/hatchet-dev/hatchet/hatchet-admin:${{ env.LATEST_TAG }} |
| 376 | + docker pull ghcr.io/hatchet-dev/hatchet/hatchet-engine:${{ env.LATEST_TAG }} |
| 377 | + docker pull ghcr.io/hatchet-dev/hatchet/hatchet-loadtest:${{ env.LATEST_TAG }} |
| 378 | +
|
| 379 | + - name: Run old migrations |
| 380 | + run: | |
| 381 | + docker run --rm --network host \ |
| 382 | + -e DATABASE_URL="${{ env.DATABASE_URL }}" \ |
| 383 | + ghcr.io/hatchet-dev/hatchet/hatchet-migrate:${{ env.LATEST_TAG }} |
| 384 | +
|
| 385 | + - name: Setup config and seed database |
| 386 | + run: | |
| 387 | + mkdir -p generated |
| 388 | + docker run --rm --network host \ |
| 389 | + -v ${{ github.workspace }}/generated:/hatchet/generated \ |
| 390 | + -e DATABASE_URL="${{ env.DATABASE_URL }}" \ |
| 391 | + -e SERVER_GRPC_PORT=7077 \ |
| 392 | + -e SERVER_GRPC_BROADCAST_ADDRESS=localhost:7077 \ |
| 393 | + -e SERVER_GRPC_INSECURE=true \ |
| 394 | + -e SERVER_AUTH_COOKIE_DOMAIN=localhost \ |
| 395 | + -e SERVER_AUTH_COOKIE_INSECURE=true \ |
| 396 | + ghcr.io/hatchet-dev/hatchet/hatchet-admin:${{ env.LATEST_TAG }} \ |
| 397 | + /hatchet/hatchet-admin quickstart --skip certs --generated-config-dir /hatchet/generated |
| 398 | +
|
| 399 | + - name: Generate API token |
| 400 | + run: | |
| 401 | + TOKEN=$(docker run --rm --network host \ |
| 402 | + -v ${{ github.workspace }}/generated:/hatchet/generated \ |
| 403 | + -e DATABASE_URL="${{ env.DATABASE_URL }}" \ |
| 404 | + -e SERVER_GRPC_PORT=7077 \ |
| 405 | + -e SERVER_GRPC_BROADCAST_ADDRESS=localhost:7077 \ |
| 406 | + -e SERVER_GRPC_INSECURE=true \ |
| 407 | + -e SERVER_AUTH_COOKIE_DOMAIN=localhost \ |
| 408 | + -e SERVER_AUTH_COOKIE_INSECURE=true \ |
| 409 | + ghcr.io/hatchet-dev/hatchet/hatchet-admin:${{ env.LATEST_TAG }} \ |
| 410 | + /hatchet/hatchet-admin token create --config /hatchet/generated) |
| 411 | + echo "HATCHET_CLIENT_TOKEN=$TOKEN" >> $GITHUB_ENV |
| 412 | +
|
| 413 | + - name: Start old engine |
| 414 | + run: | |
| 415 | + docker run -d --name hatchet-engine --network host \ |
| 416 | + -v ${{ github.workspace }}/generated:/hatchet/generated \ |
| 417 | + -e DATABASE_URL="${{ env.DATABASE_URL }}" \ |
| 418 | + -e SERVER_GRPC_PORT=7077 \ |
| 419 | + -e SERVER_GRPC_BROADCAST_ADDRESS=localhost:7077 \ |
| 420 | + -e SERVER_GRPC_INSECURE=true \ |
| 421 | + -e SERVER_AUTH_COOKIE_DOMAIN=localhost \ |
| 422 | + -e SERVER_AUTH_COOKIE_INSECURE=true \ |
| 423 | + -e SERVER_MSGQUEUE_KIND=postgres \ |
| 424 | + -e SERVER_LOGGER_LEVEL=warn \ |
| 425 | + -e SERVER_LOGGER_FORMAT=console \ |
| 426 | + -e DATABASE_LOGGER_LEVEL=warn \ |
| 427 | + -e DATABASE_LOGGER_FORMAT=console \ |
| 428 | + ghcr.io/hatchet-dev/hatchet/hatchet-engine:${{ env.LATEST_TAG }} \ |
| 429 | + /hatchet/hatchet-engine --config /hatchet/generated |
| 430 | + echo "Waiting 30s for engine to start..." |
| 431 | + sleep 30 |
| 432 | +
|
| 433 | + - name: Start old load test |
| 434 | + run: | |
| 435 | + docker run -d --name hatchet-loadtest --network host \ |
| 436 | + -e HATCHET_CLIENT_TOKEN="${{ env.HATCHET_CLIENT_TOKEN }}" \ |
| 437 | + -e HATCHET_CLIENT_TLS_STRATEGY=none \ |
| 438 | + -e HATCHET_CLIENT_HOST_PORT=localhost:7077 \ |
| 439 | + ghcr.io/hatchet-dev/hatchet/hatchet-loadtest:${{ env.LATEST_TAG }} \ |
| 440 | + /hatchet/hatchet-load-test loadtest -e 10 -d 240s -w 60s -s 100 |
| 441 | +
|
| 442 | + - name: Wait then apply new migrations |
| 443 | + run: | |
| 444 | + echo "Waiting 30s for load test to get started..." |
| 445 | + sleep 30 |
| 446 | + echo "Applying new migrations from current branch..." |
| 447 | + go run ./cmd/hatchet-migrate |
| 448 | + echo "New migrations applied successfully" |
| 449 | +
|
| 450 | + - name: Wait for load test to complete |
| 451 | + run: | |
| 452 | + echo "Waiting for load test container to finish..." |
| 453 | + docker wait hatchet-loadtest |
| 454 | + EXIT_CODE=$(docker inspect hatchet-loadtest --format='{{.State.ExitCode}}') |
| 455 | + echo "Load test exited with code: $EXIT_CODE" |
| 456 | + if [ "$EXIT_CODE" != "0" ]; then |
| 457 | + echo "=== Load test logs ===" |
| 458 | + docker logs hatchet-loadtest |
| 459 | + echo "=== Engine logs ===" |
| 460 | + docker logs hatchet-engine |
| 461 | + exit 1 |
| 462 | + fi |
| 463 | + echo "Load test passed" |
| 464 | +
|
| 465 | + - name: Teardown |
| 466 | + if: always() |
| 467 | + run: | |
| 468 | + docker rm -f hatchet-loadtest hatchet-engine 2>/dev/null || true |
| 469 | + docker compose down |
| 470 | +
|
| 471 | + load-deadlock: |
| 472 | + runs-on: ubicloud-standard-8 |
| 473 | + timeout-minutes: 30 |
| 474 | + strategy: |
| 475 | + matrix: |
| 476 | + migrate-strategy: ["latest"] |
| 477 | + rabbitmq-enabled: ["true"] |
| 478 | + pg-version: ["17-alpine"] |
| 479 | + optimistic-scheduling: ["true", "false"] |
| 480 | + |
| 481 | + steps: |
| 482 | + - uses: actions/checkout@v6 |
| 483 | + |
| 484 | + - name: Install Task |
| 485 | + uses: arduino/setup-task@v2 |
| 486 | + with: |
| 487 | + repo-token: ${{ secrets.GITHUB_TOKEN }} |
| 488 | + |
| 489 | + - name: Setup Go |
| 490 | + uses: actions/setup-go@v6 |
| 491 | + with: |
| 492 | + go-version: "1.25" |
| 493 | + |
| 494 | + - name: Setup pnpm |
| 495 | + uses: pnpm/action-setup@v4 |
| 496 | + with: |
| 497 | + version: 10.16.1 |
| 498 | + run_install: false |
| 499 | + |
| 500 | + - name: Go deps |
| 501 | + run: go mod download |
| 502 | + |
| 503 | + - name: Add go-deadlock dependency |
| 504 | + run: go get github.com/sasha-s/go-deadlock@v0.3.6 |
| 505 | + |
| 506 | + - name: Patch sync imports to use go-deadlock (sed) |
| 507 | + shell: bash |
| 508 | + run: | |
| 509 | + set -euo pipefail |
| 510 | +
|
| 511 | + # Replace ONLY the stdlib "sync" import with an alias that preserves `sync.X` call sites. |
| 512 | + # - `import "sync"` -> `import sync "github.com/sasha-s/go-deadlock"` |
| 513 | + # - within import blocks: `"sync"` -> `sync "github.com/sasha-s/go-deadlock"` |
| 514 | + # NOTE: use `-i''` (no backup) for portability across GNU/BSD sed. |
| 515 | + find . -name '*.go' -not -path './vendor/*' -print0 | xargs -0 sed -i'' -E \ |
| 516 | + -e 's/^([[:space:]]*)import[[:space:]]+"sync"[[:space:]]*$/\1import sync "github.com\/sasha-s\/go-deadlock"/' \ |
| 517 | + -e 's/^([[:space:]]*)"sync"[[:space:]]*$/\1sync "github.com\/sasha-s\/go-deadlock"/' |
| 518 | +
|
| 519 | + # Keep formatting/import grouping consistent after rewriting. |
| 520 | + find . -name '*.go' -not -path './vendor/*' -print0 | xargs -0 gofmt -w |
| 521 | +
|
| 522 | + # Evidence in CI logs that rewriting happened (or not). |
| 523 | + echo "Changed Go files (after patch):" |
| 524 | + git diff --name-only -- '*.go' || true |
| 525 | +
|
| 526 | + echo "" |
| 527 | + echo "Contents of pkg/scheduling/v1/scheduler.go after patch:" |
| 528 | + echo "----" |
| 529 | + cat pkg/scheduling/v1/scheduler.go |
| 530 | + echo "----" |
| 531 | +
|
| 532 | + - name: Test (deadlock-instrumented) |
| 533 | + run: | |
| 534 | + # Disable gzip compression for load tests to reduce CPU overhead |
| 535 | + # Compression adds overhead without benefit for 0kb payloads |
| 536 | + HATCHET_CLIENT_DISABLE_GZIP_COMPRESSION=true go test -tags load ./... -p 5 -v -race -failfast -timeout 20m |
| 537 | + env: |
| 538 | + # This job adds go-deadlock + -race overhead; relax perf threshold to avoid flakes. |
| 539 | + HATCHET_LOADTEST_AVERAGE_DURATION_THRESHOLD: 1s |
| 540 | + # Give the engine a bit more time to come up under instrumentation. |
| 541 | + HATCHET_LOADTEST_STARTUP_SLEEP: 30s |
| 542 | + TESTING_MATRIX_MIGRATE: ${{ matrix.migrate-strategy }} |
| 543 | + TESTING_MATRIX_RABBITMQ_ENABLED: ${{ matrix.rabbitmq-enabled }} |
| 544 | + TESTING_MATRIX_PG_VERSION: ${{ matrix.pg-version }} |
| 545 | + TESTING_MATRIX_OPTIMISTIC_SCHEDULING: ${{ matrix.optimistic-scheduling }} |
| 546 | + |
342 | 547 | rampup: |
343 | | - runs-on: ubicloud-standard-4 |
| 548 | + runs-on: ubicloud-standard-8 |
344 | 549 | timeout-minutes: 30 |
345 | 550 | strategy: |
346 | 551 | matrix: |
|
0 commit comments