Über Octokit.rb
Wenn du ein Skript mit Ruby schreiben möchtest, um mit der REST-API von GitHub zu interagieren, empfiehlt GitHub die Verwendung des Octokit.rb-SDK. Octokit.rb wird von GitHub verwaltet. Vom SDK werden bewährte Methoden implementiert, und es erleichtert Ihnen, über Ruby mit der REST-API zu interagieren. Octokit.rb funktioniert mit allen modernen Browsern, Node.rb und Deno. Weitere Informationen zu Octokit.rb findest du in der Octokit.rb-Infodatei.
Voraussetzungen
In diesem Leitfaden wird davon ausgegangen, dass Sie mit Ruby und der GitHub-REST-API vertraut sind. Weitere Informationen zur REST-API findest du unter Erste Schritte mit der REST-API.
Sie müssen den Edelstein octokit installieren und importieren, um die Octokit.rb-Bibliothek nutzen zu können. In diesem Leitfaden werden Importanweisungen gemäß Ruby-Konvention verwendet. Weitere Informationen zu verschiedenen Installationsmethoden finden Sie im Abschnitt „Installation“ der Octokit.rb-Infodatei.
Instanziieren und Authentifizieren
Warnung
Verwende die Anmeldeinformationen für die Authentifizierung wie ein Kennwort.
Zum Schutz deiner Anmeldeinformationen kannst du sie als Geheimnis speichern und dein Skript über GitHub Actions ausführen. Weitere Informationen finden Sie unter Verwenden von Geheimnissen in GitHub-Aktionen.
Du kannst deine Anmeldeinformationen auch als Codespaces-Geheimnis speichern und dein Skript in Codespaces ausführen. Weitere Informationen finden Sie unter Verwalten deiner kontospezifischen Geheimnisse für GitHub Codespaces.
Wenn diese Optionen nicht möglich sind, solltest du einen anderen CLI-Dienst verwenden, um die Anmeldeinformationen sicher zu speichern.
Authentifizieren mit einem personal access token
Wenn Sie die GitHub-REST-API für den privaten Gebrauch nutzen möchten, können Sie ein personal access token erstellen. Weitere Informationen zum Erstellen eines personal access tokens findest du unter Verwalten deiner persönlichen Zugriffstoken.
Zuerst muss die octokit-Bibliothek angefordert werden. Erstellen Sie dann eine Octokit-Instanz durch Weitergabe von personal access token als access_token-Option. Ersetzen Sie YOUR-TOKEN im folgenden Beispiel durch Ihre personal access token.
require 'octokit' octokit = Octokit::Client.new(access_token: 'YOUR-TOKEN')
require 'octokit'
octokit = Octokit::Client.new(access_token: 'YOUR-TOKEN')
Authentifizieren mit einer GitHub App
Wenn du die API im Namen einer Organisation oder eines anderen Benutzers nutzen möchtest, empfiehlt GitHub, dass du eine GitHub App verwendest. Wenn ein Endpunkt für GitHub Apps verfügbar ist, ist in der REST-Referenzdokumentation für diesen Endpunkt angegeben, welche Art von GitHub App-Token erforderlich ist. Weitere Informationen findest du unter Registrieren einer GitHub-App und Informationen zur Authentifizierung mit einer GitHub-App.
Erstellen Sie anstelle einer Anforderung von octokit eine Instanz von Octokit::Client, indem Sie die Informationen von GitHub App als Optionen weitergeben. Ersetzen Sie im folgenden Beispiel APP_ID mit Ihrer App-ID, PRIVATE_KEY mit Ihrem privaten Schlüssel der App und INSTALLATION_ID durch die ID der Installation der App, für die du dich authentifizieren möchtest. Auf der Einstellungsseite für die App findest du die ID der App und kannst einen privaten Schlüssel generieren. Weitere Informationen finden Sie unter Verwalten privater Schlüssel für GitHub-Apps. Eine Installations-ID kannst du mit den Endpunkten GET /users/{username}/installation, GET /repos/{owner}/{repo}/installation oder GET /orgs/{org}/installation abrufen. Weitere Informationen findest du unter REST-API-Endpunkte für GitHub Apps.
require 'octokit' app = Octokit::Client.new( client_id: APP_ID, client_secret: PRIVATE_KEY, installation_id: INSTALLATION_ID ) octokit = Octokit::Client.new(bearer_token: app.create_app_installation.access_token)
require 'octokit'
app = Octokit::Client.new(
client_id: APP_ID,
client_secret: PRIVATE_KEY,
installation_id: INSTALLATION_ID
)
octokit = Octokit::Client.new(bearer_token: app.create_app_installation.access_token)
Authentifizieren in GitHub Actions
Wenn du die API in einem GitHub Actions-Workflow verwenden möchtest, empfiehlt GitHub, dass du dich mit dem integrierten GITHUB_TOKEN authentifizierst, anstatt ein Token zu erstellen. Sie können den GITHUB_TOKEN mit dem Schlüssel permissions Berechtigungen erteilen. Weitere Informationen zu GITHUB_TOKEN findest du unter Verwenden von GITHUB_TOKEN für die Authentifizierung in Workflows.
Wenn in deinem Workflow auf Ressourcen außerhalb des Repositorys des Workflows zugegriffen werden muss, kannst du GITHUB_TOKEN nicht verwenden. Speichere die Anmeldeinformationen in diesem Fall als Geheimnis und ersetze GITHUB_TOKEN in den folgenden Beispielen durch den Namen des Geheimnisses. Weitere Informationen zu Geheimnissen findest du unter Verwenden von Geheimnissen in GitHub-Aktionen.
Wenn du das Schlüsselwort run verwendest, um dein Ruby-Skript in deinen GitHub Actions-Workflows auszuführen, kannst du den Wert von GITHUB_TOKEN als Umgebungsvariable speichern. Vom Skript kann als ENV['VARIABLE_NAME'] auf die Umgebungsvariable zugegriffen werden.
Beispiel: In diesem Workflowschritt wird GITHUB_TOKEN in einer Umgebungsvariable mit der Bezeichnung TOKEN gespeichert:
- name: Run script
env:
TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
ruby .github/actions-scripts/use-the-api.rb
Vom Skript, das vom Workflow ausgeführt wird, wird ENV['TOKEN'] zur Authentifizierung verwendet:
require 'octokit' octokit = Octokit::Client.new(access_token: ENV['TOKEN'])
require 'octokit'
octokit = Octokit::Client.new(access_token: ENV['TOKEN'])
Instanziieren ohne Authentifizierung
Du kannst die REST-API ohne Authentifizierung verwenden, obwohl du dann eine niedrigere Ratenbegrenzung hast und einige Endpunkte nicht verwenden kannst. Um eine Instanz ohne Octokit-Authentifizierung zu erstellen, geben Sie die access_token-Option nicht weiter.
require 'octokit' octokit = Octokit::Client.new
require 'octokit'
octokit = Octokit::Client.new
Ausführen von Anforderungen
Octokit unterstützt mehrere Möglichkeiten, Anforderungen auszuführen. Du kannst die request-Methode verwenden, um Anforderungen auszuführen, wenn du HTTP-Verb und -Pfad für den Endpunkt kennst. Du kannst die rest-Methode verwenden, wenn du die Vorteile der automatischen Vervollständigung in der IDE und bei der Eingabe nutzen möchtest. Für paginierte Endpunkte kannst du die paginate-Methode verwenden, um mehrere Datenseiten anzufordern.
Verwenden der request-Methode zum Ausführen von Anforderungen
Übergebe zum Ausführen von Anforderungen mit der request-Methode HTTP-Methode und -Pfad als erstes Argument. Gib alle Text-, Abfrage- oder Pfadparameter als zweites Argument in ein Hash an. Beispiel: Zum Ausführen einer GET-Anforderung an /repos/{owner}/{repo}/issues und Übergeben der Parameter owner, repo und per_page:
octokit.request("GET /repos/{owner}/{repo}/issues", owner: "github", repo: "docs", per_page: 2)
octokit.request("GET /repos/{owner}/{repo}/issues", owner: "github", repo: "docs", per_page: 2)
Bei der request-Methode wird der Header Accept: application/vnd.github+json automatisch übergeben. Füge zum Übergeben zusätzlicher Header oder eines anderen Accept-Headers dem Objekt eine headers-Option hinzu, die als zweites Argument übergeben wird. Der Wert der Option headers ist ein Hash mit den Headernamen als Schlüssel und den Headerwerten als Werte. Es folgt ein Beispiel zum Senden eines content-type-Headers mit dem Wert text/plain:
octokit.request("POST /markdown/raw", text: "Hello **world**", headers: { "content-type" => "text/plain" })
octokit.request("POST /markdown/raw", text: "Hello **world**", headers: { "content-type" => "text/plain" })
Verwenden von rest-Endpunktmethoden zum Ausführen von Anforderungen
Jeder REST-API-Endpunkt verfügt über eine zugeordnete rest-Endpunktmethode in Octokit. Diese Methoden werden in der Regel in der IDE automatisch vervollständigt. Du kannst beliebige Parameter als ein Hash an die Methode übergeben.
octokit.rest.issues.list_for_repo(owner: "github", repo: "docs", per_page: 2)
octokit.rest.issues.list_for_repo(owner: "github", repo: "docs", per_page: 2)
Ausführen paginierter Anforderungen
Wenn der Endpunkt paginiert ist und du mehr als eine Seite mit Ergebnissen abrufen möchtest, kannst du die paginate-Methode verwenden. paginate ruft die nächste Ergebnisseite ab, bis die letzte Seite erreicht ist, und gibt dann alle Ergebnisse als ein Array zurück. Einige Endpunkte geben paginierte Ergebnisse als ein Array in einem Objekt zurück, anstatt die paginierten Ergebnisse als Array zurückzugeben. paginate gibt immer ein Array aus Elementen zurück, auch wenn das Rohergebnis ein Objekt war.
So werden im folgenden Beispiel alle Issues aus dem Repository github/docs abgerufen. Obwohl 100 Issues gleichzeitig angefordert werden, wird die Funktion erst zurückgegeben, wenn die letzte Datenseite erreicht ist.
issue_data = octokit.paginate("GET /repos/{owner}/{repo}/issues", owner: "github", repo: "docs", per_page: 100)
issue_data = octokit.paginate("GET /repos/{owner}/{repo}/issues", owner: "github", repo: "docs", per_page: 100)
Die paginate-Methode akzeptiert einen optionalen Block, den Sie verwenden können, um jede Seite mit Ergebnissen zu verarbeiten. Auf diese Weise können Sie nur die gewünschten Daten aus der Antwort sammeln. Im folgenden Beispiel werden beispielsweise weiterhin Ergebnisse abgerufen, bis ein Issue zurückgegeben wird, das im Titel „test“ enthält. Für die zurückgegebenen Datenseiten werden nur der Titel und der Autor des Issue gespeichert.
issue_data = octokit.paginate("GET /repos/{owner}/{repo}/issues", owner: "github", repo: "docs", per_page: 100) do |response, done|
response.data.map do |issue|
if issue.title.include?("test")
done.call
end
{ title: issue.title, author: issue.user.login }
end
end
issue_data = octokit.paginate("GET /repos/{owner}/{repo}/issues", owner: "github", repo: "docs", per_page: 100) do |response, done|
response.data.map do |issue|
if issue.title.include?("test")
done.call
end
{ title: issue.title, author: issue.user.login }
end
end
Anstatt alle Ergebnisse gleichzeitig abzurufen, kannst du octokit.paginate.iterator() verwenden, um jeweils eine einzelne Seite zu durchlaufen. So wird im folgenden Beispiel jeweils eine Seite mit Ergebnissen abgerufen und es wird jedes Objekt von der Seite verarbeitet, bevor die nächste Seite abgerufen wird. Sobald ein Issue erreicht ist, das im Titel „Test“ enthält, beendet das Skript die Iteration und gibt Titel und Autor des Issues für jedes verarbeitete Objekt zurück. Der Iterator ist die speichereffizienteste Methode zum Abrufen paginierter Daten.
iterator = octokit.paginate.iterator("GET /repos/{owner}/{repo}/issues", owner: "github", repo: "docs", per_page: 100)
issue_data = []
break_loop = false
iterator.each do |data|
break if break_loop
data.each do |issue|
if issue.title.include?("test")
break_loop = true
break
else
issue_data << { title: issue.title, author: issue.user.login }
end
end
end
iterator = octokit.paginate.iterator("GET /repos/{owner}/{repo}/issues", owner: "github", repo: "docs", per_page: 100)
issue_data = []
break_loop = false
iterator.each do |data|
break if break_loop
data.each do |issue|
if issue.title.include?("test")
break_loop = true
break
else
issue_data << { title: issue.title, author: issue.user.login }
end
end
end
Du kannst die paginate-Methode auch mit den rest-Endpunktmethoden verwenden. Übergeben Sie die rest-Endpunktmethode als erstes Argument und alle Parameter als zweites Argument.
iterator = octokit.paginate.iterator(octokit.rest.issues.list_for_repo, owner: "github", repo: "docs", per_page: 100)
iterator = octokit.paginate.iterator(octokit.rest.issues.list_for_repo, owner: "github", repo: "docs", per_page: 100)
Weitere Informationen zur Paginierung findest du unter Verwenden der Paginierung in der REST-API.
Abfangen von Fehlern
Abfangen aller Fehler
Manchmal wird von der GitHub-REST-API ein Fehler zurückgegeben. Beispielsweise erhältst du eine Fehlermeldung, wenn das Zugriffstoken abgelaufen ist oder wenn du einen erforderlichen Parameter ausgelassen hast. Von Octokit.rb wird die Anforderung automatisch wiederholt, wenn ein anderer Fehler als 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Foundund 422 Unprocessable Entity angezeigt wird. Wenn sogar nach wiederholten Versuchen ein API-Fehler auftritt, wird von Octokit.rb eine Fehlermeldung ausgegeben, die den HTTP-Statuscode der Antwort (response.status) und die Antwortheader (response.headers) enthält. Du musst diese Fehler im Code behandeln. Du kannst beispielsweise einen try/catch-Block verwenden, um Fehler abzufangen:
begin
files_changed = []
iterator = octokit.paginate.iterator("GET /repos/{owner}/{repo}/pulls/{pull_number}/files", owner: "github", repo: "docs", pull_number: 22809, per_page: 100)
iterator.each do | data |
files_changed.concat(data.map {
| file_data | file_data.filename
})
end
rescue Octokit::Error => error
if error.response
puts "Error! Status: #{error.response.status}. Message: #{error.response.data.message}"
end
puts error
end
begin
files_changed = []
iterator = octokit.paginate.iterator("GET /repos/{owner}/{repo}/pulls/{pull_number}/files", owner: "github", repo: "docs", pull_number: 22809, per_page: 100)
iterator.each do | data |
files_changed.concat(data.map {
| file_data | file_data.filename
})
end
rescue Octokit::Error => error
if error.response
puts "Error! Status: #{error.response.status}. Message: #{error.response.data.message}"
end
puts error
end
Behandeln beabsichtigter Fehlercodes
Manchmal wird von GitHub ein 4xx-Statuscode dazu verwendet, eine Nicht-Fehlerantwort anzugeben. Wenn der von dir verwendete Endpunkt dies tut, kannst du zusätzliche Behandlung für bestimmte Fehler hinzufügen. Beispielsweise wird vom Endpunkt GET /user/starred/{owner}/{repo} der Statuscode 404 zurückgegeben, wenn das Repository nicht mit einem Stern versehen ist. Im folgenden Beispiel wird die Antwort 404 verwendet, um anzugeben, dass das Repository nicht mit einem Stern versehen wurde. Alle anderen Fehlercodes werden als Fehler behandelt.
begin
octokit.request("GET /user/starred/{owner}/{repo}", owner: "github", repo: "docs")
puts "The repository is starred by me"
rescue Octokit::NotFound => error
puts "The repository is not starred by me"
rescue Octokit::Error => error
puts "An error occurred while checking if the repository is starred: #{error&.response&.data&.message}"
end
begin
octokit.request("GET /user/starred/{owner}/{repo}", owner: "github", repo: "docs")
puts "The repository is starred by me"
rescue Octokit::NotFound => error
puts "The repository is not starred by me"
rescue Octokit::Error => error
puts "An error occurred while checking if the repository is starred: #{error&.response&.data&.message}"
end
Behandeln von Ratenlimitfehlern
Wenn ein Ratenlimitfehler angezeigt wird, solltest du die Anforderung nach einer Wartezeit wiederholen. Wenn die Rate begrenzt ist, antwortet GitHub mit dem Fehler 403 Forbidden, und der Wert des Antwortheaders x-ratelimit-remaining lautet "0". Die Antwortheader enthalten einen x-ratelimit-reset-Header, in dem der Zeitpunkt (in UTC-Epochensekunden) angegeben ist, zu dem das aktuelle Ratenlimitfenster zurückgesetzt wird. Du kannst die Anforderung nach der Zeit wiederholen, die im Header x-ratelimit-reset angegeben ist.
def request_retry(route, parameters)
begin
response = octokit.request(route, parameters)
return response
rescue Octokit::RateLimitExceeded => error
reset_time_epoch_seconds = error.response.headers['x-ratelimit-reset'].to_i
current_time_epoch_seconds = Time.now.to_i
seconds_to_wait = reset_time_epoch_seconds - current_time_epoch_seconds
puts "You have exceeded your rate limit. Retrying in #{seconds_to_wait} seconds."
sleep(seconds_to_wait)
retry
rescue Octokit::Error => error
puts error
end
end
response = request_retry("GET /repos/{owner}/{repo}/issues", owner: "github", repo: "docs", per_page: 2)
def request_retry(route, parameters)
begin
response = octokit.request(route, parameters)
return response
rescue Octokit::RateLimitExceeded => error
reset_time_epoch_seconds = error.response.headers['x-ratelimit-reset'].to_i
current_time_epoch_seconds = Time.now.to_i
seconds_to_wait = reset_time_epoch_seconds - current_time_epoch_seconds
puts "You have exceeded your rate limit. Retrying in #{seconds_to_wait} seconds."
sleep(seconds_to_wait)
retry
rescue Octokit::Error => error
puts error
end
end
response = request_retry("GET /repos/{owner}/{repo}/issues", owner: "github", repo: "docs", per_page: 2)
Verwenden der Antwort
Bei der Methode request wird ein Antwortobjekt zurückgegeben, wenn die Anforderung erfolgreich war. Die Antwort enthält data (der vom Endpunkt zurückgegebene Antworttext), status (der HTTP-Antwortcode), url (die URL der Anforderung) und headers (ein Hash, das die Antwortheader enthält). Sofern nicht anders angegeben, verwendet der Antworttext das JSON-Format. Von einigen Endpunkten wird kein Antworttext zurückgegeben. In diesen Fällen wird die Eigenschaft data weggelassen.
response = octokit.request("GET /repos/{owner}/{repo}/issues/{issue_number}", owner: "github", repo: "docs", issue_number: 11901)
puts "The status of the response is: #{response.status}"
puts "The request URL was: #{response.url}"
puts "The x-ratelimit-remaining response header is: #{response.headers['x-ratelimit-remaining']}"
puts "The issue title is: #{response.data['title']}"
response = octokit.request("GET /repos/{owner}/{repo}/issues/{issue_number}", owner: "github", repo: "docs", issue_number: 11901)
puts "The status of the response is: #{response.status}"
puts "The request URL was: #{response.url}"
puts "The x-ratelimit-remaining response header is: #{response.headers['x-ratelimit-remaining']}"
puts "The issue title is: #{response.data['title']}"
Ebenso gibt die paginate-Methode ein Antwortobjekt zurück. Wenn request erfolgreich war, enthält das response-Objekt Daten, Status, URL und Header.
response = octokit.paginate("GET /repos/{owner}/{repo}/issues", owner: "github", repo: "docs", per_page: 100)
puts "#{response.data.length} issues were returned"
puts "The title of the first issue is: #{response.data[0]['title']}"
response = octokit.paginate("GET /repos/{owner}/{repo}/issues", owner: "github", repo: "docs", per_page: 100)
puts "#{response.data.length} issues were returned"
puts "The title of the first issue is: #{response.data[0]['title']}"
Beispielskript
Hier sehen Sie ein vollständiges Beispielskript, in dem Octokit.rb verwendet wird. Durch das Skript wird Octokit importiert, und es wird eine neue Instanz von Octokit erstellt. Wenn Sie sich mit einer GitHub App statt durch ein personal access token authentifizieren möchten, würden Sie App anstelle von Octokit importieren und instanziieren. Weitere Informationen findest du unter Authentifizieren mit einer GitHub App in diesem Guide.
Durch die Funktion get_changed_files werden alle Dateien abgerufen, die für einen Pull Request geändert wurden. Durch die Funktion comment_if_data_files_changed wird die Funktion get_changed_files aufgerufen. Wenn eine der Dateien, die vom Pull Request geändert wurden, /data/ im Dateipfad enthält, wird der Pull Request von der Funktion kommentiert.
require "octokit"
octokit = Octokit::Client.new(access_token: "YOUR-TOKEN")
def get_changed_files(octokit, owner, repo, pull_number)
files_changed = []
begin
iterator = octokit.paginate.iterator("GET /repos/{owner}/{repo}/pulls/{pull_number}/files", owner: owner, repo: repo, pull_number: pull_number, per_page: 100)
iterator.each do | data |
files_changed.concat(data.map {
| file_data | file_data.filename
})
end
rescue Octokit::Error => error
if error.response
puts "Error! Status: #{error.response.status}. Message: #{error.response.data.message}"
end
puts error
end
files_changed
end
def comment_if_data_files_changed(octokit, owner, repo, pull_number)
changed_files = get_changed_files(octokit, owner, repo, pull_number)
if changed_files.any ? {
| file_name | /\/data\//i.match ? (file_name)
}
begin
comment = octokit.create_pull_request_review_comment(owner, repo, pull_number, "It looks like you changed a data file. These files are auto-generated. \n\nYou must revert any changes to data files before your pull request will be reviewed.")
comment.html_url
rescue Octokit::Error => error
if error.response
puts "Error! Status: #{error.response.status}. Message: #{error.response.data.message}"
end
puts error
end
end
end
# Example usage
owner = "github"
repo = "docs"
pull_number = 22809
comment_url = comment_if_data_files_changed(octokit, owner, repo, pull_number)
puts "A comment was added to the pull request: #{comment_url}"
require "octokit"
octokit = Octokit::Client.new(access_token: "YOUR-TOKEN")
def get_changed_files(octokit, owner, repo, pull_number)
files_changed = []
begin
iterator = octokit.paginate.iterator("GET /repos/{owner}/{repo}/pulls/{pull_number}/files", owner: owner, repo: repo, pull_number: pull_number, per_page: 100)
iterator.each do | data |
files_changed.concat(data.map {
| file_data | file_data.filename
})
end
rescue Octokit::Error => error
if error.response
puts "Error! Status: #{error.response.status}. Message: #{error.response.data.message}"
end
puts error
end
files_changed
end
def comment_if_data_files_changed(octokit, owner, repo, pull_number)
changed_files = get_changed_files(octokit, owner, repo, pull_number)
if changed_files.any ? {
| file_name | /\/data\//i.match ? (file_name)
}
begin
comment = octokit.create_pull_request_review_comment(owner, repo, pull_number, "It looks like you changed a data file. These files are auto-generated. \n\nYou must revert any changes to data files before your pull request will be reviewed.")
comment.html_url
rescue Octokit::Error => error
if error.response
puts "Error! Status: #{error.response.status}. Message: #{error.response.data.message}"
end
puts error
end
end
end
# Example usage
owner = "github"
repo = "docs"
pull_number = 22809
comment_url = comment_if_data_files_changed(octokit, owner, repo, pull_number)
puts "A comment was added to the pull request: #{comment_url}"
Hinweis
Dies ist nur ein einfaches Beispiel. In der Praxis sollten Sie die Fehlerbehandlung und bedingte Prüfungen verwenden, um verschiedene Szenarien zu bearbeiten.
Nächste Schritte
Weitere Informationen zum Arbeiten mit den GitHub-REST-API und Octokit.rb finden Sie in den folgenden Ressourcen:
- Weitere Informationen zu Octokit.rb finden Sie in der Dokumentation zu Octokit.js.
- Ausführliche Informationen zu GitHub-verfügbaren REST-API-Endpunkten, einschließlich ihrer Anforderungs- und Antwortstrukturen, finden Sie im Dokumentation zu GitHub-REST-API.