
GitHub: Remove Repository Collaborator
This item removes a collaborator from a specified repository on GitHub.
Basic Configs
- Step Name
- Note
Configs for this Auto Step
- conf_Auth
- C1: Personal Access Token (fine-grained) *
- conf_RepositoryUrl
- C2: Repository’s URL (https://github.com/{owner}/{repository}) *
- conf_UserName
- C3: Handle of the GitHub collaborator *
Notes
- To learn about how to create your Personal Access Token (fine-grained), see the GitHub documentation
- To remove a repository collaborator, it is required that the token is granted the following permission: Repository permissions > Administration > Read and Write
Capture

See Also
Script (click to open)
- An XML file that contains the code below is available to download
- github-repository-collaborater-remove.xml (C) Questetra, Inc. (MIT License)
- If you are using Professional, you can modify the contents of this file and use it as your own add-on auto step
const API_VERSION = '2022-11-28';
const API_VERSION_HEADER = 'X-GitHub-Api-Version';
const main = () => {
////// == 工程コンフィグ・ワークフローデータの参照 / Config & Data Retrieving ==
const auth = configs.getObject('conf_Auth');
const ownerAndRepo = retrieveOwnerAndRepo();
const handle = retrieveHandle();
////// == 演算 / Calculating ==
const invitationId = checkInvitee(auth, ownerAndRepo, handle);
if (invitationId !== undefined){
// 招待中のユーザは、コラボレータ削除 API では削除できないため、招待削除 API で削除する
const isInvitationRemoved = removeInvitation(auth, ownerAndRepo, handle, invitationId);
if (isInvitationRemoved) {
return;
}
}
// コラボレータでない、招待していない、GitHub ユーザでない 場合に、エラーにしたい
// しかし、コラボレータ削除の API は、これらも削除成功と同様 204 レスポンスを返し、区別できない
// だから事前にコラボレータであるかどうかチェックする
checkCollaborator(auth, ownerAndRepo, handle);
removeCollaborator(auth, ownerAndRepo, handle);
}
/**
* config からリポジトリの URL を読み出し、API に必要な文字列を取り出す
* @return {String} ownerAndRepo
*/
const retrieveOwnerAndRepo = () => {
const repositoryUrlDef = configs.getObject('conf_RepositoryUrl');
let repositoryUrl;
if (repositoryUrlDef === null) { // 固定値で指定
repositoryUrl = configs.get('conf_RepositoryUrl');
} else {
repositoryUrl = engine.findData(repositoryUrlDef);
}
if (repositoryUrl === null) {
throw new Error("Repository's URL is blank.");
}
const regExp = /^https:\/\/github\.com\/([a-zA-Z0-9-_]+\/[a-zA-Z0-9-_]+)$/;
const found = repositoryUrl.match(regExp);
if (found === null) {
throw new Error("Invalid repository URL.");
}
const ownerAndRepo = found[1];
return ownerAndRepo;
}
/**
* config から削除する GitHub ユーザのハンドル名 を読み出す
* @return {String} handle
*/
const retrieveHandle = () => {
const handleDef = configs.getObject('conf_UserName');
let handle;
if (handleDef === null) { // 固定値で指定
handle = configs.get('conf_UserName');
} else {
handle = engine.findData(handleDef);
}
if (handle === null) {
throw new Error("handle is blank.");
}
return handle;
}
/**
* ユーザーがリポジトリ招待中であるかどうかを確認する
* @param {AuthSettingWrapper} auth HTTP 認証設定
* @param {String} ownerAndRepo {owner}/{repo}
* @param {String} handle 削除する GitHub ユーザのハンドル名
* @return {String} invitationsId 招待 ID
*/
const checkInvitee = (auth, ownerAndRepo, handle) => {
const url = `https://api.github.com/repos/${ownerAndRepo}/invitations`;
const MAX_PER_PAGE = 100;
const response = httpClient.begin()
.header(API_VERSION_HEADER, API_VERSION)
.authSetting(auth)
.queryParam("per_page", MAX_PER_PAGE.toString())
.get(url);
const status = response.getStatusCode();
const responseStr = response.getResponseAsString();
if (status !== 200) {
engine.log(responseStr);
throw new Error(`Failed to get invitee information. status: ${status}`);
}
const invitations = JSON.parse(responseStr);
if (invitations.length === MAX_PER_PAGE) {
throw new Error("Too many invitations found.");
}
const invitation = invitations.find((element) => element.invitee.login === handle);
if (invitation === undefined){
return undefined;
}
engine.log('Invitation found.');
return invitation.id;
};
/**
* リポジトリ招待中のユーザについて招待を削除(キャンセル)する
* 招待中のユーザは、コラボレータ削除 API では削除できないため、招待削除 API で削除する
* @param {AuthSettingWrapper} auth HTTP 認証設定
* @param {String} ownerAndRepo {owner}/{repo}
* @param {String} handle 削除する GitHub ユーザのハンドル名
* @param {String} invitationId GitHub ユーザの招待 ID
*/
const removeInvitation = (auth, ownerAndRepo, handle, invitationId) => {
const url = `https://api.github.com/repos/${ownerAndRepo}/invitations/${invitationId}`;
const response = httpClient.begin()
.header(API_VERSION_HEADER, API_VERSION)
.authSetting(auth)
.delete(url);
const status = response.getStatusCode();
const responseStr = response.getResponseAsString();
if (status === 204) { // 招待のキャンセル成功
engine.log(`Succeeded to remove the invitation(${handle}).`);
return true;
}
if (status === 404) { // 招待が承認済み or キャンセル済み
engine.log(`Failed to remove invitation as it is already approved or removed.`);
return false;
}
engine.log(responseStr);
throw new Error(`Failed to remove the invitation. status: ${status}`);
};
/**
* ユーザーがリポジトリコラボレータであるかどうかを確認する
* コラボレータでない、招待していない、GitHub ユーザでない 場合に、エラーにしたい
* しかし、コラボレータ削除の API は、これらも削除成功と同様 204 レスポンスを返し、区別できない
* だから事前にコラボレータであるかどうかチェックする
* @param {AuthSettingWrapper} auth HTTP 認証設定
* @param {String} ownerAndRepo {owner}/{repo}
* @param {String} handle 削除する GitHub ユーザのハンドル名
*/
const checkCollaborator = (auth, ownerAndRepo, handle) => {
const url = `https://api.github.com/repos/${ownerAndRepo}/collaborators/${encodeURIComponent(handle)}`;
const response = httpClient.begin()
.header(API_VERSION_HEADER, API_VERSION)
.authSetting(auth)
.get(url);
const status = response.getStatusCode();
const responseStr = response.getResponseAsString();
if (status === 204) {
// success: the user is a collaborator
return;
}
if (status === 404) {
throw new Error(`${handle} is not a collaborator. status: ${status}`);
}
engine.log(responseStr);
throw new Error(`Failed to get a ${handle} information. status: ${status}`);
};
/**
* リポジトリのコラボレータを削除
* @param {AuthSettingWrapper} auth HTTP 認証設定
* @param {String} ownerAndRepo {owner}/{repo}
* @param {String} handle 削除する GitHub ユーザのハンドル名
*/
const removeCollaborator = (auth, ownerAndRepo, handle) => {
const url = `https://api.github.com/repos/${ownerAndRepo}/collaborators/${encodeURIComponent(handle)}`;
const response = httpClient.begin()
.header(API_VERSION_HEADER, API_VERSION)
.authSetting(auth)
.delete(url);
const status = response.getStatusCode();
const responseStr = response.getResponseAsString();
if (status !== 204) {
engine.log(responseStr);
throw new Error(`Failed to remove a collaborator. status: ${status}`);
}
engine.log(`Succeeded to remove a collaborator(${handle}).`);
};