Continuous Deployment ساده برای خود راه اندازی کنید!!

فرایند انتشار نسخه و نصب و راه اندازی آن در سرور مخصوصا در مرحله ی توسعه ی نرم افزار، کاری تکراری و زمان بر است که توسعه دهنده با هر تغییر در سورس کد می بایست تمام مراحل را تکرار کند، بدین صورت که بعد از تغییر مورد نظر کد را کامپایل کرده، به سرور منتقل کند، نسخه ی اجرایی قبلی را متوقف کند و نسخه جدید را اجرا کند.


در این مطلب آموزشی برای یک برنامه نوشته شده با فریمورک اسپرینگ ( Spring Framework)؛ به عنوان نمونه؛ Continuous Deployment ساده یا به عبارت بهتر روشی برای نسخه گذاری اتوماتیک بر روی سرور شرح داده می شود تا توسعه دهنده برای نسخه گذاری فقط لازم باشد کد خود را بروی سرور push کند و تمام مراحل تکراری بعدی بصورت اتوماتیک انجام شود و نسخه ی برنامه ی در حال اجرا بروی سرور اتوماتیک بروز گردد.

به چه ابزاری نیاز داریم؟

  • فریمورک اسپرینگ
  • نصب git روی سیستم لوکال
  • نصب git روی سرور
دقت داشته باشید که برای استفاده از این روش محدود به Spring framework نیستید و با کمی تغییر می توانید این روش را برای هر سورس کد دیگری استفاده کنید.

اولین قدم راه اندازی git روی سیستم خود به عنوان توسعه دهنده است که احتمالا این کار را از قبل انجام داده اید، در غیر اینصورت به کمک دستورات زیر:

$ git init
$ git add

به پروژه ی خود git را اضافه می کنیم.

سپس به سرور متصل شده و یک git repository در سرور راه اندازی می کنیم، جهت خلاصه کردن آموزش صرفا به صورت خیلی ساده یک repository در سرور ایجاد می کنیم:

$ mkdir /home/amir/myrepo
$ cd /home/amir/myrepo
$ git init

سپس این repository را به عنوان remote repository به پروژه ی لوکال خود معرفی می کنیم:

$ git remote add origin ssh://[serverUser]@[serverIp]:/home/amir/myrepo

در صورتیکه در روند push کردن تغییرات با خطای زیر مواجه شدید:

 remote: error: refusing to update checked out branch: refs/heads/master

احتمالا دستور زیر مشکل را حل خواهد کرد:

git config receive.denyCurrentBranch ignore

تا اینجای کار یک repository در سرور خود ایجاد کرده ایم تا با push کردن بتوانید نسخه ی سورس کد موجود در سرور را بروز کنیم.

در قدم بعدی به کمک قابلیت git hooks اتوماتیک کردن روند نسخه گذاری را کامل تر می کنیم:

قلاب ها (hooks) در git اسکریپت هایی هستند که در مراحل یا رویدادهای مختلف git اجرا می شوند. در اینجا hookی تعریف می کنیم تا بعد از ایجاد تغییرات در repository سرور این اسکریپت اجرا شود.

قبل از انجام اینکار اجازه دهید یک فولدر جهت قراردادن نسخه ی کامپایل شده ی کد ایجاد می کنیم:

$ mkdir /home/amir/deploy

و تغییر کوچکی در برنامه ی spring ی خود دهیم:

SpringApplication app = new SpringApplication(Jhip4App.class);
app.addListeners(new ApplicationPidFileWriter());

با اینجام اینکار به برنامه یک Listener از جنس ApplicationPidFileWriter اضافه می کنیم تا هنگام اجرای برنامه PID یا شناسه پروسه برنامه را در یک فایل (application.pid) ذخیره کند.

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

$ nano /home/amir/myrepo/.git/hooks/post-receive
$ chmod ug+x /home/amir/myrepo/.git/hooks/*

و اسکریپت زیر را داخل آن قرار می دهیم:

#!/bin/bash
DEPLOY=&quot/home/amir/deploy&quot
GIT_DIR=&quot/home/amir/myrepo&quot
BRANCH=&quotmaster&quot
while read oldrev newrev ref
do
	# only checking out the master (or whatever branch you would like to deploy)
	if [ &quot$ref&quot = &quotrefs/heads/$BRANCH&quot ];
	then
		echo &quotRef $ref received. Deploying ${BRANCH} branch to production...&quot
		git --work-tree=$GIT_DIR --git-dir=$GIT_DIR/.git checkout -f $BRANCH
		echo &quottry to package...&quot
		$GIT_DIR/mvnw -f $GIT_DIR/pom.xml package -Dmaven.test.skip=true		
		echo &quottry to move jar file to depoly folder&quot
		\cp -fR $GIT_DIR/target/jhip-4-0.0.1-SNAPSHOT.jar $DEPLOY/app.jar
                echo &quottry to shutdown app&quot
                kill $(cat $DEPLOY/application.pid)		
                echo &quottry to run application...&quot
                nohup java -jar $DEPLOY/app.jar &
	else
		echo &quotRef $ref received. Doing nothing: only the ${BRANCH} branch may be 
                 deployed on this server.&quot
	fi
done

اسکریپ بالا چه می کند؟

اگر تغییر اعمال شده روی شاخه یا Branch مورد نظر (در اینجا master) باشد:

  • ابتدا تغییرات جدید روی سرور در مسیر مورد نظر checkout میشود
  • سپس با دستور maven package فایل jar برنامه تولید می شود
  • در مرحله ی بعد این فایل jar به مسیر deploy منتقل می گردد
  • سپس با کمک فایل application.pid که هنگام اجرای برنامه ساخته می شود برنامه ی قبلی shutdown می شود
  • و در آخر برنامه جدید با nohup در بک گراند اجرا می شود

به همین سادگی و بدون نیاز به راه اندازی CI/CD پیچیده، مراحل نسخه گذاری مخصوصا در فاز توسعه نرم افزار را می توان اتوماتیک کرد.