Skip to content

Commit c4e423a

Browse files
authored
Merge pull request #1341 from kodustech/phantom-rules
fix(kody-rules): auto-register repository in CODE_REVIEW_CONFIG on ru…
2 parents 7a22a93 + dfc2c43 commit c4e423a

2 files changed

Lines changed: 126 additions & 0 deletions

File tree

libs/ee/kodyRules/service/kodyRules.service.ts

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,21 @@ import {
8585
} from '@libs/platformData/domain/pullRequests/contracts/pullRequests.repository';
8686
import { KodyRulesValidationService } from './kody-rules-validation.service';
8787
import { buildKodyRuleAppLink } from '../utils/build-rule-link';
88+
import {
89+
IParametersService,
90+
PARAMETERS_SERVICE_TOKEN,
91+
} from '@libs/organization/domain/parameters/contracts/parameters.service.contract';
92+
import { ParametersKey } from '@libs/core/domain/enums';
93+
import {
94+
CodeReviewParameter,
95+
ICodeRepository,
96+
RepositoryCodeReviewConfig,
97+
} from '@libs/core/infrastructure/config/types/general/codeReviewConfig.type';
98+
import { IntegrationConfigKey } from '@libs/core/domain/enums/Integration-config-key.enum';
99+
import {
100+
IIntegrationConfigService,
101+
INTEGRATION_CONFIG_SERVICE_TOKEN,
102+
} from '@libs/integrations/domain/integrationConfigs/contracts/integration-config.service.contracts';
88103

89104
@Injectable()
90105
export class KodyRulesService implements IKodyRulesService {
@@ -370,6 +385,11 @@ export class KodyRulesService implements IKodyRulesService {
370385
ruleTitle: newRule.title,
371386
});
372387

388+
await this.ensureRepositoryCodeReviewConfig(
389+
organizationAndTeamData,
390+
newRule,
391+
);
392+
373393
return newKodyRules.rules[0];
374394
}
375395

@@ -440,6 +460,11 @@ export class KodyRulesService implements IKodyRulesService {
440460
ruleTitle: newRule.title,
441461
});
442462

463+
await this.ensureRepositoryCodeReviewConfig(
464+
organizationAndTeamData,
465+
newRule,
466+
);
467+
443468
return updatedKodyRules.rules.find(
444469
(rule) => rule.uuid === newRule.uuid,
445470
);
@@ -513,6 +538,104 @@ export class KodyRulesService implements IKodyRulesService {
513538
);
514539
}
515540

541+
private async ensureRepositoryCodeReviewConfig(
542+
organizationAndTeamData: OrganizationAndTeamData,
543+
rule: Partial<IKodyRule>,
544+
): Promise<void> {
545+
if (
546+
rule.origin === KodyRulesOrigin.USER ||
547+
!rule.repositoryId ||
548+
rule.repositoryId === 'global'
549+
) {
550+
return;
551+
}
552+
553+
let parametersService: IParametersService;
554+
let integrationConfigService: IIntegrationConfigService;
555+
try {
556+
parametersService = this.moduleRef.get(PARAMETERS_SERVICE_TOKEN, {
557+
strict: false,
558+
});
559+
integrationConfigService = this.moduleRef.get(
560+
INTEGRATION_CONFIG_SERVICE_TOKEN,
561+
{ strict: false },
562+
);
563+
} catch {
564+
return;
565+
}
566+
567+
try {
568+
const codeReviewConfig =
569+
await parametersService.findByKey(
570+
ParametersKey.CODE_REVIEW_CONFIG,
571+
organizationAndTeamData,
572+
);
573+
574+
if (!codeReviewConfig?.configValue) {
575+
return;
576+
}
577+
578+
const configValue =
579+
codeReviewConfig.configValue as CodeReviewParameter;
580+
const repositories = configValue.repositories || [];
581+
582+
if (repositories.some((r) => r.id === rule.repositoryId)) {
583+
return;
584+
}
585+
586+
let repositoryName = rule.repositoryId;
587+
try {
588+
const repos =
589+
await integrationConfigService.findIntegrationConfigFormatted<
590+
ICodeRepository[]
591+
>(
592+
IntegrationConfigKey.REPOSITORIES,
593+
organizationAndTeamData,
594+
);
595+
596+
const matched = repos?.find(
597+
(r) => r.id === rule.repositoryId,
598+
);
599+
if (matched?.name) {
600+
repositoryName = matched.name;
601+
}
602+
} catch {
603+
// fallback: use repositoryId as name
604+
}
605+
606+
const newRepo: RepositoryCodeReviewConfig = {
607+
id: rule.repositoryId,
608+
name: repositoryName,
609+
isSelected: true,
610+
configs: {},
611+
};
612+
613+
const updatedConfigValue: CodeReviewParameter = {
614+
...configValue,
615+
repositories: [...repositories, newRepo],
616+
};
617+
618+
await parametersService.createOrUpdateConfig(
619+
ParametersKey.CODE_REVIEW_CONFIG,
620+
updatedConfigValue,
621+
organizationAndTeamData,
622+
);
623+
} catch (error) {
624+
this.logger.error({
625+
message:
626+
'Failed to auto-create repository config for auto-generated rule',
627+
context: KodyRulesService.name,
628+
error,
629+
metadata: {
630+
repositoryId: rule.repositoryId,
631+
ruleId: rule.uuid,
632+
ruleOrigin: rule.origin,
633+
organizationAndTeamData,
634+
},
635+
});
636+
}
637+
}
638+
516639
async updateRuleReferences(
517640
organizationId: string,
518641
ruleId: string,

test/unit/code-review/pipeline/stages/agent-review.stage.spec.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -671,6 +671,9 @@ describe('AgentReviewStage', () => {
671671
expect(
672672
mockAutomationService.updateCodeReview.mock.calls[0][1].status,
673673
).toBe('error');
674+
});
675+
});
676+
674677
describe('deduplicateSuggestions - NaN index handling (three-layer protection)', () => {
675678
const makeSuggestions = (count: number) =>
676679
Array.from({ length: count }, (_, i) => ({

0 commit comments

Comments
 (0)