e2e.yml 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. name: End-to-end tests
  2. on:
  3. push:
  4. branches: [main]
  5. paths-ignore:
  6. - '**.md'
  7. - '**.d.ts'
  8. - 'examples/**'
  9. - 'private/**'
  10. - 'website/**'
  11. - '.github/**'
  12. - '!.github/workflows/e2e.yml'
  13. pull_request_target:
  14. types: [opened, synchronize, reopened, labeled]
  15. paths-ignore:
  16. - '**.md'
  17. - '**.d.ts'
  18. - 'examples/**'
  19. - 'private/**'
  20. - 'website/**'
  21. - '.github/**'
  22. pull_request:
  23. types: [opened, synchronize, reopened]
  24. paths:
  25. - .github/workflows/e2e.yml
  26. concurrency:
  27. group:
  28. ${{ github.workflow }}--${{ github.event.pull_request.head.repo.full_name ||
  29. github.repository }} -- ${{ github.head_ref || github.ref }}
  30. cancel-in-progress:
  31. # For PRs coming from forks, we need the previous job to run until the end
  32. # to be sure it can remove the `safe to test` label before it affects the next run.
  33. ${{ github.event.pull_request.head.repo.full_name == github.repository }}
  34. permissions:
  35. pull-requests: write
  36. env:
  37. YARN_ENABLE_GLOBAL_CACHE: false
  38. jobs:
  39. compare_diff:
  40. runs-on: ubuntu-latest
  41. env:
  42. DIFF_BUILDER: true
  43. outputs:
  44. diff: ${{ steps.diff.outputs.OUTPUT_DIFF }}
  45. is_accurate_diff: ${{ steps.diff.outputs.IS_ACCURATE_DIFF }}
  46. steps:
  47. - name: Checkout sources
  48. uses: actions/checkout@v4
  49. with:
  50. fetch-depth: 2
  51. ref:
  52. ${{ github.event.pull_request && format('refs/pull/{0}/merge',
  53. github.event.pull_request.number) || github.sha }}
  54. - name: Check if there are "unsafe" changes
  55. id: build_chain_changes
  56. # If there are changes in JS script that generates the output, we cannot
  57. # test them here without human review to make sure they don't contain
  58. # someting "nasty".
  59. run: |
  60. EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64)
  61. echo "MIGHT_CONTAIN_OTHER_CHANGES<<$EOF" >> "$GITHUB_OUTPUT"
  62. git --no-pager diff HEAD^ --name-only bin package.json yarn.lock babel.config.js >> "$GITHUB_OUTPUT"
  63. echo "$EOF" >> "$GITHUB_OUTPUT"
  64. - run: git reset HEAD^ --hard
  65. - name: Get yarn cache directory path
  66. id: yarn-cache-dir-path
  67. run:
  68. echo "dir=$(corepack yarn config get cacheFolder)" >> $GITHUB_OUTPUT
  69. - uses: actions/cache@v4
  70. id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
  71. with:
  72. path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
  73. key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
  74. restore-keys: |
  75. ${{ runner.os }}-yarn-
  76. - name: Install Node.js
  77. uses: actions/setup-node@v4
  78. with:
  79. node-version: lts/*
  80. - name: Install dependencies
  81. run:
  82. corepack yarn workspaces focus $(corepack yarn workspaces list --json
  83. | jq -r .name | awk '/^@uppy-example/{ next } { if ($0!="uppy.io")
  84. print $0 }')
  85. env:
  86. # https://docs.cypress.io/guides/references/advanced-installation#Skipping-installation
  87. CYPRESS_INSTALL_BINARY: 0
  88. - run: corepack yarn build:js:typeless
  89. - name: Store output file
  90. run: tar cf /tmp/previousVersion.tar packages/@uppy/*/lib
  91. - name: Fetch source from the PR
  92. if: steps.build_chain_changes.outputs.MIGHT_CONTAIN_OTHER_CHANGES == ''
  93. run: |
  94. git checkout FETCH_HEAD -- packages
  95. echo 'IS_ACCURATE_DIFF=true' >> "$GITHUB_ENV"
  96. - name: Fetch source from the PR
  97. if:
  98. steps.build_chain_changes.outputs.MIGHT_CONTAIN_OTHER_CHANGES != '' &&
  99. (!github.event.pull_request || (github.event.action == 'labeled' &&
  100. github.event.label.name == 'safe to test' &&
  101. github.event.pull_request.state == 'open') ||
  102. (github.event.pull_request.head.repo.full_name == github.repository &&
  103. github.event.event_name != 'labeled'))
  104. run: |
  105. git reset FETCH_HEAD --hard
  106. corepack yarn workspaces focus $(\
  107. corepack yarn workspaces list --json | \
  108. jq -r .name | \
  109. awk '/^@uppy-example/{ next } { if ($0!="uppy.io") print $0 }'\
  110. )
  111. echo 'IS_ACCURATE_DIFF=true' >> "$GITHUB_ENV"
  112. env:
  113. # https://docs.cypress.io/guides/references/advanced-installation#Skipping-installation
  114. CYPRESS_INSTALL_BINARY: 0
  115. - name: Fetch source from the PR
  116. if:
  117. steps.build_chain_changes.outputs.MIGHT_CONTAIN_OTHER_CHANGES != '' &&
  118. github.event.pull_request.head.repo.full_name != github.repository &&
  119. (github.event.action != 'labeled' || github.event.label.name != 'safe
  120. to test')
  121. run: |
  122. git checkout FETCH_HEAD -- packages
  123. - run: corepack yarn build:js:typeless
  124. - name: Store output file
  125. run: tar cf /tmp/newVersion.tar packages/@uppy/*/lib
  126. - name: Setup git
  127. run: |
  128. git config --global user.email "actions@github.com"
  129. git config --global user.name "GitHub Actions"
  130. git init /tmp/uppy
  131. echo '*.map' > /tmp/uppy/.gitignore
  132. - name: Install dformat
  133. run: |
  134. curl -fsSL https://dprint.dev/install.sh | sh
  135. cd /tmp/uppy && echo '{"plugins":[]}' > dprint.json && "$HOME/.dprint/bin/dprint" config add typescript
  136. - name: Extract previous version
  137. run: cd /tmp/uppy && tar xf /tmp/previousVersion.tar
  138. - name: Format previous output code
  139. run: cd /tmp/uppy && "$HOME/.dprint/bin/dprint" fmt **/*.js
  140. - name: Commit previous version
  141. run: cd /tmp/uppy && git add -A . && git commit -m 'previous version'
  142. - name: Extract new version
  143. run: cd /tmp/uppy && tar xf /tmp/newVersion.tar
  144. - name: Format new output code
  145. run: cd /tmp/uppy && "$HOME/.dprint/bin/dprint" fmt **/*.js
  146. - name: Build diff
  147. id: diff
  148. run: |
  149. EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64)
  150. echo "OUTPUT_DIFF<<$EOF" >> "$GITHUB_OUTPUT"
  151. cd /tmp/uppy && git --no-pager diff >> "$GITHUB_OUTPUT"
  152. echo "$EOF" >> "$GITHUB_OUTPUT"
  153. echo "IS_ACCURATE_DIFF=$IS_ACCURATE_DIFF" >> "$GITHUB_OUTPUT"
  154. - name: Add/update comment
  155. if: github.event.pull_request
  156. uses: marocchino/sticky-pull-request-comment@v2
  157. with:
  158. message: |
  159. <details><summary>Diff output files</summary>
  160. ```diff
  161. ${{ steps.diff.outputs.OUTPUT_DIFF || 'No diff' }}
  162. ```
  163. ${{ env.IS_ACCURATE_DIFF != 'true' && format(fromJson('"The following build files have been modified and might affect the actual diff:\n\n```\n{0}\n```"'), steps.build_chain_changes.outputs.MIGHT_CONTAIN_OTHER_CHANGES) || '' }}
  164. </details>
  165. - name: Remove 'safe to test' label if cancelled
  166. if:
  167. cancelled() && github.event.pull_request &&
  168. github.event.pull_request.head.repo.full_name != github.repository
  169. run: gh pr edit "$NUMBER" --remove-label 'safe to test'
  170. env:
  171. NUMBER: ${{ github.event.pull_request.number }}
  172. GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  173. toggle-pending-e2e-label:
  174. # Add the 'pending end-to-end tests' label for PRs that come from forks.
  175. # For those PRs, we want to review the code before running e2e tests.
  176. # See https://securitylab.github.com/research/github-actions-preventing-pwn-requests/.
  177. needs: [compare_diff]
  178. if:
  179. github.event.pull_request.state == 'open' &&
  180. github.event.pull_request.head.repo.full_name != github.repository
  181. runs-on: ubuntu-latest
  182. steps:
  183. - name: Add label
  184. if:
  185. (needs.compare_diff.outputs.diff != '' ||
  186. !needs.compare_diff.outputs.is_accurate_diff) && (github.event.action
  187. != 'labeled' || github.event.label.name != 'safe to test')
  188. env:
  189. PR_URL: ${{ github.event.pull_request.html_url }}
  190. GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  191. run:
  192. gh pr edit "$PR_URL" --repo ${{ github.repository }} --add-label
  193. 'pending end-to-end tests'
  194. - name: Remove label
  195. if:
  196. needs.compare_diff.outputs.diff == '' &&
  197. needs.compare_diff.outputs.is_accurate_diff && github.event.action ==
  198. 'labeled' && github.event.label.name == 'safe to test'
  199. env:
  200. PR_URL: ${{ github.event.pull_request.html_url }}
  201. GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  202. run:
  203. gh pr edit "$PR_URL" --remove-label 'safe to test' --remove-label
  204. 'pending end-to-end tests'
  205. e2e:
  206. needs: [compare_diff]
  207. if:
  208. ${{ needs.compare_diff.outputs.diff != '' && (!github.event.pull_request
  209. || (github.event.action == 'labeled' && github.event.label.name == 'safe
  210. to test' && github.event.pull_request.state == 'open') ||
  211. (github.event.pull_request.head.repo.full_name == github.repository &&
  212. github.event.event_name != 'labeled')) }}
  213. name: Browser tests
  214. runs-on: ubuntu-latest
  215. steps:
  216. - name: Checkout sources
  217. uses: actions/checkout@v4
  218. with:
  219. ref: ${{ github.event.pull_request.head.sha || github.sha }}
  220. - name: Get yarn cache directory path
  221. id: yarn-cache-dir-path
  222. run:
  223. echo "dir=$(corepack yarn config get cacheFolder)" >> $GITHUB_OUTPUT
  224. - uses: actions/cache@v4
  225. id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
  226. with:
  227. path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
  228. key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
  229. restore-keys: |
  230. ${{ runner.os }}-yarn-
  231. - name: Create cache folder for Cypress
  232. id: cypress-cache-dir-path
  233. run: echo "dir=$(mktemp -d)" >> $GITHUB_OUTPUT
  234. - uses: actions/cache@v4
  235. with:
  236. path: ${{ steps.cypress-cache-dir-path.outputs.dir }}
  237. key: ${{ runner.os }}-cypress
  238. - name: Install Node.js
  239. uses: actions/setup-node@v4
  240. with:
  241. node-version: lts/*
  242. - name: Start Redis
  243. uses: supercharge/redis-github-action@ea9b21c6ecece47bd99595c532e481390ea0f044 # 1.8.0
  244. with:
  245. redis-version: 7
  246. - name: Install dependencies
  247. run: corepack yarn install --immutable
  248. env:
  249. # https://docs.cypress.io/guides/references/advanced-installation#Binary-cache
  250. CYPRESS_CACHE_FOLDER: ${{ steps.cypress-cache-dir-path.outputs.dir }}
  251. - name: Build Uppy packages
  252. run: corepack yarn build
  253. - name: Run end-to-end browser tests
  254. run: corepack yarn run e2e:ci
  255. env:
  256. COMPANION_DATADIR: ./output
  257. COMPANION_DOMAIN: localhost:3020
  258. COMPANION_PROTOCOL: http
  259. COMPANION_REDIS_URL: redis://localhost:6379
  260. COMPANION_UNSPLASH_KEY: ${{secrets.COMPANION_UNSPLASH_KEY}}
  261. COMPANION_UNSPLASH_SECRET: ${{secrets.COMPANION_UNSPLASH_SECRET}}
  262. COMPANION_AWS_KEY: ${{secrets.COMPANION_AWS_KEY}}
  263. COMPANION_AWS_SECRET: ${{secrets.COMPANION_AWS_SECRET}}
  264. COMPANION_AWS_BUCKET: ${{secrets.COMPANION_AWS_BUCKET}}
  265. COMPANION_AWS_REGION: ${{secrets.COMPANION_AWS_REGION}}
  266. VITE_COMPANION_URL: http://localhost:3020
  267. VITE_TRANSLOADIT_KEY: ${{secrets.TRANSLOADIT_KEY}}
  268. VITE_TRANSLOADIT_SECRET: ${{secrets.TRANSLOADIT_SECRET}}
  269. VITE_TRANSLOADIT_TEMPLATE: ${{secrets.TRANSLOADIT_TEMPLATE}}
  270. VITE_TRANSLOADIT_SERVICE_URL: ${{secrets.TRANSLOADIT_SERVICE_URL}}
  271. # https://docs.cypress.io/guides/references/advanced-installation#Binary-cache
  272. CYPRESS_CACHE_FOLDER: ${{ steps.cypress-cache-dir-path.outputs.dir }}
  273. - name: Upload videos in case of failure
  274. uses: actions/upload-artifact@v4
  275. if: failure()
  276. with:
  277. name: videos-and-screenshots
  278. path: |
  279. e2e/cypress/videos/
  280. e2e/cypress/screenshots/
  281. - name: Remove labels
  282. # Remove the 'pending end-to-end tests' label if tests ran successfully
  283. if:
  284. github.event.pull_request &&
  285. contains(github.event.pull_request.labels.*.name, 'pending end-to-end
  286. tests')
  287. run: gh pr edit "$NUMBER" --remove-label 'pending end-to-end tests'
  288. env:
  289. NUMBER: ${{ github.event.pull_request.number }}
  290. GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  291. - name: Remove 'safe to test' label
  292. if:
  293. always() && github.event.pull_request &&
  294. contains(github.event.pull_request.labels.*.name, 'safe to test')
  295. run: gh pr edit "$NUMBER" --remove-label 'safe to test'
  296. env:
  297. NUMBER: ${{ github.event.pull_request.number }}
  298. GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}