دستورات ورک‌فلو گیت هاب اکشنز (GitHub Actions Workflow Commands) مجموعه‌ای از پیام‌های ساختاریافته‌اند که از داخل گام‌های یک ورک‌فلو به رانر (Runner) ارسال می‌شوند و به آن می‌گویند چه اقدامی انجام دهد؛ از ثبت خطا و هشدار تا ماسک کردن اطلاعات حساس، گروه‌بندی لاگ‌ها و انتقال داده بین گام‌ها. در نگاه اول، این دستورات تنها ابزارهای گزارش‌گیری به‌نظر می‌رسند؛ اما در عمل، لایه‌ی ارتباطی میان اسکریپت شما و محیط اجرای گیت هاب هستند و تسلط بر آن‌ها، مرز میان یک ورک‌فلوی معمولی و یک خط لوله‌ی حرفه‌ای را ترسیم می‌کند. اگر با مبانی اکشنز آشنا نیستید، مطالعه‌ی راهنمای GitHub Actions نقطه‌ی شروع مناسبی است. در این نوشتار، از نحو Toolkit Commands و Environment Files تا ماسک‌سازی داده، مدیریت وضعیت و اشتباهات رایج، مسیر کامل را با تمرکز بر مهندسی و کاربردهای واقعی ترسیم می‌کنم.

هر ورک‌فلوی گیت هاب اکشنز، در لایه‌ی زیرین، یک مکالمه است میان اسکریپت شما و رانر. دستورات ورک‌فلو، واژگان این مکالمه هستند. اگر این واژگان را نشناسید، پیام‌های شما ممکن است نادیده گرفته شوند، اطلاعات حساس لو برود یا وضعیت بین گام‌ها از بین برود. در این نوشتار، این واژگان را از پایه تا کاربردهای پیشرفته بررسی می‌کنم.

دستورات ورک‌فلو چیستند؟

دستورات ورک‌فلو در گیت هاب اکشنز، پیام‌های متنی خاصی هستند که از طریق خروجی استاندارد (stdout) یا فایل‌های محیطی به رانر ارسال می‌شوند. رانر این پیام‌ها را تفسیر می‌کند و بر پایه‌ی آن‌ها، اقدامات مشخصی انجام می‌دهد. این دستورات به دو دسته‌ی اصلی تقسیم می‌شوند:

  • Workflow Commands (سنت کلاسیک): پیام‌هایی با نحو ::command:: که در stdout چاپ می‌شوند.
  • Environment Files (رویکرد نوین): فایل‌های خاصی که رانر در اختیار اسکریپت قرار می‌دهد و اسکریپت با نوشتن در آن‌ها، مقادیر را به رانر منتقل می‌کند.

در طول زمان، گیت هاب برخی از Workflow Commands کلاسیک مانند ::set-output:: و ::save-state:: را منسوخ کرده و به‌جای آن‌ها، Environment Files را توصیه کرده است. با این حال، فهم هر دو رویکرد ضروری است؛ چون بسیاری از ورک‌فلوهای موجود هنوز از نحو کلاسیک استفاده می‌کنند و ابزارهای قدیمی نیز بر همان پایه ساخته شده‌اند.

مفهوم Workflow Command در ادبیات اکشنز، بخشی از اکوسیستم Toolkit است که توسط گیت هاب برای تعامل بین Actionها و رانر توسعه یافته است. همین اکوسیستم، امکان ساخت Actionهای سفارشی را در زبان‌های مختلف فراهم می‌کند. برای مطالعه‌ی بیشتر در این حوزه، راهنمای Pull Request و CI/CD برای پروژه‌های وردپرسی منابع کاربردی محسوب می‌شوند.

Toolkit Commands و نحو ارسال

Toolkit Commands، نحو استانداردی برای ارسال دستورات به رانر هستند. ساختار کلی این دستورات به این شکل است:

::command parameter1=value1,parameter2=value2::message

سه بخش اصلی این ساختار:

  1. نام دستور: پس از دو نقطه‌ی ابتدایی می‌آید و مشخص می‌کند رانر چه اقدامی انجام دهد.
  2. پارامترها: مقادیر اختیاری که رفتار دستور را تنظیم می‌کنند و با کاما جدا می‌شوند.
  3. پیام: متن اصلی که پس از :: دوم قرار می‌گیرد و توسط دستور پردازش می‌شود.

برای مثال، دستور زیر یک خطا را گزارش می‌دهد:

