تحديث تبعيات المشاريع البرمجية بأمان وتلقائية باستخدام GitHub Actions و Renovate
في عالم تطوير البرمجيات سريع التطور، يُعد البقاء على اطلاع بأحدث التحديثات التقنية أمرًا بالغ الأهمية. لا يقتصر هذا على المطورين الذين يسعون لتطوير مهاراتهم فحسب، بل يمتد ليشمل المشاريع التي يعملون عليها ويصينونها. عند بدء مشروع جديد، غالبًا ما يتم إعداده بأحدث الإصدارات المستقرة من جميع المكتبات والأدوات. ومع مرور الوقت، ينمو المشروع، وتُضاف إليه ميزات ومكتبات جديدة، لكن إصدارات المكتبات والحزم الأساسية قد تظل كما هي، وغالبًا ما يتجاهل الفريق تحديثها. فلماذا قد تُحدّث شيئًا يعمل بشكل مثالي بالإصدارات الحالية؟

لماذا يجب عليك تحديث تبعيات مشروعك بانتظام؟
إن الحفاظ على تحديث تبعيات مشروعك ليس مجرد رفاهية، بل ضرورة حتمية لضمان استمرارية المشروع وأمانه وفعاليته. إليك أبرز الأسباب التي تدفعك لتبني هذه الممارسة:
- معالجة المشكلات والثغرات الأمنية: غالبًا ما تحتوي الإصدارات القديمة من المكتبات على أخطاء برمجية وثغرات أمنية معروفة. تحديث التبعيات يضمن حصولك على أحدث الإصلاحات الأمنية، مما يحمي مشروعك من الهجمات المحتملة.
- تحسين الأداء والكفاءة: تُقدم الإصدارات الجديدة تحسينات في الأداء، وتُقلل من استهلاك الموارد، وتُسرّع من عمليات المعالجة. هذا ينعكس إيجابًا على تجربة المستخدم وكفاءة التطبيق ككل.
- الوصول إلى الميزات الجديدة: يضيف المطورون باستمرار ميزات ووظائف جديدة إلى المكتبات. تحديث التبعيات يُمكّنك من الاستفادة من هذه الميزات، مما يُثري مشروعك ويُسهّل إضافة وظائف متقدمة.
- تحسين قابلية الصيانة: المشاريع ذات التبعيات القديمة يصعب صيانتها وتطويرها. التحديث المنتظم يُبقي قاعدة الكود نظيفة ومتوافقة مع أحدث الممارسات، مما يُسهّل على المطورين الجدد فهم المشروع والعمل عليه.
كل هذه التحسينات تُساهم بشكل مباشر في قابلية صيانة الكود والصحة العامة للمشروع. لقد عملنا جميعًا على مشاريع لم يتم تحديث تبعياتها أبدًا (أو نادرًا)، وكانت التجربة غالبًا ما تكون محبطة ومُكلفة. إذن، كيف نحافظ على تحديث مشاريعنا بفعالية وبدون عناء؟
في البداية، يمكنك تشغيل الأمر npm outdated لرؤية أحدث الإصدارات من الحزم التي تستخدمها حاليًا. بعد ذلك، يمكنك تشغيل npm update لتحديثها (مع العلم أنه لن يُحدّثها إلى الإصدارات الرئيسية major versions). لكن كيف يمكنك معرفة أي التحديثات ستُسبب مشكلات في المشروع وأيها لن يفعل؟ ومتى يجب عليك التحقق من التحديثات – يوميًا؟ أسبوعيًا؟ شهريًا؟
ماذا ستتعلم في هذا الدليل؟
لهذه الأسباب، تم إنشاء هذا الدليل: لتعلم كيفية استخدام GitHub Actions لتوفير طريقة آمنة لتحديث التبعيات تلقائيًا دون التسبب في فشل المشروع. ستتعلم في هذا الدليل كيفية استخدام تطبيق Renovate للتحقق من تحديثات التبعيات ثم إرسال طلبات سحب Pull Requests لتحديثها. هذا يُحرّرك من عناء التحقق اليدوي من التحديثات، مما يتيح لك التركيز على مهام أكثر أهمية.
الهدف من استخدام GitHub Actions هو إعداد سير عمل workflow وتشغيله مع كل طلب سحب Pull Request. سيتحقق هذا السير من أن البناء build والاختبارات tests تعمل بنجاح مع التبعيات المحدثة قبل دمجها في المشروع.
جدول المحتويات
- البدء
- إعداد سير عمل
GitHub Actions - إضافة تطبيق
Renovate - الخلاصة
- الموارد المفيدة
البدء: إعداد مشروع React أساسي
على الرغم من أن هذا النهج يمكن تطبيقه على أي مشروع، إلا أننا سنستخدم مشروع React تم إنشاؤه باستخدام Create React App. سيوفر لنا هذا مشروعًا أساسيًا جاهزًا للعمل عليه. بالمناسبة، إذا لم يكن لديك Node.js مثبتًا، يمكنك العثور على رابط التثبيت هنا. إذا كنت ترغب في الاطلاع على النتيجة النهائية قبل البدء، يمكنك ذلك من هنا.
لنبدأ بتشغيل الأوامر التالية في سطر الأوامر:
npx create-react-app my-app
cd my-app
npm start
إذا كنت تستخدم npm 5.1 أو إصدارًا أقدم، فلا يمكنك استخدام npx. بدلاً من ذلك، قم بتثبيت create-react-app عالميًا:
npm install -g create-react-app
ثم قم بتشغيل:
create-react-app my-app
إعداد سير عمل GitHub Actions
الآن سننتقل إلى تحديد سير عمل GitHub Actions Workflow في مستودعنا لأتمتة العملية. GitHub Actions هي ميزة من GitHub تساعدك على أتمتة سير عمل تطوير البرمجيات الخاص بك. يمكنها التعامل مع كل شيء بدءًا من المهام البسيطة وحتى إمكانيات التكامل المستمر Continuous Integration (CI) والنشر المستمر Continuous Deployment (CD) المخصصة في مستودعاتك.
في مجلد الجذر للمشروع، سنقوم بإنشاء مجلد جديد ونسميه .github. داخل هذا المجلد، سننشئ مجلدًا آخر باسم workflows. هكذا يجب أن يبدو هيكل مشروعك بعد هذه الخطوات:
📁 my-app
├── 📁 .github
│ └── 📁 workflows
├── ...
...
هنا سنقوم بإنشاء وإضافة سير العمل Workflows الخاص بنا. سير عمل GitHub Actions هي العمليات المؤتمتة للتكامل المستمر التي نريد تشغيلها في مشروعنا. تتكون سير العمل من مهام jobs تحتوي على مجموعة من الخطوات steps. لتوضيحها بطريقة أكثر وضوحًا، دعنا ننشئ سير عمل خاص بنا ونستعرضه خطوة بخطوة.
في دليل .github/workflows، أضف ملفًا بامتداد .yml أو .yaml وسمه main.yml. لقد اخترت هذا الاسم للحفاظ على البساطة، ولكن يمكنك إعطائه أي اسم آخر مثل build-test.yml أو continuous-integration-workflow.yml.
📁 my-app
├── 📁 .github
│ └── 📁 workflows
│ └── 📄 main.yml
├── ...
...
إليك كيف سيبدو سير العمل في النهاية في حال كنت ترغب فقط في نسخه وإضافته مباشرة قبل الشرح:
name: Build and Test
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
build_and_test:
runs-on: ubuntu-latest
strategy:
matrix:
node: [ 10, 12 ]
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: Install project
run: npm install
- name: Build the project
run: npm run build --if-present
- name: Run tests
run: npm test
شرح مكونات سير العمل
أول معلمة لسير العمل الخاص بنا ستكون اسمه name:
name: Build and Test
المعلمة الثانية هي المشغل trigger. يمكننا اختيار ما إذا كان سير العمل سيتم تشغيله بواسطة حدث مثل الدفع push أو طلب السحب pull request إلى فرع معين branch، أو يمكننا حتى جدولة مهمة cron لتشغيله تلقائيًا كل فترة زمنية محددة! في مشروعنا، سنرغب في تشغيله عند الدفع إلى الفرع الرئيسي master، وعندما يُقدم تطبيق Renovate طلب سحب Pull Request لتحديث تبعية:
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
بعد ذلك، نُعرّف المهام jobs. في هذا المثال، ستكون هناك مهمة واحدة فقط: بناء واختبار المشروع، واختيار الجهاز الافتراضي virtual machine الذي ستُشغل عليه المهمة:
jobs:
build_and_test:
runs-on: ubuntu-latest
الآن تأتي المصفوفة matrix حيث سنُكوّن مجموعة الإصدارات والأنظمة التي نريد تشغيل سير العمل عليها. في حالتنا، سنقوم بتشغيله على Node.js 10 و 12:
strategy:
matrix:
node-version: [ 10, 12 ]
أخيرًا، خطوات سير العمل Workflow's steps. أولاً، إجراء checkout وهو إجراء قياسي يجب أن تضمنه في سير عملك عندما تحتاج إلى نسخة من مستودعك لتشغيل سير العمل. ثم يمكنك تشغيل إجراءات وعمليات أخرى. في تطبيقنا، سنستخدم إجراء setup-node مع المصفوفة التي حددناها سابقًا. ثم سنضيف خطوات لتثبيت المشروع، وبنائه، وتشغيل الاختبارات:
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: Install project
run: npm install
- name: Build the project
run: npm run build --if-present
- name: Run tests
run: npm test
الآن، قم بإنشاء مستودع GitHub Repository للمشروع، وقم بتثبيت التغييرات المحلية التي أجريتها، وادفعها إليه. نصيحة سريعة: إذا كنت ترغب في إنشائه بشكل أسرع، انتقل إلى repo.new أو github.new. يمكنك استخدام gist.new للمقتطفات gists أيضًا! بمجرد دفع تغييراتك، سيتم تشغيل سير العمل. ثم ستتمكن من رؤية كيفية سيره في علامة التبويب Actions من مشروع GitHub.

