action.yml 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  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. mkdir -p artifacts tmp test_reports
  45. rm -rf artifacts/* tmp/* test_reports/*
  46. echo "WORKDIR=$(pwd)" >> $GITHUB_ENV
  47. echo "TESTREPDIR=$(pwd)/test_reports" >> $GITHUB_ENV
  48. echo "PYTESTREPDIR=$(pwd)/ydb/tests/functional/test-results/xml" >> $GITHUB_ENV
  49. echo "TESTMO_TOKEN=${{inputs.testman_token}}" >> $GITHUB_ENV
  50. echo "TESTMO_URL=${{inputs.testman_url}}" >> $GITHUB_ENV
  51. echo "ARTIFACTS_DIR=$(pwd)/artifacts" >> $GITHUB_ENV
  52. echo "logfilename=${{inputs.log_suffix}}-ctest-stdout.gz" >> $GITHUB_OUTPUT
  53. echo "testfilterfile=$(pwd)/.github/config/muted_test.txt" >> $GITHUB_OUTPUT
  54. echo "testshardfilterfile=$(pwd)/.github/config/muted_shard.txt" >> $GITHUB_OUTPUT
  55. echo "logurlprefix=${{inputs.aws_endpoint}}/${{inputs.aws_bucket}}/${{ github.repository }}/${{github.workflow}}/${{github.run_id}}" >> $GITHUB_OUTPUT
  56. echo "pytest-logfilename=${{inputs.log_suffix}}-pytest-stdout.gz" >> $GITHUB_OUTPUT
  57. - name: configure s3cmd
  58. shell: bash
  59. run: |
  60. cat <<EOF > $WORKDIR/tmp/s3cfg
  61. [default]
  62. access_key = ${aws_key_id}
  63. secret_key = ${aws_secret_access_key}
  64. bucket_location = ru-central1
  65. host_base = storage.yandexcloud.net
  66. host_bucket = %(bucket)s.storage.yandexcloud.net
  67. EOF
  68. echo "S3CMD_CONFIG=$WORKDIR/tmp/s3cfg" >> $GITHUB_ENV
  69. echo "S3_BUCKET_PATH=s3://${{ inputs.aws_bucket }}/${{ github.repository }}/${{github.workflow}}/${{ github.run_id }}/" >> $GITHUB_ENV
  70. env:
  71. aws_key_id: ${{inputs.AWS_KEY_ID }}
  72. aws_secret_access_key: ${{inputs.AWS_KEY_VALUE}}
  73. - name: Install Node required for Testmo CLI
  74. uses: actions/setup-node@v3
  75. with:
  76. node-version: 19
  77. - name: Install Testmo CLI
  78. shell: bash
  79. run: npm install -g @testmo/testmo-cli
  80. - name: Test history run create
  81. id: th
  82. if: inputs.testman_token
  83. shell: bash
  84. env:
  85. PR_NUMBER: ${{ github.event.number }}
  86. run: |
  87. RUN_URL="$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID"
  88. BRANCH_TAG="$GITHUB_REF_NAME"
  89. case $GITHUB_EVENT_NAME in
  90. workflow_dispatch)
  91. TESTMO_RUN_NAME="${{ github.run_id }} manual"
  92. EXTRA_TAG="manual"
  93. ;;
  94. pull_request | pull_request_target)
  95. TESTMO_RUN_NAME="${{ github.run_id }} PR #${PR_NUMBER}"
  96. EXTRA_TAG="pr"
  97. BRANCH_TAG=""
  98. ;;
  99. schedule)
  100. TESTMO_RUN_NAME="${{ github.run_id }} schedule"
  101. EXTRA_TAG="schedule"
  102. ;;
  103. *)
  104. TESTMO_RUN_NAME="${{ github.run_id }}"
  105. EXTRA_TAG=""
  106. ;;
  107. esac
  108. testmo automation:resources:add-link --name build --url $RUN_URL --resources testmo.json
  109. testmo automation:resources:add-field --name git-sha --type string --value ${GITHUB_SHA:0:7} --resources testmo.json
  110. testmo automation:run:create --instance "$TESTMO_URL" --project-id ${{inputs.testman_project_id}} --name "$TESTMO_RUN_NAME" \
  111. --source "${{inputs.log_suffix}}" --resources testmo.json \
  112. --tags "$BRANCH_TAG" --tags "$EXTRA_TAG" | \
  113. echo "runid=$(cat)" >> $GITHUB_OUTPUT
  114. - name: Run unit tests
  115. id: ctest
  116. if: inputs.run_unit_tests == 'true'
  117. shell: bash
  118. run: |
  119. cd $WORKDIR/../build/ydb
  120. echo "[Stdout unittest/ctest log (gzip archive)](${{steps.init.outputs.logurlprefix}}/${{steps.init.outputs.logfilename}})" >> $GITHUB_STEP_SUMMARY
  121. echo "[Testmo](${TESTMO_URL}/automation/runs/view/${{steps.th.outputs.runid}})" >> $GITHUB_STEP_SUMMARY
  122. # Sed removes coloring from the output
  123. TMPDIR=$WORKDIR/tmp GTEST_OUTPUT="xml:$TESTREPDIR/unittests/" Y_UNITTEST_OUTPUT="xml:$TESTREPDIR/unittests/" \
  124. ctest -j28 --timeout 1200 --force-new-ctest-process --output-on-failure \
  125. --output-junit $TESTREPDIR/suites/ctest_report.xml \
  126. -L '${{inputs.test_label_regexp}}' -E "${CTEST_SKIP_SHARDS:-}" | \
  127. sed -u -e 's/\x1b\[[0-9;]*m//g' | \
  128. tee >(gzip --stdout > $ARTIFACTS_DIR/${{steps.init.outputs.logfilename}}) | \
  129. grep --line-buffered -E '(Test\s*#.*\*\*\*|\[FAIL\])|.*tests passed,.*tests failed out of' | \
  130. tee $WORKDIR/short.log || (
  131. RC=$?
  132. if [ $RC == 8 ]; then
  133. echo "ctest returned TEST_ERRORS, recovering.."
  134. else
  135. exit $RC
  136. fi
  137. )
  138. - name: archive unitest reports (orig)
  139. if: inputs.run_unit_tests == 'true'
  140. shell: bash
  141. run: |
  142. tar -C $TESTREPDIR/ -czf $ARTIFACTS_DIR/reports.tar.gz .
  143. ls -la $ARTIFACTS_DIR/reports.tar.gz
  144. echo "[Unittest/CTest XML reports archive](${{steps.init.outputs.logurlprefix}}/reports.tar.gz)" >> $GITHUB_STEP_SUMMARY
  145. - name: postprocess xml reports
  146. if: inputs.run_unit_tests == 'true'
  147. shell: bash
  148. run: |
  149. echo "::group::junit-postprocess"
  150. .github/scripts/tests/junit-postprocess.py \
  151. --filter-file ${{steps.init.outputs.testfilterfile}} \
  152. $TESTREPDIR/unittests/
  153. echo "::endgroup::"
  154. echo "::group::ctest-postprocess"
  155. .github/scripts/tests/ctest-postprocess.py \
  156. --filter-file ${{steps.init.outputs.testshardfilterfile}} \
  157. --decompress \
  158. $ARTIFACTS_DIR/${{steps.init.outputs.logfilename}} \
  159. $TESTREPDIR/suites/ctest_report.xml
  160. echo "::endgroup::"
  161. echo "::group::extract-logs"
  162. mkdir $ARTIFACTS_DIR/logs/
  163. .github/scripts/tests/attach-logs.py \
  164. --url-prefix ${{steps.init.outputs.logurlprefix}}/logs/ \
  165. --filter-shard-file ${{steps.init.outputs.testshardfilterfile}} \
  166. --filter-test-file ${{steps.init.outputs.testfilterfile}} \
  167. --ctest-report $TESTREPDIR/suites/ctest_report.xml \
  168. --junit-reports-path $TESTREPDIR/unittests/ \
  169. --decompress \
  170. $ARTIFACTS_DIR/${{steps.init.outputs.logfilename}} \
  171. $ARTIFACTS_DIR/logs/
  172. echo "::endgroup::"
  173. - name: write unittests summary
  174. if: inputs.run_unit_tests == 'true'
  175. shell: bash
  176. run: |
  177. .github/scripts/tests/generate-summary.py -t "#### CTest run test shard failures" $TESTREPDIR/suites/ctest_report.xml
  178. .github/scripts/tests/generate-summary.py -t "#### Unittest failures" $TESTREPDIR/unittests/
  179. - name: sync test results to s3
  180. if: always() && inputs.run_unit_tests == 'true'
  181. shell: bash
  182. run: |
  183. echo "::group::s3-sync"
  184. s3cmd sync -P --no-progress --stats --no-check-md5 -P $ARTIFACTS_DIR/ $S3_BUCKET_PATH
  185. echo "::endgroup::"
  186. - name: Unit test history upload results
  187. if: always() && inputs.run_unit_tests == 'true' && inputs.testman_token
  188. shell: bash
  189. run: |
  190. testmo automation:run:submit-thread \
  191. --instance "$TESTMO_URL" --run-id ${{steps.th.outputs.runid}} \
  192. --results "$TESTREPDIR/unittests/*.xml"
  193. testmo automation:run:submit-thread \
  194. --exec-suppress \
  195. --instance "$TESTMO_URL" --run-id ${{steps.th.outputs.runid}} \
  196. --results "$TESTREPDIR/suites/*.xml" \
  197. -- cat $WORKDIR/short.log
  198. - name: Run functional tests
  199. if: inputs.run_functional_tests == 'true' && (success() || failure())
  200. shell: bash
  201. run: |
  202. export source_root=$WORKDIR
  203. export build_root=$WORKDIR/../build/
  204. echo "[Stdout pytest log (gzip archive)](${{steps.init.outputs.logurlprefix}}/${{steps.init.outputs.pytest-logfilename}})" >> $GITHUB_STEP_SUMMARY
  205. cd $WORKDIR/ydb/tests/functional/
  206. bad_suites=$(grep -Eo 'ignore=[a-zA-Z_-]*' pytest.ini | sed -e 's/ignore=//g')
  207. suites=""
  208. for suite in $(echo */ | sed -e 's/\///g'); do
  209. if [[ $(echo "$bad_suites" | grep -F -e $suite -) == '' ]]; then
  210. suites+=$suite
  211. suites+=$'\n'
  212. fi
  213. done
  214. if [[ "${{inputs.test_label_regexp}}" != '' ]]; then
  215. suites="${{inputs.test_label_regexp}}"
  216. fi
  217. source $WORKDIR/ydb/tests/oss/launch/prepare.sh
  218. echo -n "$suites" | parallel -j28 "pytest -o junit_logging=log -o junit_log_passing_tests=False \
  219. -v --junit-xml=$PYTESTREPDIR/{}.xml {}" | \
  220. sed -e 's/\x1b\[[0-9;]*m//g' | \
  221. tee >(gzip --stdout > $ARTIFACTS_DIR/${{steps.init.outputs.pytest-logfilename}}) | \
  222. grep -E '(FAILED|ERROR)\s*\[.*\]' | \
  223. tee $WORKDIR/pytest-short.log
  224. - name: write functional tests summary
  225. if: always() && inputs.run_functional_tests == 'true'
  226. shell: bash
  227. run: |
  228. .github/scripts/tests/generate-summary.py -t "#### Functional tests failures" $PYTESTREPDIR
  229. - name: Functional tests history upload results
  230. if: always() && inputs.run_functional_tests == 'true' && inputs.testman_token
  231. shell: bash
  232. run: |
  233. testmo automation:run:submit-thread \
  234. --instance "$TESTMO_URL" --run-id ${{steps.th.outputs.runid}} \
  235. --results "$PYTESTREPDIR/*.xml" \
  236. -- cat $WORKDIR/pytest-short.log
  237. - name: Test history run complete
  238. if: always() && inputs.testman_token
  239. shell: bash
  240. run: |
  241. testmo automation:run:complete --instance "$TESTMO_URL" --run-id ${{steps.th.outputs.runid}}
  242. - name: sync test results to s3
  243. if: always() && inputs.run_functional_tests == 'true'
  244. shell: bash
  245. run: |
  246. echo "::group::s3-sync"
  247. s3cmd sync -P --no-progress --stats --no-check-md5 -P $ARTIFACTS_DIR/ $S3_BUCKET_PATH
  248. echo "::endgroup::"
  249. - name: finish
  250. shell: bash
  251. run: |
  252. .github/scripts/tests/fail-checker.py $TESTREPDIR/unittests/ $TESTREPDIR/suites/