Skip to main content
Glama
queue-maintenance-scenario.test.ts5.39 kB
import { describe, expect, it } from '@jest/globals'; import type { ActionResult, ListResult } from '../types/tool-results'; import { callTool, callToolsBatch, callToolsBatchExpect } from './lib/mcp-runner'; const SERIAL_WORKER = process.env['JEST_WORKER_ID'] === '1' || process.env['SERIAL_BUILD_TESTS'] === 'true'; const serialDescribe = SERIAL_WORKER ? describe : describe.skip; const hasTeamCityEnv = Boolean( (process.env['TEAMCITY_URL'] ?? process.env['TEAMCITY_SERVER_URL']) && (process.env['TEAMCITY_TOKEN'] ?? process.env['TEAMCITY_API_TOKEN']) ); const ts = Date.now(); const PROJECT_ID = `E2E_QUEUE_${ts}`; const PROJECT_NAME = `E2E Queue ${ts}`; const BT_ID = `E2E_QUEUE_BT_${ts}`; const BT_NAME = `E2E Queue BuildType ${ts}`; serialDescribe('Queue maintenance (full)', () => { afterAll(async () => { try { await callTool('full', 'delete_project', { projectId: PROJECT_ID }); } catch (_e) { expect(true).toBe(true); } }); it('creates project and build config (full)', async () => { if (!hasTeamCityEnv) return expect(true).toBe(true); const results = await callToolsBatchExpect('full', [ { tool: 'create_project', args: { id: PROJECT_ID, name: PROJECT_NAME, }, }, { tool: 'create_build_config', args: { projectId: PROJECT_ID, id: BT_ID, name: BT_NAME, }, }, ]); const projectResult = results[0]?.result as ActionResult | undefined; const buildConfigResult = results[1]?.result as ActionResult | undefined; expect(projectResult).toMatchObject({ success: true, action: 'create_project' }); expect(buildConfigResult).toMatchObject({ success: true, action: 'create_build_config' }); }, 60000); it('adds a simple step, triggers multiple builds to create queued work (dev)', async () => { if (!hasTeamCityEnv) return expect(true).toBe(true); const stepBatch = await callToolsBatchExpect('full', [ { tool: 'manage_build_steps', args: { buildTypeId: BT_ID, action: 'add', name: 'quick-step', type: 'simpleRunner', properties: { 'script.content': 'echo queue-test' }, }, }, ]); const stepResult = stepBatch[0]?.result as ActionResult | undefined; expect(stepResult).toMatchObject({ success: true, action: 'add_build_step' }); const triggerBatch = await callToolsBatch('dev', [ { tool: 'trigger_build', args: { buildTypeId: BT_ID, comment: 'q1' } }, { tool: 'trigger_build', args: { buildTypeId: BT_ID, comment: 'q2' } }, { tool: 'trigger_build', args: { buildTypeId: BT_ID, comment: 'q3' } }, ]); triggerBatch.results.forEach((step) => { if (!step.ok) { // Non-fatal if triggering fails (e.g., permissions) expect(true).toBe(true); } }); }, 90000); it('reorders queued builds when available (full)', async () => { if (!hasTeamCityEnv) return expect(true).toBe(true); const queued = await callTool<ListResult<{ id?: string | number }>>( 'dev', 'list_queued_builds', { locator: `project:(id:${PROJECT_ID})`, } ); const ids = (queued.items ?? []) .map((b) => (b.id != null ? String(b.id) : '')) .filter((s) => s.length > 0); if (ids.length >= 2) { const desired = [ids[1], ids[0], ...ids.slice(2)]; try { const res = await callTool('full', 'reorder_queued_builds', { buildIds: desired }); expect(res).toMatchObject({ success: true, action: 'reorder_queued_builds' }); } catch (e) { // Non-fatal if server disallows expect(true).toBe(true); } } else { expect(true).toBe(true); } }, 60000); it('moves a queued build to top when available (full)', async () => { if (!hasTeamCityEnv) return expect(true).toBe(true); const queued = await callTool<ListResult<{ id?: string | number }>>( 'dev', 'list_queued_builds', { locator: `project:(id:${PROJECT_ID})`, } ); const first = (queued.items ?? [])[0]; if (first?.id != null) { try { const res = await callTool('full', 'move_queued_build_to_top', { buildId: String(first.id), }); expect(res).toMatchObject({ success: true, action: 'move_queued_build_to_top' }); } catch (e) { expect(true).toBe(true); } } else { expect(true).toBe(true); } }, 60000); it('cancels queued builds for build type and by locator (full)', async () => { if (!hasTeamCityEnv) return expect(true).toBe(true); const batch = await callToolsBatch('full', [ { tool: 'cancel_queued_builds_for_build_type', args: { buildTypeId: BT_ID } }, { tool: 'cancel_queued_builds_by_locator', args: { locator: `project:(id:${PROJECT_ID})` } }, ]); batch.results.forEach((step) => { if (!step.ok) { expect(true).toBe(true); } else { expect(step.result).toHaveProperty('canceled'); } }); }, 60000); it('deletes project (full)', async () => { if (!hasTeamCityEnv) return expect(true).toBe(true); const res = await callTool('full', 'delete_project', { projectId: PROJECT_ID }); expect(res).toMatchObject({ success: true, action: 'delete_project' }); }, 60000); });

Latest Blog Posts

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/Daghis/teamcity-mcp'

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