Commit 563d3dd3 authored by Rémy Coutable's avatar Rémy Coutable

Merge branch 'alberts-jest-related-tests' into 'master'

Run jest related tests on CI on frontend changes

See merge request gitlab-org/gitlab!68251
parents 3944da82 f2ee3151
...@@ -172,6 +172,8 @@ graphql-schema-dump: ...@@ -172,6 +172,8 @@ graphql-schema-dump:
# Disable warnings in browserslist which can break on backports # Disable warnings in browserslist which can break on backports
# https://github.com/browserslist/browserslist/blob/a287ec6/node.js#L367-L384 # https://github.com/browserslist/browserslist/blob/a287ec6/node.js#L367-L384
BROWSERSLIST_IGNORE_OLD_DATA: "true" BROWSERSLIST_IGNORE_OLD_DATA: "true"
before_script:
- *yarn-install
stage: test stage: test
eslint-as-if-foss: eslint-as-if-foss:
...@@ -181,20 +183,19 @@ eslint-as-if-foss: ...@@ -181,20 +183,19 @@ eslint-as-if-foss:
- .as-if-foss - .as-if-foss
needs: [] needs: []
script: script:
- *yarn-install
- run_timed_command "yarn run lint:eslint:all" - run_timed_command "yarn run lint:eslint:all"
.jest-base: .jest-base:
extends: .frontend-test-base extends: .frontend-test-base
script: script:
- *yarn-install - run_timed_command "yarn jest:ci"
- run_timed_command "yarn jest --ci --coverage --testSequencer ./scripts/frontend/parallel_ci_sequencer.js"
jest: jest:
extends: extends:
- .jest-base - .jest-base
- .frontend:rules:default-frontend-jobs - .frontend:rules:jest
needs: needs:
- job: "detect-tests"
- job: "rspec frontend_fixture" - job: "rspec frontend_fixture"
- job: "rspec-ee frontend_fixture" - job: "rspec-ee frontend_fixture"
optional: true optional: true
...@@ -210,12 +211,18 @@ jest: ...@@ -210,12 +211,18 @@ jest:
junit: junit_jest.xml junit: junit_jest.xml
parallel: 5 parallel: 5
jest minimal:
extends:
- jest
- .frontend:rules:jest:minimal
script:
- run_timed_command "yarn jest:ci:minimal"
jest-integration: jest-integration:
extends: extends:
- .frontend-test-base - .frontend-test-base
- .frontend:rules:default-frontend-jobs - .frontend:rules:default-frontend-jobs
script: script:
- *yarn-install
- run_timed_command "yarn jest:integration --ci" - run_timed_command "yarn jest:integration --ci"
needs: needs:
- job: "rspec frontend_fixture" - job: "rspec frontend_fixture"
...@@ -236,7 +243,11 @@ coverage-frontend: ...@@ -236,7 +243,11 @@ coverage-frontend:
- .default-retry - .default-retry
- .yarn-cache - .yarn-cache
- .frontend:rules:ee-mr-and-default-branch-only - .frontend:rules:ee-mr-and-default-branch-only
needs: ["jest"] needs:
- job: "jest"
optional: true
- job: "jest minimal"
optional: true
stage: post-test stage: post-test
before_script: before_script:
- *yarn-install - *yarn-install
...@@ -321,7 +332,6 @@ bundle-size-review: ...@@ -321,7 +332,6 @@ bundle-size-review:
extends: extends:
- .frontend-test-base - .frontend-test-base
script: script:
- *yarn-install
- run_timed_command "yarn generate:startup_css" - run_timed_command "yarn generate:startup_css"
- yarn check:startup_css - yarn check:startup_css
...@@ -349,7 +359,6 @@ startup-css-check as-if-foss: ...@@ -349,7 +359,6 @@ startup-css-check as-if-foss:
- .frontend-test-base - .frontend-test-base
- .storybook-yarn-cache - .storybook-yarn-cache
script: script:
- *yarn-install # storybook depends on the global webpack config, so we must install global deps.
- *storybook-yarn-install - *storybook-yarn-install
- yarn run storybook:build - yarn run storybook:build
......
...@@ -46,6 +46,9 @@ ...@@ -46,6 +46,9 @@
.if-merge-request-title-run-all-rspec: &if-merge-request-title-run-all-rspec .if-merge-request-title-run-all-rspec: &if-merge-request-title-run-all-rspec
if: '$CI_MERGE_REQUEST_LABELS =~ /pipeline:run-all-rspec/' if: '$CI_MERGE_REQUEST_LABELS =~ /pipeline:run-all-rspec/'
.if-merge-request-title-run-all-jest: &if-merge-request-title-run-all-jest
if: '$CI_MERGE_REQUEST_LABELS =~ /pipeline:run-all-jest/'
.if-merge-request-run-decomposed: &if-merge-request-run-decomposed .if-merge-request-run-decomposed: &if-merge-request-run-decomposed
if: '$CI_MERGE_REQUEST_LABELS =~ /pipeline:run-decomposed/' if: '$CI_MERGE_REQUEST_LABELS =~ /pipeline:run-decomposed/'
...@@ -365,6 +368,14 @@ ...@@ -365,6 +368,14 @@
- "danger/**/*" - "danger/**/*"
- "tooling/danger/**/*" - "tooling/danger/**/*"
.core-frontend-patterns: &core-frontend-patterns
- "{package.json,yarn.lock}"
- "babel.config.js"
- "jest.config.{base,integration,unit}.js"
- "config/helpers/**/*.js"
- "vendor/assets/javascripts/**/*"
- "{,ee}/app/assets/**/*.graphql"
################ ################
# Shared rules # # Shared rules #
################ ################
...@@ -525,6 +536,37 @@ ...@@ -525,6 +536,37 @@
- <<: *if-merge-request - <<: *if-merge-request
changes: *ci-patterns changes: *ci-patterns
.frontend:rules:jest:
rules:
- <<: *if-merge-request-title-run-all-jest
- <<: *if-default-refs
changes: *core-frontend-patterns
- <<: *if-merge-request
changes: *ci-patterns
- <<: *if-automated-merge-request
changes: *code-backstage-patterns
- <<: *if-merge-request-not-approved
when: never
- <<: *if-default-refs
changes: *code-backstage-patterns
.frontend:rules:jest:minimal:
rules:
- <<: *if-merge-request-approved
when: never
- <<: *if-automated-merge-request
when: never
- <<: *if-merge-request-title-run-all-jest
when: never
- <<: *if-default-refs
changes: *core-frontend-patterns
when: never
- <<: *if-merge-request
changes: *ci-patterns
when: never
- <<: *if-merge-request
changes: *code-backstage-patterns
.frontend:rules:eslint-as-if-foss: .frontend:rules:eslint-as-if-foss:
rules: rules:
- <<: *if-not-ee - <<: *if-not-ee
......
...@@ -70,11 +70,16 @@ verify-tests-yml: ...@@ -70,11 +70,16 @@ verify-tests-yml:
- install_gitlab_gem - install_gitlab_gem
- install_tff_gem - install_tff_gem
- retrieve_tests_mapping - retrieve_tests_mapping
- 'if [ -n "$CI_MERGE_REQUEST_IID" ]; then tooling/bin/find_tests ${MATCHED_TESTS_FILE}; fi' - |
- 'if [ -n "$CI_MERGE_REQUEST_IID" ]; then echo "test files affected: $(cat $MATCHED_TESTS_FILE)"; fi' if [ -n "$CI_MERGE_REQUEST_IID" ]; then
tooling/bin/find_changes ${CHANGES_FILE};
tooling/bin/find_tests ${CHANGES_FILE} ${MATCHED_TESTS_FILE};
echo "related rspec tests: $(cat $MATCHED_TESTS_FILE)";
fi
artifacts: artifacts:
expire_in: 7d expire_in: 7d
paths: paths:
- ${CHANGES_FILE}
- ${MATCHED_TESTS_FILE} - ${MATCHED_TESTS_FILE}
detect-tests: detect-tests:
...@@ -83,6 +88,7 @@ detect-tests: ...@@ -83,6 +88,7 @@ detect-tests:
- .rails:rules:detect-tests - .rails:rules:detect-tests
variables: variables:
RSPEC_TESTS_MAPPING_ENABLED: "true" RSPEC_TESTS_MAPPING_ENABLED: "true"
CHANGES_FILE: tmp/changed_files.txt
MATCHED_TESTS_FILE: tmp/matching_tests.txt MATCHED_TESTS_FILE: tmp/matching_tests.txt
detect-tests as-if-foss: detect-tests as-if-foss:
...@@ -91,6 +97,7 @@ detect-tests as-if-foss: ...@@ -91,6 +97,7 @@ detect-tests as-if-foss:
- .rails:rules:detect-tests - .rails:rules:detect-tests
- .as-if-foss - .as-if-foss
variables: variables:
CHANGES_FILE: tmp/changed_foss_files.txt
MATCHED_TESTS_FILE: tmp/matching_foss_tests.txt MATCHED_TESTS_FILE: tmp/matching_foss_tests.txt
before_script: before_script:
- '[ "$FOSS_ONLY" = "1" ] && rm -rf ee/ qa/spec/ee/ qa/qa/specs/features/ee/ qa/qa/ee/ qa/qa/ee.rb' - '[ "$FOSS_ONLY" = "1" ] && rm -rf ee/ qa/spec/ee/ qa/qa/specs/features/ee/ qa/qa/ee/ qa/qa/ee.rb'
...@@ -430,6 +430,23 @@ In the `detect-tests` job, we use this mapping to identify the minimal tests nee ...@@ -430,6 +430,23 @@ In the `detect-tests` job, we use this mapping to identify the minimal tests nee
After a merge request has been approved, the pipeline would contain the full RSpec tests. This will ensure that all tests After a merge request has been approved, the pipeline would contain the full RSpec tests. This will ensure that all tests
have been run before a merge request is merged. have been run before a merge request is merged.
### Jest minimal jobs
Before a merge request is approved, the pipeline will run a minimal set of Jest tests that are related to the merge request changes.
This is to reduce the pipeline cost and shorten the job duration.
To identify the minimal set of tests needed, we pass a list of all the changed files into `jest` using the [`--findRelatedTests`](https://jestjs.io/docs/cli#--findrelatedtests-spaceseparatedlistofsourcefiles) option.
In this mode, `jest` would resolve all the dependencies of related to the changed files, which include test files that have these files in the dependency chain.
After a merge request has been approved, the pipeline would contain the full Jest tests. This will ensure that all tests
have been run before a merge request is merged.
In addition, there are a few circumstances where we would always run the full Jest tests:
- when `package.json`, `yarn.lock`, `jest` config changes
- when vendored JavaScript is changed
- when `.graphql` files are changed
### PostgreSQL versions testing ### PostgreSQL versions testing
Our test suite runs against PG12 as GitLab.com runs on PG12 and Our test suite runs against PG12 as GitLab.com runs on PG12 and
......
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
"prejest": "yarn check-dependencies", "prejest": "yarn check-dependencies",
"jest": "jest --config jest.config.js", "jest": "jest --config jest.config.js",
"jest-debug": "node --inspect-brk node_modules/.bin/jest --runInBand", "jest-debug": "node --inspect-brk node_modules/.bin/jest --runInBand",
"jest:ci": "jest --config jest.config.js --ci --coverage --testSequencer ./scripts/frontend/parallel_ci_sequencer.js",
"jest:ci:minimal": "jest --config jest.config.js --ci --coverage --findRelatedTests $(cat tmp/changed_files.txt) --passWithNoTests --testSequencer ./scripts/frontend/parallel_ci_sequencer.js",
"jest:integration": "jest --config jest.config.integration.js", "jest:integration": "jest --config jest.config.integration.js",
"jsdoc": "jsdoc -c config/jsdocs.config.js", "jsdoc": "jsdoc -c config/jsdocs.config.js",
"lint:eslint": "yarn run internal:eslint", "lint:eslint": "yarn run internal:eslint",
......
#!/usr/bin/env ruby
# frozen_string_literal: true
require 'gitlab'
gitlab_token = ENV.fetch('DANGER_GITLAB_API_TOKEN', '')
gitlab_endpoint = ENV.fetch('CI_API_V4_URL')
mr_project_path = ENV.fetch('CI_MERGE_REQUEST_PROJECT_PATH')
mr_iid = ENV.fetch('CI_MERGE_REQUEST_IID')
output_file = ARGV.shift
Gitlab.configure do |config|
config.endpoint = gitlab_endpoint
config.private_token = gitlab_token
end
mr_changes = Gitlab.merge_request_changes(mr_project_path, mr_iid)
file_changes = mr_changes.changes.map { |change| change['new_path'] }
File.write(output_file, file_changes.join(' '))
#!/usr/bin/env ruby #!/usr/bin/env ruby
# frozen_string_literal: true # frozen_string_literal: true
require 'gitlab'
require 'test_file_finder' require 'test_file_finder'
gitlab_token = ENV.fetch('DANGER_GITLAB_API_TOKEN', '') changes = ARGV.shift
gitlab_endpoint = ENV.fetch('CI_API_V4_URL')
Gitlab.configure do |config|
config.endpoint = gitlab_endpoint
config.private_token = gitlab_token
end
output_file = ARGV.shift output_file = ARGV.shift
mr_project_path = ENV.fetch('CI_MERGE_REQUEST_PROJECT_PATH') changed_files = File.read(changes).split(' ')
mr_iid = ENV.fetch('CI_MERGE_REQUEST_IID')
mr_changes = Gitlab.merge_request_changes(mr_project_path, mr_iid)
changed_files = mr_changes.changes.map { |change| change['new_path'] }
tff = TestFileFinder::FileFinder.new(paths: changed_files).tap do |file_finder| tff = TestFileFinder::FileFinder.new(paths: changed_files).tap do |file_finder|
file_finder.use TestFileFinder::MappingStrategies::PatternMatching.load('tests.yml') file_finder.use TestFileFinder::MappingStrategies::PatternMatching.load('tests.yml')
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment