test.yml 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. name: Wagtail CI
  2. on:
  3. push:
  4. paths-ignore:
  5. - 'docs/**'
  6. pull_request:
  7. paths-ignore:
  8. - 'docs/**'
  9. concurrency:
  10. group: ${{ github.workflow }}-${{ github.ref }}
  11. cancel-in-progress: true
  12. # Our test suite should cover:
  13. # - all supported databases against current Python and Django (including psycopg v2 and v3)
  14. # - at least one test run for each older supported version of Python and Django
  15. # - at least one test run for each supported Elasticsearch version
  16. # - a test run against Django's git main and active stable branch (allowing failures)
  17. # - test runs with USE_EMAIL_USER_MODEL=yes, DISABLE_TIMEZONE=yes and WAGTAIL_CHECK_TEMPLATE_NUMBER_FORMAT=1
  18. # Current configuration:
  19. # - django 4.2, python 3.9, postgres:12, psycopg 2, parallel
  20. # - django 4.2, python 3.10, mysql:8.0
  21. # - django 4.2, python 3.11, mariadb:10.5
  22. # - django 5.0, python 3.11, sqlite, WAGTAIL_CHECK_TEMPLATE_NUMBER_FORMAT=1
  23. # - django 5.1, python 3.12, mysql:8.4, parallel, USE_EMAIL_USER_MODEL=yes
  24. # - django 5.1, python 3.12, mariadb:11.4, USE_EMAIL_USER_MODEL=yes
  25. # - django 5.1, python 3.13, sqlite, parallel, USE_EMAIL_USER_MODEL=yes
  26. # - django 5.1, python 3.13, postgres:15, psycopg 3, parallel, DISABLE_TIMEZONE=yes
  27. # - django stable/5.1.x, python 3.11, postgres:15, psycopg 3 (allow failures)
  28. # - django main, python 3.13, postgres:latest, psycopg 3, parallel (allow failures)
  29. # - elasticsearch 7, django 4.2, python 3.9, postgres:latest, psycopg 2
  30. # - opensearch 2, django 5.0, python 3.10, sqlite
  31. # - elasticsearch 8, django 5.1, python 3.13, sqlite, USE_EMAIL_USER_MODEL=yes
  32. # Some tests are run in parallel by passing --parallel to runtests.py.
  33. # When running tests in parallel, some errors cannot be pickled and result in
  34. # non-helpful tracebacks (see https://code.djangoproject.com/ticket/29023).
  35. # Thus, we keep one test run without --parallel for each supported database.
  36. # ElasticSearch tests are not run in parallel as the test suite is not thread-safe.
  37. permissions:
  38. contents: read # to fetch code (actions/checkout)
  39. jobs:
  40. test-sqlite:
  41. runs-on: ubuntu-latest
  42. strategy:
  43. matrix:
  44. include:
  45. - python: '3.11'
  46. django: 'Django>=5.0,<5.1'
  47. check_template_number_format: '1'
  48. - python: '3.13'
  49. django: 'Django>=5.1,<5.2'
  50. emailuser: emailuser
  51. parallel: '--parallel'
  52. steps:
  53. - uses: actions/checkout@v4
  54. - name: Set up Python ${{ matrix.python }}
  55. uses: actions/setup-python@v5
  56. with:
  57. python-version: ${{ matrix.python }}
  58. cache: 'pip'
  59. - name: Install dependencies
  60. run: |
  61. python -m pip install --upgrade pip
  62. pip install -e '.[testing]' --config-settings editable_mode=strict
  63. pip install "${{ matrix.django }}"
  64. - name: Test
  65. run: |
  66. WAGTAIL_FAIL_ON_VERSIONED_STATIC=1 DJANGO_SETTINGS_MODULE=wagtail.test.settings django-admin check
  67. coverage run --parallel-mode --source wagtail runtests.py ${{ matrix.parallel }}
  68. env:
  69. DATABASE_ENGINE: django.db.backends.sqlite3
  70. USE_EMAIL_USER_MODEL: ${{ matrix.emailuser }}
  71. WAGTAIL_CHECK_TEMPLATE_NUMBER_FORMAT: ${{ matrix.check_template_number_format }}
  72. - name: Upload coverage data
  73. uses: actions/upload-artifact@v4
  74. with:
  75. name: coverage-data-${{ github.job }}-${{ strategy.job-index }}
  76. path: .coverage.*
  77. include-hidden-files: true
  78. test-postgres:
  79. runs-on: ubuntu-latest
  80. continue-on-error: ${{ matrix.experimental }}
  81. strategy:
  82. matrix:
  83. include:
  84. - python: '3.9'
  85. django: 'Django>=4.2,<4.3'
  86. psycopg: 'psycopg2>=2.6'
  87. experimental: false
  88. parallel: '--parallel'
  89. - python: '3.13'
  90. django: 'Django>=5.0,<5.1'
  91. psycopg: 'psycopg>=3.1.8'
  92. postgres: 'postgres:15'
  93. notz: notz
  94. experimental: false
  95. parallel: '--parallel'
  96. - python: '3.11'
  97. django: 'git+https://github.com/django/django.git@stable/5.1.x#egg=Django'
  98. psycopg: 'psycopg>=3.1.8'
  99. postgres: 'postgres:15'
  100. experimental: true
  101. - python: '3.13'
  102. django: 'git+https://github.com/django/django.git@main#egg=Django'
  103. psycopg: 'psycopg>=3.1.8'
  104. experimental: true
  105. postgres: 'postgres:latest'
  106. parallel: '--parallel'
  107. services:
  108. postgres:
  109. image: ${{ matrix.postgres || 'postgres:12' }}
  110. env:
  111. POSTGRES_PASSWORD: postgres
  112. ports:
  113. - 5432:5432
  114. options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
  115. steps:
  116. - uses: actions/checkout@v4
  117. - name: Set up Python ${{ matrix.python }}
  118. uses: actions/setup-python@v5
  119. with:
  120. python-version: ${{ matrix.python }}
  121. cache: 'pip'
  122. - name: Install dependencies
  123. run: |
  124. python -m pip install --upgrade pip
  125. pip install "${{ matrix.psycopg }}"
  126. pip install -e '.[testing]' --config-settings editable_mode=strict
  127. pip install "${{ matrix.django }}"
  128. ${{ matrix.install_extras }}
  129. - name: Test
  130. run: |
  131. WAGTAIL_FAIL_ON_VERSIONED_STATIC=1 DJANGO_SETTINGS_MODULE=wagtail.test.settings django-admin check
  132. coverage run --parallel-mode --source wagtail runtests.py ${{ matrix.parallel }}
  133. env:
  134. DATABASE_ENGINE: django.db.backends.postgresql
  135. DATABASE_HOST: localhost
  136. DATABASE_USER: postgres
  137. DATABASE_PASSWORD: postgres
  138. USE_EMAIL_USER_MODEL: ${{ matrix.emailuser }}
  139. DISABLE_TIMEZONE: ${{ matrix.notz }}
  140. - name: Upload coverage data
  141. uses: actions/upload-artifact@v4
  142. with:
  143. name: coverage-data-${{ github.job }}-${{ strategy.job-index }}
  144. path: .coverage.*
  145. include-hidden-files: true
  146. test-mysql:
  147. runs-on: ubuntu-latest
  148. continue-on-error: ${{ matrix.experimental }}
  149. strategy:
  150. matrix:
  151. include:
  152. - python: '3.10'
  153. django: 'Django>=4.2,<4.3'
  154. experimental: false
  155. - python: '3.11'
  156. django: 'Django>=4.2,<4.3'
  157. experimental: false
  158. mysql: 'mariadb:10.5'
  159. - python: '3.12'
  160. django: 'Django>=5.1,<5.2'
  161. experimental: false
  162. mysql: 'mariadb:11.4'
  163. emailuser: emailuser
  164. - python: '3.12'
  165. django: 'Django>=5.1,<5.2'
  166. experimental: false
  167. parallel: '--parallel'
  168. mysql: 'mysql:8.4'
  169. emailuser: emailuser
  170. services:
  171. mysql:
  172. image: ${{ matrix.mysql || 'mysql:8.0' }}
  173. env:
  174. MARIADB_ROOT_PASSWORD: root
  175. MYSQL_ROOT_PASSWORD: root
  176. MYSQL_ALLOW_EMPTY_PASSWORD: yes
  177. MYSQL_DATABASE: wagtail
  178. HEALTH_CMD: ${{ startsWith(matrix.mysql, 'mariadb') && 'healthcheck.sh --connect --innodb_initialized' || 'mysqladmin --protocol=tcp ping' }}
  179. ports:
  180. - 3306:3306
  181. options: --health-cmd=$HEALTH_CMD --health-interval=10s --health-timeout=5s --health-retries=3 --cap-add=sys_nice
  182. steps:
  183. - uses: actions/checkout@v4
  184. - name: Set up Python ${{ matrix.python }}
  185. uses: actions/setup-python@v5
  186. with:
  187. python-version: ${{ matrix.python }}
  188. cache: 'pip'
  189. - name: Install dependencies
  190. run: |
  191. python -m pip install --upgrade pip
  192. pip install "mysqlclient>=1.4,<2"
  193. pip install -e '.[testing]' --config-settings editable_mode=strict
  194. pip install "${{ matrix.django }}"
  195. - name: Test
  196. run: |
  197. WAGTAIL_FAIL_ON_VERSIONED_STATIC=1 DJANGO_SETTINGS_MODULE=wagtail.test.settings django-admin check
  198. coverage run --parallel-mode --source wagtail runtests.py ${{ matrix.parallel }}
  199. env:
  200. DATABASE_ENGINE: django.db.backends.mysql
  201. DATABASE_HOST: '127.0.0.1'
  202. DATABASE_USER: root
  203. DATABASE_PASSWORD: root
  204. USE_EMAIL_USER_MODEL: ${{ matrix.emailuser }}
  205. DISABLE_TIMEZONE: ${{ matrix.notz }}
  206. - name: Upload coverage data
  207. uses: actions/upload-artifact@v4
  208. with:
  209. name: coverage-data-${{ github.job }}-${{ strategy.job-index }}
  210. path: .coverage.*
  211. include-hidden-files: true
  212. test-sqlite-elasticsearch8:
  213. runs-on: ubuntu-latest
  214. strategy:
  215. matrix:
  216. include:
  217. - python: '3.13'
  218. django: 'Django>=5.1,<5.2'
  219. emailuser: emailuser
  220. steps:
  221. - name: Configure sysctl limits
  222. run: |
  223. sudo swapoff -a
  224. sudo sysctl -w vm.swappiness=1
  225. sudo sysctl -w fs.file-max=262144
  226. sudo sysctl -w vm.max_map_count=262144
  227. - uses: getong/elasticsearch-action@v1.3
  228. with:
  229. elasticsearch version: 8.8.0
  230. host port: 9200
  231. container port: 9200
  232. host node port: 9300
  233. node port: 9300
  234. discovery type: 'single-node'
  235. - uses: actions/checkout@v4
  236. - name: Set up Python ${{ matrix.python }}
  237. uses: actions/setup-python@v5
  238. with:
  239. python-version: ${{ matrix.python }}
  240. cache: 'pip'
  241. - name: Install dependencies
  242. run: |
  243. python -m pip install --upgrade pip
  244. pip install -e '.[testing]' --config-settings editable_mode=strict
  245. pip install "${{ matrix.django }}"
  246. pip install "elasticsearch>=8,<9"
  247. pip install certifi
  248. - name: Test
  249. run: |
  250. coverage run --parallel-mode --source wagtail runtests.py wagtail.search wagtail.documents wagtail.images --elasticsearch8
  251. env:
  252. DATABASE_ENGINE: django.db.backends.sqlite3
  253. USE_EMAIL_USER_MODEL: ${{ matrix.emailuser }}
  254. - name: Upload coverage data
  255. uses: actions/upload-artifact@v4
  256. with:
  257. name: coverage-data-${{ github.job }}-${{ strategy.job-index }}
  258. path: .coverage.*
  259. include-hidden-files: true
  260. test-postgres-elasticsearch7:
  261. runs-on: ubuntu-latest
  262. continue-on-error: ${{ matrix.experimental }}
  263. strategy:
  264. matrix:
  265. include:
  266. - python: '3.9'
  267. django: 'Django>=4.2,<4.3'
  268. experimental: false
  269. services:
  270. postgres:
  271. image: postgres:latest
  272. env:
  273. POSTGRES_PASSWORD: postgres
  274. ports:
  275. - 5432:5432
  276. options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
  277. steps:
  278. - name: Configure sysctl limits
  279. run: |
  280. sudo swapoff -a
  281. sudo sysctl -w vm.swappiness=1
  282. sudo sysctl -w fs.file-max=262144
  283. sudo sysctl -w vm.max_map_count=262144
  284. - uses: elastic/elastic-github-actions/elasticsearch@master
  285. with:
  286. stack-version: 7.6.1
  287. - uses: actions/checkout@v4
  288. - name: Set up Python ${{ matrix.python }}
  289. uses: actions/setup-python@v5
  290. with:
  291. python-version: ${{ matrix.python }}
  292. cache: 'pip'
  293. - name: Install dependencies
  294. run: |
  295. python -m pip install --upgrade pip
  296. pip install "psycopg2>=2.6"
  297. pip install -e '.[testing]' --config-settings editable_mode=strict
  298. pip install "${{ matrix.django }}"
  299. pip install "elasticsearch>=7,<8"
  300. pip install certifi
  301. - name: Test
  302. run: |
  303. coverage run --parallel-mode --source wagtail runtests.py wagtail.search wagtail.documents wagtail.images --elasticsearch7
  304. env:
  305. DATABASE_ENGINE: django.db.backends.postgresql
  306. DATABASE_HOST: localhost
  307. DATABASE_USER: postgres
  308. DATABASE_PASSWORD: postgres
  309. USE_EMAIL_USER_MODEL: ${{ matrix.emailuser }}
  310. - name: Upload coverage data
  311. uses: actions/upload-artifact@v4
  312. with:
  313. name: coverage-data-${{ github.job }}-${{ strategy.job-index }}
  314. path: .coverage.*
  315. include-hidden-files: true
  316. test-sqlite-opensearch2:
  317. runs-on: ubuntu-latest
  318. continue-on-error: ${{ matrix.experimental }}
  319. strategy:
  320. matrix:
  321. include:
  322. - python: '3.10'
  323. django: 'Django>=5.0,<5.1'
  324. experimental: false
  325. steps:
  326. - name: Configure sysctl limits
  327. run: |
  328. sudo swapoff -a
  329. sudo sysctl -w vm.swappiness=1
  330. sudo sysctl -w fs.file-max=262144
  331. sudo sysctl -w vm.max_map_count=262144
  332. - uses: ankane/setup-opensearch@v1
  333. with:
  334. opensearch-version: 2
  335. - uses: actions/checkout@v4
  336. - name: Set up Python ${{ matrix.python }}
  337. uses: actions/setup-python@v5
  338. with:
  339. python-version: ${{ matrix.python }}
  340. cache: 'pip'
  341. - name: Install dependencies
  342. run: |
  343. python -m pip install --upgrade pip
  344. pip install -e '.[testing]' --config-settings editable_mode=strict
  345. pip install "${{ matrix.django }}"
  346. pip install "elasticsearch==7.13.4"
  347. pip install certifi
  348. - name: Test
  349. run: |
  350. coverage run --parallel-mode --source wagtail runtests.py wagtail.search wagtail.documents wagtail.images --elasticsearch7
  351. env:
  352. DATABASE_ENGINE: django.db.backends.sqlite3
  353. USE_EMAIL_USER_MODEL: ${{ matrix.emailuser }}
  354. - name: Upload coverage data
  355. uses: actions/upload-artifact@v4
  356. with:
  357. name: coverage-data-${{ github.job }}-${{ strategy.job-index }}
  358. path: .coverage.*
  359. include-hidden-files: true
  360. coverage:
  361. needs:
  362. - test-sqlite
  363. - test-postgres
  364. - test-mysql
  365. - test-sqlite-elasticsearch8
  366. - test-postgres-elasticsearch7
  367. - test-sqlite-opensearch2
  368. runs-on: ubuntu-latest
  369. steps:
  370. - name: Check out the repo
  371. uses: actions/checkout@v4
  372. - name: Set up Python
  373. uses: actions/setup-python@v5
  374. with:
  375. python-version: '3.10'
  376. - name: Install dependencies
  377. run: |
  378. python -m pip install --upgrade pip
  379. pip install coverage
  380. - name: Download coverage data
  381. uses: actions/download-artifact@v4
  382. with:
  383. pattern: coverage-data-*
  384. merge-multiple: true
  385. - name: Combine coverage data
  386. run: |
  387. coverage combine
  388. - name: Generate coverage report
  389. run: |
  390. coverage report -m --skip-covered --skip-empty | sed 's/^/ /' >> $GITHUB_STEP_SUMMARY
  391. coverage html --skip-covered --skip-empty
  392. - name: Upload HTML report as artifact
  393. uses: actions/upload-artifact@v4
  394. with:
  395. name: coverage-report
  396. path: coverage_html_report
  397. include-hidden-files: true
  398. - name: Upload coverage to Codecov
  399. uses: codecov/codecov-action@v3
  400. with:
  401. flags: backend
  402. token: ${{ secrets.CODECOV_TOKEN }}