From 177d17682c328da94110f7a23bd9d9752c4c606c Mon Sep 17 00:00:00 2001 From: Oleksandr Khotemskyi Date: Thu, 26 Feb 2026 15:55:11 +0200 Subject: [PATCH] chore: removed jira integration as not used --- app/api/config/route.ts | 18 -- app/api/jira/config/route.ts | 54 ---- app/api/jira/create-ticket/route.ts | 117 ------- app/components/jira-ticket-modal.tsx | 300 ------------------ app/components/report-details/suite-tree.tsx | 43 +-- app/config/env.ts | 5 - app/lib/config.ts | 6 - app/lib/service/jira.ts | 288 ----------------- app/settings/components/JiraConfiguration.tsx | 194 ----------- app/settings/page.tsx | 49 +-- app/settings/types.ts | 18 -- app/types/index.ts | 8 - readme.md | 27 -- 13 files changed, 11 insertions(+), 1116 deletions(-) delete mode 100644 app/api/jira/config/route.ts delete mode 100644 app/api/jira/create-ticket/route.ts delete mode 100644 app/components/jira-ticket-modal.tsx delete mode 100644 app/lib/service/jira.ts delete mode 100644 app/settings/components/JiraConfiguration.tsx diff --git a/app/api/config/route.ts b/app/api/config/route.ts index d5347380..48125044 100644 --- a/app/api/config/route.ts +++ b/app/api/config/route.ts @@ -6,7 +6,6 @@ import { revalidatePath } from 'next/cache'; import { withError } from '@/app/lib/withError'; import { DATA_FOLDER } from '@/app/lib/storage/constants'; import { service } from '@/app/lib/service'; -import { JiraService } from '@/app/lib/service/jira'; import { env } from '@/app/config/env'; import { cronService } from '@/app/lib/service/cron'; @@ -60,10 +59,6 @@ export async function PATCH(request: Request) { const faviconPath = formData.get('faviconPath'); const reporterPaths = formData.get('reporterPaths'); const headerLinks = formData.get('headerLinks'); - const jiraBaseUrl = formData.get('jiraBaseUrl'); - const jiraEmail = formData.get('jiraEmail'); - const jiraApiToken = formData.get('jiraApiToken'); - const jiraProjectKey = formData.get('jiraProjectKey'); const resultExpireDays = formData.get('resultExpireDays'); const resultExpireCronSchedule = formData.get('resultExpireCronSchedule'); const reportExpireDays = formData.get('reportExpireDays'); @@ -114,19 +109,6 @@ export async function PATCH(request: Request) { if (parsedHeaderLinks) config.headerLinks = parsedHeaderLinks; } - if (!config.jira) { - config.jira = {}; - } - - if (jiraBaseUrl !== null) config.jira.baseUrl = jiraBaseUrl.toString(); - if (jiraEmail !== null) config.jira.email = jiraEmail.toString(); - if (jiraApiToken !== null) config.jira.apiToken = jiraApiToken.toString(); - if (jiraProjectKey !== null) config.jira.projectKey = jiraProjectKey.toString(); - - if (jiraBaseUrl || jiraEmail || jiraApiToken || jiraProjectKey) { - JiraService.resetInstance(); - } - if (!config.cron) { config.cron = {}; } diff --git a/app/api/jira/config/route.ts b/app/api/jira/config/route.ts deleted file mode 100644 index bf0e308b..00000000 --- a/app/api/jira/config/route.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { JiraService } from '@/app/lib/service/jira'; -import { service } from '@/app/lib/service'; - -export const dynamic = 'force-dynamic'; - -export async function GET() { - try { - const config = await service.getConfig(); - const jiraConfig = config.jira; - - const isConfigured = !!(jiraConfig?.baseUrl && jiraConfig?.email && jiraConfig?.apiToken); - - if (!isConfigured) { - return Response.json({ - configured: false, - message: 'Jira is not configured. Please configure Jira settings in the admin panel.', - config: jiraConfig || {}, - }); - } - - const jiraService = JiraService.getInstance(jiraConfig); - - let issueTypes = []; - - if (jiraConfig?.projectKey) { - try { - const project = await jiraService.getProject(jiraConfig.projectKey); - - issueTypes = project.issueTypes || []; - } catch (error) { - console.warn(`Could not fetch project-specific issue types for ${jiraConfig.projectKey}:`, error); - } - } - - return Response.json({ - configured: true, - baseUrl: jiraConfig.baseUrl, - defaultProjectKey: jiraConfig.projectKey, - issueTypes: issueTypes.map((type: any) => ({ - id: type.id, - name: type.name, - description: type.description, - })), - }); - } catch (error) { - return Response.json( - { - configured: false, - error: `Failed to connect to Jira: ${error instanceof Error ? error.message : 'Unknown error'}`, - }, - { status: 500 }, - ); - } -} diff --git a/app/api/jira/create-ticket/route.ts b/app/api/jira/create-ticket/route.ts deleted file mode 100644 index 3ddc4b5f..00000000 --- a/app/api/jira/create-ticket/route.ts +++ /dev/null @@ -1,117 +0,0 @@ -import { withError } from '@/app/lib/withError'; -import { JiraService } from '@/app/lib/service/jira'; -import { service } from '@/app/lib/service'; - -export const dynamic = 'force-dynamic'; - -interface CreateTicketRequest { - summary: string; - description: string; - issueType: string; - projectKey: string; - testId: string; - testTitle: string; - testOutcome: string; - testLocation: { - file: string; - line: number; - column: number; - }; - reportId: string; - testAttachments?: Array<{ - name: string; - path: string; - contentType: string; - }>; -} - -export async function POST(request: Request) { - const { result: data, error: parseError } = await withError(request.json()); - - if (parseError) { - return Response.json({ error: parseError.message }, { status: 400 }); - } - - if (!data) { - return Response.json({ error: 'Request data is missing' }, { status: 400 }); - } - - const ticketData = data as CreateTicketRequest; - - try { - const report = await service.getReport(ticketData.reportId); - const projectPath = report.project ? `${report.project}/` : ''; - - ticketData.testAttachments = ticketData.testAttachments?.map((att) => ({ - ...att, - path: `${projectPath}${ticketData.reportId}/${att.path}`, - })); - } catch (error) { - console.error(`Failed to get report ${ticketData.reportId}:`, error); - } - - try { - if (!ticketData.summary || !ticketData.projectKey) { - return Response.json( - { - error: 'Summary and project key are required', - }, - { status: 400 }, - ); - } - - const config = await service.getConfig(); - const jiraService = JiraService.getInstance(config.jira); - - const jiraResponse = await jiraService.createIssue( - ticketData.summary, - ticketData.description, - ticketData.issueType, - ticketData.projectKey, - { - testId: ticketData.testId, - testTitle: ticketData.testTitle, - testOutcome: ticketData.testOutcome, - testLocation: ticketData.testLocation, - }, - ticketData.testAttachments, - ); - - return Response.json( - { - success: true, - issueKey: jiraResponse.key, - issueId: jiraResponse.id, - issueUrl: jiraResponse.self, - message: 'Jira ticket created successfully', - data: { - ...ticketData, - issueKey: jiraResponse.key, - issueId: jiraResponse.id, - issueUrl: jiraResponse.self, - created: new Date().toISOString(), - }, - }, - { status: 201 }, - ); - } catch (error) { - console.error('Failed to create Jira ticket:', error); - - if (error instanceof Error && error.message.includes('Jira configuration is incomplete')) { - return Response.json( - { - error: - 'Jira is not configured. Please set up JIRA_BASE_URL, JIRA_EMAIL, and JIRA_API_TOKEN environment variables.', - }, - { status: 500 }, - ); - } - - return Response.json( - { - error: `Failed to create Jira ticket: ${error instanceof Error ? error.message : 'Unknown error'}`, - }, - { status: 500 }, - ); - } -} diff --git a/app/components/jira-ticket-modal.tsx b/app/components/jira-ticket-modal.tsx deleted file mode 100644 index 1e38361e..00000000 --- a/app/components/jira-ticket-modal.tsx +++ /dev/null @@ -1,300 +0,0 @@ -'use client'; - -import { useState, useEffect } from 'react'; -import { - Modal, - ModalContent, - ModalHeader, - ModalBody, - ModalFooter, - Button, - Input, - Textarea, - Select, - SelectItem, -} from '@heroui/react'; -import { toast } from 'sonner'; - -import { type ReportTest } from '@/app/lib/parser'; - -interface JiraTicketModalProps { - isOpen: boolean; - onOpenChange: (open: boolean) => void; - test: ReportTest | null; - reportId?: string; -} - -interface JiraTicketData { - summary: string; - description: string; - issueType: string; - projectKey: string; -} - -export default function JiraTicketModal({ isOpen, onOpenChange, test, reportId }: JiraTicketModalProps) { - const [ticketData, setTicketData] = useState({ - summary: '', - description: '', - issueType: 'Bug', - projectKey: '', - }); - const [isSubmitting, setIsSubmitting] = useState(false); - const [jiraConfig, setJiraConfig] = useState(null); - const [isLoadingConfig, setIsLoadingConfig] = useState(true); - - useEffect(() => { - const loadJiraConfig = async () => { - try { - const response = await fetch('/api/jira/config'); - const config = await response.json(); - - setJiraConfig(config); - - if (config.configured && config.defaultProjectKey && !ticketData.projectKey) { - setTicketData((prev) => ({ ...prev, projectKey: config.defaultProjectKey })); - } - - if (config.configured) { - const newDefaults: Partial = {}; - - if (config.issueTypes?.length > 0 && ticketData.issueType === 'Bug') { - newDefaults.issueType = config.issueTypes[0].name; - } - - if (Object.keys(newDefaults).length > 0) { - setTicketData((prev) => ({ ...prev, ...newDefaults })); - } - } - } catch (error) { - console.error('Failed to load Jira configuration:', error); - } finally { - setIsLoadingConfig(false); - } - }; - - if (isOpen) { - loadJiraConfig(); - } - }, [isOpen]); - - const handleSubmit = async () => { - if (!test) return; - - setIsSubmitting(true); - - try { - const testAttachments = - test.results?.[0]?.attachments?.map((att: any) => ({ - name: att.name, - path: att.path, - contentType: att.contentType, - })) || []; - - const requestData = { - ...ticketData, - testId: test.testId, - testTitle: test.title, - testOutcome: test.outcome, - testLocation: test.location, - testAttachments, - reportId: reportId, - }; - - const response = await fetch('/api/jira/create-ticket', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(requestData), - }); - - const result = await response.json(); - - if (!response.ok) { - throw new Error(result.error || 'Failed to create Jira ticket'); - } - - toast.success(`Jira ticket created: ${result.issueKey}`); - onOpenChange(false); - - setTicketData({ - summary: '', - description: '', - issueType: 'Bug', - projectKey: ticketData.projectKey, // Keep the current project key - }); - } catch (error) { - toast.error(`Failed to create Jira ticket: ${error instanceof Error ? error.message : 'Unknown error'}`); - } finally { - setIsSubmitting(false); - } - }; - - const generateDefaultSummary = () => { - if (!test) return ''; - - return `Test Failed: ${test.title}`; - }; - - const generateDefaultDescription = () => { - if (!test) return ''; - - return `Test Failure Details - Test: ${test.title} - Project: ${test.projectName} - Location: ${test.location.file}:${test.location.line} - Test ID: ${test.testId} - - Steps to Reproduce: - 1. Run the test suite - 2. Test "${test.title}" fails - - Expected Behavior: - Test should pass - - Actual Behavior: - Test is failing - - Additional Information: - - Duration: ${test.duration}ms - - Tags: ${test.tags.join(', ') || 'None'} - - Annotations: ${test.annotations.join(', ') || 'None'}`; - }; - - // Auto-populate form when test changes - if (test && (!ticketData.summary || ticketData.summary === '')) { - setTicketData((prev) => ({ - ...prev, - summary: generateDefaultSummary(), - description: generateDefaultDescription(), - })); - } - - return ( - - - {(onClose) => ( - <> - Create Jira Ticket - - {isLoadingConfig ? ( -
-
-
-

Loading Jira configuration...

-
-
- ) : !jiraConfig?.configured ? ( -
-
- - - -
-

Jira Not Configured

-

- {jiraConfig?.message || 'Jira integration is not properly configured.'} -

-
-

Required Environment Variables:

-
    -
  • • JIRA_BASE_URL
  • -
  • • JIRA_EMAIL
  • -
  • • JIRA_API_TOKEN
  • -
-
-
- ) : ( -
- setTicketData((prev) => ({ ...prev, summary: value }))} - /> -