العودة إلى المدونة

البروكسي في GitHub Actions وCI/CD: دليل كامل مع أمثلة على الكود

نتعرف على كيفية توصيل البروكسي بسير عمل GitHub Actions - حتى لا تتعرض المهام التلقائية للحظر وتعمل من المنطقة المطلوبة.

📅٦ صفر ١٤٤٨ هـ
```html

GitHub Actions هي أداة قوية لأتمتة المهام: حيث تقوم بتشغيل الاختبارات، ونشر التطبيقات، وجمع البيانات، وتنفيذ العشرات من المهام الأخرى. ولكن بمجرد أن يبدأ سير العمل في الوصول إلى الموارد الخارجية - مثل الأسواق، ومنصات الإعلانات، وواجهات برمجة التطبيقات الأجنبية - فإنه يواجه على الفور حظرًا جغرافيًا وحدودًا على IP. الحل الوحيد هو توصيل بروكسي مباشرة في خط الأنابيب.

لماذا بروكسي في GitHub Actions: سيناريوهات حقيقية

تستخدم العديد من الفرق GitHub Actions ليس فقط لنشر الشيفرة، ولكن أيضًا لأتمتة المهام التجارية: مراقبة أسعار المنافسين، جمع البيانات من الأسواق، التحقق التلقائي من حسابات الإعلانات، واختبار المواقع من مناطق مختلفة. تجمع كل هذه المهام مشكلة واحدة - حيث أن runner GitHub Actions لديه IP ثابت من نطاق Microsoft Azure، والعديد من الخدمات تحظره أو تحد من الوصول إليه.

إليك بعض المواقف المحددة التي لا يمكن الاستغناء فيها عن البروكسي:

  • جمع البيانات من Wildberries وOzon وAvito - لقد أدرجت هذه المنصات نطاقات IP لمزودي الخدمات السحابية في القوائم السوداء منذ فترة طويلة. سيتم حظر الطلب من runner GitHub Actions أو سيتلقى CAPTCHA بعد 2-3 محاولة.
  • اختبار جغرافي مستهدف - يقوم المسوقون ومهندسو الجودة بالتحقق من كيفية ظهور الموقع أو الإعلان للمستخدمين من موسكو أو برلين أو نيويورك. بدون بروكسي، سيظل runner "يرى" المحتوى لمنطقة واحدة فقط.
  • العمل مع واجهات برمجة التطبيقات المحدودة حسب المنطقة - تعيد بعض واجهات برمجة التطبيقات (مثل الإصدارات الإقليمية من 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 على مستوى الوظيفة، ستستخدم جميع الخطوات داخل هذه الوظيفة البروكسي.
  • الـ 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 متوسطة قصوى - IP من شركات الاتصالات
بروكسي مركز البيانات اختبارات التكامل، الطلبات على واجهات برمجة التطبيقات غير المحمية، الحمل العالي عالية متوسطة

قاعدة عملية: إذا كان سير العمل الخاص بك يجمع البيانات من Wildberries أو Ozon أو أي أسواق أخرى محمية ضد الروبوتات - استخدم البروكسي السكنية. إذا كنت تختبر حسابات إعلانات Facebook Ads أو TikTok Ads - استخدم البروكسي الموبايل. للاختبارات البسيطة وطلبات واجهات برمجة التطبيقات المفتوحة، يكفي استخدام بروكسي مركز البيانات: فهي أسرع وأرخص.

💡 مهم حول البروتوكولات

من الأفضل استخدام بروكسي HTTP/HTTPS لـ GitHub Actions - حيث تدعمها معظم الأدوات بدون إعدادات إضافية. يعمل 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 وport)، فإن التنسيق يصبح أبسط:

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

إذا تم تعيين متغيرات البيئة على مستوى الوظيفة (كما هو موضح أعلاه)، فإن 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(`Request failed: ${error.message}`);
    throw error;
  }
}

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

بالنسبة لـ npm-commands (على سبيل المثال، إذا كان 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 }}

🔒 تدابير أمان إضافية

  • استخدم Secrets البيئة بدلاً من Secrets المستودع، إذا كانت البيئات المختلفة (التجريبية/الإنتاج) تستخدم بروكسيات مختلفة
  • حدد الوصول إلى الأسرار عبر قواعد حماية البيئة - تطلب تأكيدًا يدويًا للإنتاج
  • قم بتدوير بيانات اعتماد البروكسي بانتظام - غير كلمات المرور كل 30-90 يومًا
  • لا تطبع قيم الأسرار في السجلات عبر echo - تقوم GitHub بإخفائها تلقائيًا، ولكن من الأفضل عدم المخاطرة

إذا كنت تستخدم بروكسيات دوارة (عندما يتغير IP مع كل طلب أو حسب الجدول الزمني)، غالبًا ما يكفي تخزين نقطة نهاية واحدة فقط - حيث يدير مزود البروكسي مجموعة IP. في هذه الحالة، ستكون الأسرار تحتوي فقط على مضيف واحد ومنفذ بوابة التدوير.

دوران البروكسي ومعالجة الأخطاء في خط الأنابيب

حتى البروكسيات عالية الجودة قد تفشل أحيانًا: قد يقع IP في حظر مؤقت، أو قد تنقطع الجلسة، أو قد لا يستجيب الخادم. بالنسبة لخطوط CI/CD التي تعمل تلقائيًا بدون إشراف، من المهم التفكير في معالجة مثل هذه الحالات.

استراتيجية 1: إعادة المحاولة بنفس البروكسي

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"Proxy failed: {e}, trying next...")
    raise Exception("All proxies exhausted")

استراتيجية 3: استخدام نقطة نهاية دوارة

الخيار الأسهل هو استخدام مزود بروكسي مع بوابة دوارة واحدة. في هذه الحالة، تتصل بعنوان واحد، ويقوم المزود تلقائيًا بتوزيع IPs مختلفة من المجموعة. لا حاجة لأي منطق تدوير في الكود - يكفي سطر واحد من الاتصال.

سيناريوهات حقيقية: جمع البيانات، الاختبارات، مراقبة الأسعار

دعونا نلقي نظرة على ثلاث سيناريوهات محددة تتكرر غالبًا مع الفرق التي تستخدم GitHub Actions مع البروكسي.

السيناريو 1: مراقبة أسعار Wildberries يوميًا

يقوم البائعون في الأسواق غالبًا بإعداد جمع تلقائي لأسعار المنافسين. يتم تشغيل سير العمل وفقًا لجدول زمني (على سبيل المثال، كل صباح في الساعة 7:00)، ويجمع البيانات ويخزنها في 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: اختبار الموقع المستهدف جغرافيًا

يستخدم المسوقون وفرق الجودة البروكسي للتحقق من كيفية ظهور الموقع أو الإعلان للمستخدمين من مدن مختلفة. هذا مهم بشكل خاص للتحقق من الأسعار الإقليمية والمحتوى وإعادة التوجيهات.

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 من نطاقات Azure إلى إجراء تحقق أمني إضافي - يساعد البروكسي في تجاوز ذلك.

name: Ad Account Health Check

on:
  schedule:
    - cron: '*/30 6-22 * * *'  # كل 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 للتصحيح
  • ✅ تم تنفيذ معالجة الأخطاء ومنطق إعادة المحاولة
  • ✅ نوع البروكسي يتناسب مع المهمة (بروكسي سكنية للمواقع المحمية)
  • ✅ تم إعداد إشعارات الأخطاء (Telegram أو Slack أو البريد الإلكتروني)
  • ✅ تم اختبار سير العمل يدويًا عبر workflow_dispatch قبل إضافة الجدول الزمني

الخاتمة

إعداد البروكسي في GitHub Actions ليست مهمة صعبة إذا كنت تعرف النهج الصحيح. الاستنتاجات الرئيسية من هذا الدليل:

  • متغيرات البيئة HTTP_PROXY / HTTPS_PROXY - طريقة شاملة تعمل لمعظم الأدوات دون تغيير الكود.
  • GitHub Secrets - المكان الصحيح الوحيد لتخزين بيانات اعتماد البروكسي.
  • نوع البروكسي مهم: لجمع البيانات من الأسواق المحمية، تحتاج إلى IP سكنية، ولمنصات الإعلانات - موبايل، ولطلبات واجهات برمجة التطبيقات البسيطة، يمكن استخدام بروكسي مركز البيانات.
  • منطق إعادة المحاولة إلزامي للخطوط التي تعمل بدون إشراف وفقًا للجدول الزمني.
  • خطوة التحقق من IP في بداية سير العمل ستوفر ساعات من التصحيح.

إذا كان سير العمل الخاص بك في GitHub Actions يعمل مع الأسواق أو منصات الإعلانات أو أي خدمات محمية ضد الروبوتات، نوصي باستخدام بروكسي سكنية - حيث تحتوي على IP حقيقية لمستخدمين من المنازل وتسبب حظرًا أقل بكثير مقارنةً بالعناوين السحابية لخوادم GitHub. بالنسبة للمهام المتعلقة بـ Facebook Ads أو TikTok أو أي منصات اجتماعية أخرى، سيكون الخيار الأمثل هو بروكسي موبايل مع IP من شركات الاتصالات - حيث توفر أعلى مستوى من الثقة من قبل المنصات.

```