Skip to content

Commit 0a9f978

Browse files
committed
refactor(workflow): improve workflows efficiency and performance
1 parent fe5fbf6 commit 0a9f978

11 files changed

Lines changed: 391 additions & 91 deletions

File tree

.github/workflows/ci.yml

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ permissions:
2222
env:
2323
CDWR_DEBUG_LOGGING: true
2424
NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }}
25-
NX_NO_CLOUD: ${{ startsWith(github.head_ref || github.ref_name, 'renovate') || vars.NX_NO_CLOUD }}
25+
NX_NO_CLOUD: ${{ startsWith(github.head_ref || github.ref_name, 'renovate') || github.event_name == 'push' || github.event_name == 'workflow_dispatch' || vars.NX_NO_CLOUD }}
2626
NX_PARALLEL: ${{ vars.NX_PARALLEL }}
2727
NX_VERBOSE_LOGGING: ${{ vars.NX_VERBOSE_LOGGING }}
2828

@@ -60,7 +60,13 @@ jobs:
6060
- name: Analyze affected projects
6161
uses: nrwl/nx-set-shas@v4
6262

63-
- run: pnpm nx-cloud record -- nx format:check
63+
- name: Format check (Nx Cloud)
64+
if: env.NX_NO_CLOUD != 'true'
65+
run: pnpm nx-cloud record -- nx format:check
66+
67+
- name: Format check
68+
if: env.NX_NO_CLOUD == 'true'
69+
run: pnpm nx format:check
6470

6571
- run: pnpm nx affected -t lint,test,build -c ci
6672

@@ -76,6 +82,15 @@ jobs:
7682
INFISICAL_TEST_SERVICE_TOKEN: ${{ secrets.INFISICAL_TEST_SERVICE_TOKEN }}
7783
INFISICAL_TEST_SITE: ${{ vars.INFISICAL_SITE }}
7884

85+
- name: Linux e2e smoke (pnpm)
86+
run: pnpm nx e2e nx-payload-e2e -c skip-docker
87+
env:
88+
CDWR_E2E_PACKAGE_MANAGER: pnpm
89+
CDWR_E2E_VERDACCIO_HOST: localhost
90+
NX_CACHE_DIRECTORY: tmp
91+
NX_PERF_LOGGING: false
92+
NODE_OPTIONS: --max_old_space_size=4096
93+
7994
- name: Nx Self-healing CI
8095
run: pnpm nx fix-ci
8196

.github/workflows/e2e-matrix.yml

Lines changed: 174 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,28 @@
1-
name: E2E matrix
1+
name: Nightly E2E Matrix
22

33
on:
4+
schedule:
5+
# Weekdays at 05:00 UTC
6+
- cron: 0 5 * * 1-5
7+
push:
8+
branches:
9+
- main
10+
workflow_dispatch:
411
pull_request:
512
types:
13+
- labeled
614
- opened
715
- reopened
816
- synchronize
9-
merge_group:
10-
push:
11-
branches:
12-
- main
13-
workflow_dispatch:
1417

