Skip to main content

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

Напишите скрипт с помощью пакета SDK Octokit.js для взаимодействия с REST API.

О Octokit.js

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

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

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

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

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

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

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

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

Вы также можете сохранить свои учетные данные в виде секрета Codespaces и запустить скрипт в Codespaces. Дополнительные сведения см. в разделе Управление секретами, специфичными для ваших аккаунтов, для GitHub Codespaces.

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

Аутентификация с помощью personal access token

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

Сначала импортируйте Octokit из octokit. Затем передайте свой personal access token код при создании экземпляра Octokit. В следующем примере замените YOUR-TOKEN ссылку на вашу personal access token.

JavaScript
import { Octokit } from "octokit";

const octokit = new Octokit({ 
  auth: 'YOUR-TOKEN',
});

Аутентификация с помощью GitHub App

Если вы хотите использовать API от имени организации или другого пользователя, GitHub рекомендуется использовать GitHub App. Если конечная точка доступна GitHub Apps, справочная документация REST для этой конечной точки указывает, какой тип маркера GitHub App является обязательным. Дополнительные сведения см. в разделе [AUTOTITLE и Регистрация приложения GitHub](/apps/creating-github-apps/authenticating-with-a-github-app/about-authentication-with-a-github-app).

Вместо импорта Octokit из octokit, импорта App. В следующем примере замените APP_ID ссылку на идентификатор приложения. Замените PRIVATE_KEY ссылкой на закрытый ключ приложения. Замените INSTALLATION_ID идентификатором установки приложения, от имени которого требуется выполнить проверку подлинности. Идентификатор приложения можно найти и создать закрытый ключ на странице параметров приложения. Дополнительные сведения см. в разделе Управление приватными ключами для приложений GitHub. Идентификатор установки можно получить с GET /users/{username}/installationпомощью конечных точек или GET /repos/{owner}/{repo}/installation конечных GET /orgs/{org}/installationточек. Для получения дополнительной информации см. Конечные точки REST API для GitHub Apps.

JavaScript
import { App } from "octokit";

const app = new App({
  appId: APP_ID,
  privateKey: PRIVATE_KEY,
});

const octokit = await app.getInstallationOctokit(INSTALLATION_ID);

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

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

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

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

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

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

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

JavaScript
import { Octokit } from "octokit";

const octokit = new Octokit({ 
  auth: process.env.TOKEN,
});

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

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

JavaScript
import { Octokit } from "octokit";

