Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(deleted-project): Handle deleted Gitlab projects gracefully in project list and changelog #47

Merged
merged 2 commits into from
Oct 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions __tests__/project/listProjects.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,15 @@ describe('project > listProjects', () => {
channelId,
projectId: projectFixture.id + 1,
});
await addProjectToChannel({
channelId,
projectId: projectFixture.id + 2,
});

mockGitlabCall(`/projects/${projectFixture.id}`, projectFixture);
mockGitlabCall(`/projects/${projectFixture.id + 1}`, projectFixture);
// This project will be removed from the list because it doesn't exist
mockGitlabCall(`/projects/${projectFixture.id + 2}`, {});

// When
const response = await fetch('/api/v1/homer/command', {
Expand Down
20 changes: 16 additions & 4 deletions src/changelog/buildChangelogModalView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import { slackifyChangelog } from '@/changelog/utils/slackifyChangelog';
import { getProjectsByChannelId } from '@/core/services/data';
import { fetchProjectById, fetchProjectTags } from '@/core/services/gitlab';
import { logger } from '@/core/services/logger';
import type { GitlabProjectDetails } from '@/core/typings/GitlabProject';
import type { SlackOption } from '@/core/typings/SlackOption';

interface ChangelogModalData {
Expand All @@ -20,11 +22,21 @@
}: ChangelogModalData): Promise<View> {
if (channelId !== undefined && projectOptions === undefined) {
const dataProjects = await getProjectsByChannelId(channelId);
const projects = await Promise.all(
dataProjects.map(async (dataProject) =>
fetchProjectById(Number(dataProject.projectId))
const projects: GitlabProjectDetails[] = (

Check warning on line 25 in src/changelog/buildChangelogModalView.ts

View check run for this annotation

Codecov / codecov/patch

src/changelog/buildChangelogModalView.ts#L25

Added line #L25 was not covered by tests
await Promise.all(
dataProjects.map(async (dataProject) => {
try {
return await fetchProjectById(Number(dataProject.projectId));

Check warning on line 29 in src/changelog/buildChangelogModalView.ts

View check run for this annotation

Codecov / codecov/patch

src/changelog/buildChangelogModalView.ts#L27-L29

Added lines #L27 - L29 were not covered by tests
} catch (error) {
logger.error(

Check warning on line 31 in src/changelog/buildChangelogModalView.ts

View check run for this annotation

Codecov / codecov/patch

src/changelog/buildChangelogModalView.ts#L31

Added line #L31 was not covered by tests
`Failed to fetch project ${dataProject.projectId}:`,
error
);
return null;

Check warning on line 35 in src/changelog/buildChangelogModalView.ts

View check run for this annotation

Codecov / codecov/patch

src/changelog/buildChangelogModalView.ts#L35

Added line #L35 was not covered by tests
}
})
)
);
).filter((project): project is GitlabProjectDetails => project !== null);

Check warning on line 39 in src/changelog/buildChangelogModalView.ts

View check run for this annotation

Codecov / codecov/patch

src/changelog/buildChangelogModalView.ts#L39

Added line #L39 was not covered by tests

projectOptions = projects
.sort((a, b) =>
Expand Down
16 changes: 13 additions & 3 deletions src/project/commands/list/listProjectsRequestHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { Response } from 'express';
import { HTTP_STATUS_NO_CONTENT } from '@/constants';
import { getProjectsByChannelId } from '@/core/services/data';
import { fetchProjectById } from '@/core/services/gitlab';
import { logger } from '@/core/services/logger';
import { slackBotWebClient } from '@/core/services/slack';
import type { GitlabProjectDetails } from '@/core/typings/GitlabProject';
import type {
Expand All @@ -20,11 +21,20 @@ export async function listProjectsRequestHandler(

const { channel_id, user_id } = req.body as SlackSlashCommandResponse;
const dataProjects = await getProjectsByChannelId(channel_id);
const projects = (
const projects: GitlabProjectDetails[] = (
await Promise.all(
dataProjects.map(async ({ projectId }) => fetchProjectById(projectId))
dataProjects.map(async ({ projectId }) => {
try {
return await fetchProjectById(projectId);
} catch (error) {
logger.error(`Failed to fetch project ${projectId}:`, error);
return null;
}
})
)
).sort((a, b) => a.path_with_namespace.localeCompare(b.path_with_namespace));
)
.filter((project): project is GitlabProjectDetails => project !== null)
.sort((a, b) => a.path_with_namespace.localeCompare(b.path_with_namespace));

const projectsParts: GitlabProjectDetails[][] = [];

Expand Down
Loading