اتوماتیک گیت بای سکت یا چگونه با دو نیم کردن اتوماتیک از سکته جلوگیری کنیم

وقتی پروژه، محصول و تیم ها رشد می‌کنند، به همون اندازه پیدا کردن مشکلات و خطاهای کدها سخت تر میشه. تا جایی که بعضا دیده شده باگ هایی سهمگین موجب حملات قلبی عروقی سازمان‌یافته به مسئولین سالم نگه‌داشتن پروژه شده است. احتمالا چیزی نزدیک به همه تیم هایی که می‌شود ارزش سر آنها را بر تنشان سنجید، از مکانیزم های کنترلی، تست های فراوان، CI و … استفاده میکنند و کمتر با این مشکلات مواجه می‌شوند. امیدوارم برای شما پیش نیاد. این مقاله یک بحث فنی در مورد گیت است و در مورد یکی از امکاناتش برای یافتن کامیت مشکل دار در بین انبوهی از کامیت ها. git bisect

تصور کنین یک merge عظیم داشتید و بعد از صدها کامیتِ اعضای مختلف تیم، بیلد شما Fail بشه.

(خوش بینانه اگه از CI استفاده میکنید فکر میکنم نمیذارید کار به اینجا برسه و واقعا پروسه کاری شما continuos هست. اصولا تو یه تیم منظم که دائم چند بار در روز پوش و مرج میکنن خیلی این اتفاق نادره ولی همیشه همه چیز منظم پیش نمیره. این بحث که در شرایط عادی و آروم این اتفاق نمیفته و نباید بیفته کاملا درسته ولی دونستن این روش ممکنه یک روز نجاتتون بده)

ممکنه پیدا کردن کامیت با بررسی تک تک اون ها از بالا(!) اولین راهی باشه که به ذهن شما برسه. این یک سرچ خطیه و احتمالا میدونید هزینه یک سرچ خطی چقدر بالاست خصوصا توسط یک انسان که باید یک باگ رو پیدا کنه. اگه تو علوم کامپیوتر و الگوریتم دستی داشته باشید باید حدس زده باشید که راه حل یک سرچ باینریه.

حتما میدونید که سرچ باینری تو یه مجموعه با هر بار نصف کردن مجموعه و مقایسه جستجو رو محدود تر میکنه تا اینکه با چند پرش به نقطه مورد نظر برسه. چقدر خوب. شما به جای بررسی ۲۰۰ تا کامیت اگه اون ها رو باینری بگردید میتونید با مثلا هفت هشت پرش کامیت مورد نظرتون رو پیدا کنید. شما واقعا تو این حالت نمیدونید کامیت مشکل دار سَرِ هیستوریه یا تهش.

خب این ایده قبلا به فکر توسعه دهنده های گیت رسیده و ابزاری رو برای گشتن لابلای کامیت ها توسعه دادند به نام git bisect که کارش دقیقا همینه. ساده ترین نوع استفاده از این ابزار به صورت دستی به ترتیب زیره.

گیت bisect رو شروع کنید

# git bisect start

یه revision بد (خراب، شکسته، معیوب، باگی، گیت بهش میگه بد) معرفی کنید. مثلا HEAD

# git bisect bad {your bad revision}

یک revision سالم معرفی کنید (مثلا آخرین کامیتی که تو مستر قبل از مرج وجود داشت یا تگ ریلیز قبلی)

# git bisect good {your good revision}

حلقه bisect شروع میشه. حالا گیت میره به یک کامیت که از طریق باینری سرچ نوبتش شده باشه. شما میتونید اینجا اون کامیت رو تست و بیلد کنید ببینید تا اینجای اوضاع چطوره. بعدش به گیت بگید که مشکل هنوز وجود داره یا نه. با این کامند ها

# git bisect good
# git bisect bad

گیت مجددا تو بازه محدودتری سرچ میکنه و با راهنمایی شما کامیت مورد دار رو پیدا میکنه و نشونتون میده! اینجا با یه git show {commit ref} شما اون کامیت رو بررسی میکنین و مشکل رو حل میکنین. به همین سادگی و مجیکالی!

خب اینجا اگه کد های شما چیز قابل ارائه تو کنسول باشه مثلا خروجی یه build یا unit test میشه این فرآیند رو automate کرد. امیدوارم تست هاتون پوشش (coverage) قابل اتکایی داشته باشن. اصولا bisect نیاز به یه کاوریج خیلی خوب داره.

سکته یاب دو نیم کننده اتوماتیک

برای اتومِیت کردن این فرایند شما به یک اسکریپت احتیاج دارید که بیلد و تست شما رو انجام بده.

برای شرح ساده ترین حالت فرض کنید من با node.js یک اپلیکیشن نوشتم که با استفاده از npm و این کامند اون رو تست می‌کنم:

npm test

و تسک رانر npm مثلا برای من تست های mocha رو اجرا میکنه و خروجی اون رو تو ترمینال نشون میده. یه مشت خروجی که اگه توش کلمه Failed وجود داشته باشه یعنی تست ناموفق بود و اگه نه هم که تست موفقه. این اسکریپت یه حالت خیلی سادست. بعد از اون شما باید با Shell exit code ها آشنا باشید که بتونید از اون ها استفاده کنید. ساده ترین حالت اون exit کد 0 هست که به معنی موفقیت اسکریپت بیلد یا تست شماست و هر کد دیگه ای نشون دهنده ی خطا. من با گِرِپ کردن خروجی npm test خودم و گشتن دنبال کلمه fail به اسکریپت میفهمونم که تست موفق بوده یا نه. شما میتونید از هر مکانیزم و روشی برای این کار استفاده کنید. کد نمونه چیزی شبیه اینه:

‍‍‍‍‍‍#!/usr/bin/env bash 

# Build and grep for failure output. Replace with your own command. 
npm test 2>&1 | grep 'failed' 

# Retrieve the exit code of the grep. 
if [ "$?" -eq "0" ]; then 
  #echo "Fail found." 
  exit 1 
else 
  #echo "Fail not found." 
  exit 0 
fi 

بعد از نوشتن لاجیک تست خودتون، از این کامند استفاده کنید:

  # git bisect start {bad revision} {good revision}
  # git bisect run {path to your script}

گیت هر بار اسکریپت شما رو ران میکنه و با توجه به اون نتیجه براتون کامیت مشکل دار رو پیدا می‌کنه.

احتمالا راه های ساده تری برای استفاده از git bisect تو چرخه CI خودتون وجود داره. اگه فکر میکنید چیزی نیازه در تکمیل این متن یا در ادامه منتشر بشه، حتما برای ما PR بفرستید!