::error file=app.js,line=10,col=5::Undefined variable

سه نکته‌ی مهم در نحو این دستورات:

  • پارامترها با کاما جدا می‌شوند و هر پارامتر به شکل name=value است.
  • مقادیر پیام می‌توانند شامل کاراکترهای ویژه باشند، اما برخی کاراکترها مانند %، و باید با کدهای escape جایگزین شوند.
  • پیام‌ها در لاگ ورک‌فلو نمایش داده می‌شوند؛ بنابراین نباید اطلاعات حساس را در آن‌ها قرار داد.
هر دستور ورک‌فلو، یک پیام است؛ اگر رانر آن را نشناسد، یا نادیده گرفته می‌شود یا به خطا منجر می‌گردد.

Workflow Commands کلاسیک

در رویکرد کلاسیک، مجموعه‌ای از دستورات برای کاربردهای مختلف وجود دارد. این دستورات را می‌توان در سه دسته‌ی اصلی جای داد:

دستورات گزارش‌گیری

  • ::error:: گزارش خطا در ورک‌فلو. متن پیام در بخش خطاها نمایش داده می‌شود و می‌تواند فایل و خط را نیز مشخص کند.
  • ::warning:: گزارش هشدار که ورک‌فلو را متوقف نمی‌کند اما توجه را جلب می‌نماید.
  • ::notice:: گزارش یک پیام اطلاعی که در بخش اعلان‌ها نمایش داده می‌شود.
  • ::debug:: ارسال پیام دیباگ که تنها در صورت فعال بودن دیباگ نمایش داده می‌شود.

دستورات کنترل لاگ

  • ::group:: آغاز یک گروه لاگ که خطوط بعدی را در یک بخش تاشو جمع می‌کند.
  • ::endgroup:: بستن گروه لاگ.
  • ::add-mask:: ماسک کردن یک مقدار در لاگ‌ها، به‌طوری که در نمایش‌ها با *** جایگزین شود.
  • ::stop-commands:: توقف موقت پردازش دستورات، برای مواقعی که می‌خواهید متن خام را بدون تفسیر به‌عنوان دستور چاپ کنید.

دستورات مدیریت وضعیت و خروجی

  • ::save-state:: ذخیره‌ی وضعیت در طول اجرای Action (اکنون منسوخ).
  • ::set-output:: تنظیم مقدار خروجی برای استفاده در گام‌های بعدی (اکنون منسوخ و جایگزین آن فایل محیطی است).
  • ::set-env:: تنظیم متغیر محیطی (اکنون منسوخ و جایگزین آن فایل محیطی است).
  • ::add-path:: افزودن یک مسیر به PATH (اکنون منسوخ و جایگزین آن فایل محیطی است).

نکته‌ی مهم: گیت هاب به‌دلیل مسائل امنیتی، سه دستور ::set-env::، ::add-path:: و ::set-output:: را منسوخ کرده و به‌جای آن‌ها استفاده از Environment Files را توصیه می‌کند. این تغییر، به‌دلیل آسیب‌پذیری در برابر حملات تزریق دستور بوده است. برای مطالعه‌ی بیشتر در این حوزه، اصول امنیت API کمک‌کننده است.

Environment Files و روش نوین

Environment Files، رویکرد مدرن گیت هاب برای انتقال داده از اسکریپت به رانر هستند. به‌جای چاپ دستورات در stdout، اسکریپت در فایل‌های مشخصی می‌نویسد که مسیر آن‌ها در متغیرهای محیطی خاصی قرار دارد:

متغیر محیطیکاربردجایگزین دستور
GITHUB_ENVتنظیم متغیر محیطی::set-env::
GITHUB_OUTPUTتعیین مقدار خروجی گام::set-output::
GITHUB_PATHافزودن به PATH::add-path::
GITHUB_STATEذخیره وضعیت Action::save-state::
GITHUB_STEP_SUMMARYنوشتن خلاصه گام(جدید)

نحو نوشتن در این فایل‌ها به این شکل است:

echo "MY_VAR=value" >> "$GITHUB_ENV"
echo "output_name=result" >> "$GITHUB_OUTPUT"
echo "/custom/bin" >> "$GITHUB_PATH"

