{"meta":{"title":"Scripts com a API REST e o Ruby","intro":"Saiba como escrever um script usando o SDK do Octokit.rb para interagir com a API REST.","product":"API REST","breadcrumbs":[{"href":"/pt/rest","title":"API REST"},{"href":"/pt/rest/guides","title":"Guias"},{"href":"/pt/rest/guides/scripting-with-the-rest-api-and-ruby","title":"Script com Ruby"}],"documentType":"article"},"body":"# Scripts com a API REST e o Ruby\n\nSaiba como escrever um script usando o SDK do Octokit.rb para interagir com a API REST.\n\n## Sobre o Octokit.rb\n\nSe você quiser escrever um script usando Ruby para interagir com a GitHub API REST, GitHub recomenda que você use o SDK octokit.rb. Octokit.rb é mantido por GitHub. O SDK implementa as melhores práticas e facilita a interação com a API REST por meio do Ruby. O Octokit.rb funciona com todos os navegadores modernos, Node.rb e Deno. Para obter mais informações sobre o Octokit.rb, confira o arquivo [LEIAME do Octokit.rb](https://github.com/octokit/octokit.rb/#readme).\n\n## Pré-requisitos\n\nEste guia pressupõe que você esteja familiarizado com o Ruby e a GitHub API REST. Para obter informações sobre a API REST, confira [Introdução à API REST](/pt/rest/using-the-rest-api/getting-started-with-the-rest-api).\n\nVocê deve instalar e importar o gem `octokit` para usar a biblioteca Octokit.rb. Este guia usa instruções de importação de acordo com as convenções do Ruby. Para obter mais informações sobre os diferentes métodos de instalação, consulte a [seção Instalação do LEIAME do Octokit.rb](https://github.com/octokit/octokit.rb/#installation).\n\n## Instanciação e autenticação\n\n> \\[!WARNING]\n> Trate suas credenciais de autenticação como uma senha.\n>\n> Para manter suas credenciais seguras, você pode armazenar suas credenciais como segredo e executar seu script por meio de GitHub Actions. Para saber mais, confira [Usar segredos em ações do GitHub](/pt/actions/how-tos/write-workflows/choose-what-workflows-do/use-secrets).\n\n> Você também pode armazenar suas credenciais como segredo Codespaces e executar seu script em Codespaces. Para saber mais, confira [Gerenciando seus segredos específicos da conta no GitHub Codespaces](/pt/codespaces/managing-your-codespaces/managing-your-account-specific-secrets-for-github-codespaces).\n\n> Se essas opções não forem possíveis usar outro serviço da CLI para armazenar suas credenciais com segurança.\n\n### Autenticando com um personal access token\n\nSe você quiser usar a GitHub API REST para uso pessoal, poderá criar uma personal access token. Para obter mais informações sobre como criar um personal access token, consulte [Gerenciar seus tokens de acesso pessoal](/pt/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens).\n\nPrimeiro, exija a biblioteca `octokit`. Em seguida, crie uma instância de `Octokit` passando sua personal access token como a opção `access_token`. No exemplo a seguir, substitua `YOUR-TOKEN` por sua personal access token.\n\n```ruby copy\nrequire 'octokit'\n\noctokit = Octokit::Client.new(access_token: 'YOUR-TOKEN')\n```\n\n### Autenticando com um GitHub App\n\nSe você quiser usar a API em nome de uma organização ou de outro usuário, GitHub recomenda que você use uma GitHub App. Se um endpoint estiver disponível para GitHub Apps, a documentação de referência da REST API para esse endpoint indicará que tipo de token GitHub App é necessário. Para saber mais, confira [Registrando um aplicativo GitHub](/pt/apps/creating-github-apps/registering-a-github-app/registering-a-github-app) e [Sobre a autenticação com um aplicativo GitHub](/pt/apps/creating-github-apps/authenticating-with-a-github-app/about-authentication-with-a-github-app).\n\nEm vez de exigir `octokit`, crie uma instância de `Octokit::Client` passando as informações da sua GitHub App como opções. No exemplo a seguir, substitua `APP_ID` pelo ID do seu aplicativo, `PRIVATE_KEY` pela chave privada do seu aplicativo e `INSTALLATION_ID` pelo ID da instalação do seu aplicativo em nome do qual você deseja autenticar. Você pode encontrar a ID do seu aplicativo e gerar uma chave privada na página de configurações do aplicativo. Para saber mais, confira [Gerenciando chaves privadas para aplicativos GitHub](/pt/apps/creating-github-apps/authenticating-with-a-github-app/managing-private-keys-for-github-apps). Você pode obter uma ID de instalação com os pontos de extremidade `GET /users/{username}/installation`, `GET /repos/{owner}/{repo}/installation` ou `GET /orgs/{org}/installation`. Para obter mais informações, consulte [Pontos de extremidade da API REST para o GitHub Apps](/pt/rest/apps/apps).\n\n```ruby copy\nrequire 'octokit'\n\napp = Octokit::Client.new(\n  client_id: APP_ID,\n  client_secret: PRIVATE_KEY,\n  installation_id: INSTALLATION_ID\n)\n\noctokit = Octokit::Client.new(bearer_token: app.create_app_installation.access_token)\n```\n\n### Autenticação em GitHub Actions\n\nSe você deseja usar a API em um GitHub Actions fluxo de trabalho, GitHub recomenda-se que você se autentique com o token integrado `GITHUB_TOKEN` em vez de criar um token. Você pode conceder permissões à `GITHUB_TOKEN` com a chave `permissions`. Para obter mais informações sobre `GITHUB_TOKEN`, confira [GITHUB\\_TOKEN](/pt/actions/concepts/security/github_token).\n\nSe o fluxo de trabalho precisar acessar recursos fora do repositório dele, então você não poderá usar `GITHUB_TOKEN`. Nesse caso, armazene suas credenciais como um segredo e substitua `GITHUB_TOKEN` nos exemplos abaixo pelo nome do segredo. Para saber mais sobre segredos, confira [Usar segredos em ações do GitHub](/pt/actions/how-tos/write-workflows/choose-what-workflows-do/use-secrets).\n\nSe você usar a palavra-chave `run` para executar seu script Ruby em seus fluxos de trabalho GitHub Actions, poderá armazenar o valor de `GITHUB_TOKEN` como uma variável de ambiente. Seu script pode acessar a variável de ambiente como `ENV['VARIABLE_NAME']`.\n\nPor exemplo, essa etapa do fluxo de trabalho armazena `GITHUB_TOKEN` em uma variável de ambiente chamada `TOKEN`:\n\n```yaml\n- name: Run script\n  env:\n    TOKEN: ${{ secrets.GITHUB_TOKEN }}\n  run: |\n    ruby .github/actions-scripts/use-the-api.rb\n```\n\nO script que o fluxo de trabalho executa usa `ENV['TOKEN']` para se autenticar:\n\n```ruby copy\nrequire 'octokit'\n\noctokit = Octokit::Client.new(access_token: ENV['TOKEN'])\n```\n\n### Instanciação sem autenticação\n\nVocê pode usar a API REST sem autenticação, embora isso resulte em uma limitação de taxa mais baixa e não permita o uso de alguns endpoints. Para criar uma instância de `Octokit` sem autenticação, não passe a opção `access_token`.\n\n```ruby copy\nrequire 'octokit'\n\noctokit = Octokit::Client.new\n```\n\n## Como fazer solicitações\n\nO Octokit dá suporte a várias maneiras de fazer solicitações. Você pode usar o método `request` para fazer solicitações se souber o verbo HTTP e o caminho para o ponto de extremidade. Você pode usar o método `rest` se quiser aproveitar o preenchimento automático em seu IDE e digitar. Para pontos de extremidade paginados, você pode usar o método `paginate` para solicitar várias páginas de dados.\n\n### Como usar o método `request` para fazer solicitações\n\nPara usar o método `request` a fim de fazer solicitações, passe o método HTTP e o caminho como o primeiro argumento. Passe qualquer parâmetro de corpo, consulta ou caminho em um hash como o segundo argumento. Por exemplo, para fazer uma solicitação `GET` para `/repos/{owner}/{repo}/issues` e passar os parâmetros `owner`, `repo` e `per_page`:\n\n```ruby copy\noctokit.request(\"GET /repos/{owner}/{repo}/issues\", owner: \"github\", repo: \"docs\", per_page: 2)\n```\n\nO método `request` passa automaticamente o cabeçalho `Accept: application/vnd.github+json`. Para passar cabeçalhos adicionais ou um cabeçalho `Accept` diferente, adicione uma opção `headers` ao hash que é passado como um segundo argumento. O valor da opção `headers` é um hash com os nomes de cabeçalho como chaves e os valores de cabeçalho como valores. Por exemplo, para enviar um cabeçalho `content-type` com o valor `text/plain`:\n\n```ruby copy\noctokit.request(\"POST /markdown/raw\", text: \"Hello **world**\", headers: { \"content-type\" => \"text/plain\" })\n```\n\n### Como usar métodos endpoint `rest` para fazer solicitações\n\nCada ponto de extremidade da API REST tem um método de ponto de extremidade `rest` associado no Octokit. Esses métodos geralmente são preenchidos automaticamente em seu IDE para conveniência. Você pode passar qualquer parâmetro como um hash para o método.\n\n```ruby copy\noctokit.rest.issues.list_for_repo(owner: \"github\", repo: \"docs\", per_page: 2)\n```\n\n### Como fazer solicitações paginadas\n\nSe o endpoint for paginado e você quiser recuperar mais de uma página de resultados, poderá usar o método `paginate`.\n`paginate` buscará a próxima página de resultados até chegar à última página e retornará todos os resultados como uma matriz. Alguns pontos de extremidade retornam resultados paginados como matriz em um objeto, em vez de retornar os resultados paginados como uma matriz.\n`paginate` sempre retorna uma matriz de itens, mesmo que o resultado bruto tenha sido um objeto .\n\nPor exemplo, o exemplo a seguir obtém todos os problemas do repositório `github/docs`. Embora solicite 100 solicitações por vez, a função não retornará até que a última página de dados seja atingida.\n\n```ruby copy\nissue_data = octokit.paginate(\"GET /repos/{owner}/{repo}/issues\", owner: \"github\", repo: \"docs\", per_page: 100)\n```\n\nO método `paginate` aceita um bloco opcional, que você pode usar para processar cada página de resultados. Isso permite coletar apenas os dados desejados da resposta. Por exemplo, o exemplo a seguir continua buscando resultados até que seja retornada uma questão que inclua \"teste\" no título. Para as páginas de dados que foram retornadas, apenas o título e o autor da questão são armazenados.\n\n```ruby copy\nissue_data = octokit.paginate(\"GET /repos/{owner}/{repo}/issues\", owner: \"github\", repo: \"docs\", per_page: 100) do |response, done|\n  response.data.map do |issue|\n    if issue.title.include?(\"test\")\n      done.call\n    end\n    { title: issue.title, author: issue.user.login }\n  end\nend\n```\n\nEm vez de buscar todos os resultados de uma só vez, você pode usar `octokit.paginate.iterator()` para percorrer uma só página de cada vez. Por exemplo, o caso a seguir busca uma página de resultados por vez e processa cada objeto da página atual antes de buscar a próxima. Uma vez encontrado um problema com \"teste\" no título, o script interrompe a iteração e retorna o título e o autor do problema de cada objeto que foi processado. O iterador é o método mais eficiente em termos de memória para buscar dados paginados.\n\n```ruby copy\niterator = octokit.paginate.iterator(\"GET /repos/{owner}/{repo}/issues\", owner: \"github\", repo: \"docs\", per_page: 100)\nissue_data = []\nbreak_loop = false\niterator.each do |data|\n  break if break_loop\n  data.each do |issue|\n    if issue.title.include?(\"test\")\n      break_loop = true\n      break\n    else\n      issue_data << { title: issue.title, author: issue.user.login }\n    end\n  end\nend\n```\n\nVocê também pode usar o método `paginate` com os métodos de endpoint `rest`. Passe o método de ponto de extremidade `rest` como o primeiro argumento e quaisquer parâmetros como o segundo argumento.\n\n```ruby copy\niterator = octokit.paginate.iterator(octokit.rest.issues.list_for_repo, owner: \"github\", repo: \"docs\", per_page: 100)\n```\n\nPara saber mais sobre a paginação, confira [Como usar paginação na API REST](/pt/rest/using-the-rest-api/using-pagination-in-the-rest-api).\n\n## Captura de erros\n\n### Capturando todos os erros\n\nÀs vezes, a GitHub API REST retornará um erro. Por exemplo, um erro será exibido se o token de acesso tiver expirado ou se um parâmetro obrigatório for omitido. O Octokit.rb faz automaticamente novas tentativas de executar a solicitação quando obtém um erro diferente de `400 Bad Request`, `401 Unauthorized`, `403 Forbidden`, `404 Not Found` ou `422 Unprocessable Entity`. Se ocorrer um erro de API mesmo após novas tentativas, o Octokit.rb gera um erro que inclui o código de status HTTP da resposta (`response.status`) e os cabeçalhos da resposta (`response.headers`). Você deve tratar esses erros em seu código. Por exemplo, você pode usar um bloco try/catch para capturar erros:\n\n```ruby copy\nbegin\nfiles_changed = []\n\niterator = octokit.paginate.iterator(\"GET /repos/{owner}/{repo}/pulls/{pull_number}/files\", owner: \"github\", repo: \"docs\", pull_number: 22809, per_page: 100)\niterator.each do | data |\n    files_changed.concat(data.map {\n      | file_data | file_data.filename\n    })\n  end\nrescue Octokit::Error => error\nif error.response\nputs \"Error! Status: #{error.response.status}. Message: #{error.response.data.message}\"\nend\nputs error\nend\n```\n\n### Tratamento de códigos de erro previstos\n\nÀs vezes, GitHub usa um código de status 4xx para indicar uma resposta sem erro. Se o endpoint que você está usando fizer isso, você poderá adicionar tratamento adicional para erros específicos. Por exemplo, o endpoint `GET /user/starred/{owner}/{repo}` retornará `404` se o repositório não estiver marcado com estrela. O exemplo a seguir usa a resposta `404` para indicar que o repositório não foi estrelado; todos os demais códigos de erros são tratados como erros.\n\n```ruby copy\nbegin\noctokit.request(\"GET /user/starred/{owner}/{repo}\", owner: \"github\", repo: \"docs\")\nputs \"The repository is starred by me\"\nrescue Octokit::NotFound => error\nputs \"The repository is not starred by me\"\nrescue Octokit::Error => error\nputs \"An error occurred while checking if the repository is starred: #{error&.response&.data&.message}\"\nend\n```\n\n### Tratamento de erros de limite de taxa\n\nSe você receber um erro de limite de taxa, talvez seja necessário repetir a solicitação após aguardar um tempo. Quando houver limitação de taxa, GitHub retornará um erro `403 Forbidden`, e o valor do cabeçalho de resposta `x-ratelimit-remaining` será `\"0\"`. Os cabeçalhos de resposta incluirão um cabeçalho `x-ratelimit-reset`, que informa a hora em que a janela de limite de taxa atual é redefinida, em segundos UTC. Você pode repetir a solicitação após aguardar o tempo especificado por `x-ratelimit-reset`.\n\n```ruby copy\ndef request_retry(route, parameters)\n begin\n response = octokit.request(route, parameters)\n return response\n rescue Octokit::RateLimitExceeded => error\n reset_time_epoch_seconds = error.response.headers['x-ratelimit-reset'].to_i\n current_time_epoch_seconds = Time.now.to_i\n seconds_to_wait = reset_time_epoch_seconds - current_time_epoch_seconds\n puts \"You have exceeded your rate limit. Retrying in #{seconds_to_wait} seconds.\"\n sleep(seconds_to_wait)\n retry\n rescue Octokit::Error => error\n puts error\n end\n end\n\n response = request_retry(\"GET /repos/{owner}/{repo}/issues\", owner: \"github\", repo: \"docs\", per_page: 2)\n```\n\n## Como usar a resposta\n\nO método `request` retornará um objeto de resposta se a solicitação tiver sido bem-sucedida. O objeto de resposta contém `data` (o corpo da resposta retornado pelo ponto de extremidade), `status` (o código de resposta HTTP), `url` (a URL da solicitação) e `headers` (um hash que contém os cabeçalhos da resposta). A menos que especificado de outra forma, o corpo da resposta está no formato JSON. Alguns endpoints não retornam um corpo de resposta; nesses casos, a propriedade `data` é omitida.\n\n```ruby copy\nresponse = octokit.request(\"GET /repos/{owner}/{repo}/issues/{issue_number}\", owner: \"github\", repo: \"docs\", issue_number: 11901)\n puts \"The status of the response is: #{response.status}\"\n puts \"The request URL was: #{response.url}\"\n puts \"The x-ratelimit-remaining response header is: #{response.headers['x-ratelimit-remaining']}\"\n puts \"The issue title is: #{response.data['title']}\"\n```\n\nDa mesma forma, o método `paginate` retorna um objeto de resposta. Se o `request` for bem-sucedido, o objeto `response` conterá dados, status, URL e cabeçalhos.\n\n```ruby copy\nresponse = octokit.paginate(\"GET /repos/{owner}/{repo}/issues\", owner: \"github\", repo: \"docs\", per_page: 100)\nputs \"#{response.data.length} issues were returned\"\nputs \"The title of the first issue is: #{response.data[0]['title']}\"\n```\n\n## Script de exemplo\n\nAqui está um script de exemplo completo que usa o Octokit.rb. O script importa `Octokit` e cria uma instância de `Octokit`. Se você quiser autenticar com um GitHub App em vez de um personal access token, você importaria e instanciaria `App` em vez de `Octokit`. Para saber mais, confira [Autenticação com um GitHub App](#authenticating-with-a-github-app) neste guia.\n\nA função `get_changed_files` obtém todos os arquivos alterados para uma solicitação de pull. A função `comment_if_data_files_changed` chama a função `get_changed_files`. Se qualquer um dos arquivos que a solicitação de pull alterou incluir `/data/` no caminho, a função comentará sobre a solicitação de pull.\n\n```ruby copy\nrequire \"octokit\"\n\n octokit = Octokit::Client.new(access_token: \"YOUR-TOKEN\")\n\n def get_changed_files(octokit, owner, repo, pull_number)\n files_changed = []\n\n begin\n iterator = octokit.paginate.iterator(\"GET /repos/{owner}/{repo}/pulls/{pull_number}/files\", owner: owner, repo: repo, pull_number: pull_number, per_page: 100)\n iterator.each do | data |\n     files_changed.concat(data.map {\n       | file_data | file_data.filename\n     })\n   end\n rescue Octokit::Error => error\n if error.response\n puts \"Error! Status: #{error.response.status}. Message: #{error.response.data.message}\"\n end\n puts error\n end\n\n files_changed\n end\n\n def comment_if_data_files_changed(octokit, owner, repo, pull_number)\n changed_files = get_changed_files(octokit, owner, repo, pull_number)\n\n if changed_files.any ? {\n   | file_name | /\\/data\\//i.match ? (file_name)\n }\n begin\n 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.\")\n comment.html_url\n rescue Octokit::Error => error\n if error.response\n puts \"Error! Status: #{error.response.status}. Message: #{error.response.data.message}\"\n end\n puts error\n end\n end\n end\n\n# Example usage\nowner = \"github\"\nrepo = \"docs\"\npull_number = 22809\ncomment_url = comment_if_data_files_changed(octokit, owner, repo, pull_number)\n\nputs \"A comment was added to the pull request: #{comment_url}\"\n```\n\n> \\[!NOTE]\n> Este é apenas um exemplo básico. Na prática, talvez você queira usar tratamento de erros e verificações condicionais para lidar com vários cenários.\n\n## Próximas etapas\n\nPara saber mais sobre como trabalhar com a GitHub API REST e o Octokit.rb, explore os seguintes recursos:\n\n* Para saber mais sobre o Octokit.js, confira a [documentação do Octokit.rb](https://github.com/octokit/octokit.rb/#readme).\n* Para obter informações detalhadas sobre os endpoints disponíveis da API REST de GitHub, incluindo as estruturas de solicitação e resposta, consulte o [documentação da API REST GitHub](/pt/rest)."}