mirror of
https://github.com/empayre/fleet.git
synced 2024-11-06 08:55:24 +00:00
Tool: Bring back mergefreeze API integration (#6905)
* Tool: Bring back mergefreeze API integration Context: https://github.com/fleetdm/fleet/pull/5628#issuecomment-1196175485 Unfortunately, the API doesn't work. * Lay out how this would work in the database - but instead, do it ephemerally for now * Remove model * Maintain state (the easy way for now)
This commit is contained in:
parent
8369f6b1b5
commit
39fea292b9
@ -27,7 +27,13 @@ module.exports = {
|
|||||||
|
|
||||||
let GitHub = require('machinepack-github');
|
let GitHub = require('machinepack-github');
|
||||||
|
|
||||||
let IS_FROZEN = false;// « Set this to `true` whenever a freeze is in effect, then set it back to `false` when the freeze ends.
|
// Is this in use?
|
||||||
|
// > For context on the history of this bit of code, which has gone been
|
||||||
|
// > implemented a couple of different ways, and gone back and forth, check out:
|
||||||
|
// > https://github.com/fleetdm/fleet/pull/5628#issuecomment-1196175485
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
// let IS_FROZEN = false;// « Set this to `true` whenever a freeze is in effect, then set it back to `false` when the freeze ends.
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
||||||
let GITHUB_USERNAMES_OF_BOTS_AND_MAINTAINERS = [// « Used in multiple places below.
|
let GITHUB_USERNAMES_OF_BOTS_AND_MAINTAINERS = [// « Used in multiple places below.
|
||||||
'sailsbot',
|
'sailsbot',
|
||||||
@ -71,6 +77,10 @@ module.exports = {
|
|||||||
|
|
||||||
let GITHUB_USERNAME_OF_DRI_FOR_LABELS = 'noahtalerman';// « Used below (FUTURE: Remove this capability as Fleet has outgrown it. 2022-05-05)
|
let GITHUB_USERNAME_OF_DRI_FOR_LABELS = 'noahtalerman';// « Used below (FUTURE: Remove this capability as Fleet has outgrown it. 2022-05-05)
|
||||||
|
|
||||||
|
if (!sails.config.custom.mergeFreezeAccessToken) {
|
||||||
|
throw new Error('An access token for the MergeFreeze API (sails.config.custom.mergeFreezeAccessToken) is required to enable automated unfreezing/freezing of changes based on the files they change. Please ask for help in #g-digital-experience, whether you are testing locally or using this as a live webhook.');
|
||||||
|
}
|
||||||
|
|
||||||
if (!sails.config.custom.slackWebhookUrlForGithubBot) {
|
if (!sails.config.custom.slackWebhookUrlForGithubBot) {
|
||||||
throw new Error('No Slack webhook URL configured for the GitHub bot to notify with alerts! (Please set `sails.config.custom.slackWebhookUrlForGithubBot`.)');
|
throw new Error('No Slack webhook URL configured for the GitHub bot to notify with alerts! (Please set `sails.config.custom.slackWebhookUrlForGithubBot`.)');
|
||||||
}//•
|
}//•
|
||||||
@ -218,18 +228,78 @@ module.exports = {
|
|||||||
isGithubUserMaintainerOrDoesntMatter: GITHUB_USERNAMES_OF_BOTS_AND_MAINTAINERS.includes(sender.login.toLowerCase())
|
isGithubUserMaintainerOrDoesntMatter: GITHUB_USERNAMES_OF_BOTS_AND_MAINTAINERS.includes(sender.login.toLowerCase())
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Check whether the "main" branch is currently frozen (i.e. a feature freeze)
|
||||||
|
// [?] https://docs.mergefreeze.com/web-api#get-freeze-status
|
||||||
|
let isMainBranchFrozen = (await sails.helpers.http.get('https://www.mergefreeze.com/api/branches/fleetdm/fleet/main', { access_token: sails.config.custom.mergeFreezeAccessToken })).frozen;//eslint-disable-line camelcase
|
||||||
|
|
||||||
// Now, if appropriate, auto-approve the change.
|
// Now, if appropriate, auto-approve the change.
|
||||||
if (isAutoApproved) {
|
if (isAutoApproved) {
|
||||||
// [?] https://docs.github.com/en/rest/reference/pulls#create-a-review-for-a-pull-request
|
// [?] https://docs.github.com/en/rest/reference/pulls#create-a-review-for-a-pull-request
|
||||||
await sails.helpers.http.post(`https://api.github.com/repos/${owner}/${repo}/pulls/${prNumber}/reviews`, {
|
await sails.helpers.http.post(`https://api.github.com/repos/${owner}/${repo}/pulls/${prNumber}/reviews`, {
|
||||||
event: 'APPROVE'
|
event: 'APPROVE'
|
||||||
}, baseHeaders);
|
}, baseHeaders);
|
||||||
} else if (IS_FROZEN) {
|
|
||||||
// [?] https://docs.github.com/en/rest/reference/pulls#create-a-review-for-a-pull-request
|
// Since we're only using a single instance, and because the worst case scenario is that we refreeze some
|
||||||
await sails.helpers.http.post(`https://api.github.com/repos/${owner}/${repo}/pulls/${prNumber}/reviews`, {
|
// all-markdown PRs that had already been frozen, instead of using the database, we'll just use a little
|
||||||
event: 'REQUEST_CHANGES',
|
// in-memory pocket here of PRs seen by this instance of the Sails app. To get around any issues with this,
|
||||||
body: 'The repository is currently frozen for an upcoming release. \n> After the freeze has ended, please dismiss this review. \n\nIn case of emergency, you can dismiss this review and merge now.'
|
// users can edit and resave the PR description to trigger their PR to be unfrozen.
|
||||||
}, baseHeaders);
|
// FUTURE: Go through the trouble to migrate the database and make a little Platform model to hold this state in.
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
// Grab the set of GitHub pull request numbers the bot considers "unfrozen".
|
||||||
|
sails.pocketOfPrNumbersUnfrozen = sails.pocketOfPrNumbersUnfrozen || [];
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
||||||
|
// If "main" is explicitly frozen, then unfreeze this PR because it no longer contains
|
||||||
|
// (or maybe never did contain) changes to freezeworthy files.
|
||||||
|
if (isMainBranchFrozen) {
|
||||||
|
|
||||||
|
sails.pocketOfPrNumbersUnfrozen = _.union(sails.pocketOfPrNumbersUnfrozen, [ prNumber ]);
|
||||||
|
|
||||||
|
// [?] See May 6th, 2022 changelog, which includes this code sample:
|
||||||
|
// (https://www.mergefreeze.com/news)
|
||||||
|
// (but as of July 26, 2022, I didn't see it documented here: https://docs.mergefreeze.com/web-api#post-freeze-status)
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
// > You may now freeze or unfreeze a single PR (while maintaining the overall freeze) via the Web API.
|
||||||
|
// ```
|
||||||
|
// curl -d "frozen=true&user_name=Scooby Doo&unblocked_prs=[3]" -X POST https://www.mergefreeze.com/api/branches/mergefreeze/core/master/?access_token=[Your access token]
|
||||||
|
// ```
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
await sails.helpers.http.post(`https://www.mergefreeze.com/api/branches/fleetdm/fleet/main?access_token=${encodeURIComponent(sails.config.custom.mergeFreezeAccessToken)}`, {
|
||||||
|
frozen: true,
|
||||||
|
user_name: 'fleet-release',//eslint-disable-line camelcase
|
||||||
|
unblocked_prs: sails.pocketOfPrNumbersUnfrozen,//eslint-disable-line camelcase
|
||||||
|
});
|
||||||
|
|
||||||
|
}//fi
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// If "main" is explicitly frozen, then freeze this PR because it now contains
|
||||||
|
// (or maybe always did contain) changes to freezeworthy files.
|
||||||
|
if (isMainBranchFrozen) {
|
||||||
|
|
||||||
|
sails.pocketOfPrNumbersUnfrozen = _.difference(sails.pocketOfPrNumbersUnfrozen, [ prNumber ]);
|
||||||
|
|
||||||
|
// [?] See explanation above.
|
||||||
|
await sails.helpers.http.post(`https://www.mergefreeze.com/api/branches/fleetdm/fleet/main?access_token=${encodeURIComponent(sails.config.custom.mergeFreezeAccessToken)}`, {
|
||||||
|
frozen: true,
|
||||||
|
user_name: 'fleet-release',//eslint-disable-line camelcase
|
||||||
|
unblocked_prs: sails.pocketOfPrNumbersUnfrozen,//eslint-disable-line camelcase
|
||||||
|
});
|
||||||
|
}//fi
|
||||||
|
|
||||||
|
// Is this in use?
|
||||||
|
// > For context on the history of this bit of code, which has gone been
|
||||||
|
// > implemented a couple of different ways, and gone back and forth, check out:
|
||||||
|
// > https://github.com/fleetdm/fleet/pull/5628#issuecomment-1196175485
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
// if (IS_FROZEN) {
|
||||||
|
// // [?] https://docs.github.com/en/rest/reference/pulls#create-a-review-for-a-pull-request
|
||||||
|
// await sails.helpers.http.post(`https://api.github.com/repos/${owner}/${repo}/pulls/${prNumber}/reviews`, {
|
||||||
|
// event: 'REQUEST_CHANGES',
|
||||||
|
// body: 'The repository is currently frozen for an upcoming release. \n> After the freeze has ended, please dismiss this review. \n\nIn case of emergency, you can dismiss this review and merge now.'
|
||||||
|
// }, baseHeaders);
|
||||||
|
// }//fi
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
5
website/assets/.eslintrc
vendored
5
website/assets/.eslintrc
vendored
@ -55,7 +55,10 @@
|
|||||||
// Make sure backend globals aren't indadvertently tolerated in our client-side JS:
|
// Make sure backend globals aren't indadvertently tolerated in our client-side JS:
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
"sails": false,
|
"sails": false,
|
||||||
"User": false
|
"User": false,
|
||||||
|
"HistoricalUsageSnapshot": false,
|
||||||
|
"Quote": false,
|
||||||
|
"Subscription": false,
|
||||||
// ...and any other backend globals (e.g. `"Organization": false`)
|
// ...and any other backend globals (e.g. `"Organization": false`)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
}
|
}
|
||||||
|
116
website/scripts/freeze-open-pull-requests.js
vendored
116
website/scripts/freeze-open-pull-requests.js
vendored
@ -1,6 +1,5 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
|
|
||||||
|
|
||||||
friendlyName: 'Freeze open pull requests',
|
friendlyName: 'Freeze open pull requests',
|
||||||
|
|
||||||
|
|
||||||
@ -22,62 +21,69 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
fn: async function ({dry: isDryRun, limit: maxNumPullRequestsToCheck }) {
|
fn: async function () {
|
||||||
|
// Is this in use?
|
||||||
sails.log('Running custom shell script... (`sails run freeze-open-pull-requests`)');
|
// > For context on the history of this bit of code, which has gone been
|
||||||
|
// > implemented a couple of different ways, and gone back and forth, check out:
|
||||||
let owner = 'fleetdm';
|
// > https://github.com/fleetdm/fleet/pull/5628#issuecomment-1196175485
|
||||||
let repo = 'fleet';
|
throw new Error('Not currently in use. See comments in this script for more information.');
|
||||||
let baseHeaders = {
|
|
||||||
'User-Agent': 'sails run freeze-open-pull-requests',
|
|
||||||
'Authorization': `token ${sails.config.custom.githubAccessToken}`
|
|
||||||
};
|
|
||||||
|
|
||||||
// Fetch open pull requests
|
|
||||||
// [?] https://docs.github.com/en/rest/pulls/pulls#list-pull-requests
|
|
||||||
let openPullRequests = await sails.helpers.http.get(`https://api.github.com/repos/${owner}/${repo}/pulls`, {
|
|
||||||
state: 'open',
|
|
||||||
per_page: maxNumPullRequestsToCheck,//eslint-disable-line camelcase
|
|
||||||
}, baseHeaders);
|
|
||||||
|
|
||||||
if (openPullRequests.length > maxNumPullRequestsToCheck) {
|
|
||||||
openPullRequests = openPullRequests.slice(0,maxNumPullRequestsToCheck);
|
|
||||||
}
|
|
||||||
|
|
||||||
let SECONDS_TO_WAIT = 5;
|
|
||||||
sails.log(`Examining and potentially freezing ${openPullRequests.length} PRs very soon… (To cancel, press CTRL+C quickly within ${SECONDS_TO_WAIT}s!)`);
|
|
||||||
await sails.helpers.flow.pause(SECONDS_TO_WAIT*1000);
|
|
||||||
|
|
||||||
// For all open pull requests…
|
|
||||||
await sails.helpers.flow.simultaneouslyForEach(openPullRequests, async(pullRequest)=>{
|
|
||||||
|
|
||||||
let prNumber = pullRequest.number;
|
|
||||||
let prAuthor = pullRequest.user.login;
|
|
||||||
require('assert')(prAuthor !== undefined);
|
|
||||||
|
|
||||||
// Freeze, if appropriate.
|
|
||||||
// (Check versus the intersection of DRIs for all changed files to make sure SOMEONE is preapproved for all of them.)
|
|
||||||
let isAuthorPreapproved = await sails.helpers.githubAutomations.getIsPrPreapproved.with({
|
|
||||||
prNumber: prNumber,
|
|
||||||
isGithubUserMaintainerOrDoesntMatter: true// « doesn't matter here because no auto-approval is happening. Worst case, a community PR to an area with a "*" in the DRI mapping remains unfrozen.
|
|
||||||
});
|
|
||||||
|
|
||||||
if (isDryRun) {
|
|
||||||
sails.log(`#${prNumber} by @${prAuthor}:`, isAuthorPreapproved ? 'Would have skipped freeze…' : 'Would have frozen…');
|
|
||||||
} else {
|
|
||||||
sails.log(`#${prNumber} by @${prAuthor}:`, isAuthorPreapproved ? 'Skipping freeze…' : 'Freezing…');
|
|
||||||
if (!isAuthorPreapproved) {
|
|
||||||
// [?] https://docs.github.com/en/rest/reference/pulls#create-a-review-for-a-pull-request
|
|
||||||
await sails.helpers.http.post(`https://api.github.com/repos/${owner}/${repo}/pulls/${prNumber}/reviews`, {
|
|
||||||
event: 'REQUEST_CHANGES',
|
|
||||||
body: 'The repository has been frozen for an upcoming release. In case of emergency, you can dismiss this review and merge.'
|
|
||||||
}, baseHeaders);
|
|
||||||
}//fi
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fn: async function ({dry: isDryRun, limit: maxNumPullRequestsToCheck }) {
|
||||||
|
|
||||||
|
// sails.log('Running custom shell script... (`sails run freeze-open-pull-requests`)');
|
||||||
|
|
||||||
|
// let owner = 'fleetdm';
|
||||||
|
// let repo = 'fleet';
|
||||||
|
// let baseHeaders = {
|
||||||
|
// 'User-Agent': 'sails run freeze-open-pull-requests',
|
||||||
|
// 'Authorization': `token ${sails.config.custom.githubAccessToken}`
|
||||||
|
// };
|
||||||
|
|
||||||
|
// // Fetch open pull requests
|
||||||
|
// // [?] https://docs.github.com/en/rest/pulls/pulls#list-pull-requests
|
||||||
|
// let openPullRequests = await sails.helpers.http.get(`https://api.github.com/repos/${owner}/${repo}/pulls`, {
|
||||||
|
// state: 'open',
|
||||||
|
// per_page: maxNumPullRequestsToCheck,//eslint-disable-line camelcase
|
||||||
|
// }, baseHeaders);
|
||||||
|
|
||||||
|
// if (openPullRequests.length > maxNumPullRequestsToCheck) {
|
||||||
|
// openPullRequests = openPullRequests.slice(0,maxNumPullRequestsToCheck);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// let SECONDS_TO_WAIT = 5;
|
||||||
|
// sails.log(`Examining and potentially freezing ${openPullRequests.length} PRs very soon… (To cancel, press CTRL+C quickly within ${SECONDS_TO_WAIT}s!)`);
|
||||||
|
// await sails.helpers.flow.pause(SECONDS_TO_WAIT*1000);
|
||||||
|
|
||||||
|
// // For all open pull requests…
|
||||||
|
// await sails.helpers.flow.simultaneouslyForEach(openPullRequests, async(pullRequest)=>{
|
||||||
|
|
||||||
|
// let prNumber = pullRequest.number;
|
||||||
|
// let prAuthor = pullRequest.user.login;
|
||||||
|
// require('assert')(prAuthor !== undefined);
|
||||||
|
|
||||||
|
// // Freeze, if appropriate.
|
||||||
|
// // (Check versus the intersection of DRIs for all changed files to make sure SOMEONE is preapproved for all of them.)
|
||||||
|
// let isAuthorPreapproved = await sails.helpers.githubAutomations.getIsPrPreapproved.with({
|
||||||
|
// prNumber: prNumber,
|
||||||
|
// isGithubUserMaintainerOrDoesntMatter: true// « doesn't matter here because no auto-approval is happening. Worst case, a community PR to an area with a "*" in the DRI mapping remains unfrozen.
|
||||||
|
// });
|
||||||
|
|
||||||
|
// if (isDryRun) {
|
||||||
|
// sails.log(`#${prNumber} by @${prAuthor}:`, isAuthorPreapproved ? 'Would have skipped freeze…' : 'Would have frozen…');
|
||||||
|
// } else {
|
||||||
|
// sails.log(`#${prNumber} by @${prAuthor}:`, isAuthorPreapproved ? 'Skipping freeze…' : 'Freezing…');
|
||||||
|
// if (!isAuthorPreapproved) {
|
||||||
|
// // [?] https://docs.github.com/en/rest/reference/pulls#create-a-review-for-a-pull-request
|
||||||
|
// await sails.helpers.http.post(`https://api.github.com/repos/${owner}/${repo}/pulls/${prNumber}/reviews`, {
|
||||||
|
// event: 'REQUEST_CHANGES',
|
||||||
|
// body: 'The repository has been frozen for an upcoming release. In case of emergency, you can dismiss this review and merge.'
|
||||||
|
// }, baseHeaders);
|
||||||
|
// }//fi
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user