From a178f476284b65a36cbf93a7021c07f8adc63b6b Mon Sep 17 00:00:00 2001 From: PendaGTP <38917281+PendaGTP@users.noreply.github.com> Date: Mon, 20 Jan 2025 10:42:54 +0100 Subject: [PATCH] refactor: improve fetching repositories with custom properties --- lib/settings.js | 68 ++++++++++++++++++++++++++-------- test/unit/lib/settings.test.js | 4 +- 2 files changed, 54 insertions(+), 18 deletions(-) diff --git a/lib/settings.js b/lib/settings.js index 9e00c140..4fa3b25e 100644 --- a/lib/settings.js +++ b/lib/settings.js @@ -768,16 +768,10 @@ ${this.results.reduce((x, y) => { }) } if (data.suborgproperties) { - const promises = data.suborgproperties.map((customProperty) => { - return this.getReposForCustomProperty(customProperty) - }) - await Promise.all(promises).then(res => { - res.forEach(r => { - r.forEach(e => { - this.storeSubOrgConfigIfNoConflicts(subOrgConfigs, override.path, e.repository_name, data) - }) - }) - }) + const subOrgRepositories = await this.getSubOrgRepositories(data.suborgproperties) + subOrgRepositories.forEach(repo => + this.storeSubOrgConfigIfNoConflicts(subOrgConfigs, override.path, repo.repository_name, data) + ) } } @@ -876,12 +870,54 @@ ${this.results.reduce((x, y) => { return this.github.paginate(options) } - async getReposForCustomProperty (customPropertyTuple) { - const name = Object.keys(customPropertyTuple)[0] - let q = `props.${name}:${customPropertyTuple[name]}` - q = encodeURIComponent(q) - const options = this.github.request.endpoint((`/orgs/${this.repo.owner}/properties/values?repository_query=${q}`)) - return this.github.paginate(options) + async getRepositoriesByProperty (organizationName, propertyFilter) { + if (!organizationName || !propertyFilter) { + throw new Error('Organization name and property filter are required') + } + + const [name] = Object.keys(propertyFilter) + const value = propertyFilter[name] + + try { + const query = `props.${name}.${value}` + const encodedQuery = encodeURIComponent(query) + + return this.github.paginate( + this.github.repos.getCustomPropertiesValues, + { + org: organizationName, + repository_query: encodedQuery, + per_page: 100 + } + ) + } catch (error) { + throw new Error(`Failed to filter repositories for property ${name}: ${error.message}`) + } + } + + async getSubOrgRepositories (subOrgProperties) { + const organizationName = this.repo.owner + try { + const repositories = await Promise.all( + subOrgProperties.map(property => + this.getRepositoriesByProperty(organizationName, property) + ) + ) + + // Deduplicate repositories based on repository_name + const uniqueRepos = repositories + .flat() + .reduce((unique, repo) => { + unique.set(repo.repository_name, repo) + return unique + }, new Map()) + + const result = Array.from(uniqueRepos.values()) + + return result + } catch (error) { + throw new Error(`Failed to fetch suborg repositories: ${error.message}`) + } } isObject (item) { diff --git a/test/unit/lib/settings.test.js b/test/unit/lib/settings.test.js index c91583d3..d738a46e 100644 --- a/test/unit/lib/settings.test.js +++ b/test/unit/lib/settings.test.js @@ -234,7 +234,7 @@ repository: jest.spyOn(settings, 'loadConfigMap').mockImplementation(() => [{ name: "frontend", path: ".github/suborgs/frontend.yml" }]) jest.spyOn(settings, 'loadYaml').mockImplementation(() => subOrgConfig) jest.spyOn(settings, 'getReposForTeam').mockImplementation(() => [{ name: 'repo-test' }]) - jest.spyOn(settings, 'getReposForCustomProperty').mockImplementation(() => [{ repository_name: 'repo-for-property' }]) + jest.spyOn(settings, 'getSubOrgRepositories').mockImplementation(() => [{ repository_name: 'repo-for-property' }]) const subOrgConfigs = await settings.getSubOrgConfigs() expect(settings.loadConfigMap).toHaveBeenCalledTimes(1) @@ -251,7 +251,7 @@ repository: jest.spyOn(settings, 'loadConfigMap').mockImplementation(() => [{ name: "frontend", path: ".github/suborgs/frontend.yml" }, { name: "backend", path: ".github/suborgs/backend.yml" }]) jest.spyOn(settings, 'loadYaml').mockImplementation(() => subOrgConfig) jest.spyOn(settings, 'getReposForTeam').mockImplementation(() => [{ name: 'repo-test' }]) - jest.spyOn(settings, 'getReposForCustomProperty').mockImplementation(() => [{ repository_name: 'repo-for-property' }]) + jest.spyOn(settings, 'getSubOrgRepositories').mockImplementation(() => [{ repository_name: 'repo-for-property' }]) expect(async () => await settings.getSubOrgConfigs()).rejects.toThrow('Multiple suborg configs for new-repo in .github/suborgs/backend.yml and .github/suborgs/frontend.yml') // try {