From b8ca34dc1d0579ad4b8907e54d5c8804b427d698 Mon Sep 17 00:00:00 2001 From: Nikhil Bhoski <47204011+nbhoski@users.noreply.github.com> Date: Tue, 2 Jul 2024 21:25:22 +0530 Subject: [PATCH] Add Summary table under summary section (#33) * Added Summary plugin * Testing temp folder generation * Testing temp folder generation * Testing temp folder generation * Testing temp folder generation * Testing temp folder generation * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Testing JSON parse * Refactored the JSON strategy * Refactored the JSON strategy * Changed temp foldr for summary json * Added unicode for status * Handdled failure scenarios * Refactored mathods for good readability * Refactored mathods for good readability * Refactored mathods for good readability * Refactored mathods for good readability * Added tests * Added tests * Added tests * Added tests * Added tests * Added tests * Added tests * Added tests * Added tests for json read * Added tests for json read * Added tests for json read * Updated tessts * Updated tessts * Changed the tabe heading * Updated as per review comments * Updated as per review comments * Updated as per review comments * Updated as per review comments * Handdled multiple try catch issue * Handdled multiple try catch issue * Handdled multiple try catch issue * Updated build plugin error message * Changed indenattion * Handdled errors close to the functions * Handdled errors close to the functions * Handdled errors close to the functions * Handdled errors close to the functions * Updating as per review comments * Updating as per review comments * Updating as per review comments --- .../+ciplugins/+github/BuildSummaryPlugin.m | 28 +++++++++ .../+ciplugins/+github/getDefaultPlugins.m | 1 + src/buildSummary.ts | 63 +++++++++++++++++++ src/buildSummary.unit.test.ts | 41 ++++++++++++ src/index.ts | 23 ++++--- 5 files changed, 148 insertions(+), 8 deletions(-) create mode 100644 plugins/+ciplugins/+github/BuildSummaryPlugin.m create mode 100644 src/buildSummary.ts create mode 100644 src/buildSummary.unit.test.ts diff --git a/plugins/+ciplugins/+github/BuildSummaryPlugin.m b/plugins/+ciplugins/+github/BuildSummaryPlugin.m new file mode 100644 index 00000000..1eed7a13 --- /dev/null +++ b/plugins/+ciplugins/+github/BuildSummaryPlugin.m @@ -0,0 +1,28 @@ +classdef BuildSummaryPlugin < matlab.buildtool.plugins.BuildRunnerPlugin + +% Copyright 2024 The MathWorks, Inc. + + methods (Access=protected) + + function runTaskGraph(plugin, pluginData) + runTaskGraph@matlab.buildtool.plugins.BuildRunnerPlugin(plugin, pluginData); + [fID, msg] = fopen(fullfile(getenv("RUNNER_TEMP") ,"buildSummary" + getenv("GITHUB_RUN_ID") + ".json"), "w"); + + if fID == -1 + warning("ciplugins:github:BuildSummaryPlugin:UnableToOpenFile","Unable to open a file required to create the MATLAB build summary table: %s", msg); + else + closeFile = onCleanup(@()fclose(fID)); + taskDetails = struct(); + for idx = 1:numel(pluginData.TaskResults) + taskDetails(idx).name = pluginData.TaskResults(idx).Name; + taskDetails(idx).description = pluginData.TaskGraph.Tasks(idx).Description; + taskDetails(idx).failed = pluginData.TaskResults(idx).Failed; + taskDetails(idx).skipped = pluginData.TaskResults(idx).Skipped; + taskDetails(idx).duration = string(pluginData.TaskResults(idx).Duration); + end + s = jsonencode(taskDetails); + fprintf(fID, "%s",s); + end + end + end +end \ No newline at end of file diff --git a/plugins/+ciplugins/+github/getDefaultPlugins.m b/plugins/+ciplugins/+github/getDefaultPlugins.m index cf16bd53..4b390e05 100644 --- a/plugins/+ciplugins/+github/getDefaultPlugins.m +++ b/plugins/+ciplugins/+github/getDefaultPlugins.m @@ -9,5 +9,6 @@ plugins = [ ... matlab.buildtool.internal.getFactoryDefaultPlugins(pluginProviderData) ... ciplugins.github.GitHubLogPlugin() ... + ciplugins.github.BuildSummaryPlugin() ... ]; end \ No newline at end of file diff --git a/src/buildSummary.ts b/src/buildSummary.ts new file mode 100644 index 00000000..95c02b97 --- /dev/null +++ b/src/buildSummary.ts @@ -0,0 +1,63 @@ +// Copyright 2024 The MathWorks, Inc. +import * as core from "@actions/core"; +import { join } from 'path'; +import { readFileSync } from 'fs'; + +export interface Task { + name: string; + description: string; + failed: boolean; + skipped: boolean; + duration: string; +} + + +export function getBuildSummaryTable(tasks: Task[]): string[][] { + const header: string[] = ['MATLAB Build Task', 'Status', 'Description', 'Duration (HH:MM:SS)']; + let taskSummaryTableRows: string[][] = [header]; + + tasks.forEach((task, index) => { + let taskDetails: string[] = []; + taskDetails.push(task.name); + if (task.failed) { + taskDetails.push('🔴 FAILED'); + } else if (task.skipped) { + taskDetails.push('🔵 SKIPPED'); + } else { + taskDetails.push('🟢 SUCCESS'); + } + taskDetails.push(task.description); + taskDetails.push(task.duration); + + taskSummaryTableRows.push(taskDetails); + }); + + return taskSummaryTableRows; +} + +export function writeSummary(taskSummaryTableRows: string[][]) { + try { + core.summary + .addTable(taskSummaryTableRows) + .write(); + } catch (e) { + console.error('An error occurred while adding the build results table to the summary:', e); + } +} + +export function processAndDisplayBuildSummary() { + const runId = process.env.GITHUB_RUN_ID || ''; + const runnerTemp = process.env.RUNNER_TEMP || ''; + + let taskSummaryTableRows; + try { + const filePath: string = join(runnerTemp, `buildSummary${runId}.json`); + const data = JSON.parse(readFileSync(filePath, { encoding: 'utf8' })); + taskSummaryTableRows = getBuildSummaryTable(data); + } catch (e) { + console.error('An error occurred while reading the build summary file:', e); + return; + } + writeSummary(taskSummaryTableRows); +} + diff --git a/src/buildSummary.unit.test.ts b/src/buildSummary.unit.test.ts new file mode 100644 index 00000000..0586f9ff --- /dev/null +++ b/src/buildSummary.unit.test.ts @@ -0,0 +1,41 @@ +// Copyright 2024 The MathWorks, Inc. + +import * as buildSummary from './buildSummary'; +import * as core from '@actions/core'; + + +jest.mock('@actions/core', () => ({ + summary: { + addTable: jest.fn().mockReturnThis(), + write: jest.fn().mockReturnThis(), + }, +})); + +describe('summaryGeneration', () => { + it('generates a summary table correctly', () => { + const mockTasks: buildSummary.Task[] = [ + { name: 'Test Task', description: 'A test task', failed: true, skipped: false, duration: '00:00:10' } + ]; + + const expectedTable = [ + ['MATLAB Build Task', 'Status', 'Description', 'Duration (HH:MM:SS)'], + ['Test Task', '🔴 FAILED', 'A test task', '00:00:10'], + ]; + + const table = buildSummary.getBuildSummaryTable(mockTasks); + + expect(table).toEqual(expectedTable); + }); + + it('writes the summary correctly', () => { + const mockTableRows = [ + ['MATLAB Build Task', 'Status', 'Description', 'Duration (HH:MM:SS)'], + ['Test Task', '🔴 FAILED', 'A test task', '00:00:10'], + ]; + + buildSummary.writeSummary(mockTableRows); + + expect(core.summary.addTable).toHaveBeenCalledTimes(1); + expect(core.summary.addTable).toHaveBeenCalledWith(mockTableRows); + }); +}); diff --git a/src/index.ts b/src/index.ts index af783997..b21e1460 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,11 +4,13 @@ import * as core from "@actions/core"; import * as exec from "@actions/exec"; import { matlab } from "run-matlab-command-action"; import * as buildtool from "./buildtool"; +import * as buildSummary from "./buildSummary"; /** * Gather action inputs and then run action. */ async function run() { + const platform = process.platform; const architecture = process.arch; const workspaceDir = process.cwd(); @@ -22,20 +24,25 @@ async function run() { const startupOptions = core.getInput("startup-options").split(" "); const helperScript = await matlab.generateScript(workspaceDir, command); - const execOptions = { env: { - ...process.env, - "MW_MATLAB_BUILDTOOL_DEFAULT_PLUGINS_FCN_OVERRIDE":"ciplugins.github.getDefaultPlugins", - }}; + const execOptions = { + env: { + ...process.env, + "MW_MATLAB_BUILDTOOL_DEFAULT_PLUGINS_FCN_OVERRIDE": "ciplugins.github.getDefaultPlugins", + } + }; await matlab.runCommand( helperScript, platform, architecture, - (cmd,args)=>exec.exec(cmd,args,execOptions), + (cmd, args) => exec.exec(cmd, args, execOptions), startupOptions - ); + ).finally(() => { + buildSummary.processAndDisplayBuildSummary(); + }); + } -run().catch((e) => { +run().catch(e => { core.setFailed(e); -}); +}); \ No newline at end of file