بازگشت به وبلاگ

پروکسی در GitHub Actions و پایپ‌لاین‌های CI/CD: راهنمای کامل با مثال‌های کد

در این مقاله به بررسی نحوه اتصال پروکسی به جریان کار GitHub Actions می‌پردازیم تا وظایف خودکار مسدود نشوند و از منطقه مورد نظر کار کنند.

📅۲۹ تیر ۱۴۰۵
```html

GitHub Actions — ابزاری قدرتمند برای اتوماسیون است: تست‌ها را اجرا می‌کند، برنامه‌ها را مستقر می‌کند، داده‌ها را جمع‌آوری می‌کند و ده‌ها کار دیگر را انجام می‌دهد. اما به محض اینکه جریان کار به منابع خارجی — بازارها، پلتفرم‌های تبلیغاتی، API‌های خارجی — دسترسی پیدا می‌کند، بلافاصله با محدودیت‌های جغرافیایی و محدودیت‌های IP مواجه می‌شود. راه‌حل واحد: اتصال پروکسی به طور مستقیم در پایپ‌لاین.

چرا پروکسی در GitHub Actions: سناریوهای واقعی

بسیاری از تیم‌ها از GitHub Actions نه تنها برای استقرار کد، بلکه برای اتوماسیون وظایف تجاری استفاده می‌کنند: نظارت بر قیمت‌های رقبا، جمع‌آوری داده‌ها از بازارها، بررسی خودکار حساب‌های تبلیغاتی و تست وب‌سایت‌ها از مناطق مختلف. همه این وظایف یک مشکل مشترک دارند — runner GitHub Actions دارای IP ثابت از دامنه Microsoft Azure است و بسیاری از خدمات آن را مسدود یا محدود می‌کنند.

در اینجا موقعیت‌های خاصی وجود دارد که بدون پروکسی نمی‌توان از آن‌ها عبور کرد:

  • پارسینگ Wildberries، Ozon، Avito — این پلتفرم‌ها مدت‌هاست که دامنه‌های IP ارائه‌دهندگان ابری را در لیست سیاه قرار داده‌اند. درخواست از runner GitHub Actions در ۲–۳ تلاش مسدود یا CAPTCHA دریافت خواهد کرد.
  • تست جغرافیایی — بازاریابان و مهندسان QA بررسی می‌کنند که وب‌سایت یا تبلیغ برای کاربران از مسکو، برلین یا نیویورک چگونه به نظر می‌رسد. بدون پروکسی، runner همیشه محتوا را برای یک منطقه "می‌بیند".
  • کار با API‌های محدود شده بر اساس منطقه — برخی از API‌ها (به عنوان مثال، نسخه‌های منطقه‌ای Google Ads، Facebook Marketing API با تنظیمات خاص) بسته به جغرافیای درخواست داده‌های مختلفی را برمی‌گردانند.
  • نظارت بر رقبا — جمع‌آوری خودکار قیمت‌ها، تبلیغات و تنوع نیاز به درخواست‌های منظم دارد که به راحتی با IP تکراری مرکز داده شناسایی می‌شوند.
  • اتوماسیون بررسی‌های تبلیغاتی — آربیتراژکنندگان و بازاریابان عملکرد بررسی‌های خودکار وضعیت تبلیغات، موجودی و معیارها را از طریق اسکریپت‌ها در CI/CD راه‌اندازی می‌کنند.
  • تست‌های یکپارچه‌سازی با خدمات خارجی — برخی از خدمات به دلایل امنیتی درخواست‌ها را از دامنه‌های Azure مسدود می‌کنند و تست‌ها بدون توضیح به سادگی شکست می‌خورند.

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

چگونه GitHub Actions با شبکه کار می‌کند

قبل از تنظیم پروکسی، مهم است که معماری شبکه در GitHub Actions را درک کنید. زمانی که شما یک جریان کار را بر روی runner استاندارد ubuntu-latest اجرا می‌کنید، وظیفه بر روی یک ماشین مجازی در زیرساخت Microsoft Azure اجرا می‌شود. هر یک از این ماشین‌ها دارای IP عمومی از دامنه‌های Azure است — و این IP است که خدمات خارجی می‌بینند.

ویژگی‌های کلیدی شبکه در GitHub Actions:

  • IP در هر بار اجرا تغییر می‌کند — اما در دامنه‌های شناخته شده Azure باقی می‌ماند که به راحتی شناسایی می‌شوند.
  • هیچ پشتیبانی داخلی از پروکسی وجود ندارد — GitHub مکانیزم بومی برای پروکسی کردن ترافیک ارائه نمی‌دهد.
  • متغیرهای محیطی به صورت جهانی کار می‌کنند — اگر HTTP_PROXY را در سطح job تنظیم کنید، همه مراحل درون این job از پروکسی استفاده خواهند کرد.
  • Self-hosted runners — جایگزینی که در آن شما runner را بر روی سرور خود اجرا می‌کنید. در این حالت پروکسی در سطح سرور تنظیم می‌شود، نه جریان کار.

برای اکثر وظایف، رویکرد بهینه — تنظیم پروکسی از طریق متغیرهای محیطی به طور مستقیم در فایل جریان کار (.github/workflows/your-workflow.yml) است. این یک روش جهانی است که برای اکثر ابزارها کار می‌کند: curl، wget، Python requests، Node.js http، Go net/http و دیگران.

کدام نوع پروکسی برای CI/CD انتخاب کنیم

انتخاب نوع پروکسی بستگی به وظیفه دارد. برای پایپ‌لاین‌های CI/CD سه گزینه مرتبط وجود دارد و هر کدام جایگاه خود را دارند:

نوع پروکسی برای کدام وظایف سرعت سطح اعتماد
پروکسی‌های مسکونی پارسینگ وب‌سایت‌های محافظت‌شده، هدف‌گذاری جغرافیایی، نظارت بر بازارها متوسط بالا — IP‌های واقعی خانگی
پروکسی‌های موبایل تست نسخه‌های موبایل، کار با شبکه‌های اجتماعی، Facebook/TikTok API متوسط حداکثر — IP‌های اپراتوری
پروکسی‌های مرکز داده تست‌های یکپارچه‌سازی، درخواست‌ها به API‌های غیرمحافظت‌شده، بار بالا بالا متوسط

قاعده عملی: اگر جریان کار شما Wildberries، Ozon یا دیگر بازارها را با حفاظت ضد ربات پارس می‌کند — پروکسی‌های مسکونی را انتخاب کنید. اگر حساب‌های تبلیغاتی Facebook Ads یا TikTok Ads را تست می‌کنید — از پروکسی‌های موبایل استفاده کنید. برای تست‌های یکپارچه‌سازی ساده و درخواست‌ها به API‌های باز، پروکسی‌های مرکز داده کافی هستند: آن‌ها سریع‌تر و ارزان‌تر هستند.

💡 نکته مهم درباره پروتکل‌ها

برای GitHub Actions بهتر است از پروکسی‌های HTTP/HTTPS استفاده کنید — آن‌ها توسط اکثر ابزارها بدون تنظیمات اضافی پشتیبانی می‌شوند. SOCKS5 نیز کار می‌کند، اما نیاز به مشخص کردن صریح در هر ابزار دارد. اگر ارائه‌دهنده شما هر دو پروتکل را پشتیبانی می‌کند — از HTTP شروع کنید.

تنظیم پروکسی از طریق متغیرهای محیطی

ساده‌ترین و عمومی‌ترین روش برای اتصال پروکسی در GitHub Actions — تنظیم متغیرهای محیطی استاندارد HTTP_PROXY، HTTPS_PROXY و NO_PROXY است. بیشتر ابزارهای خط فرمان و زبان‌های برنامه‌نویسی به طور خودکار آن‌ها را شناسایی می‌کنند.

ساختار پایه‌ای جریان کار با پروکسی به این صورت است:

name: Workflow with Proxy

on:
  schedule:
    - cron: '0 9 * * *'
  workflow_dispatch:

jobs:
  scrape-data:
    runs-on: ubuntu-latest

    env:
      HTTP_PROXY: http://${{ secrets.PROXY_USER }}:${{ secrets.PROXY_PASS }}@${{ secrets.PROXY_HOST }}:${{ secrets.PROXY_PORT }}
      HTTPS_PROXY: http://${{ secrets.PROXY_USER }}:${{ secrets.PROXY_PASS }}@${{ secrets.PROXY_HOST }}:${{ secrets.PROXY_PORT }}
      NO_PROXY: localhost,127.0.0.1,github.com

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Check current IP (برای بررسی)
        run: curl -s https://api.ipify.org

      - name: Run main script
        run: python scripts/scraper.py

به بلوک NO_PROXY توجه کنید — در آن باید آدرس‌هایی که نیازی به پروکسی کردن ترافیک ندارند، اضافه کنید. حداقل این‌ها localhost و 127.0.0.1 هستند. همچنین توصیه می‌شود github.com را اضافه کنید تا عملیات با مخزن (checkout، push) به طور مستقیم انجام شود.

اگر پروکسی بدون احراز هویت (فقط IP و پورت) باشد، فرمت ساده‌تر می‌شود:

env:
  HTTP_PROXY: http://203.0.113.10:8080
  HTTPS_PROXY: http://203.0.113.10:8080
  NO_PROXY: localhost,127.0.0.1

برای پروکسی SOCKS5 تنها طرح در URL تغییر می‌کند:

env:
  HTTP_PROXY: socks5://user:password@proxy-host:1080
  HTTPS_PROXY: socks5://user:password@proxy-host:1080

پروکسی برای curl، wget و درخواست‌های HTTP در shell

اگر متغیرهای محیطی در سطح job تنظیم شده باشند (همانطور که در بالا نشان داده شده است)، curl و wget به طور خودکار آن‌ها را شناسایی می‌کنند. اما گاهی اوقات نیاز است که پروکسی را به طور صریح ارائه دهید — برای مثال، برای یک مرحله خاص یا در هنگام اشکال‌زدایی.

مشخص کردن صریح پروکسی در curl:

- name: Fetch data with proxy
  run: |
    curl -x http://${{ secrets.PROXY_USER }}:${{ secrets.PROXY_PASS }}@${{ secrets.PROXY_HOST }}:${{ secrets.PROXY_PORT }} \
      -s \
      -o output.json \
      https://api.example.com/data

    # بررسی از طریق پروکسی
    curl -x http://${{ secrets.PROXY_USER }}:${{ secrets.PROXY_PASS }}@${{ secrets.PROXY_HOST }}:${{ secrets.PROXY_PORT }} \
      -s https://api.ipify.org?format=json

برای wget:

- name: Download with wget via proxy
  run: |
    wget -e "https_proxy=http://${{ secrets.PROXY_USER }}:${{ secrets.PROXY_PASS }}@${{ secrets.PROXY_HOST }}:${{ secrets.PROXY_PORT }}" \
      -q \
      -O data.html \
      https://target-site.com/page

یک مرحله مفید برای اشکال‌زدایی — اضافه کردن بررسی IP در ابتدای جریان کار است. اگر پروکسی به درستی کار کند، شما IP پروکسی سرور را خواهید دید، نه Azure:

- name: Verify proxy is active
  run: |
    echo "=== IP without proxy ==="
    curl -s --noproxy '*' https://api.ipify.org || echo "درخواست مستقیم شکست خورد"
    echo ""
    echo "=== IP through proxy ==="
    curl -s https://api.ipify.org

پروکسی در اسکریپت‌های Python درون جریان کار

Python — یکی از محبوب‌ترین زبان‌ها برای اسکریپت‌ها در CI/CD است. کتابخانه requests به طور خودکار متغیرهای محیطی HTTP_PROXY و HTTPS_PROXY را می‌خواند، اگر آن‌ها تنظیم شده باشند. اما برای مدیریت انعطاف‌پذیرتر، بهتر است پروکسی را به طور صریح ارائه دهید.

مثال اسکریپت Python با ارائه صریح پروکسی از طریق متغیرهای محیطی:

import os
import requests

# خواندن داده‌های پروکسی از متغیرهای محیطی
proxy_host = os.environ.get('PROXY_HOST')
proxy_port = os.environ.get('PROXY_PORT')
proxy_user = os.environ.get('PROXY_USER')
proxy_pass = os.environ.get('PROXY_PASS')

proxies = {
    'http': f'http://{proxy_user}:{proxy_pass}@{proxy_host}:{proxy_port}',
    'https': f'http://{proxy_user}:{proxy_pass}@{proxy_host}:{proxy_port}',
}

# استفاده از پروکسی در درخواست
response = requests.get(
    'https://www.wildberries.ru/catalog/123456/detail.aspx',
    proxies=proxies,
    timeout=30,
    headers={
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
    }
)

print(f"Status: {response.status_code}")
print(f"Content length: {len(response.content)}")

در فایل جریان کار باید متغیرها را به عنوان رازهای جداگانه (نه به صورت URL کامل) منتقل کنید تا اسکریپت بتواند آن‌ها را جمع‌آوری کند:

- name: Run Python scraper
  env:
    PROXY_HOST: ${{ secrets.PROXY_HOST }}
    PROXY_PORT: ${{ secrets.PROXY_PORT }}
    PROXY_USER: ${{ secrets.PROXY_USER }}
    PROXY_PASS: ${{ secrets.PROXY_PASS }}
  run: python scripts/scraper.py

برای کار با Playwright یا Selenium در Python، پیکربندی پروکسی کمی متفاوت است:

# Playwright
from playwright.sync_api import sync_playwright
import os

proxy_url = f"http://{os.environ['PROXY_USER']}:{os.environ['PROXY_PASS']}@{os.environ['PROXY_HOST']}:{os.environ['PROXY_PORT']}"

with sync_playwright() as p:
    browser = p.chromium.launch(
        proxy={
            "server": proxy_url
        }
    )
    page = browser.new_page()
    page.goto("https://target-site.com")
    # ... ادامه منطق
    browser.close()

پروکسی در Node.js و وظایف npm

Node.js به طور خودکار متغیرهای سیستمی HTTP_PROXY را نمی‌خواند — باید یا از کتابخانه‌های خاص استفاده کنید یا پروکسی را به طور صریح تنظیم کنید. راحت‌ترین گزینه — بسته https-proxy-agent یا axios با پیکربندی پروکسی است.

// با استفاده از axios
const axios = require('axios');

const proxyConfig = {
  host: process.env.PROXY_HOST,
  port: parseInt(process.env.PROXY_PORT),
  auth: {
    username: process.env.PROXY_USER,
    password: process.env.PROXY_PASS
  }
};

async function fetchData(url) {
  try {
    const response = await axios.get(url, {
      proxy: proxyConfig,
      timeout: 30000,
      headers: {
        'User-Agent': 'Mozilla/5.0 (compatible; MyBot/1.0)'
      }
    });
    return response.data;
  } catch (error) {
    console.error(`درخواست شکست خورد: ${error.message}`);
    throw error;
  }
}

fetchData('https://api.example.com/prices')
  .then(data => console.log(JSON.stringify(data, null, 2)))
  .catch(() => process.exit(1));

برای دستورات npm (به عنوان مثال، اگر npm سعی کند بسته‌ها را از طریق پروکسی شرکتی دانلود کند) پیکربندی ساده‌تر است:

- name: Configure npm proxy
  run: |
    npm config set proxy http://${{ secrets.PROXY_USER }}:${{ secrets.PROXY_PASS }}@${{ secrets.PROXY_HOST }}:${{ secrets.PROXY_PORT }}
    npm config set https-proxy http://${{ secrets.PROXY_USER }}:${{ secrets.PROXY_PASS }}@${{ secrets.PROXY_HOST }}:${{ secrets.PROXY_PORT }}

- name: Install dependencies
  run: npm install

- name: Reset npm proxy (پاک کردن بعد از استفاده)
  run: |
    npm config delete proxy
    npm config delete https-proxy

ذخیره‌سازی امن داده‌های پروکسی در GitHub Secrets

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

رویکرد صحیح — GitHub Secrets. در اینجا یک دستورالعمل گام به گام وجود دارد:

  1. مخزن را در GitHub باز کنید
  2. به Settings → Secrets and variables → Actions بروید
  3. روی New repository secret کلیک کنید
  4. چهار راز ایجاد کنید: PROXY_HOST، PROXY_PORT، PROXY_USER، PROXY_PASS
  5. در جریان کار به آن‌ها از طریق سینتکس ${{ secrets.PROXY_HOST }} ارجاع دهید

🔒 اقدامات امنیتی اضافی

  • از Environment secrets به جای Repository secrets استفاده کنید، اگر محیط‌های مختلف (staging/production) از پروکسی‌های مختلف استفاده می‌کنند
  • دسترسی به رازها را از طریق Environment protection rules محدود کنید — تأیید دستی برای production را الزامی کنید
  • به طور منظم اعتبارنامه‌های پروکسی را چرخش دهید — رمزها را هر ۳۰–۹۰ روز تغییر دهید
  • مقادیر رازها را در لاگ‌ها از طریق echo چاپ نکنید — GitHub به طور خودکار آن‌ها را مخفی می‌کند، اما بهتر است ریسک نکنید

اگر از پروکسی‌های چرخشی استفاده می‌کنید (زمانی که IP در هر درخواست یا بر اساس زمان‌بندی تغییر می‌کند)، معمولاً کافی است تنها یک endpoint را ذخیره کنید — ارائه‌دهنده پروکسی خود مدیریت استخر IP را انجام می‌دهد. در این صورت تنها یک هاست و پورت در رازها وجود خواهد داشت.

چرخش پروکسی و مدیریت خطاها در پایپ‌لاین

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

استراتژی 1: Retry با همان پروکسی

import requests
import time
import os

def fetch_with_retry(url, max_retries=3, delay=5):
    proxies = {
        'http': f"http://{os.environ['PROXY_USER']}:{os.environ['PROXY_PASS']}@{os.environ['PROXY_HOST']}:{os.environ['PROXY_PORT']}",
        'https': f"http://{os.environ['PROXY_USER']}:{os.environ['PROXY_PASS']}@{os.environ['PROXY_HOST']}:{os.environ['PROXY_PORT']}",
    }

    for attempt in range(max_retries):
        try:
            response = requests.get(url, proxies=proxies, timeout=30)
            response.raise_for_status()
            return response
        except requests.exceptions.RequestException as e:
            print(f"Attempt {attempt + 1} failed: {e}")
            if attempt < max_retries - 1:
                print(f"Retrying in {delay} seconds...")
                time.sleep(delay)
                delay *= 2  # تأخیر نمایی
    raise Exception(f"All {max_retries} attempts failed for {url}")

استراتژی 2: لیست پروکسی با سوئیچینگ

اگر چندین سرور پروکسی دارید، می‌توانید لیست آن‌ها را در یک راز (از طریق ویرگول) ذخیره کنید و در صورت بروز خطا سوئیچ کنید:

import os
import requests
import random

# راز PROXY_LIST شامل: "host1:port1:user1:pass1,host2:port2:user2:pass2"
proxy_list_raw = os.environ.get('PROXY_LIST', '').split(',')

def parse_proxy(proxy_str):
    parts = proxy_str.strip().split(':')
    if len(parts) == 4:
        host, port, user, password = parts
        return {
            'http': f'http://{user}:{password}@{host}:{port}',
            'https': f'http://{user}:{password}@{host}:{port}',
        }
    return None

proxies = [p for p in [parse_proxy(raw) for raw in proxy_list_raw] if p]

def fetch_with_proxy_rotation(url):
    random.shuffle(proxies)  # ترتیب تصادفی
    for proxy in proxies:
        try:
            response = requests.get(url, proxies=proxy, timeout=20)
            if response.status_code == 200:
                return response
        except Exception as e:
            print(f"پروکسی شکست خورد: {e}, trying next...")
    raise Exception("All proxies exhausted")

استراتژی 3: استفاده از endpoint چرخشی

ساده‌ترین گزینه — استفاده از ارائه‌دهنده پروکسی با یک gateway چرخشی واحد است. در این حالت شما به یک آدرس متصل می‌شوید و ارائه‌دهنده به طور خودکار IP‌های مختلفی از استخر ارائه می‌دهد. هیچ منطقی برای چرخش در کد نیاز نیست — تنها یک خط اتصال کافی است.

سناریوهای واقعی: پارسینگ، تست‌ها، نظارت بر قیمت‌ها

بیایید سه سناریو خاص را بررسی کنیم که بیشتر در تیم‌هایی که از GitHub Actions با پروکسی استفاده می‌کنند، مشاهده می‌شود.

سناریو 1: نظارت روزانه بر قیمت‌ها در Wildberries

فروشندگان بازارها اغلب جمع‌آوری خودکار قیمت‌های رقبا را تنظیم می‌کنند. جریان کار به صورت زمان‌بندی شده اجرا می‌شود (برای مثال، هر صبح ساعت ۷:۰۰)، داده‌ها را جمع‌آوری کرده و در Google Sheets ذخیره می‌کند یا به Telegram ارسال می‌کند.

name: Daily Price Monitor

on:
  schedule:
    - cron: '0 4 * * *'  # 07:00 م.م. (UTC+3)

jobs:
  monitor-prices:
    runs-on: ubuntu-latest

    env:
      HTTP_PROXY: http://${{ secrets.PROXY_USER }}:${{ secrets.PROXY_PASS }}@${{ secrets.PROXY_HOST }}:${{ secrets.PROXY_PORT }}
      HTTPS_PROXY: http://${{ secrets.PROXY_USER }}:${{ secrets.PROXY_PASS }}@${{ secrets.PROXY_HOST }}:${{ secrets.PROXY_PORT }}
      NO_PROXY: github.com,api.github.com

    steps:
      - uses: actions/checkout@v4

      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      - name: Install dependencies
        run: pip install requests beautifulsoup4 gspread

      - name: Run price scraper
        env:
          GOOGLE_SHEETS_KEY: ${{ secrets.GOOGLE_SHEETS_KEY }}
          TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
          TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }}
        run: python scripts/price_monitor.py

      - name: Upload results artifact
        uses: actions/upload-artifact@v4
        with:
          name: price-data-${{ github.run_id }}
          path: output/prices.json

سناریو 2: تست جغرافیایی وب‌سایت

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

name: Geo-targeted Site Tests

on:
  push:
    branches: [main]
  pull_request:

jobs:
  test-moscow:
    runs-on: ubuntu-latest
    name: Test from Moscow
    steps:
      - uses: actions/checkout@v4
      - name: Run geo tests (RU/Moscow proxy)
        env:
          HTTP_PROXY: http://${{ secrets.PROXY_RU_USER }}:${{ secrets.PROXY_RU_PASS }}@${{ secrets.PROXY_RU_HOST }}:${{ secrets.PROXY_RU_PORT }}
          HTTPS_PROXY: http://${{ secrets.PROXY_RU_USER }}:${{ secrets.PROXY_RU_PASS }}@${{ secrets.PROXY_RU_HOST }}:${{ secrets.PROXY_RU_PORT }}
        run: |
          python tests/geo_test.py --region=RU --city=Moscow

  test-germany:
    runs-on: ubuntu-latest
    name: Test from Germany
    steps:
      - uses: actions/checkout@v4
      - name: Run geo tests (DE proxy)
        env:
          HTTP_PROXY: http://${{ secrets.PROXY_DE_USER }}:${{ secrets.PROXY_DE_PASS }}@${{ secrets.PROXY_DE_HOST }}:${{ secrets.PROXY_DE_PORT }}
          HTTPS_PROXY: http://${{ secrets.PROXY_DE_USER }}:${{ secrets.PROXY_DE_PASS }}@${{ secrets.PROXY_DE_HOST }}:${{ secrets.PROXY_DE_PORT }}
        run: |
          python tests/geo_test.py --region=DE

سناریو 3: بررسی خودکار حساب‌های تبلیغاتی

آربیتراژکنندگان و بازاریابان عملکرد به طور مکرر از GitHub Actions برای بررسی خودکار وضعیت حساب‌های تبلیغاتی Facebook Ads، موجودی و معیارها استفاده می‌کنند. درخواست‌ها به Facebook Marketing API از دامنه‌های Azure ممکن است بررسی‌های امنیتی اضافی را به همراه داشته باشد — پروکسی به دور زدن این موضوع کمک می‌کند.

name: Ad Account Health Check

on:
  schedule:
    - cron: '*/30 6-22 * * *'  # هر ۳۰ دقیقه از ۶ تا ۲۲ م.م.

jobs:
  check-accounts:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      - name: Install dependencies
        run: pip install requests

      - name: Check Facebook Ads accounts
        env:
          HTTP_PROXY: http://${{ secrets.PROXY_USER }}:${{ secrets.PROXY_PASS }}@${{ secrets.PROXY_HOST }}:${{ secrets.PROXY_PORT }}
          HTTPS_PROXY: http://${{ secrets.PROXY_USER }}:${{ secrets.PROXY_PASS }}@${{ secrets.PROXY_HOST }}:${{ secrets.PROXY_PORT }}
          FB_ACCESS_TOKEN: ${{ secrets.FB_ACCESS_TOKEN }}
          ACCOUNT_IDS: ${{ secrets.FB_ACCOUNT_IDS }}
          TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
          TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }}
        run: python scripts/check_fb_accounts.py

📋 چک‌لیست قبل از راه‌اندازی جریان کار با پروکسی

  • ✅ داده‌های پروکسی به GitHub Secrets اضافه شده‌اند (نه در فایل جریان کار)
  • ✅ متغیرهای NO_PROXY شامل github.com هستند
  • ✅ مرحله بررسی IP برای اشکال‌زدایی اضافه شده است
  • ✅ مدیریت خطاها و منطق retry پیاده‌سازی شده است
  • ✅ نوع پروکسی با وظیفه مطابقت دارد (پروکسی‌های مسکونی برای وب‌سایت‌های محافظت‌شده)
  • ✅ اعلان‌های خطا تنظیم شده‌اند (Telegram، Slack یا ایمیل)
  • ✅ جریان کار به صورت دستی از طریق workflow_dispatch قبل از اضافه کردن زمان‌بندی تست شده است

نتیجه‌گیری

تنظیم پروکسی در GitHub Actions کار سختی نیست اگر رویکرد صحیح را بدانید. نکات کلیدی از این راهنما:

  • متغیرهای محیطی HTTP_PROXY / HTTPS_PROXY — روش عمومی که برای اکثر ابزارها بدون تغییر کد کار می‌کند.
  • GitHub Secrets — تنها مکان صحیح برای ذخیره اعتبارنامه‌های پروکسی.
  • نوع پروکسی مهم است: برای پارسینگ بازارهای محافظت‌شده نیاز به IP‌های مسکونی است، برای پلتفرم‌های تبلیغاتی — موبایل، برای درخواست‌های ساده API پروکسی‌های مرکز داده کافی هستند.
  • منطق retry الزامی است برای پایپ‌لاین‌هایی که بدون نظارت بر اساس زمان‌بندی کار می‌کنند.
  • مرحله بررسی IP در ابتدای جریان کار ساعت‌ها اشکال‌زدایی را صرفه‌جویی می‌کند.

اگر جریان کار GitHub Actions شما با بازارها، پلتفرم‌های تبلیغاتی یا هر خدماتی که دارای حفاظت ضد ربات است کار می‌کند، توصیه می‌کنیم از پروکسی‌های مسکونی استفاده کنید — آن‌ها دارای IP‌های واقعی کاربران خانگی هستند و به طور قابل توجهی کمتر از آدرس‌های ابری سرورهای GitHub مسدود می‌شوند. برای وظایف مرتبط با Facebook Ads، TikTok یا دیگر پلتفرم‌های اجتماعی، بهترین انتخاب پروکسی‌های موبایل با IP‌های اپراتوری هستند — آن‌ها حداکثر سطح اعتماد را از طرف پلتفرم‌ها فراهم می‌کنند.

```