mirror of
https://github.com/temporalio/temporal.git
synced 2026-08-30 18:41:49 -07:00
## What changed? Added script to take memory report snapshots during test execution and print report after test success/failure. ## Why? Gain insights into memory usage; especially when job is OOM killed. ## How did you test it? see example: https://github.com/temporalio/temporal/actions/runs/21011468266/job/60407413329?pr=9027#step:9:15 <details><summary>Example</summary> <p> ``` Memory snapshot at 2026-01-14 22:16:53 Time Used(%) Used(MB) Goroutines Top Processes --------------------------------------------------------------- 22:06:03 16% 5347 ? java (2468MB), java (1322MB) 22:06:33 20% 6460 ? java (2450MB), java (1322MB), compile (376MB) 22:07:03 16% 5418 ? java (2430MB), java (1323MB) 22:07:33 16% 5401 2781 java (2531MB), java (1333MB) 22:08:06 17% 5702 5861 java (2493MB), java (1339MB), xdc.test (649MB) 22:08:36 18% 6034 5971 java (2528MB), java (1346MB), xdc.test (936MB) 22:09:07 20% 6455 6149 java (2539MB), java (1350MB), xdc.test (1314MB) 22:09:38 26% 8416 45668 xdc.test (3281MB), java (2535MB), java (1375MB) 22:10:10 33% 10596 43034 xdc.test (5657MB), java (2560MB), java (1405MB) 22:10:42 39% 12806 39209 xdc.test (7449MB), java (2551MB), java (1413MB) 22:11:13 42% 13580 33372 xdc.test (8166MB), java (2556MB), java (1413MB) 22:11:44 44% 14196 11067 xdc.test (8168MB), java (2548MB), java (1413MB) 22:12:15 44% 14171 11342 xdc.test (8653MB), java (2555MB), java (1415MB) 22:12:46 44% 14233 11724 xdc.test (8682MB), java (2546MB), java (1421MB) 22:13:17 45% 14536 10186 xdc.test (8858MB), java (2556MB), java (1427MB) 22:13:48 45% 14648 10392 xdc.test (8961MB), java (2555MB), java (1427MB) 22:14:19 45% 14710 10935 xdc.test (9027MB), java (2552MB), java (1428MB) 22:14:49 45% 14716 11060 xdc.test (9020MB), java (2557MB), java (1428MB) 22:15:20 45% 14702 11312 xdc.test (8925MB), java (2557MB), java (1428MB) 22:15:51 46% 14835 11571 xdc.test (9088MB), java (2545MB), java (1429MB) 22:16:22 46% 14839 11964 xdc.test (9082MB), java (2556MB), java (1429MB) 22:16:53 18% 5911 5792 java (2547MB), java (1434MB), xdc.test (628MB) --- Top Processes --- PID %MEM RSS COMMAND 2550 7.9 2608560 java 2679 4.4 1468908 java 23586 1.9 643644 xdc.test 1810 0.4 155452 provjobd 2094 0.4 142716 Runner.Worker 2079 0.3 113336 Runner.Listener 23517 0.3 99448 go 1161 0.2 78640 dockerd 833 0.1 51476 php-fpm8.3 910 0.1 51092 containerd 270 0.1 43536 multipathd 1417 0.1 36216 python3 865 0.1 35444 python3 3362 0.0 22220 go 1184 0.0 21448 php-fpm8.3 1185 0.0 21448 php-fpm8.3 831 0.0 20332 networkd-dispat 1987 0.0 19000 hca 203 0.0 16660 systemd-journal --- Memory Summary --- total used free shared buff/cache available Mem: 32098 5914 17968 51 8738 26183 Swap: 0 0 0 --- Go Heap Profile --- File: xdc.test Build ID: 2f2150795a26dac09836852e7ea9c9cf9f89fc14 Type: inuse_space Time: 2026-01-14 22:16:53 UTC Showing nodes accounting for 37251.65kB, 100% of 37251.65kB total flat flat% sum% cum cum% 6002.03kB 16.11% 16.11% 6002.03kB 16.11% go.temporal.io/sdk/internal.newLocalActivityTunnel (inline) 2565kB 6.89% 23.00% 2565kB 6.89% runtime.allocm 2564.16kB 6.88% 29.88% 3635.80kB 9.76% google.golang.org/protobuf/internal/filedesc.(*Message).unmarshalFull 2384.64kB 6.40% 36.28% 2384.64kB 6.40% go.temporal.io/server/common/aggregate.NewMovingWindowAvgImpl (inline) 2048.35kB 5.50% 41.78% 2048.35kB 5.50% github.com/aws/aws-sdk-go/aws/endpoints.init 1537.50kB 4.13% 45.91% 1537.50kB 4.13% go.uber.org/zap/internal/bufferpool.init.NewPool.func1 1536.66kB 4.13% 50.03% 1536.66kB 4.13% runtime.malg 1072.75kB 2.88% 52.91% 1072.75kB 2.88% go.temporal.io/sdk/internal.newBaseWorker 1071.64kB 2.88% 55.79% 1071.64kB 2.88% google.golang.org/protobuf/internal/strs.(*Builder).grow (inline) 1045.40kB 2.81% 58.60% 1045.40kB 2.81% github.com/gocql/gocql.(*Session).scanColumnMetadataSystem 1024.11kB 2.75% 61.35% 1024.11kB 2.75% time.newTimer 1024.09kB 2.75% 64.09% 1024.09kB 2.75% go.temporal.io/server/common/tasks.(*SequentialScheduler[go.shape.interface { Abort(); Ack(); Cancel(); Execute() error; HandleErr(error) error; IsRetryableError(error) bool; MarkPoisonPill() error; Nack(error); QueueID() interface {}; ReplicationTask() *go.temporal.io/server/api/replication/v1.ReplicationTask; Reschedule(); RetryPolicy() go.temporal.io/server/common/backoff.RetryPolicy; SourceClusterName() string; State() go.temporal.io/server/common/tasks.State; TaskCreationTime() time.Time; TaskID() int64 }]).pollTaskQueue 532.26kB 1.43% 65.52% 532.26kB 1.43% google.golang.org/protobuf/reflect/protoregistry.(*Files).RegisterFile.func2 528.17kB 1.42% 66.94% 528.17kB 1.42% bufio.NewReaderSize (inline) 528.17kB 1.42% 68.36% 528.17kB 1.42% google.golang.org/grpc/internal/transport.newBufWriter (inline) 516.76kB 1.39% 69.75% 516.76kB 1.39% runtime.procresize 514kB 1.38% 71.13% 514kB 1.38% github.com/gocql/gocql/internal/streams.New (inline) 513.50kB 1.38% 72.50% 513.50kB 1.38% go.temporal.io/server/api/history/v1.init 512.50kB 1.38% 73.88% 7680.97kB 20.62% go.uber.org/fx/internal/lifecycle.(*Lifecycle).Start 512.44kB 1.38% 75.26% 512.44kB 1.38% go/token.init.0 512.25kB 1.38% 76.63% 512.25kB 1.38% runtime.gcBgMarkWorker 512.19kB 1.37% 78.01% 512.19kB 1.37% github.com/gocql/gocql.(*Conn).executeQuery 512.17kB 1.37% 79.38% 512.17kB 1.37% google.golang.org/grpc/metadata.FromOutgoingContext 512.17kB 1.37% 80.76% 512.17kB 1.37% google.golang.org/grpc/metadata.MD.Set (inline) 512.10kB 1.37% 82.13% 512.10kB 1.37% context.(*cancelCtx).propagateCancel 512.10kB 1.37% 83.51% 512.10kB 1.37% go.uber.org/fx.moduleOption.apply 512.09kB 1.37% 84.88% 512.09kB 1.37% internal/abi.NewName 512.07kB 1.37% 86.25% 512.07kB 1.37% go.uber.org/dig.(*Scope).newGraphNode 512.06kB 1.37% 87.63% 512.06kB 1.37% google.golang.org/protobuf/internal/impl.fieldInfoForScalar 512.05kB 1.37% 89.00% 512.05kB 1.37% go.temporal.io/server/common/goro.NewAdaptivePool 512.05kB 1.37% 90.38% 512.05kB 1.37% go.temporal.io/server/common/nexus.(*EndpointRegistryImpl).setEnabled 512.05kB 1.37% 91.75% 512.05kB 1.37% google.golang.org/grpc/internal/transport.newWriteQuota (inline) 512.05kB 1.37% 93.13% 512.05kB 1.37% go.temporal.io/sdk/internal.(*baseWorker).runEagerTaskDispatcher 512.02kB 1.37% 94.50% 512.02kB 1.37% context.WithValue 512.02kB 1.37% 95.88% 512.02kB 1.37% encoding/json.typeFields 512.02kB 1.37% 97.25% 512.02kB 1.37% github.com/gocql/gocql.(*ring).addHostIfMissing 512.02kB 1.37% 98.63% 512.02kB 1.37% github.com/google/uuid.UUID.String (inline) 512.02kB 1.37% 100% 512.02kB 1.37% go.uber.org/dig.newParam 0 0% 100% 512.10kB 1.37% context.WithCancel 0 0% 100% 512.10kB 1.37% context.withCancel (inline) 0 0% 100% 512.02kB 1.37% encoding/json.(*Decoder).Decode 0 0% 100% 512.02kB 1.37% encoding/json.(*decodeState).object 0 0% 100% 512.02kB 1.37% encoding/json.(*decodeState).unmarshal 0 0% 100% 512.02kB 1.37% encoding/json.(*decodeState).value 0 0% 100% 512.02kB 1.37% encoding/json.cachedTypeFields 0 0% 100% 512.02kB 1.37% encoding/json.newStructEncoder (inline) 0 0% 100% 512.02kB 1.37% encoding/json.newTypeEncoder 0 0% 100% 512.02kB 1.37% encoding/json.typeEncoder 0 0% 100% 512.02kB 1.37% encoding/json.typeEncoder.func1 0 0% 100% 1557.42kB 4.18% github.com/gocql/gocql.(*ClusterConfig).CreateSession (inline) 0 0% 100% 512.19kB 1.37% github.com/gocql/gocql.(*Query).Iter 0 0% 100% 512.19kB 1.37% github.com/gocql/gocql.(*Query).MapScanCAS 0 0% 100% 512.19kB 1.37% github.com/gocql/gocql.(*Query).execute 0 0% 100% 1045.40kB 2.81% github.com/gocql/gocql.(*Session).KeyspaceMetadata File: xdc.test Build ID: 2f2150795a26dac09836852e7ea9c9cf9f89fc14 Type: alloc_space Time: 2026-01-14 22:16:53 UTC Showing nodes accounting for 99.45MB, 80.53% of 123.49MB total Dropped 305 nodes (cum <= 0.62MB) flat flat% sum% cum cum% 51.44MB 41.65% 41.65% 51.44MB 41.65% regexp.(*bitState).reset 5.86MB 4.75% 46.40% 5.86MB 4.75% go.temporal.io/sdk/internal.newLocalActivityTunnel (inline) 3.53MB 2.85% 49.26% 4.59MB 3.72% compress/flate.NewWriter (inline) 2.50MB 2.03% 51.28% 2.50MB 2.03% runtime.allocm 2.50MB 2.03% 53.31% 3.55MB 2.88% google.golang.org/protobuf/internal/filedesc.(*Message).unmarshalFull 2.33MB 1.89% 55.20% 2.33MB 1.89% go.temporal.io/server/common/aggregate.NewMovingWindowAvgImpl (inline) 2MB 1.62% 56.82% 2MB 1.62% go.uber.org/zap/internal/bufferpool.init.NewPool.func1 2MB 1.62% 58.44% 2MB 1.62% github.com/aws/aws-sdk-go/aws/endpoints.init 1.52MB 1.23% 59.67% 1.52MB 1.23% github.com/gocql/gocql.(*Session).scanColumnMetadataSystem 1.51MB 1.22% 60.89% 1.51MB 1.22% github.com/grpc-ecosystem/grpc-gateway/v2/runtime.(*ServeMux).Handle 1.50MB 1.22% 62.11% 1.50MB 1.22% runtime.malg 1.50MB 1.21% 63.32% 1.50MB 1.21% fmt.init.func1 1.50MB 1.21% 64.54% 1.50MB 1.21% github.com/gocql/gocql.newFramer (inline) 1.50MB 1.21% 65.75% 2MB 1.62% go.uber.org/dig.getParamOrder 1.07MB 0.86% 66.62% 1.07MB 0.86% compress/flate.(*compressor).initDeflate (inline) 1.05MB 0.85% 67.46% 1.05MB 0.85% go.temporal.io/sdk/internal.newBaseWorker 1.05MB 0.85% 68.31% 1.05MB 0.85% google.golang.org/protobuf/internal/strs.(*Builder).grow (inline) 1.03MB 0.84% 69.15% 1.03MB 0.84% compress/flate.(*dictDecoder).init (inline) 1.02MB 0.83% 69.97% 1.02MB 0.83% google.golang.org/protobuf/reflect/protoregistry.(*Files).RegisterFile.func2 1MB 0.81% 70.79% 1MB 0.81% github.com/gocql/gocql/internal/streams.New (inline) 1MB 0.81% 71.60% 2MB 1.62% go.uber.org/dig.(*Scope).findAndValidateResults 1MB 0.81% 72.41% 1MB 0.81% context.(*cancelCtx).propagateCancel 1MB 0.81% 73.22% 1MB 0.81% time.newTimer 1MB 0.81% 74.03% 1MB 0.81% go.temporal.io/server/common/tasks.(*SequentialScheduler[go.shape.interface { Abort(); Ack(); Cancel(); Execute() error; HandleErr(error) error; IsRetryableError(error) bool; MarkPoisonPill() error; Nack(error); QueueID() interface {}; ReplicationTask() *go.temporal.io/server/api/replication/v1.ReplicationTask; Reschedule(); RetryPolicy() go.temporal.io/server/common/backoff.RetryPolicy; SourceClusterName() string; State() go.temporal.io/server/common/tasks.State; TaskCreationTime() time.Time; TaskID() int64 }]).pollTaskQueue 1MB 0.81% 74.84% 7MB 5.67% go.uber.org/dig.(*Scope).provide 1MB 0.81% 75.65% 1MB 0.81% container/list.New (inline) 1MB 0.81% 76.46% 2MB 1.62% go.uber.org/dig.newParam 0.52MB 0.42% 76.88% 1.54MB 1.25% google.golang.org/protobuf/reflect/protoregistry.(*Files).RegisterFile 0.51MB 0.41% 77.29% 1.54MB 1.24% io.ReadAll 0.50MB 0.41% 77.69% 8.50MB 6.88% go.uber.org/fx/internal/lifecycle.(*Lifecycle).Start 0.50MB 0.41% 78.10% 2MB 1.62% github.com/gocql/gocql.(*Conn).executeQuery 0.50MB 0.41% 78.50% 1.50MB 1.22% go.temporal.io/server/common/log.(*zapLogger).cloneWithTags 0.50MB 0.41% 78.91% 10.98MB 8.89% go.uber.org/dig.paramObject.Build 0.50MB 0.4% 79.31% 37.04MB 29.99% go.uber.org/fx/internal/fxreflect.CallerStack 0.50MB 0.4% 79.72% 2.50MB 2.02% go.uber.org/dig.(*graphHolder).EdgesFrom 0.50MB 0.4% 80.12% 7.50MB 6.07% go.uber.org/dig.(*Scope).Provide 0.50MB 0.4% 80.53% 1MB 0.81% go.uber.org/dig.(*Scope).getAllProviders (inline) 0 0% 80.53% 1.07MB 0.86% compress/flate.(*compressor).init 0 0% 80.53% 1.03MB 0.84% compress/flate.NewReader 0 0% 80.53% 1.03MB 0.84% compress/gzip.(*Reader).Reset 0 0% 80.53% 1.03MB 0.84% compress/gzip.(*Reader).readHeader 0 0% 80.53% 4.59MB 3.72% compress/gzip.(*Writer).Write 0 0% 80.53% 1.03MB 0.84% compress/gzip.NewReader (inline) 0 0% 80.53% 1MB 0.81% context.WithCancel 0 0% 80.53% 1MB 0.81% context.withCancel (inline) 0 0% 80.53% 1MB 0.81% fmt.(*pp).doPrintf 0 0% 80.53% 1.02MB 0.82% fmt.(*pp).handleMethods 0 0% 80.53% 1.52MB 1.23% fmt.(*pp).printArg 0 0% 80.53% 2MB 1.62% fmt.Fprintf 0 0% 80.53% 1MB 0.81% fmt.Sprintf 0 0% 80.53% 1.50MB 1.21% fmt.newPrinter 0 0% 80.53% 4.02MB 3.26% github.com/gocql/gocql.(*ClusterConfig).CreateSession (inline) 0 0% 80.53% 2MB 1.62% github.com/gocql/gocql.(*Conn).recv ``` </p> </details> --------- Co-authored-by: David Reiss <dnr@dnr.im>
996 lines
38 KiB
YAML
996 lines
38 KiB
YAML
name: All Tests
|
|
run-name: ${{ inputs.test_name }}${{ inputs.test_dbs }}
|
|
|
|
on:
|
|
pull_request:
|
|
push:
|
|
branches:
|
|
- main
|
|
- cloud/*
|
|
- feature/*
|
|
- release/*
|
|
|
|
workflow_dispatch:
|
|
inputs:
|
|
commit:
|
|
description: "Commit SHA"
|
|
required: true
|
|
run_single_functional_test:
|
|
description: "Run a single functional test"
|
|
type: boolean
|
|
default: false
|
|
run_single_unit_test:
|
|
description: "Run a single unit test (INSTEAD of functional test)"
|
|
type: boolean
|
|
default: false
|
|
unit_test_directory:
|
|
description: "[Unit Test Only] Directory to run unit tests in"
|
|
type: string
|
|
default: "./temporal"
|
|
n_runs:
|
|
description: "Number of times to repeat the test per database type (except for unit tests, start with n=25 or lower to avoid OOMKill)"
|
|
type: number
|
|
default: 1
|
|
test_name:
|
|
description: "Name of the test to run (i.e. 'TestAcquireShard_DeadlineExceededErrorSuite' or 'TestFunctionalSuite/TestUpdateWorkflow')"
|
|
type: string
|
|
timeout_minutes:
|
|
description: "Test timeout in minutes"
|
|
type: number
|
|
default: 120
|
|
test_runner:
|
|
description: "Which runner to use. Choose higher RAM if your n_runs is high."
|
|
type: choice
|
|
default: "16GB RAM (ubuntu-latest)"
|
|
options:
|
|
- "16GB RAM (ubuntu-latest)"
|
|
- "64GB RAM (ubuntu-latest-16-cores)"
|
|
test_dbs:
|
|
description: 'List of DBs to test on (i.e. ["sqlite", "cassandra", "mysql8", "postgres12"])'
|
|
type: string
|
|
default: '["sqlite"]'
|
|
|
|
concurrency: # Auto-cancel existing runs in the PR when a new commit is pushed
|
|
group: run-tests-${{ github.head_ref || github.run_id }}
|
|
cancel-in-progress: true
|
|
|
|
env:
|
|
# For workflow_dispatch: use the given commit.
|
|
# For pull_request: use the head of the PR branch (not the merge branch which is the default!)
|
|
# For push: use the pushed commit.
|
|
COMMIT: ${{ github.event.inputs.commit || github.event.pull_request.head.sha || github.sha }}
|
|
PR_BASE_COMMIT: ${{ github.event.pull_request.base.sha }}
|
|
DOCKER_COMPOSE_FILE: ./develop/github/docker-compose.yml
|
|
TEMPORAL_VERSION_CHECK_DISABLED: 1
|
|
MAX_TEST_ATTEMPTS: 3
|
|
|
|
jobs:
|
|
set-up-single-test:
|
|
name: Set up single test
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
shard_indices: ${{ steps.generate_output.outputs.shard_indices }}
|
|
total_shards: ${{ steps.generate_output.outputs.shards }}
|
|
github_timeout: ${{ steps.generate_output.outputs.github_timeout }}
|
|
test_timeout: ${{ steps.generate_output.outputs.test_timeout }}
|
|
single_test_args: ${{ steps.generate_output.outputs.single_test_args }}
|
|
runs_on: ${{ steps.generate_output.outputs.runs_on }}
|
|
dbs: ${{ inputs.test_dbs }}
|
|
modified_unit_test_suites: ${{ env.modified_unit_test_suites }}
|
|
modified_integration_test_suites: ${{ env.modified_integration_test_suites }}
|
|
modified_functional_test_suites: ${{ env.modified_functional_test_suites }}
|
|
modified_functional_ndc_test_suites: ${{ env.modified_functional_ndc_test_suites }}
|
|
modified_functional_xdc_test_suites: ${{ env.modified_functional_xdc_test_suites }}
|
|
steps:
|
|
- id: generate_output
|
|
run: |
|
|
shards=3
|
|
timeout=35 # update this to TEST_TIMEOUT if you update the Makefile
|
|
runs_on='["ubuntu-latest"]'
|
|
if [[ "${{ inputs.run_single_functional_test }}" == "true" || "${{ inputs.run_single_unit_test }}" == "true" ]]; then
|
|
shards=1
|
|
timeout=${{ inputs.timeout_minutes }}
|
|
single_test_args="-run ${{ inputs.test_name }} -count ${{ inputs.n_runs }}"
|
|
if [[ "${{ inputs.test_runner }}" == "64GB RAM (ubuntu-latest-16-cores)" ]]; then
|
|
runs_on='[ "ubuntu-latest-16-cores" ]'
|
|
fi
|
|
fi
|
|
{
|
|
echo "shard_indices=[ $(seq -s, 0 $((shards-1))) ]"
|
|
echo "shards=$shards"
|
|
echo "github_timeout=$((timeout+5))"
|
|
echo "test_timeout=${timeout}m"
|
|
echo "single_test_args=$single_test_args"
|
|
echo "runs_on=$runs_on"
|
|
} >> "$GITHUB_OUTPUT"
|
|
- id: cat_output
|
|
run: |
|
|
cat "$GITHUB_OUTPUT"
|
|
|
|
- name: Checkout Code
|
|
uses: actions/checkout@v6
|
|
with:
|
|
token: ${{ secrets.GITHUB_TOKEN }}
|
|
ref: ${{ env.COMMIT }}
|
|
fetch-depth: 0
|
|
|
|
- name: Fetch base branch
|
|
run: git fetch origin ${{ github.event.pull_request.base.ref }}:${{ github.event.pull_request.base.ref }}
|
|
|
|
- name: Compute merge base
|
|
if: ${{ github.event_name == 'pull_request' }}
|
|
run: |
|
|
MERGE_BASE="$(git merge-base "${{ env.COMMIT }}" "${{ github.event.pull_request.base.ref }}")"
|
|
echo "MERGE_BASE=${MERGE_BASE}" >> "$GITHUB_ENV"
|
|
|
|
set -exuo pipefail
|
|
|
|
go run ./cmd/tools/test/find_altered_tests.go \
|
|
-c unit \
|
|
-c integration \
|
|
-c functional \
|
|
-c functional_ndc \
|
|
-c functional_xdc \
|
|
-s "${MERGE_BASE}" \
|
|
-t "${COMMIT}" | tee -a "$GITHUB_ENV"
|
|
shell: bash
|
|
|
|
pre-build:
|
|
name: Pre-build for cache
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
if: ${{ !inputs.run_single_functional_test && !inputs.run_single_unit_test }}
|
|
with:
|
|
token: ${{ secrets.GITHUB_TOKEN }}
|
|
ref: ${{ env.COMMIT }}
|
|
|
|
- uses: actions/setup-go@v6
|
|
if: ${{ !inputs.run_single_functional_test && !inputs.run_single_unit_test }}
|
|
with:
|
|
go-version-file: "go.mod"
|
|
cache: false # do our own caching
|
|
|
|
- name: Restore dependencies
|
|
if: ${{ !inputs.run_single_functional_test && !inputs.run_single_unit_test }}
|
|
id: restore-deps
|
|
uses: actions/cache/restore@v4
|
|
with:
|
|
path: ~/go/pkg/mod
|
|
key: go-${{ runner.os }}${{ runner.arch }}-${{ hashFiles('go.mod') }}-deps-${{ hashFiles('go.sum') }}
|
|
|
|
- run: make pre-build-functional-test-coverage
|
|
if: ${{ !inputs.run_single_functional_test && !inputs.run_single_unit_test }}
|
|
|
|
- name: Save dependencies
|
|
uses: actions/cache/save@v4
|
|
if: ${{ !inputs.run_single_functional_test && !inputs.run_single_unit_test && steps.restore-deps.outputs.cache-hit != 'true' }}
|
|
with:
|
|
path: ~/go/pkg/mod
|
|
key: ${{ steps.restore-deps.outputs.cache-primary-key }}
|
|
|
|
- name: Save build outputs
|
|
uses: actions/cache/save@v4
|
|
if: ${{ !inputs.run_single_functional_test && !inputs.run_single_unit_test }}
|
|
with:
|
|
path: ~/.cache/go-build
|
|
key: go-${{ runner.os }}${{ runner.arch }}-build-${{ env.COMMIT }}
|
|
|
|
misc-checks:
|
|
name: Misc checks
|
|
needs: pre-build
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
if: ${{ !inputs.run_single_functional_test && !inputs.run_single_unit_test }}
|
|
with:
|
|
token: ${{ secrets.GITHUB_TOKEN }}
|
|
ref: ${{ env.COMMIT }}
|
|
# buf-breaking tries to compare HEAD against merge base so we need to be able to find it
|
|
fetch-depth: 100
|
|
|
|
- uses: actions/setup-go@v6
|
|
if: ${{ !inputs.run_single_functional_test && !inputs.run_single_unit_test }}
|
|
with:
|
|
go-version-file: "go.mod"
|
|
cache: false # do our own caching
|
|
|
|
- name: Restore dependencies
|
|
if: ${{ !inputs.run_single_functional_test && !inputs.run_single_unit_test }}
|
|
uses: actions/cache/restore@v4
|
|
with:
|
|
path: ~/go/pkg/mod
|
|
key: go-${{ runner.os }}${{ runner.arch }}-${{ hashFiles('go.mod') }}-deps-${{ hashFiles('go.sum') }}
|
|
|
|
- name: Restore build outputs
|
|
if: ${{ !inputs.run_single_functional_test && !inputs.run_single_unit_test }}
|
|
uses: actions/cache/restore@v4
|
|
with:
|
|
path: ~/.cache/go-build
|
|
key: go-${{ runner.os }}${{ runner.arch }}-build-${{ env.COMMIT }}
|
|
|
|
- uses: arduino/setup-protoc@v3
|
|
if: ${{ !inputs.run_single_functional_test && !inputs.run_single_unit_test }}
|
|
with:
|
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- run: GOOS=windows GOARCH=amd64 make clean-bins bins
|
|
if: ${{ !inputs.run_single_functional_test && !inputs.run_single_unit_test }}
|
|
|
|
- run: GOOS=darwin GOARCH=arm64 make clean-bins bins
|
|
if: ${{ !inputs.run_single_functional_test && !inputs.run_single_unit_test }}
|
|
|
|
- run: make clean-bins ci-build-misc
|
|
if: ${{ !inputs.run_single_functional_test && !inputs.run_single_unit_test }}
|
|
|
|
unit-test:
|
|
if: ${{ inputs.run_single_functional_test != true }}
|
|
name: Unit test
|
|
needs: [pre-build, set-up-single-test]
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
with:
|
|
token: ${{ secrets.GITHUB_TOKEN }}
|
|
ref: ${{ env.COMMIT }}
|
|
|
|
- uses: actions/setup-go@v6
|
|
with:
|
|
go-version-file: "go.mod"
|
|
cache: false # do our own caching
|
|
|
|
- name: Restore dependencies
|
|
uses: actions/cache/restore@v4
|
|
with:
|
|
path: ~/go/pkg/mod
|
|
key: go-${{ runner.os }}${{ runner.arch }}-${{ hashFiles('go.mod') }}-deps-${{ hashFiles('go.sum') }}
|
|
|
|
- name: Restore build outputs
|
|
uses: actions/cache/restore@v4
|
|
with:
|
|
path: ~/.cache/go-build
|
|
key: go-${{ runner.os }}${{ runner.arch }}-build-${{ env.COMMIT }}
|
|
|
|
- name: Run unit tests
|
|
timeout-minutes: 20
|
|
run: TEST_TIMEOUT=15m make unit-test-coverage
|
|
env:
|
|
UNIT_TEST_DIRS: ${{ inputs.unit_test_directory }}
|
|
TEST_ARGS: ${{ needs.set-up-single-test.outputs.single_test_args }}
|
|
TEST_TIMEOUT: ${{ needs.set-up-single-test.outputs.test_timeout }}
|
|
|
|
- name: Generate crash report
|
|
if: failure()
|
|
run:
|
|
| # if the tests failed, we would expect one JUnit XML report per attempt; otherwise it must have crashed
|
|
[ "$(find .testoutput -maxdepth 1 -name 'junit.*.xml' | wc -l)" -lt "$MAX_TEST_ATTEMPTS" ] &&
|
|
CRASH_REPORT_NAME="$GITHUB_JOB" make report-test-crash
|
|
|
|
- name: Generate test summary
|
|
uses: mikepenz/action-junit-report@v5.0.0-rc01
|
|
if: failure()
|
|
with:
|
|
report_paths: ./.testoutput/junit.*.xml
|
|
detailed_summary: true
|
|
check_annotations: false
|
|
annotate_only: true
|
|
skip_annotations: true
|
|
|
|
- name: Upload code coverage to Codecov
|
|
uses: codecov/codecov-action@v5
|
|
with:
|
|
token: ${{ secrets.CODECOV_TOKEN }}
|
|
directory: ./.testoutput
|
|
flags: unit-test
|
|
|
|
- name: Upload test results to Codecov
|
|
if: ${{ !cancelled() }}
|
|
uses: codecov/test-results-action@v1
|
|
with:
|
|
token: ${{ secrets.CODECOV_TOKEN }}
|
|
directory: ./.testoutput
|
|
flags: unit-test
|
|
|
|
- name: Upload test results to GitHub
|
|
# Can't pin to major because the action linter doesn't recognize the include-hidden-files flag.
|
|
uses: actions/upload-artifact@v4.4.3
|
|
if: ${{ !cancelled() && !inputs.run_single_unit_test }}
|
|
with:
|
|
name: junit-xml--${{github.run_id}}--${{github.run_attempt}}--unit-test
|
|
path: ./.testoutput/junit.*.xml
|
|
include-hidden-files: true
|
|
retention-days: 28
|
|
|
|
# Ensure this doesn't contribute to the junit output.
|
|
- name: Flaky Unit Test Detection
|
|
if: ${{ !cancelled() && !inputs.run_single_unit_test && env.MODIFIED_TEST_SUITES != '' }}
|
|
timeout-minutes: 30
|
|
run: |
|
|
echo "Detecting flaky unit tests: ${{ needs.set-up-single-test.outputs.modified_unit_test_suites }}"
|
|
make unit-test
|
|
env:
|
|
FAILED_TEST_RETRIES: "0" # not retrying failed tests intentionally here since we're trying to detect flakes
|
|
TEST_ARGS: "-run=${{ needs.set-up-single-test.outputs.modified_unit_test_suites }} -count=10"
|
|
TEST_TIMEOUT: 35
|
|
|
|
integration-test:
|
|
if: ${{ inputs.run_single_functional_test != true && inputs.run_single_unit_test != true }}
|
|
name: Integration test
|
|
needs: [pre-build, set-up-single-test]
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
with:
|
|
token: ${{ secrets.GITHUB_TOKEN }}
|
|
ref: ${{ env.COMMIT }}
|
|
|
|
- name: Start containerized dependencies
|
|
uses: hoverkraft-tech/compose-action@v2.0.1
|
|
with:
|
|
compose-file: ${{ env.DOCKER_COMPOSE_FILE }}
|
|
services: |
|
|
cassandra
|
|
mysql
|
|
postgresql
|
|
down-flags: -v
|
|
|
|
- uses: actions/setup-go@v6
|
|
with:
|
|
go-version-file: "go.mod"
|
|
cache: false # do our own caching
|
|
|
|
- name: Restore dependencies
|
|
uses: actions/cache/restore@v4
|
|
with:
|
|
path: ~/go/pkg/mod
|
|
key: go-${{ runner.os }}${{ runner.arch }}-${{ hashFiles('go.mod') }}-deps-${{ hashFiles('go.sum') }}
|
|
|
|
- name: Restore build outputs
|
|
uses: actions/cache/restore@v4
|
|
with:
|
|
path: ~/.cache/go-build
|
|
key: go-${{ runner.os }}${{ runner.arch }}-build-${{ env.COMMIT }}
|
|
|
|
- name: Run integration test
|
|
timeout-minutes: 15
|
|
run: make integration-test-coverage
|
|
|
|
- name: Generate crash report
|
|
if: failure()
|
|
run:
|
|
| # if the tests failed, we would expect one JUnit XML report per attempt; otherwise it must have crashed
|
|
[ "$(find .testoutput -maxdepth 1 -name 'junit.*.xml' | wc -l)" -lt "$MAX_TEST_ATTEMPTS" ] &&
|
|
CRASH_REPORT_NAME="$GITHUB_JOB" make report-test-crash
|
|
|
|
- name: Generate test summary
|
|
uses: mikepenz/action-junit-report@v5.0.0-rc01
|
|
if: failure()
|
|
with:
|
|
report_paths: ./.testoutput/junit.*.xml
|
|
detailed_summary: true
|
|
check_annotations: false
|
|
annotate_only: true
|
|
skip_annotations: true
|
|
|
|
- name: Upload code coverage to Codecov
|
|
uses: codecov/codecov-action@v5
|
|
with:
|
|
token: ${{ secrets.CODECOV_TOKEN }}
|
|
directory: ./.testoutput
|
|
flags: integration-test
|
|
|
|
- name: Upload test results to Codecov
|
|
if: ${{ !cancelled() }}
|
|
uses: codecov/test-results-action@v1
|
|
with:
|
|
token: ${{ secrets.CODECOV_TOKEN }}
|
|
directory: ./.testoutput
|
|
flags: integration-test
|
|
|
|
- name: Upload test results to GitHub
|
|
# Can't pin to major because the action linter doesn't recognize the include-hidden-files flag.
|
|
uses: actions/upload-artifact@v4.4.3
|
|
if: ${{ !cancelled() }}
|
|
with:
|
|
name: junit-xml--${{github.run_id}}--${{github.run_attempt}}--integration-test
|
|
path: ./.testoutput/junit.*.xml
|
|
include-hidden-files: true
|
|
retention-days: 28
|
|
|
|
# Ensure this doesn't contribute to the junit output.
|
|
- name: Flaky Integration Test Detection
|
|
if: ${{ env.MODIFIED_TEST_SUITES != '' }}
|
|
timeout-minutes: 30
|
|
run: |
|
|
echo "Detecting flaky integration tests: ${{ needs.set-up-single-test.outputs.modified_integration_test_suites }}"
|
|
make integration-test-coverage
|
|
env:
|
|
FAILED_TEST_RETRIES: "0" # not retrying failed tests intentionally here since we're trying to detect flakes
|
|
TEST_ARGS: "-run=${{ needs.set-up-single-test.outputs.modified_integration_test_suites }} -count=5"
|
|
|
|
- name: Tear down docker compose
|
|
if: ${{ always() }}
|
|
run: |
|
|
docker compose -f ${{ env.DOCKER_COMPOSE_FILE }} down -v
|
|
|
|
# Root job name includes matrix details so it is unique per shard.
|
|
# This MUST stay in sync with the `job_name` passed to the job-id action below.
|
|
functional-test:
|
|
if: ${{ inputs.run_single_unit_test != true }}
|
|
# Display name shown in the UI. The job-id lookup uses this exact value.
|
|
name: Functional test (${{ matrix.name }}, shard ${{ matrix.shard_index }})
|
|
needs: [pre-build, set-up-single-test]
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
name:
|
|
- cass_es
|
|
- cass_es8
|
|
- cass_os2
|
|
- cass_os3
|
|
- sqlite
|
|
- mysql8
|
|
- postgres12
|
|
- postgres12_pgx
|
|
shard_index: ${{ fromJson(needs.set-up-single-test.outputs.shard_indices) }}
|
|
runs-on: ${{ fromJson(needs.set-up-single-test.outputs.runs_on) }}
|
|
include:
|
|
- name: cass_es
|
|
persistence_type: nosql
|
|
persistence_driver: cassandra
|
|
containers: [cassandra, elasticsearch]
|
|
es_version: v7
|
|
# Cassandra tests need a larger instance
|
|
runs_on_override: ubuntu-latest-8-cores
|
|
- name: cass_es8
|
|
persistence_type: nosql
|
|
persistence_driver: cassandra
|
|
containers: [cassandra, elasticsearch8]
|
|
es_version: v8
|
|
# Cassandra tests need a larger instance
|
|
runs_on_override: ubuntu-latest-8-cores
|
|
- name: cass_os2
|
|
persistence_type: nosql
|
|
persistence_driver: cassandra
|
|
containers: [cassandra, opensearch2]
|
|
- name: cass_os3
|
|
persistence_type: nosql
|
|
persistence_driver: cassandra
|
|
containers: [cassandra, opensearch3]
|
|
- name: sqlite
|
|
persistence_type: sql
|
|
persistence_driver: sqlite
|
|
containers: []
|
|
- name: mysql8
|
|
persistence_type: sql
|
|
persistence_driver: mysql8
|
|
containers: [mysql]
|
|
- name: postgres12
|
|
persistence_type: sql
|
|
persistence_driver: postgres12
|
|
containers: [postgresql]
|
|
- name: postgres12_pgx
|
|
persistence_type: sql
|
|
persistence_driver: postgres12_pgx
|
|
containers: [postgresql]
|
|
runs-on: ${{ matrix.runs_on_override || matrix.runs-on }}
|
|
env:
|
|
TEST_TOTAL_SHARDS: ${{ needs.set-up-single-test.outputs.total_shards }}
|
|
TEST_SHARD_INDEX: ${{ matrix.shard_index }}
|
|
PERSISTENCE_TYPE: ${{ matrix.persistence_type }}
|
|
PERSISTENCE_DRIVER: ${{ matrix.persistence_driver }}
|
|
TEST_TIMEOUT: ${{ needs.set-up-single-test.outputs.test_timeout }}
|
|
steps:
|
|
- uses: ScribeMD/docker-cache@0.3.7
|
|
if: ${{ inputs.run_single_functional_test != true || (inputs.run_single_functional_test == true && contains(fromJSON(needs.set-up-single-test.outputs.dbs), env.PERSISTENCE_DRIVER)) }}
|
|
with:
|
|
key: docker-${{ runner.os }}${{ runner.arch }}-${{ hashFiles(env.DOCKER_COMPOSE_FILE) }}
|
|
|
|
- uses: actions/checkout@v6
|
|
if: ${{ inputs.run_single_functional_test != true || (inputs.run_single_functional_test == true && contains(fromJSON(needs.set-up-single-test.outputs.dbs), env.PERSISTENCE_DRIVER)) }}
|
|
with:
|
|
token: ${{ secrets.GITHUB_TOKEN }}
|
|
ref: ${{ env.COMMIT }}
|
|
|
|
- name: Start containerized dependencies
|
|
if: ${{ toJson(matrix.containers) != '[]' && (inputs.run_single_functional_test != true || (inputs.run_single_functional_test == true && contains(fromJSON(needs.set-up-single-test.outputs.dbs), env.PERSISTENCE_DRIVER))) }}
|
|
uses: hoverkraft-tech/compose-action@v2.0.1
|
|
with:
|
|
compose-file: ${{ env.DOCKER_COMPOSE_FILE }}
|
|
services: "${{ join(matrix.containers, '\n') }}"
|
|
down-flags: -v
|
|
|
|
- uses: actions/setup-go@v6
|
|
if: ${{ inputs.run_single_functional_test != true || (inputs.run_single_functional_test == true && contains(fromJSON(needs.set-up-single-test.outputs.dbs), env.PERSISTENCE_DRIVER)) }}
|
|
with:
|
|
go-version-file: "go.mod"
|
|
cache: false # do our own caching
|
|
|
|
- name: Restore dependencies
|
|
uses: actions/cache/restore@v4
|
|
with:
|
|
path: ~/go/pkg/mod
|
|
key: go-${{ runner.os }}${{ runner.arch }}-${{ hashFiles('go.mod') }}-deps-${{ hashFiles('go.sum') }}
|
|
|
|
- name: Restore build outputs
|
|
uses: actions/cache/restore@v4
|
|
with:
|
|
path: ~/.cache/go-build
|
|
key: go-${{ runner.os }}${{ runner.arch }}-build-${{ env.COMMIT }}
|
|
|
|
- name: Get job ID
|
|
if: ${{ inputs.run_single_functional_test != true || (inputs.run_single_functional_test == true && contains(fromJSON(needs.set-up-single-test.outputs.dbs), env.PERSISTENCE_DRIVER)) }}
|
|
id: get_job_id
|
|
uses: ./.github/actions/get-job-id
|
|
with:
|
|
job_name: Functional test (${{ matrix.name }}, shard ${{ matrix.shard_index }})
|
|
run_id: ${{ github.run_id }}
|
|
|
|
- name: Run functional test
|
|
if: ${{ inputs.run_single_functional_test != true || (inputs.run_single_functional_test == true && contains(fromJSON(needs.set-up-single-test.outputs.dbs), env.PERSISTENCE_DRIVER)) }}
|
|
timeout-minutes: ${{ fromJSON(needs.set-up-single-test.outputs.github_timeout) }} # make sure this is larger than the test timeout in the Makefile
|
|
run: ./develop/github/monitor_test.sh make functional-test-coverage
|
|
env:
|
|
TEST_ARGS: ${{ needs.set-up-single-test.outputs.single_test_args }}
|
|
TEMPORAL_TEST_OTEL_OUTPUT: ${{ github.workspace }}/.testoutput
|
|
TEMPORAL_OTEL_DEBUG: true
|
|
|
|
- name: Print memory snapshot
|
|
if: always()
|
|
run: if [ -f /tmp/memory_snapshot.txt ]; then cat /tmp/memory_snapshot.txt; fi
|
|
|
|
- name: Generate crash report
|
|
if: failure()
|
|
run:
|
|
| # if the tests failed, we would expect one JUnit XML report per attempt; otherwise it must have crashed
|
|
[ "$(find .testoutput -maxdepth 1 -name 'junit.*.xml' | wc -l)" -lt "$MAX_TEST_ATTEMPTS" ] &&
|
|
CRASH_REPORT_NAME="$GITHUB_JOB" make report-test-crash
|
|
|
|
- name: Generate test summary
|
|
uses: mikepenz/action-junit-report@v5.0.0-rc01
|
|
if: failure()
|
|
with:
|
|
report_paths: ./.testoutput/junit.*.xml
|
|
detailed_summary: true
|
|
check_annotations: false
|
|
annotate_only: true
|
|
skip_annotations: true
|
|
|
|
- name: Upload code coverage to Codecov
|
|
uses: codecov/codecov-action@v5
|
|
with:
|
|
token: ${{ secrets.CODECOV_TOKEN }}
|
|
directory: ./.testoutput
|
|
flags: functional-test
|
|
|
|
- name: Upload test results to Codecov
|
|
if: ${{ !cancelled() }}
|
|
uses: codecov/test-results-action@v1
|
|
with:
|
|
token: ${{ secrets.CODECOV_TOKEN }}
|
|
directory: ./.testoutput
|
|
flags: functional-test
|
|
|
|
- name: Upload test results to GitHub
|
|
# Can't pin to major because the action linter doesn't recognize the include-hidden-files flag.
|
|
uses: actions/upload-artifact@v4.4.3
|
|
if: ${{ !cancelled() && !inputs.run_single_functional_test }}
|
|
with:
|
|
name: junit-xml--${{github.run_id}}--${{ steps.get_job_id.outputs.job_id }}--${{github.run_attempt}}--${{matrix.name}}--${{matrix.shard_index}}--functional-test
|
|
path: ./.testoutput/junit.*.xml
|
|
include-hidden-files: true
|
|
retention-days: 28
|
|
|
|
# Ensure this doesn't contribute to the junit output.
|
|
- name: Flaky Functional Test Detection
|
|
if: ${{ (env.MODIFIED_TEST_SUITES != '') && (inputs.run_single_functional_test != true || (inputs.run_single_functional_test == true && contains(fromJSON(needs.set-up-single-test.outputs.dbs), env.PERSISTENCE_DRIVER))) }}
|
|
timeout-minutes: ${{ fromJSON(needs.set-up-single-test.outputs.github_timeout) }} # make sure this is larger than the test timeout in the Makefile
|
|
run: |
|
|
echo "Detecting flaky functional tests: ${{ needs.set-up-single-test.outputs.modified_integration_test_suites }}"
|
|
make functional-test-coverage
|
|
env:
|
|
FAILED_TEST_RETRIES: "0" # not retrying failed tests intentionally here since we're trying to detect flakes
|
|
TEST_ARGS: "-run=${{ needs.set-up-single-test.outputs.modified_functional_test_suites }} -count=5"
|
|
|
|
# Upload OpenTelemetry traces.
|
|
- name: Upload OpenTelemetry traces
|
|
if: always()
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: traces-json--${{github.run_id}}--${{ steps.get_job_id.outputs.job_id }}--${{matrix.shard_index}}--${{github.run_attempt}}--${{matrix.name}}--functional-test
|
|
path: ./.testoutput/traces.*.json
|
|
if-no-files-found: ignore
|
|
include-hidden-files: true
|
|
retention-days: 28
|
|
|
|
# XDC matrix job. Include `${{ matrix.name }}` in the display name so each
|
|
# matrix variant has a unique name for the job-id lookup.
|
|
functional-test-xdc:
|
|
if: ${{ inputs.run_single_functional_test != true && inputs.run_single_unit_test != true }}
|
|
# Display name shown in the UI. The job-id lookup uses this exact value.
|
|
name: Functional test xdc (${{ matrix.name }})
|
|
needs: [pre-build, set-up-single-test]
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
name:
|
|
- cass_es
|
|
- cass_es8
|
|
- cass_os2
|
|
- cass_os3
|
|
- mysql8
|
|
- postgres12
|
|
- postgres12_pgx
|
|
include:
|
|
- name: cass_es
|
|
persistence_type: nosql
|
|
persistence_driver: elasticsearch
|
|
parallel_flags: ""
|
|
containers: [cassandra, elasticsearch]
|
|
# Cassandra tests need a larger instance
|
|
runs_on_override: ubuntu-latest-8-cores
|
|
- name: cass_es8
|
|
persistence_type: nosql
|
|
persistence_driver: elasticsearch
|
|
parallel_flags: ""
|
|
containers: [cassandra, elasticsearch8]
|
|
# Cassandra tests need a larger instance
|
|
runs_on_override: ubuntu-latest-8-cores
|
|
- name: cass_os2
|
|
persistence_type: nosql
|
|
persistence_driver: cassandra
|
|
containers: [cassandra, opensearch2]
|
|
- name: cass_os3
|
|
persistence_type: nosql
|
|
persistence_driver: cassandra
|
|
containers: [cassandra, opensearch3]
|
|
- name: mysql8
|
|
persistence_type: sql
|
|
persistence_driver: mysql8
|
|
parallel_flags: ""
|
|
containers: [mysql]
|
|
- name: postgres12
|
|
persistence_type: sql
|
|
persistence_driver: postgres12
|
|
parallel_flags: "-parallel=2" # reduce parallelism for postgres
|
|
containers: [postgresql]
|
|
- name: postgres12_pgx
|
|
persistence_type: sql
|
|
persistence_driver: postgres12_pgx
|
|
parallel_flags: "-parallel=2" # reduce parallelism for postgres
|
|
containers: [postgresql]
|
|
runs-on: ${{ matrix.runs_on_override || 'ubuntu-latest' }}
|
|
env:
|
|
PERSISTENCE_TYPE: ${{ matrix.persistence_type }}
|
|
PERSISTENCE_DRIVER: ${{ matrix.persistence_driver }}
|
|
TEST_PARALLEL_FLAGS: ${{ matrix.parallel_flags }}
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
with:
|
|
token: ${{ secrets.GITHUB_TOKEN }}
|
|
ref: ${{ env.COMMIT }}
|
|
# Resolve the numeric job ID for this job instance.
|
|
# IMPORTANT: `job_name` must exactly match the job's display name above.
|
|
- name: Get job ID
|
|
id: get_job_id
|
|
uses: ./.github/actions/get-job-id
|
|
with:
|
|
job_name: Functional test xdc (${{ matrix.name }})
|
|
run_id: ${{ github.run_id }}
|
|
|
|
- name: Start containerized dependencies
|
|
uses: hoverkraft-tech/compose-action@v2.0.1
|
|
with:
|
|
compose-file: ${{ env.DOCKER_COMPOSE_FILE }}
|
|
services: "${{ join(matrix.containers, '\n') }}"
|
|
down-flags: -v
|
|
|
|
- uses: actions/setup-go@v6
|
|
with:
|
|
go-version-file: "go.mod"
|
|
cache: false # do our own caching
|
|
|
|
- name: Restore dependencies
|
|
uses: actions/cache/restore@v4
|
|
with:
|
|
path: ~/go/pkg/mod
|
|
key: go-${{ runner.os }}${{ runner.arch }}-${{ hashFiles('go.mod') }}-deps-${{ hashFiles('go.sum') }}
|
|
|
|
- name: Restore build outputs
|
|
uses: actions/cache/restore@v4
|
|
with:
|
|
path: ~/.cache/go-build
|
|
key: go-${{ runner.os }}${{ runner.arch }}-build-${{ env.COMMIT }}
|
|
|
|
- name: Run functional test xdc
|
|
timeout-minutes: 35 # update this to TEST_TIMEOUT+5 if you update the Makefile
|
|
run: ./develop/github/monitor_test.sh make functional-test-xdc-coverage
|
|
env:
|
|
TEMPORAL_TEST_OTEL_OUTPUT: ${{ github.workspace }}/.testoutput
|
|
TEMPORAL_OTEL_DEBUG: true
|
|
|
|
- name: Print memory snapshot
|
|
if: always()
|
|
run: if [ -f /tmp/memory_snapshot.txt ]; then cat /tmp/memory_snapshot.txt; fi
|
|
|
|
- name: Generate crash report
|
|
if: failure()
|
|
run:
|
|
| # if the tests failed, we would expect one JUnit XML report per attempt; otherwise it must have crashed
|
|
[ "$(find .testoutput -maxdepth 1 -name 'junit.*.xml' | wc -l)" -lt "$MAX_TEST_ATTEMPTS" ] &&
|
|
CRASH_REPORT_NAME="$GITHUB_JOB" make report-test-crash
|
|
|
|
- name: Generate test summary
|
|
uses: mikepenz/action-junit-report@v5.0.0-rc01
|
|
if: failure()
|
|
with:
|
|
report_paths: ./.testoutput/junit.*.xml
|
|
detailed_summary: true
|
|
check_annotations: false
|
|
annotate_only: true
|
|
skip_annotations: true
|
|
|
|
- name: Upload code coverage to Codecov
|
|
uses: codecov/codecov-action@v5
|
|
with:
|
|
token: ${{ secrets.CODECOV_TOKEN }}
|
|
directory: ./.testoutput
|
|
flags: functional-test-xdc
|
|
|
|
- name: Upload test results to Codecov
|
|
if: ${{ !cancelled() }}
|
|
uses: codecov/test-results-action@v1
|
|
with:
|
|
token: ${{ secrets.CODECOV_TOKEN }}
|
|
directory: ./.testoutput
|
|
flags: functional-test-xdc
|
|
|
|
- name: Upload test results to GitHub
|
|
# Can't pin to major because the action linter doesn't recognize the include-hidden-files flag.
|
|
uses: actions/upload-artifact@v4.4.3
|
|
if: ${{ !cancelled() }}
|
|
with:
|
|
name: junit-xml--${{github.run_id}}--${{ steps.get_job_id.outputs.job_id }}--${{github.run_attempt}}--${{matrix.name}}--functional-test-xdc
|
|
path: ./.testoutput
|
|
include-hidden-files: true
|
|
retention-days: 28
|
|
|
|
# Ensure this doesn't contribute to the junit output.
|
|
- name: Flaky Functional XDC Test Detection
|
|
if: ${{ env.MODIFIED_TEST_SUITES != '' }}
|
|
timeout-minutes: 60
|
|
run: |
|
|
echo "Detecting flaky functional xdc tests: ${{ needs.set-up-single-test.outputs.modified_functional_xdc_test_suites }}"
|
|
make functional-test-xdc-coverage
|
|
env:
|
|
FAILED_TEST_RETRIES: "0" # not retrying failed tests intentionally here since we're trying to detect flakes
|
|
TEST_ARGS: "-run=${{ needs.set-up-single-test.outputs.modified_functional_xdc_test_suites }} -count=5"
|
|
|
|
# Upload OpenTelemetry traces.
|
|
- name: Upload OpenTelemetry traces
|
|
if: always()
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: traces-json--${{github.run_id}}--${{ steps.get_job_id.outputs.job_id }}--${{github.run_attempt}}--${{matrix.name}}--functional-test-xdc
|
|
path: ./.testoutput/traces.*.json
|
|
if-no-files-found: ignore
|
|
retention-days: 28
|
|
|
|
# NDC matrix job. Include `${{ matrix.name }}` in the display name so each
|
|
# matrix variant has a unique name for the job-id lookup.
|
|
functional-test-ndc:
|
|
if: ${{ inputs.run_single_functional_test != true && inputs.run_single_unit_test != true }}
|
|
# Display name shown in the UI. The job-id lookup uses this exact value.
|
|
name: Functional test ndc (${{ matrix.name }})
|
|
needs: [pre-build, set-up-single-test]
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
name:
|
|
- cass_es
|
|
- cass_es8
|
|
- cass_os2
|
|
- cass_os3
|
|
- mysql8
|
|
- postgres12
|
|
- postgres12_pgx
|
|
include:
|
|
- name: cass_es
|
|
persistence_type: nosql
|
|
persistence_driver: elasticsearch
|
|
containers: [cassandra, elasticsearch]
|
|
es_version: v7
|
|
# Cassandra tests need a larger instance
|
|
runs_on_override: ubuntu-latest-8-cores
|
|
- name: cass_es8
|
|
persistence_type: nosql
|
|
persistence_driver: elasticsearch
|
|
containers: [cassandra, elasticsearch8]
|
|
es_version: v8
|
|
# Cassandra tests need a larger instance
|
|
runs_on_override: ubuntu-latest-8-cores
|
|
- name: cass_os2
|
|
persistence_type: nosql
|
|
persistence_driver: cassandra
|
|
containers: [cassandra, opensearch2]
|
|
- name: cass_os3
|
|
persistence_type: nosql
|
|
persistence_driver: cassandra
|
|
containers: [cassandra, opensearch3]
|
|
- name: mysql8
|
|
persistence_type: sql
|
|
persistence_driver: mysql8
|
|
containers: [mysql]
|
|
- name: postgres12
|
|
persistence_type: sql
|
|
persistence_driver: postgres12
|
|
containers: [postgresql]
|
|
- name: postgres12_pgx
|
|
persistence_type: sql
|
|
persistence_driver: postgres12_pgx
|
|
containers: [postgresql]
|
|
runs-on: ${{ matrix.runs_on_override || 'ubuntu-latest' }}
|
|
env:
|
|
PERSISTENCE_TYPE: ${{ matrix.persistence_type }}
|
|
PERSISTENCE_DRIVER: ${{ matrix.persistence_driver }}
|
|
ES_VERSION: ${{ matrix.es_version }}
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
with:
|
|
token: ${{ secrets.GITHUB_TOKEN }}
|
|
ref: ${{ env.COMMIT }}
|
|
# Resolve the numeric job ID for this job instance.
|
|
# IMPORTANT: `job_name` must exactly match the job's display name above.
|
|
- name: Get job ID
|
|
id: get_job_id
|
|
uses: ./.github/actions/get-job-id
|
|
with:
|
|
job_name: Functional test ndc (${{ matrix.name }})
|
|
run_id: ${{ github.run_id }}
|
|
|
|
- name: Start containerized dependencies
|
|
uses: hoverkraft-tech/compose-action@v2.0.1
|
|
with:
|
|
compose-file: ${{ env.DOCKER_COMPOSE_FILE }}
|
|
services: "${{ join(matrix.containers, '\n') }}"
|
|
down-flags: -v
|
|
|
|
- uses: actions/setup-go@v6
|
|
with:
|
|
go-version-file: "go.mod"
|
|
cache: false # do our own caching
|
|
|
|
- name: Restore dependencies
|
|
uses: actions/cache/restore@v4
|
|
with:
|
|
path: ~/go/pkg/mod
|
|
key: go-${{ runner.os }}${{ runner.arch }}-${{ hashFiles('go.mod') }}-deps-${{ hashFiles('go.sum') }}
|
|
|
|
- name: Restore build outputs
|
|
uses: actions/cache/restore@v4
|
|
with:
|
|
path: ~/.cache/go-build
|
|
key: go-${{ runner.os }}${{ runner.arch }}-build-${{ env.COMMIT }}
|
|
|
|
- name: Run functional test ndc
|
|
timeout-minutes: 15
|
|
run: ./develop/github/monitor_test.sh make functional-test-ndc-coverage
|
|
env:
|
|
TEMPORAL_TEST_OTEL_OUTPUT: ${{ github.workspace }}/.testoutput
|
|
TEMPORAL_OTEL_DEBUG: true
|
|
|
|
- name: Print memory snapshot
|
|
if: always()
|
|
run: if [ -f /tmp/memory_snapshot.txt ]; then cat /tmp/memory_snapshot.txt; fi
|
|
|
|
- name: Generate crash report
|
|
if: failure()
|
|
run:
|
|
| # if the tests failed, we would expect one JUnit XML report per attempt; otherwise it must have crashed
|
|
[ "$(find .testoutput -maxdepth 1 -name 'junit.*.xml' | wc -l)" -lt "$MAX_TEST_ATTEMPTS" ] &&
|
|
CRASH_REPORT_NAME="$GITHUB_JOB" make report-test-crash
|
|
|
|
- name: Upload code coverage to Codecov
|
|
uses: codecov/codecov-action@v5
|
|
with:
|
|
token: ${{ secrets.CODECOV_TOKEN }}
|
|
directory: ./.testoutput
|
|
flags: functional-test-ndc
|
|
|
|
- name: Upload test results to Codecov
|
|
if: ${{ !cancelled() }}
|
|
uses: codecov/test-results-action@v1
|
|
with:
|
|
token: ${{ secrets.CODECOV_TOKEN }}
|
|
directory: ./.testoutput
|
|
flags: functional-test-ndc
|
|
|
|
- name: Upload test results to GitHub
|
|
# Can't pin to major because the action linter doesn't recognize the include-hidden-files flag.
|
|
uses: actions/upload-artifact@v4.4.3
|
|
if: ${{ !cancelled() }}
|
|
with:
|
|
name: junit-xml--${{github.run_id}}--${{ steps.get_job_id.outputs.job_id }}--${{github.run_attempt}}--${{matrix.name}}--functional-test-ndc
|
|
path: ./.testoutput/junit.*.xml
|
|
include-hidden-files: true
|
|
retention-days: 28
|
|
|
|
# Ensure this doesn't contribute to the junit output.
|
|
- name: Flaky Functional NDC Test Detection
|
|
if: ${{ env.MODIFIED_TEST_SUITES != '' }}
|
|
timeout-minutes: 30
|
|
run: |
|
|
echo "Detecting flaky functional ndc tests: ${{ needs.set-up-single-test.outputs.modified_functional_ndc_test_suites }}"
|
|
make functional-test-ndc-coverage
|
|
env:
|
|
FAILED_TEST_RETRIES: "0" # not retrying failed tests intentionally here since we're trying to detect flakes
|
|
TEST_ARGS: "-run=${{ needs.set-up-single-test.outputs.modified_functional_ndc_test_suites }} -count=5"
|
|
|
|
# Upload OpenTelemetry traces.
|
|
- name: Upload OpenTelemetry traces
|
|
if: always()
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: traces-json--${{github.run_id}}--${{ steps.get_job_id.outputs.job_id }}--${{github.run_attempt}}--${{matrix.name}}--functional-test-ndc
|
|
path: ./.testoutput/traces.*.json
|
|
if-no-files-found: ignore
|
|
retention-days: 28
|
|
|
|
test-status:
|
|
if: always()
|
|
name: Test Status
|
|
needs:
|
|
- misc-checks
|
|
- unit-test
|
|
- integration-test
|
|
- functional-test
|
|
- functional-test-xdc
|
|
- functional-test-ndc
|
|
runs-on: ubuntu-latest
|
|
env:
|
|
RESULTS: ${{ toJSON(needs.*.result) }}
|
|
steps:
|
|
- name: Check results
|
|
run: |
|
|
if [[ "${{ inputs.run_single_functional_test }}" != "true" ]]; then
|
|
# if in all-tests mode, all statuses must be success
|
|
if [[ -n $(echo "$RESULTS" | jq '.[] | select (. != "success")') ]]; then
|
|
exit 1
|
|
fi
|
|
else
|
|
# if in single-test mode, skipped status is ok, failure is failure
|
|
if [[ -n $(echo "$RESULTS" | jq '.[] | select (. == "failure")') ]]; then
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
notify-failure:
|
|
name: Notify Slack on Failure
|
|
if: |
|
|
always() &&
|
|
github.ref == 'refs/heads/main' &&
|
|
needs.test-status.result == 'failure'
|
|
needs: test-status
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
contents: read
|
|
actions: read
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Set up Go
|
|
uses: actions/setup-go@v5
|
|
with:
|
|
go-version-file: "go.mod"
|
|
cache: true
|
|
|
|
- name: Send Slack notification
|
|
env:
|
|
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
|
|
GH_TOKEN: ${{ github.token }}
|
|
run: |
|
|
go run ./cmd/tools/ci-notify \
|
|
--run-id "${{ github.run_id }}" \
|
|
--slack-webhook "$SLACK_WEBHOOK"
|