إضافة تطبيق Renovate لأتمتة التحديثات
Renovate هو تطبيق مجاني، مفتوح المصدر، وقابل للتخصيص يساعدك على تحديث تبعيات مشاريعك البرمجية تلقائيًا عن طريق استقبال طلبات السحب pull requests. يُستخدم من قبل شركات برمجيات كبرى مثل Google و Mozilla و Uber، ويمكنك استخدامه على GitHub و GitLab و Bitbucket و Azure DevOps و Gitea.
سنضيف روبوتًا bot سيُقدم طلبات سحب pull requests إلى مستودعنا عندما تكون هناك تحديثات في تبعيات مشروعنا. الشيء الرائع، والهدف الأساسي من مشروعنا، هو أننا قمنا مسبقًا بتعريف سير عملنا workflow لتشغيل الاختبارات مع طلبات السحب. لذلك، عندما يُقدم Renovate طلب سحب، سنتحقق تلقائيًا مما إذا كانت التحديثات المقترحة ستُسبب مشكلات في المشروع أم لا قبل دمجها في الفرع الرئيسي master.
![]()
لإضافة Renovate إلى مشروعنا، يجب علينا تثبيت تطبيقه في مستودع المشروع. كن حذرًا عند اختيار المستودع الذي تريد إضافة Renovate إليه واختر المستودع الذي أنشأته سابقًا. إذا ارتكبت خطأً وأردت إعادة تكوينه، يمكنك القيام بذلك في علامة التبويب Applications ضمن Personal Settings من حسابك.
بعد بضع دقائق، سيتعين عليك قبول ودمج طلب السحب الخاص بالتهيئة onboarding Pull Request الذي ستتلقاه. بمجرد دمجه، تحتاج إلى تكوينه عن طريق تحديث ملف renovate.json في جذر المشروع. تذكر سحب التغييرات بعد دمج طلب السحب لكي يظهر الملف.
يمكنك استخدام التكوين الافتراضي حيث سيُقدم Renovate طلبات السحب كلما وجد تحديثات وينتظر منك دمجها:
{
"extends": [
"config:base"
]
}
أو يمكنك تكييفه مع متطلبات مشروعك مثل التكوين الذي يستخدمه Renovate نفسه. لتجنب أي مشكلات، ولتعلم المزيد عن الأداة، سنستخدم تكوينًا يضم بعضًا من ميزاتها الأكثر فائدة. إذا كنت تريد معرفة المزيد عن تكوينها، إليك الوثائق الخاصة بها. سيكون هذا هو ملف renovate.json الخاص بنا. ألقِ نظرة عليه، وسأشرحه لاحقًا.
{
"extends": [
"config:base"
],
"packageRules": [
{
"updateTypes": [
"minor",
"patch"
],
"automerge": true
}
],
"timezone": "Europe/Madrid",
"schedule": [
"after 10pm every weekday",
"before 5am every weekday",
"every weekend"
]
}
شرح ملف التكوين renovate.json
في الجزء الأول، نخبر Renovate أن تكويننا سيكون امتدادًا للتكوين الافتراضي:
{
"extends": [
"config:base"
],
ثم لدينا packageRules. بعد بضعة أشهر من استخدامه، أدركت أن مراجعة طلبات السحب pull requests (من وقت لآخر) وقبولها إذا اجتازت الاختبارات كان مضيعة كبيرة للوقت. لهذا السبب، تم تعيين automerge على true، بحيث يدمج Renovate طلب السحب تلقائيًا إذا اجتاز سير العمل workflow بنجاح. لتقييد حرية Renovate قليلاً، نحدد أنه يمكنه فقط إجراء automerge عندما يكون التحديث من نوع minor أو patch. بهذه الطريقة، إذا كان التحديث من نوع major أو أي نوع آخر، سنكون نحن من يتحقق مما إذا كان يجب إضافة هذا التحديث أم لا. هنا يمكنك العثور على مزيد من المعلومات حول أنواع التحديثات المتاحة.
"packageRules": [
{
"updateTypes": [
"minor",
"patch"
],
"automerge": true
}
],
أخيرًا، لدينا جدول المواعيد time schedule. إذا كنت تعمل بمفردك أو في فريق في ساعات معينة، فمن الجيد أن تتم التحديثات عندما لا تكون تعمل لتجنب التشتت غير الضروري. نختار منطقتنا الزمنية timezone ونضيف جدولًا مخصصًا لها. يمكنك العثور على أسماء المناطق الزمنية الصالحة هنا.
"timezone": "Europe/Madrid",
"schedule": [
"after 10pm every weekday",
"before 5am every weekday",
"every weekend"
],
على أي حال، إذا كنت لا تهتم بالوقت الذي سيتم فيه تقديم طلبات السحب، أو كان الأشخاص الذين يساهمون في الكود موجودين في مناطق زمنية مختلفة، فيمكنك إزالة هذا الجزء.
بمجرد تحديث التكوين، ندفع التغييرات إلى GitHub لجعل تطبيق Renovate يتكيف مع التكوين الجديد. الآن لديك أخيرًا تبعيات المشروع محدثة بأمان دون الحاجة إلى التحقق منها يدويًا. إليك المشروع الناتج بعد اتباع جميع الخطوات المذكورة أعلاه. تذكر أنه إذا أضفت جزء جدول المواعيد، فلن يتم دمج طلب السحب تلقائيًا حتى يمتثل لهذا التكوين.
الخلاصة التقنية
تُقدم هذه الاستراتيجية المتكاملة، التي تجمع بين قوة GitHub Actions ومرونة Renovate، حلًا جذريًا لمشكلة تحديث تبعيات المشاريع. فبدلاً من الاعتماد على المراجعات اليدوية المُستهلكة للوقت والمعرضة للخطأ، يُمكن للمطورين الآن أتمتة هذه العملية بالكامل، مع ضمان سلامة المشروع عبر اختبارات التكامل المستمر. إن القدرة على تحديد قواعد الدمج التلقائي لأنواع معينة من التحديثات (مثل minor و patch) مع الاحتفاظ بالتحكم البشري في التحديثات الرئيسية major، تُعزز من كفاءة سير العمل دون التضحية بالاستقرار. هذا النهج لا يُحسن فقط من أمان المشروع وأدائه، بل يُسهم أيضًا في بناء ثقافة تطوير أكثر حداثة وفعالية، مما يُمكن الفرق من التركيز على الابتكار بدلاً من المهام الروتينية.
الموارد المفيدة
إليك مجموعة من الروابط والموارد التي أعتقد أنها يمكن أن تكون مفيدة لتحسين وتعلم المزيد عن GitHub Actions والتطبيقات:
- المشروع التعليمي. – المشروع الناتج عن هذا الدليل.
- GitHub Marketplace. – المكان للعثور على جميع
GitHub Actionsوالتطبيقات. - GitHub Actions Workflow Configuration – الوثائق الكاملة حول كيفية إعداد سير عمل على
GitHub Actions. - Renovate GitHub app – الصفحة الرئيسية لتطبيق
RenovateفيGitHub Marketplace. - GitHub Actions project Workflow. – سير العمل المستخدم في هذا الدليل.
- Renovate App’s configuration file. – ملف التكوين المخصص لتطبيق
Renovateمن الدليل. - Up to Date React Template. – مشروع شخصي يستخدم النهج الموضح في هذا الدليل.