كيفية إعداد CI / CD Pipeline لتطبيق node.js مع Jenkins

ما هو CI / CD؟

التكامل المستمر والنشر المستمر هما من الممارسات الحديثة لتطوير البرمجيات. التكامل المستمر (CI) هو عملية أتمتة إنشاء واختبار التعليمات البرمجية في كل مرة يرتكب فيها أحد أعضاء الفريق تغييرات على التحكم في الإصدار. يمكن اعتبار النشر المستمر (CD) امتدادًا للتكامل المستمر ، وهي عملية نشر تطبيق تلقائيًا بعد نجاح CI. الهدف هو تقليل المهلة. الوقت المنقضي بين تطوير كتابة سطر جديد من التعليمات البرمجية وهذا الكود الجديد الذي يستخدمه المستخدمون المباشرون في الإنتاج.

لماذا CI / CD؟

هناك العديد من الفوائد لممارسات CI / CD. لن أتحدث عن كل منفعة بالتفصيل ولكني أود تسليط الضوء على القليل منها هنا:

فوائد التكامل المستمر:

  • البق أقل
  • تبديل سياق أقل عندما يتم تنبيه المطورين بمجرد كسر البنية
  • يتم تخفيض تكاليف الاختبار
  • يقضي فريق ضمان الجودة لديك وقتًا أقل في الاختبار

فوائد النشر المستمر:

  • الإصدارات أقل خطورة
  • من السهل الافراج
  • يرى العملاء دفق مستمر من التحسينات
  • تسريع عملية التطوير لعدم وجود حاجة لإيقاف التطوير للإصدارات

ما الذي سنبنيه؟

نحن بصدد إنشاء تطبيق Node بسيط واستضافته على مثيل DigitalOcean. بالإضافة إلى ذلك ، سنقوم بتكوين خادم أتمتة واستضافة Jenkins على مثيل DigitalOcean منفصل. سوف Jenkins مساعدتنا لأتمتة عملية CI / CD. في كل تغيير رمز من مستودع تطبيق Node الخاص بنا ، سيتم إخطار Jenkins وسيقوم بإجراء التغييرات في Jenkins Server (الخطوة 1) ، وتثبيت التبعيات (الخطوة 2) وتشغيل اختبار التكامل (الخطوة 3). إذا نجحت جميع الاختبارات ، فسيقوم Jenkins بنشر التطبيق على خادم العقدة (الخطوة 4). إذا فشلت ، سيتم إعلام المطور.

ميزة 1

إنشاء تطبيق العقدة

قبل أن نكتب أي خط أنابيب CI / CD ، نحتاج إلى تطبيق لاختبار ونشر. سنقوم ببناء تطبيق node.js بسيط يستجيب بنص "hello world". أولاً ، دعنا ننشئ مستودع جيثب لهذا المشروع.

تعيين مستودع جيثب

قم بإنشاء مستودع جديد تحت حساب GitHub الخاص بك وقم بتسميته باسم "node-app".

  • يمكنك اختيار الريبو العام أو الخاص
  • تحقق من تهيئة هذا المستودع باستخدام مربع اختيار README
  • حدد عقدة في القائمة المنسدلة إضافة .gitignore
  • انقر فوق زر إنشاء مستودع
الشكل 2

الآن دعنا نستنسخ الريبو الخاص بتطبيق node-appo على جهاز الكمبيوتر المحلي لدينا وانتقل إليه:

git clone git@github.com: <اسم مستخدم github> /node-app.git
مؤتمر نزع السلاح التطبيق العقدة

إنشاء تطبيق Node.js

الخطوة الأولى عند إنشاء تطبيق عقدة هي إنشاء ملف package.json. في هذا الملف ، ندرج تبعيات التطبيق. قم بإنشاء ملف جديد في جذر مشروعك يسمى package.json وانسخ المحتوى التالي الصقه فيه:

{
 "الاسم": "تطبيق العقدة" ،
 "الوصف": "تطبيق اختبار hello jenkins" ،
 "الإصدار": "0.0.1" ،
 "خاص": صحيح ،
 "التبعيات": {
    "صريح": "3.12.0"
 }،
 "devDependencies": {
    "المخاوي": "1.20.1" ،
    "الاختبار الفائق": "0.13.0"
 }
}
  • صريح: إطار العقدة
  • mocha: إطار اختبار للعقدة (يمكنك اختيار إطار اختبار آخر إذا كنت ترغب في ذلك مثل Jasmin و Jest و Tape وما إلى ذلك)
  • supertest: توفير تجريد عالي المستوى لاختبار HTTP