سه نکته‌ی کلیدی درباره‌ی این فایل‌ها:

  1. هر فایل، نحو خاص خود را دارد. برای مثال، در GITHUB_ENV و GITHUB_OUTPUT، از نحو name=value استفاده می‌شود؛ در GITHUB_PATH و GITHUB_STATE، تنها مسیر یا مقدار نوشته می‌شود.
  2. نحو قدیمی همچنان پشتیبانی می‌شود اما توصیه نمی‌گردد. گیت هاب اعلام کرده که در آینده‌ای نامعلوم، دستورات منسوخ را به‌طور کامل غیرفعال خواهد کرد.
  3. امنیت بالاتر: چون داده‌ها در فایل نوشته می‌شوند و از stdout عبور نمی‌کنند، ریسک تزریق دستور کاهش می‌یابد.

اگر با اصول مدیریت متغیرهای محیطی و امنیت کد آشنایی ندارید، مطالعه‌ی نوشتن کد PHP امن و اعتبارسنجی داده در کد کمک‌کننده است.

ماسک کردن اطلاعات حساس

در ورک‌فلوها، گاهی نیاز است که مقادیر حساس (مانند توکن یا رمز) در لاگ‌ها نمایش داده نشوند. دستور ::add-mask:: یا استفاده از Secrets، این امکان را فراهم می‌کند.

نحوه‌ی استفاده از دستور کلاسیک:

::add-mask::my-secret-value

نحوه‌ی استفاده در Bash با Environment Files:

SECRET_VALUE=$(generate-token)
echo "::add-mask::$SECRET_VALUE"
echo "TOKEN=$SECRET_VALUE" >> "$GITHUB_ENV"

سه نکته‌ی مهم در ماسک‌سازی:

  1. ترتیب اهمیت دارد. ابتدا باید ماسک را فعال کنید، سپس مقدار را در جای دیگری استفاده نمایید.
  2. ماسک در تمام گام‌های بعدی معتبر است. اما در گام‌های قبلی که مقدار چاپ شده باشد، ماسک اعمال نمی‌شود.
  3. ماسک‌سازی جایگزین Secrets نیست. مقادیر حساس باید از طریق Secrets یا Vault مدیریت شوند. برای مطالعه‌ی بیشتر در این حوزه، اصول امنیت وب کمک‌کننده است.
ماسک‌سازی یک لایه دفاعی است، نه یک راهکار کامل؛ مدیریت Secrets پایه‌ی امنیت است.

گروه‌بندی لاگ‌ها

در ورک‌فلوهای پیچیده، حجم لاگ‌ها می‌تواند زیاد شود و پیدا کردن اطلاعات کلیدی دشوار گردد. دستور ::group:: به شما امکان می‌دهد خطوط لاگ را در بخش‌های تاشو سازمان‌دهی کنید.

نمونه‌ی استفاده:

echo "::group::نصب وابستگی‌ها"
npm install
echo "::endgroup::"

در رابط گیت هاب، این بخش در لاگ به شکل یک گروه تاشو نمایش داده می‌شود که کاربر می‌تواند آن را باز یا بسته کند. این ویژگی، به‌ویژه در ورک‌فلوهای چندمرحله‌ای بسیار کاربردی است. برای مطالعه‌ی بیشتر در این حوزه، آموزش GitHub Actions و دستورات ضروری Git کمک‌کننده است.

مدیریت وضعیت بین گام‌ها

یکی از چالش‌های اصلی در ورک‌فلوها، انتقال داده بین گام‌ها است. سه راه‌حل اصلی وجود دارد:

خروجی گام‌ها

هر گام می‌تواند یک یا چند خروجی داشته باشد که در گام‌های بعدی قابل استفاده است:

- id: build
  run: echo "version=1.2.3" >> "$GITHUB_OUTPUT"

- run: echo "Built version ${{ steps.build.outputs.version }}"

متغیرهای محیطی

متغیرهایی که در GITHUB_ENV نوشته می‌شوند، در گام‌های بعدی به‌عنوان متغیر محیطی قابل استفاده هستند:

- run: echo "NODE_VERSION=20" >> "$GITHUB_ENV"
- run: echo "Using Node $NODE_VERSION"

وضعیت Action

در Actionهای سفارشی، می‌توان از GITHUB_STATE برای ذخیره‌ی وضعیت میان اجرای pre و post استفاده کرد:

echo "start_time=$(date +%s)" >> "$GITHUB_STATE"

نکته‌ی مهم: داده‌های خروجی و متغیرها، تنها برای گام‌های همان Job قابل دسترسی هستند؛ برای انتقال به Job دیگر، باید از Artifact یا Matrix Output استفاده شود. برای مطالعه‌ی بیشتر در این حوزه، CI/CD برای پروژه‌های وردپرسی کمک‌کننده است.

