@daghis/teamcity-mcp 1.9.5 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.release-please-config.json +0 -1
- package/.release-please-manifest.json +1 -1
- package/CHANGELOG.md +64 -0
- package/dist/index.js +970 -17
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
- package/server.json +2 -2
package/dist/index.js
CHANGED
|
@@ -936,6 +936,137 @@ var ResolutionTypeEnum = {
|
|
|
936
936
|
AtTime: "atTime"
|
|
937
937
|
};
|
|
938
938
|
|
|
939
|
+
// src/teamcity/agent-requirements-manager.ts
|
|
940
|
+
var JSON_HEADERS = {
|
|
941
|
+
headers: {
|
|
942
|
+
"Content-Type": "application/json",
|
|
943
|
+
Accept: "application/json"
|
|
944
|
+
}
|
|
945
|
+
};
|
|
946
|
+
var JSON_GET_HEADERS = {
|
|
947
|
+
headers: {
|
|
948
|
+
Accept: "application/json"
|
|
949
|
+
}
|
|
950
|
+
};
|
|
951
|
+
var toStringRecord = (input) => {
|
|
952
|
+
if (!input) {
|
|
953
|
+
return {};
|
|
954
|
+
}
|
|
955
|
+
return Object.fromEntries(
|
|
956
|
+
Object.entries(input).map(([name, value]) => {
|
|
957
|
+
if (value === void 0 || value === null) {
|
|
958
|
+
return [name, ""];
|
|
959
|
+
}
|
|
960
|
+
if (typeof value === "boolean") {
|
|
961
|
+
return [name, value ? "true" : "false"];
|
|
962
|
+
}
|
|
963
|
+
return [name, String(value)];
|
|
964
|
+
})
|
|
965
|
+
);
|
|
966
|
+
};
|
|
967
|
+
var propertiesToRecord = (properties) => {
|
|
968
|
+
if (properties == null) {
|
|
969
|
+
return {};
|
|
970
|
+
}
|
|
971
|
+
const propertyEntries = properties.property;
|
|
972
|
+
const items = Array.isArray(propertyEntries) ? propertyEntries : propertyEntries != null ? [propertyEntries] : [];
|
|
973
|
+
const record = {};
|
|
974
|
+
for (const item of items) {
|
|
975
|
+
if (!item?.name) {
|
|
976
|
+
continue;
|
|
977
|
+
}
|
|
978
|
+
record[item.name] = item.value != null ? String(item.value) : "";
|
|
979
|
+
}
|
|
980
|
+
return record;
|
|
981
|
+
};
|
|
982
|
+
var recordToProperties = (record) => {
|
|
983
|
+
const entries = Object.entries(record);
|
|
984
|
+
if (entries.length === 0) {
|
|
985
|
+
return void 0;
|
|
986
|
+
}
|
|
987
|
+
return {
|
|
988
|
+
property: entries.map(([name, value]) => ({ name, value }))
|
|
989
|
+
};
|
|
990
|
+
};
|
|
991
|
+
var mergeRecords = (base, override) => ({
|
|
992
|
+
...base,
|
|
993
|
+
...override
|
|
994
|
+
});
|
|
995
|
+
var AgentRequirementsManager = class {
|
|
996
|
+
constructor(client) {
|
|
997
|
+
this.client = client;
|
|
998
|
+
}
|
|
999
|
+
async addRequirement(input) {
|
|
1000
|
+
const { buildTypeId } = input;
|
|
1001
|
+
const payload = this.buildPayload(void 0, input);
|
|
1002
|
+
const response = await this.client.modules.buildTypes.addAgentRequirementToBuildType(
|
|
1003
|
+
buildTypeId,
|
|
1004
|
+
void 0,
|
|
1005
|
+
payload,
|
|
1006
|
+
JSON_HEADERS
|
|
1007
|
+
);
|
|
1008
|
+
const id = response.data?.id;
|
|
1009
|
+
if (!id) {
|
|
1010
|
+
throw new Error("TeamCity did not return an agent requirement identifier.");
|
|
1011
|
+
}
|
|
1012
|
+
return { id };
|
|
1013
|
+
}
|
|
1014
|
+
async updateRequirement(requirementId, input) {
|
|
1015
|
+
const { buildTypeId } = input;
|
|
1016
|
+
const existing = await this.fetchRequirement(buildTypeId, requirementId);
|
|
1017
|
+
if (!existing) {
|
|
1018
|
+
throw new Error(
|
|
1019
|
+
`Agent requirement ${requirementId} was not found on ${buildTypeId}; verify the ID or update via the TeamCity UI.`
|
|
1020
|
+
);
|
|
1021
|
+
}
|
|
1022
|
+
const payload = this.buildPayload(existing, input);
|
|
1023
|
+
await this.client.modules.buildTypes.replaceAgentRequirement(
|
|
1024
|
+
buildTypeId,
|
|
1025
|
+
requirementId,
|
|
1026
|
+
void 0,
|
|
1027
|
+
payload,
|
|
1028
|
+
JSON_HEADERS
|
|
1029
|
+
);
|
|
1030
|
+
return { id: requirementId };
|
|
1031
|
+
}
|
|
1032
|
+
async deleteRequirement(buildTypeId, requirementId) {
|
|
1033
|
+
await this.client.modules.buildTypes.deleteAgentRequirement(
|
|
1034
|
+
buildTypeId,
|
|
1035
|
+
requirementId,
|
|
1036
|
+
JSON_HEADERS
|
|
1037
|
+
);
|
|
1038
|
+
}
|
|
1039
|
+
async fetchRequirement(buildTypeId, requirementId) {
|
|
1040
|
+
try {
|
|
1041
|
+
const response = await this.client.modules.buildTypes.getAgentRequirement(
|
|
1042
|
+
buildTypeId,
|
|
1043
|
+
requirementId,
|
|
1044
|
+
"id,type,disabled,properties(property(name,value))",
|
|
1045
|
+
JSON_GET_HEADERS
|
|
1046
|
+
);
|
|
1047
|
+
return response.data;
|
|
1048
|
+
} catch (error2) {
|
|
1049
|
+
if (typeof error2 === "object" && error2 !== null && "response" in error2 && error2.response?.status === 404) {
|
|
1050
|
+
return null;
|
|
1051
|
+
}
|
|
1052
|
+
throw error2;
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
buildPayload(existing, input) {
|
|
1056
|
+
const baseProps = propertiesToRecord(existing?.properties);
|
|
1057
|
+
const mergedProps = mergeRecords(baseProps, toStringRecord(input.properties));
|
|
1058
|
+
const payload = {
|
|
1059
|
+
...existing ?? {},
|
|
1060
|
+
disabled: input.disabled ?? existing?.disabled
|
|
1061
|
+
};
|
|
1062
|
+
const properties = recordToProperties(mergedProps);
|
|
1063
|
+
if (properties) {
|
|
1064
|
+
payload.properties = properties;
|
|
1065
|
+
}
|
|
1066
|
+
return payload;
|
|
1067
|
+
}
|
|
1068
|
+
};
|
|
1069
|
+
|
|
939
1070
|
// src/teamcity/artifact-manager.ts
|
|
940
1071
|
var import_axios = require("axios");
|
|
941
1072
|
init_errors();
|
|
@@ -1817,6 +1948,356 @@ var BuildConfigurationUpdateManager = class {
|
|
|
1817
1948
|
}
|
|
1818
1949
|
};
|
|
1819
1950
|
|
|
1951
|
+
// src/teamcity/build-dependency-manager.ts
|
|
1952
|
+
var JSON_HEADERS2 = {
|
|
1953
|
+
headers: {
|
|
1954
|
+
"Content-Type": "application/json",
|
|
1955
|
+
Accept: "application/json"
|
|
1956
|
+
}
|
|
1957
|
+
};
|
|
1958
|
+
var JSON_GET_HEADERS2 = {
|
|
1959
|
+
headers: {
|
|
1960
|
+
Accept: "application/json"
|
|
1961
|
+
}
|
|
1962
|
+
};
|
|
1963
|
+
var defaultTypeFor = (dependencyType) => {
|
|
1964
|
+
switch (dependencyType) {
|
|
1965
|
+
case "artifact":
|
|
1966
|
+
return void 0;
|
|
1967
|
+
case "snapshot":
|
|
1968
|
+
return void 0;
|
|
1969
|
+
default:
|
|
1970
|
+
return void 0;
|
|
1971
|
+
}
|
|
1972
|
+
};
|
|
1973
|
+
var toStringRecord2 = (input) => {
|
|
1974
|
+
if (!input) {
|
|
1975
|
+
return {};
|
|
1976
|
+
}
|
|
1977
|
+
const entries = Object.entries(input).map(([name, value]) => {
|
|
1978
|
+
if (value === void 0 || value === null) {
|
|
1979
|
+
return [name, ""];
|
|
1980
|
+
}
|
|
1981
|
+
if (typeof value === "boolean") {
|
|
1982
|
+
return [name, value ? "true" : "false"];
|
|
1983
|
+
}
|
|
1984
|
+
return [name, String(value)];
|
|
1985
|
+
});
|
|
1986
|
+
return Object.fromEntries(entries);
|
|
1987
|
+
};
|
|
1988
|
+
var propertiesToRecord2 = (properties) => {
|
|
1989
|
+
if (properties == null) {
|
|
1990
|
+
return {};
|
|
1991
|
+
}
|
|
1992
|
+
const propertyEntries = properties.property;
|
|
1993
|
+
const collection = Array.isArray(propertyEntries) ? propertyEntries : propertyEntries != null ? [propertyEntries] : [];
|
|
1994
|
+
const map = {};
|
|
1995
|
+
for (const item of collection) {
|
|
1996
|
+
if (!item?.name) {
|
|
1997
|
+
continue;
|
|
1998
|
+
}
|
|
1999
|
+
map[item.name] = item.value != null ? String(item.value) : "";
|
|
2000
|
+
}
|
|
2001
|
+
return map;
|
|
2002
|
+
};
|
|
2003
|
+
var recordToProperties2 = (record) => {
|
|
2004
|
+
const entries = Object.entries(record);
|
|
2005
|
+
if (entries.length === 0) {
|
|
2006
|
+
return void 0;
|
|
2007
|
+
}
|
|
2008
|
+
return {
|
|
2009
|
+
property: entries.map(([name, value]) => ({ name, value }))
|
|
2010
|
+
};
|
|
2011
|
+
};
|
|
2012
|
+
var mergeRecords2 = (base, override) => {
|
|
2013
|
+
const merged = { ...base };
|
|
2014
|
+
for (const [key, value] of Object.entries(override)) {
|
|
2015
|
+
merged[key] = value;
|
|
2016
|
+
}
|
|
2017
|
+
return merged;
|
|
2018
|
+
};
|
|
2019
|
+
var BuildDependencyManager = class {
|
|
2020
|
+
constructor(client) {
|
|
2021
|
+
this.client = client;
|
|
2022
|
+
}
|
|
2023
|
+
async addDependency(input) {
|
|
2024
|
+
const { buildTypeId, dependencyType, dependsOn } = input;
|
|
2025
|
+
if (!dependsOn || dependsOn.trim() === "") {
|
|
2026
|
+
throw new Error(
|
|
2027
|
+
"dependsOn is required when adding a dependency; specify the upstream build configuration ID or use the TeamCity UI."
|
|
2028
|
+
);
|
|
2029
|
+
}
|
|
2030
|
+
const payload = this.buildPayload(dependencyType, void 0, {
|
|
2031
|
+
...input,
|
|
2032
|
+
dependsOn
|
|
2033
|
+
});
|
|
2034
|
+
const response = await this.createDependency(dependencyType, buildTypeId, payload);
|
|
2035
|
+
const id = response.data?.id;
|
|
2036
|
+
if (!id) {
|
|
2037
|
+
throw new Error("TeamCity did not return a dependency identifier. Verify server response.");
|
|
2038
|
+
}
|
|
2039
|
+
return { id };
|
|
2040
|
+
}
|
|
2041
|
+
async updateDependency(dependencyId, input) {
|
|
2042
|
+
const { buildTypeId, dependencyType } = input;
|
|
2043
|
+
const existing = await this.fetchDependency(dependencyType, buildTypeId, dependencyId);
|
|
2044
|
+
if (!existing) {
|
|
2045
|
+
throw new Error(
|
|
2046
|
+
`Dependency ${dependencyId} was not found on ${buildTypeId}; verify the identifier or update via the TeamCity UI.`
|
|
2047
|
+
);
|
|
2048
|
+
}
|
|
2049
|
+
const payload = this.buildPayload(dependencyType, existing, input);
|
|
2050
|
+
await this.replaceDependency(dependencyType, buildTypeId, dependencyId, payload);
|
|
2051
|
+
return { id: dependencyId };
|
|
2052
|
+
}
|
|
2053
|
+
async deleteDependency(dependencyType, buildTypeId, dependencyId) {
|
|
2054
|
+
if (!dependencyId) {
|
|
2055
|
+
throw new Error("dependencyId is required to delete a dependency.");
|
|
2056
|
+
}
|
|
2057
|
+
if (dependencyType === "artifact") {
|
|
2058
|
+
await this.client.modules.buildTypes.deleteArtifactDependency(
|
|
2059
|
+
buildTypeId,
|
|
2060
|
+
dependencyId,
|
|
2061
|
+
JSON_HEADERS2
|
|
2062
|
+
);
|
|
2063
|
+
return;
|
|
2064
|
+
}
|
|
2065
|
+
await this.client.modules.buildTypes.deleteSnapshotDependency(
|
|
2066
|
+
buildTypeId,
|
|
2067
|
+
dependencyId,
|
|
2068
|
+
JSON_HEADERS2
|
|
2069
|
+
);
|
|
2070
|
+
}
|
|
2071
|
+
async createDependency(dependencyType, buildTypeId, payload) {
|
|
2072
|
+
if (dependencyType === "artifact") {
|
|
2073
|
+
return this.client.modules.buildTypes.addArtifactDependencyToBuildType(
|
|
2074
|
+
buildTypeId,
|
|
2075
|
+
void 0,
|
|
2076
|
+
payload,
|
|
2077
|
+
JSON_HEADERS2
|
|
2078
|
+
);
|
|
2079
|
+
}
|
|
2080
|
+
return this.client.modules.buildTypes.addSnapshotDependencyToBuildType(
|
|
2081
|
+
buildTypeId,
|
|
2082
|
+
void 0,
|
|
2083
|
+
payload,
|
|
2084
|
+
JSON_HEADERS2
|
|
2085
|
+
);
|
|
2086
|
+
}
|
|
2087
|
+
async replaceDependency(dependencyType, buildTypeId, dependencyId, payload) {
|
|
2088
|
+
if (dependencyType === "artifact") {
|
|
2089
|
+
return this.client.modules.buildTypes.replaceArtifactDependency(
|
|
2090
|
+
buildTypeId,
|
|
2091
|
+
dependencyId,
|
|
2092
|
+
void 0,
|
|
2093
|
+
payload,
|
|
2094
|
+
JSON_HEADERS2
|
|
2095
|
+
);
|
|
2096
|
+
}
|
|
2097
|
+
return this.client.modules.buildTypes.replaceSnapshotDependency(
|
|
2098
|
+
buildTypeId,
|
|
2099
|
+
dependencyId,
|
|
2100
|
+
void 0,
|
|
2101
|
+
payload,
|
|
2102
|
+
JSON_HEADERS2
|
|
2103
|
+
);
|
|
2104
|
+
}
|
|
2105
|
+
async fetchDependency(dependencyType, buildTypeId, dependencyId) {
|
|
2106
|
+
try {
|
|
2107
|
+
if (dependencyType === "artifact") {
|
|
2108
|
+
const response2 = await this.client.modules.buildTypes.getArtifactDependency(
|
|
2109
|
+
buildTypeId,
|
|
2110
|
+
dependencyId,
|
|
2111
|
+
"id,type,disabled,properties(property(name,value)),'source-buildType'(id)",
|
|
2112
|
+
JSON_GET_HEADERS2
|
|
2113
|
+
);
|
|
2114
|
+
return response2.data;
|
|
2115
|
+
}
|
|
2116
|
+
const response = await this.client.modules.buildTypes.getSnapshotDependency(
|
|
2117
|
+
buildTypeId,
|
|
2118
|
+
dependencyId,
|
|
2119
|
+
"id,type,disabled,properties(property(name,value)),'source-buildType'(id)",
|
|
2120
|
+
JSON_GET_HEADERS2
|
|
2121
|
+
);
|
|
2122
|
+
return response.data;
|
|
2123
|
+
} catch (error2) {
|
|
2124
|
+
if (this.isNotFound(error2)) {
|
|
2125
|
+
return null;
|
|
2126
|
+
}
|
|
2127
|
+
throw error2;
|
|
2128
|
+
}
|
|
2129
|
+
}
|
|
2130
|
+
buildPayload(dependencyType, existing, input) {
|
|
2131
|
+
const baseProps = propertiesToRecord2(existing?.properties);
|
|
2132
|
+
const mergedProps = mergeRecords2(baseProps, toStringRecord2(input.properties));
|
|
2133
|
+
const properties = recordToProperties2(mergedProps);
|
|
2134
|
+
const resolvedType = input.type ?? existing?.type ?? defaultTypeFor(dependencyType);
|
|
2135
|
+
const payload = {
|
|
2136
|
+
...existing ?? {},
|
|
2137
|
+
disabled: input.disabled ?? existing?.disabled
|
|
2138
|
+
};
|
|
2139
|
+
if (resolvedType) {
|
|
2140
|
+
payload.type = resolvedType;
|
|
2141
|
+
}
|
|
2142
|
+
if (properties) {
|
|
2143
|
+
payload.properties = properties;
|
|
2144
|
+
}
|
|
2145
|
+
const dependsOn = input.dependsOn ?? existing?.["source-buildType"]?.id;
|
|
2146
|
+
if (dependsOn) {
|
|
2147
|
+
payload["source-buildType"] = { id: dependsOn };
|
|
2148
|
+
} else {
|
|
2149
|
+
delete payload["source-buildType"];
|
|
2150
|
+
}
|
|
2151
|
+
return payload;
|
|
2152
|
+
}
|
|
2153
|
+
isNotFound(error2) {
|
|
2154
|
+
return Boolean(
|
|
2155
|
+
typeof error2 === "object" && error2 !== null && "response" in error2 && error2.response?.status === 404
|
|
2156
|
+
);
|
|
2157
|
+
}
|
|
2158
|
+
};
|
|
2159
|
+
|
|
2160
|
+
// src/teamcity/build-feature-manager.ts
|
|
2161
|
+
var JSON_HEADERS3 = {
|
|
2162
|
+
headers: {
|
|
2163
|
+
"Content-Type": "application/json",
|
|
2164
|
+
Accept: "application/json"
|
|
2165
|
+
}
|
|
2166
|
+
};
|
|
2167
|
+
var JSON_GET_HEADERS3 = {
|
|
2168
|
+
headers: {
|
|
2169
|
+
Accept: "application/json"
|
|
2170
|
+
}
|
|
2171
|
+
};
|
|
2172
|
+
var toStringRecord3 = (input) => {
|
|
2173
|
+
if (!input) {
|
|
2174
|
+
return {};
|
|
2175
|
+
}
|
|
2176
|
+
return Object.fromEntries(
|
|
2177
|
+
Object.entries(input).map(([name, value]) => {
|
|
2178
|
+
if (value === void 0 || value === null) {
|
|
2179
|
+
return [name, ""];
|
|
2180
|
+
}
|
|
2181
|
+
if (typeof value === "boolean") {
|
|
2182
|
+
return [name, value ? "true" : "false"];
|
|
2183
|
+
}
|
|
2184
|
+
return [name, String(value)];
|
|
2185
|
+
})
|
|
2186
|
+
);
|
|
2187
|
+
};
|
|
2188
|
+
var propertiesToRecord3 = (properties) => {
|
|
2189
|
+
if (properties == null) {
|
|
2190
|
+
return {};
|
|
2191
|
+
}
|
|
2192
|
+
const propertyEntries = properties.property;
|
|
2193
|
+
const items = Array.isArray(propertyEntries) ? propertyEntries : propertyEntries != null ? [propertyEntries] : [];
|
|
2194
|
+
const record = {};
|
|
2195
|
+
for (const item of items) {
|
|
2196
|
+
if (!item?.name) {
|
|
2197
|
+
continue;
|
|
2198
|
+
}
|
|
2199
|
+
record[item.name] = item.value != null ? String(item.value) : "";
|
|
2200
|
+
}
|
|
2201
|
+
return record;
|
|
2202
|
+
};
|
|
2203
|
+
var recordToProperties3 = (record) => {
|
|
2204
|
+
const entries = Object.entries(record);
|
|
2205
|
+
if (entries.length === 0) {
|
|
2206
|
+
return void 0;
|
|
2207
|
+
}
|
|
2208
|
+
return {
|
|
2209
|
+
property: entries.map(([name, value]) => ({ name, value }))
|
|
2210
|
+
};
|
|
2211
|
+
};
|
|
2212
|
+
var mergeRecords3 = (base, override) => ({
|
|
2213
|
+
...base,
|
|
2214
|
+
...override
|
|
2215
|
+
});
|
|
2216
|
+
var BuildFeatureManager = class {
|
|
2217
|
+
constructor(client) {
|
|
2218
|
+
this.client = client;
|
|
2219
|
+
}
|
|
2220
|
+
async addFeature(input) {
|
|
2221
|
+
const { buildTypeId, type } = input;
|
|
2222
|
+
if (!type || type.trim() === "") {
|
|
2223
|
+
throw new Error("type is required when adding a build feature.");
|
|
2224
|
+
}
|
|
2225
|
+
const payload = this.buildPayload(void 0, input);
|
|
2226
|
+
payload.type = type;
|
|
2227
|
+
const response = await this.client.modules.buildTypes.addBuildFeatureToBuildType(
|
|
2228
|
+
buildTypeId,
|
|
2229
|
+
void 0,
|
|
2230
|
+
payload,
|
|
2231
|
+
JSON_HEADERS3
|
|
2232
|
+
);
|
|
2233
|
+
const id = response.data?.id;
|
|
2234
|
+
if (!id) {
|
|
2235
|
+
throw new Error("TeamCity did not return a feature identifier.");
|
|
2236
|
+
}
|
|
2237
|
+
return { id };
|
|
2238
|
+
}
|
|
2239
|
+
async updateFeature(featureId, input) {
|
|
2240
|
+
const { buildTypeId } = input;
|
|
2241
|
+
const existing = await this.fetchFeature(buildTypeId, featureId);
|
|
2242
|
+
if (!existing) {
|
|
2243
|
+
throw new Error(
|
|
2244
|
+
`Feature ${featureId} was not found on ${buildTypeId}; verify the feature ID or update via the TeamCity UI.`
|
|
2245
|
+
);
|
|
2246
|
+
}
|
|
2247
|
+
const payload = this.buildPayload(existing, input);
|
|
2248
|
+
await this.client.modules.buildTypes.replaceBuildFeature(
|
|
2249
|
+
buildTypeId,
|
|
2250
|
+
featureId,
|
|
2251
|
+
void 0,
|
|
2252
|
+
payload,
|
|
2253
|
+
JSON_HEADERS3
|
|
2254
|
+
);
|
|
2255
|
+
return { id: featureId };
|
|
2256
|
+
}
|
|
2257
|
+
async deleteFeature(buildTypeId, featureId) {
|
|
2258
|
+
await this.client.modules.buildTypes.deleteFeatureOfBuildType(
|
|
2259
|
+
buildTypeId,
|
|
2260
|
+
featureId,
|
|
2261
|
+
JSON_HEADERS3
|
|
2262
|
+
);
|
|
2263
|
+
}
|
|
2264
|
+
async fetchFeature(buildTypeId, featureId) {
|
|
2265
|
+
try {
|
|
2266
|
+
const response = await this.client.modules.buildTypes.getBuildFeature(
|
|
2267
|
+
buildTypeId,
|
|
2268
|
+
featureId,
|
|
2269
|
+
"id,type,disabled,properties(property(name,value))",
|
|
2270
|
+
JSON_GET_HEADERS3
|
|
2271
|
+
);
|
|
2272
|
+
return response.data;
|
|
2273
|
+
} catch (error2) {
|
|
2274
|
+
if (typeof error2 === "object" && error2 !== null && "response" in error2 && error2.response?.status === 404) {
|
|
2275
|
+
return null;
|
|
2276
|
+
}
|
|
2277
|
+
throw error2;
|
|
2278
|
+
}
|
|
2279
|
+
}
|
|
2280
|
+
buildPayload(existing, input) {
|
|
2281
|
+
const baseProps = propertiesToRecord3(existing?.properties);
|
|
2282
|
+
const mergedProps = mergeRecords3(baseProps, toStringRecord3(input.properties));
|
|
2283
|
+
const payload = {
|
|
2284
|
+
...existing ?? {},
|
|
2285
|
+
disabled: input.disabled ?? existing?.disabled
|
|
2286
|
+
};
|
|
2287
|
+
if (existing?.type && !input.type) {
|
|
2288
|
+
payload.type = existing.type;
|
|
2289
|
+
}
|
|
2290
|
+
if (input.type) {
|
|
2291
|
+
payload.type = input.type;
|
|
2292
|
+
}
|
|
2293
|
+
const properties = recordToProperties3(mergedProps);
|
|
2294
|
+
if (properties) {
|
|
2295
|
+
payload.properties = properties;
|
|
2296
|
+
}
|
|
2297
|
+
return payload;
|
|
2298
|
+
}
|
|
2299
|
+
};
|
|
2300
|
+
|
|
1820
2301
|
// src/teamcity/build-results-manager.ts
|
|
1821
2302
|
init_errors();
|
|
1822
2303
|
var isRecord2 = (value) => {
|
|
@@ -1891,11 +2372,37 @@ var BuildResultsManager = class _BuildResultsManager {
|
|
|
1891
2372
|
}
|
|
1892
2373
|
return result;
|
|
1893
2374
|
} catch (error2) {
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
2375
|
+
if (error2 instanceof TeamCityAPIError) {
|
|
2376
|
+
if (error2.statusCode === 404) {
|
|
2377
|
+
throw new TeamCityNotFoundError("Build", buildId, error2.requestId, error2);
|
|
2378
|
+
}
|
|
2379
|
+
throw error2;
|
|
2380
|
+
}
|
|
2381
|
+
if (this.isAxiosNotFound(error2)) {
|
|
2382
|
+
const axiosError = error2;
|
|
2383
|
+
const apiError = TeamCityAPIError.fromAxiosError(axiosError);
|
|
2384
|
+
if (apiError.statusCode === 404) {
|
|
2385
|
+
throw new TeamCityNotFoundError("Build", buildId, apiError.requestId, apiError);
|
|
2386
|
+
}
|
|
2387
|
+
throw apiError;
|
|
1897
2388
|
}
|
|
1898
|
-
|
|
2389
|
+
const message = error2 instanceof Error ? error2.message : String(error2);
|
|
2390
|
+
if (/not found/i.test(message)) {
|
|
2391
|
+
throw new TeamCityNotFoundError(
|
|
2392
|
+
"Build",
|
|
2393
|
+
buildId,
|
|
2394
|
+
void 0,
|
|
2395
|
+
error2 instanceof Error ? error2 : void 0
|
|
2396
|
+
);
|
|
2397
|
+
}
|
|
2398
|
+
throw new TeamCityAPIError(
|
|
2399
|
+
`Failed to fetch build results: ${message}`,
|
|
2400
|
+
"GET_BUILD_RESULTS_FAILED",
|
|
2401
|
+
void 0,
|
|
2402
|
+
void 0,
|
|
2403
|
+
void 0,
|
|
2404
|
+
error2 instanceof Error ? error2 : void 0
|
|
2405
|
+
);
|
|
1899
2406
|
}
|
|
1900
2407
|
}
|
|
1901
2408
|
/**
|
|
@@ -2407,6 +2914,10 @@ var BuildResultsManager = class _BuildResultsManager {
|
|
|
2407
2914
|
getCacheKey(buildId, options) {
|
|
2408
2915
|
return `${buildId}:${JSON.stringify(options)}`;
|
|
2409
2916
|
}
|
|
2917
|
+
isAxiosNotFound(error2) {
|
|
2918
|
+
const axiosError = error2;
|
|
2919
|
+
return Boolean(axiosError?.response && axiosError.response.status === 404);
|
|
2920
|
+
}
|
|
2410
2921
|
/**
|
|
2411
2922
|
* Get from cache if valid
|
|
2412
2923
|
*/
|
|
@@ -38988,6 +39499,17 @@ var DEV_TOOLS = [
|
|
|
38988
39499
|
type: "object",
|
|
38989
39500
|
properties: {
|
|
38990
39501
|
buildId: { type: "string", description: "Build ID" },
|
|
39502
|
+
buildTypeId: {
|
|
39503
|
+
type: "string",
|
|
39504
|
+
description: "Build configuration ID when resolving by number"
|
|
39505
|
+
},
|
|
39506
|
+
buildNumber: {
|
|
39507
|
+
oneOf: [
|
|
39508
|
+
{ type: "string", description: "Build number as TeamCity displays it" },
|
|
39509
|
+
{ type: "number", description: "Numeric build number" }
|
|
39510
|
+
],
|
|
39511
|
+
description: "Build number when buildId is not available"
|
|
39512
|
+
},
|
|
38991
39513
|
includeArtifacts: {
|
|
38992
39514
|
type: "boolean",
|
|
38993
39515
|
description: "Include artifacts listing and metadata"
|
|
@@ -39006,12 +39528,13 @@ var DEV_TOOLS = [
|
|
|
39006
39528
|
enum: ["base64", "stream"],
|
|
39007
39529
|
default: "base64"
|
|
39008
39530
|
}
|
|
39009
|
-
}
|
|
39010
|
-
required: ["buildId"]
|
|
39531
|
+
}
|
|
39011
39532
|
},
|
|
39012
39533
|
handler: async (args) => {
|
|
39013
39534
|
const schema = import_zod4.z.object({
|
|
39014
|
-
buildId: import_zod4.z.string().min(1),
|
|
39535
|
+
buildId: import_zod4.z.string().min(1).optional(),
|
|
39536
|
+
buildTypeId: import_zod4.z.string().min(1).optional(),
|
|
39537
|
+
buildNumber: import_zod4.z.union([import_zod4.z.string().min(1), import_zod4.z.number().int()]).optional(),
|
|
39015
39538
|
includeArtifacts: import_zod4.z.boolean().optional(),
|
|
39016
39539
|
includeStatistics: import_zod4.z.boolean().optional(),
|
|
39017
39540
|
includeChanges: import_zod4.z.boolean().optional(),
|
|
@@ -39019,6 +39542,24 @@ var DEV_TOOLS = [
|
|
|
39019
39542
|
artifactFilter: import_zod4.z.string().min(1).optional(),
|
|
39020
39543
|
maxArtifactSize: import_zod4.z.number().int().min(1).optional(),
|
|
39021
39544
|
artifactEncoding: import_zod4.z.enum(["base64", "stream"]).default("base64")
|
|
39545
|
+
}).superRefine((value, ctx) => {
|
|
39546
|
+
const hasBuildId = typeof value.buildId === "string" && value.buildId.trim().length > 0;
|
|
39547
|
+
const hasBuildType = typeof value.buildTypeId === "string" && value.buildTypeId.trim().length > 0;
|
|
39548
|
+
const hasBuildNumber = value.buildNumber !== void 0 && String(value.buildNumber).trim().length > 0;
|
|
39549
|
+
if (hasBuildType !== hasBuildNumber) {
|
|
39550
|
+
ctx.addIssue({
|
|
39551
|
+
code: import_zod4.z.ZodIssueCode.custom,
|
|
39552
|
+
message: "buildTypeId and buildNumber must be provided together",
|
|
39553
|
+
path: hasBuildType ? ["buildNumber"] : ["buildTypeId"]
|
|
39554
|
+
});
|
|
39555
|
+
}
|
|
39556
|
+
if (!hasBuildId && !(hasBuildType && hasBuildNumber)) {
|
|
39557
|
+
ctx.addIssue({
|
|
39558
|
+
code: import_zod4.z.ZodIssueCode.custom,
|
|
39559
|
+
message: "Provide either buildId or buildTypeId with buildNumber",
|
|
39560
|
+
path: ["buildId"]
|
|
39561
|
+
});
|
|
39562
|
+
}
|
|
39022
39563
|
});
|
|
39023
39564
|
return runTool(
|
|
39024
39565
|
"get_build_results",
|
|
@@ -39026,16 +39567,42 @@ var DEV_TOOLS = [
|
|
|
39026
39567
|
async (typed) => {
|
|
39027
39568
|
const adapter = createAdapterFromTeamCityAPI(TeamCityAPI.getInstance());
|
|
39028
39569
|
const manager = new BuildResultsManager(adapter);
|
|
39029
|
-
const
|
|
39030
|
-
|
|
39031
|
-
|
|
39032
|
-
|
|
39033
|
-
|
|
39034
|
-
|
|
39035
|
-
|
|
39036
|
-
|
|
39037
|
-
|
|
39038
|
-
|
|
39570
|
+
const trimmedBuildId = typeof typed.buildId === "string" ? typed.buildId.trim() : void 0;
|
|
39571
|
+
const hasBuildId = typeof trimmedBuildId === "string" && trimmedBuildId.length > 0;
|
|
39572
|
+
const buildTypeId = typed.buildTypeId?.trim();
|
|
39573
|
+
const buildNumberRaw = typed.buildNumber;
|
|
39574
|
+
const buildNumber = typeof buildNumberRaw === "number" ? buildNumberRaw.toString() : buildNumberRaw?.toString().trim();
|
|
39575
|
+
let buildLocator;
|
|
39576
|
+
let friendlyIdentifier;
|
|
39577
|
+
if (hasBuildId && trimmedBuildId) {
|
|
39578
|
+
buildLocator = trimmedBuildId;
|
|
39579
|
+
friendlyIdentifier = `ID '${trimmedBuildId}'`;
|
|
39580
|
+
} else if (buildTypeId && buildNumber) {
|
|
39581
|
+
buildLocator = `buildType:(id:${buildTypeId}),number:${buildNumber}`;
|
|
39582
|
+
friendlyIdentifier = `build type '${buildTypeId}' and number ${buildNumber}`;
|
|
39583
|
+
} else {
|
|
39584
|
+
throw new TeamCityAPIError(
|
|
39585
|
+
"Unable to resolve build identifier",
|
|
39586
|
+
"INVALID_BUILD_IDENTIFIER"
|
|
39587
|
+
);
|
|
39588
|
+
}
|
|
39589
|
+
try {
|
|
39590
|
+
const result = await manager.getBuildResults(buildLocator, {
|
|
39591
|
+
includeArtifacts: typed.includeArtifacts,
|
|
39592
|
+
includeStatistics: typed.includeStatistics,
|
|
39593
|
+
includeChanges: typed.includeChanges,
|
|
39594
|
+
includeDependencies: typed.includeDependencies,
|
|
39595
|
+
artifactFilter: typed.artifactFilter,
|
|
39596
|
+
maxArtifactSize: typed.maxArtifactSize,
|
|
39597
|
+
artifactEncoding: typed.artifactEncoding ?? "base64"
|
|
39598
|
+
});
|
|
39599
|
+
return json(result);
|
|
39600
|
+
} catch (error2) {
|
|
39601
|
+
if (error2 instanceof TeamCityNotFoundError) {
|
|
39602
|
+
throw new TeamCityNotFoundError("Build", friendlyIdentifier, error2.requestId, error2);
|
|
39603
|
+
}
|
|
39604
|
+
throw error2;
|
|
39605
|
+
}
|
|
39039
39606
|
},
|
|
39040
39607
|
args
|
|
39041
39608
|
);
|
|
@@ -40228,6 +40795,392 @@ var FULL_MODE_TOOLS = [
|
|
|
40228
40795
|
},
|
|
40229
40796
|
mode: "full"
|
|
40230
40797
|
},
|
|
40798
|
+
// === Dependency, Feature, and Requirement Management ===
|
|
40799
|
+
{
|
|
40800
|
+
name: "manage_build_dependencies",
|
|
40801
|
+
description: "Add, update, or delete artifact and snapshot dependencies for a build configuration",
|
|
40802
|
+
inputSchema: {
|
|
40803
|
+
type: "object",
|
|
40804
|
+
properties: {
|
|
40805
|
+
buildTypeId: { type: "string", description: "Build configuration ID" },
|
|
40806
|
+
dependencyType: {
|
|
40807
|
+
type: "string",
|
|
40808
|
+
enum: ["artifact", "snapshot"],
|
|
40809
|
+
description: "Dependency type to manage"
|
|
40810
|
+
},
|
|
40811
|
+
action: {
|
|
40812
|
+
type: "string",
|
|
40813
|
+
enum: ["add", "update", "delete"],
|
|
40814
|
+
description: "Operation to perform"
|
|
40815
|
+
},
|
|
40816
|
+
dependencyId: {
|
|
40817
|
+
type: "string",
|
|
40818
|
+
description: "Dependency ID (required for update/delete)"
|
|
40819
|
+
},
|
|
40820
|
+
dependsOn: {
|
|
40821
|
+
type: "string",
|
|
40822
|
+
description: "Upstream build configuration ID for the dependency"
|
|
40823
|
+
},
|
|
40824
|
+
properties: {
|
|
40825
|
+
type: "object",
|
|
40826
|
+
description: "Dependency properties (e.g. cleanDestinationDirectory, pathRules)"
|
|
40827
|
+
},
|
|
40828
|
+
type: {
|
|
40829
|
+
type: "string",
|
|
40830
|
+
description: "Override dependency type value sent to TeamCity"
|
|
40831
|
+
},
|
|
40832
|
+
disabled: { type: "boolean", description: "Disable or enable the dependency" }
|
|
40833
|
+
},
|
|
40834
|
+
required: ["buildTypeId", "dependencyType", "action"]
|
|
40835
|
+
},
|
|
40836
|
+
handler: async (args) => {
|
|
40837
|
+
const propertyValue = import_zod4.z.union([import_zod4.z.string(), import_zod4.z.number(), import_zod4.z.boolean()]);
|
|
40838
|
+
const schema = import_zod4.z.object({
|
|
40839
|
+
buildTypeId: import_zod4.z.string().min(1),
|
|
40840
|
+
dependencyType: import_zod4.z.enum(["artifact", "snapshot"]),
|
|
40841
|
+
action: import_zod4.z.enum(["add", "update", "delete"]),
|
|
40842
|
+
dependencyId: import_zod4.z.string().min(1).optional(),
|
|
40843
|
+
dependsOn: import_zod4.z.string().min(1).optional(),
|
|
40844
|
+
properties: import_zod4.z.record(import_zod4.z.string(), propertyValue).optional(),
|
|
40845
|
+
type: import_zod4.z.string().min(1).optional(),
|
|
40846
|
+
disabled: import_zod4.z.boolean().optional()
|
|
40847
|
+
}).superRefine((value, ctx) => {
|
|
40848
|
+
if ((value.action === "update" || value.action === "delete") && !value.dependencyId) {
|
|
40849
|
+
ctx.addIssue({
|
|
40850
|
+
code: import_zod4.z.ZodIssueCode.custom,
|
|
40851
|
+
message: "dependencyId is required for update/delete actions. Provide the TeamCity dependency ID or fall back to the UI.",
|
|
40852
|
+
path: ["dependencyId"]
|
|
40853
|
+
});
|
|
40854
|
+
}
|
|
40855
|
+
if (value.action === "add" && !value.dependsOn) {
|
|
40856
|
+
ctx.addIssue({
|
|
40857
|
+
code: import_zod4.z.ZodIssueCode.custom,
|
|
40858
|
+
message: "dependsOn is required when adding a dependency.",
|
|
40859
|
+
path: ["dependsOn"]
|
|
40860
|
+
});
|
|
40861
|
+
}
|
|
40862
|
+
});
|
|
40863
|
+
return runTool(
|
|
40864
|
+
"manage_build_dependencies",
|
|
40865
|
+
schema,
|
|
40866
|
+
async (typed) => {
|
|
40867
|
+
const adapter = createAdapterFromTeamCityAPI(TeamCityAPI.getInstance());
|
|
40868
|
+
const manager = new BuildDependencyManager(adapter);
|
|
40869
|
+
switch (typed.action) {
|
|
40870
|
+
case "add": {
|
|
40871
|
+
const result = await manager.addDependency({
|
|
40872
|
+
buildTypeId: typed.buildTypeId,
|
|
40873
|
+
dependencyType: typed.dependencyType,
|
|
40874
|
+
dependsOn: typed.dependsOn,
|
|
40875
|
+
properties: typed.properties,
|
|
40876
|
+
type: typed.type,
|
|
40877
|
+
disabled: typed.disabled
|
|
40878
|
+
});
|
|
40879
|
+
return json({
|
|
40880
|
+
success: true,
|
|
40881
|
+
action: "manage_build_dependencies",
|
|
40882
|
+
operation: "add",
|
|
40883
|
+
buildTypeId: typed.buildTypeId,
|
|
40884
|
+
dependencyType: typed.dependencyType,
|
|
40885
|
+
dependencyId: result.id
|
|
40886
|
+
});
|
|
40887
|
+
}
|
|
40888
|
+
case "update": {
|
|
40889
|
+
const result = await manager.updateDependency(typed.dependencyId, {
|
|
40890
|
+
buildTypeId: typed.buildTypeId,
|
|
40891
|
+
dependencyType: typed.dependencyType,
|
|
40892
|
+
dependsOn: typed.dependsOn,
|
|
40893
|
+
properties: typed.properties,
|
|
40894
|
+
type: typed.type,
|
|
40895
|
+
disabled: typed.disabled
|
|
40896
|
+
});
|
|
40897
|
+
return json({
|
|
40898
|
+
success: true,
|
|
40899
|
+
action: "manage_build_dependencies",
|
|
40900
|
+
operation: "update",
|
|
40901
|
+
buildTypeId: typed.buildTypeId,
|
|
40902
|
+
dependencyType: typed.dependencyType,
|
|
40903
|
+
dependencyId: result.id
|
|
40904
|
+
});
|
|
40905
|
+
}
|
|
40906
|
+
case "delete": {
|
|
40907
|
+
await manager.deleteDependency(
|
|
40908
|
+
typed.dependencyType,
|
|
40909
|
+
typed.buildTypeId,
|
|
40910
|
+
typed.dependencyId
|
|
40911
|
+
);
|
|
40912
|
+
return json({
|
|
40913
|
+
success: true,
|
|
40914
|
+
action: "manage_build_dependencies",
|
|
40915
|
+
operation: "delete",
|
|
40916
|
+
buildTypeId: typed.buildTypeId,
|
|
40917
|
+
dependencyType: typed.dependencyType,
|
|
40918
|
+
dependencyId: typed.dependencyId
|
|
40919
|
+
});
|
|
40920
|
+
}
|
|
40921
|
+
default:
|
|
40922
|
+
return json({
|
|
40923
|
+
success: false,
|
|
40924
|
+
action: "manage_build_dependencies",
|
|
40925
|
+
error: `Unsupported action: ${typed.action}`
|
|
40926
|
+
});
|
|
40927
|
+
}
|
|
40928
|
+
},
|
|
40929
|
+
args
|
|
40930
|
+
);
|
|
40931
|
+
},
|
|
40932
|
+
mode: "full"
|
|
40933
|
+
},
|
|
40934
|
+
{
|
|
40935
|
+
name: "manage_build_features",
|
|
40936
|
+
description: "Add, update, or delete build features such as ssh-agent or requirements enforcement",
|
|
40937
|
+
inputSchema: {
|
|
40938
|
+
type: "object",
|
|
40939
|
+
properties: {
|
|
40940
|
+
buildTypeId: { type: "string", description: "Build configuration ID" },
|
|
40941
|
+
action: {
|
|
40942
|
+
type: "string",
|
|
40943
|
+
enum: ["add", "update", "delete"],
|
|
40944
|
+
description: "Operation to perform"
|
|
40945
|
+
},
|
|
40946
|
+
featureId: {
|
|
40947
|
+
type: "string",
|
|
40948
|
+
description: "Feature ID (required for update/delete)"
|
|
40949
|
+
},
|
|
40950
|
+
type: { type: "string", description: "Feature type (required for add)" },
|
|
40951
|
+
properties: { type: "object", description: "Feature properties" },
|
|
40952
|
+
disabled: { type: "boolean", description: "Disable or enable the feature" }
|
|
40953
|
+
},
|
|
40954
|
+
required: ["buildTypeId", "action"]
|
|
40955
|
+
},
|
|
40956
|
+
handler: async (args) => {
|
|
40957
|
+
const propertyValue = import_zod4.z.union([import_zod4.z.string(), import_zod4.z.number(), import_zod4.z.boolean()]);
|
|
40958
|
+
const schema = import_zod4.z.object({
|
|
40959
|
+
buildTypeId: import_zod4.z.string().min(1),
|
|
40960
|
+
action: import_zod4.z.enum(["add", "update", "delete"]),
|
|
40961
|
+
featureId: import_zod4.z.string().min(1).optional(),
|
|
40962
|
+
type: import_zod4.z.string().min(1).optional(),
|
|
40963
|
+
properties: import_zod4.z.record(import_zod4.z.string(), propertyValue).optional(),
|
|
40964
|
+
disabled: import_zod4.z.boolean().optional()
|
|
40965
|
+
}).superRefine((value, ctx) => {
|
|
40966
|
+
if ((value.action === "update" || value.action === "delete") && !value.featureId) {
|
|
40967
|
+
ctx.addIssue({
|
|
40968
|
+
code: import_zod4.z.ZodIssueCode.custom,
|
|
40969
|
+
message: "featureId is required for update/delete actions. Capture the feature ID from TeamCity or use the UI.",
|
|
40970
|
+
path: ["featureId"]
|
|
40971
|
+
});
|
|
40972
|
+
}
|
|
40973
|
+
if (value.action === "add" && !value.type) {
|
|
40974
|
+
ctx.addIssue({
|
|
40975
|
+
code: import_zod4.z.ZodIssueCode.custom,
|
|
40976
|
+
message: "type is required when adding a build feature.",
|
|
40977
|
+
path: ["type"]
|
|
40978
|
+
});
|
|
40979
|
+
}
|
|
40980
|
+
});
|
|
40981
|
+
return runTool(
|
|
40982
|
+
"manage_build_features",
|
|
40983
|
+
schema,
|
|
40984
|
+
async (typed) => {
|
|
40985
|
+
const adapter = createAdapterFromTeamCityAPI(TeamCityAPI.getInstance());
|
|
40986
|
+
const manager = new BuildFeatureManager(adapter);
|
|
40987
|
+
switch (typed.action) {
|
|
40988
|
+
case "add": {
|
|
40989
|
+
const result = await manager.addFeature({
|
|
40990
|
+
buildTypeId: typed.buildTypeId,
|
|
40991
|
+
type: typed.type,
|
|
40992
|
+
properties: typed.properties,
|
|
40993
|
+
disabled: typed.disabled
|
|
40994
|
+
});
|
|
40995
|
+
return json({
|
|
40996
|
+
success: true,
|
|
40997
|
+
action: "manage_build_features",
|
|
40998
|
+
operation: "add",
|
|
40999
|
+
buildTypeId: typed.buildTypeId,
|
|
41000
|
+
featureId: result.id
|
|
41001
|
+
});
|
|
41002
|
+
}
|
|
41003
|
+
case "update": {
|
|
41004
|
+
const result = await manager.updateFeature(typed.featureId, {
|
|
41005
|
+
buildTypeId: typed.buildTypeId,
|
|
41006
|
+
type: typed.type,
|
|
41007
|
+
properties: typed.properties,
|
|
41008
|
+
disabled: typed.disabled
|
|
41009
|
+
});
|
|
41010
|
+
return json({
|
|
41011
|
+
success: true,
|
|
41012
|
+
action: "manage_build_features",
|
|
41013
|
+
operation: "update",
|
|
41014
|
+
buildTypeId: typed.buildTypeId,
|
|
41015
|
+
featureId: result.id
|
|
41016
|
+
});
|
|
41017
|
+
}
|
|
41018
|
+
case "delete": {
|
|
41019
|
+
await manager.deleteFeature(typed.buildTypeId, typed.featureId);
|
|
41020
|
+
return json({
|
|
41021
|
+
success: true,
|
|
41022
|
+
action: "manage_build_features",
|
|
41023
|
+
operation: "delete",
|
|
41024
|
+
buildTypeId: typed.buildTypeId,
|
|
41025
|
+
featureId: typed.featureId
|
|
41026
|
+
});
|
|
41027
|
+
}
|
|
41028
|
+
default:
|
|
41029
|
+
return json({
|
|
41030
|
+
success: false,
|
|
41031
|
+
action: "manage_build_features",
|
|
41032
|
+
error: `Unsupported action: ${typed.action}`
|
|
41033
|
+
});
|
|
41034
|
+
}
|
|
41035
|
+
},
|
|
41036
|
+
args
|
|
41037
|
+
);
|
|
41038
|
+
},
|
|
41039
|
+
mode: "full"
|
|
41040
|
+
},
|
|
41041
|
+
{
|
|
41042
|
+
name: "manage_agent_requirements",
|
|
41043
|
+
description: "Add, update, or delete build agent requirements for a configuration",
|
|
41044
|
+
inputSchema: {
|
|
41045
|
+
type: "object",
|
|
41046
|
+
properties: {
|
|
41047
|
+
buildTypeId: { type: "string", description: "Build configuration ID" },
|
|
41048
|
+
action: {
|
|
41049
|
+
type: "string",
|
|
41050
|
+
enum: ["add", "update", "delete"],
|
|
41051
|
+
description: "Operation to perform"
|
|
41052
|
+
},
|
|
41053
|
+
requirementId: {
|
|
41054
|
+
type: "string",
|
|
41055
|
+
description: "Requirement ID (required for update/delete)"
|
|
41056
|
+
},
|
|
41057
|
+
properties: {
|
|
41058
|
+
type: "object",
|
|
41059
|
+
description: "Requirement properties (e.g. property-name, condition, value)"
|
|
41060
|
+
},
|
|
41061
|
+
disabled: { type: "boolean", description: "Disable or enable the requirement" }
|
|
41062
|
+
},
|
|
41063
|
+
required: ["buildTypeId", "action"]
|
|
41064
|
+
},
|
|
41065
|
+
handler: async (args) => {
|
|
41066
|
+
const propertyValue = import_zod4.z.union([import_zod4.z.string(), import_zod4.z.number(), import_zod4.z.boolean()]);
|
|
41067
|
+
const schema = import_zod4.z.object({
|
|
41068
|
+
buildTypeId: import_zod4.z.string().min(1),
|
|
41069
|
+
action: import_zod4.z.enum(["add", "update", "delete"]),
|
|
41070
|
+
requirementId: import_zod4.z.string().min(1).optional(),
|
|
41071
|
+
properties: import_zod4.z.record(import_zod4.z.string(), propertyValue).optional(),
|
|
41072
|
+
disabled: import_zod4.z.boolean().optional()
|
|
41073
|
+
}).superRefine((value, ctx) => {
|
|
41074
|
+
if ((value.action === "update" || value.action === "delete") && !value.requirementId) {
|
|
41075
|
+
ctx.addIssue({
|
|
41076
|
+
code: import_zod4.z.ZodIssueCode.custom,
|
|
41077
|
+
message: "requirementId is required for update/delete actions. Capture the requirement ID via the API or TeamCity UI.",
|
|
41078
|
+
path: ["requirementId"]
|
|
41079
|
+
});
|
|
41080
|
+
}
|
|
41081
|
+
});
|
|
41082
|
+
return runTool(
|
|
41083
|
+
"manage_agent_requirements",
|
|
41084
|
+
schema,
|
|
41085
|
+
async (typed) => {
|
|
41086
|
+
const adapter = createAdapterFromTeamCityAPI(TeamCityAPI.getInstance());
|
|
41087
|
+
const manager = new AgentRequirementsManager(adapter);
|
|
41088
|
+
switch (typed.action) {
|
|
41089
|
+
case "add": {
|
|
41090
|
+
const result = await manager.addRequirement({
|
|
41091
|
+
buildTypeId: typed.buildTypeId,
|
|
41092
|
+
properties: typed.properties,
|
|
41093
|
+
disabled: typed.disabled
|
|
41094
|
+
});
|
|
41095
|
+
return json({
|
|
41096
|
+
success: true,
|
|
41097
|
+
action: "manage_agent_requirements",
|
|
41098
|
+
operation: "add",
|
|
41099
|
+
buildTypeId: typed.buildTypeId,
|
|
41100
|
+
requirementId: result.id
|
|
41101
|
+
});
|
|
41102
|
+
}
|
|
41103
|
+
case "update": {
|
|
41104
|
+
const result = await manager.updateRequirement(typed.requirementId, {
|
|
41105
|
+
buildTypeId: typed.buildTypeId,
|
|
41106
|
+
properties: typed.properties,
|
|
41107
|
+
disabled: typed.disabled
|
|
41108
|
+
});
|
|
41109
|
+
return json({
|
|
41110
|
+
success: true,
|
|
41111
|
+
action: "manage_agent_requirements",
|
|
41112
|
+
operation: "update",
|
|
41113
|
+
buildTypeId: typed.buildTypeId,
|
|
41114
|
+
requirementId: result.id
|
|
41115
|
+
});
|
|
41116
|
+
}
|
|
41117
|
+
case "delete": {
|
|
41118
|
+
await manager.deleteRequirement(typed.buildTypeId, typed.requirementId);
|
|
41119
|
+
return json({
|
|
41120
|
+
success: true,
|
|
41121
|
+
action: "manage_agent_requirements",
|
|
41122
|
+
operation: "delete",
|
|
41123
|
+
buildTypeId: typed.buildTypeId,
|
|
41124
|
+
requirementId: typed.requirementId
|
|
41125
|
+
});
|
|
41126
|
+
}
|
|
41127
|
+
default:
|
|
41128
|
+
return json({
|
|
41129
|
+
success: false,
|
|
41130
|
+
action: "manage_agent_requirements",
|
|
41131
|
+
error: `Unsupported action: ${typed.action}`
|
|
41132
|
+
});
|
|
41133
|
+
}
|
|
41134
|
+
},
|
|
41135
|
+
args
|
|
41136
|
+
);
|
|
41137
|
+
},
|
|
41138
|
+
mode: "full"
|
|
41139
|
+
},
|
|
41140
|
+
{
|
|
41141
|
+
name: "set_build_config_state",
|
|
41142
|
+
description: "Enable or disable a build configuration by toggling its paused flag",
|
|
41143
|
+
inputSchema: {
|
|
41144
|
+
type: "object",
|
|
41145
|
+
properties: {
|
|
41146
|
+
buildTypeId: { type: "string", description: "Build configuration ID" },
|
|
41147
|
+
paused: { type: "boolean", description: "True to pause/disable, false to enable" }
|
|
41148
|
+
},
|
|
41149
|
+
required: ["buildTypeId", "paused"]
|
|
41150
|
+
},
|
|
41151
|
+
handler: async (args) => {
|
|
41152
|
+
const schema = import_zod4.z.object({
|
|
41153
|
+
buildTypeId: import_zod4.z.string().min(1),
|
|
41154
|
+
paused: import_zod4.z.boolean()
|
|
41155
|
+
});
|
|
41156
|
+
return runTool(
|
|
41157
|
+
"set_build_config_state",
|
|
41158
|
+
schema,
|
|
41159
|
+
async (typed) => {
|
|
41160
|
+
const adapter = createAdapterFromTeamCityAPI(TeamCityAPI.getInstance());
|
|
41161
|
+
await adapter.modules.buildTypes.setBuildTypeField(
|
|
41162
|
+
typed.buildTypeId,
|
|
41163
|
+
"paused",
|
|
41164
|
+
String(typed.paused),
|
|
41165
|
+
{
|
|
41166
|
+
headers: {
|
|
41167
|
+
"Content-Type": "text/plain",
|
|
41168
|
+
Accept: "application/json"
|
|
41169
|
+
}
|
|
41170
|
+
}
|
|
41171
|
+
);
|
|
41172
|
+
return json({
|
|
41173
|
+
success: true,
|
|
41174
|
+
action: "set_build_config_state",
|
|
41175
|
+
buildTypeId: typed.buildTypeId,
|
|
41176
|
+
paused: typed.paused
|
|
41177
|
+
});
|
|
41178
|
+
},
|
|
41179
|
+
args
|
|
41180
|
+
);
|
|
41181
|
+
},
|
|
41182
|
+
mode: "full"
|
|
41183
|
+
},
|
|
40231
41184
|
// === VCS attachment ===
|
|
40232
41185
|
{
|
|
40233
41186
|
name: "add_vcs_root_to_build",
|