Skip to content

Commit 81edfbe

Browse files
iamzifeiclaude
andcommitted
refactor: auto-detect package manager instead of enforcing bun
Revert bun-only approach in favor of lock file detection: pnpm-lock.yaml → pnpm, package-lock.json → npm, default → bun. Add pnpm/action-setup with version:latest and oven-sh/setup-bun to all 7 reusable workflows. Add package manager rules to org-rules.md. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 433404e commit 81edfbe

8 files changed

Lines changed: 236 additions & 29 deletions

File tree

.github/workflows/ci-build.yml

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# Reusable workflow: Build
22
# Runs a production build with auto-detected or custom build command.
3+
# Auto-detects package manager (pnpm > npm > bun) based on lockfile.
34
# Sets common dummy env vars for Next.js builds so they don't fail on missing secrets.
45
name: CI - Build
56

@@ -112,8 +113,26 @@ jobs:
112113
echo "is_node=false" >> "$GITHUB_OUTPUT"
113114
fi
114115
115-
- name: Setup Bun
116+
- name: Detect package manager
116117
if: steps.check-project.outputs.is_node == 'true'
118+
id: detect-pm
119+
run: |
120+
if [ -f "pnpm-lock.yaml" ]; then
121+
echo "manager=pnpm" >> "$GITHUB_OUTPUT"
122+
elif [ -f "package-lock.json" ]; then
123+
echo "manager=npm" >> "$GITHUB_OUTPUT"
124+
else
125+
echo "manager=bun" >> "$GITHUB_OUTPUT"
126+
fi
127+
128+
- name: Setup pnpm
129+
if: steps.check-project.outputs.is_node == 'true' && steps.detect-pm.outputs.manager == 'pnpm'
130+
uses: pnpm/action-setup@v4
131+
with:
132+
version: latest
133+
134+
- name: Setup Bun
135+
if: steps.check-project.outputs.is_node == 'true' && steps.detect-pm.outputs.manager == 'bun'
117136
uses: oven-sh/setup-bun@v2
118137

119138
- name: Setup Node.js
@@ -124,7 +143,12 @@ jobs:
124143

125144
- name: Install dependencies
126145
if: steps.check-project.outputs.is_node == 'true'
127-
run: bun install --frozen-lockfile
146+
run: |
147+
case "${{ steps.detect-pm.outputs.manager }}" in
148+
pnpm) pnpm install --frozen-lockfile ;;
149+
npm) npm ci ;;
150+
bun) bun install --frozen-lockfile ;;
151+
esac
128152
129153
# Determine which build command to run, or skip if not a buildable project
130154
- name: Detect build command
@@ -139,8 +163,10 @@ jobs:
139163
echo "::notice::No package.json found — skipping build step"
140164
echo "skip=true" >> "$GITHUB_OUTPUT"
141165
else
142-
if bun -e "const p=require('./package.json'); process.exit(p.scripts && p.scripts.build ? 0 : 1)"; then
143-
echo "cmd=bun run build" >> "$GITHUB_OUTPUT"
166+
if node -e "const p=require('./package.json'); process.exit(p.scripts && p.scripts.build ? 0 : 1)"; then
167+
# Build command uses the detected package manager
168+
PM="${{ steps.detect-pm.outputs.manager }}"
169+
echo "cmd=${PM} run build" >> "$GITHUB_OUTPUT"
144170
echo "skip=false" >> "$GITHUB_OUTPUT"
145171
else
146172
echo "::notice::No 'build' script in package.json — skipping build step"

.github/workflows/ci-e2e.yml

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# Reusable workflow: End-to-End Tests (Playwright)
22
# Only runs if a Playwright config file exists in the project.
3+
# Auto-detects package manager (pnpm > npm > bun) based on lockfile.
34
# Installs Playwright browsers, runs tests, and uploads results as artifacts.
45
name: CI - E2E Tests
56