دیباگ ورک‌فلو

در زمان دیباگ، می‌توان از دستور ::debug:: برای چاپ پیام‌های اضافی استفاده کرد. این پیام‌ها تنها در صورت فعال بودن دیباگ نمایش داده می‌شوند. برای فعال‌سازی، باید یکی از دو روش زیر را به کار گرفت:

  1. فعال‌سازی از طریق Secrets: با تعریف یک Secret با نام ACTIONS_STEP_DEBUG و مقدار true.
  2. فعال‌سازی از طریق Re-run: در زمان اجرای مجدد، گزینه‌ی Enable debug logging را فعال کنید.

نمونه‌ی استفاده:

echo "::debug::Current directory is $PWD"
echo "::debug::Files count: $(ls | wc -l)"

نکته‌ی مهم: در محیط تولید، پیام‌های دیباگ نباید حاوی اطلاعات حساس باشند. اگر با اصول دیباگ کردن کد آشنایی ندارید، مطالعه‌ی دیباگ کد سفارشی وردپرس کمک‌کننده است.

الگوهای عملی

در پروژه‌های واقعی، ترکیب دستورات ورک‌فلو الگوهای کاربردی می‌سازد:

الگوی یک: گزارش خطای سفارشی در اسکریپت

if [ ! -f "package.json" ]; then
  echo "::error file=package.json::فایل package.json یافت نشد"
  exit 1
fi

الگوی دو: گروه‌بندی مراحل اجرای تست

echo "::group::Running tests"
npm test
echo "::endgroup::"

الگوی سه: انتقال خروجی به Job دیگر

- id: version
  run: echo "value=1.2.3" >> "$GITHUB_OUTPUT"

- uses: actions/upload-artifact@v4
  with:
    name: version-file
    path: version.txt

الگوی چهار: ماسک کردن توکن تولیدی

