المشكلة في الـ CI
ريبو فيه web و api و ui و types. غيّرت سطر في الـ README بتاع api — هل محتاج تبني الـ web وتشغّل الـ Storybook build؟ لأ طبعًا. الحل فكرتين مع بعض:
🎯 Affected
شغّل المهام بس على الـ packages اللي اتغيّرت + اللي بيعتمدوا عليها.
☁️ Remote Cache
حتى اللي “اتأثر” ممكن يكون اتبنى قبل كده في PR تاني أو على جهاز زميلك → hit.
GitHub Actions
.github/workflows/ci.yml
name: CIon: pull_request: push: branches: [main]jobs: ci: runs-on: ubuntu-latest env: TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} # remote cache TURBO_TEAM: ${{ vars.TURBO_TEAM }} steps: - uses: actions/checkout@v4 with: fetch-depth: 0 # محتاج الـ history عشان يقارن بـ main - uses: pnpm/action-setup@v4 # بيقرا packageManager من package.json - uses: actions/setup-node@v4 with: node-version: 20 cache: pnpm - run: pnpm install --frozen-lockfile - run: pnpm turbo run lint typecheck test build --affectedDocker لـ app واحد: turbo prune
المشكلة: لو عملت COPY . . للـ api، الـ image هتشيل كود الـ web والـ Storybook وكل الـ dependencies بتاعتهم. وأسوأ: أي تعديل في web هيكسر الـ Docker layer cache بتاع الـ api.
turbo prune api --docker بيطلّعلك فولدر out/ فيه بس اللي الـ api محتاجه:
out/├── json/ # package.json بتاع api و types و tsconfig بس├── full/ # الكود الكامل للـ packages دي بس└── pnpm-lock.yaml # lockfile متقلّم للـ subset دهapps/api/Dockerfile
FROM node:20-alpine AS baseRUN corepack enableWORKDIR /app# 1) قلّم الريبو لـ api بسFROM base AS prunerCOPY . .RUN pnpm dlx turbo prune api --docker# 2) نزّل الـ deps (layer بيتكيّش طالما الـ package.json ماتغيرش)FROM base AS builderCOPY --from=pruner /app/out/json/ .COPY --from=pruner /app/out/pnpm-lock.yaml ./pnpm-lock.yamlRUN pnpm install --frozen-lockfile# 3) انسخ الكود وابنيCOPY --from=pruner /app/out/full/ .RUN pnpm turbo run build --filter=api...# 4) image التشغيلFROM base AS runnerENV NODE_ENV=productionCOPY --from=builder /app .USER nodeCMD ["node", "apps/api/dist/main.js"]# من الـ root بتاع الريبو (مش من جوه apps/api)docker build -f apps/api/Dockerfile -t jobs-api .
Changesets: لو هتنشر packages
لو الـ packages كلها private ومستخدمة جوه الريبو بس، مش محتاج Changesets. هتحتاجه لو هتنشر الـ design system على npm (حتى لو private registry) لفرق تانية بره الريبو.
pnpm changesetتكتب إيه اتغير
.changeset/*.mdيتعمله commit مع الـ PR
changeset versionbump + CHANGELOG
changeset publishnpm
pnpm add -Dw @changesets/clipnpm changeset initpnpm changeset # اختار الـ packages ونوع التغيير (patch/minor/major)pnpm changeset version # يرفع الأرقام ويكتب CHANGELOG ويحدّث workspace:^pnpm turbo build --filter=@repo/uipnpm changeset publish
.changeset/brave-lions-dance.md
---"@repo/ui": minor---Add `loading` prop to ButtonChecklist الأسبوع الرابع
🧠 اختبر نفسك
١) ليه بنعمل COPY out/json و install قبل COPY out/full؟
عشان Docker يكيّش الـ install layer؛ تعديل الكود مايعيدش تنزيل الـ deps.
٢) --affected بيبني كل حاجة في كل PR. أول شك؟
الـ checkout بـ depth 1 فمفيش base يقارن بيه.
٣) كل الـ packages private. محتاج Changesets؟
غالبًا لأ؛ الـ workspace protocol كفاية.