@daghis/teamcity-mcp 1.8.2 → 1.9.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/CHANGELOG.md +7 -0
- package/dist/index.js +296 -22
- package/dist/index.js.map +3 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.9.0](https://github.com/Daghis/teamcity-mcp/compare/v1.8.2...v1.9.0) (2025-09-20)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **teamcity:** add runtime guards for manager responses ([#179](https://github.com/Daghis/teamcity-mcp/issues/179)) ([9d7eaef](https://github.com/Daghis/teamcity-mcp/commit/9d7eaef161e675246d317603df47f7f39407b7d8))
|
|
9
|
+
|
|
3
10
|
## [1.8.2](https://github.com/Daghis/teamcity-mcp/compare/v1.8.1...v1.8.2) (2025-09-20)
|
|
4
11
|
|
|
5
12
|
|
package/dist/index.js
CHANGED
|
@@ -938,11 +938,15 @@ var ResolutionTypeEnum = {
|
|
|
938
938
|
|
|
939
939
|
// src/teamcity/artifact-manager.ts
|
|
940
940
|
var import_axios = require("axios");
|
|
941
|
+
init_errors();
|
|
941
942
|
|
|
942
943
|
// src/teamcity/utils/build-locator.ts
|
|
943
944
|
var toBuildLocator = (buildId) => buildId.includes(":") ? buildId : `id:${buildId}`;
|
|
944
945
|
|
|
945
946
|
// src/teamcity/artifact-manager.ts
|
|
947
|
+
var isRecord = (value) => {
|
|
948
|
+
return typeof value === "object" && value !== null;
|
|
949
|
+
};
|
|
946
950
|
var ArtifactManager = class _ArtifactManager {
|
|
947
951
|
client;
|
|
948
952
|
cache = /* @__PURE__ */ new Map();
|
|
@@ -979,12 +983,8 @@ var ArtifactManager = class _ArtifactManager {
|
|
|
979
983
|
"file(name,fullName,size,modificationTime,href,children(file(name,fullName,size,modificationTime,href)))"
|
|
980
984
|
);
|
|
981
985
|
const baseUrl = this.getBaseUrl();
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
buildId,
|
|
985
|
-
options.includeNested,
|
|
986
|
-
baseUrl
|
|
987
|
-
);
|
|
986
|
+
const artifactPayload = this.ensureArtifactListingResponse(response.data, buildId);
|
|
987
|
+
let artifacts = this.parseArtifacts(artifactPayload, buildId, options.includeNested, baseUrl);
|
|
988
988
|
artifacts = this.applyFilters(artifacts, options);
|
|
989
989
|
if (options.limit ?? options.offset) {
|
|
990
990
|
artifacts = this.paginate(
|
|
@@ -1183,6 +1183,39 @@ var ArtifactManager = class _ArtifactManager {
|
|
|
1183
1183
|
/**
|
|
1184
1184
|
* Parse artifacts from API response
|
|
1185
1185
|
*/
|
|
1186
|
+
ensureArtifactListingResponse(data, buildId) {
|
|
1187
|
+
if (!isRecord(data)) {
|
|
1188
|
+
throw new TeamCityAPIError(
|
|
1189
|
+
"TeamCity returned a non-object artifact listing response",
|
|
1190
|
+
"INVALID_RESPONSE",
|
|
1191
|
+
void 0,
|
|
1192
|
+
{ buildId }
|
|
1193
|
+
);
|
|
1194
|
+
}
|
|
1195
|
+
const payload = data;
|
|
1196
|
+
const { file } = payload;
|
|
1197
|
+
if (file !== void 0 && !Array.isArray(file)) {
|
|
1198
|
+
throw new TeamCityAPIError(
|
|
1199
|
+
"TeamCity artifact listing response contains a non-array file field",
|
|
1200
|
+
"INVALID_RESPONSE",
|
|
1201
|
+
void 0,
|
|
1202
|
+
{ buildId }
|
|
1203
|
+
);
|
|
1204
|
+
}
|
|
1205
|
+
if (Array.isArray(file)) {
|
|
1206
|
+
file.forEach((entry, index) => {
|
|
1207
|
+
if (!isRecord(entry)) {
|
|
1208
|
+
throw new TeamCityAPIError(
|
|
1209
|
+
"TeamCity artifact listing response contains a non-object file entry",
|
|
1210
|
+
"INVALID_RESPONSE",
|
|
1211
|
+
void 0,
|
|
1212
|
+
{ buildId, index }
|
|
1213
|
+
);
|
|
1214
|
+
}
|
|
1215
|
+
});
|
|
1216
|
+
}
|
|
1217
|
+
return payload;
|
|
1218
|
+
}
|
|
1186
1219
|
parseArtifacts(data, buildId, includeNested, baseUrl) {
|
|
1187
1220
|
const artifacts = [];
|
|
1188
1221
|
const files = data.file ?? [];
|
|
@@ -1699,6 +1732,10 @@ var BuildConfigurationUpdateManager = class {
|
|
|
1699
1732
|
};
|
|
1700
1733
|
|
|
1701
1734
|
// src/teamcity/build-results-manager.ts
|
|
1735
|
+
init_errors();
|
|
1736
|
+
var isRecord2 = (value) => {
|
|
1737
|
+
return typeof value === "object" && value !== null;
|
|
1738
|
+
};
|
|
1702
1739
|
var BuildResultsManager = class _BuildResultsManager {
|
|
1703
1740
|
client;
|
|
1704
1741
|
cache = /* @__PURE__ */ new Map();
|
|
@@ -1783,15 +1820,14 @@ var BuildResultsManager = class _BuildResultsManager {
|
|
|
1783
1820
|
toBuildLocator(buildId),
|
|
1784
1821
|
_BuildResultsManager.fields
|
|
1785
1822
|
);
|
|
1786
|
-
return response.data;
|
|
1823
|
+
return this.ensureBuildSummary(response.data, buildId);
|
|
1787
1824
|
}
|
|
1788
1825
|
/**
|
|
1789
1826
|
* Transform build data to result format
|
|
1790
1827
|
*/
|
|
1791
|
-
transformBuildData(
|
|
1792
|
-
const buildData = data;
|
|
1828
|
+
transformBuildData(buildData) {
|
|
1793
1829
|
const build = {
|
|
1794
|
-
id: buildData.id,
|
|
1830
|
+
id: typeof buildData.id === "string" ? Number.parseInt(buildData.id, 10) : buildData.id,
|
|
1795
1831
|
number: buildData.number,
|
|
1796
1832
|
status: buildData.status,
|
|
1797
1833
|
state: buildData.state,
|
|
@@ -1820,16 +1856,107 @@ var BuildResultsManager = class _BuildResultsManager {
|
|
|
1820
1856
|
build.duration = finish - start;
|
|
1821
1857
|
}
|
|
1822
1858
|
if (buildData.triggered) {
|
|
1823
|
-
|
|
1859
|
+
const triggered = {
|
|
1824
1860
|
type: buildData.triggered.type,
|
|
1825
1861
|
date: buildData.triggered.date
|
|
1826
1862
|
};
|
|
1827
|
-
|
|
1828
|
-
|
|
1863
|
+
const triggeredUser = buildData.triggered.user;
|
|
1864
|
+
if (triggeredUser) {
|
|
1865
|
+
const username = triggeredUser.username ?? triggeredUser.name;
|
|
1866
|
+
if (username) {
|
|
1867
|
+
triggered.user = username;
|
|
1868
|
+
}
|
|
1829
1869
|
}
|
|
1870
|
+
build.triggered = triggered;
|
|
1830
1871
|
}
|
|
1831
1872
|
return build;
|
|
1832
1873
|
}
|
|
1874
|
+
ensureBuildSummary(data, buildId) {
|
|
1875
|
+
if (!isRecord2(data)) {
|
|
1876
|
+
throw new TeamCityAPIError(
|
|
1877
|
+
"TeamCity returned a non-object build summary response",
|
|
1878
|
+
"INVALID_RESPONSE",
|
|
1879
|
+
void 0,
|
|
1880
|
+
{ buildId, expected: "object with build fields", receivedType: typeof data }
|
|
1881
|
+
);
|
|
1882
|
+
}
|
|
1883
|
+
const summary = data;
|
|
1884
|
+
const { id, number, status, state, buildTypeId, webUrl, triggered } = summary;
|
|
1885
|
+
if (typeof id !== "number" && typeof id !== "string" || typeof number !== "string" || typeof status !== "string" || typeof state !== "string" || typeof buildTypeId !== "string" || typeof webUrl !== "string") {
|
|
1886
|
+
throw new TeamCityAPIError(
|
|
1887
|
+
"TeamCity build summary response is missing required fields",
|
|
1888
|
+
"INVALID_RESPONSE",
|
|
1889
|
+
void 0,
|
|
1890
|
+
{ buildId, receivedKeys: Object.keys(summary) }
|
|
1891
|
+
);
|
|
1892
|
+
}
|
|
1893
|
+
let normalizedTriggered;
|
|
1894
|
+
if (triggered !== void 0 && triggered !== null) {
|
|
1895
|
+
if (!isRecord2(triggered)) {
|
|
1896
|
+
throw new TeamCityAPIError(
|
|
1897
|
+
"TeamCity build summary response contains an invalid triggered payload",
|
|
1898
|
+
"INVALID_RESPONSE",
|
|
1899
|
+
void 0,
|
|
1900
|
+
{ buildId, receivedType: typeof triggered }
|
|
1901
|
+
);
|
|
1902
|
+
}
|
|
1903
|
+
const { type, date, user } = triggered;
|
|
1904
|
+
if (typeof type !== "string" || typeof date !== "string") {
|
|
1905
|
+
throw new TeamCityAPIError(
|
|
1906
|
+
"TeamCity build summary response contains an invalid triggered payload",
|
|
1907
|
+
"INVALID_RESPONSE",
|
|
1908
|
+
void 0,
|
|
1909
|
+
{ buildId }
|
|
1910
|
+
);
|
|
1911
|
+
}
|
|
1912
|
+
if (user !== void 0 && user !== null && !isRecord2(user)) {
|
|
1913
|
+
throw new TeamCityAPIError(
|
|
1914
|
+
"TeamCity build summary response contains an invalid trigger user payload",
|
|
1915
|
+
"INVALID_RESPONSE",
|
|
1916
|
+
void 0,
|
|
1917
|
+
{ buildId }
|
|
1918
|
+
);
|
|
1919
|
+
}
|
|
1920
|
+
let normalizedUser;
|
|
1921
|
+
if (user !== void 0 && user !== null) {
|
|
1922
|
+
const userRecord = user;
|
|
1923
|
+
const username = userRecord["username"];
|
|
1924
|
+
const name = userRecord["name"];
|
|
1925
|
+
const normalizedUsername = typeof username === "string" ? username : void 0;
|
|
1926
|
+
const normalizedName = typeof name === "string" ? name : void 0;
|
|
1927
|
+
if (normalizedUsername !== void 0 || normalizedName !== void 0) {
|
|
1928
|
+
normalizedUser = {};
|
|
1929
|
+
if (normalizedUsername) {
|
|
1930
|
+
normalizedUser.username = normalizedUsername;
|
|
1931
|
+
}
|
|
1932
|
+
if (normalizedName) {
|
|
1933
|
+
normalizedUser.name = normalizedName;
|
|
1934
|
+
}
|
|
1935
|
+
}
|
|
1936
|
+
}
|
|
1937
|
+
normalizedTriggered = {
|
|
1938
|
+
type,
|
|
1939
|
+
date,
|
|
1940
|
+
...normalizedUser ? { user: normalizedUser } : {}
|
|
1941
|
+
};
|
|
1942
|
+
}
|
|
1943
|
+
const normalized = {
|
|
1944
|
+
id,
|
|
1945
|
+
number,
|
|
1946
|
+
status,
|
|
1947
|
+
state,
|
|
1948
|
+
buildTypeId,
|
|
1949
|
+
statusText: typeof summary["statusText"] === "string" ? summary["statusText"] : void 0,
|
|
1950
|
+
webUrl,
|
|
1951
|
+
projectId: typeof summary["projectId"] === "string" ? summary["projectId"] : void 0,
|
|
1952
|
+
branchName: typeof summary["branchName"] === "string" ? summary["branchName"] : void 0,
|
|
1953
|
+
startDate: typeof summary["startDate"] === "string" ? summary["startDate"] : void 0,
|
|
1954
|
+
finishDate: typeof summary["finishDate"] === "string" ? summary["finishDate"] : void 0,
|
|
1955
|
+
queuedDate: typeof summary["queuedDate"] === "string" ? summary["queuedDate"] : void 0,
|
|
1956
|
+
triggered: normalizedTriggered
|
|
1957
|
+
};
|
|
1958
|
+
return normalized;
|
|
1959
|
+
}
|
|
1833
1960
|
/**
|
|
1834
1961
|
* Fetch build artifacts
|
|
1835
1962
|
*/
|
|
@@ -1839,7 +1966,7 @@ var BuildResultsManager = class _BuildResultsManager {
|
|
|
1839
1966
|
const response = await this.client.modules.builds.getFilesListOfBuild(
|
|
1840
1967
|
toBuildLocator(buildId)
|
|
1841
1968
|
);
|
|
1842
|
-
const artifactListing = response.data;
|
|
1969
|
+
const artifactListing = this.ensureArtifactListResponse(response.data, buildId);
|
|
1843
1970
|
let artifacts = artifactListing.file ?? [];
|
|
1844
1971
|
if (options.artifactFilter) {
|
|
1845
1972
|
artifacts = this.filterArtifacts(artifacts, options.artifactFilter);
|
|
@@ -1881,7 +2008,11 @@ var BuildResultsManager = class _BuildResultsManager {
|
|
|
1881
2008
|
);
|
|
1882
2009
|
return result;
|
|
1883
2010
|
} catch (error2) {
|
|
1884
|
-
warn("Failed to fetch artifacts", {
|
|
2011
|
+
warn("Failed to fetch artifacts", {
|
|
2012
|
+
error: error2 instanceof Error ? error2.message : error2,
|
|
2013
|
+
buildId,
|
|
2014
|
+
expected: "file[]"
|
|
2015
|
+
});
|
|
1885
2016
|
return [];
|
|
1886
2017
|
}
|
|
1887
2018
|
}
|
|
@@ -1894,6 +2025,137 @@ var BuildResultsManager = class _BuildResultsManager {
|
|
|
1894
2025
|
);
|
|
1895
2026
|
return artifacts.filter((a) => regex.test(a.name));
|
|
1896
2027
|
}
|
|
2028
|
+
ensureArtifactListResponse(data, buildId) {
|
|
2029
|
+
if (!isRecord2(data)) {
|
|
2030
|
+
throw new TeamCityAPIError(
|
|
2031
|
+
"TeamCity returned a non-object artifact list response",
|
|
2032
|
+
"INVALID_RESPONSE",
|
|
2033
|
+
void 0,
|
|
2034
|
+
{ buildId, expected: "object with file[]" }
|
|
2035
|
+
);
|
|
2036
|
+
}
|
|
2037
|
+
const { file } = data;
|
|
2038
|
+
if (file !== void 0 && !Array.isArray(file)) {
|
|
2039
|
+
throw new TeamCityAPIError(
|
|
2040
|
+
"TeamCity artifact list response contains a non-array file field",
|
|
2041
|
+
"INVALID_RESPONSE",
|
|
2042
|
+
void 0,
|
|
2043
|
+
{ buildId, receivedType: typeof file }
|
|
2044
|
+
);
|
|
2045
|
+
}
|
|
2046
|
+
return data;
|
|
2047
|
+
}
|
|
2048
|
+
ensureStatisticsResponse(data, buildId) {
|
|
2049
|
+
if (!isRecord2(data)) {
|
|
2050
|
+
throw new TeamCityAPIError(
|
|
2051
|
+
"TeamCity returned a non-object statistics response",
|
|
2052
|
+
"INVALID_RESPONSE",
|
|
2053
|
+
void 0,
|
|
2054
|
+
{ buildId, expected: "object with property[]" }
|
|
2055
|
+
);
|
|
2056
|
+
}
|
|
2057
|
+
const { property } = data;
|
|
2058
|
+
if (property === void 0) {
|
|
2059
|
+
return {};
|
|
2060
|
+
}
|
|
2061
|
+
if (!Array.isArray(property)) {
|
|
2062
|
+
throw new TeamCityAPIError(
|
|
2063
|
+
"TeamCity statistics response contains a non-array property field",
|
|
2064
|
+
"INVALID_RESPONSE",
|
|
2065
|
+
void 0,
|
|
2066
|
+
{ buildId, receivedType: typeof property }
|
|
2067
|
+
);
|
|
2068
|
+
}
|
|
2069
|
+
property.forEach((entry, index) => {
|
|
2070
|
+
if (!isRecord2(entry)) {
|
|
2071
|
+
throw new TeamCityAPIError(
|
|
2072
|
+
"TeamCity statistics response contains a non-object property entry",
|
|
2073
|
+
"INVALID_RESPONSE",
|
|
2074
|
+
void 0,
|
|
2075
|
+
{ buildId, index }
|
|
2076
|
+
);
|
|
2077
|
+
}
|
|
2078
|
+
const { name, value } = entry;
|
|
2079
|
+
if (typeof name !== "string" || typeof value !== "string") {
|
|
2080
|
+
throw new TeamCityAPIError(
|
|
2081
|
+
"TeamCity statistics response property entry is missing required fields",
|
|
2082
|
+
"INVALID_RESPONSE",
|
|
2083
|
+
void 0,
|
|
2084
|
+
{ buildId, index, receivedKeys: Object.keys(entry) }
|
|
2085
|
+
);
|
|
2086
|
+
}
|
|
2087
|
+
});
|
|
2088
|
+
return { property };
|
|
2089
|
+
}
|
|
2090
|
+
ensureChangesResponse(data, buildId) {
|
|
2091
|
+
if (!isRecord2(data)) {
|
|
2092
|
+
throw new TeamCityAPIError(
|
|
2093
|
+
"TeamCity returned a non-object changes response",
|
|
2094
|
+
"INVALID_RESPONSE",
|
|
2095
|
+
void 0,
|
|
2096
|
+
{ buildId, expected: "object with change[]" }
|
|
2097
|
+
);
|
|
2098
|
+
}
|
|
2099
|
+
const { change } = data;
|
|
2100
|
+
if (change !== void 0 && !Array.isArray(change)) {
|
|
2101
|
+
throw new TeamCityAPIError(
|
|
2102
|
+
"TeamCity changes response contains a non-array change field",
|
|
2103
|
+
"INVALID_RESPONSE",
|
|
2104
|
+
void 0,
|
|
2105
|
+
{ buildId, receivedType: typeof change }
|
|
2106
|
+
);
|
|
2107
|
+
}
|
|
2108
|
+
return data;
|
|
2109
|
+
}
|
|
2110
|
+
ensureDependenciesResponse(data, buildId) {
|
|
2111
|
+
if (!isRecord2(data)) {
|
|
2112
|
+
throw new TeamCityAPIError(
|
|
2113
|
+
"TeamCity returned a non-object dependencies response",
|
|
2114
|
+
"INVALID_RESPONSE",
|
|
2115
|
+
void 0,
|
|
2116
|
+
{ buildId, expected: "object with build[]" }
|
|
2117
|
+
);
|
|
2118
|
+
}
|
|
2119
|
+
const { build } = data;
|
|
2120
|
+
if (build !== void 0 && !Array.isArray(build)) {
|
|
2121
|
+
throw new TeamCityAPIError(
|
|
2122
|
+
"TeamCity dependencies response contains a non-array build field",
|
|
2123
|
+
"INVALID_RESPONSE",
|
|
2124
|
+
void 0,
|
|
2125
|
+
{ buildId, receivedType: typeof build }
|
|
2126
|
+
);
|
|
2127
|
+
}
|
|
2128
|
+
if (Array.isArray(build)) {
|
|
2129
|
+
build.forEach((entry, index) => {
|
|
2130
|
+
if (!isRecord2(entry)) {
|
|
2131
|
+
throw new TeamCityAPIError(
|
|
2132
|
+
"TeamCity dependencies response contains a non-object build entry",
|
|
2133
|
+
"INVALID_RESPONSE",
|
|
2134
|
+
void 0,
|
|
2135
|
+
{ buildId, index }
|
|
2136
|
+
);
|
|
2137
|
+
}
|
|
2138
|
+
const { id, number, buildTypeId, status } = entry;
|
|
2139
|
+
if (typeof id !== "number" && typeof id !== "string" || typeof number !== "string" || typeof buildTypeId !== "string" || typeof status !== "string") {
|
|
2140
|
+
throw new TeamCityAPIError(
|
|
2141
|
+
"TeamCity dependencies response is missing required fields on build entry",
|
|
2142
|
+
"INVALID_RESPONSE",
|
|
2143
|
+
void 0,
|
|
2144
|
+
{ buildId, index, receivedKeys: Object.keys(entry) }
|
|
2145
|
+
);
|
|
2146
|
+
}
|
|
2147
|
+
if (typeof id === "string" && Number.isNaN(Number.parseInt(id, 10))) {
|
|
2148
|
+
throw new TeamCityAPIError(
|
|
2149
|
+
"TeamCity dependencies response contains a non-numeric id value",
|
|
2150
|
+
"INVALID_RESPONSE",
|
|
2151
|
+
void 0,
|
|
2152
|
+
{ buildId, index, receivedValue: id }
|
|
2153
|
+
);
|
|
2154
|
+
}
|
|
2155
|
+
});
|
|
2156
|
+
}
|
|
2157
|
+
return data;
|
|
2158
|
+
}
|
|
1897
2159
|
/**
|
|
1898
2160
|
* Fetch build statistics
|
|
1899
2161
|
*/
|
|
@@ -1902,7 +2164,7 @@ var BuildResultsManager = class _BuildResultsManager {
|
|
|
1902
2164
|
const response = await this.client.modules.builds.getBuildStatisticValues(
|
|
1903
2165
|
toBuildLocator(buildId)
|
|
1904
2166
|
);
|
|
1905
|
-
const payload = response.data;
|
|
2167
|
+
const payload = this.ensureStatisticsResponse(response.data, buildId);
|
|
1906
2168
|
const properties = payload.property ?? [];
|
|
1907
2169
|
const stats = {};
|
|
1908
2170
|
for (const prop of properties) {
|
|
@@ -1934,7 +2196,11 @@ var BuildResultsManager = class _BuildResultsManager {
|
|
|
1934
2196
|
}
|
|
1935
2197
|
return stats;
|
|
1936
2198
|
} catch (error2) {
|
|
1937
|
-
warn("Failed to fetch statistics", {
|
|
2199
|
+
warn("Failed to fetch statistics", {
|
|
2200
|
+
error: error2 instanceof Error ? error2.message : error2,
|
|
2201
|
+
buildId,
|
|
2202
|
+
expected: "property[]"
|
|
2203
|
+
});
|
|
1938
2204
|
return {};
|
|
1939
2205
|
}
|
|
1940
2206
|
}
|
|
@@ -1944,7 +2210,7 @@ var BuildResultsManager = class _BuildResultsManager {
|
|
|
1944
2210
|
async fetchChanges(buildId) {
|
|
1945
2211
|
try {
|
|
1946
2212
|
const response = await this.client.modules.changes.getAllChanges(`build:(id:${buildId})`);
|
|
1947
|
-
const changePayload = response.data;
|
|
2213
|
+
const changePayload = this.ensureChangesResponse(response.data, buildId);
|
|
1948
2214
|
const changes = changePayload.change ?? [];
|
|
1949
2215
|
return changes.map((change) => ({
|
|
1950
2216
|
revision: change.version,
|
|
@@ -1957,7 +2223,11 @@ var BuildResultsManager = class _BuildResultsManager {
|
|
|
1957
2223
|
}))
|
|
1958
2224
|
}));
|
|
1959
2225
|
} catch (error2) {
|
|
1960
|
-
warn("Failed to fetch changes", {
|
|
2226
|
+
warn("Failed to fetch changes", {
|
|
2227
|
+
error: error2 instanceof Error ? error2.message : error2,
|
|
2228
|
+
buildId,
|
|
2229
|
+
expected: "change[]"
|
|
2230
|
+
});
|
|
1961
2231
|
return [];
|
|
1962
2232
|
}
|
|
1963
2233
|
}
|
|
@@ -1970,16 +2240,20 @@ var BuildResultsManager = class _BuildResultsManager {
|
|
|
1970
2240
|
`snapshotDependency:(to:(id:${buildId}))`,
|
|
1971
2241
|
"build(id,number,buildTypeId,status)"
|
|
1972
2242
|
);
|
|
1973
|
-
const depsData = response.data;
|
|
2243
|
+
const depsData = this.ensureDependenciesResponse(response.data, buildId);
|
|
1974
2244
|
const builds = depsData.build ?? [];
|
|
1975
2245
|
return builds.map((build) => ({
|
|
1976
|
-
buildId: build.id,
|
|
2246
|
+
buildId: typeof build.id === "string" ? Number.parseInt(build.id, 10) : build.id,
|
|
1977
2247
|
buildNumber: build.number,
|
|
1978
2248
|
buildTypeId: build.buildTypeId,
|
|
1979
2249
|
status: build.status
|
|
1980
2250
|
}));
|
|
1981
2251
|
} catch (error2) {
|
|
1982
|
-
warn("Failed to fetch dependencies", {
|
|
2252
|
+
warn("Failed to fetch dependencies", {
|
|
2253
|
+
error: error2 instanceof Error ? error2.message : error2,
|
|
2254
|
+
buildId,
|
|
2255
|
+
expected: "build[]"
|
|
2256
|
+
});
|
|
1983
2257
|
return [];
|
|
1984
2258
|
}
|
|
1985
2259
|
}
|