From 1d5de1f61b2cafc0ca80f92ae45374683b39387c Mon Sep 17 00:00:00 2001 From: "Breno A." Date: Wed, 25 Sep 2024 22:40:27 -0300 Subject: [PATCH] feat: implement codeHealth and badge --- README.md | 26 +++++++-------- action.yml | 3 +- src/github/comments.ts | 7 ++-- src/templates/badge.ts | 63 ++++++++++++++++++++++++++++++++++++ src/templates/comment.ts | 69 +++++++++++++++++++++++++++++----------- src/types.ts | 13 ++++++++ 6 files changed, 142 insertions(+), 39 deletions(-) create mode 100644 src/templates/badge.ts diff --git a/README.md b/README.md index 28b17b1..31871b2 100644 --- a/README.md +++ b/README.md @@ -15,8 +15,8 @@ request alerts and display badges effortlessly.
Preview - - ![image](https://github.com/user-attachments/assets/975a8e08-ce7d-4b36-8f2d-3b16307a4d49) + +![image](https://github.com/user-attachments/assets/975a8e08-ce7d-4b36-8f2d-3b16307a4d49)
## Installation @@ -63,7 +63,7 @@ jobs: with: github-token: ${{ secrets.GITHUB_TOKEN }} # check inputs for full args list - + ``` ## Usage @@ -76,16 +76,16 @@ artifacts. > [!TIP] > You can find the list of inputs and their descriptions in the [action.yml](action.yml) file. -| Input | Description | Required | Default | -|-----------------|-------------------------------------------------------------------|----------|----------| -| github-token | GitHub token for commenting on pull requests/generating artifacts | false | | -| version | Version of Vue Mess Detector | true | latest | -| skipInstall | Skip the installation of Vue Mess Detector | true | false | -| commentsEnabled | Comment on Pull requests? | true | true | -| packageManager | Package manager to use | false | (detect) | -| runArgs | Arguments to pass to Vue Mess Detector | false | | -| entryPoint | Entry point for Vue Mess Detector | false | ./ | -| srcDir | Source directory to analyze | true | src/ | +| Input | Description | Required | Default | +|-----------------|----------------------------------------------|----------|----------| +| github-token | GitHub token for commenting on pull requests | false | | +| version | Version of Vue Mess Detector | true | latest | +| skipInstall | Skip the installation of Vue Mess Detector | true | false | +| commentsEnabled | Comment on Pull requests? | true | true | +| packageManager | Package manager to use | false | (detect) | +| runArgs | Arguments to pass to Vue Mess Detector | false | | +| entryPoint | Entry point for Vue Mess Detector | false | ./ | +| srcDir | Source directory to analyze | true | src/ | ## Contributing diff --git a/action.yml b/action.yml index b110add..2a9afd1 100644 --- a/action.yml +++ b/action.yml @@ -7,8 +7,7 @@ branding: color: "green" inputs: github-token: - description: - "GitHub token for commenting on pull requests/generating artifacts" + description: "GitHub token for commenting on pull requests" required: false version: description: "Version of Vue Mess Detector" diff --git a/src/github/comments.ts b/src/github/comments.ts index 1865e24..7973eb5 100644 --- a/src/github/comments.ts +++ b/src/github/comments.ts @@ -5,7 +5,7 @@ import { GitHub } from "@actions/github/lib/utils.js"; import { getCommentTemplate } from "../templates/comment.js"; export async function commentOnPullRequest( - parsedOutput: VMDAnalysis, + analysis: VMDAnalysis, artifactId: number | undefined ): Promise { if (!github.context.payload.pull_request) { @@ -22,10 +22,7 @@ export async function commentOnPullRequest( const pull_number: number = github.context.payload.pull_request.number; try { - const commentBody: string = getCommentTemplate( - parsedOutput.codeHealthOutput, - artifactId - ); + const commentBody: string = getCommentTemplate(analysis, artifactId); await octokit.rest.issues.createComment({ owner, repo, diff --git a/src/templates/badge.ts b/src/templates/badge.ts new file mode 100644 index 0000000..8f19dbe --- /dev/null +++ b/src/templates/badge.ts @@ -0,0 +1,63 @@ +import * as core from "@actions/core"; + +const baseUrl: string = "https://img.shields.io/badge/"; + +export type BadgeStyle = + | "flat" + | "plastic" + | "flat-square" + | "for-the-badge" + | "social"; + +interface BadgeOptions { + text: string; + style: BadgeStyle; + label: string; + labelColor: string; + color: string; +} + +export function buildBadgeUrl({ + text, + style, + label, + labelColor, + color +}: BadgeOptions): string { + return `${baseUrl}${text}-${text}?style=${style}&label=${encodeURIComponent(label)}&labelColor=${labelColor}&color=${color}`; +} + +export function getCoverageBadge( + percentage: number | undefined | string +): string { + let color: string = "blue"; + const label: string = "Code Health"; + + if (percentage === undefined) { + percentage = "N/A"; + color = "lightgrey"; + core.warning( + "No code health data found in the analysis output! you may need to update vue-mess-detector to >= 0.54.1" + ); + } + + if (typeof percentage === "number") { + if (percentage < 40) { + color = "red"; + } else if (percentage < 70) { + color = "yellow"; + } else { + color = "green"; + } + } + + const badgeUrl: string = buildBadgeUrl({ + text: `${percentage.toString()}%`, + style: "flat", + label, + labelColor: "8A2BE2", + color + }); + + return `![${label}](${badgeUrl})`; +} diff --git a/src/templates/comment.ts b/src/templates/comment.ts index aee8d3c..d128b8f 100644 --- a/src/templates/comment.ts +++ b/src/templates/comment.ts @@ -1,39 +1,70 @@ -import { CodeHealthOutputElement } from "../types.js"; +import { CodeHealth, VMDAnalysis } from "../types.js"; import * as github from "@actions/github"; +import { getCoverageBadge } from "./badge.js"; const comment: string = ` -## 🎉 Vue Mess Detector Analysis Results 🎉 - -📊 **Coverage Information:** +## 📊 Vue Mess Detector Analysis Results +#### Code Health: {{coverageBadge}} {{coverageInfo}} {{artifactText}} -_For any issues, please report them [here](https://github.com/brenoepics/vmd-action/issues) 🐞._ +###### For any issues, please [report them here](https://github.com/brenoepics/vmd-action/issues/). +`; + +const coverageInfo: string = ` +Errors: {{errors}} +Warnings: {{warnings}} +Total Lines: {{linesCount}} +Total Files: {{filesCount}} +Points: {{points}} `; const artifactText: string = ` -🚀 The detailed coverage report has been successfully uploaded! You can access it [here](../actions/runs/{{runId}}/artifacts/{{artifactId}}) 🔗. +[See analysis details here](../actions/runs/{{runId}}/artifacts/{{artifactId}}) `; -/** - * TODO: this is a tweak to remove the progress,in the future would be great to have a fully parsed errors, warns... message. - * - */ -export function getCommentTemplate( - codeHealthOutput: CodeHealthOutputElement[], - artifactId: number | undefined -): string { - const coverageInfo: string = codeHealthOutput - .filter((_, index) => index !== 1) // Skip the progress element (index 1) - .map(element => element.info) - .join("\n"); +function getCoverageInfo(result: VMDAnalysis) { + return result.codeHealthOutput.map(element => element.info).join("\n"); +} - return comment +function replaceCodeHealth(message: string, health: CodeHealth) { + return message .replace(/{{coverageInfo}}/g, coverageInfo) + .replace(/{{errors}}/g, health.errors.toString()) + .replace(/{{warnings}}/g, health.warnings.toString()) + .replace(/{{linesCount}}/g, health.linesCount.toString()) + .replace(/{{filesCount}}/g, health.filesCount.toString()) + .replace(/{{points}}/g, health.points.toString()); +} + +function replaceRepoData(message: string, artifactId: number | undefined) { + return message .replace(/{{artifactText}}/g, artifactId ? artifactText : "") .replace(/{{artifactId}}/g, String(artifactId ?? 0)) .replace(/{{runId}}/g, github.context.runId.toString()) .replace(/{{repository/g, github.context.repo.repo) .replace(/{{repositoryOwner/g, github.context.repo.owner); } + +function replaceBadges(message: string, result: VMDAnalysis) { + return message.replace( + /{{coverageBadge}}/g, + getCoverageBadge(result.codeHealth?.points) + ); +} + +export function getCommentTemplate( + result: VMDAnalysis, + artifactId: number | undefined +): string { + let message: string = replaceRepoData(comment, artifactId); + if (result.codeHealth) { + message = replaceCodeHealth(message, result.codeHealth); + } else { + message = message.replace(/{{coverageInfo}}/g, getCoverageInfo(result)); + } + + message = replaceBadges(message, result); + return message; +} diff --git a/src/types.ts b/src/types.ts index 2456b94..050c30a 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,7 +1,20 @@ +/** + * This file contains the typescript interfaces for the VMDAnalysis object + * codeHealth is only present on vue-mess-detector >= 0.54.1 + */ export interface VMDAnalysis { output: CodeHealthOutputElement[]; codeHealthOutput: CodeHealthOutputElement[]; reportOutput: { [key: string]: ReportOutput[] }; + codeHealth?: CodeHealth; +} + +export interface CodeHealth { + errors: number; + warnings: number; + linesCount: number; + filesCount: number; + points: number; } export interface CodeHealthOutputElement {