پرش به مطلب اصلی

CI/CD

مقدمه

زمانی که بر روی یک پروژۀ شخصی کار می‌کنیم، معمولاً به ندرت احتیاج داریم آن را تست یا مستقر کنیم. اما زمانی که پروژه به صورت تیمی توسعه داده شود، نیاز است به طور مداوم تست‌های مختلف اجرا و فرآیند استقرار به‌طور خودکار انجام شود. برای حل این مشکل می‌توانیم از روش‌های Continuous Integration و Continuous Deployment استفاده کنیم.

  • چگونه می‌توان تست‌ها را به‌طور خودکار اجرا کرد؟
  • چگونه می‌تواند فرآیندی جهت استقرار پروژه تنظیم کرد؟
  • چگونه می‌توان گزارشی از تمیزی کدهای جدید بدست آورد؟

یادگیری

تعریف

برای آشنایی بیشتر با این مفهوم می‌توانید از لینک‌های زیر استفاده کنید:


GitHub Actions

یکی از ابزارهای CI/CD معروف، GitHub Actions است که به کمک آن، می‌توانیم یک Pipeline شامل عملیات Build، اجرای Testها، استقرار پروژه و دیگر عملیاتی که در دستهٔ CI/CD قرار می‌گیرد را به Repository خود اضافه کنیم.

Setup

یک پوشه با نام github. در پوشۀ اصلی پروژه بسازید و یک پوشه با نام workflows به آن اضافه کنید. حال یک فایل که به پسوند yml ختم می‌شود را درون پوشۀ workflows قرار دهید؛ به‌طور مثال ما از نام deploy.yml استفاده می‌کنیم.

برای آنکه نام Workflow را مشخص کنید، کافی است محتوای زیر را به فایل خود اضافه نمایید:

name: Deployment Workflow

Conditions

ممکن است بخواهید فقط زمانی Workflow اجرا شود که بر روی یک Branch خاص عملیات Push را انجام می‌دهید؛ در این صورت محتوای زیر را به فایل خود اضافه نمایید:

on:
push:
branches:
- main

اما اگر می‌خواهید بر روی تمام Branchها این اتفاق بیفتد؛ از محتوای زیر استفاده کنید:

on:
push:

همچنین می‌توانید شرایط دیگری را برای اجرا شدن Workflow در نظر بگیرید؛ به‌عنوان مثال ایجاد یک Pull Request جدید یا عوض‌شدن وضعیت Issueها.

Test

هر Workflow می‌تواند شامل چند Job باشد که به‌صورت موازی یا متوالی انجام می‌شوند.

برای تعریف کار Test می‌توانید از محتوای زیر استفاده کنید:

jobs:
test:
name: Test
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2

- name: Setup Node
uses: actions/setup-node@v1
with:
node-version: '16.x'

- name: Install Dependencies
run: npm ci

- name: ESLint
run: npm run eslint:check

- name: Stylelint
if: success()
run: npm run stylelint:check

- name: Prettier
if: success()
run: npm run prettier:check

- name: Angular
if: success()
run: npm run test:ci

در اینجا ابتدا نامی برای Job در نظر می‌گیریم تا بتوانیم آن را از سایر Jobها تشخیص دهیم؛ در خط بعد سیستم‌عاملی که Job بر روی آن اجرا می‌شود را مشخص کنیم؛ سپس مراحل کار را تعریف می‌کنیم که هر کدام را در ادامه به‌صورت مختصر توضیح می‌دهیم.

Checkout

همان‌طور که شما برای انجام هر کاری احتیاج دارید ابتدا بر روی Branch مورد نظر عملیات Checkout را انجام دهید، زمانی که از GitHub Actions استفاده می‌کنیم هم باید این عملیات انجام شود.

Setup Node

در این مرحله Node.js بر روی سیستم عامل نصب می‌شود. شما می‌توانید یک نسخۀ خاص از Node.js را که مطمئنید با پروژۀ شما سازگار است نصب کنید.

Install Dependencies

با اجرای دستور npm ci در ترمینال به نصب Dependencyها می‌پردازیم.

ESLint

با اجرای دستور npm run eslint:check از پاس‌شدن تست‌های ESLint اطمینان حاصل می‌کنیم.

