Skip to main content

Enterprise Server 3.20 은(는) 현재 릴리스 후보로 제공됩니다.

REST API 및 JavaScript를 사용하여 스크립팅

Octokit.js SDK를 사용하여 REST API와 상호 작용하는 스크립트를 작성합니다.

Octokit.js 정보

JavaScript를 사용하여 GitHub의 REST API와 상호 작용하는 스크립트를 작성하려면 GitHub에서 Octokit.js SDK를 사용하는 것이 좋습니다. Octokit.js는 GitHub에 의해 유지됨니다. SDK는 모범 사례를 구현하고 JavaScript를 통해 REST API와 보다 쉽게 상호 작용할 수 있도록 합니다. Octokit.js는 모든 최신 브라우저, Node.js 및 Deno에서 작동합니다. Octokit.js에 대한 자세한 정보는 Octokit.js 추가 정보를 참조하세요.

필수 조건

이 가이드에서는 JavaScript 및 GitHub REST API에 익숙하다고 가정합니다. REST API에 대한 자세한 내용은 AUTOTITLE을(를) 참조하세요.

참고: Octokit.js 라이브러리를 사용하려면 을(를) 설치하고 가져와야 합니다. 이 가이드에서는 ES6에 따라 import 문을 사용합니다. 다양한 설치 및 가져오기 메서드에 대한 자세한 정보는 Octokit.js 추가 정보 사용 섹션을 참조하세요.

인스턴스화 및 인증

경고

인증 자격 증명을 암호처럼 처리합니다.

자격 증명을 안전하게 유지하기 위해 비밀로 저장하고 GitHub Actions를 통해 스크립트를 실행할 수 있습니다. 자세한 내용은 AUTOTITLE을(를) 참조하세요.

이(가) 불가능하며, 다른 CLI 서비스를 사용하여 자격 증명을 안전하게 저장하는 것이 좋습니다.

personal access token을(를) 사용하여 인증

개인용으로 GitHub REST API를 사용하려는 경우 personal access token를 만들 수 있습니다. personal access token을 만드는 방법에 대한 자세한 내용은 AUTOTITLE을(를) 참조하세요.

먼저 에서 를 가져옵니다. 그런 다음 인스턴스를 만들 때 personal access token을(를) 패스합니다. 다음 예제에서는 을 personal access token에 대한 참조로 치환합니다. 을 GitHub Enterprise Server 인스턴스의 이름으로 치환합니다.

JavaScript
import { Octokit } from "octokit";

const octokit = new Octokit({ 
  baseUrl: "http(s)://HOSTNAME/api/v3",
  auth: 'YOUR-TOKEN',
});

GitHub App(을)를 사용하여 인증하기

조직 또는 다른 사용자를 대신하여 API를 사용하려는 경우 GitHub에서 GitHub App을(를) 사용하는 것이 좋습니다. GitHub Apps에 엔드포인트를 사용할 수 있는 경우 해당 엔드포인트에 대한 REST 참조 설명서에 필요한 GitHub App 토큰 유형이 표시됩니다. 자세한 내용은 AUTOTITLE 및 AUTOTITLE을(를) 참조하세요.

에서 를 가져오는 대신 을 가져옵니다. 다음 예제에서는 을(를) 앱 ID에 대한 참조로 바꿉니다. 앱의 프라이빗 키에 대한 참조로 를 대체합니다. 를 대신하여 인증하려는 앱의 설치의 ID로 바꿉니다. 앱 ID를 찾고 앱의 설정 페이지 설정에서 프라이빗 키를 생성할 수 있습니다. 자세한 내용은 AUTOTITLE을(를) 참조하세요. , , 엔드포인트를 사용하여 설치 ID를 가져올 수 있습니다. 자세한 내용은 AUTOTITLE을(를) 참조하세요. 을 GitHub Enterprise Server 인스턴스의 이름으로 바꿉니다.

JavaScript
import { App } from "octokit";

const app = new App({
  appId: APP_ID,
  privateKey: PRIVATE_KEY,
  Octokit: Octokit.defaults({
    baseUrl: "http(s)://HOSTNAME/api/v3",
  }),
});

const octokit = await app.getInstallationOctokit(INSTALLATION_ID);

GitHub Actions으로 인증하기

GitHub Actions 워크플로에서 API를 사용하려면 GitHub에서 토큰을 만드는 대신 기본 제공 으로 인증하는 것이 좋습니다. 키를 사용하여 에 대한 사용 권한을 부여할 수 있습니다. 에 대한 자세한 내용은 AUTOTITLE을(를) 참조하세요.

워크플로가 워크플로 리포지토리 외부의 리소스에 액세스해야 하는 경우 을 사용할 수 없습니다. 이 경우 자격 증명을 비밀로 저장하고 아래 예제의 을 비밀의 이름으로 바꿉니다. 비밀에 대한 자세한 내용은 AUTOTITLE을(를) 참조하세요.

