نظرة عامة على GitHub REST API
مكتبة PyGitHub، ورموز الوصول الشخصية، وحدود معدل API
نظرة عامة على GitHub REST API درس مجاني في AI Agents على CoddyKit. هذا هو الدرس 1 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في AI Agents، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة AI Agents 4 دروس في المجموع.
PyGitHub — عميل Python لـ GitHub
PyGitHub هي مكتبة Python الأكثر شيوعًا لواجهة GitHub REST API. وهي تغلف واجهة HTTP API الخام ضمن كائنات Python تمثل المستودعات والمشكلات وطلبات السحب وعمليات الإيداع والمستخدمين. تبدأ تقريبًا كل مهمة لأتمتة GitHub باستخدام Github(token=) وg.get_repo().
# Install: pip install PyGitHub
from github import Github
import os
# Authenticate with a personal access token
g = Github(token=os.environ['GITHUB_TOKEN'])
# Get the authenticated user
user = g.get_user()
print(f'Logged in as: {user.login}')
print(f'Name: {user.name}')
print(f'Public repos: {user.public_repos}')
# Get a specific repository
repo = g.get_repo('octocat/Hello-World')
print(f'Repo: {repo.full_name}')
print(f'Stars: {repo.stargazers_count}')المصادقة: رمز وصول شخصي
أبسط طرق المصادقة هي رمز الوصول الشخصي (PAT) — وهو رمز طويل الأمد مرتبط بحسابكم على GitHub. أنشئوه من github.com → الإعدادات → إعدادات المطور → رموز الوصول الشخصية. خزّنوه في متغير بيئة، ولا تضعوه في التعليمة البرمجية مطلقًا. استخدموا رموز PAT دقيقة الصلاحيات لتحسين الأمان (مع تقييدها بمستودعات محددة).
from github import Github, Auth
import os
# Method 1: Classic token (works with PyGitHub)
token = os.environ['GITHUB_TOKEN']
g = Github(token=token)
# Method 2: Auth object (recommended for PyGitHub >= 1.59)
auth = Auth.Token(os.environ['GITHUB_TOKEN'])
g = Github(auth=auth)
# Test authentication
try:
user = g.get_user()
print(f'Authenticated as {user.login}')
except Exception as e:
print(f'Auth failed: {e}')
print('Check: Is GITHUB_TOKEN set? Has it expired?')
g.close() # close the connection when doneالمصادقة باستخدام تطبيق GitHub
بالنسبة إلى الوكلاء في بيئة الإنتاج، يُفضَّل استخدام تطبيقات GitHub بدلًا من رموز PAT. فهي توفر أذونات دقيقة، ويمكن تثبيتها على مستودعات محددة، وتستخدم رموز تثبيت قصيرة الأمد تُجدَّد تلقائيًا. استخدموا github.GithubIntegration لإنشاء رموز التثبيت.
import os
import github
APP_ID = os.environ['GITHUB_APP_ID']
PRIVATE_KEY = os.environ['GITHUB_APP_PRIVATE_KEY'] # PEM content
INSTALLATION_ID = os.environ['GITHUB_INSTALLATION_ID']
# Create GitHub App client
auth = github.Auth.AppAuth(APP_ID, PRIVATE_KEY)
gi = github.GithubIntegration(auth=auth)
# Get installation access token (expires in 1 hour)
installation = gi.get_installation(int(INSTALLATION_ID))
access_token = gi.get_access_token(int(INSTALLATION_ID))
# Use the token with a standard Github client
g = github.Github(token=access_token.token)
print(f'App authenticated, token expires: {access_token.expires_at}')حدود المعدل: 5,000 طلب في الساعة
تسمح GitHub REST API للمستخدمين الذين تمت مصادقتهم بإجراء 5,000 طلب في الساعة. يُحتسب كل استدعاء لواجهة API (حتى الاستدعاءات المقسمة إلى صفحات). تحققوا من الحصة المتبقية قبل تشغيل العمليات المجمعة — فعند نفادها، تُرجع جميع الطلبات الحالة 403 Forbidden إلى أن يُعاد ضبط حد المعدل.
from github import Github
import os
g = Github(token=os.environ['GITHUB_TOKEN'])
# Check current rate limit status
rate_limit = g.get_rate_limit()
core = rate_limit.core
print(f'Remaining: {core.remaining}/{core.limit} requests')
print(f'Resets at: {core.reset}')
# Calculate time until reset
import datetime
now = datetime.datetime.utcnow()
reset_in = (core.reset.replace(tzinfo=None) - now).seconds
print(f'Reset in: {reset_in // 60}m {reset_in % 60}s')
# Check before heavy operations
if core.remaining < 100:
print('WARNING: Rate limit nearly exhausted!')الحصول على كائن مستودع
يُعد كائن repo نقطة البداية لمعظم عمليات GitHub تقريبًا. احصلوا عليه باستخدام g.get_repo('owner/name'). ويحتوي على بيانات وصفية (عدد النجوم، والتفرعات، والوصف، ومستوى الظهور) وطرق للوصول إلى المشكلات وطلبات السحب وعمليات الإيداع والإصدارات وغير ذلك.
from github import Github
import os
g = Github(token=os.environ['GITHUB_TOKEN'])
repo = g.get_repo('myorg/myrepo')
# Repository metadata
print(f'Full name: {repo.full_name}')
print(f'Description: {repo.description}')
print(f'Default branch: {repo.default_branch}')
print(f'Stars: {repo.stargazers_count}')
print(f'Forks: {repo.forks_count}')
print(f'Open issues: {repo.open_issues_count}')
print(f'Private: {repo.private}')
print(f'Language: {repo.language}')
print(f'Created: {repo.created_at}')
print(f'Last push: {repo.pushed_at}')تقسيم صفحات API — PaginatedList
تُرجع استدعاءات GitHub API التي تعيد عددًا كبيرًا من العناصر (المشكلات وعمليات الإيداع وطلبات السحب) كائنًا من نوع PaginatedList. يمكنكم التكرار عليه كما تفعلون مع قائمة عادية — إذ تجلب PyGitHub الصفحات تلقائيًا أثناء التكرار. لكن استدعاء len() على PaginatedList يجلب جميع الصفحات، وقد يكون ذلك مكلفًا.
from github import Github
import os
g = Github(token=os.environ['GITHUB_TOKEN'])
repo = g.get_repo('myorg/myrepo')
# PaginatedList: fetch pages lazily as you iterate
issues = repo.get_issues(state='open') # returns PaginatedList
# Iterate — fetches pages 30 at a time automatically
for issue in issues:
print(f'#{issue.number}: {issue.title}')
# Get first N items without fetching everything
first_10 = list(issues[:10]) # only fetches first page
# Count (WARNING: fetches ALL pages)
total_open = issues.totalCount # uses the count from API metadata, not iterationمعالجة استثناءات تجاوز حد المعدل
عند تجاوز حد المعدل، تثير PyGitHub الاستثناء github.GithubException.RateLimitExceededException. عالجوه بالتحقق من وقت إعادة الضبط والانتظار حتى يُعاد ضبط الحد. أدرجوا ذلك في غلاف لإعادة المحاولة لجعل أي استدعاء إلى GitHub قادرًا على تحمّل الأعطال.
from github import Github
from github.GithubException import RateLimitExceededException
import os
import time
import datetime
g = Github(token=os.environ['GITHUB_TOKEN'])
def github_call_with_rate_limit(func, *args, **kwargs):
while True:
try:
return func(*args, **kwargs)
except RateLimitExceededException:
rate_limit = g.get_rate_limit()
reset_time = rate_limit.core.reset.replace(tzinfo=None)
now = datetime.datetime.utcnow()
wait_seconds = (reset_time - now).total_seconds() + 10
print(f'Rate limit exceeded. Sleeping {wait_seconds:.0f}s until reset...')
time.sleep(max(wait_seconds, 1))
# Usage
repo = github_call_with_rate_limit(
g.get_repo, 'myorg/myrepo'
)البحث في GitHub
استخدموا g.search_issues() وg.search_repositories() وg.search_code() لإجراء بحث GitHub عبر جميع المستودعات العامة (ومستودعاتكم الخاصة). تستخدم هذه الاستدعاءات Search API، التي لها حد معدل منفصل يبلغ 30 طلبًا في الدقيقة.
from github import Github
import os
g = Github(token=os.environ['GITHUB_TOKEN'])
# Search issues across all your repos
results = g.search_issues(
query='is:open is:issue label:bug user:myorg',
sort='created',
order='desc'
)
print(f'Found {results.totalCount} open bugs')
for issue in results[:10]:
print(f'{issue.repository.full_name}#{issue.number}: {issue.title}')
# Search for repos using a specific package
repos = g.search_repositories(
query='topic:machine-learning language:python stars:>100'
)
for repo in repos[:5]:
print(f'{repo.full_name}: {repo.stargazers_count} stars')العمل مع مستودعات متعددة
غالبًا ما تحتاج الوكلاء إلى العمل عبر مستودعات متعددة في مؤسسة واحدة. استخدموا g.get_organization() لسرد جميع المستودعات في مؤسسة، ثم عالجوها ضمن حلقة تكرار. صفّوا النتائج حسب اللغة أو حالة الأرشفة أو تاريخ النشاط لتجنب معالجة المستودعات غير النشطة.
from github import Github
import os
import datetime
g = Github(token=os.environ['GITHUB_TOKEN'])
org = g.get_organization('myorg')
# Get all active Python repos
cutoff = datetime.datetime.now() - datetime.timedelta(days=180)
active_repos = [
repo
for repo in org.get_repos(type='all')
if (
not repo.archived
and repo.language == 'Python'
and repo.pushed_at
and repo.pushed_at.replace(tzinfo=None) > cutoff
)
]
print(f'Active Python repos: {len(active_repos)}')
for repo in active_repos[:5]:
print(f' {repo.name}: last push {repo.pushed_at.date()}')قراءة محتوى ملف من مستودع
استخدموا repo.get_contents(path) لقراءة أي ملف من مستودع. يكون المحتوى مشفّرًا بترميز base64، لكن PyGitHub يفك ترميزه تلقائيًا عبر الخاصية .decoded_content. حدّدوا فرعًا أو SHA لعملية إيداع باستخدام المعامل ref.
from github import Github
import os
g = Github(token=os.environ['GITHUB_TOKEN'])
repo = g.get_repo('myorg/myrepo')
# Read a file from the default branch
contents = repo.get_contents('README.md')
readme_text = contents.decoded_content.decode('utf-8')
print(f'README ({len(readme_text)} chars):')
print(readme_text[:200])
# Read from a specific branch
requirements = repo.get_contents(
'requirements.txt',
ref='feature/new-deps'
)
deps = requirements.decoded_content.decode('utf-8')
print('Dependencies:', deps[:300])معالجة استثناءات GitHub الشائعة
تثير PyGitHub الاستثناء GithubException لجميع أخطاء API. ومن الفئات الفرعية الشائعة: UnknownObjectException (404 — لم يُعثر على المستودع أو المشكلة)، وBadCredentialsException (401 — الرمز غير صالح)، وRateLimitExceededException (403 — تم تجاوز حد المعدل). احرصوا دائمًا على التقاط هذه الاستثناءات بشكل محدد.
from github import Github
from github.GithubException import (
GithubException, UnknownObjectException,
BadCredentialsException, RateLimitExceededException
)
import os
g = Github(token=os.environ['GITHUB_TOKEN'])
def get_repo_safely(repo_full_name):
try:
return g.get_repo(repo_full_name)
except BadCredentialsException:
print('ERROR: GitHub token is invalid or expired')
return None
except UnknownObjectException:
print(f'ERROR: Repo not found: {repo_full_name}')
print('Check: typo in name? Private repo you can\'t access?')
return None
except RateLimitExceededException:
print('ERROR: GitHub rate limit exceeded, retry later')
return None
except GithubException as e:
print(f'GitHub API error {e.status}: {e.data}')
return Noneتحقق سريع: حد المعدل
اختبروا مدى فهمكم لحدود معدل GitHub API.
خلاصة GitHub REST API
يمكنكم الآن الاتصال بـ GitHub باستخدام PyGitHub:
- Github(token=) أو Github(auth=Auth.Token(...)) للمصادقة باستخدام PAT
- استخدام تطبيقات GitHub مع
GithubIntegrationللوكلاء في بيئة الإنتاج ذوي الأذونات الدقيقة - حد المعدل: 5,000 طلب في الساعة؛ تحققوا منه باستخدام
g.get_rate_limit()؛ وعالجواRateLimitExceededException - PaginatedList: التكرار بطريقة كسولة؛ استخدموا
.totalCountللحصول على الأعداد دون جلب جميع الصفحات - g.get_repo('owner/name') — نقطة الدخول إلى العمليات على مستوى المستودع
- التقطوا
UnknownObjectException(404) وBadCredentialsException(401) بشكل صريح
الأسئلة الشائعة
هل درس «نظرة عامة على GitHub REST API» مجاني؟
نعم — نص درس «نظرة عامة على GitHub REST API» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة AI Agents، انتقل إلى CoddyKit PRO. تتضمن دورة AI Agents 4 دروس في المجموع.
ماذا ستتعلم في «نظرة عامة على GitHub REST API»؟
مكتبة PyGitHub، ورموز الوصول الشخصية، وحدود معدل API تتمرن على AI Agents مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ AI Agents؟
لا تُشترط خبرة سابقة. AI Agents على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 1 من أصل 4.
كم من الوقت يستغرق درس «نظرة عامة على GitHub REST API»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس AI Agents هذا؟
نعم. كل درس في AI Agents يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- نظرة عامة على GitHub REST API
- عرض المشكلات وإدارتها
- تعليقات المراجعة الآلية لـ PR
- تحليل سجل الالتزامات والفروق