Skip to content
This repository has been archived by the owner on Apr 19, 2023. It is now read-only.

Commit

Permalink
feat: reload config on push to .github repository, push new config al…
Browse files Browse the repository at this point in the history
…l org repositories (#26)
  • Loading branch information
mrparkers authored May 2, 2022
1 parent 64eeb27 commit 9422055
Show file tree
Hide file tree
Showing 8 changed files with 805 additions and 400 deletions.
1 change: 1 addition & 0 deletions .eslintrc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ parserOptions:
ecmaVersion: 11
rules:
"security/detect-object-injection": off
"unicorn/prevent-abbreviations": off
overrides:
- files:
- "**/*.spec.js"
Expand Down
8 changes: 7 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
"description": "",
"main": "src/app.js",
"private": true,
"engines": {
"node": ">=16"
},
"scripts": {
"lint": "eslint .",
"lintfix": "eslint --fix .",
Expand All @@ -21,7 +24,10 @@
"homepage": "https://github.com/liatrio-enterprise/github-policy-service#readme",
"dependencies": {
"@octokit/app": "^12.0.5",
"@octokit/core": "^3.6.0",
"@octokit/plugin-paginate-rest": "^2.17.0",
"@octokit/rest": "^18.12.0",
"deepmerge": "^4.2.2",
"dotenv": "^14.2.0",
"express": "^4.17.2",
"express-pino-logger": "^7.0.0",
Expand All @@ -30,8 +36,8 @@
"devDependencies": {
"@liatrio/eslint-config": "^1.1.0",
"@semantic-release/git": "^10.0.1",
"conventional-changelog-conventionalcommits": "^4.6.1",
"chance": "^1.1.8",
"conventional-changelog-conventionalcommits": "^4.6.1",
"eslint": "^8.9.0",
"jest": "^27.5.1",
"jest-extended": "^2.0.0",
Expand Down
4 changes: 4 additions & 0 deletions src/app.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
const { App, createNodeMiddleware } = require("@octokit/app");
const { paginateRest } = require("@octokit/plugin-paginate-rest");
const { Octokit } = require("@octokit/core");

const express = require("express");
const fs = require("node:fs");

Expand Down Expand Up @@ -66,6 +69,7 @@ const app = new App({
webhooks: {
secret: process.env.WEBHOOK_SECRET,
},
Octokit: Octokit.plugin(paginateRest),
});

(async () => {
Expand Down
20 changes: 11 additions & 9 deletions src/config/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
const merge = require("deepmerge");

const defaultConfig = require("./default");

const config = {};
Expand All @@ -13,9 +15,7 @@ const getConfigForOrg = async (logger, octokit, organization) => {
return config[organization].config;
}

await refreshConfigForOrg(logger, octokit, organization);

return config[organization].config;
return refreshConfigForOrg(logger, octokit, organization);
};

const refreshConfigForOrg = async (logger, octokit, organization) => {
Expand All @@ -34,23 +34,25 @@ const refreshConfigForOrg = async (logger, octokit, organization) => {
const json = JSON.parse(Buffer.from(response.data.content, "base64").toString("utf8"));

config[organization] = {
config: {
...defaultConfig,
...json,
},
config: merge(defaultConfig, json),
expiration: getExpirationDateInMinutes(15),
};
} catch (error) {
logger.error({ error,
organization }, "Error refreshing config for organization, using default config");
logger.error({
error,
organization,
}, "Error refreshing config for organization, using default config");

config[organization] = {
config: defaultConfig,
expiration: getExpirationDateInMinutes(15),
};
}

return config[organization].config;
};

module.exports = {
getConfigForOrg,
refreshConfigForOrg,
};
19 changes: 19 additions & 0 deletions src/handlers/config-reload.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const { refreshConfigForOrg } = require("../config");
const { setBranchProtectionForAllRepositories } = require("../util/batch");

module.exports = {
name: "configReload",
events: [
"push",
],
handler: ({ logger }) => async ({ octokit, payload }) => {
const mainBranchReference = `refs/heads/${payload.repository.default_branch}`;
const organization = payload.repository.owner.login;

if (payload.repository.name === ".github" && payload.ref === mainBranchReference) {
const refreshedConfig = await refreshConfigForOrg(logger, octokit, organization);

await setBranchProtectionForAllRepositories(logger, octokit, organization, refreshedConfig);
}
},
};
2 changes: 1 addition & 1 deletion src/handlers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ module.exports = async (app, logger) => {
const repository = payload.repository.name;
const config = await getConfigForOrg(logger, octokit, organization);

if (!config.repositoryWhitelist.includes(repository)) {
if (!config.repositoryWhitelist.includes(repository) || handlerName === "config-reload") {
await handler({
logger: logger.child({
name: handlerName,
Expand Down
37 changes: 37 additions & 0 deletions src/util/batch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
const BATCH_SIZE = 15;

const setBranchProtectionForAllRepositories = async (logger, octokit, organization, config) => {
const allRepositories = await octokit.paginate("GET /orgs/{organization}/repos", {
organization,
});

const repositories = allRepositories.filter((repository) => !config.repositoryWhitelist.includes(repository.name));

for (let i = 0; i < repositories.length; i += BATCH_SIZE) {
const batchRepositories = repositories.slice(i, i + BATCH_SIZE);
const batchRepositoryNames = batchRepositories.map((repository) => repository.name);

logger.debug({
repositories: batchRepositoryNames,
}, "Enabling branch protection for repository batch");

// eslint-disable-next-line no-await-in-loop
const results = await Promise.allSettled(batchRepositories.map((repository) => octokit.request(
"PUT /repos/{owner}/{repo}/branches/{branch}/protection",
{
owner: repository.owner.login,
repo: repository.name,
branch: repository.default_branch,
...config.branchProtection,
},
)));

logger.debug({
results,
}, "Results for branch protection");
}
};

module.exports = {
setBranchProtectionForAllRepositories,
};
Loading

0 comments on commit 9422055

Please sign in to comment.