بعد أن حددنا تبعياتنا في ملف package.json ، نحن على استعداد لتثبيتها:

تثبيت npm

رائع! على استعداد لكتابة بعض الرموز؟ قم بإنشاء ملف جديد في جذر المشروع يسمى index.js وانسخ التعليمة البرمجية التالية:

// استيراد إطار العقدة
فار اكسبريس = تتطلب ('اكسبريس') ؛
 
فار التطبيق = اكسبريس () ؛
الرد على "مرحبا العالم" للطلبات التي تصل جذرنا "/"
app.get (‘/ '، وظيفة (مسا ، دقة) {
 res.send ('hello world') ؛
})؛
// الاستماع إلى منفذ 3000 افتراضيا
app.listen (process.env.PORT || 3000) ؛
 
module.exports = التطبيق ؛

سيرد تطبيقنا على "hello world" عندما تصل الطلبات إلى عنوان URL الجذري ("/").

وهذا هو تطبيقنا!

هنا هو هيكل المجلد النهائي:

الشكل 3

نحن الآن على استعداد لتشغيل تطبيقنا:

index.js العقدة

يمكنك عرض تطبيقك على متصفحك عند الانتقال إلى http: // localhost: 3000

اختبارات الكتابة

نحن على استعداد لكتابة اختبار التكامل الأول لدينا. سينتقل اختبارنا إلى جذر الموقع ("/") والتحقق من أن الصفحة تستجيب للنص "hello world".

تحت دليل جديد / اختبار / إنشاء test.js. انسخ والصق الكود التالي:

طلب var = requ (‘supertest’) ؛
var app = require (‘../ index.js’) ؛
صف (ET GET / ’، الوظيفة () {
 (الرد مع hello world) ، الوظيفة (القيام به) {
 // انتقل إلى الجذر وتحقق من الاستجابة "عالم الترحيب"
 طلب (تطبيق) .get (‘/ '). توقع (ello hello world'، done)؛
 })؛
})؛

سوف نستخدم Mocha لإجراء اختبارنا. لقد قمنا بتثبيت Mocha كجزء من devDependencies في ملف package.json. لتشغيل الاختبار ، نحتاج إلى اجتياز ملف Mocha الخاص بنا /test/test.js كوسيطة.

./node_modules/.bin/mocha ./test/test.js

إذا قمت بتشغيل هذا الأمر من جذر المشروع الخاص بك ، فسترى اختبار التشغيل الخاص بنا.

الشكل 4

بالنظر إلى الشكل 1 ، الخطوة رقم 3 ، نود أن يقوم جينكينز بتنفيذ اختبار التكامل الخاص بنا بعد بنائه. لتحقيق ذلك ، نحتاج إلى إنشاء نص برمجي في مشروعنا يؤدي إلى اختبارنا.

قم بإجراء / script / مجلد جديد واختبار اسم الملف دون امتداد الملف. انسخ والصق الكود التالي في ملف الاختبار:

#! / بن / ش
./node_modules/.bin/mocha ./test/test.js

منح أذونات قابلة للتنفيذ:

شمود + س النصي / اختبار

واختبره عن طريق تنفيذ البرنامج النصي shell من جذر المشروع:

./script/test

فقاعة! اختبار الاندماج جاهز والآن نحن على استعداد لدفع كودنا إلى جيثب:

بوابة إضافة.
git ارتكاب - m "تطبيق عقدة بسيط مع اختبار"
بوابة دفع أصل الرئيسي

خدمة العقدة التطبيق

سنستضيف تطبيق العقدة الخاص بنا على خادم حتى يتمكن العالم بأسره من رؤية تحفة أعمالنا سوف نستخدم DigitalOcean كموفر استضافة لدينا. توفر DigitalOcean طريقة سهلة لتكوين الخوادم وتدوير مثيلات جديدة.

إنشاء عقدة Droplet

الاشتراك وتسجيل الدخول إلى حساب DigitalOcean الخاص بك.

  • انقر على زر إنشاء قطرة جديدة.
  • اختر صورة: انقر فوق علامة تبويب التطبيق بنقرة واحدة وحدد العقدة JS من القائمة
  • اختيار الحجم: 1GB (أرخص واحد)
  • اختر منطقة مركز بيانات: اختر الأقرب إليك. اخترت منطقة نيويورك 3
  • أضف مفاتيح SSH: أضف مفتاح SSH الخاص بالجهاز المحلي. إذا لم يكن لديك مفتاح SSH ، فاتبع هذا لإنشاء مفتاح. سيقوم هذا الأمر بنسخ مفتاح SSH العام ولصقه في حقل النص