@@ -38,8 +39,26 @@ jobs:
3839
echo "::notice::No Playwright config found — skipping E2E tests"
3940
fi
4041
41-
- name: Setup Bun
42+
- name: Detect package manager
4243
if: steps.check-pw.outputs.has_config == 'true'
44+
id: detect-pm
45+
run: |
46+
if [ -f "pnpm-lock.yaml" ]; then
47+
echo "manager=pnpm" >> "$GITHUB_OUTPUT"
48+
elif [ -f "package-lock.json" ]; then
49+
echo "manager=npm" >> "$GITHUB_OUTPUT"
50+
else
51+
echo "manager=bun" >> "$GITHUB_OUTPUT"
52+
fi
53+
54+
- name: Setup pnpm
55+
if: steps.check-pw.outputs.has_config == 'true' && steps.detect-pm.outputs.manager == 'pnpm'
56+
uses: pnpm/action-setup@v4
57+
with:
58+
version: latest
59+
60+
- name: Setup Bun
61+
if: steps.check-pw.outputs.has_config == 'true' && steps.detect-pm.outputs.manager == 'bun'
4362
uses: oven-sh/setup-bun@v2
4463

4564
- name: Setup Node.js
@@ -50,15 +69,20 @@ jobs:
5069

5170
- name: Install dependencies
5271
if: steps.check-pw.outputs.has_config == 'true'
53-
run: bun install --frozen-lockfile
72+
run: |
73+
case "${{ steps.detect-pm.outputs.manager }}" in
74+
pnpm) pnpm install --frozen-lockfile ;;
75+
npm) npm ci ;;
76+
bun) bun install --frozen-lockfile ;;
77+
esac
5478
5579
- name: Install Playwright browsers
5680
if: steps.check-pw.outputs.has_config == 'true'
57-
run: bunx playwright install --with-deps
81+
run: npx playwright install --with-deps
5882

5983
- name: Run Playwright tests
6084
if: steps.check-pw.outputs.has_config == 'true'
61-
run: bunx playwright test
85+
run: npx playwright test
6286

6387
- name: Upload Playwright report
6488
if: steps.check-pw.outputs.has_config == 'true' && always()

.github/workflows/ci-lint-typecheck.yml

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Reusable workflow: Lint & Type Check
22
# Runs lint and typecheck scripts from package.json if they exist.
3-
# Uses bun as the standard package manager for all OrrisTech repos.
3+
# Auto-detects package manager: pnpm-lock.yaml → pnpm, package-lock.json → npm,
4+
# otherwise → bun (default for new projects).
45
name: CI - Lint & Type Check
56

67
on:
@@ -28,7 +29,26 @@ jobs:
2829
- name: Checkout repository
2930
uses: actions/checkout@v4
3031

32+
# Detect package manager from lock files. Default to bun for new projects.
33+
- name: Detect package manager
34+
id: detect-pm
35+
run: |
36+
if [ -f "pnpm-lock.yaml" ]; then
37+
echo "manager=pnpm" >> "$GITHUB_OUTPUT"
38+
elif [ -f "package-lock.json" ]; then
39+
echo "manager=npm" >> "$GITHUB_OUTPUT"
40+
else
41+
echo "manager=bun" >> "$GITHUB_OUTPUT"
42+
fi
43+
44+
- name: Setup pnpm
45+
if: steps.detect-pm.outputs.manager == 'pnpm'
46+
uses: pnpm/action-setup@v4
47+
with:
48+
version: latest
49+
3150
- name: Setup Bun
51+
if: steps.detect-pm.outputs.manager == 'bun'
3252
uses: oven-sh/setup-bun@v2
3353

3454
- name: Setup Node.js
@@ -37,13 +57,18 @@ jobs:
3757
node-version: ${{ inputs.node_version }}
3858

3959
- name: Install dependencies
40-
run: bun install --frozen-lockfile
60+
run: |
61+
case "${{ steps.detect-pm.outputs.manager }}" in
62+
pnpm) pnpm install --frozen-lockfile ;;
63+
npm) npm ci ;;
64+
bun) bun install --frozen-lockfile ;;
65+
esac
4166
4267
# Check if a lint script exists before running it
4368
- name: Check for lint script
4469
id: check-lint
4570
run: |
46-
if bun -e "const p=require('./package.json'); process.exit(p.scripts && p.scripts.lint ? 0 : 1)"; then
71+
if node -e "const p=require('./package.json'); process.exit(p.scripts && p.scripts.lint ? 0 : 1)"; then
4772
echo "has_lint=true" >> "$GITHUB_OUTPUT"
4873
else
4974
echo "has_lint=false" >> "$GITHUB_OUTPUT"
@@ -52,13 +77,18 @@ jobs:
5277
5378
- name: Run lint
5479
if: steps.check-lint.outputs.has_lint == 'true'
55-
run: bun run lint
80+
run: |
81+
case "${{ steps.detect-pm.outputs.manager }}" in
82+
pnpm) pnpm run lint ;;
83+
npm) npm run lint ;;
84+
bun) bun run lint ;;
85+
esac
5686
5787
# Check if a typecheck script exists (supports both "typecheck" and "type-check")
5888
- name: Check for typecheck script
5989
id: check-typecheck
6090
run: |
61-
SCRIPT=$(bun -e "
91+
SCRIPT=$(node -e "
6292
const p = require('./package.json');
6393
const s = p.scripts || {};
6494
if (s['typecheck']) console.log('typecheck');
@@ -75,4 +105,11 @@ jobs:
75105
76106
- name: Run type check
77107
if: steps.check-typecheck.outputs.has_typecheck == 'true'
78-
run: bun run ${{ steps.check-typecheck.outputs.script_name }}
108+
env:
109+
SCRIPT: ${{ steps.check-typecheck.outputs.script_name }}
110+
run: |
111+
case "${{ steps.detect-pm.outputs.manager }}" in
112+
pnpm) pnpm run "$SCRIPT" ;;
113+
npm) npm run "$SCRIPT" ;;
114+
bun) bun run "$SCRIPT" ;;
115+
esac