1518
# Environment details:
16-
# - renovate branches should never use Nx Cloud
19+
# - Nx Cloud disabled unless NX_E2E_USE_CLOUD repo variable is 'true' and branch is not renovate
20+
# - Full matrix runs nightly, on main pushes, manual triggers, or PRs labeled "full-e2e"
1721
env:
1822
CDWR_DEBUG_LOGGING: true
1923
IS_RENOVATE: ${{ startsWith(github.head_ref || github.ref_name, 'renovate') }}
2024
NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }}
21-
NX_NO_CLOUD: ${{ startsWith(github.head_ref || github.ref_name, 'renovate') || vars.NX_NO_CLOUD }}
25+
NX_NO_CLOUD: ${{ startsWith(github.head_ref || github.ref_name, 'renovate') || vars.NX_E2E_USE_CLOUD != 'true' }}
2226
NX_DAEMON: ${{ vars.NX_DAEMON }}
2327
NX_PARALLEL: ${{ vars.NX_PARALLEL }}
2428
NX_VERBOSE_LOGGING: ${{ vars.NX_VERBOSE_LOGGING }}
@@ -31,21 +35,98 @@ jobs:
3135
init:
3236
runs-on: ubuntu-latest
3337
outputs:
34-
e2e-enabled: ${{ steps.e2e-enabled.outputs.status }}
38+
e2e-enabled: ${{ steps.gate.outputs.run_status == 'true' && (steps.gate.outputs.reason == 'manual' || steps.affected.outputs.affected == 'true') }}
39+
projects: ${{ steps.affected.outputs.projects }}
40+
reason: ${{ steps.gate.outputs.reason }}
3541
steps:
36-
# Disable e2e for
37-
# - merge groups unless it's renovate
38-
# - renovate pull requests
39-
- name: Whether e2e is enabled
40-
id: e2e-enabled
42+
- name: Determine matrix request
43+
id: gate
44+
env:
45+
EVENT_NAME: ${{ github.event_name }}
46+
GITHUB_REF: ${{ github.ref }}
47+
IS_RENOVATE: ${{ env.IS_RENOVATE }}
48+
PR_LABELS: ${{ toJson(github.event.pull_request.labels.*.name) }}
49+
run: |
50+
set -euo pipefail
51+
52+
run_status=false
53+
reason=not-requested
54+
55+
if [ "$IS_RENOVATE" = "true" ]; then
56+
run_status=false
57+
reason=renovate
58+
elif [ "$EVENT_NAME" = "schedule" ]; then
59+
run_status=true
60+
reason=schedule
61+
elif [ "$EVENT_NAME" = "workflow_dispatch" ]; then
62+
run_status=true
63+
reason=manual
64+
elif [ "$EVENT_NAME" = "push" ] && [ "$GITHUB_REF" = "refs/heads/main" ]; then
65+
run_status=true
66+
reason=push-main
67+
elif [ "$EVENT_NAME" = "pull_request" ]; then
68+
labels=${PR_LABELS:-[]}
69+
if printf '%s\n' "$labels" | grep -Fq '"full-e2e"'; then
70+
run_status=true
71+
reason=pr-label
72+
else
73+
run_status=false
74+
reason=pr-no-label
75+
fi
76+
fi
77+
echo "run_status = $run_status"
78+
echo "reason = $reason"
79+
echo "run_status=$run_status" >> "$GITHUB_OUTPUT"
80+
echo "reason=$reason" >> "$GITHUB_OUTPUT"
81+
82+
- uses: actions/checkout@v4
83+
if: steps.gate.outputs.run_status == 'true'
84+
with:
85+
fetch-depth: 0
86+
87+
- name: Install pnpm package manager
88+
if: steps.gate.outputs.run_status == 'true'
89+
uses: pnpm/action-setup@v4
90+
91+
- name: Setup Node.js
92+
if: steps.gate.outputs.run_status == 'true'
93+
uses: actions/setup-node@v4
94+
with:
95+
node-version: 20
96+
cache: pnpm
97+
98+
- name: Install dependencies
99+
if: steps.gate.outputs.run_status == 'true'
100+
run: pnpm install --frozen-lockfile --prefer-offline
101+
102+
- name: Resolve Nx base and head
103+
if: steps.gate.outputs.run_status == 'true'
104+
uses: nrwl/nx-set-shas@v4
105+
with:
106+
# For schedule: compare against last successful nightly run
107+
# For PR/push: normal base/head comparison
108+
last-successful-event: ${{ github.event_name == 'schedule' && 'schedule' || '' }}
109+
set-environment-variables-for-job: true
110+
111+
- name: Determine affected e2e targets
112+
if: steps.gate.outputs.run_status == 'true'
113+
id: affected
41114
run: |
42-
if [[ "${{ github.event_name }}" == "merge_group" && "${{ env.IS_RENOVATE }}" == "false" ]]; then
43-
echo "status=false" >> $GITHUB_OUTPUT
44-
elif [[ "${{ github.event_name }}" == "pull_request" && "${{ env.IS_RENOVATE }}" == "true" ]]; then
45-
echo "status=false" >> $GITHUB_OUTPUT
115+
set -euo pipefail
116+
117+
cmd=(pnpm nx show projects --affected --with-target=e2e)
118+
projects="$("${cmd[@]}")"
119+
projects_list="$(printf '%s' "$projects" | tr -d '\r')"
120+
121+
if [ -n "$projects" ]; then
122+
affected=true
46123
else
47-
echo "status=true" >> $GITHUB_OUTPUT
124+
affected=false
48125
fi
126+
echo Affected projects: "$projects_list"
127+
128+
echo "affected=$affected" >> "$GITHUB_OUTPUT"
129+
echo "projects=$projects_list" >> "$GITHUB_OUTPUT"
49130
50131
preinstall:
51132
needs: init
@@ -74,15 +155,34 @@ jobs:
74155
id: cache-modules
75156
with:
76157
lookup-only: true
77-
path: '**/node_modules'
158+
path: "**/node_modules"
78159
key: ${{ matrix.os }}-modules-${{ matrix.node }}-${{ github.run_id }}
79160

80161
- if: steps.cache-modules.outputs.cache-hit != 'true'
81162
run: pnpm install --frozen-lockfile
82163

