Skip to main content
Glama
queue-management.js•7.43 kB
/** * Queue Management Tools */ import axios from "axios"; import { encodeJobPath, isSuccessStatus, formatError, success, failure, } from "../utils/jenkins.js"; /** * Cancel a pending/queued Jenkins build that hasn't started yet */ export async function cancelQueuedBuild(client, args) { const { jobFullName, queueId = null } = args; const jobPath = encodeJobPath(jobFullName); try { // If queueId is provided, cancel that specific item if (queueId) { const cancelResponse = await client.post( `${client.baseUrl}/queue/cancelItem`, `id=${queueId}`, { headers: { "Content-Type": "application/x-www-form-urlencoded", }, } ); if ( isSuccessStatus(cancelResponse.status) || cancelResponse.status === 204 ) { return success("cancelQueuedBuild", { message: `Queue item #${queueId} cancelled successfully`, queueId, method: "direct", }); } else { return failure( "cancelQueuedBuild", `Failed to cancel queue item #${queueId}`, { statusCode: cancelResponse.status } ); } } // If no queueId provided, find and cancel all queued items for this job const queueResponse = await client.get( `${client.baseUrl}/queue/api/json` ); if (queueResponse.status !== 200) { return failure( "cancelQueuedBuild", "Failed to fetch queue information", { statusCode: queueResponse.status } ); } const queueItems = queueResponse.data.items || []; // Find items for this specific job const jobQueueItems = queueItems.filter((item) => { if (item.task && item.task.url) { const itemJobPath = item.task.url .replace(client.baseUrl, "") .replace(/^\//, "") .replace(/\/$/, ""); const targetJobPath = `job/${jobPath}`.replace(/\/$/, ""); return itemJobPath === targetJobPath; } if (item.task && item.task.name) { const jobName = jobFullName.split("/").pop(); return ( item.task.name === jobFullName || item.task.name === jobName ); } return false; }); if (jobQueueItems.length === 0) { return failure( "cancelQueuedBuild", `No queued builds found for job: ${jobFullName}`, { totalQueueItems: queueItems.length } ); } // Cancel all found queue items for this job const cancelResults = []; for (const item of jobQueueItems) { try { const cancelResponse = await client.post( `${client.baseUrl}/queue/cancelItem`, `id=${item.id}`, { headers: { "Content-Type": "application/x-www-form-urlencoded", }, } ); cancelResults.push({ queueId: item.id, success: isSuccessStatus(cancelResponse.status) || cancelResponse.status === 204, statusCode: cancelResponse.status, why: item.why || "No reason provided", inQueueSince: item.inQueueSince, params: item.params, }); } catch (error) { cancelResults.push({ queueId: item.id, success: false, error: error.message, }); } } const successCount = cancelResults.filter((r) => r.success).length; const allSuccess = successCount === cancelResults.length; return allSuccess ? success("cancelQueuedBuild", { message: `Successfully cancelled ${successCount} queued build(s) for ${jobFullName}`, cancelledItems: cancelResults, totalCancelled: successCount, totalFound: jobQueueItems.length, }) : failure( "cancelQueuedBuild", `Cancelled ${successCount} out of ${cancelResults.length} queued build(s)`, { cancelledItems: cancelResults, totalCancelled: successCount, totalFound: jobQueueItems.length, } ); } catch (error) { return formatError(error, "cancel queued build"); } } /** * Get information about queued builds */ export async function getQueueInfo(client, args = {}) { const { jobFullName = null } = args; try { const queueResponse = await client.get( `${client.baseUrl}/queue/api/json` ); if (queueResponse.status !== 200) { return failure( "getQueueInfo", "Failed to fetch queue information", { statusCode: queueResponse.status } ); } const allItems = queueResponse.data.items || []; // If jobFullName is specified, filter for that job if (jobFullName) { const jobPath = encodeJobPath(jobFullName); const filteredItems = allItems.filter((item) => { if (item.task && item.task.url) { const itemJobPath = item.task.url .replace(client.baseUrl, "") .replace(/^\//, "") .replace(/\/$/, ""); const targetJobPath = `job/${jobPath}`.replace(/\/$/, ""); return itemJobPath === targetJobPath; } if (item.task && item.task.name) { const jobName = jobFullName.split("/").pop(); return ( item.task.name === jobFullName || item.task.name === jobName ); } return false; }); return success("getQueueInfo", { jobName: jobFullName, queueItems: filteredItems.map((item) => ({ id: item.id, why: item.why || "Waiting", stuck: item.stuck || false, blocked: item.blocked || false, buildable: item.buildable !== false, inQueueSince: new Date(item.inQueueSince).toISOString(), queuedFor: Math.floor((Date.now() - item.inQueueSince) / 1000) + " seconds", params: item.params, taskName: item.task?.name, taskUrl: item.task?.url, })), totalInQueue: filteredItems.length, }); } // Return all queue items return success("getQueueInfo", { queueItems: allItems.map((item) => ({ id: item.id, taskName: item.task?.name || "Unknown", taskUrl: item.task?.url, why: item.why || "Waiting", stuck: item.stuck || false, blocked: item.blocked || false, buildable: item.buildable !== false, inQueueSince: new Date(item.inQueueSince).toISOString(), queuedFor: Math.floor((Date.now() - item.inQueueSince) / 1000) + " seconds", params: item.params, })), totalInQueue: allItems.length, summary: { total: allItems.length, stuck: allItems.filter((i) => i.stuck).length, blocked: allItems.filter((i) => i.blocked).length, buildable: allItems.filter((i) => i.buildable !== false).length, }, }); } catch (error) { return formatError(error, "get queue info"); } } /** * Get a specific queued item by queueId (helper tool) */ export async function getQueueItem(client, args = {}) { const { queueId } = args; if (queueId === undefined || queueId === null) { return failure("getQueueItem", "queueId is required"); } try { const res = await client.get( `${client.baseUrl}/queue/item/${queueId}/api/json` ); if (res.status === 200) { // Determine if it has transitioned to a build const executable = res.data?.executable; return success("getQueueItem", { queueId, blocked: res.data?.blocked || false, buildable: res.data?.buildable !== false, stuck: res.data?.stuck || false, why: res.data?.why || "Waiting", params: res.data?.params, taskName: res.data?.task?.name, taskUrl: res.data?.task?.url, executable: executable ? { number: executable.number, url: executable.url, } : null, transitioned: Boolean(executable), }); } return failure("getQueueItem", `Queue item not found: ${queueId}`, { statusCode: res.status, }); } catch (error) { return formatError(error, "getQueueItem"); } }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/umishra1504/Jenkins-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server