pbcopy <~ / .ssh / id_rsa.pub
  • اختر اسم مضيف: أطلق عليه اسم "nodejs-app"
  • انقر فوق زر إنشاء

سوف تكون الحبرية جاهزة في بضع ثوانٍ.

الشكل 5

تكوين خادم Nodejs-app

دعونا نضع قبعة DevOps ونضع خادم العقدة الخاص بنا

افتح جهازك على جهازك المحلي وتسجيل الدخول إلى خادم التطبيق nodejs الخاص بك كمستخدم الجذر:

ssh root@NODE.SERVER.IP

الآن قمت بتسجيل الدخول كمستخدم الجذر وهو مستخدم قوة عظمى. و "مع القوة العظمى تأتي مسؤوليات كبيرة".

نظرًا لأننا لا نحب المسؤوليات ، فلنقم بإنشاء مستخدم جديد للقيام بتكوين الخادم وتسميته باسمك الأخير:

adduser 

اختر كلمة مرور المستخدم واتبع التعليمات. قبل أن ننتقل إلى مستخدمنا الجديد ، نحتاج إلى منحه امتيازات sudo:

usermod -a -G sudo 

الآن يمكنك التبديل إلى المستخدم الجديد الخاص بك.

اسم المستخدم سو

نشر التطبيق العقدة

يأتي خادم DigitalOcean الخاص بنا مع Node لكن ليس Git. يتيح تثبيت git باستخدام التطبيق-get:

sudo-apt-get install git

استنساخ الريبو التطبيق العقدة لدينا:

بوابة استنساخ https://github.com//node-app.git

انتقل إلى مجلد المشروع وتثبيت تبعيات التطبيق:

مؤتمر نزع السلاح التطبيق العقدة
تثبيت npm - الإنتاج

قبل أن نتمكن من الوصول إلى التطبيق لدينا على المتصفح ، نحتاج إلى إكمال خطوة إضافية. كما تتذكر ، فإننا نقوم بتشغيل تطبيقنا على المنفذ 3000 افتراضيًا. يعمل جدار الحماية DigitalOcean على منع العملاء من الوصول إلى أي منفذ باستثناء 80. الحمد لله Ubuntu يتضمن أداة تكوين جدار الحماية UFW التي تضيف قاعدة جدار الحماية لإلغاء حظر منافذ معينة.

لنقم بإلغاء قفل المنفذ 3000 وتشغيل تطبيقنا:

sudo ufw تسمح 3000
index.js العقدة

يمكنك الآن الوصول إلى تطبيق العقدة الخاص بك عن طريق إلحاق المنفذ إلى عنوان IP الخاص بك:

HTTP: //NODE.SERVER.IP: 3000

تشغيل التطبيق العقدة إلى الأبد

يعد بدء تطبيق العقدة كما هو موضح أعلاه جيدًا لأغراض التطوير ولكن ليس في الإنتاج. في حالة تعطل مثيل العقدة لدينا ، نحتاج إلى عملية ستقوم بإعادة التشغيل التلقائي. سنستخدم وحدة PM2 لمساعدتنا في هذه المهمة. PM2 هو مدير عملية للأغراض العامة ووقت تشغيل إنتاج لتطبيقات Node.js مع Load Balancer مدمج. لنقم بتثبيت PM2 وبدء مثيل العقدة لدينا:

sudo npm تثبيت pm2 @ latest -g
pm2 start index.js

الآن تم تكوين خادم العقدة الخاص بنا وتشغيله.

إعداد خادم جنكينز

خلق جنكينز القطرة

لنبدأ بإنشاء تطبيق DigitalOcean Droplet الذي سيخدم تطبيق Jenkins الخاص بنا. اتبع الإرشادات الموجودة أسفل قسم إنشاء العقدة Droplet أعلاه واختر "jenkins-app" كاسم مضيف. سوف ينتهي بك مع 2 قطرات:

الشكل 6

إنشاء مستخدم جديد

SSH في القطرة الجديدة كمستخدم الجذر ، وإنشاء مستخدم جديد ، ومنحه امتيازات sudo والتحول إلى المستخدم المضافة حديثا:

ssh root@JENKINS.SERVER.IP
adduser <اسم المستخدم>
usermod -a -G sudo 
سو - <اسم المستخدم>

يجب أن يكون جينكينز قادرًا على سحب التغييرات من الريبو التطبيق العقدة ، وبالتالي ، نحن بحاجة إلى تثبيت بوابة على سبيل المثال:

sudo-apt-get install git

تثبيت جنكينز

الحصول على جنكينز:

/ / أضف مفتاح المستودع إلى النظام
wget -q -O - https://pkg.jenkins.io/debian/jenkins-ci.org.key | sudo apt-key add -
// إلحاق عنوان مستودع حزمة دبيان بعبارة "echo deb" للخادم https://pkg.jenkins.io/debian-stable binary / | sudo tee /etc/apt/sources.list.d/ jenkins.list
//تحديث
sudo الحصول على التحديث

تثبيت جنكينز:

سودو الرابطة بين الحصول على تثبيت جنكينز

ابدأ جنكينز:

sudo systemctl حالة جنكينز

جنكينز تعمل على المنفذ 8080. هل تتذكر جدار الحماية؟ يتيح فتح المنفذ:

sudo ufw تسمح 8080

والآن يمكننا الوصول إلى Jenkins على المتصفح من خلال التنقل إلى:

HTTP: //JENKINS.SERVER.IP: 8080

تكوين جنكينز

عند الانتقال إلى صفحة جينكينز الرئيسية ، ربما تكون قد لاحظت خطوة إضافية عليك القيام بها. تحتاج إلى فتح جنكينز

الشكل 7

انسخ كلمة مرور جنكينز المستضافة على خادم جنكينز

sudo vim / var / lib / jenkins / أسرار / initialAdminPassword

الصق كلمة المرور في حقل النص. أنت مستعد لإعداد جنكينز. أولاً ، نود أن نضيف GitHub المساعد. اختر من القائمة اليسرى إدارة Jenkins وانتقل إلى إدارة المكونات الإضافية. في صفحة الإضافات ، حدد علامة التبويب المتاحة وابحث عن المكون الإضافي لـ GitHub ، وحدد مربع الاختيار الخاص به وانقر فوق الزر تنزيل الآن ثم التثبيت بعد إعادة التشغيل.

الشكل 8

بمجرد اكتمال التثبيت ، مرر الصفحة لأسفل واختر إعادة تشغيل جنكينز عند اكتمال التثبيت. سيؤدي هذا إلى إعادة تشغيل Jenkins وإكمال التثبيت.

تغيير كلمة مرور مسؤول جنكينز

أقترح في هذه المرحلة تغيير كلمة مرور مستخدم جنكينز. حدد Manage Jenkins من القائمة اليمنى وانقر فوق "إدارة المستخدمين". حدد المستخدم المسؤول واختر كلمة مرور جديدة. ستستخدم كلمة المرور الجديدة عند تسجيل الدخول إلى جنكينز في المستقبل.

إنشاء جنكينز الوظيفة

سننشئ مهمة Jenkins الخاصة بنا والتي ستكون مسؤولة عن سحب تغييرات التعليمات البرمجية من repo git-app repo ، وتثبيت التبعيات ، وتشغيل اختبار التكامل ونشر التطبيق في كل مرة يقوم فيها المطور بدفع التغييرات إلى فرع repo الرئيسي nodejs-app.

انقر فوق الزر "عنصر جديد" ، وقم بتسمية عقدة التطبيق ، ثم حدد خيار إنشاء مشروع برمجيات حرة وانقر فوق الزر "موافق".

تكوين جنكينز الوظيفة

إدارة كود المصدر: حدد زر الاختيار git وأدخل رابط github https إلى الريبو node-app:

https://github.com//node-app.git

إنشاء مشغلات: حدد الخيار GitHub hook trigger لاستطلاع GITScm. سيبدأ هذا العمل لدينا Jenkins في كل دفعة git على الفرع الرئيسي

Add Build Step: انقر فوق الزر Add Build Step وحدد خيار Execute Shell. أدخل الأوامر التالية في منطقة النص:

تثبيت npm
./script/test

في خطوة الإنشاء هذه ، سنقوم بتثبيت التبعيات ثم نقوم بتشغيل البرنامج النصي shell shell.

الشكل 9

أضف بوابة Webhook

سنقوم بإضافة Git Webhook لإعلام جينكينز في كل مرة يقوم فيها مطور بدفع كود جديد لإتقان الفرع.

انتقل إلى GitHub لتطبيق العقدة ، وانقر فوق علامة التبويب "الإعدادات" ، وحدد Webhooks من القائمة اليمنى وانقر فوق الزر "إضافة Webhooks". أدخل عنوان URL الخاص بـ Jenkins على الويب تحت عنوان Payload:

HTTP: //JENKINS.SERVER.IP: 8080 / جيثب-webhook /

