From 99eaee3722f4d4247a6f506e8974cb86246fda09 Mon Sep 17 00:00:00 2001 From: Brian Surowiec Date: Tue, 27 Apr 2021 17:03:55 -0400 Subject: [PATCH] Add support for dotnet-format v4 --- CHANGELOG.md | 2 ++ README.md | 4 +-- src/dotnet.ts | 80 ++++++++++++++++++++++++++++++++++++++++++++++++-- src/version.ts | 2 ++ 4 files changed, 83 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 950c0941..9628d871 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +- Added support for `dotnet-format` v4. To use this version set `version: 4`. + ## Version 1.2.0 - Bumped `@actions/core` from 1.2.6 to 1.2.7 diff --git a/README.md b/README.md index 2e7703a4..a8f3aa70 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![CI Workflow Status](https://github.com/xt0rted/dotnet-format/workflows/CI/badge.svg)](https://github.com/xt0rted/dotnet-format/actions?query=workflow%3ACI) -Run [dotnet-format](https://github.com/dotnet/format) v3 as part of your workflow to report formatting errors or auto fix violations as part of your pull request workflow. +Run [dotnet-format](https://github.com/dotnet/format) as part of your workflow to report formatting errors or auto fix violations as part of your pull request workflow. ## Usage @@ -160,7 +160,7 @@ jobs: Name | Allowed values | Description -- | -- | -- `repo-token` | `GITHUB_TOKEN` (default) or PAT | `GITHUB_TOKEN` token or a repo scoped PAT. -`version` | `3` (default) | Version of `dotnet-format` to use. +`version` | `3` (default), `4` | Version of `dotnet-format` to use. `action` | `check` (default), `fix` | Primary action `dotnet-format` should perform. ### Optional diff --git a/src/dotnet.ts b/src/dotnet.ts index 6189d4cd..04949a77 100644 --- a/src/dotnet.ts +++ b/src/dotnet.ts @@ -1,3 +1,8 @@ +import { + existsSync, + promises, +} from "fs"; + import { debug, info, @@ -13,6 +18,8 @@ import type { ExecOptions } from "@actions/exec/lib/interfaces"; import type { DotNetFormatVersion } from "./version"; +const { readFile } = promises; + export type FormatFunction = (options: FormatOptions) => Promise; export interface FormatOptions { @@ -34,8 +41,29 @@ function formatOnlyChangedFiles(onlyChangedFiles: boolean): boolean { return false; } +function tempReportFile(): string { + return `../dotnet-format-${new Date().getTime()}.json`; +} + +async function hadChangedFiles(report: string): Promise { + if (!existsSync(report)) { + throw Error(`Report not found at ${report}`); + } + + const reportContents = await readFile(report, "utf8"); + const formatResults = JSON.parse(reportContents) as []; + + debug(`Formatting issues found: ${formatResults.length}`); + + return !!formatResults.length; +} + async function formatVersion3(options: FormatOptions): Promise { - const execOptions: ExecOptions = { ignoreReturnCode: true }; + const execOptions: ExecOptions = { + ignoreReturnCode: true, + listeners: { debug }, + windowsVerbatimArguments: true, + }; const dotnetFormatOptions = ["format", "--check"]; @@ -48,9 +76,9 @@ async function formatVersion3(options: FormatOptions): Promise { info(`Checking ${filesToCheck.length} files`); - // if there weren't any files to check then we need to bail if (!filesToCheck.length) { - debug("No files found for formatting"); + debug("No files found to format"); + return false; } @@ -63,11 +91,57 @@ async function formatVersion3(options: FormatOptions): Promise { return !!dotnetResult; } +async function formatVersion4(options: FormatOptions): Promise { + const execOptions: ExecOptions = { + ignoreReturnCode: true, + listeners: { debug }, + windowsVerbatimArguments: true, + }; + + const dotnetFormatReport = tempReportFile(); + const dotnetFormatOptions = ["format", "--report", dotnetFormatReport]; + + if (options.dryRun) { + dotnetFormatOptions.push("--check"); + } + + if (formatOnlyChangedFiles(options.onlyChangedFiles)) { + const filesToCheck = await getPullRequestFiles(); + + info(`Checking ${filesToCheck.length} files`); + + if (!filesToCheck.length) { + debug("No files found to format"); + + return false; + } + + const files = filesToCheck + .map((file) => { + debug(`Including file: ${file}`); + + return `"${file}"`; + }); + + dotnetFormatOptions.push("-f", "--include", ...files); + } + + // If the args are passed as args while using the --report parameter then dotnet-format thinks the + // report path is the project path, but passing them as part of the command works as expected 🤷 + const dotnetPath: string = await which("dotnet", true); + await exec(`${dotnetPath} ${dotnetFormatOptions.join(" ")}`, [], execOptions); + + return await hadChangedFiles(dotnetFormatReport); +} + export function format(version: DotNetFormatVersion): FormatFunction { switch (version || "") { case "3": return formatVersion3; + case "4": + return formatVersion4; + default: throw Error(`dotnet-format version "${version}" is unsupported`); } diff --git a/src/version.ts b/src/version.ts index f242cf47..615a5ffd 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1,9 +1,11 @@ export type DotNetFormatVersion = | "3" + | "4" ; const supportedVersions: DotNetFormatVersion[] = [ "3", + "4", ]; export function checkVersion(version: string): DotNetFormatVersion {