Skip to main content

Скриптирование с помощью REST API и Ruby

Узнайте, как писать скрипт с помощью пакета SDK octokit.rb для взаимодействия с REST API.

О Octokit.rb

Если вы хотите написать скрипт с помощью Ruby для взаимодействия с REST API GitHub, GitHub рекомендует использовать пакет SDK octokit.rb. Octokit.rb поддерживается GitHub. Пакет SDK реализует рекомендации и упрощает взаимодействие с REST API через Ruby. Octokit.rb работает со всеми современными браузерами, Node.rb и Deno. Дополнительные сведения о Octokit.rb см . в разделе Octokit.rb README.

Необходимые компоненты

В этом руководстве предполагается, что вы знакомы с Ruby и REST API GitHub. Дополнительные сведения о REST API см. в разделе AUTOTITLE.

Чтобы использовать библиотеку Octokit.rb, необходимо установить и импортировать драгоценный камень. В этом руководстве используются инструкции импорта в соответствии с соглашениями Ruby. Дополнительные сведения о различных методах установки см . в разделе установки Octokit.rb README.

Создание экземпляров и проверка подлинности

Предупреждение

Обработайте учетные данные проверки подлинности как пароль.

Чтобы обеспечить безопасность учетных данных, вы можете хранить свои учетные данные в виде секрета и запускать скрипт с помощью GitHub Actions. Дополнительные сведения см. в разделе AUTOTITLE.

Если это невозможно, попробуйте использовать другую службу CLI для безопасного хранения учетных данных.

Проверка подлинности с помощью personal access token

Если вы хотите использовать REST API GitHub для личного использования, можно создать personal access token. Дополнительные сведения о создании personal access tokenсм. в разделе AUTOTITLE.

Сначала требуется библиотека. Затем создайте экземпляр , передав personal access token в качестве параметра. В следующем примере замените данные personal access token.

Ruby
require 'octokit'

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

Проверка подлинности с помощью GitHub App

Если вы хотите использовать API от имени организации или другого пользователя, GitHub рекомендует использовать GitHub App. Если конечная точка доступна для GitHub Apps, справочная документация REST для этой конечной точки будет указывать тип маркера GitHub App. Дополнительные сведения см. в разделе AUTOTITLE и AUTOTITLE.

Вместо необходимости создайте экземпляр , передав данные GitHub Appв качестве параметров. В следующем примере замените идентификатором приложения, закрытым ключом приложения и идентификатором установки приложения, от имени которого требуется пройти проверку подлинности. Идентификатор приложения можно найти и создать закрытый ключ на странице параметров приложения. Дополнительные сведения см. в разделе AUTOTITLE. Идентификатор установки можно получить с помощью конечных точек или конечных точек. Дополнительные сведения см. в разделе AUTOTITLE.{ %ifversion ghes %} Замените именем ваш экземпляр GitHub Enterprise Server.{ % endif %}

Ruby
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)

Проверка подлинности в GitHub Actions

Если вы хотите использовать API в рабочем процессе GitHub Actions, GitHub рекомендует выполнять проверку подлинности с помощью встроенного вместо создания маркера. Вы можете предоставить разрешения для с помощью ключа . Дополнительные сведения см. в разделе AUTOTITLE.

Если рабочий процесс должен получить доступ к ресурсам за пределами репозитория рабочего процесса, вы не сможете использовать . В этом случае сохраните свои учетные данные в виде секрета и замените в приведенных ниже примерах именем секрета. Дополнительные сведения о секретах см. в разделе AUTOTITLE.

Если вы используете ключевое слово для выполнения скрипта Ruby в рабочих процессах GitHub Actions, можно сохранить значение в виде переменной среды. Скрипт может получить доступ к переменной среды как .

Например, этот шаг рабочего процесса сохраняется в переменной среды:

- name: Run script
  env:
    TOKEN: ${{ secrets.GITHUB_TOKEN }}
  run: |
    ruby .github/actions-scripts/use-the-api.rb

Скрипт, который выполняется рабочим процессом для проверки подлинности:

Ruby
require 'octokit'

octokit = Octokit::Client.new(access_token: ENV['TOKEN'])

Создание экземпляров без проверки подлинности

REST API можно использовать без проверки подлинности, хотя у вас будет более низкий предел скорости и не удастся использовать некоторые конечные точки. Чтобы создать экземпляр без проверки подлинности , не передайте этот параметр.

Ruby
require 'octokit'

octokit = Octokit::Client.new

Выполнение запросов

Octokit поддерживает несколько способов выполнения запросов. Метод можно использовать для выполнения запросов, если вы знаете HTTP-команду и путь к конечной точке. Этот метод можно использовать, если вы хотите воспользоваться преимуществами автозаполнения в интегрированной среде разработки и вводе. Для конечных точек с разбивкой на страницы можно использовать метод для запроса нескольких страниц данных.

Использование метода для выполнения запросов

Чтобы использовать метод для выполнения запросов, передайте метод HTTP и путь в качестве первого аргумента. Передайте все параметры текста, запроса или пути в хэш в качестве второго аргумента. Например, чтобы выполнить запрос к и передать параметры, и выполнить следующие параметры:

Ruby
octokit.request("GET /repos/{owner}/{repo}/issues", owner: "github", repo: "docs", per_page: 2)

Метод автоматически передает заголовок. Чтобы передать дополнительные заголовки или другой заголовок, добавьте параметр в хэш, передаваемый в качестве второго аргумента. Значение параметра — хэш с именами заголовков в качестве ключей и значений заголовков в качестве значений. Например, чтобы отправить заголовок со значением :

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

Использование методов конечной точки для выполнения запросов

Каждая конечная точка REST API имеет связанный метод конечной точки в Octokit. Эти методы обычно автоматически заполняются в интегрированной среде разработки для удобства. В метод можно передать любые параметры в виде хэша.

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

Выполнение запросов с разбивкой на страницы

Если конечная точка разбина на страницы и вы хотите получить несколько страниц результатов, можно использовать этот метод. Возвращает следующую страницу результатов, пока не достигнет последней страницы, а затем возвращает все результаты в виде массива. Несколько конечных точек возвращают результаты с разбивкой на страницы в виде массива в объекте, а не возвращать результаты с разбивкой на страницы в виде массива. всегда возвращает массив элементов, даже если необработанный результат был объектом.

Например, следующий пример получает все проблемы из репозитория. Хотя она запрашивает 100 проблем за раз, функция не возвращается до достижения последней страницы данных.

Ruby
issue_data = octokit.paginate("GET /repos/{owner}/{repo}/issues", owner: "github", repo: "docs", per_page: 100)

Метод принимает необязательный блок, который можно использовать для обработки каждой страницы результатов. Это позволяет собирать только нужные данные из ответа. Например, следующий пример продолжает получение результатов до тех пор, пока не будет возвращена проблема, содержащая "test" в заголовке. Для страниц возвращаемых данных хранятся только название проблемы и автор.

Ruby
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

Вместо одновременного получения всех результатов можно использовать для итерации по одной странице за раз. Например, следующий пример извлекает одну страницу результатов за раз и обрабатывает каждый объект из страницы перед получением следующей страницы. После достижения проблемы, включающей "test" в заголовок, скрипт останавливает итерацию и возвращает заголовок проблемы и автор проблемы каждого обработанного объекта. Итератор — это наиболее эффективный метод для получения данных с разбивкой на страницы.

Ruby
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

Этот метод также можно использовать с методами конечной точки. Передайте метод конечной точки в качестве первого аргумента и любые параметры в качестве второго аргумента.

Ruby
iterator = octokit.paginate.iterator(octokit.rest.issues.list_for_repo, owner: "github", repo: "docs", per_page: 100)

Дополнительные сведения о разбиении на страницы см. в разделе AUTOTITLE.

выявления ошибок;

Перехват всех ошибок

Иногда REST API GitHub возвращает ошибку. Например, вы получите ошибку, если срок действия маркера доступа истек или если не указан обязательный параметр. Octokit.rb автоматически повторяет запрос при получении ошибки, отличной от , , и . Если ошибка API возникает даже после повторных попыток, Octokit.rb выдает ошибку, содержащую код состояния HTTP ответа () и заголовки ответа (). Эти ошибки следует обрабатывать в коде. Например, для перехвата ошибок можно использовать блок try/catch:

Ruby
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

Обработка предполагаемых кодов ошибок

Иногда GitHub использует код состояния 4xx для указания ответа без ошибок. Если используется эта конечная точка, можно добавить дополнительную обработку для определенных ошибок. Например, конечная точка вернет объект, если репозиторий не указан. В следующем примере используется ответ, указывающий, что репозиторий не был указан в главной роли. Все остальные коды ошибок рассматриваются как ошибки.

Ruby
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

Обработка ошибок ограничения скорости

Если вы получаете ошибку ограничения скорости, вы можете повторить запрос после ожидания. Если скорость ограничена, GitHub отвечает ошибкой, а значение заголовка ответа будет. Заголовки ответа будут содержать заголовок, который указывает время сброса текущего ограничения скорости в секундах эпохи UTC. После указанного времени можно повторить запрос.

Ruby
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)

Использование ответа

Метод возвращает объект ответа, если запрос выполнен успешно. Объект ответа содержит (текст ответа, возвращаемый конечной точкой), (код ответа HTTP), (URL-адрес запроса) и (хэш, содержащий заголовки ответа). Если не указано иное, текст ответа имеет формат JSON. Некоторые конечные точки не возвращают текст ответа; В этих случаях свойство опущено.

Ruby
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']}"

Аналогичным образом метод возвращает объект ответа. В случае успешного выполнения объект содержит данные, состояние, URL-адрес и заголовки.

Ruby
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']}"

Пример сценария

Ниже приведен полный пример скрипта, использующего Octokit.rb. Скрипт импортирует и создает новый экземпляр . Если вы хотите выполнить проверку подлинности с помощью GitHub App, а не personal access token, вы импортируете и создайте экземпляр вместо него. Дополнительные сведения см. в руководстве по проверке подлинности с помощью GitHub App в этом руководстве.

Функция получает все файлы, измененные для запроса на вытягивание. Функция вызывает функцию . Если любой из файлов, измененных запросом на вытягивание, включен в путь к файлу, функция будет комментировать запрос на вытягивание.

Ruby
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}"

Примечание.

Это просто базовый пример. На практике может потребоваться использовать обработку ошибок и условные проверки для обработки различных сценариев.

Следующие шаги

Дополнительные сведения о работе с API REST API GitHub и Octokit.rb см. в следующих ресурсах:

  • Дополнительные сведения о Octokit.rb см . в документации по Octokit.rb.
  • Подробные сведения о доступных конечных точках REST API % variables.product.company_short %}, включая структуры запросов и ответов, см. в разделе AUTOTITLE.