मोनोरेपो प्रोजेक्ट्स के लिए GitHub क्रियाएँ CI/CD
मोनोरेपो के लिए सीआई/सीडी पाइपलाइन को एकल-एप्लिकेशन पाइपलाइन की तुलना में मौलिक रूप से भिन्न चुनौती का सामना करना पड़ता है: जब आपके 5 अनुप्रयोगों में से केवल 1 बदल जाता है तो आप तेज़, विश्वसनीय पाइपलाइन कैसे चलाते हैं? हर कमिट पर सब कुछ भोलेपन से बनाने से 2 मिनट की पाइपलाइन 15 मिनट की बाधा में बदल जाती है, जिसे डेवलपर्स बैचिंग कमिट द्वारा हल करते हैं - ठीक वही जो आप रोकने की कोशिश कर रहे हैं।
यह मार्गदर्शिका टर्बोरेपो मोनोरेपो के लिए उत्पादन गिटहब एक्शन सेटअप को कवर करती है: प्रभावित-केवल बिल्ड, समानांतर कार्य निष्पादन, टर्बो रिमोट कैशिंग एकीकरण, पर्यावरण-आधारित परिनियोजन द्वार, और सुरक्षा पैटर्न जो रहस्यों को लॉग या फोर्कड पीआर रन में लीक होने से रोकते हैं।
मुख्य बातें
- टर्बो के प्रभावित पैकेज का पता लगाने को सक्षम करने के लिए चेकआउट में
fetch-depth: 2का उपयोग करें- समानांतर कार्यों में लिंट चलाएं, टाइप-चेक करें, परीक्षण करें और निर्माण करें - उन्हें क्रमिक रूप से श्रृंखलाबद्ध न करें
- मैट्रिक्स नौकरियां आपको YAML की नकल किए बिना कई Node.js संस्करणों या ऑपरेटिंग सिस्टम पर परीक्षण करने देती हैं
- टर्बो रिमोट कैश क्रेडेंशियल्स को GitHub सीक्रेट्स के रूप में स्टोर करें, YAML में पर्यावरण चर के रूप में नहीं
- मैन्युअल अनुमोदन की आवश्यकता के लिए उत्पादन परिनियोजन कार्यों पर
environment:सुरक्षा नियमों का उपयोग करेंpaths-filterकार्रवाई आपको सीआई को पूरी तरह से छोड़ने की सुविधा देती है जब केवल दस्तावेज़ या गैर-कोड फ़ाइलें बदली जाती हैं- कभी भी लॉग में रहस्य प्रिंट न करें - रनटाइम-जनरेटेड रहस्यों के लिए
::add-mask::का उपयोग करें- पुन: प्रयोज्य वर्कफ़्लोज़ (
workflow_call) कई रिपॉजिटरी वर्कफ़्लोज़ में दोहराव को समाप्त करते हैं
सीआई के लिए रिपोजिटरी संरचना
एक अच्छा सीआई सेटअप आपके विकास वर्कफ़्लो को प्रतिबिंबित करता है। यहां वह संरचना है जो टर्बोरेपो मोनोरेपो के लिए काम करती है:
.github/
workflows/
ci.yml — Runs on every PR and push to main
deploy.yml — Runs on push to main (after CI passes)
security.yml — Weekly security scans
cleanup.yml — Scheduled: delete stale preview deployments
actions/
setup-pnpm/
action.yml — Reusable: install Node + pnpm + cache
कोर सीआई वर्कफ़्लो
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
types: [opened, synchronize, reopened]
# Cancel in-progress runs when a new run starts
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
NODE_VERSION: '22'
PNPM_VERSION: '10.28.0'
jobs:
# Fast path: skip if only docs/assets changed
changes:
runs-on: ubuntu-latest
outputs:
code: ${{ steps.filter.outputs.code }}
docs: ${{ steps.filter.outputs.docs }}
steps:
- uses: actions/checkout@v4
- uses: dorny/paths-filter@v3
id: filter
with:
filters: |
code:
- 'apps/**/*.ts'
- 'apps/**/*.tsx'
- 'packages/**/*.ts'
- 'turbo.json'
- 'package.json'
- 'pnpm-lock.yaml'
docs:
- 'apps/docs/**'
- '**/*.md'
lint:
needs: changes
if: needs.changes.outputs.code == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 2 # Required for turbo affected detection
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'pnpm'
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Lint
run: pnpm turbo run lint
- name: Type check
run: pnpm turbo run type-check
test:
needs: changes
if: needs.changes.outputs.code == 'true'
runs-on: ubuntu-latest
services:
postgres:
image: postgres:17-alpine
env:
POSTGRES_DB: ecosire_test
POSTGRES_USER: ecosire
POSTGRES_PASSWORD: password
ports:
- 5433:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
redis:
image: redis:7-alpine
ports:
- 6379:6379
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 2
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'pnpm'
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Run unit tests
run: pnpm turbo run test
env:
DATABASE_URL: postgresql://ecosire:password@localhost:5433/ecosire_test
REDIS_URL: redis://localhost:6379
- name: Upload coverage
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./apps/api/coverage/lcov.info
build:
needs: [lint, test]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 2
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'pnpm'
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build all apps
run: pnpm turbo run build
env:
NEXT_PUBLIC_API_URL: ${{ vars.STAGING_API_URL }}
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: build-${{ github.sha }}
path: |
apps/web/.next/
apps/api/dist/
retention-days: 1 # Keep briefly for deploy job
नाटककार के साथ E2E टेस्ट जॉब
e2e:
needs: build
runs-on: ubuntu-latest
strategy:
matrix:
project: [chromium, firefox, mobile-chrome]
fail-fast: false # Don't cancel other browsers if one fails
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'pnpm'
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Install Playwright browsers
run: cd apps/web && npx playwright install ${{ matrix.project }} --with-deps
- name: Download build artifacts
uses: actions/download-artifact@v4
with:
name: build-${{ github.sha }}
- name: Start test servers
run: |
cd apps/api && node dist/main.js &
cd apps/web && npx next start &
npx wait-on http://localhost:3000 http://localhost:3001/health
env:
DATABASE_URL: ${{ secrets.TEST_DATABASE_URL }}
- name: Run E2E tests
run: cd apps/web && npx playwright test --project=${{ matrix.project }}
env:
BASE_URL: http://localhost:3000
- name: Upload test results
uses: actions/upload-artifact@v4
if: failure()
with:
name: playwright-report-${{ matrix.project }}
path: apps/web/playwright-report/
retention-days: 7
सुरक्षा स्कैनिंग वर्कफ़्लो
# .github/workflows/security.yml
name: Security Scan
on:
schedule:
- cron: '0 2 * * 1' # Weekly Monday 2am UTC
push:
paths:
- '**/package.json'
- 'pnpm-lock.yaml'
jobs:
audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: '10.28.0'
- name: Run pnpm audit
run: pnpm audit --audit-level moderate
continue-on-error: true # Don't fail CI, just report
- name: Run Snyk security scan
uses: snyk/actions/node@master
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
with:
command: test
args: --severity-threshold=high
secret-scanning:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Full history for secret scanning
- name: Run Gitleaks
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
परिनियोजन वर्कफ़्लो
# .github/workflows/deploy.yml
name: Deploy to Production
on:
workflow_dispatch:
inputs:
environment:
description: 'Deploy environment'
required: true
default: 'production'
type: choice
options:
- production
- staging
# Only one production deploy at a time
concurrency:
group: deploy-${{ inputs.environment }}
cancel-in-progress: false # Don't cancel in-flight deploys
jobs:
quality-gate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: '10.28.0'
- uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'pnpm'
- run: pnpm install --frozen-lockfile
- name: Run quality checks
run: |
pnpm turbo run lint type-check test
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
deploy:
needs: quality-gate
runs-on: ubuntu-latest
environment: ${{ inputs.environment }} # Requires approval for production
steps:
- uses: actions/checkout@v4
- name: Deploy via SSH
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
set -e
cd /opt/ecosire/app
echo "Pulling latest changes..."
git pull origin main
echo "Installing dependencies..."
pnpm install --frozen-lockfile
echo "Building..."
TURBO_TOKEN=${{ secrets.TURBO_TOKEN }} \
TURBO_TEAM=${{ vars.TURBO_TEAM }} \
npx turbo run build
echo "Running migrations..."
pnpm --filter @ecosire/db db:migrate
echo "Restarting services..."
pm2 restart ecosystem.config.cjs --update-env
echo "Health check..."
sleep 10
curl -f https://ecosire.com/api/health || exit 1
curl -f https://api.ecosire.com/api/health || exit 1
echo "Deploy complete!"
- name: Notify on success
if: success()
uses: actions/github-script@v7
with:
script: |
github.rest.repos.createCommitComment({
owner: context.repo.owner,
repo: context.repo.repo,
commit_sha: context.sha,
body: `Deployed to ${process.env.ENVIRONMENT} at ${new Date().toISOString()}`
})
env:
ENVIRONMENT: ${{ inputs.environment }}
- name: Notify on failure
if: failure()
uses: actions/github-script@v7
with:
script: |
github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: `Deploy failed: ${process.env.ENVIRONMENT}`,
body: `Deploy to ${process.env.ENVIRONMENT} failed at ${new Date().toISOString()}\n\nRun: ${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`
})
env:
ENVIRONMENT: ${{ inputs.environment }}
कैशिंग रणनीति
प्रभावी कैशिंग 2-मिनट और 8-मिनट सीआई रन के बीच का अंतर है:
# Reusable setup step (extract to composite action)
# .github/actions/setup-pnpm/action.yml
name: Setup pnpm
runs:
using: composite
steps:
- uses: pnpm/action-setup@v4
with:
version: '10.28.0'
- uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'pnpm'
# Turbo cache (separate from pnpm cache)
- uses: actions/cache@v4
with:
path: .turbo
key: turbo-${{ runner.os }}-${{ github.sha }}
restore-keys: |
turbo-${{ runner.os }}-
- name: Install dependencies
run: pnpm install --frozen-lockfile
shell: bash
सुरक्षा सर्वोत्तम प्रथाएँ
कभी भी रहस्य न दोहराएँ:
# Wrong — secret appears in logs
- run: echo "API key is ${{ secrets.API_KEY }}"
# If you must generate and use runtime secrets
- run: |
echo "::add-mask::$GENERATED_SECRET"
GENERATED_SECRET=$(generate-secret)
echo "GENERATED_SECRET=$GENERATED_SECRET" >> $GITHUB_ENV
अनुमतियाँ प्रतिबंधित करें:
# Minimum permissions at workflow level
permissions:
contents: read
actions: read
checks: write # Add only what you need
jobs:
test:
permissions:
contents: read # Override at job level if needed
पुल अनुरोध इंजेक्शन को रोकें:
# For PRs from forks — never expose secrets
on:
pull_request:
jobs:
test:
# Secrets not available in fork PRs by default
# Use pull_request_target only for trusted actions
runs-on: ubuntu-latest
अक्सर पूछे जाने वाले प्रश्न
मैं केवल विशिष्ट पैकेज बदलने पर ही वर्कफ़्लो कैसे ट्रिगर करूं?
यह पता लगाने के लिए dorny/paths-filter का उपयोग करें कि कौन से पैकेज बदले हैं, फिर फ़िल्टर आउटपुट को कार्य स्थितियों में पास करें। टर्बो की अंतर्निहित प्रभावित पहचान के लिए, अपने चेकआउट चरण में fetch-depth: 2 सुनिश्चित करें ताकि टर्बो पिछले कमिट के मुकाबले तुलना कर सके। केवल परिवर्तित पैकेजों और उनके आश्रितों के लिए परीक्षण चलाने के लिए pnpm turbo run test --filter="...[HEAD^1]" का उपयोग करें।
मुझे सीआई में डेटाबेस माइग्रेशन को कैसे संभालना चाहिए?
माइग्रेशन को एक अलग कार्य में चलाएँ जो परीक्षणों के बाद लेकिन अंतिम बिल्ड आर्टिफैक्ट बनने से पहले चलता है। सीआई में एक समर्पित परीक्षण डेटाबेस यूआरएल का उपयोग करें (विकास और उत्पादन से अलग)। कभी भी CI से उत्पादन के विरुद्ध स्वचालित रूप से माइग्रेशन न चलाएं - उत्पादन डेटाबेस परिवर्तनों के लिए GitHub पर्यावरण संरक्षण नियमों के माध्यम से मैन्युअल अनुमोदन के साथ workflow_dispatch का उपयोग करें।
कई परिवेशों में रहस्यों को प्रबंधित करने का सबसे अच्छा तरीका क्या है?
सुरक्षा नियमों के साथ GitHub वातावरण (सेटिंग्स > वातावरण) का उपयोग करें। staging और production के लिए अलग वातावरण बनाएं। पर्यावरण-विशिष्ट रहस्यों को प्रत्येक परिवेश के अंतर्गत संग्रहित करें, भंडार स्तर पर नहीं। साझा रहस्यों (जैसे टर्बो रिमोट कैश टोकन) के लिए, रिपॉजिटरी-स्तरीय रहस्यों का उपयोग करें। कार्य कॉन्फ़िगरेशन में environment: कुंजी पर्यावरण-विशिष्ट रहस्यों और सुरक्षा नियमों को सक्षम करती है।
मैं सीआई में पीएनपीएम इंस्टालेशन की गति कैसे बढ़ाऊं?
actions/setup-node@v4 cache: 'pnpm' के साथ pnpm स्टोर को कैश करता है। बड़े मोनोरेपो के लिए, कैश को पुनर्स्थापित करने के बाद pnpm install --prefer-offline का भी उपयोग करें। पीएनपीएम स्टोर कैशिंग और टर्बो रिमोट कैशिंग का संयोजन आम तौर पर कैश हिट पर इंस्टॉल + बिल्ड समय को 60-80% तक कम कर देता है।
मैं पीआर बनाम मुख्य शाखा पुश के लिए अलग-अलग वर्कफ़्लो कैसे चला सकता हूं?
on ट्रिगर शर्तों का उपयोग करें: मुख्य के लिए on.push.branches और PRs के लिए on.pull_request.branches। आप पीआर (लिंट, यूनिट टेस्ट) के लिए परीक्षणों का तेज़ उपसमूह और मुख्य पर पूरा सूट चला सकते हैं। डिप्लॉयमेंट जॉब को केवल पुश टू मेन पर चलाने के लिए github.event_name == 'push' शर्तों का उपयोग करें, पीआर इवेंट पर नहीं।
अगले चरण
एक अच्छी तरह से डिज़ाइन की गई सीआई/सीडी पाइपलाइन एक उच्च-वेग इंजीनियरिंग टीम की नींव है - यह आपको बार-बार शिप करने और स्वचालित रूप से रिग्रेशन पकड़ने का आत्मविश्वास देती है। ECOSIRE लिंट, टाइप-चेक, 1,301 यूनिट टेस्ट, प्लेराइट E2E और मेन पर हर पुश पर शून्य-डाउनटाइम SSH परिनियोजन के साथ GitHub Actions CI चलाता है।
चाहे आपको सीआई/सीडी आर्किटेक्चर परामर्श, टर्बोरेपो मोनोरेपो सेटअप, या पूर्ण DevOps समर्थन की आवश्यकता हो, हमारी इंजीनियरिंग सेवाओं का अन्वेषण करें।
लेखक
ECOSIRE Research and Development Team
ECOSIRE में एंटरप्राइज़-ग्रेड डिजिटल उत्पाद बना रहे हैं। Odoo एकीकरण, ई-कॉमर्स ऑटोमेशन, और AI-संचालित व्यावसायिक समाधानों पर अंतर्दृष्टि साझा कर रहे हैं।
संबंधित लेख
AI-Powered Accounting Automation: What Works in 2026
Discover which AI accounting automation tools deliver real ROI in 2026, from bank reconciliation to predictive cash flow, with implementation strategies.
Payroll Processing: Setup, Compliance, and Automation
Complete payroll processing guide covering employee classification, federal and state withholding, payroll taxes, garnishments, automation platforms, and year-end W-2 compliance.
AI Agents for Business Automation: The 2026 Landscape
Explore how AI agents are transforming business automation in 2026, from multi-agent orchestration to practical deployment strategies for enterprise teams.