وقتی روی یک پروژه کار میکنید، مجموعهای از دستورهای تکراری دارید که باید بارها اجرا شوند:
1npm install
2npm run lint
3npm test4npm run build
5docker build -t myapp .
6docker push myapp
مشکل این است که:
باید همهٔ این دستورها را به خاطر بسپارید
وقتی عضو جدیدی به تیم میپیوندد، باید آنها را یاد بگیرد
اگر دستوری عوض شود، باید همه را مطلع کنید
در CI/CD باید دقیقاً همان دستورها را تکرار کنید
Makefile این مشکل را حل میکند: شما دستورهای پروژه را یکبار در Makefile تعریف میکنید، بعد همه فقط make test یا make build میزنند.
Makefile چیست؟
make اصلاً برای compile کردن برنامههای C/C++ ساخته شده، اما امروزه بیشتر بهعنوان task runner استفاده میشود — ابزاری برای اجرای دستورهای استاندارد پروژه.
یک Makefile از targetها تشکیل شده. هر target یک نام دارد و یک یا چند دستور:
1test:2 npm test34build:5 npm run build
67deploy:8 ./scripts/deploy.sh
حالا بهجای یادآوری دستور دقیق، فقط میزنید:
1make test2make build
3make deploy
ساختار Makefile
یک Makefile ساده:
1# این یک comment است
2 3.PHONY:help 4help: 5 @echo "Available commands:" 6 @echo " make install - Install dependencies" 7 @echo " make test - Run tests" 8 @echo " make build - Build the application" 910.PHONY:install11install:12 npm install
1314.PHONY:test15test:16 npm test1718.PHONY:build19build:20 npm run build
نکات مهم:
Tab، نه Space: خطوط دستور باید با Tab شروع شوند (نه space)
.PHONY: به make میگوید این target یک فایل نیست، یک دستور است
@: جلوی دستور باعث میشود خود دستور چاپ نشود، فقط خروجیاش
$(shell ...): اجرای یک دستور و قرار دادن خروجی در متغیر
$(VAR): استفاده از متغیر
مثال واقعی: Makefile یک پروژهٔ Node.js
1.DEFAULT_GOAL:=help 2 3APP_NAME:= myapp
4VERSION:=$(shell git describe --tags --always --dirty) 5NODE_ENV:= production
6 7.PHONY:help 8help: 9 @echo "Usage: make <target>"10 @echo ""11 @echo "Available targets:"12 @echo " install Install dependencies"13 @echo " lint Run linter"14 @echo " test Run tests"15 @echo " build Build for production"16 @echo " dev Run development server"17 @echo " clean Remove build artifacts"18 @echo " docker-build Build Docker image"19 @echo " all Run lint, test, and build"2021.PHONY:install22install:23 npm ci
2425.PHONY:lint26lint:27 npm run lint
2829.PHONY:test30test:31 npm test3233.PHONY:build34build:35NODE_ENV=$(NODE_ENV) npm run build
3637.PHONY:dev38dev:39 npm run dev
4041.PHONY:clean42clean:43 rm -rf dist node_modules coverage
4445.PHONY:docker-build46docker-build:47 docker build -t $(APP_NAME):$(VERSION) .
4849.PHONY:all50all:linttestbuild
استفاده:
1# نصب dependencies 2make install
3 4# اجرای تست 5make test 6 7# ساخت برای production 8make build
910# همهٔ مراحل پیش از deploy11make all
1213# ساخت Docker image14make docker-build
چرا Makefile در DevOps؟
1. Interface یکنواخت
تیم شما ممکن است پروژههایی با زبانهای مختلف داشته باشد:
Node.js → npm test
Python → pytest
Go → go test ./...
با Makefile، همهٔ پروژهها interface یکسان دارند:
1make test# در هر پروژهای2make build # در هر پروژهای
2. Reproducibility
دستورات دقیق در یک جا نوشته شدهاند. هم developer محلی و هم CI/CD از همان دستورها استفاده میکنند: