action.yml 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. name: Run tests (ya make)
  2. description: Run tests using ya make
  3. inputs:
  4. build_target:
  5. required: false
  6. description: "build target"
  7. build_preset:
  8. required: true
  9. default: "relwithdebinfo"
  10. description: "relwithdebinfo, release-asan, release-tsan"
  11. test_size:
  12. required: false
  13. default: "small,medium,large"
  14. description: "small or small-medium or all"
  15. test_type:
  16. required: false
  17. default: "unittest,py3test,py2test,pytest"
  18. description: "run "
  19. test_threads:
  20. required: false
  21. default: "28"
  22. description: "Test threads count"
  23. link_threads:
  24. required: false
  25. default: "8"
  26. description: "link threads count"
  27. testman_token:
  28. required: false
  29. description: "test manager auth token"
  30. testman_url:
  31. required: false
  32. description: "test manager endpoint"
  33. testman_project_id:
  34. required: false
  35. description: "test manager project id"
  36. bazel_remote_uri:
  37. required: false
  38. description: "bazel-remote endpoint"
  39. bazel_remote_username:
  40. required: false
  41. description: "bazel-remote username"
  42. bazel_remote_password:
  43. required: false
  44. description: "bazel-remote password"
  45. runs:
  46. using: "composite"
  47. steps:
  48. - name: Init
  49. id: init
  50. shell: bash
  51. run: |
  52. echo "SHELLOPTS=xtrace" >> $GITHUB_ENV
  53. export TMP_DIR=$(pwd)/tmp
  54. echo "TMP_DIR=$TMP_DIR" >> $GITHUB_ENV
  55. echo "LOG_DIR=$TMP_DIR/logs" >> $GITHUB_ENV
  56. echo "OUT_DIR=$TMP_DIR/out" >> $GITHUB_ENV
  57. echo "ARTIFACTS_DIR=$TMP_DIR/artifacts" >> $GITHUB_ENV
  58. echo "REPORTS_ARTIFACTS_DIR=$TMP_DIR/artifacts/test_reports" >> $GITHUB_ENV
  59. echo "JUNIT_REPORT_XML=$TMP_DIR/junit.xml" >> $GITHUB_ENV
  60. echo "JUNIT_REPORT_PARTS=$TMP_DIR/junit-split" >> $GITHUB_ENV
  61. echo "TESTMO_TOKEN=${{ inputs.testman_token }}" >> $GITHUB_ENV
  62. echo "TESTMO_URL=${{ inputs.testman_url }}" >> $GITHUB_ENV
  63. echo "SUMMARY_LINKS=$(mktemp)" >> $GITHUB_ENV
  64. echo "GITHUB_TOKEN=${{ github.token }}" >> $GITHUB_ENV
  65. echo "BUILD_PRESET=${{ inputs.build_preset }}" >> $GITHUB_ENV
  66. - name: prepare
  67. shell: bash
  68. run: |
  69. rm -rf $TMP_DIR $JUNIT_REPORT_XML $JUNIT_REPORT_PARTS $REPORTS_ARTIFACTS_DIR
  70. mkdir -p $TMP_DIR $OUT_DIR $ARTIFACTS_DIR $LOG_DIR $JUNIT_REPORT_PARTS $REPORTS_ARTIFACTS_DIR
  71. - name: Install Node required for Testmo CLI
  72. uses: actions/setup-node@v3
  73. with:
  74. node-version: 19
  75. - name: Install Testmo CLI
  76. shell: bash
  77. run: npm install -g @testmo/testmo-cli
  78. - name: Upload tests result to testmo
  79. id: th
  80. if: inputs.testman_token
  81. shell: bash
  82. env:
  83. PR_NUMBER: ${{ github.event.number }}
  84. run: |
  85. RUN_URL="$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID"
  86. BRANCH_TAG="$GITHUB_REF_NAME"
  87. ARCH="${{ runner.arch == 'X64' && 'x86-64' || runner.arch == 'ARM64' && 'arm64' || 'unknown' }}"
  88. case "$BUILD_PRESET" in
  89. relwithdebinfo)
  90. TESTMO_SOURCE="ya-${ARCH}"
  91. ;;
  92. debug)
  93. TESTMO_SOURCE="ya-${ARCH}-debug"
  94. ;;
  95. release-*)
  96. TESTMO_SOURCE="ya-${ARCH}-${BUILD_PRESET/release-/}"
  97. ;;
  98. *)
  99. echo "Invalid preset: $BUILD_PRESET"
  100. exit 1
  101. ;;
  102. esac
  103. case $GITHUB_EVENT_NAME in
  104. workflow_dispatch)
  105. TESTMO_RUN_NAME="${{ github.run_id }} manual"
  106. EXTRA_TAG="manual"
  107. ;;
  108. pull_request | pull_request_target)
  109. TESTMO_RUN_NAME="${{ github.run_id }} PR #${PR_NUMBER}"
  110. EXTRA_TAG="pr"
  111. BRANCH_TAG=""
  112. ;;
  113. schedule)
  114. TESTMO_RUN_NAME="${{ github.run_id }} schedule"
  115. EXTRA_TAG="schedule"
  116. ;;
  117. push)
  118. TESTMO_RUN_NAME="${{ github.run_id }} POST"
  119. EXTRA_TAG="post-commit"
  120. ;;
  121. *)
  122. TESTMO_RUN_NAME="${{ github.run_id }}"
  123. EXTRA_TAG=""
  124. ;;
  125. esac
  126. testmo automation:resources:add-link --name build --url "$RUN_URL" --resources testmo.json
  127. testmo automation:resources:add-field --name git-sha --type string --value "${GITHUB_SHA:0:7}" --resources testmo.json
  128. RUN_ID=$(
  129. testmo automation:run:create --instance "$TESTMO_URL" --project-id ${{ inputs.testman_project_id }} \
  130. --name "$TESTMO_RUN_NAME" --source "$TESTMO_SOURCE" --resources testmo.json \
  131. --tags "$BRANCH_TAG" --tags "$EXTRA_TAG"
  132. )
  133. echo "runid=${RUN_ID}" >> $GITHUB_OUTPUT
  134. echo "TEST_HISTORY_URL=${TESTMO_URL}/automation/runs/view/${RUN_ID}" >> $GITHUB_ENV
  135. - name: Print test history link
  136. shell: bash
  137. if: inputs.testman_token
  138. run: |
  139. echo "10 [Test history](${TEST_HISTORY_URL})" >> $SUMMARY_LINKS
  140. - name: set environment variables required by some tests
  141. shell: bash
  142. run: |
  143. echo "PSQL_BINARY=/usr/bin/psql" >> $GITHUB_ENV
  144. - name: ya test
  145. shell: bash
  146. run: |
  147. readarray -d ',' -t test_size < <(printf "%s" "${{ inputs.test_size }}")
  148. readarray -d ',' -t test_type < <(printf "%s" "${{ inputs.test_type }}")
  149. params=(
  150. -T -k -D'BUILD_LANGUAGES=CPP PY3 PY2 GO'
  151. ${test_size[@]/#/--test-size=} ${test_type[@]/#/--test-type=}
  152. --cache-size 512G --do-not-output-stderrs
  153. --stat --canonization-backend=ydb-canondata.storage.yandexcloud.net
  154. --test-threads "${{ inputs.test_threads }}" --link-threads "${{ inputs.link_threads }}"
  155. )
  156. # FIXME: copy-paste from build_ya
  157. case "$BUILD_PRESET" in
  158. debug)
  159. params+=(--build "debug")
  160. ;;
  161. relwithdebinfo)
  162. params+=(--build "relwithdebinfo")
  163. ;;
  164. release-asan)
  165. params+=(
  166. --build "release" --sanitize="address"
  167. -DSKIP_JUNK -DUSE_EAT_MY_DATA -DDEBUGINFO_LINES_ONLY
  168. )
  169. ;;
  170. release-tsan)
  171. params+=(
  172. --build "release" --sanitize="thread"
  173. -DSKIP_JUNK -DUSE_EAT_MY_DATA -DDEBUGINFO_LINES_ONLY
  174. )
  175. ;;
  176. release-msan)
  177. params+=(
  178. --build "release" --sanitize="memory"
  179. -DSKIP_JUNK -DUSE_EAT_MY_DATA -DDEBUGINFO_LINES_ONLY
  180. )
  181. ;;
  182. *)
  183. echo "Invalid preset: $BUILD_PRESET"
  184. exit 1
  185. ;;
  186. esac
  187. if [ ! -z "${{ inputs.build_target }}" ]; then
  188. params+=(--target="${{ inputs.build_target }}")
  189. fi
  190. if [ ! -z "${{ inputs.bazel_remote_uri }}" ]; then
  191. params+=(--bazel-remote-store)
  192. params+=(--bazel-remote-base-uri "${{ inputs.bazel_remote_uri }}")
  193. fi
  194. echo "::debug::get version"
  195. ./ya --version
  196. echo "Tests are running..." | .github/scripts/tests/comment-pr.py
  197. if [ ! -z "${{ inputs.bazel_remote_username }}" ]; then
  198. echo "::debug::start tests"
  199. ./ya test "${params[@]}" \
  200. --bazel-remote-put --bazel-remote-username "${{ inputs.bazel_remote_username }}" --bazel-remote-password "${{ inputs.bazel_remote_password }}" -DCONSISTENT_DEBUG \
  201. --log-file "$LOG_DIR/ya_log_prewarm.txt" --evlog-file "$LOG_DIR/ya_evlog_prewarm.jsonl" \
  202. --dist-cache-evict-bins --cache-tests --no-dir-outputs --test-node-output-limit 100000 --drop-graph-result-before-tests || (
  203. RC=$?
  204. echo "::debug::ya test RC=$RC"
  205. )
  206. fi
  207. echo "::debug::save tests reports"
  208. ./ya test "${params[@]}" \
  209. --stat --log-file "$LOG_DIR/ya_log.txt" --evlog-file "$LOG_DIR/ya_evlog.jsonl" -DCONSISTENT_DEBUG \
  210. --cache-tests --dist-cache-evict-bins --no-dir-outputs --test-node-output-limit 100000 --drop-graph-result-before-tests \
  211. --junit "$JUNIT_REPORT_XML" --output "$OUT_DIR" || (
  212. RC=$?
  213. if [ $RC -ne 0 ]; then
  214. echo "ya test returned $RC, check existence $JUNIT_REPORT_XML"
  215. if [ -s "$JUNIT_REPORT_XML" ]; then
  216. echo "$JUNIT_REPORT_XML exists"
  217. ls -la "$JUNIT_REPORT_XML"
  218. else
  219. echo "$JUNIT_REPORT_XML doesn't exist or has zero size"
  220. ls -la "$JUNIT_REPORT_XML" || true
  221. exit $RC
  222. fi
  223. fi
  224. )
  225. - name: archive unitest reports (orig)
  226. shell: bash
  227. run: |
  228. gzip -c $JUNIT_REPORT_XML > $REPORTS_ARTIFACTS_DIR/orig_junit.xml.gz
  229. - name: postprocess junit report
  230. shell: bash
  231. run: |
  232. .github/scripts/tests/transform-ya-junit.py -i \
  233. -m .github/config/muted_ya.txt \
  234. --ya-out "$OUT_DIR" \
  235. --log-url-prefix "$S3_URL_PREFIX/logs/" \
  236. --log-out-dir "$ARTIFACTS_DIR/logs/" \
  237. "$JUNIT_REPORT_XML"
  238. .github/scripts/tests/split-junit.py -o "$JUNIT_REPORT_PARTS" "$JUNIT_REPORT_XML"
  239. - name: archive unitest reports (transformed)
  240. shell: bash
  241. run: |
  242. tar -C $JUNIT_REPORT_PARTS/.. -czf $REPORTS_ARTIFACTS_DIR/junit_parts.xml.tar.gz $(basename $JUNIT_REPORT_PARTS)
  243. - name: Unit test history upload results
  244. if: inputs.testman_token
  245. shell: bash
  246. run: |
  247. PROXY_ADDR=127.0.0.1:8888
  248. openssl req -x509 -newkey rsa:2048 \
  249. -keyout $TMP_DIR/key.pem -out $TMP_DIR/cert.pem \
  250. -sha256 -days 1 -nodes -subj "/CN=127.0.0.1"
  251. ./ydb/ci/testmo-proxy/testmo-proxy.py -l $PROXY_ADDR \
  252. --cert-file "$TMP_DIR/cert.pem" \
  253. --cert-key "$TMP_DIR/key.pem" \
  254. --target-timeout 3,10 \
  255. --max-request-time 55 \
  256. "$TESTMO_URL" &
  257. proxy_pid=$!
  258. NODE_TLS_REJECT_UNAUTHORIZED=0 testmo automation:run:submit-thread \
  259. --instance "https://$PROXY_ADDR" --run-id "${{ steps.th.outputs.runid }}" \
  260. --results "$JUNIT_REPORT_PARTS/*.xml"
  261. kill $proxy_pid
  262. - name: Test history run complete
  263. if: always() && inputs.testman_token
  264. shell: bash
  265. run: |
  266. testmo automation:run:complete --instance "$TESTMO_URL" --run-id ${{ steps.th.outputs.runid }}
  267. - name: write tests summary
  268. shell: bash
  269. if: always()
  270. run: |
  271. mkdir $ARTIFACTS_DIR/summary/
  272. cat $SUMMARY_LINKS | python3 -c 'import sys; print(" | ".join([v for _, v in sorted([l.strip().split(" ", 1) for l in sys.stdin], key=lambda a: (int(a[0]), a))]))' >> $GITHUB_STEP_SUMMARY
  273. .github/scripts/tests/generate-summary.py \
  274. --summary-out-path $ARTIFACTS_DIR/summary/ \
  275. --summary-url-prefix $S3_URL_PREFIX/summary/ \
  276. --test-history-url $TEST_HISTORY_URL \
  277. --build-preset "$BUILD_PRESET" \
  278. "Tests" ya-test.html "$JUNIT_REPORT_XML"
  279. - name: sync test results to s3
  280. if: always()
  281. shell: bash
  282. run: |
  283. echo "::group::s3-sync"
  284. s3cmd sync -r --follow-symlinks --acl-public --no-progress --stats --no-check-md5 "$ARTIFACTS_DIR/" "$S3_BUCKET_PATH/"
  285. echo "::endgroup::"
  286. - name: sync logs results to s3
  287. if: always()
  288. shell: bash
  289. run: |
  290. echo "::group::s3-sync"
  291. s3cmd sync --follow-symlinks --acl-private --no-progress --stats --no-check-md5 "$LOG_DIR/" "$S3_BUCKET_PATH/test_logs/"
  292. echo "::endgroup::"
  293. - name: check test results
  294. shell: bash
  295. run: |
  296. .github/scripts/tests/fail-checker.py "$JUNIT_REPORT_XML"
  297. - name: show free space
  298. if: always()
  299. shell: bash
  300. run: df -h