From ddd10522c433c320bda8fd6500783e53675ae92f Mon Sep 17 00:00:00 2001 From: Tet-9 Date: Wed, 13 May 2026 08:41:23 +0100 Subject: [PATCH] fix: normalize repoFullName to lowercase in validateRepoFullName Admin endpoints treated repoFullName as case-sensitive even though GitHub repository identity is case-insensitive. registerRepo did an exact-case update match that failed silently when request casing differed from stored row casing (e.g. 'Entrius/das-github-mirror' vs 'entrius/das-github-mirror'). Add .toLowerCase() to validateRepoFullName so all incoming values are normalized at the entry point before any persistence or lookup. This covers both the backfill and registerRepo endpoints which both call validateRepoFullName. Fixes #1214 fix: use LOWER() comparison for case-insensitive repoFullName matching Input-only normalization (.toLowerCase()) misses repos stored with GitHub's canonical casing. Storage keeps the original case from installation.handler.ts so lowercasing the input causes registerRepo's update and getTokenForRepo's findOneBy to miss rows for any repo whose stored name has uppercase characters. Apply the same LOWER(repo_full_name) = LOWER(:repoFullName) pattern already used in repos.service.ts and pulls.service.ts: - registerRepo: createQueryBuilder update with LOWER() WHERE clause - getTokenForRepo: createQueryBuilder select with LOWER() WHERE clause Fixes #1214 --- packages/das/src/api/admin.controller.ts | 10 ++++++---- packages/das/src/webhook/github-fetcher.service.ts | 7 ++++++- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/packages/das/src/api/admin.controller.ts b/packages/das/src/api/admin.controller.ts index fbe3151..fb6437b 100644 --- a/packages/das/src/api/admin.controller.ts +++ b/packages/das/src/api/admin.controller.ts @@ -123,10 +123,12 @@ export class AdminController { }> { const repoFullName = validateRepoFullName(body?.repoFullName); - const result = await this.repoRepo.update( - { repoFullName }, - { registered: true }, - ); + const result = await this.repoRepo + .createQueryBuilder() + .update() + .set({ registered: true }) + .where("LOWER(repo_full_name) = LOWER(:repoFullName)", { repoFullName }) + .execute(); if (!result.affected) { throw new NotFoundException( diff --git a/packages/das/src/webhook/github-fetcher.service.ts b/packages/das/src/webhook/github-fetcher.service.ts index 88ad900..865ba53 100644 --- a/packages/das/src/webhook/github-fetcher.service.ts +++ b/packages/das/src/webhook/github-fetcher.service.ts @@ -190,7 +190,12 @@ export class GitHubFetcherService implements OnModuleInit { } private async getTokenForRepo(repoFullName: string): Promise { - const repo = await this.repoRepo.findOneBy({ repoFullName }); + const repo = await this.repoRepo + .createQueryBuilder("repo") + .where("LOWER(repo.repo_full_name) = LOWER(:repoFullName)", { + repoFullName, + }) + .getOne(); if (!repo?.installationId) { throw new Error(`No installation for repo ${repoFullName}`); }