feat: add GitHub App Installation ID to Project migration and update related components

This commit is contained in:
Nawaz Dhandala 2025-12-28 22:50:53 +00:00
parent d8806159e4
commit 9ff1a20858
No known key found for this signature in database
GPG key ID: 96C5DCA24769DBCA
7 changed files with 82 additions and 33 deletions

View file

@ -1,18 +1,31 @@
import { MigrationInterface, QueryRunner } from "typeorm";
export class AddGitHubAppInstallationIdToProject1766958924188 implements MigrationInterface {
name = 'AddGitHubAppInstallationIdToProject1766958924188'
export class AddGitHubAppInstallationIdToProject1766958924188
implements MigrationInterface
{
public name = "AddGitHubAppInstallationIdToProject1766958924188";
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "Project" ADD "gitHubAppInstallationId" character varying`);
await queryRunner.query(`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type":"Recurring","value":{"intervalType":"Day","intervalCount":{"_type":"PositiveNumber","value":1}}}'`);
await queryRunner.query(`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type":"RestrictionTimes","value":{"restictionType":"None","dayRestrictionTimes":null,"weeklyRestrictionTimes":[]}}'`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type": "RestrictionTimes", "value": {"restictionType": "None", "dayRestrictionTimes": null, "weeklyRestrictionTimes": []}}'`);
await queryRunner.query(`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type": "Recurring", "value": {"intervalType": "Day", "intervalCount": {"_type": "PositiveNumber", "value": 1}}}'`);
await queryRunner.query(`ALTER TABLE "Project" DROP COLUMN "gitHubAppInstallationId"`);
}
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "Project" ADD "gitHubAppInstallationId" character varying`,
);
await queryRunner.query(
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type":"Recurring","value":{"intervalType":"Day","intervalCount":{"_type":"PositiveNumber","value":1}}}'`,
);
await queryRunner.query(
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type":"RestrictionTimes","value":{"restictionType":"None","dayRestrictionTimes":null,"weeklyRestrictionTimes":[]}}'`,
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type": "RestrictionTimes", "value": {"restictionType": "None", "dayRestrictionTimes": null, "weeklyRestrictionTimes": []}}'`,
);
await queryRunner.query(
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type": "Recurring", "value": {"intervalType": "Day", "intervalCount": {"_type": "PositiveNumber", "value": 1}}}'`,
);
await queryRunner.query(
`ALTER TABLE "Project" DROP COLUMN "gitHubAppInstallationId"`,
);
}
}

View file

@ -427,5 +427,5 @@ export default [
MigrationName1766777986427,
AddAIAgentIsDefault1766918848434,
MigrationName1766923324521,
AddGitHubAppInstallationIdToProject1766958924188
AddGitHubAppInstallationIdToProject1766958924188,
];

View file