164+
- name: Cache Playwright browsers
165+
uses: actions/cache@v4
166+
id: cache-playwright
167+
with:
168+
path: ~/.cache/ms-playwright
169+
key: playwright-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
170+
restore-keys: |
171+
playwright-${{ runner.os }}-
172+
173+
- name: Install Playwright browsers
174+
if: steps.cache-playwright.outputs.cache-hit != 'true'
175+
run: pnpm exec playwright install
176+
177+
- name: Install Playwright system dependencies
178+
if: matrix.os == 'ubuntu-latest' && steps.cache-playwright.outputs.cache-hit != 'true'
179+
run: pnpm exec playwright install-deps
180+
83181
e2e:
84182
needs: [init, preinstall]
85-
if: always()
183+
if: needs.init.outputs.e2e-enabled == 'true'
184+
env:
185+
projects: ${{ needs.init.outputs.projects }}
86186
permissions:
87187
contents: read
88188
runs-on: ${{ matrix.os }}
@@ -92,7 +192,6 @@ jobs:
92192
os: [ubuntu-latest, macos-latest, windows-latest]
93193
node: [20]
94194
pm: [npm, pnpm, yarn]
95-
project: [nx-payload-e2e]
96195
include:
97196
- os: ubuntu-latest
98197
name: Linux
@@ -118,46 +217,39 @@ jobs:
118217
pm: yarn
119218
fail-fast: false
120219

121-
name: E2E ${{ matrix.os }}/${{ matrix.pm }}/${{ matrix.node }} ${{ join(matrix.project) }}
220+
name: E2E ${{ matrix.os }}/${{ matrix.pm }}/${{ matrix.node }}
122221
steps:
123222
- uses: actions/checkout@v4
124-
if: needs.init.outputs.e2e-enabled == 'true'
125223
with:
126224
fetch-depth: 0
127225

128226
- name: Install pnpm package manager
129-
if: needs.init.outputs.e2e-enabled == 'true'
130227
uses: pnpm/action-setup@v4
131228

132229
- uses: actions/setup-node@v4
133-
if: needs.init.outputs.e2e-enabled == 'true'
134230
with:
135231
node-version: ${{ matrix.node }}
136232
cache: pnpm
137233

138234
- uses: actions/cache@v4
139-
if: needs.init.outputs.e2e-enabled == 'true'
140235
id: cache-modules
141236
with:
142-
path: '**/node_modules'
237+
path: "**/node_modules"
143238
key: ${{ matrix.os }}-modules-${{ matrix.node }}-${{ github.run_id }}
144239

145240
- name: Install dependencies
146-
if: needs.init.outputs.e2e-enabled == 'true'
147241
run: pnpm install --frozen-lockfile
148242

149243
- name: Install Playwright browser dependencies
150-
if: needs.init.outputs.e2e-enabled == 'true' && matrix.name == 'Linux'
151-
run: npx playwright install-deps
244+
if: matrix.name == 'Linux'
245+
run: pnpm exec playwright install-deps
152246

153247
- name: Analyze affected projects
154-
if: needs.init.outputs.e2e-enabled == 'true'
155248
uses: nrwl/nx-set-shas@v4
156249

157-
- name: Run e2e tests
158-
if: needs.init.outputs.e2e-enabled == 'true'
250+
- name: Run affected e2e tests
159251
id: e2e-run
160-
run: pnpm nx e2e ${{ matrix.project }} -c ${{ matrix.configuration }}
252+
run: pnpm nx run-many -t e2e --projects ${{ env.projects }} -c ${{ matrix.configuration }}
161253
timeout-minutes: ${{ matrix.timeout }}
162254
env:
163255
CDWR_E2E_PACKAGE_MANAGER: ${{ matrix.pm }}
@@ -175,61 +267,79 @@ jobs:
175267
else
176268
status="skipped"
177269
fi
178-
echo '{"project": "${{ matrix.project }}", "os": "${{ matrix.os }}", "pm": "${{ matrix.pm }}", "node": "${{ matrix.node }}", "configuration": "${{ matrix.configuration }}", "status": "'"$status"'"}' > results-${{ matrix.project }}-${{ matrix.os }}-${{ matrix.pm }}-${{ matrix.node }}.json
270+
echo '{"os": "${{ matrix.os }}", "pm": "${{ matrix.pm }}", "node": "${{ matrix.node }}", "configuration": "${{ matrix.configuration }}", "status": "'"$status"'"}' > results-${{ matrix.os }}-${{ matrix.pm }}-${{ matrix.node }}.json
179271
shell: bash
180272