const octokit = new Octokit({ );

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

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

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

Чтобы использовать метод для выполнения запросов, передайте request метод HTTP и путь в качестве первого аргумента. Передайте все параметры текста, запроса или пути в объект в качестве второго аргумента. Например, чтобы выполнить GET запрос к /repos/{owner}/{repo}/issues и передать параметрыowner``repo, и per_page выполнить следующие параметры:

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

Метод request автоматически передает Accept: application/vnd.github+json заголовок. Чтобы передать дополнительные заголовки или другой Accept заголовок, добавьте headers свойство в объект, передаваемый в качестве второго аргумента. Значение свойства headers — это объект с именами заголовков в качестве ключей и значениями заголовков в качестве значений. Например, чтобы отправить content-type заголовок со значением text/plain и x-github-api-version заголовком со значением 2026-03-10:

JavaScript
await octokit.request("POST /markdown/raw", {
  text: "Hello **world**",
  headers: {
    "content-type": "text/plain",
    "x-github-api-version": "2026-03-10",
  },
});

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

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

JavaScript
await octokit.rest.issues.listForRepo({
  owner: "github",
  repo: "docs",
  per_page: 2
});

Кроме того, если используется типизированный язык, например TypeScript, можно импортировать типы для использования с этими методами. Дополнительные сведения см . в разделе TypeScript в plugin-rest-endpoint-methods.js README.

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

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

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

JavaScript
const issueData = await octokit.paginate("GET /repos/{owner}/{repo}/issues", {
  owner: "github",
  repo: "docs",
  per_page: 100,
  headers: {
    "x-github-api-version": "2026-03-10",
  },
});

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

JavaScript
const issueData = await octokit.paginate("GET /repos/{owner}/{repo}/issues", {
  owner: "github",
  repo: "docs",
  per_page: 100,
  headers: {
    "x-github-api-version": "2026-03-10",
  },
},
    (response, done) => response.data.map((issue) => {
    if (issue.title.includes("test")) {
      done()
    }
    return ({title: issue.title, author: issue.user.login})
  })
);

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

JavaScript
const iterator = octokit.paginate.iterator("GET /repos/{owner}/{repo}/issues", {
  owner: "github",
  repo: "docs",
  per_page: 100,
  headers: {
    "x-github-api-version": "2026-03-10",
  },
});

let issueData = []
let breakLoop = false
for await (const {data} of iterator) {
  if (breakLoop) break
  for (const issue of data) {
    if (issue.title.includes("test")) {
      breakLoop = true
      break
    } else {
      issueData = [...issueData, {title: issue.title, author: issue.user.login}];
    }
  }
}

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

JavaScript
const iterator = octokit.paginate.iterator(octokit.rest.issues.listForRepo, {
  owner: "github",
  repo: "docs",
  per_page: 100,
  headers: {
    "x-github-api-version": "2026-03-10",
  },
});

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

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

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

GitHub Иногда REST API возвращает ошибку. Например, вы получите ошибку, если срок действия маркера доступа истек или если не указан обязательный параметр. Octokit.js автоматически повторяет запрос при получении ошибки, отличной от 400 Bad Request, 401 Unauthorized, 403 Forbiddenи 404 Not Found.422 Unprocessable Entity Если ошибка API возникает даже после повторных попыток, Octokit.js выдает ошибку, содержащую код состояния HTTP ответа (response.status) и заголовки ответа (response.headers). Эти ошибки следует обрабатывать в коде. Например, для перехвата ошибок можно использовать блок try/catch:

JavaScript
let filesChanged = []

try {
  const iterator = octokit.paginate.iterator("GET /repos/{owner}/{repo}/pulls/{pull_number}/files", {
    owner: "github",
    repo: "docs",
    pull_number: 22809,
    per_page: 100,
    headers: {
      "x-github-api-version": "2026-03-10",
    },
  });

  for await (const {data} of iterator) {
    filesChanged = [...filesChanged, ...data.map(fileData => fileData.filename)];
  }
} catch (error) {
  if (error.response) {
    console.error(`Error! Status: ${error.response.status}. Message: ${error.response.data.message}`)
  }
  console.error(error)
}

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

GitHub Иногда используется код состояния 4xx для указания ответа, отличного от ошибок. Если используется эта конечная точка, можно добавить дополнительную обработку для определенных ошибок. Например, конечная GET /user/starred/{owner}/{repo} точка вернет объект, 404 если репозиторий не указан. В следующем примере используется ответ, указывающий, что репозиторий 404 не был в главной роли; все остальные коды ошибок рассматриваются как ошибки.

JavaScript
try {
  await octokit.request("GET /user/starred/{owner}/{repo}", {
    owner: "github",
    repo: "docs",
    headers: {
      "x-github-api-version": "2026-03-10",
    },
  });

  console.log(`The repository is starred by me`);

} catch (error) {
  if (error.status === 404) {
    console.log(`The repository is not starred by me`);
  } else {
    console.error(`An error occurred while checking if the repository is starred: ${error?.response?.data?.message}`);
  }
}

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

Если вы получаете ошибку ограничения скорости, вы можете повторить запрос после ожидания. Если скорость ограничена, ответит ошибкой 403 Forbidden и GitHub значение заголовка x-ratelimit-remaining ответа будет"0". Заголовки ответа будут содержать x-ratelimit-reset заголовок, который указывает время сброса текущего ограничения скорости в секундах эпохи UTC. После указанного x-ratelimit-resetвремени можно повторить запрос.

JavaScript
async function requestRetry(route, parameters) {
  try {
    const response = await octokit.request(route, parameters);
    return response
  } catch (error) {
    if (error.response && error.status === 403 && error.response.headers['x-ratelimit-remaining'] === '0') {
      const resetTimeEpochSeconds = error.response.headers['x-ratelimit-reset'];
      const currentTimeEpochSeconds = Math.floor(Date.now() / 1000);
      const secondsToWait = resetTimeEpochSeconds - currentTimeEpochSeconds;
      console.log(`You have exceeded your rate limit. Retrying in ${secondsToWait} seconds.`);
      setTimeout(requestRetry, secondsToWait * 1000, route, parameters);
    } else {
      console.error(error);
    }
  }
}

const response = await requestRetry("GET /repos/{owner}/{repo}/issues", {
    owner: "github",
    repo: "docs",
    per_page: 2
  })

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

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

JavaScript
const response = await octokit.request("GET /repos/{owner}/{repo}/issues/{issue_number}", {
  owner: "github",
  repo: "docs",
  issue_number: 11901,
  headers: {
    "x-github-api-version": "2026-03-10",
  },
});

console.log(`The status of the response is: ${response.status}`)
console.log(`The request URL was: ${response.url}`)
console.log(`The x-ratelimit-remaining response header is: ${response.headers["x-ratelimit-remaining"]}`)
console.log(`The issue title is: ${response.data.title}`)

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

JavaScript
const data = await octokit.paginate("GET /repos/{owner}/{repo}/issues", {
  owner: "github",
  repo: "docs",
  per_page: 100,
  headers: {
    "x-github-api-version": "2026-03-10",
  },
});

console.log(`${data.length} issues were returned`)
console.log(`The title of the first issue is: ${data[0].title}`)

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

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

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

JavaScript
import { Octokit } from "octokit";

const octokit = new Octokit({ 
  auth: 'YOUR-TOKEN',
});

async function getChangedFiles({owner, repo, pullNumber}) {
  let filesChanged = []

  try {
    const iterator = octokit.paginate.iterator("GET /repos/{owner}/{repo}/pulls/{pull_number}/files", {
      owner: owner,
      repo: repo,
      pull_number: pullNumber,
      per_page: 100,
      headers: {
        "x-github-api-version": "2026-03-10",
      },
    });

    for await (const {data} of iterator) {
      filesChanged = [...filesChanged, ...data.map(fileData => fileData.filename)];
    }
  } catch (error) {
    if (error.response) {
      console.error(`Error! Status: ${error.response.status}. Message: ${error.response.data.message}`)
    }
    console.error(error)
  }

  return filesChanged
}

async function commentIfDataFilesChanged({owner, repo, pullNumber}) {
  const changedFiles = await getChangedFiles({owner, repo, pullNumber});

  const filePathRegex = new RegExp(/\/data\//, "i");
  if (!changedFiles.some(fileName => filePathRegex.test(fileName))) {
    return;
  }

  try {
    const {data: comment} = await octokit.request("POST /repos/{owner}/{repo}/issues/{issue_number}/comments", {
      owner: owner,
      repo: repo,
      issue_number: pullNumber,
      body: `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.`,
      headers: {
        "x-github-api-version": "2026-03-10",
      },
    });

    return comment.html_url;
  } catch (error) {
    if (error.response) {
      console.error(`Error! Status: ${error.response.status}. Message: ${error.response.data.message}`)
    }
    console.error(error)
  }
}

await commentIfDataFilesChanged({owner: "github", repo: "docs", pullNumber: 191});

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