From 0f99bababcb12d655c445afa4ef1008970ae3ce9 Mon Sep 17 00:00:00 2001 From: Edward McFarlane Date: Fri, 5 Jul 2024 17:12:10 -0400 Subject: [PATCH] Test parsing format diff --- dist/index.js | 42 ++++++++++++++++++++++++++++++++++++------ src/main.ts | 39 +++++++++++++++++++++++++++++++++------ 2 files changed, 69 insertions(+), 12 deletions(-) diff --git a/dist/index.js b/dist/index.js index 1b166da..2cfc710 100644 --- a/dist/index.js +++ b/dist/index.js @@ -9896,6 +9896,15 @@ function onceStrict (fn) { } +/***/ }), + +/***/ 4833: +/***/ ((module) => { + +"use strict"; +function _typeof(obj){"@babel/helpers - typeof";return _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(obj){return typeof obj}:function(obj){return obj&&"function"==typeof Symbol&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj},_typeof(obj)}function _createForOfIteratorHelper(o,allowArrayLike){var it=typeof Symbol!=="undefined"&&o[Symbol.iterator]||o["@@iterator"];if(!it){if(Array.isArray(o)||(it=_unsupportedIterableToArray(o))||allowArrayLike&&o&&typeof o.length==="number"){if(it)o=it;var i=0;var F=function F(){};return{s:F,n:function n(){if(i>=o.length)return{done:true};return{done:false,value:o[i++]}},e:function e(_e2){throw _e2},f:F}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var normalCompletion=true,didErr=false,err;return{s:function s(){it=it.call(o)},n:function n(){var step=it.next();normalCompletion=step.done;return step},e:function e(_e3){didErr=true;err=_e3},f:function f(){try{if(!normalCompletion&&it["return"]!=null)it["return"]()}finally{if(didErr)throw err}}}}function _defineProperty(obj,key,value){key=_toPropertyKey(key);if(key in obj){Object.defineProperty(obj,key,{value:value,enumerable:true,configurable:true,writable:true})}else{obj[key]=value}return obj}function _toPropertyKey(arg){var key=_toPrimitive(arg,"string");return _typeof(key)==="symbol"?key:String(key)}function _toPrimitive(input,hint){if(_typeof(input)!=="object"||input===null)return input;var prim=input[Symbol.toPrimitive];if(prim!==undefined){var res=prim.call(input,hint||"default");if(_typeof(res)!=="object")return res;throw new TypeError("@@toPrimitive must return a primitive value.")}return(hint==="string"?String:Number)(input)}function _slicedToArray(arr,i){return _arrayWithHoles(arr)||_iterableToArrayLimit(arr,i)||_unsupportedIterableToArray(arr,i)||_nonIterableRest()}function _nonIterableRest(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function _unsupportedIterableToArray(o,minLen){if(!o)return;if(typeof o==="string")return _arrayLikeToArray(o,minLen);var n=Object.prototype.toString.call(o).slice(8,-1);if(n==="Object"&&o.constructor)n=o.constructor.name;if(n==="Map"||n==="Set")return Array.from(o);if(n==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return _arrayLikeToArray(o,minLen)}function _arrayLikeToArray(arr,len){if(len==null||len>arr.length)len=arr.length;for(var i=0,arr2=new Array(len);i core.debug(`done in ${process.uptime()} s`)); // createSummary creates a GitHub summary of the steps. The summary is a table // with the name and status of each step. -function createSummary(inputs, steps) { +function createSummary(inputs, steps, moduleNames) { const table = [ [ { data: "Build", header: true }, @@ -45821,6 +45835,7 @@ function createSummary(inputs, steps) { }), ], ]; + console.log("moduleNames", moduleNames); // If push or archive is enabled add a link to the registry. //if (inputs.push) table.push(["push", message(steps.push?.status)]); //if (inputs.archive) table.push(["archive", message(steps.archive?.status)]); @@ -45830,7 +45845,7 @@ function createSummary(inputs, steps) { // First, it builds the input. If the build fails, the workflow stops. // Next, it runs lint, format, and breaking checks. If any of these fail, the workflow stops. // Finally, it pushes or archives the label to the registry. -async function runWorkflow(bufPath, inputs) { +async function runWorkflow(bufPath, inputs, moduleNames) { const steps = {}; steps.build = await build(bufPath, inputs); if (steps.build.status == Status.Failed) { @@ -45847,7 +45862,6 @@ async function runWorkflow(bufPath, inputs) { if (checks.some((result) => result.status == Status.Failed)) { return steps; } - const moduleNames = await parseModuleNames(bufPath, inputs.input); steps.push = await push(bufPath, inputs, moduleNames); steps.archive = await archive(inputs, moduleNames); return steps; @@ -45924,7 +45938,23 @@ async function format(bufPath, inputs) { for (const path of inputs.exclude_paths) { args.push("--exclude-path", path); } - return run(bufPath, args); + const result = await run(bufPath, args); + if (result.status == Status.Failed) { + // If the format step fails, parse the diff and write github annotations. + const diff = parse_diff(result.stdout); + result.stdout = ""; // Clear the stdout. + console.log("diff", diff); + for (const file of diff) { + for (const chunk of file.chunks) { + for (const change of chunk.changes) { + // TODO: Write annotations. + console.log("change", change); + //result.stdout += `::error file=${name},line=${line},title=${title}::${message}\n`; + } + } + } + } + return result; } // breaking runs the "buf breaking" step. async function breaking(bufPath, inputs) { diff --git a/src/main.ts b/src/main.ts index 0efcbf7..e2791b8 100644 --- a/src/main.ts +++ b/src/main.ts @@ -20,6 +20,7 @@ import { createConnectTransport } from "@connectrpc/connect-web"; import { createPromiseClient, ConnectError, Code } from "@connectrpc/connect"; import { LabelService } from "@buf/bufbuild_registry.connectrpc_es/buf/registry/module/v1/label_service_connect"; import { LabelRef } from "@buf/bufbuild_registry.bufbuild_es/buf/registry/module/v1/label_pb"; +import * as parseDiff from "parse-diff"; import { getInputs, Inputs, getEnv } from "./inputs"; import { Outputs } from "./outputs"; @@ -38,10 +39,12 @@ async function main() { core.info("Setup only, skipping steps"); return; } + // Parse the module names from the input. + const moduleNames = await parseModuleNames(bufPath, inputs.input); // Run the buf workflow. - const steps = await runWorkflow(bufPath, inputs); + const steps = await runWorkflow(bufPath, inputs, moduleNames); // Create a summary of the steps. - const summary = createSummary(inputs, steps); + const summary = createSummary(inputs, steps, moduleNames); // Comment on the PR with the summary, if requested. if (inputs.pr_comment) { const commentID = await findCommentOnPR(context, github); @@ -83,7 +86,11 @@ interface Steps { // createSummary creates a GitHub summary of the steps. The summary is a table // with the name and status of each step. -function createSummary(inputs: Inputs, steps: Steps): typeof core.summary { +function createSummary( + inputs: Inputs, + steps: Steps, + moduleNames: ModuleName[], +): typeof core.summary { const table = [ [ { data: "Build", header: true }, @@ -105,6 +112,7 @@ function createSummary(inputs: Inputs, steps: Steps): typeof core.summary { }), ], ]; + console.log("moduleNames", moduleNames); // If push or archive is enabled add a link to the registry. //if (inputs.push) table.push(["push", message(steps.push?.status)]); //if (inputs.archive) table.push(["archive", message(steps.archive?.status)]); @@ -115,7 +123,11 @@ function createSummary(inputs: Inputs, steps: Steps): typeof core.summary { // First, it builds the input. If the build fails, the workflow stops. // Next, it runs lint, format, and breaking checks. If any of these fail, the workflow stops. // Finally, it pushes or archives the label to the registry. -async function runWorkflow(bufPath: string, inputs: Inputs): Promise { +async function runWorkflow( + bufPath: string, + inputs: Inputs, + moduleNames: ModuleName[], +): Promise { const steps: Steps = {}; steps.build = await build(bufPath, inputs); if (steps.build.status == Status.Failed) { @@ -132,7 +144,6 @@ async function runWorkflow(bufPath: string, inputs: Inputs): Promise { if (checks.some((result) => result.status == Status.Failed)) { return steps; } - const moduleNames = await parseModuleNames(bufPath, inputs.input); steps.push = await push(bufPath, inputs, moduleNames); steps.archive = await archive(inputs, moduleNames); return steps; @@ -217,7 +228,23 @@ async function format(bufPath: string, inputs: Inputs): Promise { for (const path of inputs.exclude_paths) { args.push("--exclude-path", path); } - return run(bufPath, args); + const result = await run(bufPath, args); + if (result.status == Status.Failed) { + // If the format step fails, parse the diff and write github annotations. + const diff = parseDiff(result.stdout); + result.stdout = ""; // Clear the stdout. + console.log("diff", diff); + for (const file of diff) { + for (const chunk of file.chunks) { + for (const change of chunk.changes) { + // TODO: Write annotations. + console.log("change", change); + //result.stdout += `::error file=${name},line=${line},title=${title}::${message}\n`; + } + } + } + } + return result; } // breaking runs the "buf breaking" step.