// Copyright (C) 2025 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only // This module contains a number of functions for interacting with COIN. const zlib = require('zlib') const { snipTestFailureFromLog, getAnalysis } = require('./logTools'); const { logger } = require('./logger.js'); const axios = require('axios'); exports.getErrorsFromLog = getErrorsFromLog; async function getErrorsFromLog(integrationId) { return new Promise((resolve, reject) => { getWorkItemsFromTask(integrationId) .then(workItems => { getWorkItemLog(workItems[0]) .then(log => { if(workItems[0].task_action === "Build") resolve(getAnalysis(log, workItems[0].identifier)); else { snipTestFailureFromLog(log, workItems[0].identifier).then(errs => { logger.info(errs); if (errs.errors.length > 0) { resolve(errs); } else { // Fall back to getAnalysis if no test failures are found resolve(getAnalysis(log, workItems[0].identifier)); } }); } }) }) .catch(error => { reject(error); }); }); } exports.getTaskfromIntegration = getTaskfromIntegration; async function getTaskfromIntegration(integrationId, fallbackURL) { return new Promise((resolve, reject) => { let url = (fallbackURL || 'http://coin.ci.qt.io/coin/api/taskDetail') + `?id=${integrationId}`; logger.info(`GET request for ${url}`); axios.get(url) .then(response => { let workItem = response.data.tasks.pop(); resolve(workItem); }) .catch(error => { if (fallbackURL) reject(error); else { getTaskfromIntegration(integrationId, 'https://testresults.qt.io/coin/api/taskDetail') .then(workItem => { resolve(workItem); }) .catch(error => { reject(error); }); } }) } ); } exports.getWorkItemsFromTask = getWorkItemsFromTask; async function getWorkItemsFromTask(taskId, fallbackURL) { return new Promise((resolve, reject) => { let url = (fallbackURL || 'http://coin.ci.qt.io/coin/api/taskWorkItems') + `?id=${taskId}`; logger.info(`GET request for ${url}`); axios.get(url) .then(response => { let workItems = response.data.tasks_with_workitems.pop().workitems; workItems = filterFailedTestWorkItems(workItems); resolve(workItems); }) .catch(error => { if (fallbackURL) reject(error); else { getWorkItemsFromTask(taskId, 'https://testresults.qt.io/coin/api/taskWorkItems') .then(workItems => { resolve(workItems); }) .catch(error => { reject(error); }); } }) } ); } function filterFailedTestWorkItems(workItems) { return workItems.filter(workItem => { return workItem.state === 'Failed'; }); } exports.getWorkItemLog = getWorkItemLog; async function getWorkItemLog(workItem, fallbackURL) { return new Promise((resolve, reject) => { let url = (fallbackURL || `http://coin.ci.qt.io/`) + workItem.storage_paths.log_raw ; logger.info(`GET request for ${url}`); axios.get(url, { 'responseType': 'arraybuffer' }) .then(response => { zlib.gunzip(response.data, function (_err, output) { resolve(output.toString()); }) }) .catch(error => { if (fallbackURL) reject(error); else { getWorkItemLog(workItem, 'https://testresults.qt.io/') .then(log => { resolve(log); }) .catch(error => { reject(error); }); } }) }); }