-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ci: Improve CI dependency checks (#13175)
This PR updates the way we detect changed packages to rely on Nx under the hood, which should always be in sync. Previously, we hard-coded paths in the GH workflow to determine which packages have been changed, so we can make sure to run tests accordingly. Now, we use Nx to detect this for PRs - this takes the dependency graph into consideration and should always be up-to-date. We just need to make sure to have correct dependencies defined, also for dev packages like node-integration-tests (see addition I made there). Note: For profiling-node, we still check the old way, because we want to avoid re-running this every time a dependency of profiling-node changes - because that depends on e.g. core and utils, and we don't want to/need to re-run this all the time. This PR does two other things: 1. Enable global yarn cache - this may help us reduce install time on CI 2. Merge the install & build CI steps - these were run in parallel, which in reality only ate up about 50s, because this is how long it takes to restore the dependency cache, which had to happen in the build step. By merging this, min. time for install + build for a fully cached scenario is down to ~1:15 minutes, where previously it was >2 minutes across the two steps. Example runs: * Change in packages/browser: https://github.com/getsentry/sentry-javascript/actions/runs/10215948246 * Change in packages/core: https://github.com/getsentry/sentry-javascript/actions/runs/10215944443 * Change in packages/profiling-node: https://github.com/getsentry/sentry-javascript/actions/runs/10216003595
- Loading branch information
Showing
2 changed files
with
67 additions
and
136 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -73,6 +73,7 @@ jobs: | |
# We need to check out not only the fake merge commit between the PR and the base branch which GH creates, but | ||
# also its parents, so that we can pull the commit message from the head commit of the PR | ||
fetch-depth: 2 | ||
|
||
- name: Get metadata | ||
id: get_metadata | ||
# We need to try a number of different options for finding the head commit, because each kind of trigger event | ||
|
@@ -82,101 +83,32 @@ jobs: | |
echo "COMMIT_SHA=$COMMIT_SHA" >> $GITHUB_ENV | ||
echo "COMMIT_MESSAGE=$(git log -n 1 --pretty=format:%s $COMMIT_SHA)" >> $GITHUB_ENV | ||
# Most changed packages are determined in job_build via Nx | ||
# However, for profiling-node we only want to run certain things when in this specific package | ||
# something changed, not in any of the dependencies (which include core, utils, ...) | ||
- name: Determine changed packages | ||
uses: dorny/[email protected] | ||
id: changed | ||
with: | ||
filters: | | ||
workflow: &workflow | ||
workflow: | ||
- '.github/**' | ||
shared: &shared | ||
- *workflow | ||
- '*.{js,ts,json,yml,lock}' | ||
- 'CHANGELOG.md' | ||
- 'jest/**' | ||
- 'scripts/**' | ||
- 'packages/core/**' | ||
- 'packages/rollup-utils/**' | ||
- 'packages/utils/**' | ||
- 'packages/types/**' | ||
- 'dev-packages/test-utils/**' | ||
browser: &browser | ||
- *shared | ||
- 'packages/browser/**' | ||
- 'packages/browser-utils/**' | ||
- 'packages/replay-internal/**' | ||
- 'packages/replay-worker/**' | ||
- 'packages/replay-canvas/**' | ||
- 'packages/feedback/**' | ||
- 'packages/wasm/**' | ||
node: &node | ||
- *shared | ||
- 'packages/node/**' | ||
- 'packages/opentelemetry/**' | ||
browser_integration: | ||
- *shared | ||
- *browser | ||
- 'dev-packages/browser-integration-tests/**' | ||
ember: | ||
- *shared | ||
- *browser | ||
- 'packages/ember/**' | ||
node_integration: | ||
- *shared | ||
- *node | ||
- 'dev-packages/node-integration-tests/**' | ||
- 'packages/nestjs/**' | ||
nextjs: | ||
- *shared | ||
- *browser | ||
- *node | ||
- 'packages/nextjs/**' | ||
- 'packages/react/**' | ||
- 'packages/vercel-edge/**' | ||
remix: | ||
- *shared | ||
- *browser | ||
- *node | ||
- 'packages/remix/**' | ||
- 'packages/react/**' | ||
profiling_node: | ||
- *shared | ||
- 'packages/node/**' | ||
- 'packages/profiling-node/**' | ||
- 'dev-packages/e2e-tests/test-applications/node-profiling/**' | ||
profiling_node_bindings: | ||
- 'packages/profiling-node/**' | ||
- 'dev-packages/e2e-tests/test-applications/node-profiling/**' | ||
deno: | ||
- *shared | ||
- 'packages/deno/**' | ||
bun: | ||
- *shared | ||
- 'packages/bun/**' | ||
any_code: | ||
- '!**/*.md' | ||
- name: Get PR labels | ||
id: pr-labels | ||
uses: mydea/pr-labels-action@fn/bump-node20 | ||
|
||
outputs: | ||
commit_label: '${{ env.COMMIT_SHA }}: ${{ env.COMMIT_MESSAGE }}' | ||
changed_nextjs: ${{ steps.changed.outputs.nextjs }} | ||
changed_ember: ${{ steps.changed.outputs.ember }} | ||
changed_remix: ${{ steps.changed.outputs.remix }} | ||
changed_node: ${{ steps.changed.outputs.node }} | ||
changed_node_integration: ${{ steps.changed.outputs.node_integration }} | ||
changed_profiling_node: ${{ steps.changed.outputs.profiling_node }} | ||
changed_profiling_node_bindings: ${{ steps.changed.outputs.profiling_node_bindings }} | ||
changed_deno: ${{ steps.changed.outputs.deno }} | ||
changed_bun: ${{ steps.changed.outputs.bun }} | ||
changed_browser: ${{ steps.changed.outputs.browser }} | ||
changed_browser_integration: ${{ steps.changed.outputs.browser_integration }} | ||
changed_any_code: ${{ steps.changed.outputs.any_code }} | ||
# Note: These next three have to be checked as strings ('true'/'false')! | ||
is_develop: ${{ github.ref == 'refs/heads/develop' }} | ||
is_release: ${{ startsWith(github.ref, 'refs/heads/release/') }} | ||
changed_profiling_node: ${{ steps.changed.outputs.profiling_node == 'true' }} | ||
changed_ci: ${{ steps.changed.outputs.workflow == 'true' }} | ||
# When merging into master, or from master | ||
is_gitflow_sync: ${{ github.head_ref == 'master' || github.ref == 'refs/heads/master' }} | ||
has_gitflow_label: | ||
|
@@ -185,22 +117,30 @@ jobs: | |
${{ github.event_name == 'schedule' || (github.event_name == 'pull_request' && | ||
contains(steps.pr-labels.outputs.labels, ' ci-skip-cache ')) }} | ||
|
||
job_install_deps: | ||
name: Install Dependencies | ||
job_build: | ||
name: Build | ||
needs: job_get_metadata | ||
runs-on: ubuntu-20.04 | ||
timeout-minutes: 15 | ||
if: | | ||
(needs.job_get_metadata.outputs.is_gitflow_sync == 'false' && needs.job_get_metadata.outputs.has_gitflow_label == 'false') | ||
steps: | ||
- name: Check out base commit (${{ github.event.pull_request.base.sha }}) | ||
uses: actions/checkout@v4 | ||
if: github.event_name == 'pull_request' | ||
with: | ||
ref: ${{ github.event.pull_request.base.sha }} | ||
|
||
- name: 'Check out current commit (${{ needs.job_get_metadata.outputs.commit_label }})' | ||
uses: actions/checkout@v4 | ||
with: | ||
ref: ${{ env.HEAD_COMMIT }} | ||
|
||
- name: Set up Node | ||
uses: actions/setup-node@v4 | ||
with: | ||
node-version-file: 'package.json' | ||
|
||
# we use a hash of yarn.lock as our cache key, because if it hasn't changed, our dependencies haven't changed, | ||
# so no need to reinstall them | ||
- name: Compute dependency cache key | ||
|
@@ -217,46 +157,14 @@ jobs: | |
- name: Install dependencies | ||
if: steps.cache_dependencies.outputs.cache-hit != 'true' | ||
run: yarn install --ignore-engines --frozen-lockfile | ||
outputs: | ||
dependency_cache_key: ${{ steps.compute_lockfile_hash.outputs.hash }} | ||
|
||
job_check_branches: | ||
name: Check PR branches | ||
needs: job_get_metadata | ||
runs-on: ubuntu-20.04 | ||
if: github.event_name == 'pull_request' | ||
permissions: | ||
pull-requests: write | ||
steps: | ||
- name: PR is opened against master | ||
uses: mshick/add-pr-comment@dd126dd8c253650d181ad9538d8b4fa218fc31e8 | ||
if: ${{ github.base_ref == 'master' && !startsWith(github.head_ref, 'prepare-release/') }} | ||
with: | ||
message: | | ||
⚠️ This PR is opened against **master**. You probably want to open it against **develop**. | ||
|
||
job_build: | ||
name: Build | ||
needs: [job_get_metadata, job_install_deps] | ||
runs-on: ubuntu-20.04-large-js | ||
timeout-minutes: 30 | ||
if: | | ||
(needs.job_get_metadata.outputs.changed_any_code == 'true' || github.event_name != 'pull_request') | ||
steps: | ||
- name: Check out current commit (${{ needs.job_get_metadata.outputs.commit_label }}) | ||
uses: actions/checkout@v4 | ||
with: | ||
ref: ${{ env.HEAD_COMMIT }} | ||
- name: Set up Node | ||
uses: actions/setup-node@v4 | ||
with: | ||
node-version-file: 'package.json' | ||
- name: Check dependency cache | ||
uses: actions/cache/restore@v4 | ||
- name: Check for Affected Nx Projects | ||
uses: dkhunt27/[email protected] | ||
id: checkForAffected | ||
if: github.event_name == 'pull_request' | ||
with: | ||
path: ${{ env.CACHED_DEPENDENCY_PATHS }} | ||
key: ${{ needs.job_install_deps.outputs.dependency_cache_key }} | ||
fail-on-cache-miss: true | ||
base: ${{ github.event.pull_request.base.sha }} | ||
head: ${{ env.HEAD_COMMIT }} | ||
|
||
- name: Check build cache | ||
uses: actions/cache@v4 | ||
|
@@ -285,10 +193,31 @@ jobs: | |
env: | ||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} | ||
run: yarn build | ||
|
||
outputs: | ||
# this needs to be passed on, because the `needs` context only looks at direct ancestors (so steps which depend on | ||
# `job_build` can't see `job_install_deps` and what it returned) | ||
dependency_cache_key: ${{ needs.job_install_deps.outputs.dependency_cache_key }} | ||
dependency_cache_key: ${{ steps.compute_lockfile_hash.outputs.hash }} | ||
changed_node_integration: ${{ needs.job_get_metadata.outputs.changed_ci == 'true' || contains(steps.checkForAffected.outputs.affected, '@sentry-internal/node-integration-tests') }} | ||
changed_remix: ${{ needs.job_get_metadata.outputs.changed_ci == 'true' || contains(steps.checkForAffected.outputs.affected, '@sentry/remix') }} | ||
changed_node: ${{ needs.job_get_metadata.outputs.changed_ci == 'true' || contains(steps.checkForAffected.outputs.affected, '@sentry/node') }} | ||
changed_deno: ${{ needs.job_get_metadata.outputs.changed_ci == 'true' || contains(steps.checkForAffected.outputs.affected, '@sentry/deno') }} | ||
changed_bun: ${{ needs.job_get_metadata.outputs.changed_ci == 'true' || contains(steps.checkForAffected.outputs.affected, '@sentry/bun') }} | ||
changed_browser_integration: ${{ needs.job_get_metadata.outputs.changed_ci == 'true' || contains(steps.checkForAffected.outputs.affected, '@sentry-internal/browser-integration-tests') }} | ||
# If you are looking for changed_profiling_node, this is defined in job_get_metadata | ||
|
||
job_check_branches: | ||
name: Check PR branches | ||
needs: job_get_metadata | ||
runs-on: ubuntu-20.04 | ||
if: github.event_name == 'pull_request' | ||
permissions: | ||
pull-requests: write | ||
steps: | ||
- name: PR is opened against master | ||
uses: mshick/add-pr-comment@dd126dd8c253650d181ad9538d8b4fa218fc31e8 | ||
if: ${{ github.base_ref == 'master' && !startsWith(github.head_ref, 'prepare-release/') }} | ||
with: | ||
message: | | ||
⚠️ This PR is opened against **master**. You probably want to open it against **develop**. | ||
job_size_check: | ||
name: Size Check | ||
|
@@ -345,7 +274,7 @@ jobs: | |
|
||
job_check_format: | ||
name: Check file formatting | ||
needs: [job_get_metadata, job_install_deps] | ||
needs: [job_get_metadata, job_build] | ||
timeout-minutes: 10 | ||
runs-on: ubuntu-20.04 | ||
steps: | ||
|
@@ -361,7 +290,7 @@ jobs: | |
uses: actions/cache/restore@v4 | ||
with: | ||
path: ${{ env.CACHED_DEPENDENCY_PATHS }} | ||
key: ${{ needs.job_install_deps.outputs.dependency_cache_key }} | ||
key: ${{ needs.job_build.outputs.dependency_cache_key }} | ||
fail-on-cache-miss: true | ||
- name: Check file formatting | ||
run: yarn lint:prettier && yarn lint:biome | ||
|
@@ -437,6 +366,7 @@ jobs: | |
steps: | ||
- name: Check out base commit (${{ github.event.pull_request.base.sha }}) | ||
uses: actions/checkout@v4 | ||
if: github.event_name == 'pull_request' | ||
with: | ||
ref: ${{ github.event.pull_request.base.sha }} | ||
|
||
|
@@ -469,7 +399,7 @@ jobs: | |
job_bun_unit_tests: | ||
name: Bun Unit Tests | ||
needs: [job_get_metadata, job_build] | ||
if: needs.job_get_metadata.outputs.changed_bun == 'true' || github.event_name != 'pull_request' | ||
if: needs.job_build.outputs.changed_bun == 'true' || github.event_name != 'pull_request' | ||
timeout-minutes: 10 | ||
runs-on: ubuntu-20.04 | ||
strategy: | ||
|
@@ -496,7 +426,7 @@ jobs: | |
job_deno_unit_tests: | ||
name: Deno Unit Tests | ||
needs: [job_get_metadata, job_build] | ||
if: needs.job_get_metadata.outputs.changed_deno == 'true' || github.event_name != 'pull_request' | ||
if: needs.job_build.outputs.changed_deno == 'true' || github.event_name != 'pull_request' | ||
timeout-minutes: 10 | ||
runs-on: ubuntu-20.04 | ||
strategy: | ||
|
@@ -536,6 +466,7 @@ jobs: | |
steps: | ||
- name: Check out base commit (${{ github.event.pull_request.base.sha }}) | ||
uses: actions/checkout@v4 | ||
if: github.event_name == 'pull_request' | ||
with: | ||
ref: ${{ github.event.pull_request.base.sha }} | ||
- name: Check out current commit (${{ needs.job_get_metadata.outputs.commit_label }}) | ||
|
@@ -571,7 +502,7 @@ jobs: | |
job_profiling_node_unit_tests: | ||
name: Node Profiling Unit Tests | ||
needs: [job_get_metadata, job_build] | ||
if: needs.job_get_metadata.outputs.changed_node == 'true' || needs.job_get_metadata.outputs.changed_profiling_node == 'true' || github.event_name != 'pull_request' | ||
if: needs.job_build.outputs.changed_node == 'true' || needs.job_get_metadata.outputs.changed_profiling_node == 'true' || github.event_name != 'pull_request' | ||
runs-on: ubuntu-latest | ||
timeout-minutes: 10 | ||
steps: | ||
|
@@ -599,7 +530,7 @@ jobs: | |
job_browser_playwright_tests: | ||
name: Playwright (${{ matrix.bundle }}${{ matrix.shard && format(' {0}/{1}', matrix.shard, matrix.shards) || ''}}) Tests | ||
needs: [job_get_metadata, job_build] | ||
if: needs.job_get_metadata.outputs.changed_browser_integration == 'true' || github.event_name != 'pull_request' | ||
if: needs.job_build.outputs.changed_browser_integration == 'true' || github.event_name != 'pull_request' | ||
runs-on: ubuntu-20.04-large-js | ||
timeout-minutes: 25 | ||
strategy: | ||
|
@@ -674,11 +605,10 @@ jobs: | |
name: playwright-traces | ||
path: dev-packages/browser-integration-tests/test-results | ||
|
||
|
||
job_browser_loader_tests: | ||
name: Playwright Loader (${{ matrix.bundle }}) Tests | ||
needs: [job_get_metadata, job_build] | ||
if: needs.job_get_metadata.outputs.changed_browser_integration == 'true' || github.event_name != 'pull_request' | ||
if: needs.job_build.outputs.changed_browser_integration == 'true' || github.event_name != 'pull_request' | ||
runs-on: ubuntu-20.04 | ||
timeout-minutes: 15 | ||
strategy: | ||
|
@@ -748,13 +678,12 @@ jobs: | |
exit 1 | ||
fi | ||
job_node_integration_tests: | ||
name: | ||
Node (${{ matrix.node }})${{ (matrix.typescript && format(' (TS {0})', matrix.typescript)) || '' }} Integration | ||
Tests | ||
needs: [job_get_metadata, job_build] | ||
if: needs.job_get_metadata.outputs.changed_node_integration == 'true' || github.event_name != 'pull_request' | ||
if: needs.job_build.outputs.changed_node_integration == 'true' || github.event_name != 'pull_request' | ||
runs-on: ubuntu-20.04 | ||
timeout-minutes: 15 | ||
strategy: | ||
|
@@ -796,7 +725,7 @@ jobs: | |
job_remix_integration_tests: | ||
name: Remix v${{ matrix.remix }} (Node ${{ matrix.node }}) Tests | ||
needs: [job_get_metadata, job_build] | ||
if: needs.job_get_metadata.outputs.changed_remix == 'true' || github.event_name != 'pull_request' | ||
if: needs.job_build.outputs.changed_remix == 'true' || github.event_name != 'pull_request' | ||
runs-on: ubuntu-20.04 | ||
timeout-minutes: 10 | ||
strategy: | ||
|
@@ -866,14 +795,14 @@ jobs: | |
# Rebuild profiling by compiling TS and pull the precompiled binary artifacts | ||
- name: Build Profiling Node | ||
if: | | ||
(needs.job_get_metadata.outputs.changed_profiling_node_bindings == 'true') || | ||
(needs.job_get_metadata.outputs.changed_profiling_node == 'true') || | ||
(needs.job_get_metadata.outputs.is_release == 'true') || | ||
(github.event_name != 'pull_request') | ||
run: yarn lerna run build:lib --scope @sentry/profiling-node | ||
|
||
- name: Extract Profiling Node Prebuilt Binaries | ||
if: | | ||
(needs.job_get_metadata.outputs.changed_profiling_node_bindings == 'true') || | ||
(needs.job_get_metadata.outputs.changed_profiling_node == 'true') || | ||
(needs.job_get_metadata.outputs.is_release == 'true') || | ||
(github.event_name != 'pull_request') | ||
uses: actions/download-artifact@v4 | ||
|
@@ -1167,7 +1096,7 @@ jobs: | |
always() && needs.job_e2e_prepare.result == 'success' && | ||
(github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) && | ||
( | ||
(needs.job_get_metadata.outputs.changed_profiling_node_bindings == 'true') || | ||
(needs.job_get_metadata.outputs.changed_profiling_node == 'true') || | ||
(needs.job_get_metadata.outputs.is_release == 'true') || | ||
(github.event_name != 'pull_request') | ||
) | ||
|
@@ -1320,11 +1249,11 @@ jobs: | |
|
||
job_compile_bindings_profiling_node: | ||
name: Compile & Test Profiling Bindings (v${{ matrix.node }}) ${{ matrix.target_platform || matrix.os }}, ${{ matrix.node || matrix.container }}, ${{ matrix.arch || matrix.container }}, ${{ contains(matrix.container, 'alpine') && 'musl' || 'glibc' }} | ||
needs: [job_get_metadata, job_install_deps, job_build] | ||
needs: [job_get_metadata, job_build] | ||
# Compiling bindings can be very slow (especially on windows), so only run precompile | ||
# Skip precompile unless we are on a release branch as precompile slows down CI times. | ||
if: | | ||
(needs.job_get_metadata.outputs.changed_profiling_node_bindings == 'true') || | ||
(needs.job_get_metadata.outputs.changed_profiling_node == 'true') || | ||
(needs.job_get_metadata.outputs.is_release == 'true') || | ||
(github.event_name != 'pull_request') | ||
runs-on: ${{ matrix.os }} | ||
|
@@ -1481,7 +1410,7 @@ jobs: | |
id: restore-dependencies | ||
with: | ||
path: ${{ env.CACHED_DEPENDENCY_PATHS }} | ||
key: ${{ needs.job_install_deps.outputs.dependency_cache_key }} | ||
key: ${{ needs.job_build.outputs.dependency_cache_key }} | ||
enableCrossOsArchive: true | ||
|
||
- name: Restore build cache | ||
|
Oops, something went wrong.