From cc820e9563e6b2fe4825fe8f0b6c996c81d6ff58 Mon Sep 17 00:00:00 2001 From: Rory Harness Date: Fri, 26 Jun 2026 08:50:09 -0600 Subject: [PATCH 1/2] fix: process repositories in batches to prevent partial sync on large orgs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When an org has many repositories, `eachRepositoryRepos` fires all of them concurrently via `Promise.all`. This exhausts GitHub's API rate limit (5,000 req/hr for app installations) mid-sync, causing the remaining repositories to be silently skipped — leaving them out of sync with the desired config. This change processes repositories in chunks of 10 using `Promise.allSettled`, so: 1. Concurrent API pressure stays well within rate limits 2. A single repo failure no longer aborts the entire sync — errors are logged individually and processing continues --- lib/settings.js | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/lib/settings.js b/lib/settings.js index fd7ca2693..63a9bd6c6 100644 --- a/lib/settings.js +++ b/lib/settings.js @@ -538,13 +538,23 @@ ${this.results.reduce((x, y) => { async eachRepositoryRepos (github, log) { log.debug('Fetching repositories') - return github.paginate('GET /installation/repositories').then(repositories => { - return Promise.all(repositories.map(repository => { - const { owner, name } = repository - return this.checkAndProcessRepo(owner.login, name) - }) + const repositories = await github.paginate('GET /installation/repositories') + const CONCURRENCY = 10 + const results = [] + for (let i = 0; i < repositories.length; i += CONCURRENCY) { + const chunk = repositories.slice(i, i + CONCURRENCY) + const chunkResults = await Promise.allSettled( + chunk.map(({ owner, name }) => this.checkAndProcessRepo(owner.login, name)) ) - }) + for (const result of chunkResults) { + if (result.status === 'fulfilled') { + results.push(result.value) + } else { + log.error(`Error processing repository in batch: ${result.reason}`) + } + } + } + return results } async checkAndProcessRepo (owner, name) { From 805f61ba166ed57f75bf737d86800a0e1d2d2eae Mon Sep 17 00:00:00 2001 From: Rory Harness Date: Fri, 26 Jun 2026 15:25:33 -0600 Subject: [PATCH 2/2] fix: include full-sync.js in Docker image --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index 1da906ff3..44a5df652 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,6 +11,7 @@ LABEL version="1.0" \ ## to the image to be as small as possible COPY package*.json /opt/safe-settings/ COPY index.js /opt/safe-settings/ +COPY full-sync.js /opt/safe-settings/ COPY lib /opt/safe-settings/lib ## Install the app and dependencies