I am creating an application in which there is a Jenkins Pipeline responsible for cloning repository and running megalinter on it and then when the process is completed the megalinter.log file is cleaned and issues are shown in Issues.jsx page. Till the pipeline build process is going on there is a animation under which the pipeline status is shown but following errors are seen
-Even when the pipeline is triggered successfully then too just after few seconds these errors are seen in the console log.
-There are no articafts being fetched even when the build is completed
-The stages of animation is showing failed in few seconds but pipeline is triggred in jenins so I don’t know what’s causing these erros.
I don’t know from where that 147 is coming I am not even using that url
I tried these things in code
Jenkins Pipeline
pipeline {
agent any
environment {
NODEJS_HOME = tool name: 'NodeJS', type: 'jenkins.plugins.nodejs.tools.NodeJSInstallation'
PATH = "${env.NODEJS_HOME}/bin:${env.PATH}"
}
parameters {
string(name: 'REPO_URL', defaultValue: '', description: 'URL of the Git repository to analyze')
}
stages {
stage('Clone Repository') {
steps {
script {
try {
git url: "${params.REPO_URL}", branch: 'main'
} catch (Exception e) {
echo "Main branch not found, trying master branch"
git url: "${params.REPO_URL}", branch: 'master'
}
}
}
}
stage('Run MegaLinter') {
steps {
script {
try {
bat "npx mega-linter-runner --flavor cupcake --release v6"
} catch (Exception e) {
echo "MegaLinter found issues, but continuing pipeline"
}
}
}
}
}
post {
always {
archiveArtifacts artifacts: 'megalinter-reports/**', allowEmptyArchive: true
cleanWs()
}
}
}
Issues.jsx page code
const Issues = () => {
const { repoName } = useParams();
const [buildStage, setBuildStage] = useState('Initializing');
const [issues, setIssues] = useState([]);
const [filteredIssues, setFilteredIssues] = useState([]);
const [filters, setFilters] = useState({
severity: "",
language: "",
linter: ""
});
useEffect(() => {
let isMounted = true;
let intervalId;
const runPipeline = async () => {
try {
setBuildStage('Triggering Pipeline');
await triggerPipeline({ name: repoName });
if (!isMounted) return;
setBuildStage('Waiting for Build');
let lastBuildNumber = null;
const pollBuildStatus = async () => {
try {
const { isBuilding, result, number } = await checkBuildStatus();
if (number !== lastBuildNumber) {
lastBuildNumber = number;
console.log(`New build started: #${number}`);
}
if (!isBuilding && result) {
clearInterval(intervalId);
if (result === 'SUCCESS') {
if (isMounted) {
setBuildStage('Fetching Results');
const results = await getBuildResults(number);
await processMegaLinterResults(results.megaLinterLog);
setBuildStage('Complete');
}
} else {
if (isMounted) setBuildStage(`Failed: ${result}`);
}
}
} catch (error) {
console.error('Error in pollBuildStatus:', error);
if (isMounted) setBuildStage('Failed: Error checking status');
}
};
intervalId = setInterval(pollBuildStatus, 5000); // Check every 5 seconds
} catch (error) {
console.error('Error in pipeline process:', error);
if (isMounted) setBuildStage('Failed: Error triggering pipeline');
}
};
runPipeline();
return () => {
isMounted = false;
if (intervalId) clearInterval(intervalId);
};
}, [repoName]);
const processMegaLinterResults = (logContent) => {
try {
const processedIssues = [];
const lines = logContent.split('n');
let currentLinter = '';
let currentFile = '';
for (const line of lines) {
if (line.startsWith('Linter:')) {
currentLinter = line.split(':')[1].trim();
} else if (line.startsWith('File:')) {
currentFile = line.split(':')[1].trim();
} else if (line.includes('|')) {
const [lineNumber, column, level, message] = line.split('|').map(item => item.trim());
processedIssues.push({
message,
linter: currentLinter,
file: currentFile,
severity: level,
line: lineNumber,
column
});
}
}
setIssues(processedIssues);
setFilteredIssues(processedIssues);
} catch (error) {
console.error('Error processing MegaLinter results:', error);
}
};
useEffect(() => {
const filtered = issues.filter(issue =>
(!filters.severity || issue.severity === filters.severity) &&
(!filters.language || issue.language === filters.language) &&
(!filters.linter || issue.linter === filters.linter)
);
setFilteredIssues(filtered);
}, [issues, filters]);
const handleFilterChange = (filterType, value) => {
setFilters(prev => ({ ...prev, [filterType]: value }));
};
return (
<div className='flex'>
<Sidebar>
<SideBarItem link="/user/dashboard" icon={<Home size={20} />} text="Home" alert />
<SideBarItem link={`/user/dashboard/repos/${repoName}`} icon={<BarChart4 size={20} />} text="Details" alert />
<SideBarItem link={`/user/dashboard/repos/${repoName}/issues`} icon={<Bug size={20} />} text="Issues" />
<SideBarItem link={`/user/dashboard/repos/${repoName}/commits`} icon={<GitCommitVertical size={20} />} text="Commits" />
<SideBarItem link={`/user/dashboard/repos/${repoName}/pull-requests`} icon={<GitPullRequestIcon size={20} />} text="Pull Requests" />
<SideBarItem link="/user/dashboard/help" icon={<HandHelping size={20} />} text="Help" />
</Sidebar>
<div className="p-4 flex-grow">
<h1 className="text-2xl font-bold mb-4">Issues of {repoName}</h1>
{buildStage !== 'Complete' ? (
<div className="flex flex-col items-center justify-center h-64">
<div className="loader"></div>
<p className="mt-4">Status: {buildStage}</p>
</div>
) : (
<div className="flex flex-col md:flex-row gap-4">
<div className="flex-grow bg-black shadow-md rounded-lg p-6">
<h2 className="text-xl font-semibold mb-4">Mega Linter Results</h2>
<div className="overflow-x-auto">
<table className="min-w-full bg-black">
<thead className="bg-gray-100">
<tr>
<th className="py-2 px-4 border-b text-left">S.No</th>
<th className="py-2 px-4 border-b text-left">Issues</th>
<th className="py-2 px-4 border-b text-left">Linter</th>
<th className="py-2 px-4 border-b text-left">File</th>
<th className="py-2 px-4 border-b text-left">Severity</th>
</tr>
</thead>
<tbody>
{filteredIssues.map((issue, index) => (
<tr key={index} className={index % 2 === 0 ? 'bg-gray-50' : 'bg-black'}>
<td className="py-2 px-4 border-b">{index + 1}</td>
<td className="py-2 px-4 border-b">{issue.message}</td>
<td className="py-2 px-4 border-b">{issue.linter}</td>
<td className="py-2 px-4 border-b">{issue.file}</td>
<td className="py-2 px-4 border-b">{issue.severity}</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
<div className="w-full md:w-64 bg-black shadow-md rounded-lg p-6">
<h2 className="text-xl font-semibold mb-4">Filters</h2>
<div className="space-y-4">
<div>
<label htmlFor="severity" className="block text-sm font-medium text-gray-700">Severity</label>
<select
id="severity"
className="mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md"
onChange={(e) => handleFilterChange('severity', e.target.value)}
>
<option value="">Select severity</option>
{['Low', 'Medium', 'High'].map((option) => (
<option key={option} value={option}>{option}</option>
))}
</select>
</div>
<div>
<label htmlFor="language" className="block text-sm font-medium text-gray-700">Language</label>
<select
id="language"
className="mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md"
onChange={(e) => handleFilterChange('language', e.target.value)}
>
<option value="">Select language</option>
{[...new Set(issues.map(issue => issue.language))].map((option) => (
<option key={option} value={option}>{option}</option>
))}
</select>
</div>
<div>
<label htmlFor="linter" className="block text-sm font-medium text-gray-700">Linter</label>
<select
id="linter"
className="mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md"
onChange={(e) => handleFilterChange('linter', e.target.value)}
>
<option value="">Select linter</option>
{[...new Set(issues.map(issue => issue.linter))].map((option) => (
<option key={option} value={option}>{option}</option>
))}
</select>
</div>
</div>
</div>
</div>
)}
</div>
</div>
);
};
export default Issues;
Controller functions
export const triggerPipeline = async (repo) => {
try {
if (!repo || !repo.name) {
throw new Error('Invalid repository information');
}
const { data: { user }, error } = await supabase.auth.getUser();
if (error) {
throw new Error('Failed to fetch user data');
}
const githubUsername = user.user_metadata.user_name;
if (!githubUsername) {
throw new Error('GitHub username not found in user metadata');
}
const response = await fetch('http://localhost:8080/job/generate-issues/buildWithParameters', {
method: 'POST',
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/x-www-form-urlencoded'
},
body: `REPO_URL=https://github.com/${githubUsername}/${repo.name}.git`,
});
console.log('Response status:', response.status);
console.log('Response headers:', JSON.stringify(Object.fromEntries(response.headers)));
if (response.status === 201 || response.status === 303) {
console.log('Jenkins pipeline triggered successfully');
return { message: 'Pipeline triggered successfully' };
} else {
throw new Error(`Failed to trigger Jenkins pipeline: ${response.status}`);
}
} catch (error) {
console.error('Error triggering Jenkins pipeline:', error);
throw error;
}
};
export const checkBuildStatus = async () => {
const buildUrl = 'http://localhost:8080/job/generate-issues/lastBuild/api/json';
const authHeader = 'Basic ' + btoa('username:password');
try {
const response = await fetch(buildUrl, {
headers: {
'Authorization': authHeader
}
});
if (!response.ok) {
throw new Error(`Failed to fetch build status: ${response.status}`);
}
const buildData = await response.json();
console.log('Build data:', buildData);
return {
isBuilding: buildData.building,
result: buildData.result,
number: buildData.number
};
} catch (error) {
console.error('Error checking build status:', error);
return { isBuilding: false, result: 'ERROR', number: null };
}
};
export const getBuildResults = async (buildNumber) => {
const logUrl = `http://localhost:8080/job/generate-issues/${buildNumber}/artifact/megalinter-reports/megalinter.log`;
const authHeader = 'Basic ' + btoa('username:password');
try {
const response = await fetch(logUrl, {
headers: {
'Authorization': authHeader
}
});
if (!response.ok) {
throw new Error(`Failed to fetch MegaLinter log: ${response.status}`);
}
const megaLinterLog = await response.text();
return { megaLinterLog };
} catch (error) {
console.error('Error fetching MegaLinter log:', error);
throw error;
}
};