# Skripterstellung mit der REST-API und Ruby

Lernen Sie, wie Sie ein Skript mit dem Octokit.rb-SDK schreiben, um mit der REST-API zu interagieren.

## Über Octokit.rb

Wenn Sie ein Skript mit Ruby für die Interaktion mit der GitHub REST-API schreiben möchten, empfiehlt es sich, GitHub das Octokit.rb SDK zu verwenden. Octokit.rb wird von GitHub betreut. 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](https://github.com/octokit/octokit.rb/#readme).

## 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](/de/enterprise-server@3.22/rest/using-the-rest-api/getting-started-with-the-rest-api).

Sie müssen das `octokit`-Gem installieren und importieren, um die Octokit.rb-Bibliothek nutzen zu können. In diesem Leitfaden werden Importanweisungen gemäß den Ruby-Konventionen verwendet. Weitere Informationen zu verschiedenen Installationsmethoden finden Sie im [Abschnitt „Installation“ der Octokit.rb-Infodatei](https://github.com/octokit/octokit.rb/#installation).

## Instanziieren und Authentifizieren

> \[!WARNING]
> Verwende die Anmeldeinformationen für die Authentifizierung wie ein Kennwort.
>
> Um Ihre Anmeldeinformationen zu schützen, können Sie Ihre Anmeldeinformationen als Geheimnis speichern und Ihr Skript über GitHub Actions ausführen. Weitere Informationen finden Sie unter [Verwenden von Geheimnissen in GitHub-Aktionen](/de/enterprise-server@3.22/actions/how-tos/write-workflows/choose-what-workflows-do/use-secrets).

> Wenn  sind, sollten Sie einen anderen CLI-Dienst verwenden, um Ihre Anmeldeinformationen sicher zu speichern.

### Authentifizieren mit einem personal access token

Wenn Sie die GitHub REST-API für den persönlichen Gebrauch nutzen möchten, können Sie ein personal access token erstellen. Weitere Informationen zum Erstellen eines personal access token finden Sie unter [Verwalten deiner persönlichen Zugriffstoken](/de/enterprise-server@3.22/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens).

Zuerst muss die `octokit`-Bibliothek angefordert werden. Erstellen Sie dann eine Instanz von `Octokit`, indem Sie Ihr personal access token als `access_token`-Option übergeben. Ersetzen Sie im folgenden Beispiel `YOUR-TOKEN` durch Ihre personal access token.

```ruby copy
require 'octokit'

octokit = Octokit::Client.new(access_token: 'YOUR-TOKEN')
```

### Authentifizieren mit einem GitHub App

Wenn Sie die API im Namen einer Organisation oder eines anderen Benutzers verwenden möchten, GitHub empfiehlt die Verwendung einer GitHub App. Wenn ein Endpunkt für GitHub Apps verfügbar ist, gibt die REST-Referenzdokumentation für diesen Endpunkt an, welcher Typ von GitHub App-Token erforderlich ist. Weitere Informationen findest du unter [Registrieren einer GitHub-App](/de/enterprise-server@3.22/apps/creating-github-apps/registering-a-github-app/registering-a-github-app) und [Informationen zur Authentifizierung mit einer GitHub-App](/de/enterprise-server@3.22/apps/creating-github-apps/authenticating-with-a-github-app/about-authentication-with-a-github-app).

Anstatt `octokit` zu benötigen, erstellen Sie eine Instanz von `Octokit::Client`, indem Sie die Informationen Ihrer GitHub App als Optionen übergeben. 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](/de/enterprise-server@3.22/apps/creating-github-apps/authenticating-with-a-github-app/managing-private-keys-for-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 finden Sie unter [REST-API-Endpunkte für GitHub Apps](/de/enterprise-server@3.22/rest/apps/apps). Ersetzen Sie `HOSTNAME` durch den Namen von Ihre GitHub Enterprise Server-Instance.

```ruby copy
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 Sie die API in einem GitHub Actions Workflow verwenden möchten, empfiehlt GitHub, sich bei der integrierten `GITHUB_TOKEN` zu authentifizieren, anstatt ein Token zu erstellen. Sie können dem `GITHUB_TOKEN` mit dem Schlüssel `permissions` Berechtigungen erteilen. Weitere Informationen zu `GITHUB_TOKEN` findest du unter [GITHUB\_TOKEN](/de/enterprise-server@3.22/actions/concepts/security/github_token).

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](/de/enterprise-server@3.22/actions/how-tos/write-workflows/choose-what-workflows-do/use-secrets).

Wenn Sie das `run` Schlüsselwort verwenden, um Ihr Ruby-Skript in Ihren GitHub Actions Workflows auszuführen, können Sie den Wert `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:

```yaml
- 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:

```ruby copy
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 von `Octokit` ohne Authentifizierung zu erstellen, lassen Sie die `access_token`-Option weg.

```ruby copy
require 'octokit'

octokit = Octokit::Client.new
```

## Anfragen stellen

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 für das Ausführen von Anfragen

Um Anforderungen mit der `request`-Methode auszuführen, übergib die HTTP-Methode und den Pfad als erstes Argument. Übergib alle Body-, Query- oder Path-Parameter als zweites Argument in einem Hash. Beispiel: Zum Ausführen einer `GET`-Anforderung an `/repos/{owner}/{repo}/issues` und Übergeben der Parameter `owner`, `repo` und `per_page`:

```ruby copy
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`:

```ruby copy
octokit.request("POST /markdown/raw", text: "Hello **world**", headers: { "content-type" => "text/plain" })
```

### Verwendung von `rest`-Endpunktmethoden zum Ausführen von Anfragen

Jeder REST-API-Endpunkt verfügt über eine zugeordnete `rest`-Endpunktmethode in Octokit. Diese Methoden werden in der Regel in Ihrer IDE zur bequemen Nutzung automatisch vervollständigt. Du kannst beliebige Parameter als ein Hash an die Methode übergeben.

```ruby copy
octokit.rest.issues.list_for_repo(owner: "github", repo: "docs", per_page: 2)
```

### Erstellen paginierter Anfragen

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.

```ruby copy
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.

```ruby copy
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.

```ruby copy
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.

```ruby copy
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](/de/enterprise-server@3.22/rest/using-the-rest-api/using-pagination-in-the-rest-api).

## Abfangen von Fehlern

### Erfassung aller Fehler

Manchmal gibt die GitHub REST-API einen Fehler zurück. 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 Found`und `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:

```ruby copy
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
```

### Handhabung von beabsichtigten Fehlercodes

Manchmal verwendet GitHub einen 4xx-Statuscode, um eine Antwort anzugeben, die keinen Fehler darstellt. 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.

```ruby copy
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 Fehlern bei der Ratenbegrenzung

Wenn ein Ratenlimitfehler angezeigt wird, solltest du die Anforderung nach einer Wartezeit wiederholen. Wenn für Sie ein Ratenlimit gilt, antwortet GitHub mit dem Fehler `403 Forbidden`, und der Wert des Antwort-Headers `x-ratelimit-remaining` ist `"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 Anfrage nach der Zeit, die von `x-ratelimit-reset` angegeben wird, erneut versuchen.

```ruby copy
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)
```

## Verwendung 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.

```ruby copy
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.

```ruby copy
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 anstelle von einer personal access token authentifizieren möchten, würden Sie `App` anstelle von `Octokit` importieren und instanziieren. Weitere Informationen finden Sie unter [Authentifizierung mit einem GitHub App](#authenticating-with-a-github-app) in diesem Leitfaden.

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.

```ruby copy
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}"
```

> \[!NOTE]
> 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 der 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](https://github.com/octokit/octokit.rb/#readme).
* Ausführliche Informationen zu GitHubden verfügbaren REST-API-Endpunkten, einschließlich ihrer Anforderungs- und Antwortstrukturen, finden Sie im [GitHub REST-API-Dokumentation](/de/enterprise-server@3.22/rest).