Skip to content

Commit 0031e98

Browse files
authored
ci: improve workflow robustness and performance (#197)
* ci: improve workflow robustness and performance - Add concurrency controls to prevent duplicate workflow runs - Implement job timeouts (10min quality, 30min test, 45min release) - Replace hardcoded pnpm setup with Corepack for automatic version management - Add pnpm store caching to speed up dependency installation - Add matrix testing for Node.js 18, 20, and 22 - Add build verification steps before tests and releases - Improve changeset validation with better error handling - Fix biome format check with --unsafe flag for CI environment - Add minimal permissions to release workflow for security - Enhance dry run mode to show actual version changes - Ensure only one release can run at a time * ci: address code review feedback for workflow improvements - Add explanatory comments for the --unsafe flag in format checks - Fix script error handling by moving set -e to the beginning - Use timestamp-based unique branch names for dry-run to prevent conflicts * ci: improve workflow robustness based on code review feedback - Add explanatory comments for the --unsafe flag in format checks - Fix script error handling by moving set -e to the beginning - Use GITHUB_RUN_ID for unique branch names to prevent conflicts - Make build verification dynamic to discover packages automatically - Fix git diff references in dry run by saving original HEAD * ci: improve workflow reliability and fix formatting issues - Replace hardcoded package paths with dynamic discovery in build verification - Fix shell compatibility by avoiding command substitution in variable expansion - Use 1135430206 instead of 1753700397 for better portability - Save original HEAD reference before dry-run changes for accurate diffs - Fix spacing in error messages for better readability * ci: fix workflow consistency and dry-run git configuration - Make build verification consistent between workflows by using dynamic package discovery - Add git user configuration for dry-run to prevent changeset version errors - Remove hardcoded package paths in release.yml to match tests.yaml approach - Remove Node.js 18 from test matrix due to Firebase CLI v14 incompatibility
1 parent b807700 commit 0031e98

File tree

2 files changed

+173
-23
lines changed

2 files changed

+173
-23
lines changed

.github/workflows/release.yml

Lines changed: 108 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,21 @@ on:
99
default: false
1010
type: boolean
1111

12+
# Ensure only one release can run at a time
13+
concurrency:
14+
group: release
15+
cancel-in-progress: false
16+
17+
# Minimal permissions for security
18+
permissions:
19+
contents: write
20+
pull-requests: write
21+
issues: write
22+
1223
jobs:
1324
quality:
1425
runs-on: ubuntu-latest
26+
timeout-minutes: 10
1527
steps:
1628
- name: Checkout
1729
uses: actions/checkout@v4
@@ -21,10 +33,22 @@ jobs:
2133
with:
2234
node-version: "20"
2335

24-
- name: Setup pnpm
25-
uses: pnpm/action-setup@v2
36+
- name: Enable Corepack
37+
run: corepack enable
38+
39+
- name: Get pnpm store directory
40+
id: pnpm-cache
41+
shell: bash
42+
run: |
43+
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
44+
45+
- name: Setup pnpm cache
46+
uses: actions/cache@v4
2647
with:
27-
version: 8.15.4
48+
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
49+
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
50+
restore-keys: |
51+
${{ runner.os }}-pnpm-store-
2852
2953
- name: Install dependencies
3054
run: pnpm install
@@ -35,6 +59,7 @@ jobs:
3559
release:
3660
name: Release
3761
runs-on: ubuntu-latest
62+
timeout-minutes: 45
3863
needs: quality
3964
steps:
4065
- name: Checkout
@@ -48,10 +73,22 @@ jobs:
4873
node-version: "20"
4974
registry-url: "https://registry.npmjs.org"
5075

51-
- name: Setup pnpm
52-
uses: pnpm/action-setup@v2
76+
- name: Enable Corepack
77+
run: corepack enable
78+
79+
- name: Get pnpm store directory
80+
id: pnpm-cache
81+
shell: bash
82+
run: |
83+
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
84+
85+
- name: Setup pnpm cache
86+
uses: actions/cache@v4
5387
with:
54-
version: 8.15.4
88+
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
89+
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
90+
restore-keys: |
91+
${{ runner.os }}-pnpm-store-
5592
5693
- name: Install dependencies
5794
run: pnpm install
@@ -70,17 +107,45 @@ jobs:
70107
- name: Build packages
71108
run: pnpm turbo build
72109

110+
- name: Verify build outputs
111+
run: |
112+
echo "Checking build outputs..."
113+
# Check all packages for dist directories
114+
MISSING_BUILDS=""
115+
for PKG_DIR in packages/*; do
116+
if [ -d "$PKG_DIR" ] && [ -f "$PKG_DIR/package.json" ]; then
117+
PKG_NAME=$(basename "$PKG_DIR")
118+
if [ ! -d "$PKG_DIR/dist" ]; then
119+
MISSING_BUILDS="$MISSING_BUILDS $PKG_NAME"
120+
fi
121+
fi
122+
done
123+
124+
if [ -n "$MISSING_BUILDS" ]; then
125+
echo "❌ Build outputs missing for: $MISSING_BUILDS"
126+
exit 1
127+
fi
128+
129+
echo "✅ All build outputs verified"
130+
73131
- name: Validate changesets
74132
run: |
75-
if [ -z "$(ls .changeset/*.md 2>/dev/null)" ]; then
76-
echo "❌ No changesets found. Please create changesets locally with 'pnpm changeset' before releasing."
133+
set -e
134+
CHANGESET_FILES=$(find .changeset -name "*.md" -type f ! -name "README.md" 2>/dev/null || true)
135+
136+
if [ -z "$CHANGESET_FILES" ]; then
137+
echo "❌ No changesets found!"
138+
echo ""
139+
echo "Please create changesets locally with: pnpm changeset"
77140
echo "Changesets should be created during development, not during release."
78141
exit 1
79-
else
80-
echo "✅ Found $(ls .changeset/*.md | wc -l) changeset(s)"
81-
echo "Changesets:"
82-
ls .changeset/*.md
83142
fi
143+
144+
CHANGESET_COUNT=$(echo "$CHANGESET_FILES" | wc -l | tr -d ' ')
145+
echo "✅ Found $CHANGESET_COUNT changeset(s):"
146+
echo "$CHANGESET_FILES" | while read -r file; do
147+
echo " - $(basename "$file")"
148+
done
84149
85150
- name: Create Release Pull Request or Publish
86151
if: ${{ !inputs.dry_run }}
@@ -101,15 +166,42 @@ jobs:
101166
echo ""
102167
echo "📋 Changeset contents:"
103168
for file in .changeset/*.md; do
104-
if [ -f "$file" ]; then
105-
echo "--- $file ---"
169+
if [ -f "$file" ] && [ "$(basename "$file")" != "README.md" ]; then
170+
echo "--- $(basename "$file") ---"
106171
cat "$file"
107172
echo ""
108173
fi
109174
done
110175
111176
echo "📦 Version changes that would be applied:"
112-
pnpm changeset version --dry-run
113-
177+
# Configure git user for changeset version command
178+
git config user.name "github-actions[bot]"
179+
git config user.email "github-actions[bot]@users.noreply.github.com"
180+
181+
# Save current HEAD reference before making changes
182+
ORIGINAL_HEAD=$(git rev-parse HEAD)
183+
# Create a temporary branch for dry run with unique name
184+
FALLBACK_ID=${GITHUB_RUN_ID:-$RANDOM$RANDOM}
185+
TEMP_BRANCH="dry-run-temp-$FALLBACK_ID"
186+
git checkout -b "$TEMP_BRANCH"
187+
pnpm changeset version
188+
189+
echo ""
190+
echo "🔍 Changed files:"
191+
git diff --name-status "$ORIGINAL_HEAD"
192+
193+
echo ""
194+
echo "🔍 Package version changes:"
195+
VERSION_CHANGES=$(git diff "$ORIGINAL_HEAD" -- '**/package.json' | grep -E "^[+-]\s*\"version\"" || true)
196+
if [ -z "$VERSION_CHANGES" ]; then
197+
echo " No version changes detected (this might indicate an issue with changesets)"
198+
else
199+
echo "$VERSION_CHANGES"
200+
fi
201+
202+
# Clean up
203+
git checkout -
204+
git branch -D "$TEMP_BRANCH"
205+
114206
echo ""
115207
echo "✅ Dry run completed successfully"

.github/workflows/tests.yaml

Lines changed: 65 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,15 @@ on:
88
branches:
99
- main
1010

11+
# Cancel in-progress runs when a new run is queued on the same branch
12+
concurrency:
13+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
14+
cancel-in-progress: true
15+
1116
jobs:
1217
quality:
1318
runs-on: ubuntu-latest
19+
timeout-minutes: 10
1420
steps:
1521
- name: Checkout
1622
uses: actions/checkout@v4
@@ -20,10 +26,22 @@ jobs:
2026
with:
2127
node-version: "20"
2228

23-
- name: Setup pnpm
24-
uses: pnpm/action-setup@v2
29+
- name: Enable Corepack
30+
run: corepack enable
31+
32+
- name: Get pnpm store directory
33+
id: pnpm-cache
34+
shell: bash
35+
run: |
36+
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
37+
38+
- name: Setup pnpm cache
39+
uses: actions/cache@v4
2540
with:
26-
version: 8.15.4
41+
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
42+
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
43+
restore-keys: |
44+
${{ runner.os }}-pnpm-store-
2745
2846
- name: Install dependencies
2947
run: pnpm install
@@ -33,21 +51,37 @@ jobs:
3351

3452
test:
3553
runs-on: ubuntu-latest
54+
timeout-minutes: 30
3655
needs: quality
56+
strategy:
57+
matrix:
58+
node-version: [20, 22]
3759
steps:
3860
- name: Checkout code
3961
uses: actions/checkout@v4
4062

4163
- name: Setup Node.js
4264
uses: actions/setup-node@v4
4365
with:
44-
node-version: "20"
66+
node-version: ${{ matrix.node-version }}
4567
registry-url: "https://registry.npmjs.org"
4668

47-
- name: Setup pnpm
48-
uses: pnpm/action-setup@v2
69+
- name: Enable Corepack
70+
run: corepack enable
71+
72+
- name: Get pnpm store directory
73+
id: pnpm-cache
74+
shell: bash
75+
run: |
76+
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
77+
78+
- name: Setup pnpm cache
79+
uses: actions/cache@v4
4980
with:
50-
version: 8.15.4
81+
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
82+
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
83+
restore-keys: |
84+
${{ runner.os }}-pnpm-store-
5185
5286
- name: Install dependencies
5387
run: pnpm install
@@ -71,6 +105,30 @@ jobs:
71105
angular:
72106
- 'packages/angular/**'
73107
108+
# Build packages before testing
109+
- name: Build packages
110+
run: pnpm turbo build
111+
112+
# Verify build outputs
113+
- name: Verify build outputs
114+
run: |
115+
# Check all packages for dist directories
116+
MISSING_BUILDS=""
117+
for PKG_DIR in packages/*; do
118+
if [ -d "$PKG_DIR" ] && [ -f "$PKG_DIR/package.json" ]; then
119+
PKG_NAME=$(basename "$PKG_DIR")
120+
if [ ! -d "$PKG_DIR/dist" ]; then
121+
MISSING_BUILDS="$MISSING_BUILDS $PKG_NAME"
122+
fi
123+
fi
124+
done
125+
126+
if [ -n "$MISSING_BUILDS" ]; then
127+
echo "❌ Build outputs not found for: $MISSING_BUILDS"
128+
exit 1
129+
fi
130+
echo "✅ All build outputs verified"
131+
74132
# Run tests with emulator for changed packages
75133
- name: Run tests with emulator
76134
run: pnpm test:emulator

0 commit comments

Comments
 (0)