action.yml 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. name: build-and-test
  2. description: Build YDB and run Tests
  3. inputs:
  4. log_suffix:
  5. required: true
  6. type: string
  7. test_label_regexp:
  8. required: false
  9. type: string
  10. aws_key_id:
  11. required: true
  12. type: string
  13. aws_key_value:
  14. required: true
  15. type: string
  16. testman_token:
  17. required: false
  18. type: string
  19. testman_url:
  20. required: false
  21. type: string
  22. testman_project_id:
  23. required: false
  24. type: string
  25. aws_bucket:
  26. required: true
  27. type: string
  28. aws_endpoint:
  29. required: true
  30. type: string
  31. run_unit_tests:
  32. required: true
  33. type: string
  34. run_functional_tests:
  35. required: true
  36. type: string
  37. runs:
  38. using: "composite"
  39. steps:
  40. - name: Init
  41. id: init
  42. shell: bash
  43. run: |
  44. rm -rf artifacts tmp test_reports
  45. mkdir -p artifacts tmp/pytest test_reports/pytest
  46. echo "WORKDIR=$(pwd)" >> $GITHUB_ENV
  47. echo "TESTREPDIR=$(pwd)/test_reports" >> $GITHUB_ENV
  48. echo "TMPDIR=$(pwd)/tmp" >> $GITHUB_ENV
  49. echo "PYTESTREPDIR=$(pwd)/test_reports/pytest/" >> $GITHUB_ENV
  50. echo "TESTMO_TOKEN=${{inputs.testman_token}}" >> $GITHUB_ENV
  51. echo "TESTMO_URL=${{inputs.testman_url}}" >> $GITHUB_ENV
  52. echo "ARTIFACTS_DIR=$(pwd)/artifacts" >> $GITHUB_ENV
  53. echo "SUMMARY_LINKS=$(mktemp)" >> $GITHUB_ENV
  54. echo "logfilename=${{inputs.log_suffix}}-ctest-stdout.gz" >> $GITHUB_OUTPUT
  55. echo "testfilterfile=$(pwd)/.github/config/muted_test.txt" >> $GITHUB_OUTPUT
  56. echo "testshardfilterfile=$(pwd)/.github/config/muted_shard.txt" >> $GITHUB_OUTPUT
  57. echo "functestfilterfile=$(pwd)/.github/config/muted_functest.txt" >> $GITHUB_OUTPUT
  58. echo "pytest-logfilename=${{inputs.log_suffix}}-pytest-stdout.log" >> $GITHUB_OUTPUT
  59. echo "PORT_SYNC_PATH=$(mktemp -d -p $(pwd)/tmp port-sync-XXXXXX)" >> $GITHUB_ENV
  60. - name: configure s3cmd
  61. shell: bash
  62. run: |
  63. cat <<EOF > $TMPDIR/s3cfg
  64. [default]
  65. access_key = ${aws_key_id}
  66. secret_key = ${aws_secret_access_key}
  67. bucket_location = ru-central1
  68. host_base = storage.yandexcloud.net
  69. host_bucket = %(bucket)s.storage.yandexcloud.net
  70. EOF
  71. echo "S3CMD_CONFIG=$TMPDIR/s3cfg" >> $GITHUB_ENV
  72. echo "S3_BUCKET_PATH=s3://${{ inputs.aws_bucket }}/${{ github.repository }}/${{github.workflow}}/${{ github.run_id }}/${{inputs.log_suffix}}/" >> $GITHUB_ENV
  73. echo "S3_URL_PREFIX=${{inputs.aws_endpoint}}/${{inputs.aws_bucket}}/${{ github.repository }}/${{github.workflow}}/${{github.run_id}}/${{inputs.log_suffix}}" >> $GITHUB_ENV
  74. env:
  75. aws_key_id: ${{inputs.AWS_KEY_ID }}
  76. aws_secret_access_key: ${{inputs.AWS_KEY_VALUE}}
  77. - name: Install Node required for Testmo CLI
  78. uses: actions/setup-node@v3
  79. with:
  80. node-version: 19
  81. - name: Install Testmo CLI
  82. shell: bash
  83. run: npm install -g @testmo/testmo-cli
  84. - name: Test history run create
  85. id: th
  86. if: inputs.testman_token
  87. shell: bash
  88. env:
  89. PR_NUMBER: ${{ github.event.number }}
  90. run: |
  91. RUN_URL="$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID"
  92. BRANCH_TAG="$GITHUB_REF_NAME"
  93. ARCH="${{ runner.arch == 'X64' && 'x86-64' || runner.arch == 'ARM64' && 'arm64' || 'unknown' }}"
  94. LOG_SUFFIX="${{ inputs.log_suffix }}"
  95. TESTMO_SOURCE="cmake-${ARCH}"
  96. if [ ! -z "${LOG_SUFFIX}" ]; then
  97. TESTMO_SOURCE="${TESTMO_SOURCE}-${LOG_SUFFIX/_/-}"
  98. fi
  99. case $GITHUB_EVENT_NAME in
  100. workflow_dispatch)
  101. TESTMO_RUN_NAME="${{ github.run_id }} manual"
  102. EXTRA_TAG="manual"
  103. ;;
  104. pull_request | pull_request_target)
  105. TESTMO_RUN_NAME="${{ github.run_id }} PR #${PR_NUMBER}"
  106. EXTRA_TAG="pr"
  107. BRANCH_TAG=""
  108. ;;
  109. schedule)
  110. TESTMO_RUN_NAME="${{ github.run_id }} schedule"
  111. EXTRA_TAG="schedule"
  112. ;;
  113. *)
  114. TESTMO_RUN_NAME="${{ github.run_id }}"
  115. EXTRA_TAG=""
  116. ;;
  117. esac
  118. testmo automation:resources:add-link --name build --url $RUN_URL --resources testmo.json
  119. testmo automation:resources:add-field --name git-sha --type string --value ${GITHUB_SHA:0:7} --resources testmo.json
  120. RUN_ID=$(
  121. testmo automation:run:create --instance "$TESTMO_URL" --project-id ${{inputs.testman_project_id}} \
  122. --name "$TESTMO_RUN_NAME" --source "$TESTMO_SOURCE" --resources testmo.json \
  123. --tags "$BRANCH_TAG" --tags "$EXTRA_TAG"
  124. )
  125. echo "runid=${RUN_ID}" >> $GITHUB_OUTPUT
  126. echo "TEST_HISTORY_URL=${TESTMO_URL}/automation/runs/view/${RUN_ID}" >> $GITHUB_ENV
  127. - name: Print test history link
  128. shell: bash
  129. run: |
  130. echo "10 [Test history](${TEST_HISTORY_URL})" >> $SUMMARY_LINKS
  131. - name: set environment variables required by some tests
  132. shell: bash
  133. run: |
  134. echo "PSQL_BINARY=/usr/bin/psql" >> $GITHUB_ENV
  135. - name: Run unit tests
  136. id: ctest
  137. if: inputs.run_unit_tests == 'true'
  138. shell: bash
  139. run: |
  140. cd $WORKDIR/../build/ydb
  141. echo "20 [Unittest log]($S3_URL_PREFIX/${{steps.init.outputs.logfilename}})" >> $SUMMARY_LINKS
  142. # Sed removes coloring from the output
  143. GTEST_OUTPUT="xml:$TESTREPDIR/unittests/" Y_UNITTEST_OUTPUT="xml:$TESTREPDIR/unittests/" \
  144. ctest -j28 --timeout 1200 --force-new-ctest-process --output-on-failure \
  145. --output-junit $TESTREPDIR/suites/ctest_report.xml \
  146. -L '${{inputs.test_label_regexp}}' -E "${CTEST_SKIP_SHARDS:-}" | \
  147. sed -u -e 's/\x1b\[[0-9;]*m//g' | \
  148. tee >(gzip --stdout > $ARTIFACTS_DIR/${{steps.init.outputs.logfilename}}) | \
  149. grep --line-buffered -E '(Test\s*#.*\*\*\*|\[FAIL\])|.*tests passed,.*tests failed out of' | \
  150. tee $WORKDIR/short.log || (
  151. RC=$?
  152. if [ $RC == 8 ]; then
  153. echo "ctest returned TEST_ERRORS, recovering.."
  154. else
  155. exit $RC
  156. fi
  157. )
  158. - name: archive unitest reports (orig)
  159. if: inputs.run_unit_tests == 'true'
  160. shell: bash
  161. run: |
  162. tar -C $TESTREPDIR/ -czf $ARTIFACTS_DIR/xml_orig.tar.gz .
  163. - name: postprocess xml reports
  164. if: inputs.run_unit_tests == 'true'
  165. shell: bash
  166. run: |
  167. echo "::group::extract-logs"
  168. mkdir $ARTIFACTS_DIR/logs/
  169. .github/scripts/tests/attach-logs.py \
  170. --url-prefix $S3_URL_PREFIX/logs/ \
  171. --ctest-report $TESTREPDIR/suites/ctest_report.xml \
  172. --junit-reports-path $TESTREPDIR/unittests/ \
  173. --decompress \
  174. $ARTIFACTS_DIR/${{steps.init.outputs.logfilename}} \
  175. $ARTIFACTS_DIR/logs/
  176. echo "::endgroup::"
  177. echo "::group::junit-postprocess"
  178. .github/scripts/tests/junit-postprocess.py \
  179. --filter-file ${{steps.init.outputs.testfilterfile}} \
  180. $TESTREPDIR/unittests/
  181. echo "::endgroup::"
  182. echo "::group::ctest-postprocess"
  183. .github/scripts/tests/ctest-postprocess.py \
  184. --filter-file ${{steps.init.outputs.testshardfilterfile}} \
  185. --decompress \
  186. $ARTIFACTS_DIR/${{steps.init.outputs.logfilename}} \
  187. $TESTREPDIR/suites/ctest_report.xml
  188. tar -C $TESTREPDIR/ -czf $ARTIFACTS_DIR/reports.tar.gz .
  189. echo "90 [XML reports archive]($S3_URL_PREFIX/reports.tar.gz)" >> $SUMMARY_LINKS
  190. echo "::endgroup::"
  191. - name: sync test results to s3
  192. if: always() && inputs.run_unit_tests == 'true'
  193. shell: bash
  194. run: |
  195. echo "::group::s3-sync"
  196. s3cmd sync -P --no-progress --stats --no-check-md5 -P $ARTIFACTS_DIR/ $S3_BUCKET_PATH
  197. echo "::endgroup::"
  198. - name: Unit test history upload results
  199. if: always() && inputs.run_unit_tests == 'true' && inputs.testman_token
  200. shell: bash
  201. run: |
  202. testmo automation:run:submit-thread \
  203. --instance "$TESTMO_URL" --run-id ${{steps.th.outputs.runid}} \
  204. --results "$TESTREPDIR/unittests/*.xml"
  205. testmo automation:run:submit-thread \
  206. --exec-suppress \
  207. --instance "$TESTMO_URL" --run-id ${{steps.th.outputs.runid}} \
  208. --results "$TESTREPDIR/suites/*.xml" \
  209. -- cat $WORKDIR/short.log
  210. - name: Run functional tests
  211. if: inputs.run_functional_tests == 'true' && (success() || failure())
  212. shell: bash
  213. run: |
  214. export source_root=$WORKDIR
  215. export build_root=$WORKDIR/../build/
  216. echo "30 [Functional test log]($S3_URL_PREFIX/${{steps.init.outputs.pytest-logfilename}})" >> $SUMMARY_LINKS
  217. source $WORKDIR/ydb/tests/oss/launch/prepare.sh
  218. rm -rf $ARTIFACTS_DIR/pytest/
  219. mkdir $ARTIFACTS_DIR/pytest/
  220. cd $WORKDIR/ydb/tests/functional/
  221. pytest \
  222. -p xdist -n 24 --dist worksteal \
  223. --timeout_method signal \
  224. -o junit_logging=log -o junit_log_passing_tests=False --junit-xml=$PYTESTREPDIR/pytest.xml \
  225. -ra --tb=no --show-capture=no \
  226. --github-repo $GITHUB_REPOSITORY --github-ref $GITHUB_SHA \
  227. --source-root $source_root \
  228. --build-root $build_root \
  229. --output-dir $TMPDIR/pytest/ \
  230. . | tee $ARTIFACTS_DIR/${{steps.init.outputs.pytest-logfilename}} || {
  231. RC=$?
  232. if [ $RC == 1 ]; then
  233. echo "pytest: tests were collected and run but some of the tests failed"
  234. else
  235. exit $RC
  236. fi;
  237. }
  238. # --artifacts-dir $ARTIFACTS_DIR/pytest/ \
  239. # --artifacts-url $S3_URL_PREFIX/pytest/ \
  240. - name: postprocess functional test reports
  241. if: always() && inputs.run_functional_tests == 'true'
  242. shell: bash
  243. run: |
  244. echo "::group::junit-postprocess"
  245. # append orig pytest reports
  246. if [ -f "$ARTIFACTS_DIR/xml_orig.tar.gz" ]; then
  247. echo "add pytest to xml_orig.tar.gz"
  248. gzip -d $ARTIFACTS_DIR/xml_orig.tar.gz
  249. tar -C $TESTREPDIR/ -rvf $ARTIFACTS_DIR/xml_orig.tar pytest
  250. gzip -v $ARTIFACTS_DIR/xml_orig.tar
  251. fi
  252. .github/scripts/tests/pytest-postprocess.py \
  253. --filter-file ${{ steps.init.outputs.functestfilterfile }} \
  254. $PYTESTREPDIR/
  255. # make archive again with pytest reports
  256. tar -C $TESTREPDIR/ -czf $ARTIFACTS_DIR/reports.tar.gz .
  257. ls -la $ARTIFACTS_DIR/reports.tar.gz
  258. echo "::endgroup::"
  259. - name: Functional tests history upload results
  260. if: always() && inputs.run_functional_tests == 'true' && inputs.testman_token
  261. shell: bash
  262. run: |
  263. testmo automation:run:submit-thread \
  264. --instance "$TESTMO_URL" --run-id ${{steps.th.outputs.runid}} \
  265. --results "$PYTESTREPDIR/*.xml" \
  266. -- cat $ARTIFACTS_DIR/${{steps.init.outputs.pytest-logfilename}}
  267. - name: Test history run complete
  268. if: always() && inputs.testman_token
  269. shell: bash
  270. run: |
  271. testmo automation:run:complete --instance "$TESTMO_URL" --run-id ${{steps.th.outputs.runid}}
  272. - name: write tests summary
  273. if: always()
  274. shell: bash
  275. env:
  276. GITHUB_TOKEN: ${{ github.token }}
  277. run: |
  278. 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
  279. mkdir $ARTIFACTS_DIR/summary/
  280. .github/scripts/tests/generate-summary.py \
  281. --summary-out-path $ARTIFACTS_DIR/summary/ \
  282. --summary-url-prefix $S3_URL_PREFIX/summary/ \
  283. --test-history-url $TEST_HISTORY_URL \
  284. "Unittests" unittest.html $TESTREPDIR/unittests \
  285. "Unittest binary runs" ctest.html $TESTREPDIR/suites \
  286. "Functional tests" functional.html $PYTESTREPDIR
  287. - name: sync test results to s3
  288. if: always()
  289. shell: bash
  290. run: |
  291. echo "::group::s3-sync"
  292. s3cmd sync -P --no-progress --stats --no-check-md5 -P $ARTIFACTS_DIR/ $S3_BUCKET_PATH
  293. echo "::endgroup::"
  294. - name: finish
  295. shell: bash
  296. run: |
  297. .github/scripts/tests/fail-checker.py $TESTREPDIR/unittests/ $TESTREPDIR/suites/ $PYTESTREPDIR/