diff --git a/lib/settings.js b/lib/settings.js index e5b9f56b..284279c6 100644 --- a/lib/settings.js +++ b/lib/settings.js @@ -424,12 +424,51 @@ ${this.results.reduce((x, y) => { async getRepoConfigMap () { try { this.log.debug(` In getRepoConfigMap ${JSON.stringify(this.repo)}`) + // GitHub getContent api has a hard limit of returning 1000 entries without + // any pagination. They suggest to use Tree api. + // https://docs.github.com/en/rest/repos/contents?apiVersion=2022-11-28#get-repository-content + + // get .github/repos directory sha to use in the getTree api const repo = { owner: this.repo.owner, repo: 'admin' } - const CONFIG_PATH = '.github' - const params = Object.assign(repo, { path: path.posix.join(CONFIG_PATH, 'repos'), ref: this.ref }) + const params = Object.assign(repo, { path: path.posix.join(CONFIG_PATH), ref: this.ref }) + const githubDirectoryContentResponse = await this.github.repos.getContent(params).catch(e => { + this.log.debug(`Error getting settings ${JSON.stringify(params)} ${e}`) + }) - const response = await this.loadConfigMap(params) - return response + if (!githubDirectoryContentResponse) { + throw new Error('Error reading .github directory') + } + + const githubDirContent = githubDirectoryContentResponse.data + const repoDirInfo = githubDirContent.filter(dir => dir.name === 'repos')[0] + if (!repoDirInfo) { + this.log.debug('No repos directory in the admin/.github') + return [] + } + + // read the repo contents using tree + this.log.debug(`repos directory info ${JSON.stringify(repoDirInfo)}`) + const endpoint = `/repos/${this.repo.owner}/${repo.repo}/git/trees/${repoDirInfo.sha}` + this.log.debug(`endpoint: ${endpoint}`) + const response = await this.github.request(`GET ${endpoint}`).catch(e => { + this.log.debug(`Error getting settings ${JSON.stringify(endpoint)} ${e}`) + }) + + if (!response || !response.data) { + this.log.debug('repos directory exist but reading the tree failed') + throw new Error('exception while reading the repos directory') + } + // throw error if truncated is true. + if (response.data.truncated) { + this.log.debug('not all repo files in directory are read') + throw new Error('not all repo files in directory are read') + } + const treeInfo = response.data.tree + // we emulated the existing loadConfigMap function as is by returning the + // the same overrides list. This way the overall changes are minimal + const overrides = treeInfo.map(d => { return { name: d.path, path: path.posix.join(CONFIG_PATH, 'repos', d.path) } }) + this.log.debug('Total overrides found in getRepoConfigMap are ' + overrides.length) + return overrides } catch (e) { if (this.nop) { const nopcommand = new NopCommand('getRepoConfigMap', this.repo, null, e, 'ERROR') @@ -657,4 +696,4 @@ Settings.PLUGINS = { validator: require('./plugins/validator') } -module.exports = Settings \ No newline at end of file +module.exports = Settings