mirror of
https://github.com/Azure/k8s-deploy.git
synced 2026-04-11 16:52:18 +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)
|
||||
return Promise.resolve(errorWebResponse);
|
||||
});*/
|
||||
|
||||
jest.spyOn(httpClient, 'sendRequest').mockImplementation(() => Promise.resolve(lastSuccessfulRunUrlResponse));
|
||||
//Invoke and assert
|
||||
await expect(utility.getLastSuccessfulRunSha(process.env.GITHUB_TOKEN)).resolves.not.toThrowError;
|
||||
|
||||
@ -41,9 +41,9 @@ function getWorkflowAnnotationsJson(lastSuccessRunSha) {
|
||||
+ `}`;
|
||||
}
|
||||
exports.getWorkflowAnnotationsJson = getWorkflowAnnotationsJson;
|
||||
function getWorkflowAnnotationKeyLabel() {
|
||||
function getWorkflowAnnotationKeyLabel(workflowFilePath) {
|
||||
const hashKey = require("crypto").createHash("MD5")
|
||||
.update(`${process.env.GITHUB_REPOSITORY}/${process.env.GITHUB_WORKFLOW}`)
|
||||
.update(`${process.env.GITHUB_REPOSITORY}/${workflowFilePath}`)
|
||||
.digest("hex");
|
||||
return `githubWorkflow_${hashKey}`;
|
||||
}
|
||||
|
||||
@ -17,10 +17,10 @@ class GitHubClient {
|
||||
this._repository = repository;
|
||||
this._token = token;
|
||||
}
|
||||
getSuccessfulRunsOnBranch(branch, force) {
|
||||
getSuccessfulRunsOnBranch(branch, workflowFileName, force) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
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();
|
||||
webRequest.method = "GET";
|
||||
webRequest.uri = lastSuccessfulRunUrl;
|
||||
@ -34,5 +34,22 @@ class GitHubClient {
|
||||
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;
|
||||
|
||||
@ -111,25 +111,26 @@ function checkManifestStability(kubectl, resources) {
|
||||
});
|
||||
}
|
||||
function annotateAndLabelResources(files, kubectl, resourceTypes, allPods) {
|
||||
const annotationKeyLabel = models.getWorkflowAnnotationKeyLabel();
|
||||
annotateResources(files, kubectl, resourceTypes, allPods, annotationKeyLabel);
|
||||
labelResources(files, kubectl, annotationKeyLabel);
|
||||
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);
|
||||
labelResources(files, kubectl, annotationKeyLabel);
|
||||
});
|
||||
}
|
||||
function annotateResources(files, kubectl, resourceTypes, allPods, annotationKey) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const annotateResults = [];
|
||||
const lastSuccessSha = yield utility_1.getLastSuccessfulRunSha(TaskInputParameters.githubToken);
|
||||
let annotationKeyValStr = annotationKey + '=' + models.getWorkflowAnnotationsJson(lastSuccessSha);
|
||||
annotateResults.push(kubectl.annotate('namespace', TaskInputParameters.namespace, [annotationKeyValStr], true));
|
||||
annotateResults.push(kubectl.annotateFiles(files, [annotationKeyValStr], true));
|
||||
resourceTypes.forEach(resource => {
|
||||
if (resource.type.toUpperCase() !== models.KubernetesWorkload.pod.toUpperCase()) {
|
||||
utility_1.annotateChildPods(kubectl, resource.type, resource.name, annotationKeyValStr, allPods)
|
||||
.forEach(execResult => annotateResults.push(execResult));
|
||||
}
|
||||
});
|
||||
utility_1.checkForErrors(annotateResults, true);
|
||||
const annotateResults = [];
|
||||
const lastSuccessSha = utility_1.getLastSuccessfulRunSha(kubectl, TaskInputParameters.namespace, annotationKey);
|
||||
let annotationKeyValStr = annotationKey + '=' + models.getWorkflowAnnotationsJson(lastSuccessSha);
|
||||
annotateResults.push(kubectl.annotate('namespace', TaskInputParameters.namespace, [annotationKeyValStr], true));
|
||||
annotateResults.push(kubectl.annotateFiles(files, [annotationKeyValStr], true));
|
||||
resourceTypes.forEach(resource => {
|
||||
if (resource.type.toUpperCase() !== models.KubernetesWorkload.pod.toUpperCase()) {
|
||||
utility_1.annotateChildPods(kubectl, resource.type, resource.name, annotationKeyValStr, allPods)
|
||||
.forEach(execResult => annotateResults.push(execResult));
|
||||
}
|
||||
});
|
||||
utility_1.checkForErrors(annotateResults, true);
|
||||
}
|
||||
function labelResources(files, kubectl, label) {
|
||||
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 });
|
||||
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 core = require("@actions/core");
|
||||
const githubClient_1 = require("../githubClient");
|
||||
@ -60,29 +60,55 @@ function checkForErrors(execResults, warnIfError) {
|
||||
}
|
||||
}
|
||||
exports.checkForErrors = checkForErrors;
|
||||
function getLastSuccessfulRunSha(githubToken) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
let lastSuccessRunSha = '';
|
||||
const gitHubClient = new githubClient_1.GitHubClient(process.env.GITHUB_REPOSITORY, githubToken);
|
||||
const branch = process.env.GITHUB_REF.replace("refs/heads/", "");
|
||||
const response = yield gitHubClient.getSuccessfulRunsOnBranch(branch);
|
||||
if (response.statusCode == httpClient_1.StatusCodes.OK
|
||||
&& !!response.body
|
||||
&& !!response.body.total_count) {
|
||||
if (response.body.total_count > 0) {
|
||||
lastSuccessRunSha = response.body.workflow_runs[0].head_sha;
|
||||
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 {
|
||||
lastSuccessRunSha = 'NA';
|
||||
return 'NA';
|
||||
}
|
||||
}
|
||||
else if (response.statusCode != httpClient_1.StatusCodes.OK) {
|
||||
core.debug(`An error occured while getting succeessful run results. Statuscode: ${response.statusCode}, StatusMessage: ${response.statusMessage}`);
|
||||
}
|
||||
return Promise.resolve(lastSuccessRunSha);
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.getLastSuccessfulRunSha = getLastSuccessfulRunSha;
|
||||
function getWorkflowFilePath(githubToken) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
let workflowFilePath = process.env.GITHUB_WORKFLOW;
|
||||
if (!workflowFilePath.startsWith('.github/workflows/')) {
|
||||
const githubClient = new githubClient_1.GitHubClient(process.env.GITHUB_REPOSITORY, githubToken);
|
||||
const response = yield githubClient.getWorkflows();
|
||||
if (response.statusCode == httpClient_1.StatusCodes.OK
|
||||
&& !!response.body
|
||||
&& !!response.body.total_count) {
|
||||
if (response.body.total_count > 0) {
|
||||
for (let workflow of response.body.workflows) {
|
||||
if (process.env.GITHUB_WORKFLOW === workflow.name) {
|
||||
workflowFilePath = workflow.path;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (response.statusCode != httpClient_1.StatusCodes.OK) {
|
||||
core.debug(`An error occured while getting list of workflows on the repo. Statuscode: ${response.statusCode}, StatusMessage: ${response.statusMessage}`);
|
||||
}
|
||||
}
|
||||
return Promise.resolve(workflowFilePath);
|
||||
});
|
||||
}
|
||||
exports.getWorkflowFilePath = getWorkflowFilePath;
|
||||
function annotateChildPods(kubectl, resourceType, resourceName, annotationKeyValStr, allPods) {
|
||||
const commandExecutionResults = [];
|
||||
let owner = resourceName;
|
||||
|
||||
@ -40,9 +40,9 @@ export function getWorkflowAnnotationsJson(lastSuccessRunSha: string): string {
|
||||
+ `'provider': 'GitHub'`
|
||||
+ `}`;
|
||||
}
|
||||
export function getWorkflowAnnotationKeyLabel(): string {
|
||||
export function getWorkflowAnnotationKeyLabel(workflowFilePath: string): string {
|
||||
const hashKey = require("crypto").createHash("MD5")
|
||||
.update(`${process.env.GITHUB_REPOSITORY}/${process.env.GITHUB_WORKFLOW}`)
|
||||
.update(`${process.env.GITHUB_REPOSITORY}/${workflowFilePath}`)
|
||||
.digest("hex");
|
||||
return `githubWorkflow_${hashKey}`;
|
||||
}
|
||||
@ -7,9 +7,9 @@ export class GitHubClient {
|
||||
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) {
|
||||
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();
|
||||
webRequest.method = "GET";
|
||||
webRequest.uri = lastSuccessfulRunUrl;
|
||||
@ -24,7 +24,25 @@ export class GitHubClient {
|
||||
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 _token: string;
|
||||
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 { 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) {
|
||||
@ -112,15 +112,16 @@ async function checkManifestStability(kubectl: Kubectl, resources: Resource[]):
|
||||
await KubernetesManifestUtility.checkManifestStability(kubectl, resources);
|
||||
}
|
||||
|
||||
function annotateAndLabelResources(files: string[], kubectl: Kubectl, resourceTypes: Resource[], allPods: any) {
|
||||
const annotationKeyLabel = models.getWorkflowAnnotationKeyLabel();
|
||||
async function annotateAndLabelResources(files: string[], kubectl: Kubectl, resourceTypes: Resource[], allPods: any) {
|
||||
const workflowFilePath = await getWorkflowFilePath(TaskInputParameters.githubToken);
|
||||
const annotationKeyLabel = models.getWorkflowAnnotationKeyLabel(workflowFilePath);
|
||||
annotateResources(files, kubectl, resourceTypes, allPods, 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 lastSuccessSha = await getLastSuccessfulRunSha(TaskInputParameters.githubToken);
|
||||
const lastSuccessSha = getLastSuccessfulRunSha(kubectl, TaskInputParameters.namespace, annotationKey);
|
||||
let annotationKeyValStr = annotationKey + '=' + models.getWorkflowAnnotationsJson(lastSuccessSha);
|
||||
annotateResults.push(kubectl.annotate('namespace', TaskInputParameters.namespace, [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> {
|
||||
let lastSuccessRunSha = '';
|
||||
const gitHubClient = new GitHubClient(process.env.GITHUB_REPOSITORY, githubToken);
|
||||
const branch = process.env.GITHUB_REF.replace("refs/heads/", "");
|
||||
const response = await gitHubClient.getSuccessfulRunsOnBranch(branch);
|
||||
if (response.statusCode == StatusCodes.OK
|
||||
&& !!response.body
|
||||
&& !!response.body.total_count) {
|
||||
if (response.body.total_count > 0) {
|
||||
lastSuccessRunSha = response.body.workflow_runs[0].head_sha;
|
||||
export function getLastSuccessfulRunSha(kubectl: Kubectl, namespaceName: string, annotationKey: string): string {
|
||||
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 {
|
||||
lastSuccessRunSha = 'NA';
|
||||
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';
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (response.statusCode != StatusCodes.OK) {
|
||||
core.debug(`An error occured while getting succeessful run results. Statuscode: ${response.statusCode}, StatusMessage: ${response.statusMessage}`);
|
||||
}
|
||||
|
||||
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
|
||||
&& !!response.body
|
||||
&& !!response.body.total_count) {
|
||||
if (response.body.total_count > 0) {
|
||||
for (let workflow of response.body.workflows) {
|
||||
if (process.env.GITHUB_WORKFLOW === workflow.name) {
|
||||
workflowFilePath = workflow.path;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (response.statusCode != StatusCodes.OK) {
|
||||
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[] {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user