لماذا يستحق مشروع Rust الخاص بك CI/CD حقيقي؟
\n\nتخيل: أنت تكتب بلغة Rust، المترجم هو أفضل صديق لك، مدقق الاقتراض (borrow checker) لا يسمح لك بالاسترخاء، والكود يعمل بسرعة البرق. ولكن بمجرد أن تصل إلى مرحلة النشر، ينتهي السحر. تشغيل الاختبارات يدويًا، البناء على الجهاز المحلي، رفع الملف الثنائي إلى الخادم عبر SCP - هذا طريق إلى لا شيء. خاصة عندما يكبر المشروع ويظهر مطور ثانٍ في الفريق.
\n\nCI/CD (التكامل المستمر / النشر المستمر) ليست مجرد كلمة طنانة. إنه نظام يتولى المهام الروتينية: تشغيل الاختبارات، التحقق من نمط الكود، بناء نسخة الإصدار وإرسالها إلى حيث يجب أن تعمل. بالنسبة لـ Rust، مع تركيزها على الموثوقية والأداء، فإن أتمتة البناء هي امتداد طبيعي لفلسفة اللغة.
\n\nفي هذه المقالة، سنقوم بإعداد خط أنابيب CI/CD لتطبيق Rust من الصفر باستخدام GitHub Actions. ستتعلم كيفية تنظيم الاختبار، التحليل البرمجي، بناء الملفات الثنائية لمنصات مختلفة والنشر. كل ذلك مع أمثلة كود حقيقية يمكنك نسخها إلى مشروعك.
\n\nماذا سنقوم بأتمتته؟
\n\nقبل كتابة الكود، دعنا نحدد أهدافنا. سيقوم خط الأنابيب الخاص بنا بأربعة أشياء:
\n\n- \n
- التحليل البرمجي والتنسيق - لضمان مطابقة الكود لمعايير Rust وعدم احتوائه على أخطاء نموذجية. \n
- الاختبار - تشغيل جميع اختبارات الوحدة واختبارات التكامل إن وجدت. \n
- بناء الملف الثنائي - ترجمة نسخة محسنة (release). \n
- النشر - تحميل القطعة المُنشأة إلى الخادم أو إلى إصدارات GitHub. \n
كل هذا سيحدث تلقائيًا مع كل دفع إلى الفرع main أو عند إنشاء طلب سحب (pull request). يبدو كالسحر؟ في الواقع، إنها مجرد ملفات YAML وبضع أوامر Cargo.
الخطوة 1: إعداد المشروع
\n\nعلى سبيل المثال، سنأخذ خادم ويب بسيط باستخدام Actix-web. لكن خط الأنابيب عالمي: يناسب أي مشروع Rust، سواء كان أداة CLI، مكتبة أو خدمة مصغرة.
\n\nلننشئ مشروعًا جديدًا:
\n\ncargo new rust-ci-cd-demo --bin\ncd rust-ci-cd-demo\n\nأضف التبعيات في Cargo.toml:
[dependencies]\nactix-web = "4"\nserde = { version = "1", features = ["derive"] }\n\nوكود بسيط في src/main.rs:
use actix_web::{get, App, HttpResponse, HttpServer, Responder};\n\n#[get("/")]\nasync fn hello() -> impl Responder {\n HttpResponse::Ok().body("Hello from Rust CI/CD!")\n}\n\n#[actix_web::main]\nasync fn main() -> std::io::Result<()> {\n HttpServer::new(|| {\n App::new().service(hello)\n })\n .bind(("0.0.0.0", 8080))?\n .run()\n .await\n}\n\nأضف اختبارًا بسيطًا في src/main.rs (في أسفل الملف):
#[cfg(test)]\nmod tests {\n use actix_web::{test, App, web};\n use crate::hello;\n\n #[actix_web::test]\n async fn test_hello_endpoint() {\n let app = test::init_service(App::new().service(hello)).await;\n let req = test::TestRequest::get().uri("/").to_request();\n let resp = test::call_service(&app, req).await;\n assert!(resp.status().is_success());\n }\n}\n\nكل شيء جاهز. الآن الجزء الممتع - إعداد CI/CD.
\n\nالخطوة 2: إنشاء سير عمل GitHub Actions
\n\nGitHub Actions هي أداة CI/CD مدمجة في GitHub. تعمل بناءً على ملفات YAML الموجودة في دليل .github/workflows/. لننشئه:
mkdir -p .github/workflows\ntouch .github/workflows/ci.yml\n\nافتح ci.yml وابدأ في كتابة خط الأنابيب. سنسميه "Rust CI/CD Pipeline".
المشغل الأساسي والبيئة
\n\nname: Rust CI/CD Pipeline\n\non:\n push:\n branches: [ main ]\n pull_request:\n branches: [ main ]\n\nenv:\n CARGO_TERM_CO