Ă propos dâOctokit.js
Si vous souhaitez Ă©crire un script avec JavaScript pour interagir avec lâAPI REST de GitHub, GitHub vous recommande dâutiliser le SDK Octokit.js. Octokit.js est gĂ©rĂ© par GitHub. Le SDK implĂ©mente les bonnes pratiques et vous permet dâinteragir plus facilement avec lâAPI REST via JavaScript. Octokit.js fonctionne avec tous les navigateurs modernes, Node.js et Deno. Pour plus dâinformations sur Octokit.js, consultez le fichier README dâOctokit.js.
Prérequis
Ce guide suppose que vous ĂȘtes familiarisĂ© avec JavaScript et lâAPI REST GitHub. Pour plus dâinformations sur lâAPI REST, consultez Prise en main de lâAPI REST.
Vous devez installer et importer octokit
pour utiliser la bibliothĂšque Octokit.js. Ce guide utilise des instructions import conformĂ©ment Ă ES6. Pour plus dâinformations sur les diffĂ©rentes mĂ©thodes dâinstallation et dâimportation, consultez la section Usage du fichier README dâOctokit.js.
Instanciation et authentification
Avertissement
GĂ©rez vos informations dâauthentification comme un mot de passe.
Pour que vos informations dâidentification restent sĂ©curisĂ©es, vous pouvez les stocker sous forme de secret et exĂ©cuter votre script par le biais de GitHub Actions. Pour plus dâinformations, consultez « Utilisation de secrets dans GitHub Actions ».
Si ce nâest pas possible, envisagez dâutiliser un autre service CLI pour stocker vos informations dâidentification de façon sĂ©curisĂ©e.
Authentification avec un personal access token
Si vous voulez utiliser lâAPI REST GitHub Ă des fins personnelles, vous pouvez crĂ©er un personal access token. Pour plus dâinformations sur la crĂ©ation dâun personal access token, consultez Gestion de vos jetons d'accĂšs personnels.
Tout dâabord, importez Octokit
depuis octokit
. Ensuite, transmettez votre personal access token lorsque vous créez une instance Octokit
. Dans lâexemple suivant, remplacez YOUR-TOKEN
par une référence à votre personal access token. Remplacez HOSTNAME
par le nom de votre instance GitHub Enterprise Server.
import { Octokit } from "octokit"; const octokit = new Octokit({ baseUrl: "http(s)://HOSTNAME/api/v3", auth: 'YOUR-TOKEN', });
import { Octokit } from "octokit";
const octokit = new Octokit({
baseUrl: "http(s)://HOSTNAME/api/v3",
auth: 'YOUR-TOKEN',
});
Authentification avec une GitHub App
Si vous voulez utiliser lâAPI au nom dâune organisation ou dâun autre utilisateur, GitHub vous recommande dâutiliser une GitHub App. Si un point de terminaison est disponible pour GitHub Apps, la documentation de rĂ©fĂ©rence de REST pour ce point de terminaison indique quel type de jeton GitHub App est nĂ©cessaire. Pour plus dâinformations, consultez « Inscription dâune application GitHub » et « Ă propos de lâauthentification avec une application GitHub ».
Au lieu dâimporter Octokit
depuis octokit
, importez App
. Dans lâexemple suivant, remplacez APP_ID
par une rĂ©fĂ©rence Ă lâID de votre application. Remplacez PRIVATE_KEY
par une référence à la clé privée de votre application. Remplacez INSTALLATION_ID
par lâID de lâinstallation de votre application que vous souhaitez authentifier. Vous pouvez trouver lâID de votre application et gĂ©nĂ©rer une clĂ© privĂ©e dans la page des paramĂštres de votre application. Pour plus dâinformations, consultez « Gestion des clĂ©s privĂ©es pour les applications GitHub ». Vous pouvez obtenir un ID dâinstallation avec les points de terminaison GET /users/{username}/installation
, GET /repos/{owner}/{repo}/installation
ou GET /orgs/{org}/installation
. Pour plus dâinformations, consultez Points de terminaison dâAPI REST pour GitHub Apps. Remplacez HOSTNAME
par le nom de votre instance GitHub Enterprise Server.
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);
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);
Authentification dans GitHub Actions
Si vous voulez utiliser lâAPI dans un workflow GitHub Actions, GitHub vous recommande dâĂȘtre authentifiĂ© avec le jeton GITHUB_TOKEN
intégré au lieu de créer un jeton. Vous pouvez accorder des autorisations au GITHUB_TOKEN
avec la clé permissions
. Pour plus dâinformations sur GITHUB_TOKEN
, consultez Utiliser GITHUB_TOKEN pour lâauthentification dans les flux de travail.
Si votre workflow doit accéder à des ressources en dehors du dépÎt du workflow, vous ne pourrez pas utiliser GITHUB_TOKEN
. Dans ce cas, stockez vos informations dâidentification sous forme de secret et remplacez GITHUB_TOKEN
dans les exemples ci-dessous par le nom de votre secret. Pour plus dâinformations sur les secrets, consultez « Utilisation de secrets dans GitHub Actions ».
Si vous utilisez le mot clé run
pour exécuter votre script JavaScript dans vos workflows GitHub Actions, vous pouvez stocker la valeur de GITHUB_TOKEN
en tant que variable dâenvironnement. Votre script peut accĂ©der Ă la variable dâenvironnement en tant que process.env.VARIABLE_NAME
.
Par exemple, cette étape de workflow stocke GITHUB_TOKEN
dans une variable dâenvironnement appelĂ©e TOKEN
:
- name: Run script
env:
TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
node .github/actions-scripts/use-the-api.mjs
Le script quâexĂ©cute le workflow utilise process.env.TOKEN
pour lâauthentification :
import { Octokit } from "octokit"; const octokit = new Octokit({ baseUrl: "http(s)://HOSTNAME/api/v3", auth: process.env.TOKEN, });
import { Octokit } from "octokit";
const octokit = new Octokit({
baseUrl: "http(s)://HOSTNAME/api/v3",
auth: process.env.TOKEN,
});
Instanciation sans authentification
Vous pouvez utiliser lâAPI REST sans authentification, mais vous aurez une limite de dĂ©bit infĂ©rieure et vous ne pourrez pas utiliser certains points de terminaison. Pour crĂ©er une instance Octokit
sans authentification, ne passez pas lâargument auth
. DĂ©finissez lâURL de base sur http(s)://HOSTNAME/api/v3
. Remplacez [hostname]
par le nom de votre instance GitHub Enterprise Server.
import { Octokit } from "octokit"; const octokit = new Octokit({ baseUrl: "http(s)://HOSTNAME/api/v3", });
import { Octokit } from "octokit";
const octokit = new Octokit({
baseUrl: "http(s)://HOSTNAME/api/v3",
});
CrĂ©ation de requĂȘtes
Octokit prend en charge plusieurs façons de crĂ©er des requĂȘtes. Vous pouvez utiliser la mĂ©thode request
pour crĂ©er des requĂȘtes si vous connaissez le verbe HTTP et le chemin du point de terminaison. Vous pouvez utiliser la mĂ©thode rest
si vous souhaitez tirer parti de lâautocomplĂ©tion dans votre IDE et de la saisie. Pour les points de terminaison paginĂ©s, vous pouvez utiliser la mĂ©thode paginate
pour demander plusieurs pages de données.
Utilisation de la méthode request
pour crĂ©er des requĂȘtes
Pour utiliser la méthode request
pour crĂ©er des requĂȘtes, passez la mĂ©thode HTTP et le chemin comme premier argument. Passez tous les paramĂštres de corps, de requĂȘte ou de chemin dans un objet en tant que deuxiĂšme argument. Par exemple, pour crĂ©er une requĂȘte GET
dans /repos/{owner}/{repo}/issues
et passer les paramĂštres owner
, repo
et per_page
:
await octokit.request("GET /repos/{owner}/{repo}/issues", { owner: "github", repo: "docs", per_page: 2 });
await octokit.request("GET /repos/{owner}/{repo}/issues", {
owner: "github",
repo: "docs",
per_page: 2
});
La méthode request
passe automatiquement lâen-tĂȘte Accept: application/vnd.github+json
. Pour passer des en-tĂȘtes supplĂ©mentaires ou un en-tĂȘte Accept
différent, ajoutez une propriété headers
Ă lâobjet passĂ© en tant que deuxiĂšme argument. La valeur de la propriĂ©tĂ© headers
est un objet avec les noms dâen-tĂȘte en tant que clĂ©s et les valeurs dâen-tĂȘte en tant que valeurs. Par exemple, pour envoyer un en-tĂȘte content-type
avec la valeur text/plain
et un en-tĂȘte x-github-api-version
avec la valeur 2022-11-28
:
await octokit.request("POST /markdown/raw", { text: "Hello **world**", headers: { "content-type": "text/plain", "x-github-api-version": "2022-11-28", }, });
await octokit.request("POST /markdown/raw", {
text: "Hello **world**",
headers: {
"content-type": "text/plain",
"x-github-api-version": "2022-11-28",
},
});
Utilisation des méthodes de point de terminaison rest
pour crĂ©er des requĂȘtes
Chaque point de terminaison dâAPI REST a une mĂ©thode de point de terminaison rest
associĂ©e dans Octokit. Ces mĂ©thodes appliquent gĂ©nĂ©ralement lâautocomplĂ©tion dans votre IDE pour des raisons pratiques. Vous pouvez passer nâimporte quel paramĂštre en tant quâobjet Ă la mĂ©thode.
await octokit.rest.issues.listForRepo({ owner: "github", repo: "docs", per_page: 2 });
await octokit.rest.issues.listForRepo({
owner: "github",
repo: "docs",
per_page: 2
});
De plus, si vous utilisez un langage typĂ© tel que TypeScript, vous pouvez importer des types Ă utiliser avec ces mĂ©thodes. Pour plus dâinformations, consultez la section TypeScript dans le README plugin-rest-endpoint-methods.js.
CrĂ©ation de requĂȘtes paginĂ©es
Si le point de terminaison est paginé et que vous souhaitez extraire plusieurs pages de résultats, vous pouvez utiliser la méthode paginate
. paginate
rĂ©cupĂšre la page de rĂ©sultats suivante jusquâĂ atteindre la derniĂšre page, puis retourne tous les rĂ©sultats sous la forme dâun tableau. Quelques points de terminaison retournent les rĂ©sultats paginĂ©s sous forme de tableau dans un objet, au lieu de les retourner sous forme de tableau. paginate
retourne toujours un tableau dâĂ©lĂ©ments mĂȘme si le rĂ©sultat brut Ă©tait un objet.
Par exemple, lâexemple suivant rĂ©cupĂšre tous les problĂšmes du dĂ©pĂŽt github/docs
. Bien quâelle demande 100 problĂšmes Ă la fois, la fonction nâest pas retournĂ©e tant que la derniĂšre page de donnĂ©es nâest pas atteinte.
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", }, });
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",
},
});
La méthode paginate
accepte une fonction map facultative, que vous pouvez utiliser pour collecter uniquement les donnĂ©es souhaitĂ©es Ă partir de la rĂ©ponse. Cela rĂ©duit lâutilisation de la mĂ©moire par votre script. La fonction map peut prendre un deuxiĂšme argument, done
, que vous pouvez appeler pour mettre fin Ă la pagination avant que la derniĂšre page ne soit atteinte. Cela vous permet dâextraire un sous-ensemble de pages. Par exemple, lâexemple suivant continue dâextraire les rĂ©sultats jusquâĂ ce quâun problĂšme incluant « test » dans le titre soit retournĂ©. Pour les pages de donnĂ©es qui ont Ă©tĂ© retournĂ©es, seuls le titre et lâauteur du problĂšme sont stockĂ©s.
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}) }) );
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})
})
);
Au lieu dâextraire tous les rĂ©sultats Ă la fois, vous pouvez utiliser octokit.paginate.iterator()
pour itĂ©rer au sein dâune seule page Ă la fois. Par exemple, lâexemple suivant extrait une page de rĂ©sultats Ă la fois et traite chaque objet de la page avant dâextraire la page suivante. Une fois quâun problĂšme qui inclut « test » dans le titre est atteint, le script arrĂȘte lâitĂ©ration et retourne le titre du problĂšme et lâauteur du problĂšme de chaque objet qui a Ă©tĂ© traitĂ©. LâitĂ©rateur est la mĂ©thode la plus efficace en mĂ©moire pour extraire des donnĂ©es paginĂ©es.
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}]; } } }
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}];
}
}
}
Vous pouvez également utiliser la méthode paginate
avec les méthodes de point de terminaison rest
. Passez la méthode de point de terminaison rest
en tant que premier argument. Passez tous les paramĂštres en tant que deuxiĂšme argument.
const iterator = octokit.paginate.iterator(octokit.rest.issues.listForRepo, { owner: "github", repo: "docs", per_page: 100, headers: { "x-github-api-version": "2022-11-28", }, });
const iterator = octokit.paginate.iterator(octokit.rest.issues.listForRepo, {
owner: "github",
repo: "docs",
per_page: 100,
headers: {
"x-github-api-version": "2022-11-28",
},
});
Pour plus dâinformations sur la pagination, consultez Utilisation de la pagination dans lâAPI REST.
Interception des erreurs
Interception de toutes les erreurs
Parfois, lâAPI REST GitHub retourne une erreur. Par exemple, vous obtenez une erreur si votre jeton dâaccĂšs a expirĂ© ou si vous avez omis un paramĂštre obligatoire. Octokit.js retente automatiquement la demande lorsquâil obtient une erreur autre que 400 Bad Request
, 401 Unauthorized
, 403 Forbidden
, 404 Not Found
et 422 Unprocessable Entity
. Si une erreur dâAPI se produit mĂȘme aprĂšs plusieurs tentatives, Octokit.js lĂšve une erreur qui inclut le code dâĂ©tat HTTP de la rĂ©ponse (response.status
) et les en-tĂȘtes de rĂ©ponse (response.headers
). Vous devez gérer ces erreurs dans votre code. Par exemple, vous pouvez utiliser un bloc try/catch pour intercepter les erreurs :
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) }
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)
}
Gestion des codes dâerreur prĂ©vus
Parfois, GitHub utilise un code dâĂ©tat 4xx pour indiquer une rĂ©ponse de non-erreur. Si le point de terminaison que vous utilisez le fait, vous pouvez ajouter une gestion supplĂ©mentaire pour des erreurs spĂ©cifiques. Par exemple, le point de terminaison GET /user/starred/{owner}/{repo}
retourne une erreur 404
si le dĂ©pĂŽt nâa pas dâĂ©toile. Lâexemple suivant utilise la rĂ©ponse 404
pour indiquer que le dĂ©pĂŽt nâa pas eu dâĂ©toile, tous les autres codes dâerreur sont traitĂ©s comme des erreurs.
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}`); } }
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}`);
}
}
Gestion des erreurs de limite de débit
Si vous recevez une erreur de limite de débit, vous pouvez retenter votre demande aprÚs avoir attendu. Lorsque votre taux est limité, GitHub répond avec une erreur 403 Forbidden
et la valeur dâen-tĂȘte de rĂ©ponse x-ratelimit-remaining
est "0"
. Les en-tĂȘtes de rĂ©ponse incluent un en-tĂȘte x-ratelimit-reset
, qui vous indique lâheure Ă laquelle la fenĂȘtre de limite de dĂ©bit actuelle est rĂ©initialisĂ©e, en secondes dâĂ©poque UTC. Vous pouvez retenter votre demande aprĂšs lâheure spĂ©cifiĂ©e par x-ratelimit-reset
.
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 })
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
})
Utilisation de la réponse
La méthode request
retourne une promesse qui est rĂ©solue en objet si la demande a rĂ©ussi. Les propriĂ©tĂ©s de lâobjet sont data
(le corps de la réponse retourné par le point de terminaison), status
(le code de réponse HTTP), url
(lâURL de la requĂȘte) et headers
(un objet contenant les en-tĂȘtes de rĂ©ponse). Sauf indication contraire, le corps de rĂ©ponse est au format JSON. Certains points de terminaison ne retournent pas de corps de rĂ©ponse, auquel cas, la propriĂ©tĂ© data
est omise.
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}`)
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}`)
De mĂȘme, la mĂ©thode paginate
retourne une promesse. Si la demande a réussi, la promesse est résolue en tableau de données retourné par le point de terminaison. Contrairement à la méthode request
, la méthode paginate
ne retourne pas le code dâĂ©tat, lâURL ou les en-tĂȘtes.
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}`)
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}`)
Exemple de script
Voici un exemple de script complet qui utilise Octokit.js. Le script importe Octokit
et crée une nouvelle instance Octokit
. Si vous souhaitez vous authentifier avec une GitHub App au lieu dâun personal access token, vous devez importer et instancier App
Ă la place de Octokit
. Pour plus dâinformations, consultez Authentification avec une GitHub App.
La fonction getChangedFiles
obtient tous les fichiers modifiés pour une demande de tirage. La fonction commentIfDataFilesChanged
appelle la fonction getChangedFiles
. Si lâun des fichiers modifiĂ©s par la demande de tirage inclut /data/
dans le chemin, la fonction commente la demande de tirage.
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});
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});
Ătapes suivantes
- Pour en savoir plus sur Octokit.js, consultez la documentation Octokit.js.
- Pour obtenir des exemples concrets, regardez comment GitHub Docs utilise Octokit.js en recherchant dans le dépÎt GitHub Docs.