mirror of
https://github.com/Azure/k8s-deploy.git
synced 2026-04-12 01:15:09 +08:00
Integrated workflow list and run API to get lastSuccessRunCommit
This commit is contained in:
parent
3919a9ee22
commit
3d1e46f18f
@ -384,7 +384,6 @@ test("utility - getLastSuccessfulRunSha() - Get Commits under different conditio
|
|||||||
if (name == errorWebRequest)
|
if (name == errorWebRequest)
|
||||||
return Promise.resolve(errorWebResponse);
|
return Promise.resolve(errorWebResponse);
|
||||||
});*/
|
});*/
|
||||||
|
|
||||||
jest.spyOn(httpClient, 'sendRequest').mockImplementation(() => Promise.resolve(lastSuccessfulRunUrlResponse));
|
jest.spyOn(httpClient, 'sendRequest').mockImplementation(() => Promise.resolve(lastSuccessfulRunUrlResponse));
|
||||||
//Invoke and assert
|
//Invoke and assert
|
||||||
await expect(utility.getLastSuccessfulRunSha(process.env.GITHUB_TOKEN)).resolves.not.toThrowError;
|
await expect(utility.getLastSuccessfulRunSha(process.env.GITHUB_TOKEN)).resolves.not.toThrowError;
|
||||||
|
|||||||
@ -41,9 +41,9 @@ function getWorkflowAnnotationsJson(lastSuccessRunSha) {
|
|||||||
+ `}`;
|
+ `}`;
|
||||||
}
|
}
|
||||||
exports.getWorkflowAnnotationsJson = getWorkflowAnnotationsJson;
|
exports.getWorkflowAnnotationsJson = getWorkflowAnnotationsJson;
|
||||||
function getWorkflowAnnotationKeyLabel() {
|
function getWorkflowAnnotationKeyLabel(workflowFilePath) {
|
||||||
const hashKey = require("crypto").createHash("MD5")
|
const hashKey = require("crypto").createHash("MD5")
|
||||||
.update(`${process.env.GITHUB_REPOSITORY}/${process.env.GITHUB_WORKFLOW}`)
|
.update(`${process.env.GITHUB_REPOSITORY}/${workflowFilePath}`)
|
||||||
.digest("hex");
|
.digest("hex");
|
||||||
return `githubWorkflow_${hashKey}`;
|
return `githubWorkflow_${hashKey}`;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,10 +17,10 @@ class GitHubClient {
|
|||||||
this._repository = repository;
|
this._repository = repository;
|
||||||
this._token = token;
|
this._token = token;
|
||||||
}
|
}
|
||||||
getSuccessfulRunsOnBranch(branch, force) {
|
getSuccessfulRunsOnBranch(branch, workflowFileName, force) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
if (force || !this._successfulRunsOnBranchPromise) {
|
if (force || !this._successfulRunsOnBranchPromise) {
|
||||||
const lastSuccessfulRunUrl = `https://api.github.com/repos/${this._repository}/actions/runs?status=success&branch=${branch}`;
|
const lastSuccessfulRunUrl = `https://api.github.com/repos/${this._repository}/actions/workflows/${workflowFileName}/runs?status=success&branch=${branch}`;
|
||||||
const webRequest = new httpClient_1.WebRequest();
|
const webRequest = new httpClient_1.WebRequest();
|
||||||
webRequest.method = "GET";
|
webRequest.method = "GET";
|
||||||
webRequest.uri = lastSuccessfulRunUrl;
|
webRequest.uri = lastSuccessfulRunUrl;
|
||||||
@ -34,5 +34,22 @@ class GitHubClient {
|
|||||||
return this._successfulRunsOnBranchPromise;
|
return this._successfulRunsOnBranchPromise;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
getWorkflows(force) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
if (force || !this._workflowsPromise) {
|
||||||
|
const getWorkflowFileNameUrl = `https://api.github.com/repos/${this._repository}/actions/workflows`;
|
||||||
|
const webRequest = new httpClient_1.WebRequest();
|
||||||
|
webRequest.method = "GET";
|
||||||
|
webRequest.uri = getWorkflowFileNameUrl;
|
||||||
|
webRequest.headers = {
|
||||||
|
Authorization: `Bearer ${this._token}`
|
||||||
|
};
|
||||||
|
core.debug(`Getting workflows for repo: ${this._repository}`);
|
||||||
|
const response = yield httpClient_1.sendRequest(webRequest);
|
||||||
|
this._workflowsPromise = Promise.resolve(response);
|
||||||
|
}
|
||||||
|
return this._workflowsPromise;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
exports.GitHubClient = GitHubClient;
|
exports.GitHubClient = GitHubClient;
|
||||||
|
|||||||
@ -111,14 +111,16 @@ function checkManifestStability(kubectl, resources) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
function annotateAndLabelResources(files, kubectl, resourceTypes, allPods) {
|
function annotateAndLabelResources(files, kubectl, resourceTypes, allPods) {
|
||||||
const annotationKeyLabel = models.getWorkflowAnnotationKeyLabel();
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
const workflowFilePath = yield utility_1.getWorkflowFilePath(TaskInputParameters.githubToken);
|
||||||
|
const annotationKeyLabel = models.getWorkflowAnnotationKeyLabel(workflowFilePath);
|
||||||
annotateResources(files, kubectl, resourceTypes, allPods, annotationKeyLabel);
|
annotateResources(files, kubectl, resourceTypes, allPods, annotationKeyLabel);
|
||||||
labelResources(files, kubectl, annotationKeyLabel);
|
labelResources(files, kubectl, annotationKeyLabel);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
function annotateResources(files, kubectl, resourceTypes, allPods, annotationKey) {
|
function annotateResources(files, kubectl, resourceTypes, allPods, annotationKey) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
|
||||||
const annotateResults = [];
|
const annotateResults = [];
|
||||||
const lastSuccessSha = yield utility_1.getLastSuccessfulRunSha(TaskInputParameters.githubToken);
|
const lastSuccessSha = utility_1.getLastSuccessfulRunSha(kubectl, TaskInputParameters.namespace, annotationKey);
|
||||||
let annotationKeyValStr = annotationKey + '=' + models.getWorkflowAnnotationsJson(lastSuccessSha);
|
let annotationKeyValStr = annotationKey + '=' + models.getWorkflowAnnotationsJson(lastSuccessSha);
|
||||||
annotateResults.push(kubectl.annotate('namespace', TaskInputParameters.namespace, [annotationKeyValStr], true));
|
annotateResults.push(kubectl.annotate('namespace', TaskInputParameters.namespace, [annotationKeyValStr], true));
|
||||||
annotateResults.push(kubectl.annotateFiles(files, [annotationKeyValStr], true));
|
annotateResults.push(kubectl.annotateFiles(files, [annotationKeyValStr], true));
|
||||||
@ -129,7 +131,6 @@ function annotateResources(files, kubectl, resourceTypes, allPods, annotationKey
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
utility_1.checkForErrors(annotateResults, true);
|
utility_1.checkForErrors(annotateResults, true);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
function labelResources(files, kubectl, label) {
|
function labelResources(files, kubectl, label) {
|
||||||
utility_1.checkForErrors([kubectl.labelFiles(files, [`workflow=${label}`], true)], true);
|
utility_1.checkForErrors([kubectl.labelFiles(files, [`workflow=${label}`], true)], true);
|
||||||
|
|||||||
@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
exports.getCurrentTime = exports.getRandomInt = exports.sleep = exports.annotateChildPods = exports.getLastSuccessfulRunSha = exports.checkForErrors = exports.isEqual = exports.getExecutableExtension = void 0;
|
exports.getCurrentTime = exports.getRandomInt = exports.sleep = exports.annotateChildPods = exports.getWorkflowFilePath = exports.getLastSuccessfulRunSha = exports.checkForErrors = exports.isEqual = exports.getExecutableExtension = void 0;
|
||||||
const os = require("os");
|
const os = require("os");
|
||||||
const core = require("@actions/core");
|
const core = require("@actions/core");
|
||||||
const githubClient_1 = require("../githubClient");
|
const githubClient_1 = require("../githubClient");
|
||||||
@ -60,29 +60,55 @@ function checkForErrors(execResults, warnIfError) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.checkForErrors = checkForErrors;
|
exports.checkForErrors = checkForErrors;
|
||||||
function getLastSuccessfulRunSha(githubToken) {
|
function getLastSuccessfulRunSha(kubectl, namespaceName, annotationKey) {
|
||||||
|
const result = kubectl.getResource('namespace', namespaceName);
|
||||||
|
if (!result) {
|
||||||
|
core.debug(`Failed to get commits from cluster.`);
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (result.stderr) {
|
||||||
|
core.debug(`${result.stderr}`);
|
||||||
|
return process.env.GITHUB_SHA;
|
||||||
|
}
|
||||||
|
else if (result.stdout) {
|
||||||
|
const annotationsSet = JSON.parse(result.stdout).metadata.annotations;
|
||||||
|
if (!!annotationsSet[annotationKey]) {
|
||||||
|
return JSON.parse(annotationsSet[annotationKey].replace(/'/g, '"')).commit;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return 'NA';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.getLastSuccessfulRunSha = getLastSuccessfulRunSha;
|
||||||
|
function getWorkflowFilePath(githubToken) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
let lastSuccessRunSha = '';
|
let workflowFilePath = process.env.GITHUB_WORKFLOW;
|
||||||
const gitHubClient = new githubClient_1.GitHubClient(process.env.GITHUB_REPOSITORY, githubToken);
|
if (!workflowFilePath.startsWith('.github/workflows/')) {
|
||||||
const branch = process.env.GITHUB_REF.replace("refs/heads/", "");
|
const githubClient = new githubClient_1.GitHubClient(process.env.GITHUB_REPOSITORY, githubToken);
|
||||||
const response = yield gitHubClient.getSuccessfulRunsOnBranch(branch);
|
const response = yield githubClient.getWorkflows();
|
||||||
if (response.statusCode == httpClient_1.StatusCodes.OK
|
if (response.statusCode == httpClient_1.StatusCodes.OK
|
||||||
&& !!response.body
|
&& !!response.body
|
||||||
&& !!response.body.total_count) {
|
&& !!response.body.total_count) {
|
||||||
if (response.body.total_count > 0) {
|
if (response.body.total_count > 0) {
|
||||||
lastSuccessRunSha = response.body.workflow_runs[0].head_sha;
|
for (let workflow of response.body.workflows) {
|
||||||
|
if (process.env.GITHUB_WORKFLOW === workflow.name) {
|
||||||
|
workflowFilePath = workflow.path;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
lastSuccessRunSha = 'NA';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (response.statusCode != httpClient_1.StatusCodes.OK) {
|
else if (response.statusCode != httpClient_1.StatusCodes.OK) {
|
||||||
core.debug(`An error occured while getting succeessful run results. Statuscode: ${response.statusCode}, StatusMessage: ${response.statusMessage}`);
|
core.debug(`An error occured while getting list of workflows on the repo. Statuscode: ${response.statusCode}, StatusMessage: ${response.statusMessage}`);
|
||||||
}
|
}
|
||||||
return Promise.resolve(lastSuccessRunSha);
|
}
|
||||||
|
return Promise.resolve(workflowFilePath);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
exports.getLastSuccessfulRunSha = getLastSuccessfulRunSha;
|
exports.getWorkflowFilePath = getWorkflowFilePath;
|
||||||
function annotateChildPods(kubectl, resourceType, resourceName, annotationKeyValStr, allPods) {
|
function annotateChildPods(kubectl, resourceType, resourceName, annotationKeyValStr, allPods) {
|
||||||
const commandExecutionResults = [];
|
const commandExecutionResults = [];
|
||||||
let owner = resourceName;
|
let owner = resourceName;
|
||||||
|
|||||||
@ -40,9 +40,9 @@ export function getWorkflowAnnotationsJson(lastSuccessRunSha: string): string {
|
|||||||
+ `'provider': 'GitHub'`
|
+ `'provider': 'GitHub'`
|
||||||
+ `}`;
|
+ `}`;
|
||||||
}
|
}
|
||||||
export function getWorkflowAnnotationKeyLabel(): string {
|
export function getWorkflowAnnotationKeyLabel(workflowFilePath: string): string {
|
||||||
const hashKey = require("crypto").createHash("MD5")
|
const hashKey = require("crypto").createHash("MD5")
|
||||||
.update(`${process.env.GITHUB_REPOSITORY}/${process.env.GITHUB_WORKFLOW}`)
|
.update(`${process.env.GITHUB_REPOSITORY}/${workflowFilePath}`)
|
||||||
.digest("hex");
|
.digest("hex");
|
||||||
return `githubWorkflow_${hashKey}`;
|
return `githubWorkflow_${hashKey}`;
|
||||||
}
|
}
|
||||||
@ -7,9 +7,9 @@ export class GitHubClient {
|
|||||||
this._token = token;
|
this._token = token;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getSuccessfulRunsOnBranch(branch: string, force?: boolean): Promise<any> {
|
public async getSuccessfulRunsOnBranch(branch: string, workflowFileName: string, force?: boolean): Promise<any> {
|
||||||
if (force || !this._successfulRunsOnBranchPromise) {
|
if (force || !this._successfulRunsOnBranchPromise) {
|
||||||
const lastSuccessfulRunUrl = `https://api.github.com/repos/${this._repository}/actions/runs?status=success&branch=${branch}`;
|
const lastSuccessfulRunUrl = `https://api.github.com/repos/${this._repository}/actions/workflows/${workflowFileName}/runs?status=success&branch=${branch}`;
|
||||||
const webRequest = new WebRequest();
|
const webRequest = new WebRequest();
|
||||||
webRequest.method = "GET";
|
webRequest.method = "GET";
|
||||||
webRequest.uri = lastSuccessfulRunUrl;
|
webRequest.uri = lastSuccessfulRunUrl;
|
||||||
@ -24,7 +24,25 @@ export class GitHubClient {
|
|||||||
return this._successfulRunsOnBranchPromise;
|
return this._successfulRunsOnBranchPromise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async getWorkflows(force?: boolean): Promise<any> {
|
||||||
|
if (force || !this._workflowsPromise) {
|
||||||
|
const getWorkflowFileNameUrl = `https://api.github.com/repos/${this._repository}/actions/workflows`;
|
||||||
|
const webRequest = new WebRequest();
|
||||||
|
webRequest.method = "GET";
|
||||||
|
webRequest.uri = getWorkflowFileNameUrl;
|
||||||
|
webRequest.headers = {
|
||||||
|
Authorization: `Bearer ${this._token}`
|
||||||
|
};
|
||||||
|
|
||||||
|
core.debug(`Getting workflows for repo: ${this._repository}`);
|
||||||
|
const response: WebResponse = await sendRequest(webRequest);
|
||||||
|
this._workflowsPromise = Promise.resolve(response);
|
||||||
|
}
|
||||||
|
return this._workflowsPromise;
|
||||||
|
}
|
||||||
|
|
||||||
private _repository: string;
|
private _repository: string;
|
||||||
private _token: string;
|
private _token: string;
|
||||||
private _successfulRunsOnBranchPromise: Promise<any>;
|
private _successfulRunsOnBranchPromise: Promise<any>;
|
||||||
|
private _workflowsPromise: Promise<any>;
|
||||||
}
|
}
|
||||||
@ -17,7 +17,7 @@ import { IExecSyncResult } from '../../utilities/tool-runner';
|
|||||||
|
|
||||||
import { deployPodCanary } from './pod-canary-deployment-helper';
|
import { deployPodCanary } from './pod-canary-deployment-helper';
|
||||||
import { deploySMICanary } from './smi-canary-deployment-helper';
|
import { deploySMICanary } from './smi-canary-deployment-helper';
|
||||||
import { checkForErrors, annotateChildPods, getLastSuccessfulRunSha } from "../utility";
|
import { checkForErrors, annotateChildPods, getWorkflowFilePath, getLastSuccessfulRunSha } from "../utility";
|
||||||
|
|
||||||
|
|
||||||
export async function deploy(kubectl: Kubectl, manifestFilePaths: string[], deploymentStrategy: string) {
|
export async function deploy(kubectl: Kubectl, manifestFilePaths: string[], deploymentStrategy: string) {
|
||||||
@ -112,15 +112,16 @@ async function checkManifestStability(kubectl: Kubectl, resources: Resource[]):
|
|||||||
await KubernetesManifestUtility.checkManifestStability(kubectl, resources);
|
await KubernetesManifestUtility.checkManifestStability(kubectl, resources);
|
||||||
}
|
}
|
||||||
|
|
||||||
function annotateAndLabelResources(files: string[], kubectl: Kubectl, resourceTypes: Resource[], allPods: any) {
|
async function annotateAndLabelResources(files: string[], kubectl: Kubectl, resourceTypes: Resource[], allPods: any) {
|
||||||
const annotationKeyLabel = models.getWorkflowAnnotationKeyLabel();
|
const workflowFilePath = await getWorkflowFilePath(TaskInputParameters.githubToken);
|
||||||
|
const annotationKeyLabel = models.getWorkflowAnnotationKeyLabel(workflowFilePath);
|
||||||
annotateResources(files, kubectl, resourceTypes, allPods, annotationKeyLabel);
|
annotateResources(files, kubectl, resourceTypes, allPods, annotationKeyLabel);
|
||||||
labelResources(files, kubectl, annotationKeyLabel);
|
labelResources(files, kubectl, annotationKeyLabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function annotateResources(files: string[], kubectl: Kubectl, resourceTypes: Resource[], allPods: any, annotationKey: string) {
|
function annotateResources(files: string[], kubectl: Kubectl, resourceTypes: Resource[], allPods: any, annotationKey: string) {
|
||||||
const annotateResults: IExecSyncResult[] = [];
|
const annotateResults: IExecSyncResult[] = [];
|
||||||
const lastSuccessSha = await getLastSuccessfulRunSha(TaskInputParameters.githubToken);
|
const lastSuccessSha = getLastSuccessfulRunSha(kubectl, TaskInputParameters.namespace, annotationKey);
|
||||||
let annotationKeyValStr = annotationKey + '=' + models.getWorkflowAnnotationsJson(lastSuccessSha);
|
let annotationKeyValStr = annotationKey + '=' + models.getWorkflowAnnotationsJson(lastSuccessSha);
|
||||||
annotateResults.push(kubectl.annotate('namespace', TaskInputParameters.namespace, [annotationKeyValStr], true));
|
annotateResults.push(kubectl.annotate('namespace', TaskInputParameters.namespace, [annotationKeyValStr], true));
|
||||||
annotateResults.push(kubectl.annotateFiles(files, [annotationKeyValStr], true));
|
annotateResults.push(kubectl.annotateFiles(files, [annotationKeyValStr], true));
|
||||||
|
|||||||
@ -51,25 +51,51 @@ export function checkForErrors(execResults: IExecSyncResult[], warnIfError?: boo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getLastSuccessfulRunSha(githubToken: string): Promise<string> {
|
export function getLastSuccessfulRunSha(kubectl: Kubectl, namespaceName: string, annotationKey: string): string {
|
||||||
let lastSuccessRunSha = '';
|
const result = kubectl.getResource('namespace', namespaceName);
|
||||||
const gitHubClient = new GitHubClient(process.env.GITHUB_REPOSITORY, githubToken);
|
if (!result) {
|
||||||
const branch = process.env.GITHUB_REF.replace("refs/heads/", "");
|
core.debug(`Failed to get commits from cluster.`);
|
||||||
const response = await gitHubClient.getSuccessfulRunsOnBranch(branch);
|
return '';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (result.stderr) {
|
||||||
|
core.debug(`${result.stderr}`);
|
||||||
|
return process.env.GITHUB_SHA;
|
||||||
|
}
|
||||||
|
else if (result.stdout) {
|
||||||
|
const annotationsSet = JSON.parse(result.stdout).metadata.annotations;
|
||||||
|
if (!!annotationsSet[annotationKey]) {
|
||||||
|
return JSON.parse(annotationsSet[annotationKey].replace(/'/g, '"')).commit;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return 'NA';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getWorkflowFilePath(githubToken: string): Promise<string> {
|
||||||
|
let workflowFilePath = process.env.GITHUB_WORKFLOW;
|
||||||
|
if (!workflowFilePath.startsWith('.github/workflows/')) {
|
||||||
|
const githubClient = new GitHubClient(process.env.GITHUB_REPOSITORY, githubToken);
|
||||||
|
const response = await githubClient.getWorkflows();
|
||||||
if (response.statusCode == StatusCodes.OK
|
if (response.statusCode == StatusCodes.OK
|
||||||
&& !!response.body
|
&& !!response.body
|
||||||
&& !!response.body.total_count) {
|
&& !!response.body.total_count) {
|
||||||
if (response.body.total_count > 0) {
|
if (response.body.total_count > 0) {
|
||||||
lastSuccessRunSha = response.body.workflow_runs[0].head_sha;
|
for (let workflow of response.body.workflows) {
|
||||||
|
if (process.env.GITHUB_WORKFLOW === workflow.name) {
|
||||||
|
workflowFilePath = workflow.path;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
lastSuccessRunSha = 'NA';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (response.statusCode != StatusCodes.OK) {
|
else if (response.statusCode != StatusCodes.OK) {
|
||||||
core.debug(`An error occured while getting succeessful run results. Statuscode: ${response.statusCode}, StatusMessage: ${response.statusMessage}`);
|
core.debug(`An error occured while getting list of workflows on the repo. Statuscode: ${response.statusCode}, StatusMessage: ${response.statusMessage}`);
|
||||||
}
|
}
|
||||||
return Promise.resolve(lastSuccessRunSha);
|
}
|
||||||
|
return Promise.resolve(workflowFilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function annotateChildPods(kubectl: Kubectl, resourceType: string, resourceName: string, annotationKeyValStr: string, allPods): IExecSyncResult[] {
|
export function annotateChildPods(kubectl: Kubectl, resourceType: string, resourceName: string, annotationKeyValStr: string, allPods): IExecSyncResult[] {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user