From 02e83a29102db2620f3ddfbef30b55bf2df4a7ad Mon Sep 17 00:00:00 2001 From: afrocandy Date: Mon, 15 May 2023 14:05:01 +0900 Subject: [PATCH] Change GitHub api endpoint (#2) * Feature/add options (#1) * add 'add' action and ghBaseUrl * use env for base url * update nodejs ver 12 to 16 * revert dist/index.js to upstream's one --- README.md | 8 +++--- action.yml | 4 +-- package-lock.json | 2 +- package.json | 2 +- src/action.js | 65 ++++++++++++++++++++++------------------------- 5 files changed, 39 insertions(+), 42 deletions(-) diff --git a/README.md b/README.md index 2fa22e7..bdb623f 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ This action will set / delete Branch Protection rules on specified branches of G "enforce_admins": true, "required_linear_history": true, "required_pull_request_reviews": { - "dismiss_stale_reviews": true + "dismiss_stale_reviews": true } }, "main": { @@ -40,7 +40,7 @@ This action will set / delete Branch Protection rules on specified branches of G "enforce_admins": null, "required_linear_history": null, "required_pull_request_reviews": { - "dismiss_stale_reviews": true + "dismiss_stale_reviews": true } } } @@ -53,8 +53,8 @@ This action will set / delete Branch Protection rules on specified branches of G **Description** - Path of the text file(.txt) with repos to be excluded from branch protection. Specify every repo name (without org/ prefix) on a new line. This is optional. If not provided, no repos will be excluded and branch protection will be applied on all the repos within the organization. ### `action` -**Description** - This GitHub Custom action can be used to set / delete branch protection. The default value is set (if not specified). If delete is assigned, it will remove branch protection from every repo, if branch protection is already applied. -**Default** - 'set' +**Description** - This GitHub Custom action can be used to set / add / delete branch protection. The default value is set (if not specified). If add is assigned, it will add branch protection to every repo, if branch protection is not applied. If delete is assigned, it will remove branch protection from every repo, if branch protection is already applied. +**Default** - 'set' # Usage diff --git a/action.yml b/action.yml index 181a34c..b9f6008 100644 --- a/action.yml +++ b/action.yml @@ -18,12 +18,12 @@ inputs: excludedReposPath: description: 'Path of the file with repos (newline separated) to be excluded for branch protection. This is optional.' action: - description: 'Set or Delete Branch protection. Default is set.' + description: 'Set or Add or Delete Branch protection. Default is set.' default: 'set' required: true runs: - using: 'node12' + using: 'node16' main: 'dist/index.js' branding: diff --git a/package-lock.json b/package-lock.json index a169be5..cc89e31 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "branch-protection", - "version": "1.0.0", + "version": "1.1.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 73e853d..b6f9324 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "branch-protection", - "version": "1.0.0", + "version": "1.1.0", "description": "Custom GitHub Action based on Node.js to set branch protection rules", "main": "dist/index.js", "scripts": { diff --git a/src/action.js b/src/action.js index 7caf1d0..b37e361 100644 --- a/src/action.js +++ b/src/action.js @@ -1,5 +1,5 @@ const core = require('@actions/core'); -const { request } = require("@octokit/request"); +const { request: orgRequest } = require("@octokit/request"); const fs = require('fs') var excludedReposPath = ''; @@ -12,29 +12,43 @@ async function run() { excludedReposPath = core.getInput("excludedReposPath"); includedReposPath = core.getInput("includedReposPath"); const action = core.getInput("action"); - const limit = 100; + const canDeleteProtection = action == 'set' || action == 'delete'; + const canSetProtection = action == 'set' || action == 'add'; + var rulesObj; var branches; try { if(!fs.existsSync(rulesPath)){ throw "Rules JSON is missing." } + + const request = orgRequest.defaults({ + baseUrl: process.env.GITHUB_API_URL || 'https://api.github.com', + headers: { + authorization: "token " + token, + }, + }) const rules = fs.readFileSync(rulesPath, {encoding:'utf8', flag:'r'}); rulesObj = JSON.parse(rules); keys = Object.keys(rulesObj); - var repos = await getFinalRepos(token, orgName); + var repos = await getFinalRepos(request, orgName); for (let i = 0; i < repos.length; i++) { - branches = await getBranches(token, repos[i], keys); + branches = await getBranches(request, repos[i], keys); for (let j = 0; j < branches.length; j++) { if(branches[j].protected){ + if (!canDeleteProtection) { + console.log("Skip Branch Protection for " + branches[j].name + " branch of " + repos[i]); + continue; + } + console.log("Deleting Branch Protection for " + branches[j].name + " branch of " + repos[i]); core.debug("Deleting Branch Protection for " + branches[j].name + " branch of " + repos[i]); - await deleteProtection(token, repos[i], branches[j].name); + await deleteProtection(request, repos[i], branches[j].name); } - if(action == "set"){ + if(canSetProtection){ console.log("Setting Branch Protection for " + branches[j].name + " branch of " + repos[i]); core.debug("Setting Branch Protection for " + branches[j].name + " branch of " + repos[i]); - await setProtection(token, repos[i], branches[j].name, rulesObj[branches[j].name] ) + await setProtection(request, repos[i], branches[j].name, rulesObj[branches[j].name] ) } } } @@ -45,7 +59,7 @@ async function run() { } } -async function setProtection(token, repoName, branchName, ruleData){ +async function setProtection(request, repoName, branchName, ruleData){ const url = "/repos/" + repoName + "/branches/" + branchName + "/protection" if(ruleData == ""){ ruleData = { @@ -58,9 +72,6 @@ async function setProtection(token, repoName, branchName, ruleData){ } try { const result = await request("PUT " + url, { - headers: { - authorization: "token " + token, - }, data: ruleData }); //console.log(result.data); @@ -72,14 +83,10 @@ async function setProtection(token, repoName, branchName, ruleData){ } } -async function deleteProtection(token, repoName, branchName){ +async function deleteProtection(request, repoName, branchName){ const url = "/repos/" + repoName + "/branches/" + branchName + "/protection" try{ - const result = await request("DELETE " + url, { - headers: { - authorization: "token " + token, - } - }); + const result = await request("DELETE " + url); if(result.status != 204){ throw "Exception occured during Delete Protection"; } @@ -90,15 +97,11 @@ async function deleteProtection(token, repoName, branchName){ } } -async function getBranches(token, repoName, branchNames){ +async function getBranches(request, repoName, branchNames){ branchInfoArr = []; const url = "/repos/" + repoName + "/branches" try { - const result = await request("GET " + url, { - headers: { - authorization: "token " + token, - } - }); + const result = await request("GET " + url); branchData = result.data; for (let j = 0; j < branchData.length; j++) { const element = branchData[j]; @@ -114,13 +117,10 @@ async function getBranches(token, repoName, branchNames){ return branchInfoArr; } -async function getRepoCount(token, orgName){ +async function getRepoCount(request, orgName){ repoCnt = 0; try { const result = await request("GET /orgs/{org}/repos", { - headers: { - authorization: "token " + token, - }, org: orgName, per_page:1, type: "all" @@ -140,13 +140,10 @@ function getPageCount(itemCount, limit){ return pageCount; } -async function getPagedRepos(token, orgName, pageNum, limit){ +async function getPagedRepos(request, orgName, pageNum, limit){ var repos = []; try { const result = await request("GET /orgs/{org}/repos", { - headers: { - authorization: "token " + token, - }, org: orgName, per_page:limit, type: "all", @@ -163,7 +160,7 @@ async function getPagedRepos(token, orgName, pageNum, limit){ return repos; } -async function getFinalRepos(token, orgName){ +async function getFinalRepos(request, orgName){ repos = []; includedRepos = []; limit = 100; @@ -175,12 +172,12 @@ async function getFinalRepos(token, orgName){ } return includedRepos; } - repoCount = await getRepoCount(token, orgName); + repoCount = await getRepoCount(request, orgName); pageCnt = getPageCount(repoCount, limit); excludedRepos = getReposFromFile(excludedReposPath); for (let i = 0; i < pageCnt; i++) { i = i + 1; - pagedRepos = await getPagedRepos(token, orgName, i, limit); + pagedRepos = await getPagedRepos(request, orgName, i, limit); for (let j = 0; j < pagedRepos.length; j++) { repoShortName = pagedRepos[j].replace(orgName + "/",""); if(!excludedRepos.includes(repoShortName)) {