TOKEN=$(curl -s https://auth.example.com/token)
echo "::add-mask::$TOKEN"
echo "AUTH_TOKEN=$TOKEN" >> "$GITHUB_ENV"

الگوی پنج: نوشتن خلاصه گام

cat >> "$GITHUB_STEP_SUMMARY" << EOF
### نتیجه Build

- نسخه: 1.2.3
- زمان: 2 دقیقه
- وضعیت: موفق
EOF

این الگوها، در پروژه‌های واقعی کاربرد فراوانی دارند و می‌توانند به‌عنوان پایه‌ای برای الگوهای سفارشی‌تر استفاده شوند. برای مطالعه‌ی بیشتر، دپندابات در گیت هاب و مقایسه GitHub و GitLab کمک‌کننده است.

الگوهای عملی، پایه‌ی ورک‌فلوهای حرفه‌ای هستند؛ اما هر پروژه، الگوهای خود را می‌سازد.

نکات امنیتی

دستورات ورک‌فلو، در صورت استفاده‌ی نادرست، می‌توانند به آسیب‌پذیری منجر شوند. سه اصل کلیدی:

  1. پرهیز از دستورات منسوخ: دستورات ::set-env::، ::add-path:: و ::set-output:: در برابر تزریق آسیب‌پذیر هستند و باید کنار گذاشته شوند.
  2. ماسک کردن داده‌های حساس: هر داده‌ی محرمانه‌ای که در لاگ چاپ می‌شود، باید ماسک گردد.
  3. اعتبارسنجی ورودی‌ها: در Actionهای سفارشی، ورودی‌ها باید پیش از استفاده اعتبارسنجی شوند تا از اجرای دستور مخرب جلوگیری شود.

نکته‌ی مهم: در ورک‌فلوهایی که از Pull Requestهای خارجی اجرا می‌شوند، باید دقت بیشتری در استفاده از Secrets و دستورات ورک‌فلو داشت. برای مطالعه‌ی بیشتر در این حوزه، امنیت API در وب و CVE در امنیت کمک‌کننده است.

خطاهای رایج

سه خطای رایج در استفاده از دستورات ورک‌فلو:

  1. استفاده از دستورات منسوخ: دستورات ::set-output:: و ::save-state:: اگرچه همچنان کار می‌کنند، اما در آینده غیرفعال خواهند شد و باید به Environment Files مهاجرت کرد.
  2. فراموش کردن escape کاراکترها: برخی کاراکترها در پیام‌های دستور، باید با کدهای escape جایگزین شوند. نادیده گرفتن این نکته، به دستورات نادرست منجر می‌شود.
  3. چاپ داده‌های حساس بدون ماسک: هر داده‌ای که در لاگ چاپ شود، در تاریخچه‌ی اجرا باقی می‌ماند و می‌تواند در آینده افشا شود.

برای پرهیز از این خطاها، مطالعه‌ی رفع خطاهای رایج گیت و اشتباهات رایج پاسخ به حملات سایبری کمک‌کننده است.

پرسش‌های پرتکرار

تفاوت Workflow Commands و Environment Files چیست؟

Workflow Commands پیام‌هایی هستند که در stdout چاپ می‌شوند و با نحو ::command:: شناسایی می‌گردند. Environment Files فایل‌هایی هستند که رانر مسیر آن‌ها را در متغیرهای محیطی قرار می‌دهد و اسکریپت با نوشتن در آن‌ها، داده را به رانر منتقل می‌کند. روش دوم امن‌تر و مدرن‌تر است.

چرا برخی دستورات منسوخ شده‌اند؟

دستورات ::set-env::، ::add-path:: و ::set-output:: در برابر حملات تزریق آسیب‌پذیر بودند. گیت هاب برای رفع این آسیب‌پذیری، Environment Files را معرفی کرد که داده‌ها را در فایل‌های جدا نوشته می‌کند و از دسترسی مستقیم به محیط اجرا جلوگیری می‌نماید.

چگونه یک پیام خطای سفارشی در لاگ نمایش دهیم؟

با دستور ::error:: می‌توان خطا را گزارش داد. می‌توان پارامترهایی مانند فایل، خط و ستون نیز اضافه کرد تا خطا دقیق‌تر نمایش داده شود.

چگونه داده‌ها را در لاگ‌ها ماسک کنیم؟

با دستور ::add-mask::. اما این دستور تنها از نمایش داده در لاگ‌های بعدی جلوگیری می‌کند. برای مدیریت اصولی داده‌های حساس، باید از Secrets یا Vault استفاده شود.

آیا می‌توان خلاصه‌ی گام را در گیت هاب نمایش داد؟

بله. با نوشتن در فایل GITHUB_STEP_SUMMARY، می‌توان خلاصه‌ای به شکل Markdown ساخت که در رابط گیت هاب در پایین هر گام نمایش داده می‌شود.

چگونه دستورات ورک‌فلو را در پروژه‌های وردپرسی به کار ببریم؟

در پروژه‌های وردپرسی، این دستورات را می‌توان برای گزارش‌گیری، ماسک کردن اطلاعات حساس، ساخت خلاصه‌ی build و انتقال داده بین گام‌های آزمون و استقرار به کار برد. برای مطالعه‌ی بیشتر، CI/CD برای پروژه‌های وردپرسی و دپندابات گیت هاب کمک‌کننده است.

ارتباطی که ورک‌فلو را حرفه‌ای می‌کند

دستورات ورک‌فلو گیت هاب اکشنز، لایه‌ی ارتباطی میان اسکریپت شما و رانر هستند. از گزارش خطا و هشدار تا ماسک کردن اطلاعات حساس، گروه‌بندی لاگ‌ها و انتقال وضعیت بین گام‌ها، این دستورات ابزارهایی هستند که ورک‌فلوی شما را از یک خط لوله‌ی ساده به یک خط لوله‌ی حرفه‌ای و امن تبدیل می‌کنند. تسلط بر این دستورات، نه فقط برای توسعه‌دهندگانی که Actionهای سفارشی می‌سازند، بلکه برای هر مهندسی که می‌خواهد ورک‌فلوهای خود را شفاف، قابل نگهداری و امن کند، ضروری است. با مهاجرت به Environment Files، اجتناب از دستورات منسوخ و پیاده‌سازی الگوهای عملی مانند ماسک‌سازی و گروه‌بندی، می‌توان خط لوله‌ای ساخت که در محیط‌های واقعی، پایدار و قابل اعتماد باقی بماند. برای تیم‌های وردپرسی، پیوند این مفاهیم با آموزش GitHub Actions و CI/CD برای پروژه‌های وردپرسی مسیر عملی‌تری ترسیم می‌کند. اگر در پروژه‌های واقعی این دستورات را به کار برده‌اید، برای خوانندگان بعدی ارزشمند است بدانید کدام الگو بیشترین کمک را به تیم شما کرده و چه چالشی در مهاجرت از دستورات کلاسیک به Environment Files تجربه کرده‌اید.