وحدد فقط خيار "دفع الحدث". انقر فوق الزر "إضافة webhook".

الرقم 10

لنختبر ما لدينا حتى الآن. انتقل إلى مشروع تطبيق العقدة على جهازك وقم بتغيير الإصدار الموجود في package.json إلى 0.0.2. الالتزام ودفع هذا التغيير إلى جيثب. بعد الدفع ، انتقل إلى مهمة Jenkins الخاصة بك على المتصفح ولاحظ أن مهمة Jenkins قد بدأت وانتهت بنجاح.

نشر

آخر جزء من اللغز هو نشر تطبيق العقدة الخاص بنا في خادم تطبيقات العقدة عند انتهاء الاختبار.

مصادقة SSH

من أجل القيام بذلك ، سيحتاج Jenkins Server إلى ssh في خادم تطبيق العقدة واستنساخ الريبو وتثبيت التبعيات وإعادة تشغيل الخادم. يتيح إعداد وصول ssh إلى جنكينز أولاً.

عندما نقوم بتثبيت جينكينز ، فإنه يقوم تلقائيًا بإنشاء مستخدم جينكينز. SSH في خادم Jenkins الخاص بنا كمستخدم جذر:

ssh root@JENKINS.SERVER.IP

قم بالتبديل إلى مستخدم Jenkins:

سو جنكينز

إنشاء مفتاح SSH:

سه كجن ، ر

وحفظ المفتاح الذي تم إنشاؤه في /var/lib/ jenkins/.ssh/id_rsa

اطبع مفتاح SSH الذي أنشأته للتو:

القط ~ / .ssh / id_rsa.pub

ونسخ الإخراج إلى الحافظة الخاصة بك. نحن الآن على استعداد لوضع المفتاح العمومي على خادم التطبيق nodejs لاستكمال المصادقة بين خادم Jenkins وخادم تطبيق nodejs.

SSH في خادم التطبيق nodejs كجذر والتبديل إلى المستخدم الخاص بك:

ssh root@NODE.SERVER.IP
سو - <اسم المستخدم>

افتح الملف حيث يتم تخزين المفاتيح المخولة:

vim ~ / .ssh / Author_keys

وانسخ المفتاح العمومي لـ Jenkins الذي أنشأناه للتو في هذا الملف. احفظ بالضغط على زر esc على لوحة المفاتيح ، اكتب: x واضغط على enter.

تعيين الإذن الصحيح في المجلد .ssh:

chmod 700 ~ / .ssh
chmod 600 ~ / .ssh / *

قبل أن ننتقل إلى - يتيح اختبار إعداد SSH. إذا كانت الإعداد صحيحة ، فسنكون قادرين على SSH من JENKINS.SERVER.IP كمستخدم jenkins إلى @ NODE.SERVER.IP دون إدخال كلمة مرور

ssh root@JENKINS.SERVER.IP
سو جنكينز
ssh  @ NODE.SERVER.IP

نجاح!

النشر التلقائي

سنقوم بإنشاء نص برمجي آخر مسؤول عن النشر. قم بإنشاء ملف تحت برنامج نصي يسمى نشر وإضافة البرنامج النصي التالي:

#! / بن / ش
ssh ezderman@NODE.SERVER.IP << EOF
 مؤتمر نزع السلاح ~ / عقدة التطبيق
 بوابة سحب
 تثبيت npm - الإنتاج
 pm2 إعادة تشغيل جميع
 ىخرج
EOF

سيقوم هذا البرنامج النصي SSH بخادم العقدة وسحب التغييرات من GitHub وتثبيت التبعيات وإعادة تشغيل الخدمة.

اجعل ملف البرنامج النصي الجديد قابلاً للتنفيذ:

chmod + x النصي / نشر

قبل أن نلتزم بالتغييرات التي أجريناها ، يمكنك إضافة خطوة النشر إلى Jenkins Job:

الشكل 11

وحفظ.

لحظة الحقيقة

نحن على استعداد لاختبار كل شيء بنينا. انتقل إلى مشروع تطبيق nodejs وقم بتحرير ملف index.js للرد باستخدام "“ hey world ". لا تنسَ تغيير test / test.js الخاص بك لاختبار هذه السلسلة أيضًا.

الالتزام والدفع:

بوابة إضافة.
بوابة الالتزام - م "إضافة نص نشر"
بوابة دفع أصل الرئيسي

بعد أن تضغط ، يجب أن ترى Jenkins Job. عند الاكتمال ، سترى تغييراتك على http: //NODE.SERVER.IP: 3000

الشكل 12

ونحن فعلنا!