Stylelint

با اجرای دستور npm run stylelint:check از پاس‌شدن تست‌های Stylelint اطمینان حاصل می‌کنیم.

Prettier

با اجرای دستور npm run prettier:check از پاس‌شدن تست‌های Prettier اطمینان حاصل می‌کنیم.

Angular

با اجرای دستور npm run test:ci از پاس‌شدن تست‌های Angular اطمینان حاصل می‌کنیم.

Scripts

این Scriptها را باید به فایل package.json اضافه نمایید:

{
"name": "...",
"version": "...",
"scripts": {
"eslint:check": "ng lint",
"eslint:fix": "ng lint --fix",
"stylelint:check": "stylelint \"**/*.scss\"",
"stylelint:fix": "stylelint \"**/*.scss\" --fix",
"prettier:check": "prettier . --check",
"prettier:fix": "prettier . --write",
"test:ci": "ng test --browsers=ChromeHeadless --watch=false"
}
}

همچنین برای راحتی کار شما، نسخۀ fix: را برای هر Script قرار داده‌ایم تا با استفاده از آن بتوانید خطاهای احتمالی را به‌صورت خودکار رفع کنید.

Build

برای تعریف کار Build می‌توانید از محتوای زیر استفاده کنید:

jobs:
test: ...
build:
name: Build
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2

- name: Setup Node
uses: actions/setup-node@v1
with:
node-version: '16.x'

- name: Install Dependencies
run: npm ci

- name: Build
run: npm run build:prod

- name: 404.html Hack
if: success()
run: cp dist/my-project-name/index.html dist/my-project-name/404.html

- name: Upload Build
if: success()
uses: actions/upload-artifact@v1
with:
name: deploy_dist
path: dist

با اجرای دستور npm run build:prod از پروژه Build تهیه می‌کنیم.

این Script را باید به فایل package.json اضافه نمایید:

{
"name": "...",
"version": "...",
"scripts": {
"build:prod": "ng build --base-href=/my-project-name/"
}
}
caution

به جای my-project-name باید نام پروژۀ خود را قرار دهید.

404.html Hack

زمانی که از GitHub Pages برای استقرار سایت استفاده می‌کنیم، اگر به‌صورت دستی آدرس یکی از صفحات را در مرورگر وارد کنیم، صفحۀ 404 نمایش داده می‌شود و از Routing خودِ Angular استفاده نمی‌کند. برای حل این مشکل یک کپی از index.html می‌گیریم و نام آن را 404 می‌گذاریم.

Upload Build

تنها در صورتی که نتیجۀ Build موفقیت‌آمیز بود، آن را به طور موقت با نام deploy_dist ذخیره می‌کنیم تا در ادامه بتوانیم از آن استفاده کنیم.

Deploy

برای تعریف کار Deploy می‌توانید از محتوای زیر استفاده کنید:

jobs:
test: ...
build: ...
deploy:
name: Deploy
runs-on: ubuntu-latest
needs:
- test
- build
steps:
- name: Checkout
uses: actions/checkout@v1

- name: Download Build
uses: actions/download-artifact@v1
with:
name: deploy_dist

- name: Deploy to GitHub Pages
uses: JamesIves/github-pages-deploy-action@releases/v3
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BRANCH: gh-pages
FOLDER: deploy_dist/my-project-name
caution

به جای my-project-name باید نام پروژۀ خود را قرار دهید.

Download Build

پوشه‌ای که در مرحلۀ قبل ذخیره کرده بودیم را در اینجا دانلود می‌کنیم.

Deploy to GitHub Pages

محتویات پوشه را داخل برنچ gh-pages قرار می‌دهیم که GitHub بتواند از آن استفاده کند.

Monitor

از این پس، بعد از آنکه بر روی Branch مورد نظر عملیات Push انجام دهید، در صفحۀ Actions پروژۀ خود می‌توانید اجرا آن را مرحله به مرحله زیر نظر بگیرید و در صورتی که خطایی رخ دهد از آن باخبر شوید.


پروژه

با توجه به مطالبی که در این فاز یاد گرفتید، فرآیند CI/CD را برای پروژۀ خود فراهم کنید.