181273
- name: Upload test results
182274
if: always()
183275
uses: actions/upload-artifact@v4
184276
with:
185-
name: results-${{ matrix.project }}-${{ matrix.os }}-${{ matrix.pm }}-${{ matrix.node }}
186-
path: results-${{ matrix.project }}-${{ matrix.os }}-${{ matrix.pm }}-${{ matrix.node }}.json
277+
name: results-${{ matrix.os }}-${{ matrix.pm }}-${{ matrix.node }}
278+
path: results-${{ matrix.os }}-${{ matrix.pm }}-${{ matrix.node }}.json
187279

188280
summary:
189281
name: E2E Test Summary
190-
needs: e2e
282+
needs: [init, e2e]
191283
runs-on: ubuntu-latest
192-
if: always()
284+
if: always() && needs.init.result != 'cancelled'
193285
steps:
194286
- name: Download all workflow run artifacts
287+
if: needs.e2e.result != 'skipped'
195288
uses: actions/download-artifact@v4
196289
with:
197290
path: artifacts
198291
pattern: results-*
199292
merge-multiple: true
200293
- name: Create summary
294+
env:
295+
REASON: ${{ needs.init.outputs.reason }}
296+
PROJECTS: ${{ needs.init.outputs.projects }}
297+
E2E_ENABLED: ${{ needs.init.outputs.e2e-enabled }}
298+
E2E_RESULT: ${{ needs.e2e.result }}
201299
run: |
202300
echo "# E2E Test Results Summary" > summary.md
203301
echo "" >> summary.md
204-
echo "| Project | OS | Package Manager | Node Version | Configuration | Status |" >> summary.md
205-
echo "| ------- | -- | --------------- | ------------ | ------------- | ------ |" >> summary.md
206-
for artifact in artifacts/*.json; do
207-
if [ -f "$artifact" ]; then
208-
project=$(jq -r '.project' "$artifact")
209-
os=$(jq -r '.os' "$artifact")
210-
pm=$(jq -r '.pm' "$artifact")
211-
configuration=$(jq -r '.configuration' "$artifact")
212-
node=$(jq -r '.node' "$artifact")
213-
status=$(jq -r '.status' "$artifact")
214-
echo "| $project | $os | $pm | $node | $configuration | $status |" >> summary.md
215-
fi
216-
done
302+
echo "**Trigger:** \`$REASON\`" >> summary.md
217303
218-
echo "" >> summary.md
219-
echo "## Detailed Results" >> summary.md
220-
echo "" >> summary.md
221-
echo "<details><summary>Click to expand</summary>" >> summary.md
222-
for artifact in artifacts/*.json; do
223-
echo "$(basename $artifact)" >> summary.md
304+
if [ "$E2E_ENABLED" != "true" ]; then
224305
echo "" >> summary.md
225-
echo '```json' >> summary.md
306+
echo "⏭️ **E2E tests skipped** - no affected projects with e2e targets" >> summary.md
307+
elif [ "$E2E_RESULT" = "skipped" ]; then
226308
echo "" >> summary.md
227-
jq -s '.' $artifact >> summary.md
309+
echo "⏭️ **E2E tests skipped**" >> summary.md
310+
else
311+
if [ -n "$PROJECTS" ]; then
312+
echo "**Affected projects:** \`$PROJECTS\`" >> summary.md
313+
fi
228314
echo "" >> summary.md
229-
echo '```' >> summary.md
315+
echo "| OS | Package Manager | Node Version | Configuration | Status |" >> summary.md
316+
echo "| -- | --------------- | ------------ | ------------- | ------ |" >> summary.md
317+
for artifact in artifacts/*.json; do
318+
if [ -f "$artifact" ]; then
319+
os=$(jq -r '.os' "$artifact")
320+
pm=$(jq -r '.pm' "$artifact")
321+
configuration=$(jq -r '.configuration' "$artifact")
322+
node=$(jq -r '.node' "$artifact")
323+
status=$(jq -r '.status' "$artifact")
324+
echo "| $os | $pm | $node | $configuration | $status |" >> summary.md
325+
fi
326+
done
230327
echo "" >> summary.md
231-
done
232-
echo "</details>" >> summary.md
328+
echo "## Detailed Results" >> summary.md
329+
echo "" >> summary.md
330+
echo "<details><summary>Click to expand</summary>" >> summary.md
331+
for artifact in artifacts/*.json; do
332+
echo "$(basename $artifact)" >> summary.md
333+
echo "" >> summary.md
334+
echo '```json' >> summary.md
335+
echo "" >> summary.md
336+
jq -s '.' $artifact >> summary.md
337+
echo "" >> summary.md
338+
echo '```' >> summary.md
339+
echo "" >> summary.md
340+
done
341+
echo "</details>" >> summary.md
342+
fi
233343
234344
- name: Upload summary artifact
235345
uses: actions/upload-artifact@v4

0 commit comments

Comments
 (0)