import { z } from "zod";
import { AdoClient } from "../../ado-client.js";
import * as ReleaseInterfaces from "azure-devops-node-api/interfaces/ReleaseInterfaces";
export const createReleaseSchema = z.object({
project: z.string().optional().describe("Project name, defaults to ADO_PROJECT env var"),
definitionId: z.number().describe("Release definition ID"),
description: z.string().optional().describe("Release description"),
artifacts: z
.array(
z.object({
alias: z.string(),
version: z.string(),
})
)
.optional()
.describe("Artifact versions to use"),
isDraft: z.boolean().default(false).describe("Create as draft"),
variables: z.record(z.string()).optional().describe("Release variables"),
});
export const createReleaseTool = {
name: "create_release",
description: "Create a new release",
inputSchema: {
type: "object" as const,
properties: {
project: {
type: "string",
description: "Project name, defaults to ADO_PROJECT env var",
},
definitionId: {
type: "number",
description: "Release definition ID",
},
description: {
type: "string",
description: "Release description",
},
artifacts: {
type: "array",
items: {
type: "object",
properties: {
alias: { type: "string" },
version: { type: "string" },
},
required: ["alias", "version"],
},
description: "Artifact versions to use",
},
isDraft: {
type: "boolean",
description: "Create as draft",
},
variables: {
type: "object",
additionalProperties: { type: "string" },
description: "Release variables",
},
},
required: ["definitionId"],
},
};
export interface CreateReleaseResult {
id: number;
name: string;
status: string;
url: string;
message: string;
}
export async function createRelease(
client: AdoClient,
params: z.infer<typeof createReleaseSchema>
): Promise<CreateReleaseResult> {
const validatedParams = createReleaseSchema.parse(params);
const project = client.resolveProject(validatedParams.project);
const releaseApi = await client.getReleaseApi();
// Build release start metadata
const releaseStartMetadata: ReleaseInterfaces.ReleaseStartMetadata = {
definitionId: validatedParams.definitionId,
description: validatedParams.description,
isDraft: validatedParams.isDraft,
};
// Add artifact versions if specified
if (validatedParams.artifacts && validatedParams.artifacts.length > 0) {
releaseStartMetadata.artifacts = validatedParams.artifacts.map((art) => ({
alias: art.alias,
instanceReference: {
id: art.version,
name: art.version,
},
}));
}
// Add variables if specified
if (validatedParams.variables) {
releaseStartMetadata.variables = {};
for (const [key, value] of Object.entries(validatedParams.variables)) {
releaseStartMetadata.variables[key] = { value };
}
}
const release = await releaseApi.createRelease(releaseStartMetadata, project);
if (!release) {
throw new Error("Failed to create release");
}
return {
id: release.id || 0,
name: release.name || "",
status: validatedParams.isDraft ? "draft" : "active",
url: release.url || "",
message: `Successfully created release ${release.name}`,
};
}