From b8fb174436a30cef7439c50071cabd0dfc89d77b Mon Sep 17 00:00:00 2001 From: Nicolas Lepage <19571875+nlepage@users.noreply.github.com> Date: Tue, 19 Nov 2024 16:30:43 +0100 Subject: [PATCH] WIP feat: adds a debounce for RA deployments --- build/controllers/github.js | 6 +++--- common/services/scalingo-client.js | 23 ++++++++++++++++++++++- config.js | 1 + sample.env | 7 +++++++ 4 files changed, 33 insertions(+), 4 deletions(-) diff --git a/build/controllers/github.js b/build/controllers/github.js index 7e56584c..e91ca16f 100644 --- a/build/controllers/github.js +++ b/build/controllers/github.js @@ -187,7 +187,7 @@ async function _handleIssueComment(request, scalingoClient = ScalingoClient, git const branchName = await githubService.getPullRequestBranchName({ repo, owner, pull_number }); - await client.deployUsingSCM(reviewAppName, branchName); + await client.deployUsingSCM(reviewAppName, branchName, config.ecoMode.deployDebounce); return 'ok'; } @@ -214,12 +214,12 @@ async function deployPullRequest( try { const reviewAppExists = await client.reviewAppExists(reviewAppName); if (reviewAppExists) { - await client.deployUsingSCM(reviewAppName, ref); + await client.deployUsingSCM(reviewAppName, ref, config.ecoMode.deployDebounce); } else { await reviewAppRepository.create({ name: reviewAppName, repository, prNumber: prId, parentApp: appName }); await client.deployReviewApp(appName, prId); await client.disableAutoDeploy(reviewAppName); - await client.deployUsingSCM(reviewAppName, ref); + await client.deployUsingSCM(reviewAppName, ref, config.ecoMode.deployDebounce); } deployedRA.push({ name: appName, isCreated: !reviewAppExists }); } catch (error) { diff --git a/common/services/scalingo-client.js b/common/services/scalingo-client.js index e9fd92f5..82379f5e 100644 --- a/common/services/scalingo-client.js +++ b/common/services/scalingo-client.js @@ -6,6 +6,8 @@ import { logger } from './logger.js'; const DEFAULT_OPTS = { withEnvSuffix: true }; +const debouncedDeployments = new Map(); + class ScalingoClient { constructor(client, environment) { this.client = client; @@ -47,7 +49,26 @@ class ScalingoClient { return `${scalingoApp} ${releaseTag} has been deployed`; } - async deployUsingSCM(scalingoApp, releaseTag) { + async deployUsingSCM(scalingoApp, releaseTag, debounce) { + if (!debounce) return this.#requestDeploymentUsingSCM(scalingoApp, releaseTag); + + if (debouncedDeployments.has(scalingoApp)) { + clearTimeout(debouncedDeployments.get(scalingoApp)); + } + + debouncedDeployments.set( + scalingoApp, + setTimeout(() => { + this.#requestDeploymentUsingSCM(scalingoApp, releaseTag).catch(() => {}); + debouncedDeployments.delete(scalingoApp); + }, debounce), + ); + + logger.info({ message: `Deployment of ${scalingoApp} ${releaseTag} will be requested after ${debounce}ms` }); + return `Deployment of ${scalingoApp} ${releaseTag} will be requested after ${debounce}ms`; + } + + async #requestDeploymentUsingSCM(scalingoApp, releaseTag) { try { await this.client.SCMRepoLinks.manualDeploy(scalingoApp, releaseTag); } catch (e) { diff --git a/config.js b/config.js index 937cf20d..5eccbb84 100644 --- a/config.js +++ b/config.js @@ -25,6 +25,7 @@ const configuration = (function () { ecoMode: { stopSchedule: process.env.REVIEW_APP_STOP_SCHEDULE, startSchedule: process.env.REVIEW_APP_START_SCHEDULE, + deployDebounce: _getNumber(process.env.REVIEW_APP_DEPLOY_DEBOUNCE, 30) * 1000, }, baleen: { diff --git a/sample.env b/sample.env index a9fd0769..f551b512 100644 --- a/sample.env +++ b/sample.env @@ -324,6 +324,13 @@ SCALINGO_TOKEN_REVIEW_APPS=__CHANGE_ME__ # default: "0 0 8 * * 1-5" #REVIEW_APP_START_SCHEDULE=0 0 8 * * 1-5 +# Debounce time for deploying review apps. +# +# presence: optionnal +# type: number +# default: 30 +#REVIEW_APP_DEPLOY_DEBOUNCE=30 + # List of review apps that must not be managed. # # If not present, all the review apps will be stopped and restrated.