.github/workflows/ci-react-doctor.yml

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# Reusable workflow: React Doctor
22
# Runs react-doctor to detect common React issues and anti-patterns.
3+
# Auto-detects package manager (pnpm > npm > bun) based on lockfile.
34
# Posts results as a PR comment when triggered by a pull_request event.
45
name: CI - React Doctor
56

@@ -32,7 +33,25 @@ jobs:
3233
- name: Checkout repository
3334
uses: actions/checkout@v4
3435

36+
- name: Detect package manager
37+
id: detect-pm
38+
run: |
39+
if [ -f "pnpm-lock.yaml" ]; then
40+
echo "manager=pnpm" >> "$GITHUB_OUTPUT"
41+
elif [ -f "package-lock.json" ]; then
42+
echo "manager=npm" >> "$GITHUB_OUTPUT"
43+
else
44+
echo "manager=bun" >> "$GITHUB_OUTPUT"
45+
fi
46+
47+
- name: Setup pnpm
48+
if: steps.detect-pm.outputs.manager == 'pnpm'
49+
uses: pnpm/action-setup@v4
50+
with:
51+
version: latest
52+
3553
- name: Setup Bun
54+
if: steps.detect-pm.outputs.manager == 'bun'
3655
uses: oven-sh/setup-bun@v2
3756

3857
- name: Setup Node.js
@@ -41,13 +60,18 @@ jobs:
4160
node-version: ${{ inputs.node_version }}
4261

4362
- name: Install dependencies
44-
run: bun install --frozen-lockfile
63+
run: |
64+
case "${{ steps.detect-pm.outputs.manager }}" in
65+
pnpm) pnpm install --frozen-lockfile ;;
66+
npm) npm ci ;;
67+
bun) bun install --frozen-lockfile ;;
68+
esac
4569
4670
- name: Run react-doctor
4771
id: react-doctor
4872
continue-on-error: true
4973
run: |
50-
OUTPUT=$(bunx react-doctor@latest . --verbose 2>&1) || true
74+
OUTPUT=$(npx react-doctor@latest . --verbose 2>&1) || true
5175
echo "$OUTPUT" > /tmp/react-doctor-output.txt
5276
echo "exit_code=$?" >> "$GITHUB_OUTPUT"
5377

.github/workflows/ci-security.yml

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# Reusable workflow: Security Audit
2-
# Runs npm audit at high severity level (bun lacks native audit).
2+
# Runs npm audit at high severity level.
3+
# Auto-detects package manager (pnpm > npm > bun) based on lockfile.
34
# Optionally runs Snyk scan if SNYK_TOKEN secret is available.
45
# Audit failures are advisory (continue-on-error) and do not block the pipeline.
56
name: CI - Security Audit
@@ -33,7 +34,25 @@ jobs:
3334
- name: Checkout repository
3435
uses: actions/checkout@v4
3536

37+
- name: Detect package manager
38+
id: detect-pm
39+
run: |
40+
if [ -f "pnpm-lock.yaml" ]; then
41+
echo "manager=pnpm" >> "$GITHUB_OUTPUT"
42+
elif [ -f "package-lock.json" ]; then
43+
echo "manager=npm" >> "$GITHUB_OUTPUT"
44+
else
45+
echo "manager=bun" >> "$GITHUB_OUTPUT"
46+
fi
47+
48+
- name: Setup pnpm
49+
if: steps.detect-pm.outputs.manager == 'pnpm'
50+
uses: pnpm/action-setup@v4
51+
with:
52+
version: latest
53+
3654
- name: Setup Bun
55+
if: steps.detect-pm.outputs.manager == 'bun'
3756
uses: oven-sh/setup-bun@v2
3857

