From 4f9b2f7f065cbd60b389893b55fda99565816340 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 19 Sep 2025 13:38:21 +0100 Subject: [PATCH] Add initial client for repository properties --- src/feature-flags/properties.ts | 84 +++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 src/feature-flags/properties.ts diff --git a/src/feature-flags/properties.ts b/src/feature-flags/properties.ts new file mode 100644 index 000000000..58ae99ffc --- /dev/null +++ b/src/feature-flags/properties.ts @@ -0,0 +1,84 @@ +import { getApiClient } from "../api-client"; +import { Logger } from "../logging"; +import { RepositoryNwo } from "../repository"; + +/** + * Enumerates repository property names that have some meaning to us. + */ +export enum RepositoryPropertyName {} + +/** + * A repository property has a name and a value. + */ +export interface RepositoryProperty { + property_name: string; + value: string; +} + +/** + * The API returns a list of `RepositoryProperty` objects. + */ +type GitHubPropertiesResponse = RepositoryProperty[]; + +/** + * A partial mapping from `RepositoryPropertyName` to values. + */ +export type RepositoryProperties = Partial< + Record +>; + +/** + * Retrieves all known repository properties from the API. + * + * @param logger The logger to use. + * @param repositoryNwo Information about the repository for which to load properties. + * @returns Returns a partial mapping from `RepositoryPropertyName` to values. + */ +export async function loadPropertiesFromApi( + logger: Logger, + repositoryNwo: RepositoryNwo, +): Promise { + try { + const response = await getApiClient().request( + "GET /repos/:owner/:repo/properties/values", + { + owner: repositoryNwo.owner, + repo: repositoryNwo.repo, + }, + ); + const remoteProperties = response.data as GitHubPropertiesResponse; + + if (!Array.isArray(remoteProperties)) { + throw new Error( + `Expected repository properties API to return an array, but got: ${JSON.stringify(response.data)}`, + ); + } + + const knownProperties = new Set(Object.keys(RepositoryPropertyName)); + const properties: RepositoryProperties = {}; + for (const property of remoteProperties) { + if (property.property_name === undefined) { + throw new Error( + `Expected property object to have a 'property_name', but got: ${JSON.stringify(property)}`, + ); + } + + if (knownProperties.has(property.property_name)) { + properties[property.property_name] = property.value; + } + } + + logger.debug("Loaded the following values for the repository properties:"); + for (const [property, value] of Object.entries(properties).sort( + ([nameA], [nameB]) => nameA.localeCompare(nameB), + )) { + logger.debug(` ${property}: ${value}`); + } + + return properties; + } catch (e) { + throw new Error( + `Encountered an error while trying to determine repository properties: ${e}`, + ); + } +}