diff --git a/.gitlab/ci/caching.gitlab-ci.yml b/.gitlab/ci/caching.gitlab-ci.yml index 0b20b86ab7c6a99d4844046902f8b5634bf0fc7f..8dfb76ac86fc3d8dfc787f6ffe67b52a9c789dd9 100644 --- a/.gitlab/ci/caching.gitlab-ci.yml +++ b/.gitlab/ci/caching.gitlab-ci.yml @@ -102,6 +102,23 @@ cache:workhorse-hash: reports: dotenv: build.env +#================================= +# node_modules +#================================= + +cache:node-modules-hash: + extends: + - .cache-pull-push-base + - .with-alpine-ruby-image + - .caching:rules:update-cache-on-code-changes + script: + - echo "GLCI_NODE_MODULES_HASH=$(ruby scripts/lib/node_modules_sha.rb)" > build.env + - echo "Calculated node modules checksum - $(cat build.env)" + artifacts: + reports: + dotenv: build.env + + #================================= # Frontend #================================= @@ -118,6 +135,9 @@ cache:assets-hash: dotenv: build.env allow_failure: false +#================================= +# FE Islands +#================================= cache:frontend-islands-hash: extends: - .cache-pull-push-base diff --git a/.gitlab/ci/docs.gitlab-ci.yml b/.gitlab/ci/docs.gitlab-ci.yml index a6fa77557a9b8cb6b1b70411cee7ae1bdd7c26e4..f2e149f493797c85fb38b030c21a30b2a7849f5d 100644 --- a/.gitlab/ci/docs.gitlab-ci.yml +++ b/.gitlab/ci/docs.gitlab-ci.yml @@ -70,7 +70,8 @@ docs-lint mermaid: - .docs-markdown-lint-image - .yarn-cache stage: lint - needs: [] + needs: + - job: cache:node-modules-hash script: - source ./scripts/utils.sh - yarn_install_script diff --git a/.gitlab/ci/frontend.gitlab-ci.yml b/.gitlab/ci/frontend.gitlab-ci.yml index 3e3b24573426ea3dd5eac07ce9d2c3b8d8a7601c..f02e5dfaeb0a9dfffef5ce2b59188c1508f5fa76 100644 --- a/.gitlab/ci/frontend.gitlab-ci.yml +++ b/.gitlab/ci/frontend.gitlab-ci.yml @@ -26,6 +26,7 @@ WEBPACK_COMPILE_LOG_PATH: "tmp/webpack-output.log" stage: prepare needs: + - cache:node-modules-hash - cache:assets-hash - job: cache:frontend-islands-hash optional: true @@ -99,6 +100,7 @@ build-vite-prod: - .frontend:rules:compile-production-assets stage: prepare needs: + - job: cache:node-modules-hash - job: cache:node-modules optional: true script: @@ -255,6 +257,7 @@ upload-graphql-schema-dump: - !reference [.yarn-cache, cache] - !reference [.frontend-islands-cache-pull] needs: + - job: cache:node-modules-hash - job: cache:frontend-islands-hash optional: true @@ -587,6 +590,7 @@ coverage-frontend: - .frontend:rules:coverage-frontend needs: - !reference [.repo-from-artifacts, needs] + - job: cache:node-modules-hash - job: "jest" optional: true - job: "jest-with-fixtures" @@ -620,6 +624,10 @@ webpack-dev-server: - .repo-from-artifacts - .frontend:rules:default-frontend-jobs stage: test-frontend + needs: + - job: cache:node-modules-hash + - job: clone-gitlab-repo + optional: true variables: WEBPACK_MEMORY_TEST: "true" WEBPACK_VENDOR_DLL: "true" @@ -645,6 +653,7 @@ compile-storybook: - !reference [.repo-from-artifacts, needs] - !reference [.with-fixtures-needs, needs] - !reference [.with-graphql-schema-dump-needs, needs] + - job: cache:node-modules-hash - job: cache:frontend-islands-hash optional: true artifacts: @@ -669,6 +678,7 @@ test-storybook: - !reference [.repo-from-artifacts, needs] - !reference [.with-fixtures-needs, needs] - !reference [.with-graphql-schema-dump-needs, needs] + - job: cache:node-modules-hash - job: cache:frontend-islands-hash optional: true allow_failure: true diff --git a/.gitlab/ci/global.gitlab-ci.yml b/.gitlab/ci/global.gitlab-ci.yml index 575d9540823cc3aa051009ed7ebd0873a8e0b247..5fb2f539d8f92dfd37a98468a5766fc451fc7b0c 100644 --- a/.gitlab/ci/global.gitlab-ci.yml +++ b/.gitlab/ci/global.gitlab-ci.yml @@ -444,11 +444,7 @@ policy: pull-push .node-modules-cache: &node-modules-cache - key: - files: - - yarn.lock - - ee/frontend_islands/apps/duo_next/yarn.lock - prefix: node-modules-${BUILD_OS}-${OS_VERSION}-${NODE_ENV}-node-${NODE_VERSION} + key: "node-modules-${BUILD_OS}-${OS_VERSION}-${NODE_ENV}-node-${NODE_VERSION}-${GLCI_NODE_MODULES_HASH}" paths: - node_modules/ - ee/frontend_islands/apps/duo_next/node_modules/ @@ -542,6 +538,7 @@ .static-analysis-cache: extends: .cache-analytics + needs: ["cache:node-modules-hash"] cache: - !reference [.ruby-gems-cache] - *node-modules-cache @@ -558,6 +555,7 @@ - *rubocop-cache-push .ruby-node-cache: + needs: ["cache:node-modules-hash"] cache: - !reference [.ruby-gems-cache] - *node-modules-cache @@ -572,10 +570,12 @@ policy: pull-push .yarn-cache: + needs: ["cache:node-modules-hash"] cache: - *node-modules-cache .yarn-cache-pull-push: + needs: ["cache:node-modules-hash"] cache: <<: *node-modules-cache policy: pull-push @@ -583,6 +583,7 @@ .assets-compile-cache: extends: - .cache-analytics + needs: ["cache:node-modules-hash"] cache: - !reference [.ruby-gems-cache] - *node-modules-cache @@ -592,6 +593,7 @@ .assets-compile-cache-pull: # this cache is used only for gdk:compile-test-assets which should only pull, never push extends: - .cache-analytics + needs: ["cache:node-modules-hash"] cache: - !reference [.ruby-gems-cache] - *node-modules-cache @@ -600,11 +602,13 @@ policy: pull .storybook-yarn-cache: + needs: ["cache:node-modules-hash"] cache: - *node-modules-cache - *storybook-node-modules-cache .storybook-yarn-cache-pull-push: + needs: ["cache:node-modules-hash"] cache: - *node-modules-cache - *storybook-node-modules-cache-pull-push diff --git a/.gitlab/ci/includes/gitlab-com/danger-review.gitlab-ci.yml b/.gitlab/ci/includes/gitlab-com/danger-review.gitlab-ci.yml index 4f6565055629953f5adf0554a004c030495a2617..aace5a7828c2789292e2798905e81fa63455ecab 100644 --- a/.gitlab/ci/includes/gitlab-com/danger-review.gitlab-ci.yml +++ b/.gitlab/ci/includes/gitlab-com/danger-review.gitlab-ci.yml @@ -16,6 +16,7 @@ danger-review: needs: - job: cache:ruby-gems optional: true + - job: cache:node-modules-hash - job: cache:node-modules optional: true variables: diff --git a/.gitlab/ci/preflight.gitlab-ci.yml b/.gitlab/ci/preflight.gitlab-ci.yml index cf997340b49b5219eeb4c31a00efee6ff63656ed..e969e223115bb14d52b19deaeac35001df2983b6 100644 --- a/.gitlab/ci/preflight.gitlab-ci.yml +++ b/.gitlab/ci/preflight.gitlab-ci.yml @@ -79,6 +79,10 @@ bundle-size-review: - .repo-from-artifacts - .frontend:rules:bundle-size-review stage: preflight + needs: + - job: clone-gitlab-repo + optional: true + - job: cache:node-modules-hash variables: SETUP_DB: "false" script: diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml index 7ae8a1adce9b03432ac40a75c91d734042a7d667..346a6da5aae6db9b5a5a761a7144f01daa2fb3ec 100644 --- a/.gitlab/ci/rules.gitlab-ci.yml +++ b/.gitlab/ci/rules.gitlab-ci.yml @@ -646,6 +646,12 @@ - "{,ee/,jh/}spec/**/*" - "scripts/**/*" - "{,spec/}tooling/**/*" + # FE island changes + - "ee/frontend_islands/apps/**/.{gitattributes,nvmrc,prettierrc,stylelintrc,yamllint}" + - "ee/frontend_islands/apps/**/{package.json,yarn.lock}" + - "ee/frontend_islands/apps/**/tsconfig*.json" + - "ee/frontend_islands/apps/**/components.json" + - "ee/frontend_islands/apps/**/*.config.{js,ts,cjs,mjs}" # .code-patterns + .qa-patterns .code-qa-patterns: &code-qa-patterns diff --git a/.gitlab/ci/static-analysis.gitlab-ci.yml b/.gitlab/ci/static-analysis.gitlab-ci.yml index 84873dca5a3334fb98b04edbeed01f5345fd4bd1..7e77018691a7baf11b2be57d58f8f6c7dd49efbf 100644 --- a/.gitlab/ci/static-analysis.gitlab-ci.yml +++ b/.gitlab/ci/static-analysis.gitlab-ci.yml @@ -21,6 +21,7 @@ static-analysis: needs: - job: cache:ruby-gems optional: true + - job: cache:node-modules-hash - job: cache:node-modules optional: true - job: db:setup pg16 @@ -122,6 +123,8 @@ eslint-docs: - .static-analysis-base - .yarn-cache - .frontend:rules:default-frontend-jobs-with-docs-changes + needs: + - job: cache:node-modules-hash variables: USE_BUNDLE_INSTALL: "false" script: diff --git a/.gitlab/ci/test-metadata.gitlab-ci.yml b/.gitlab/ci/test-metadata.gitlab-ci.yml index d46ffcca831c60d73869d50c701fb668a37f72c9..51fe8c2d144e4eff8b16fdda7f418b94e9f0d9cf 100644 --- a/.gitlab/ci/test-metadata.gitlab-ci.yml +++ b/.gitlab/ci/test-metadata.gitlab-ci.yml @@ -77,6 +77,10 @@ export-predictive-test-metrics: - .predictive:rules:default variables: GLCI_PREDICTIVE_TEST_METRICS_OUTPUT_DIR: "tmp/predictive_tests" + needs: + - cache:node-modules-hash + - graphql-schema-dump + - retrieve-tests-metadata dependencies: # required to generate predictive jest test list - graphql-schema-dump diff --git a/scripts/lib/node_modules_sha.rb b/scripts/lib/node_modules_sha.rb new file mode 100644 index 0000000000000000000000000000000000000000..cfe73c86cf1099c20d03912dc3f616e1433a7b65 --- /dev/null +++ b/scripts/lib/node_modules_sha.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +require "digest" + +module NodeModulesSha + # Node.js dependency files that impact node_modules installation + NODE_MODULES_FILES = %w[ + yarn.lock + package.json + ee/frontend_islands/apps/duo_next/yarn.lock + ee/frontend_islands/apps/duo_next/package.json + ].freeze + + class << self + def sha256_of_node_modules_impacting_compilation + node_modules_sha256 = node_modules_impacting_compilation.map do |file| + Digest::SHA256.file(file).hexdigest + end.join + + Digest::SHA256.hexdigest(node_modules_sha256) + end + + private + + def node_modules_impacting_compilation + NODE_MODULES_FILES.select { |file| File.exist?(file) && File.file?(file) }.sort + end + end +end + +printf NodeModulesSha.sha256_of_node_modules_impacting_compilation if __FILE__ == $PROGRAM_NAME