@ -80,7 +80,8 @@ const GitRepoConnectionModal: FunctionComponent<ComponentProps> = (
fieldType: FormFieldSchemaType.Text,
required: true,
placeholder: "my-organization",
description: "The organization or username that owns the repository",
description:
"The organization or username that owns the repository",
},
{
field: {
@ -101,7 +102,8 @@ const GitRepoConnectionModal: FunctionComponent<ComponentProps> = (
fieldType: FormFieldSchemaType.Text,
required: false,
placeholder: "main",
description: "The main branch of the repository (defaults to 'main')",
description:
"The main branch of the repository (defaults to 'main')",
},
{
field: {

View file

@ -136,7 +136,9 @@ const CodeRepositoryPage: FunctionComponent<
title="Connect Repository"
description="Connect your code repositories to enable code analysis, automatic improvements, and CI/CD integration."
>
<div className={`grid gap-4 ${isGitHubAppConfigured ? "md:grid-cols-2" : "md:grid-cols-1"}`}>
<div
className={`grid gap-4 ${isGitHubAppConfigured ? "md:grid-cols-2" : "md:grid-cols-1"}`}
>
{/* GitHub App Option */}
{isGitHubAppConfigured && (
<div
@ -146,8 +148,16 @@ const CodeRepositoryPage: FunctionComponent<
<div className="flex items-start space-x-4">
<div className="flex-shrink-0">
<div className="flex h-12 w-12 items-center justify-center rounded-lg bg-gray-900 text-white">
<svg className="h-6 w-6" fill="currentColor" viewBox="0 0 24 24">
<path fillRule="evenodd" d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z" clipRule="evenodd" />
<svg
className="h-6 w-6"
fill="currentColor"
viewBox="0 0 24 24"
>
<path
fillRule="evenodd"
d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z"
clipRule="evenodd"
/>
</svg>
</div>
</div>
@ -156,7 +166,8 @@ const CodeRepositoryPage: FunctionComponent<
Connect with GitHub App
</h3>
<p className="mt-1 text-sm text-gray-500">
Recommended for GitHub repositories. Provides seamless integration with automatic authentication.
Recommended for GitHub repositories. Provides seamless
integration with automatic authentication.
</p>
<div className="mt-3">
<span className="inline-flex items-center rounded-full bg-green-50 px-2 py-1 text-xs font-medium text-green-700 ring-1 ring-inset ring-green-600/20">
@ -176,8 +187,18 @@ const CodeRepositoryPage: FunctionComponent<
<div className="flex items-start space-x-4">
<div className="flex-shrink-0">
<div className="flex h-12 w-12 items-center justify-center rounded-lg bg-indigo-600 text-white">
<svg className="h-6 w-6" fill="none" viewBox="0 0 24 24" strokeWidth="1.5" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" d="M17.25 6.75L22.5 12l-5.25 5.25m-10.5 0L1.5 12l5.25-5.25m7.5-3l-4.5 16.5" />
<svg
className="h-6 w-6"
fill="none"
viewBox="0 0 24 24"
strokeWidth="1.5"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M17.25 6.75L22.5 12l-5.25 5.25m-10.5 0L1.5 12l5.25-5.25m7.5-3l-4.5 16.5"
/>
</svg>
</div>
</div>
@ -186,7 +207,8 @@ const CodeRepositoryPage: FunctionComponent<
Connect with Access Token
</h3>
<p className="mt-1 text-sm text-gray-500">
Connect any Git repository (GitHub, GitLab, etc.) using a personal access token.
Connect any Git repository (GitHub, GitLab, etc.) using a
personal access token.
</p>
<div className="mt-3">
<span className="inline-flex items-center rounded-full bg-gray-50 px-2 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10">
@ -215,7 +237,9 @@ const CodeRepositoryPage: FunctionComponent<
"Your connected code repositories for code analysis and improvements.",
}}
showViewIdButton={true}
noItemsMessage={"No repositories connected. Use the buttons above to connect a repository."}
noItemsMessage={
"No repositories connected. Use the buttons above to connect a repository."
}
showRefreshButton={true}
viewPageRoute={Navigation.getCurrentRoute()}
filters={[

View file

@ -18,8 +18,10 @@ import ProxyConfig from "../Utils/ProxyConfig";
const router: ExpressRouter = Express.getRouter();
// Metrics endpoint for Keda autoscaling
// Returns the number of monitors pending to be probed by this probe
/*
* Metrics endpoint for Keda autoscaling
* Returns the number of monitors pending to be probed by this probe
*/
router.get(
"/queue-size",
async (
@ -28,8 +30,10 @@ router.get(
next: NextFunction,
): Promise<void> => {
try {
// Get the pending monitor count for this specific probe from ProbeIngest API
// This is the correct metric - the number of monitors waiting to be probed
/*
* Get the pending monitor count for this specific probe from ProbeIngest API
* This is the correct metric - the number of monitors waiting to be probed
*/
const pendingMonitorsUrl: URL = URL.fromString(
PROBE_INGEST_URL.toString(),
).addRoute("/monitor/pending-count");
@ -51,7 +55,9 @@ router.get(
});
if (result instanceof HTTPErrorResponse) {
logger.error("Error fetching pending monitor count from ProbeIngest API");
logger.error(
"Error fetching pending monitor count from ProbeIngest API",
);
logger.error(result);
throw result;
}

View file

@ -277,8 +277,10 @@ router.get(
},
);
// This API returns the count of monitors pending to be probed for the authenticated probe.
// Used by KEDA for autoscaling probes based on pending monitor count.
/*
* This API returns the count of monitors pending to be probed for the authenticated probe.
* Used by KEDA for autoscaling probes based on pending monitor count.
*/
router.post(
"/monitor/pending-count",
ProbeAuthorization.isAuthorizedServiceMiddleware,

View file

@ -188,9 +188,11 @@ describe("ExceptionUtil", () => {
test("handles null/undefined gracefully", () => {
// @ts-expect-error - testing edge case
const normalizedNull: string = ExceptionUtil.normalizeForFingerprint(null);
const normalizedNull: string =
ExceptionUtil.normalizeForFingerprint(null);
// @ts-expect-error - testing edge case
const normalizedUndefined: string = ExceptionUtil.normalizeForFingerprint(undefined);
const normalizedUndefined: string =
ExceptionUtil.normalizeForFingerprint(undefined);
expect(normalizedNull).toBe("");
expect(normalizedUndefined).toBe("");