또한 키워드를 사용하여GitHub Actions 워크플로에서 JavaScript 스크립트를 실행할 수 있으며 의 값을 환경 변수로 저장할 수 있습니다. 스크립트는 환경 변수에 로 액세스할 수 있습니다.

예를 들어 이 워크플로 단계에서 이라는 환경 변수에 을 저장합니다.

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

워크플로가 실행하는 스크립트는 을 인증하는 데 사용합니다.

JavaScript
import { Octokit } from "octokit";

const octokit = new Octokit({ 
  baseUrl: "http(s)://HOSTNAME/api/v3",
  auth: process.env.TOKEN,
});

인증 없는 인스턴스화

트래픽률 제한이 낮고 일부 엔드포인트를 사용할 수 없어도 인증 없이 REST API를 사용할 수 있습니다. 인증하지 않고 인스턴스 를 만들려면 인수를 패스하지 마세요. 기준 URL을 로 설정합니다. 을 GitHub Enterprise Server 인스턴스의 이름으로 바꿉니다.

JavaScript
import { Octokit } from "octokit";

const octokit = new Octokit({ 
  baseUrl: "http(s)://HOSTNAME/api/v3",
});

요청하기

Octokit은 요청을 만드는 여러 가지 방법을 지원합니다. 엔드포인트에 대한 HTTP 동사와 경로를 알고 있는 경우 메서드를 사용하여 요청을 수행할 수 있습니다. IDE에서 자동 완성 및 입력을 이용하려는 경우 메서드를 사용할 수 있습니다. 페이지를 매긴 엔드포인트의 경우 메서드를 사용하여 여러 데이터 페이지를 요청할 수 있습니다.

메서드를 사용하여 요청을 수행합니다.

메서드를 사용하여 요청을 만들려면 HTTP 메서드와 경로를 첫 번째 인수로 전달합니다. 개체의 본문, 쿼리, 경로 매개 변수를 두 번째 인수로 패스합니다. 예를 들어 에 을 요청하고 , , 매개변수를 전달하려면 다음을 수행하세요.

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

메서드는 자동으로 머리글을 전달합니다. 추가 헤더 또는 다른 머리글을 전달하려면 두 번째 인수로 전달되는 개체에 속성을 추가합니다. 속성의 값은 헤더 이름을 키로, 헤더 값을 값으로 가지고 있는 개체입니다. 예를 들어 값이 인 머리글과 값이 인 머리글을 보내려면 다음을 수행합니다.

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

엔드포인트 메서드를 사용하여 요청을 수행하기

모든 REST API 엔드포인트에는 Octokit에 연결된 엔드포인트 메서드가 있습니다. 이러한 메서드는 일반적으로 편의를 위해 IDE에서 자동 완성됩니다. 모든 매개 변수를 개체로 메서드에 전달할 수 있습니다.

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

또한 TypeScript와 같은 형식화된 언어를 사용하는 경우 이러한 메서드와 함께 사용할 형식을 가져올 수 있습니다. 자세한 정보는 plugin-rest-endpoint-methods.js 추가 정보에서 TypeScript 섹션을 참조하세요.

페이지 나열된 요청 만들기

엔드포인트가 페이지 단위로 나뉘어 있고 둘 이상의 결과 페이지를 가져오려는 경우 메서드를 사용할 수 있습니다. 는 마지막 페이지에 도달할 때까지 결과의 다음 페이지를 가져온 다음 모든 결과를 단일 배열로 반환합니다. 일부 엔드포인트는 페이지 매김된 결과를 배열이 아닌 객체 안의 배열로 반환합니다. 원시 결과가 개체인 경우에도 는 항상 항목 배열을 반환합니다.

예를 들어 다음 예제에서는 리포지토리에서 모든 이슈를 가져옵니다. 한 번에 100개의 이슈를 요청하지만 함수는 데이터의 마지막 페이지에 도달할 때까지 반환되지 않습니다.

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

메서드는 응답에서 원하는 데이터만 수집하는 데 사용할 수 있는 선택적 맵 함수를 수락합니다. 이렇게 하면 스크립트의 메모리 사용량이 줄어듭니다. map 함수는 마지막 페이지에 도달하기 전에 페이지 매김을 종료하기 위해 호출할 수 있는 두 번째 인수 을 사용할 수 있습니다. 이렇게 하면 페이지의 하위 집합을 가져올 수 있습니다. 예를 들어 다음 예제에서는 제목에 "test"가 포함된 이슈가 반환될 때까지 결과를 계속 가져옵니다. 반환된 데이터 페이지의 경우 이슈 제목과 작성자만 저장됩니다.

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

