لاراول، فریمورک وب PHP، به دلیل سینتکس زیبا، ویژگیهای قوی و قدرتی که در اختیار توسعهدهندگان قرار میدهد، محبوبیت زیادی به دست آورده است. اگر می ترسید وارد دنیایی ناشناخته شوید، فقط آنچه که در این مقاله وجود دارد را به یاد داشته باشید، و هرگز نمی توانید بدانید که سازگاری با آن برای شما چقدر آسان است و چقدر می توانید از آن لذت ببرید.
ممکن است برای تنظیم CI/CD برای لاراول کمی سخت یا واضح نباشد. برای تازه واردان، موانع زیادی وجود دارد که باید از آنها عبور کنید تا به ثمره اتوماسیون برسید که باید تک تک مشکلاتی را که با آن مواجه میشوید در گوگل جستجو کنید تا زمانی که با مشکل GitHub مواجه شوید که با «nvm، رفع شد» بسته شده است.
در این مقاله می خواهیم به شما در مورد CI/CD، نحوه تنظیم صحیح CI/CD برای پروژه های لاراول خود و نحوه انجام تست های واحد خوب، و نحوه پیکربندی CI/CD برای اجازه دادن به تست های مرورگر با لاراول را به شما آموزش دهم.
CI/CD چیست؟ و چه کاری انجام می دهد؟
ممکن است، در همان ابتدای برنامهنویسی، شما فقط فایلهای فشرده بایگانیشده را با کد منبع از برنامهنویسی به برنامهنویس دیگر منتقل کنید و تا زمانی که Git آمد و ایدئولوژی کنترل منبع را اصلاح کرد، یک آشفتگی کامل بود. این اتفاق با CI/CD افتاد. در ابتدا، بدون داشتن هیچ ایده ای از خرابی چیزی کد خود را به صورت دستی آزمایش می کردند (زیرا می توانم به شما بگویم،اگر تستی نداشته باشید، ممکن است برنامه شما در جایی خراب شود). بنابراین آزمایشهای خودکار آمدند و کار آزمایش دستی را آسان کردند، فقط به یک ماشین مجازی در فضای ابری بگویید (در نسخههای جدیدتر کانتینرهای Docker در یک خوشه Kubernetes میچرخند) تا یک Pipeline (مجموعهای از مراحل) را شروع کند: PHP را اجرا کنید. ، Ruby یا هر چیز دیگری و یک لیست دقیق از دستورات را انجام دهید، مانند اجرای یک نمونه MySQL و پر کردن آن با داده های فیک برای تست، و اگر هیچ دستوری وجود نداشت که یک کد خروج غیر صفر را برمی گرداند، تست ها را به عنوان قبول شده علامت بزنید.
CI/CD مخفف Continous Integration و Continous Deployment است، یعنی استقرار مداوم و تحویل مداوم در اصل، شما کد می نویسید، کد روی یک ماشین مجازی در فضای ابری قرار می گیرد و با آن لیست دقیق دستورات، یا نتیجه می گیرید که کد شما خوب است یا بد، و در مرحله دوم (CD) که روشن می شود، می پرد. سرور (بدون اینکه کاربران شما حتی متوجه آن شوند مستقر می شود) (یا اگر شما برای استقرار زمان توقف غیر صفر انتخاب کرده اید، می توانند متوجه شوند).
بنابراین، در shell، هر نوع دستوری که یک کد خروج غیر صفر را برمی گرداند خوب تلقی می شود. در غیر این صورت، ممکن است در ساخت شکست بخورد یا ممکن است یک ساخت خطرناک باشد. به عنوان مثال، این دستور یک کد خروجی صفر را برمی گرداند:
$ ls -al
این یک کد خروج غیر صفر را برمی گرداند (زیرا در این مورد، my-inexistent-cli
یک دستور غیر موجود است):
$ my-inexistent-cli
ما همچنین چرا CI/CD برای شرکت شما مهم می باشد را نیز بررسی کردیم.
راه اندازی CI/CD در لاراول
بنابراین، لاراول یک روش داخلی و تمیز برای نوشتن تست با استفاده از PHPUnit یا Dusk دارد، اما ابزاری برای تنظیم پیکربندی برای این مورد وجود ندارد. من به شما خواهم گفت که چگونه CI/CD را برای دو ارائه دهنده اصلی تنظیم کنید: GitlabCI، CircleCI.
بیاید در گیت لب با هم دیگر راه اندازی کنیم.
Gitlab CI
اگر قصد دارید از این برای پروژه های خصوصی خود استفاده کنید، 400 دقیقه ساخت برای حداکثر دو نفر در هر پروژه کافی است؟ می توانید هر ماه حدود 80 بیلد (هر کدام 5 دقیقه) را به صورت رایگان اجرا کنید. چیزی که من متوجه شدم این است که کند است، به خصوص هنگام اجرای اسکریپت نصب Chromium برای Dusk Tests. من دو نسخه به شما می دهم، یکی با PHPUnit و دیگری با هر دو PHPUnit و Dusk، فقط برای اینکه بتوانید ایده بگیرید.
شاید با خودتان بگویید که : "شما می توانستید از نسخه ای از PHP که همراه با آپاچی است استفاده کنید" اما به طور جدی، تا زمانی که لاراول یک روش داخلی برای راه اندازی وب سرور دارد، نیازی به ثانیه های اضافی برای ساخت من نیست. همچنین به دلیل ماهیت داخلی می توان آن را در هنگام غروب به درستی انجام داد.
این باید در gitlab-ci.yml
شما در داخل پروژه ریشه شما باقی بماند. دفعه بعد که برنامه خود را push کردید، CI/CD را از منوی سمت چپ در مخزن خود بررسی کنید. یک Pipeline جدید باید شروع شود.
به این صورت:
stages:
- test
# Set up cache, so we have to run composer update between builds, speeding it up!
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- node_modules/
- vendor/
test:
image: edbizarro/gitlab-ci-pipeline-php:7.2
stage: test
services:
- mariadb:10.3.11
variables:
MYSQL_DATABASE: "test"
MYSQL_ROOT_PASSWORD: "secret"
script:
- composer update --no-interaction --no-progress --prefer-dist --optimize-autoloader --ignore-platform-reqs
- cp .env.testing .env
- php artisan key:generate
- php artisan config:cache
- php artisan route:cache
- npm install
- npm run prod
- php artisan migrate --seed
- php artisan storage:link
- php artisan serve &
- vendor/bin/phpunit
بنابراین، Gitlab CI به کانتینرها متکی است، بنابراین اگر MySQL را به جای MariaDB میخواهید، راحت آن را به mysql:[your_version]
تغییر دهید، برای مثال: mysql:5.7. همچنین، اگر دارایی ها را با npm کامپایل نکنید، نصب و اجرای prod بی فایده است.
همچنین، من از ایمیج Gitlab Pipeline Ed Bizarro برای آزمایش استفاده میکنم، با خیال راحت نسخه PHP را به چیزی مناسب تغییر دهید.
برای این تست، برای اجرای آن به این نوع env.testing.
نیاز است:
APP_NAME="Laravel"
APP_ENV=testing
APP_KEY=
APP_DEBUG=true
APP_URL=http://127.0.0.1:8000
LOG_CHANNEL=null
DB_CONNECTION=mysql
DB_HOST=mariadb #change with string 'mysql' if you run mysql
DB_PORT=3306
DB_DATABASE=test
DB_USERNAME=root
DB_PASSWORD=secret
BROADCAST_DRIVER=log
CACHE_DRIVER=file
SESSION_DRIVER=file
SESSION_LIFETIME=120
QUEUE_DRIVER=sync
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_DRIVER=smtp
MAIL_HOST=localhost
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
بنابراین، برای آزمایش با Dusk به تنظیمات بیشتری نیاز داریم:
stages:
- test
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- node_modules/
- vendor/
test:
image: edbizarro/gitlab-ci-pipeline-php:7.2
stage: test
services:
- mariadb:10.3.11
variables:
MYSQL_DATABASE: "test"
MYSQL_ROOT_PASSWORD: "secret"
# Install Google Chrome
before_script:
- sudo apt-get update -y
- sudo apt-get install unzip xvfb libxi6 libgconf-2-4 libnss3 wget -yqq
- wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
- sudo sh -c 'echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list'
- sudo apt-get update -yqq
- sudo apt-get install -y google-chrome-stable
script:
- composer update --no-interaction --no-progress --prefer-dist --optimize-autoloader --ignore-platform-reqs
- cp .env.testing .env
- php artisan key:generate
- php artisan config:cache
- php artisan route:cache
- npm install
- npm run prod
- php artisan migrate --seed
- php artisan storage:link
- php artisan serve &
- ./vendor/laravel/dusk/bin/chromedriver-linux --port=9515 &
- sleep 5
- vendor/bin/phpunit
- php artisan dusk
برای این کار، یک env.dusk.testing
اضافی مورد نیاز است:
APP_NAME="Laravel"
APP_ENV=testing
APP_KEY=
APP_DEBUG=true
APP_URL=http://127.0.0.1:8000
LOG_CHANNEL=null
DB_CONNECTION=mysql
DB_HOST=mariadb
DB_PORT=3306
DB_DATABASE=test
DB_USERNAME=root
DB_PASSWORD=secret
BROADCAST_DRIVER=log
CACHE_DRIVER=file
SESSION_DRIVER=file
SESSION_LIFETIME=120
QUEUE_DRIVER=sync
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_DRIVER=smtp
MAIL_HOST=localhost
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
CircleCI
در CircleCI نیز 500 دقیقه برای لذت بردن از آزمایش و استقرار شما ارائه می دهد. ثابت می کند در مقایسه با Gitlab CI سریع است. یک دقیقه کامل (از 3 دقیقه به 2 دقیقه، با همان ساخت اولیه) قطع می شود، زیرا آنها بر روی CPU های بهینه شده کار می کنند.
برای CircleCI از همان پیکربندی فایلهای env استفاده میکنم، اما از پیکربندی متفاوت. این بار، یک پوشه به نام circleci.
خواهید داشت و داخل آن باید یک config.yml
باشد:
version: 2
jobs:
test:
docker:
- image: edbizarro/gitlab-ci-pipeline-php:7.2
- image: circleci/mysql:5.7
environment:
MYSQL_DATABASE: "test"
MYSQL_ROOT_PASSWORD: "secret"
working_directory: /var/www/html
steps:
- checkout
# Install Google Chrome
- run: sudo apt-get update -y
- run: sudo apt-get install unzip xvfb libxi6 libgconf-2-4 libnss3 wget -yqq
- run: wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
- run: sudo sh -c 'echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list'
- run: sudo apt-get update -yqq
- run: sudo apt-get install -y google-chrome-stable
- restore_cache:
keys:
- vendor-{{ checksum "composer.json" }}
- run: composer update --no-interaction --no-progress --prefer-dist --optimize-autoloader --ignore-platform-reqs
- save_cache:
paths:
- ./vendor
key: vendor-{{ checksum "composer.json" }}
- run: cp .env.testing.env
- run: php artisan key:generate
- run: php artisan config:cache
- run: php artisan route:cache
- restore_cache:
keys:
- node-{{ checksum "package.json" }}
- run: npm update
- save_cache:
paths:
- ./node_modules
key: node-{{ checksum "package.json" }}
- run: npm run prod
- run: php artisan migrate --seed
- run: php artisan storage:link
- run:
background: true
command: php artisan serve
- run:
background: true
command: ./vendor/laravel/dusk/bin/chromedriver-linux --port=9515
- run: ./vendor/bin/phpunit
- run: php artisan dusk
workflows:
version: 2
deploy:
jobs:
- test
این پیکربندی به بازیابی حافظه نهان قبل از اجرای بهروزرسانی composer یا بهروزرسانی npm و ذخیره node_modules و پوشههای vendor در کش برای استفاده بعدی متکی است.
Service containers
بنابراین، همانطور که از ابتدا به شما گفتم، می توانید یک Pipeline CI/CD را در مراحل کوچک، با یک فایل env و یک فایل YAML راه اندازی کنید. شما فقط دستوراتی را اعلام می کنید که می توانند در پس زمینه یا جداگانه اجرا شوند، مانند کانتینرهای سرویس.
کانتینرهای سرویس در پیکربندی شما اعلان می شوند و به شما امکان می دهند چیزهای اساسی مانند Redis، MySQL یا MongoDB را تنظیم کنید. همه اینها بر اساس کانتینرهای Docker هستند. می توانید کانتینرهای خدمات خود را در Docker Hub جستجو کنید. به عنوان مثال، می توانید یک تصویر برای MongoDB پیدا کنید و از آن در Pipeline خود استفاده کنید:
version: 2
jobs:
test:
docker:
- image: edbizarro/gitlab-ci-pipeline-php:7.2
- image: mongo:4.0.3
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: example
- image: circleci/mysql:5.7
environment:
MYSQL_DATABASE: "test"
MYSQL_ROOT_PASSWORD: "secret"
working_directory: /var/www/html
steps:
- checkout
...
در پیکربندی Gitlab CI اینگونه به نظر می رسد:
...
phpunit:
image: edbizarro/gitlab-ci-pipeline-php:7.2
stage: test
services:
- mariadb:10.3.11
- mongo:4.0.3
variables:
MYSQL_DATABASE: "test"
MYSQL_ROOT_PASSWORD: "secret"
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: example
...
میتوانید کانتینرهایی را با سرویسها باز کنید و آنها را متغیرهای محیطی تنظیم کنید. مطمئن شوید که با استفاده از نام تصویر به عنوان میزبان به آنها دسترسی دارید. به عنوان مثال، کانتینر mariadb با 127.0.0.1 قابل دسترسی نیست، بلکه با رشته mariadb قابل دسترسی است. مطمئن شوید که وقتی این را در فایل env خود تنظیم می کنید، به این صورت باشد.
نتیجه
ما در این مقاله با قدرت CI و CD آشنا شدیم و نحوه استفاده از آن نیز برای شما شرح دادیم. ممکن است در ابتدا کمی سخت باشد ولی بعد از چند بار تکرار و تلاش می توانید به آن تلسط پیدا کنید و از آن لذت خواهید برد.و نکته ای که باید به آن توجه کنید این است که من یک کانتینر برای Redis تنظیم نکردم زیرا در آزمایشات می خواهید پاسخی را به صورت همگام دریافت کنید، بنابراین می توانید آنها را از یک سر به سر دیگر به روشی کاملاً روان آزمایش کنید، تصور کنید اگر شما یک کار را شروع میکند، و زمانی که آزمایشهای شما شروع به ارائه مدلی میکنند که باید در پایگاه داده نوشته میشد، به طور کامل پردازش نمیشود، برای این نوع آزمایشها، از ویژگی Mocking استفاده کنید.