Skip to content

Commit

Permalink
Merge branch 'main' into snyk-fix-7c624c8a76e8cb5453225c130601d9b1
Browse files Browse the repository at this point in the history
  • Loading branch information
PatrickAtlassian committed Oct 22, 2024
2 parents a7dc2de + 2d9e776 commit 0725677
Show file tree
Hide file tree
Showing 55 changed files with 1,897 additions and 1,457 deletions.
19 changes: 18 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,25 @@ module.exports = {
},
'import/external-module-folders': ['node_modules'],
},
parser: '@typescript-eslint/parser',
plugins: ['prettier', '@typescript-eslint', '@atlaskit/design-system'],
overrides: [
{
files: ['**/*.ts', '**/*.tsx'],
parser: '@typescript-eslint/parser',
parserOptions: {
project: ['./tsconfig.json', './ui/tsconfig.json'],
},
rules: {
'@typescript-eslint/no-misused-promises': [
'error',
{
checksVoidReturn: false,
},
],
'@typescript-eslint/no-floating-promises': 'error',
},
},
],
rules: {
'max-len': [
'warn',
Expand Down
4 changes: 3 additions & 1 deletion manifest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ modules:
- key: process-gitlab-event
handler: index.processGitlabEvent
- key: import-projects
handler: resolvers/import-queue-resolver.run
handler: index.importQueueResolver
- key: pre-uninstall
handler: index.preUninstall
- key: data-provider-fn
Expand All @@ -65,6 +65,8 @@ modules:
method: import
app:
id: ari:cloud:ecosystem::app/fe7b0913-7421-4c84-b401-041eaab2ef2e
runtime:
name: nodejs18.x
features:
autoUserConsent: true
resources:
Expand Down
16 changes: 7 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"private": true,
"devDependencies": {
"@atlaskit/eslint-plugin-design-system": "^8.7.0",
"@forge/cli": "^6.21.0",
"@forge/cli": "^10.5.0",
"@types/jest": "^27.4.1",
"@types/js-yaml": "^4.0.5",
"@types/lodash": "^4.14.182",
Expand All @@ -35,18 +35,16 @@
"typescript": "~4.5.5"
},
"dependencies": {
"@atlaskit/tokens": "^1.29.1",
"@atlassian/forge-graphql": "13.9.2",
"@forge/api": "^2.8.1",
"@forge/bridge": "^2.6.0",
"@forge/events": "^0.5.3",
"@forge/metrics": "^0.1.1",
"@forge/resolver": "^1.4.6",
"@atlassian/forge-graphql": "13.12.1",
"@forge/api": "^3.9.1",
"@forge/bridge": "^3.5.0",
"@forge/events": "^0.9.1",
"@forge/resolver": "^1.5.39",
"@forge/metrics": "0.2.18",
"@forge/ui": "^1.1.0",
"exponential-backoff": "^3.1.0",
"js-yaml": "^4.1.0",
"lodash": "^4.17.21",
"react-router-dom": "^6.3.0",
"url-parse": "^1.5.10"
},
"scripts": {
Expand Down
1 change: 1 addition & 0 deletions src/client/gitlab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ export const callGitlab = async (
headers: {
'PRIVATE-TOKEN': authToken,
Accept: config?.contentType || GitLabContentType.JSON,
'Content-Type': config?.contentType || GitLabContentType.JSON,
},
body,
});
Expand Down
15 changes: 11 additions & 4 deletions src/entry/config-validator/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,16 @@ import { ConfigValidatorResult, ConfigValidatorResponse } from '@atlassian/forge
import { getConnectedGroups } from '../../services/group';

export const configValidator = async (): Promise<ConfigValidatorResult> => {
const connectedGroups = await getConnectedGroups();
const appConfigured = connectedGroups && connectedGroups.length > 0;
try {
const connectedGroups = await getConnectedGroups();
const appConfigured = connectedGroups && connectedGroups.length > 0;

const response = new ConfigValidatorResponse(appConfigured);
return response.build();
const response = new ConfigValidatorResponse(appConfigured);
return response.build();
} catch (e) {
console.error('Could not determine installation state when invoking config validator');
const response = new ConfigValidatorResponse(false);
response.error = 'Could not determine installation state';
return response.build();
}
};
27 changes: 22 additions & 5 deletions src/entry/data-provider/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,34 @@ import { GitlabHttpMethodError } from '../../models/errors';
export const dataProvider = async (
request: DataProviderPayload,
): Promise<DataProviderResult | ForgeInvocationError> => {
const {
project: { id: projectId, default_branch: defaultBranch, name: projectName },
groupToken,
} = await getProjectDataFromUrl(request.url);
let projectId: number;
let defaultBranch: string;
let projectName: string;
let groupToken: string;
let trackingBranch: string;

try {
({
project: { id: projectId, default_branch: defaultBranch, name: projectName },
groupToken,
} = await getProjectDataFromUrl(request.url));
} catch (e) {
console.error(`Error while getting project data from URL in dataProvider ${e}`);
return null;
}

if (!projectId) {
console.warn('Cannot get GitLab project data by provided link.');
return null;
}

const trackingBranch = await getTrackingBranchName(groupToken, projectId, defaultBranch);
try {
trackingBranch = await getTrackingBranchName(groupToken, projectId, defaultBranch);
} catch (e) {
console.error(`Error while getting tracking branch name in dataProvider ${e}`);

return null;
}

const backfillData: BackfillData = {
builds: [],
Expand Down
9 changes: 7 additions & 2 deletions src/entry/extension-points/pre-uninstall.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { getFormattedErrors, hasRejections } from '../../utils/promise-allsettled-helpers';
import { disconnectGroup } from '../../services/disconnect-group';
import { getForgeAppId } from '../../utils/get-forge-app-id';
import { getGroupIds } from '../../utils/storage-utils';
Expand All @@ -14,10 +15,14 @@ export default async function preUninstall(payload: PreUninstallPayload): Promis
console.log(`Performing preUninstall for site ${cloudId}`);

const forgeAppId = getForgeAppId();
const groupIds = await getGroupIds();

try {
await Promise.all(groupIds.map((groupId) => disconnectGroup(groupId, cloudId, forgeAppId)));
const groupIds = await getGroupIds();

const results = await Promise.allSettled(groupIds.map((groupId) => disconnectGroup(groupId, cloudId, forgeAppId)));
if (hasRejections(results)) {
throw new Error(`Error while disconnecting groups: ${getFormattedErrors(results)}`);
}
} catch (e) {
console.error({ message: 'Error performing preUninstall', error: e });
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ jest.mock('../../../client/gitlab');
jest.mock('../../../services/insert-metric-values');
jest.mock('../../../utils/has-deployment-after-28days');

jest.spyOn(global.console, 'error').mockImplementation(() => ({}));

const mockedGetEnvironments = mocked(getEnvironments);
const mockedGetDeployment = mocked(getDeployment);
const mockedSendEventsToCompass = mocked(sendEventToCompass);
Expand All @@ -40,6 +42,7 @@ const MOCK_DEPLOYMENT_EVENT = generateDeploymentEvent();
const MOCK_ENVIRONMENTS_EVENT = generateEnvironmentEvent();
const PROJECT_ID = 123;
const MOCK_DATE = Date.parse('2022-01-29T01:15:42.960Z');
const MOCK_ERROR = new Error('Unexpected Error');

const generateMockDeploymentInput = (
environment = CompassDeploymentEventEnvironmentCategory.Production,
Expand Down Expand Up @@ -108,11 +111,26 @@ describe('GitLab deployment event', () => {

mockedGetEnvironments.mockResolvedValue([MOCK_PRODUCTION_ENVIRONMENT_EVENT]);

await expect(handleDeploymentEvent(MOCK_PRD_DEPLOYMENT_EVENT, TEST_TOKEN, MOCK_CLOUD_ID)).rejects.toThrow(
'Environment with name "prd" not found',
await handleDeploymentEvent(MOCK_PRD_DEPLOYMENT_EVENT, TEST_TOKEN, MOCK_CLOUD_ID);

expect(console.error).toHaveBeenCalledWith(
'Error while sending deployment event to Compass',
new Error('Environment with name "prd" not found'),
);
});

it('failed sending deployment event', async () => {
const MOCK_DEPLOYMENT_EVENT_INPUT = generateMockDeploymentInput();

mockedGetEnvironments.mockResolvedValue([MOCK_ENVIRONMENTS_EVENT]);
mockedGetDeployment.mockResolvedValue(MOCK_DEPLOYMENT_EVENT_INPUT);

mockedSendEventsToCompass.mockRejectedValue(MOCK_ERROR);

await handleDeploymentEvent(MOCK_DEPLOYMENT_EVENT, TEST_TOKEN, MOCK_CLOUD_ID);
expect(console.error).toHaveBeenCalledWith('Error while sending deployment event to Compass', MOCK_ERROR);
});

describe('when isSendStagingEventsEnabled', () => {
beforeEach(() => {
jest.spyOn(featureFlagService, 'isSendStagingEventsEnabled').mockReturnValue(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,19 @@ export const handleDeploymentEvent = async (
environment,
project: { id: projectId },
} = event;
const environments = await getProjectEnvironments(projectId, groupToken);
try {
const environments = await getProjectEnvironments(projectId, groupToken);

const environmentTier = await getEnvironmentTier(environments, environment);
const environmentTier = await getEnvironmentTier(environments, environment);

if (
environmentTier === EnvironmentTier.PRODUCTION ||
(isSendStagingEventsEnabled() && environmentTier === EnvironmentTier.STAGING)
) {
const deployment = await getDeployment(event, groupToken, environmentTier, cloudId);
await sendEventToCompass(deployment);
if (
environmentTier === EnvironmentTier.PRODUCTION ||
(isSendStagingEventsEnabled() && environmentTier === EnvironmentTier.STAGING)
) {
const deployment = await getDeployment(event, groupToken, environmentTier, cloudId);
await sendEventToCompass(deployment);
}
} catch (e) {
console.error('Error while sending deployment event to Compass', e);
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ jest.mock('../../../services/mergeRequest', () => ({
}));
jest.mock('../../../services/insert-metric-values');

jest.spyOn(global.console, 'error').mockImplementation(() => ({}));

const mockedGetTrackingBranchName = mocked(getTrackingBranchName);
const mockedGetLastMergedMergeRequests = mocked(getLastMergedMergeRequests);
const mockedGetOpenMergeRequests = mocked(getOpenMergeRequests);
Expand All @@ -34,6 +36,7 @@ const MOCK_METRIC_INPUT = generateMetricInput([
generateMetric(BuiltinMetricDefinitions.PULL_REQUEST_CYCLE_TIME_AVG_LAST_10),
generateMetric(BuiltinMetricDefinitions.OPEN_PULL_REQUESTS, 2),
]);
const MOCK_ERROR = new Error('Unexpected Error');

describe('Gitlab merge request', () => {
it('handles merge request event', async () => {
Expand All @@ -45,4 +48,16 @@ describe('Gitlab merge request', () => {

expect(mockedInsertMetricValues).toHaveBeenCalledWith(MOCK_METRIC_INPUT, MOCK_CLOUD_ID);
});

it('failed inserting merge request event', async () => {
mockedGetTrackingBranchName.mockResolvedValue(MOCK_MERGE_REQUEST_EVENT.project.default_branch);
mockedGetLastMergedMergeRequests.mockResolvedValue(mergeRequests);
mockedGetOpenMergeRequests.mockResolvedValue(mergeRequests);

mockedInsertMetricValues.mockRejectedValue(MOCK_ERROR);

await handleMergeRequestEvent(MOCK_MERGE_REQUEST_EVENT, TEST_TOKEN, MOCK_CLOUD_ID);

expect(console.error).toHaveBeenCalledWith('Error while inserting merge requests metric values', MOCK_ERROR);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { getTrackingBranchName } from '../../../services/get-tracking-branch';
import { MergeRequestEvent } from '../../../types';
import { insertMetricValues } from '../../../services/insert-metric-values';
import { getMRCycleTime, getOpenMergeRequestsCount } from '../../../services/compute-event-and-metrics';
import { ALL_SETTLED_STATUS, getFormattedErrors } from '../../../utils/promise-allsettled-helpers';

export const handleMergeRequestEvent = async (
event: MergeRequestEvent,
Expand All @@ -14,29 +15,48 @@ export const handleMergeRequestEvent = async (
project: { id, default_branch: defaultBranch },
object_attributes: { target_branch: targetBranch },
} = event;
const trackingBranch = await getTrackingBranchName(groupToken, id, defaultBranch);
try {
const trackingBranch = await getTrackingBranchName(groupToken, id, defaultBranch);

if (trackingBranch === targetBranch) {
const [cycleTime, openMergeRequestsCount] = await Promise.all([
getMRCycleTime(groupToken, id, trackingBranch),
getOpenMergeRequestsCount(groupToken, id, trackingBranch),
]);
if (trackingBranch === targetBranch) {
const [cycleTimeResult, openMergeRequestsCountResult] = await Promise.allSettled([
getMRCycleTime(groupToken, id, trackingBranch),
getOpenMergeRequestsCount(groupToken, id, trackingBranch),
]);

const metricInput = {
projectID: id.toString(),
metrics: [
{
metricAri: BuiltinMetricDefinitions.PULL_REQUEST_CYCLE_TIME_AVG_LAST_10,
value: cycleTime,
timestamp: new Date().toISOString(),
},
{
metricAri: BuiltinMetricDefinitions.OPEN_PULL_REQUESTS,
value: openMergeRequestsCount,
timestamp: new Date().toISOString(),
},
],
};
await insertMetricValues(metricInput, cloudId);
if (
cycleTimeResult.status === ALL_SETTLED_STATUS.REJECTED ||
openMergeRequestsCountResult.status === ALL_SETTLED_STATUS.REJECTED
) {
throw new Error(
`Failed to get merge request cycle time or open merge request count: ${getFormattedErrors([
cycleTimeResult,
openMergeRequestsCountResult,
])}`,
);
}

const cycleTime = cycleTimeResult.value;
const openMergeRequestsCount = openMergeRequestsCountResult.value;

const metricInput = {
projectID: id.toString(),
metrics: [
{
metricAri: BuiltinMetricDefinitions.PULL_REQUEST_CYCLE_TIME_AVG_LAST_10,
value: cycleTime,
timestamp: new Date().toISOString(),
},
{
metricAri: BuiltinMetricDefinitions.OPEN_PULL_REQUESTS,
value: openMergeRequestsCount,
timestamp: new Date().toISOString(),
},
],
};
await insertMetricValues(metricInput, cloudId);
}
} catch (e) {
console.error('Error while inserting merge requests metric values', e);
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ jest.mock('../../../client/gitlab');
jest.mock('../../../services/compute-event-and-metrics');
jest.mock('../../../services/insert-metric-values');

jest.spyOn(global.console, 'error').mockImplementation(() => ({}));

const MOCK_ERROR = new Error('Unexpected Error');

describe('Gitlab events', () => {
const event = generatePipelineEvent();

Expand Down Expand Up @@ -73,4 +77,14 @@ describe('Gitlab events', () => {
);
expect(insertMetricValuesMock).not.toBeCalled();
});

it('failed sending pipeline events', async () => {
getTrackingBranchNameMock.mockResolvedValue(event.project.default_branch);

sendEventToCompassMock.mockRejectedValue(MOCK_ERROR);

await handlePipelineEvent(event, TEST_TOKEN, MOCK_CLOUD_ID);

expect(console.error).toHaveBeenCalledWith('Error while sending pipeline event to Compass', MOCK_ERROR);
});
});
Loading

0 comments on commit 0725677

Please sign in to comment.