모든 결과를 한 번에 가져오는 대신 한 번에 단일 페이지를 반복하는 데 를 사용할 수 있습니다. 예를 들어 다음 예제에서는 결과의 한 페이지를 한 번에 가져오고 다음 페이지를 가져오기 전에 페이지에서 각 개체를 처리합니다. 제목에 "test"가 포함된 이슈에 도달하면 스크립트는 반복을 중지하고 처리된 각 개체의 이슈 제목 및 이슈 작성자를 반환합니다. 반복기는 페이지를 매긴 데이터를 가져오기 위한 가장 메모리 효율적인 메서드입니다.

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

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}];
    }
  }
}

엔드포인트 메서드에서도 메서드를 사용할 수 있습니다. 엔드포인트 메서드를 첫 번째 인수로 전달합니다. 매개 변수를 두 번째 인수로 전달합니다.

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

페이지 매김에 대한 자세한 내용은 AUTOTITLE을(를) 참조하세요.

오류 포착하기

모든 오류 포착하기

경우에 따라 GitHub REST API에서 오류를 반환합니다. 예를 들어 액세스 토큰이 만료되었거나 필수 매개 변수를 생략하면 오류가 발생합니다. Octokit.js는 , , , 및 이외의 오류가 발생하면 요청을 자동으로 다시 시도합니다. 재시도 후에도 API 오류가 발생하면 Octokit.js는 응답() 및 응답 헤더()의 HTTP 상태 코드를 포함하는 오류를 throw합니다. 코드에서 이러한 오류를 처리해야 합니다. 예를 들어 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": "2022-11-28",
    },
  });

  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 상태 코드를 사용하여 오류가 아닌 응답을 나타냅니다. 사용 중인 엔드포인트에서 이 작업을 수행하는 경우, 특정 오류에 대한 처리를 추가할 수 있습니다. 예를 들어 엔드포인트는 리포지토리에 별표를 하지 않은 경우 를 반환합니다. 다음 예제에서는 응답을 사용하여 리포지토리가 별표 표시되지 않았음을 나타내고 다른 모든 오류 코드는 오류로 처리됩니다.

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

  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}`);
  }
}

트래픽률 제한 오류 처리

트래픽률 제한 오류가 표시되는 경우 대기 후 요청을 다시 시도할 수 있습니다. 요청 속도가 제한될 때, GitHub이(가) 오류로 응답하고 응답 헤더 값은 이 됩니다. 응답 헤더에는 현재 트래픽률 제한 창이 재설정되는 시간을 UTC Epoch 초 단위로 알려주는 헤더가 포함됩니다. 에 지정된 시간 후에 요청을 다시 시도할 수 있습니다.

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

응답 사용

메서드는 요청이 성공한 경우 객체로 해결되는 프로미스를 반환합니다. 개체 속성은 (엔드포인트에서 반환된 응답 본문), (HTTP 응답 코드), (요청의 URL) 및 (응답 머리글을 포함하는 개체)입니다. 달리 지정하지 않는 한 응답 본문은 JSON 형식입니다. 일부 엔드포인트는 응답 본문을 반환하지 않습니다. 이 경우 속성은 생략됩니다.

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": "2022-11-28",
  },
});

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}`)

마찬가지로 메서드는 프라미스를 반환합니다. 요청이 성공하면, 프로미스는 엔드포인트에서 반환된 데이터 배열로 해결됩니다. 메서드와 달리 메서드는 상태 코드, URL 또는 머리글을 반환하지 않습니다.

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

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

예제 스크립트

다음은 Octokit.js를 사용하는 전체 예제 스크립트입니다. 스크립트는 를 가져오고 새 인스턴스 를 만듭니다. personal access token 대신 GitHub App을(를) 사용하여 인증하려는 경우 대신 을 가져오고 인스턴스화합니다. 자세한 정보는 GitHub App에서 인증을 참조하세요.

함수는 끌어오기 요청에 대해 변경된 모든 파일을 가져옵니다. 함수는 함수를 호출합니다. 끌어오기 요청이 변경된 파일이 파일 경로에 가 포함된 경우 함수는 끌어오기 요청에 대해 설명을 달게 됩니다.

JavaScript
import { Octokit } from "octokit";

const octokit = new Octokit({ 
  baseUrl: "http(s)://HOSTNAME/api/v3",
  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": "2022-11-28",
      },
    });

    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": "2022-11-28",
      },
    });

    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});

다음 단계

  • Octokit.js에 대한 자세한 정보는 Octokit.js 설명서를 참조하세요.
  • 몇 가지 실제 예제를 보려면 GitHub Docs에서 GitHub Docs 리포지토리를 검색하여 Octokit.js를 사용하는 방법을 살펴봅니다.