Skip to content

Commit

Permalink
use ado-node-api
Browse files Browse the repository at this point in the history
  • Loading branch information
DenisRumyantsev committed Dec 19, 2023
1 parent ee56363 commit eb48fec
Show file tree
Hide file tree
Showing 9 changed files with 215 additions and 205 deletions.
237 changes: 131 additions & 106 deletions ci/ci-test-tasks/test-and-verify-v2/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion ci/ci-test-tasks/test-and-verify-v2/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"build": "tsc"
},
"dependencies": {
"axios": "^1.6.2"
"azure-devops-node-api": "^12.1.0"
},
"devDependencies": {
"@tsconfig/node20": "^20.1.2",
Expand Down
34 changes: 24 additions & 10 deletions ci/ci-test-tasks/test-and-verify-v2/src/config.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { WebApi, getPersonalAccessTokenHandler } from 'azure-devops-node-api';

class Config {
public readonly AuthToken: string;
public readonly AdoUrl: string;
public readonly ProjectName: string;
public readonly TaskArg: string;
public readonly ApiUrl: string;
// TODO: Replace axios usage to node-api. Need to add support of Pipelines API.
public readonly AxiosAuth: { auth: { username: string, password: string } };
public readonly webApi: WebApi;

constructor(argv: string[]) {
this.AuthToken = argv[2];
Expand All @@ -25,14 +25,28 @@ class Config {
throw new Error('Task list is not provided');
}

this.ApiUrl = `${this.AdoUrl}/${this.ProjectName}/_apis`;
const authHandler = getPersonalAccessTokenHandler(this.AuthToken);
this.webApi = new WebApi(this.AdoUrl, authHandler);
}

this.AxiosAuth = {
auth: {
username: 'Basic',
password: this.AuthToken
}
}
public async getDefinitions () {
const api = await this.webApi.getBuildApi();
return await api.getDefinitions(this.ProjectName);
}

public async queueBuild (definitionId: number, parameters = {}) {
const api = await this.webApi.getBuildApi();
return await api.queueBuild({ definition: { id: definitionId }, parameters: JSON.stringify(parameters) }, this.ProjectName);
}

public async getBuild (buildId: number) {
const api = await this.webApi.getBuildApi();
return api.getBuild(this.ProjectName, buildId);
}

public async updateBuild (buildId: number) {
const api = await this.webApi.getBuildApi();
return api.updateBuild({}, this.ProjectName, buildId, true);
}
}

Expand Down
1 change: 0 additions & 1 deletion ci/ci-test-tasks/test-and-verify-v2/src/constants.ts

This file was deleted.

34 changes: 12 additions & 22 deletions ci/ci-test-tasks/test-and-verify-v2/src/helpers.Build.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,32 @@
import axios from "axios";
import { Build } from 'azure-devops-node-api/interfaces/BuildInterfaces';
import { configInstance } from './config';

import { PipelineBuild } from "./interfaces";
import { API_VERSION } from "./constants";
import { configInstance } from "./config";
const buildLogData = (build: Build) => `[Definition Name: ${build.definition?.name}, Build Number: ${build.buildNumber}, Build Id: ${build.id}]`;

export async function fetchBuildStatus(pipelineBuild: PipelineBuild): Promise<PipelineBuild> {
export async function fetchBuildStatus(pipelineBuild: Build): Promise<Build> {
const intervalInSeconds = 20;
const maxRetries = 10;

let retryCount = 0;

const getBuildPromise = new Promise<PipelineBuild>((resolve, reject) => {
const getBuildPromise = new Promise<Build>((resolve, reject) => {
const interval = setInterval(
async () => {
try {
const res = await axios.get(pipelineBuild.url, configInstance.AxiosAuth);
const res = await configInstance.getBuild(pipelineBuild.id!);

clearInterval(interval);
resolve(res.data);
resolve(res);
}
catch (err: any) {
if (['ETIMEDOUT', 'ECONNRESET'].includes(err.code) || err.response?.status >= 500) {
if (retryCount < maxRetries) {
retryCount++;
console.log(`Error verifying state of the [${pipelineBuild.name} ${pipelineBuild.id}] build, retry request. Retry count: ${retryCount} out of ${maxRetries}. Error message: ${err.message}`);
console.log(`Error verifying state of the ${buildLogData(pipelineBuild)} build, retry request. Retry count: ${retryCount} out of ${maxRetries}. Error message: ${err.message}`);

return;
} else {
console.error(`Error verifying state of the [${pipelineBuild.name} ${pipelineBuild.id}], retries limit reached. Cancel retries. Error message: ${err.message}`);
console.error(`Error verifying state of the ${buildLogData(pipelineBuild)} build, retries limit reached. Cancel retries. Error message: ${err.message}`);
}
}

Expand All @@ -49,21 +48,12 @@ export async function fetchBuildStatus(pipelineBuild: PipelineBuild): Promise<Pi
return getBuildPromise;
}

export async function retryFailedJobsInBuild(pipelineBuild: PipelineBuild): Promise<void> {
const buildLogData = `(Name: ${pipelineBuild.name}, Id: ${pipelineBuild.id})`;

export async function retryFailedJobsInBuild(pipelineBuild: Build): Promise<void> {
try {
await axios.patch(
`${configInstance.ApiUrl}/build/builds/${pipelineBuild.id}?retry=true&${API_VERSION}`,
undefined,
{
...configInstance.AxiosAuth,
headers: { 'Content-Type': 'application/json' }
}
)
await configInstance.updateBuild(pipelineBuild.id!);
}
catch (err: any) {
err.stack = `Error retrying failed jobs in build ${buildLogData}. Error: ${err.stack}`;
err.stack = `Error retrying failed jobs in build ${buildLogData(pipelineBuild)}. Error: ${err.stack}`;
console.error(err.stack);
if (err.response?.data) {
console.error(err.response.data);
Expand Down
Loading

0 comments on commit eb48fec

Please sign in to comment.