3958
- name: Setup Node.js
@@ -42,13 +61,22 @@ jobs:
4261
node-version: ${{ inputs.node_version }}
4362

4463
- name: Install dependencies
45-
run: bun install --frozen-lockfile
64+
run: |
65+
case "${{ steps.detect-pm.outputs.manager }}" in
66+
pnpm) pnpm install --frozen-lockfile ;;
67+
npm) npm ci ;;
68+
bun) bun install --frozen-lockfile ;;
69+
esac
4670
47-
# Bun does not have a built-in audit command; use npm audit against
48-
# the installed node_modules and package-lock.json equivalent
71+
# Run package audit using the appropriate tool for each package manager
4972
- name: Run package audit
5073
continue-on-error: true
51-
run: npm audit --audit-level=high || true
74+
run: |
75+
case "${{ steps.detect-pm.outputs.manager }}" in
76+
pnpm) pnpm audit --audit-level=high || true ;;
77+
npm) npm audit --audit-level=high || true ;;
78+
bun) npm audit --audit-level=high || true ;;
79+
esac
5280
5381
# Run Snyk scan only if SNYK_TOKEN is provided
5482
- name: Check for Snyk token

.github/workflows/ci-seo-lighthouse.yml

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# Reusable workflow: SEO & Lighthouse
22
# Runs Lighthouse CI (lhci) to check performance, accessibility, and SEO scores.
3+
# Auto-detects package manager (pnpm > npm > bun) based on lockfile.
34
# Runs if a lighthouserc config exists or if urls are explicitly provided.
45
name: CI - SEO & Lighthouse
56

@@ -71,8 +72,26 @@ jobs:
7172
echo "::notice::No Lighthouse config found and no custom URLs provided — skipping audit"
7273
fi
7374
74-
- name: Setup Bun
75+
- name: Detect package manager
7576
if: steps.check-lh.outputs.should_run == 'true'
77+
id: detect-pm
78+
run: |
79+
if [ -f "pnpm-lock.yaml" ]; then
80+
echo "manager=pnpm" >> "$GITHUB_OUTPUT"
81+
elif [ -f "package-lock.json" ]; then
82+
echo "manager=npm" >> "$GITHUB_OUTPUT"
83+
else
84+
echo "manager=bun" >> "$GITHUB_OUTPUT"
85+
fi
86+
87+
- name: Setup pnpm
88+
if: steps.check-lh.outputs.should_run == 'true' && steps.detect-pm.outputs.manager == 'pnpm'
89+
uses: pnpm/action-setup@v4
90+
with:
91+
version: latest
92+
93+
- name: Setup Bun
94+
if: steps.check-lh.outputs.should_run == 'true' && steps.detect-pm.outputs.manager == 'bun'
7695
uses: oven-sh/setup-bun@v2
7796

7897
- name: Setup Node.js
@@ -83,7 +102,12 @@ jobs:
83102

84103
- name: Install dependencies
85104
if: steps.check-lh.outputs.should_run == 'true'
86-
run: bun install --frozen-lockfile
105+
run: |
106+
case "${{ steps.detect-pm.outputs.manager }}" in
107+
pnpm) pnpm install --frozen-lockfile ;;
108+
npm) npm ci ;;
109+
bun) bun install --frozen-lockfile ;;
110+
esac
87111
88112
- name: Install Lighthouse CI
89113
if: steps.check-lh.outputs.should_run == 'true'
@@ -101,7 +125,7 @@ jobs:
101125
LH_A11Y: ${{ inputs.threshold_accessibility }}
102126
LH_SEO: ${{ inputs.threshold_seo }}
103127
run: |
104-
URLS_JSON=$(echo "$LH_URLS" | bun -e "
128+
URLS_JSON=$(echo "$LH_URLS" | node -e "
105129
const input = require('fs').readFileSync('/dev/stdin','utf8').trim();
106130
const urls = input.split(',').map(u => u.trim()).filter(Boolean);
107131
console.log(JSON.stringify(urls));

0 commit comments

Comments
 (0)