كيف ساهمت في مشروع مفتوح المصدر كبير من دون كتابة أي سطر برمجي
مقدمة: المساهمة التقنية لا تعني دائماً كتابة الشيفرة
يظن كثيرون أن المساهمة في المشاريع مفتوحة المصدر تقتصر على كتابة الميزات الجديدة أو إصلاح الأخطاء البرمجية. لكن الواقع أوسع من ذلك بكثير. فقد يمكن إحداث أثر واضح داخل مشروع كبير عبر تحسين الاختبارات، أو تبسيط بيئة التطوير، أو تسهيل آلية البناء والتكامل المستمر. وهذا بالضبط ما حدث عند المساهمة في مشروع Phoenix Framework الشهير، من دون كتابة أي شيفرة بلغة Elixir، ومن دون حتى تعديل الوثائق.
التركيز كان على تحسين عملية البناء والاختبار، وهي خطوة عملية ومفيدة لأي مشروع يعتمد على تعدد البيئات والإصدارات. والأهم أن هذه الفكرة لا تخص Phoenix وحده، بل يمكن تطبيقها على عدد كبير من المشاريع التقنية.

ما هو إطار Phoenix Framework؟
يُعد Phoenix إطار عمل ويب متقدماً يتميز بقدرته على بناء تطبيقات تفاعلية غنية من دون الحاجة إلى كتابة شيفرة جانب العميل بشكل مكثف. ومن أبرز مزاياه ميزة LiveView، التي تتيح إرسال تحديثات مباشرة من الخادم إلى المتصفح لتحديث واجهة HTML لحظياً.
بفضل هذه المقاربة، يصبح من الممكن إنشاء صفحات تعرض بيانات آنية، مثل أحدث التغريدات حول موضوع محدد، بطريقة مباشرة وفعالة.
مثال مبسط على LiveView
defmodule TimelineLive do
use Phoenix.LiveView
def render(assigns) do
render("timeline.html", assigns)
end
def mount(_, socket) do
Twitter.subscribe("elixirphoenix")
{:ok, assign(socket, :tweets, [])}
end
def handle_info({:new, tweet}, socket) do
{:noreply,
update(socket, :tweets, fn tweets ->
Enum.take([tweet | tweets], 10)
end)
}
end
end

