Skip to content

Commit

Permalink
chore(logs): Prefix imported logs
Browse files Browse the repository at this point in the history
  • Loading branch information
aurelien-baudet committed Jun 9, 2023
1 parent c2b3c6d commit 46e0c62
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 101 deletions.
7 changes: 6 additions & 1 deletion .github/workflows/retrieve-logs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Echo message
run: for i in {1..5000}; do; echo "Hello $i"; sleep 0.1; done
run: |
for i in {1..500}
do
echo "Hello $i"
sleep 0.1
done
timeout:
runs-on: ubuntu-latest
Expand Down
78 changes: 34 additions & 44 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9765,8 +9765,7 @@ function handleLogs(args, workflowHandler) {
return __awaiter(this, void 0, void 0, function* () {
try {
const workflowRunId = yield workflowHandler.getWorkflowRunId();
const workflowLogsHandler = (0, workflow_logs_handler_1.logHandlerFactory)(args.workflowLogMode, args.token, workflowRunId, args.owner, args.repo);
yield workflowLogsHandler.handle();
yield (0, workflow_logs_handler_1.handleWorkflowLogsPerJob)(args, workflowRunId);
}
catch (e) {
core.error(`Failed to handle logs of tirggered workflow. Cause: ${e}`);
Expand Down Expand Up @@ -10227,82 +10226,73 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
});
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.logHandlerFactory = void 0;
exports.handleWorkflowLogsPerJob = void 0;
const core = __importStar(__nccwpck_require__(2186));
const github = __importStar(__nccwpck_require__(5438));
const debug_1 = __nccwpck_require__(1417);
function getWorkflowLogsPerJob(octokit, workflowRunId, owner, repo) {
var _a;
function handleWorkflowLogsPerJob(args, workflowRunId) {
return __awaiter(this, void 0, void 0, function* () {
const logsPerJob = [];
const mode = args.workflowLogMode;
const token = args.token;
const owner = args.token;
const repo = args.repo;
const handler = logHandlerFactory(mode);
if (handler == null) {
return;
}
const octokit = github.getOctokit(token);
const runId = workflowRunId;
const response = yield octokit.rest.actions.listJobsForWorkflowRun({
owner: owner,
repo: repo,
run_id: runId
});
(0, debug_1.debug)('Jobs in workflow', response);
yield handler.handleJobList(response.data.jobs);
for (const job of response.data.jobs) {
try {
const jobLog = yield octokit.rest.actions.downloadJobLogsForWorkflowRun({
owner: owner,
repo: repo,
job_id: job.id,
});
(0, debug_1.debug)(`Job ${job.id} log`, jobLog);
logsPerJob.push({
job: job,
logs: (_a = jobLog.data) === null || _a === void 0 ? void 0 : _a.toString()
});
yield handler.handleJobLogs(job, jobLog.data);
}
catch (error) {
(0, debug_1.debug)('Job log download error', error);
logsPerJob.push({
job: job,
error: error instanceof Error ? error : new Error(`${error}`)
});
yield handler.handleError(job, error);
}
}
return logsPerJob;
});
}
class NoOpLogsHandler {
handle() {
exports.handleWorkflowLogsPerJob = handleWorkflowLogsPerJob;
class PrintLogsHandler {
handleJobList(jobs) {
return __awaiter(this, void 0, void 0, function* () {
(0, debug_1.debug)('Retrieving logs for jobs in workflow', jobs);
});
}
}
class PrintLogsHandler {
constructor(token, workflowRunId, owner, repo) {
this.workflowRunId = workflowRunId;
this.owner = owner;
this.repo = repo;
// Get octokit client for making API calls
this.octokit = github.getOctokit(token);
handleJobLogs(job, logs) {
return __awaiter(this, void 0, void 0, function* () {
core.startGroup(`Logs of job '${job.name}'`);
core.info(escapeImportedLogs(logs));
core.endGroup();
});
}
handle() {
handleError(job, error) {
return __awaiter(this, void 0, void 0, function* () {
const logsPerJob = yield getWorkflowLogsPerJob(this.octokit, this.workflowRunId, this.owner, this.repo);
for (const jobLogs of logsPerJob) {
core.info(`::group::Logs of job '${jobLogs.job.name}'`);
if (jobLogs.logs) {
core.info(jobLogs.logs);
}
if (jobLogs.error) {
core.warning(jobLogs.error);
}
core.info(`::endgroup::`);
}
core.warning(escapeImportedLogs(error.message));
});
}
}
function logHandlerFactory(mode, token, workflowRunId, owner, repo) {
function logHandlerFactory(mode) {
switch (mode) {
case 'print': return new PrintLogsHandler(token, workflowRunId, owner, repo);
default: return new NoOpLogsHandler();
case 'print': return new PrintLogsHandler();
default: return null;
}
}
exports.logHandlerFactory = logHandlerFactory;
function escapeImportedLogs(str) {
return str.replace(/^/mg, "| ")
.replace(/^(##\[[^\]]+\])/gm, "| $1");
}


/***/ }),
Expand Down
5 changes: 2 additions & 3 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import * as core from '@actions/core'
import * as github from '@actions/github'
import { formatDuration, getArgs, isTimedOut, sleep } from './utils';
import { WorkflowHandler, WorkflowRunConclusion, WorkflowRunResult, WorkflowRunStatus } from './workflow-handler';
import { logHandlerFactory } from './workflow-logs-handler';
import { handleWorkflowLogsPerJob } from './workflow-logs-handler';



Expand Down Expand Up @@ -64,8 +64,7 @@ function computeConclusion(start: number, waitForCompletionTimeout: number, resu
async function handleLogs(args: any, workflowHandler: WorkflowHandler) {
try {
const workflowRunId = await workflowHandler.getWorkflowRunId()
const workflowLogsHandler = logHandlerFactory(args.workflowLogMode, args.token, workflowRunId, args.owner, args.repo);
await workflowLogsHandler.handle();
await handleWorkflowLogsPerJob(args, workflowRunId);
} catch(e: any) {
core.error(`Failed to handle logs of tirggered workflow. Cause: ${e}`);
}
Expand Down
95 changes: 42 additions & 53 deletions src/workflow-logs-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,30 @@ import { debug } from './debug';

interface JobInfo {
name: string,
id: string
}
interface JobLogs {
job: JobInfo,
logs?: string,
error?: Error
id: number
}


async function getWorkflowLogsPerJob(octokit: any, workflowRunId: number, owner: string, repo: string): Promise<Array<JobLogs>> {
const logsPerJob: Array<JobLogs> = []
export async function handleWorkflowLogsPerJob(args: any, workflowRunId: number): Promise<void> {
const mode = args.workflowLogMode;
const token = args.token;
const owner = args.owner;
const repo = args.repo;

const handler = logHandlerFactory(mode);
if (handler == null) {
return;
}

const octokit = github.getOctokit(token);
const runId = workflowRunId;
const response = await octokit.rest.actions.listJobsForWorkflowRun({
owner: owner,
repo: repo,
run_id: runId
});

debug('Jobs in workflow', response);
await handler.handleJobList(response.data.jobs);

for (const job of response.data.jobs) {
try {
Expand All @@ -32,65 +36,50 @@ async function getWorkflowLogsPerJob(octokit: any, workflowRunId: number, owner:
repo: repo,
job_id: job.id,
});
debug(`Job ${job.id} log`, jobLog);

logsPerJob.push({
job: job,
logs: jobLog.data?.toString()
});
} catch (error) {
debug('Job log download error', error);
logsPerJob.push({
job: job,
error: error instanceof Error ? error : new Error(`${error}`)
});
await handler.handleJobLogs(job, jobLog.data as string);
} catch (error: any) {
await handler.handleError(job, error);
}
}

return logsPerJob;
}



export interface WorkflowLogHandler {
handle(): Promise<void>
}

class NoOpLogsHandler implements WorkflowLogHandler {
async handle(): Promise<void> {
}


interface WorkflowLogHandler {
handleJobList(jobs: Array<JobInfo>): Promise<void>
handleJobLogs(job: JobInfo, logs: string): Promise<void>
handleError(job: JobInfo, error: Error): Promise<void>
}

class PrintLogsHandler implements WorkflowLogHandler {
private octokit: any;

constructor(token: string,
private workflowRunId: number,
private owner: string,
private repo: string) {
// Get octokit client for making API calls
this.octokit = github.getOctokit(token);

async handleJobList(jobs: Array<JobInfo>): Promise<void> {
debug('Retrieving logs for jobs in workflow', jobs);
}

async handle(): Promise<void> {
const logsPerJob = await getWorkflowLogsPerJob(this.octokit, this.workflowRunId, this.owner, this.repo);

for (const jobLogs of logsPerJob) {
core.info(`::group::Logs of job '${jobLogs.job.name}'`);
if (jobLogs.logs) {
core.info(jobLogs.logs);
}
if (jobLogs.error) {
core.warning(jobLogs.error);
}
core.info(`::endgroup::`);
}
async handleJobLogs(job: JobInfo, logs: string): Promise<void> {
core.startGroup(`Logs of job '${job.name}'`);
core.info(escapeImportedLogs(logs));
core.endGroup();

}

async handleError(job: JobInfo, error: Error): Promise<void> {
core.warning(escapeImportedLogs(error.message));
}
}

export function logHandlerFactory(mode: string, token: string, workflowRunId: number, owner: string, repo: string): WorkflowLogHandler {
function logHandlerFactory(mode: string): WorkflowLogHandler | null {
switch(mode) {
case 'print': return new PrintLogsHandler(token, workflowRunId, owner, repo);
default: return new NoOpLogsHandler();
case 'print': return new PrintLogsHandler();
default: return null;
}
}

function escapeImportedLogs(str: string): string {
return str.replace(/^/mg, "| ")
.replace(/##\[([^\]]+)\]/gm, "##<$1>")
}

0 comments on commit 46e0c62

Please sign in to comment.