الإطار مبني بلغة Elixir التي طورها José Valim. وقد تبدو في شكلها قريبة من Ruby، لكنها مختلفة عنها في السلوك والبنية الداخلية. كما تعمل Elixir فوق آلة Erlang VM، وهي بيئة معروفة بالاعتمادية العالية، وتُستخدم في مشاريع وشركات بارزة مثل Discord وHeroku.
التحدي الحقيقي: كيف يمكن إعادة إنتاج بيئة البناء والاختبار؟
يعتمد مشروع Phoenix Framework على GitHub Actions لتشغيل خط البناء والاختبارات. وكحال المشاريع الناضجة، فهو لا يكتفي باختبارات الوحدات Unit Tests، بل يستخدم أيضاً اختبارات تكامل Integration Tests للتأكد من أن التعديلات الجديدة لا تؤثر سلباً في التكامل مع قواعد البيانات المدعومة.
يعتمد Phoenix على طبقة ORM للتعامل مع أكثر من قاعدة بيانات، لذلك كان من الضروري اختبار كل تغيير على عدة بيئات مختلفة.
العوامل التي يجب اختبارها مع كل تعديل
- قواعد البيانات:
PostgresوMySQLوMSSQL. - إصدارات
Elixir: الإصدار الحالي والإصدار السابق. - إصدارات
OTP: الإصدار الحالي والإصدار السابق.
هذا يعني أن كل مساهمة يجب أن تمر بعدة تركيبات من البيئات، وهو أمر يسهل تعريفه داخل GitHub Actions، لكنه يصبح أقل راحة عند تشغيله محلياً على جهاز المطور.
ولو طُلب من كل مساهم تثبيت هذه الإصدارات والخدمات يدوياً، فإن عائق الدخول إلى المشروع سيرتفع كثيراً، وسيضطر الجميع إلى الاعتماد على رفع التعديلات إلى GitHub وانتظار نتيجة الاختبارات. وهذه آلية تُبطئ التطوير بشكل واضح.
الفكرة الأساسية: توحيد تشغيل الاختبارات محلياً وداخل CI
الحل لم يكن في إضافة اختبارات جديدة، بل في نقل منطق البناء والاختبار إلى صيغة قابلة للتشغيل في أي مكان، سواء على جهاز المطور أو داخل بيئة التكامل المستمر. وهنا برز دور أداة Earthly، وهي أداة بناء مفتوحة المصدر تساعد على إنشاء خطوات قابلة لإعادة الإنتاج باستخدام الحاويات Containers.
الهدف كان بسيطاً: كتابة وصف موحد لآلية الاختبار، ثم استخدام هذا الوصف نفسه محلياً وداخل GitHub Actions، بدلاً من تكرار المنطق في أكثر من مكان.
تشغيل اختبارات Phoenix محلياً باستخدام Earthly
الحل العملي تمثل في إنشاء ملف Earthfile يضم أهدافاً Targets متعددة، مثل هدف للإعداد وهدف لاختبارات التكامل.
setup:
ARG ELIXIR=1.10.4
ARG OTP=23.0.3
# Pull a Docker Image to Run Build Inside Of
FROM hexpm/elixir:$ELIXIR-erlang-$OTP-alpine-3.12.0
...
integration-test:
FROM +setup
COPY . .
# Pull In Dependencies
RUN mix deps.get
# Start Up Service Dependencies
WITH DOCKER --compose docker-compose.yml
# Run Tests
RUN mix test --include database
# Stop Service Dependencies
END
في هذا المثال، يتم تشغيل الاختبارات داخل حاوية Docker تحتوي على إصدار Elixir وإصدار OTP المطلوبين. وتكمن الفائدة هنا في أن بيئة التشغيل تصبح ثابتة وقابلة لإعادة الإنتاج، بصرف النظر عن نظام المطور المحلي.
قبل تنفيذ الأمر mix test --include database، يتم تشغيل الخدمات المساندة من خلال Docker Compose.
WITH DOCKER --compose docker-compose.yml
RUN mix test --include database
END
ملف docker-compose.yml الخاص بقواعد البيانات
version: '3'
services:
postgres:
image: postgres
ports:
- "5432:5432"
environment:
POSTGRES_PASSWORD: postgres
mysql:
image: mysql
ports:
- "3306:3306"
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
mssql:
image: mcr.microsoft.com/mssql/server:2019-latest
environment:
ACCEPT_EULA: Y
SA_PASSWORD: some!Password
ports:
- "1433:1433"
هذا الملف يشغّل قواعد البيانات الثلاث المطلوبة لاختبارات التكامل، ما يوفّر بيئة قريبة جداً من البيئة الفعلية التي يحتاجها المشروع.
طريقة تشغيل الاختبارات من الطرفية
> earthly -P +integration-test
وإذا كانت الحاجة لاختبار إصدار مختلف من Elixir أو OTP، فيمكن تمريرها كوسائط بناء:
> earthly -P --build-arg ELIXIR=1.11.0 --build-arg OTP=23.1.1 +integration-test
صحيح أن هذا ليس الحل الوحيد الممكن، إذ يمكن الاعتماد أيضاً على Makefile مع ملفات Dockerfile، لكن الفكرة الجوهرية تبقى واحدة: يجب إخراج منطق البناء من تنسيق خاص بمنصة واحدة، وجعله قابلاً للتشغيل في أي بيئة.
تشغيل الآلية نفسها داخل GitHub Actions
بعد توحيد منطق البناء والاختبار في Earthfile، أصبح استخدامه داخل GitHub Actions أمراً مباشراً. كل ما يلزم هو تعديل ملف YAML ليستخدم Earthly بدلاً من كتابة منطق الاختبارات بشكل منفصل.
integration-test-elixir:
runs-on: ubuntu-latest
env:
FORCE_COLOR: 1
strategy:
fail-fast: false
matrix:
include:
- elixir: 1.11.1
otp: 21.3.8.18
- elixir: 1.11.1
otp: 23.1.1
steps:
- uses: actions/checkout@v2
- name: Download released earth
run: "sudo /bin/sh -c 'wget https://github.com/earthly/earthly/releases/download/v0.4.1/earthly-linux-amd64 -O /usr/local/bin/earthly && chmod +x /usr/local/bin/earthly'"
- name: Execute tests
run: earthly -P --build-arg ELIXIR=${{ matrix.elixir }} --build-arg OTP=${{ matrix.otp }} +integration-test
بهذه الطريقة، أصبح المشروع يستخدم الإجراء نفسه محلياً وداخل نظام التكامل المستمر، ما يقلل التباين بين البيئات ويحد من المشاكل الناتجة عن اختلاف الإعدادات.
الفوائد العملية لهذا النهج في المشاريع مفتوحة المصدر
1. تسهيل مساهمة المطورين الجدد
حين يصبح تشغيل الاختبارات محلياً ممكناً بأمر واحد تقريباً، تقل الحواجز أمام المساهمين الجدد، ولا يضطرون إلى قضاء ساعات طويلة في ضبط البيئة.
2. تقليل الاعتماد الكامل على GitHub Actions
بدلاً من إرسال كل تعديل إلى المستودع فقط لمعرفة ما إذا كان سينجح، يستطيع المطور التحقق محلياً أولاً، ما يوفر الوقت ويزيد سرعة التكرار.
3. توحيد منطق البناء
وجود مصدر واحد لتعريف عملية البناء يخفف التكرار، ويجعل صيانة خط الاختبارات أسهل على المدى الطويل.
4. تحسين قابلية إعادة الإنتاج
عندما تعمل الاختبارات داخل حاويات محددة الإصدارات، يصبح من الأسهل إعادة المشكلات وتشخيصها بدقة.
النتيجة النهائية: مساهمة مؤثرة من خارج الشيفرة التطبيقية
بعد التعاون مع فريق Phoenix، تم اعتماد التغيير، وأصبح لدى المشروع أسلوب أوضح وأسهل لتجربة خط البناء محلياً وتطويره. وهذه النتيجة تؤكد أن القيمة في المشاريع مفتوحة المصدر لا تأتي فقط من كتابة الميزات، بل قد تأتي أيضاً من تحسين البنية المحيطة بالتطوير.
إن تحسين تجربة الاختبار، وتقليل التعقيد، وتسهيل مساهمة الآخرين، كلها أعمال تقنية ذات أثر كبير، وغالباً ما تكون أكثر أهمية من إضافة سطر برمجي جديد.
دروس مهمة لأي مساهم في البرمجيات مفتوحة المصدر
- لا تحصر مساهمتك في كتابة الكود فقط.
- ابحث عن نقاط الألم في عملية البناء أو الاختبار أو الإعداد.
- اجعل بيئة التطوير سهلة ومفهومة وقابلة للتكرار.
- كلما قلّ الفرق بين البيئة المحلية وبيئة
CI، زادت موثوقية النتائج. - المساهمة التي توفّر وقت الفريق قد تكون من أكثر المساهمات قيمة.
الخلاصة التقنية
من منظور هندسة البرمجيات، يُعد توحيد مسار البناء والاختبار بين البيئة المحلية وبيئة CI خطوة ذكية ترفع موثوقية المشروع وتسرّع دورة التطوير. استخدام أدوات مثل Earthly أو أي بديل مشابه لا يتعلق بالأداة نفسها بقدر ما يتعلق بالمبدأ: بناء عملية قابلة لإعادة الإنتاج، سهلة للمطور، ومناسبة للمشروع على المدى البعيد. وهذه النوعية من المساهمات غالباً ما تصنع فرقاً حقيقياً في نضج المشاريع مفتوحة المصدر.