From 211a5c7a739bdbb6e3d7ffebfa1d78711980a843 Mon Sep 17 00:00:00 2001 From: Ikiru Yoshizaki <3856350+guitarrapc@users.noreply.github.com> Date: Tue, 10 Dec 2024 20:24:11 +0900 Subject: [PATCH 01/21] feat: added action command, versioning --- .gitignore | 403 +++++++++++++++++++++ Actions.sln | 22 ++ src/Actions/Actions.csproj | 17 + src/Actions/Program.cs | 114 ++++++ src/Actions/Properties/launchSettings.json | 28 ++ 5 files changed, 584 insertions(+) create mode 100644 .gitignore create mode 100644 Actions.sln create mode 100644 src/Actions/Actions.csproj create mode 100644 src/Actions/Program.cs create mode 100644 src/Actions/Properties/launchSettings.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84681bb --- /dev/null +++ b/.gitignore @@ -0,0 +1,403 @@ +### Generated by gibo (https://github.com/simonwhitaker/gibo) +### https://raw.github.com/github/gitignore/077ec2d64ed63f9db51bba853ac9f1cd51654da1/VisualStudio.gitignore + +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +# but not Directory.Build.rsp, as it configures directory-level build defaults +!Directory.Build.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio 6 auto-generated project file (contains which files were open etc.) +*.vbp + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files +*.ncb +*.aps + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp + +# JetBrains Rider +*.sln.iml diff --git a/Actions.sln b/Actions.sln new file mode 100644 index 0000000..89ea2b1 --- /dev/null +++ b/Actions.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.12.35527.113 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Actions", "src\Actions\Actions.csproj", "{0371D0AA-BB43-4136-B9AA-A311A3E4615B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0371D0AA-BB43-4136-B9AA-A311A3E4615B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0371D0AA-BB43-4136-B9AA-A311A3E4615B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0371D0AA-BB43-4136-B9AA-A311A3E4615B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0371D0AA-BB43-4136-B9AA-A311A3E4615B}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/Actions/Actions.csproj b/src/Actions/Actions.csproj new file mode 100644 index 0000000..7813782 --- /dev/null +++ b/src/Actions/Actions.csproj @@ -0,0 +1,17 @@ + + + + Exe + net8.0 + enable + enable + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + diff --git a/src/Actions/Program.cs b/src/Actions/Program.cs new file mode 100644 index 0000000..3d2014f --- /dev/null +++ b/src/Actions/Program.cs @@ -0,0 +1,114 @@ +using ConsoleAppFramework; + +var app = ConsoleApp.Create(); +app.Add(); +app.Run(args); + +public class ActionsCommand +{ + /// Get version string from tag + /// + /// + /// + /// + /// + /// + public void Versioning(string tag, string prefix = "", VersionIncrement versionIncrement = VersionIncrement.Patch, bool isPrelease = false, string prerelease = "preview", OutputFormat outputFormat = global::OutputFormat.Console) + { + var handler = new VersionHandler(tag, prefix, versionIncrement, isPrelease, prerelease); + var versioning = handler.Versioning(); + + Console.WriteLine(OutputFormat("version", versioning, outputFormat)); + } + + private string OutputFormat(string key, string value, OutputFormat format) => format switch + { + global::OutputFormat.Console => value, + global::OutputFormat.GitHubActions => $"{key}={value}", + _ => throw new NotImplementedException(nameof(format)), + }; +} + +public class VersionHandler(string tag, string prefix, VersionIncrement versionIncrement, bool isPrelease, string prerelease) +{ + /// + /// Handling versioning + /// + /// + public string Versioning() + { + var version = GetNormalizedVersion(tag, prefix); + var increment = IncrementVersion(version, versionIncrement); + var format = FormatVersion(increment, prefix, isPrelease, prerelease); + return format; + } + + /// + /// Normalize tag. Tag may contains prefix, remove prefix and retrun version. + /// + /// + /// + /// + /// + private Version GetNormalizedVersion(string tag, string prefix) + { + if (string.IsNullOrEmpty(tag)) throw new ActionCommandException("tag missing"); + if (tag.StartsWith(prefix, StringComparison.Ordinal)) + { + var span = tag.AsSpan(); + var substring = span.Slice(prefix.Length, span.Length - prefix.Length); + return Version.Parse(substring); + } + else + { + return Version.Parse(tag); + } + } + + /// + /// Increment version for specific place + /// + /// + /// + /// + /// + private Version IncrementVersion(Version version, VersionIncrement versionIncrement) => versionIncrement switch + { + VersionIncrement.Major => new Version(version.Major + 1, version.Minor, version.Build), + VersionIncrement.Minor => new Version(version.Major, version.Minor + 1, version.Build), + VersionIncrement.Patch => new Version(version.Major, version.Minor, version.Build + 1), + _ => throw new NotImplementedException(nameof(versionIncrement)), + }; + + /// + /// Format version + /// + /// + /// + /// + /// + /// + private string FormatVersion(Version version, string prefix, bool isPrelease, string prerelease) + { + var preReleaseSuffix = isPrelease ? $"-{prerelease}" : ""; + return $"{prefix}{version}{preReleaseSuffix}"; + } +} + +public enum VersionIncrement +{ + Major, + Minor, + Patch, + //Prerelease, // TODO: how to calculate count since last tag? +} + +public enum OutputFormat +{ + Console, + GitHubActions, +} +public class ActionCommandException : Exception +{ + public ActionCommandException(string message) : base(message) { } +} diff --git a/src/Actions/Properties/launchSettings.json b/src/Actions/Properties/launchSettings.json new file mode 100644 index 0000000..ad08cdd --- /dev/null +++ b/src/Actions/Properties/launchSettings.json @@ -0,0 +1,28 @@ +{ + "profiles": { + "versioning (help)": { + "commandName": "Project", + "commandLineArgs": "versioning --help" + }, + "versioning (major)": { + "commandName": "Project", + "commandLineArgs": "versioning --tag 0.1.0 --version-increment major" + }, + "versioning (minor)": { + "commandName": "Project", + "commandLineArgs": "versioning --tag 0.1.0 --version-increment minor" + }, + "versioning (patch)": { + "commandName": "Project", + "commandLineArgs": "versioning --tag 0.1.0" + }, + "versioning (patch - prefix)": { + "commandName": "Project", + "commandLineArgs": "versioning --tag v0.1.0 --prefix v" + }, + "versioning (patch - github actions)": { + "commandName": "Project", + "commandLineArgs": "versioning --tag 0.1.0 --output-format GitHubActions" + } + } +} \ No newline at end of file From 709e4cad7ff88a510804f846af05bf8492e05cc7 Mon Sep 17 00:00:00 2001 From: Ikiru Yoshizaki <3856350+guitarrapc@users.noreply.github.com> Date: Wed, 11 Dec 2024 14:38:23 +0900 Subject: [PATCH 02/21] refactor: move handler --- src/Actions/CommandEnums.cs | 15 +++++ src/Actions/Handlers/VersionHandler.cs | 67 +++++++++++++++++++ src/Actions/Program.cs | 93 +++----------------------- 3 files changed, 90 insertions(+), 85 deletions(-) create mode 100644 src/Actions/CommandEnums.cs create mode 100644 src/Actions/Handlers/VersionHandler.cs diff --git a/src/Actions/CommandEnums.cs b/src/Actions/CommandEnums.cs new file mode 100644 index 0000000..834c737 --- /dev/null +++ b/src/Actions/CommandEnums.cs @@ -0,0 +1,15 @@ +namespace Actions; + +public enum VersionIncrement +{ + Major, + Minor, + Patch, + //Prerelease, // TODO: how to calculate count since last tag? +} + +public enum OutputFormatType +{ + Console, + GitHubActions, +} \ No newline at end of file diff --git a/src/Actions/Handlers/VersionHandler.cs b/src/Actions/Handlers/VersionHandler.cs new file mode 100644 index 0000000..d9af3cc --- /dev/null +++ b/src/Actions/Handlers/VersionHandler.cs @@ -0,0 +1,67 @@ +namespace Actions.Handlers; + +public class VersionHandler(string tag, string prefix, VersionIncrement versionIncrement, bool isPrelease, string prerelease) +{ + /// + /// Handling versioning + /// + /// + public string Versioning() + { + var version = GetNormalizedVersion(tag, prefix); + var increment = IncrementVersion(version, versionIncrement); + var format = FormatVersion(increment, prefix, isPrelease, prerelease); + return format; + } + + /// + /// Normalize tag. Tag may contains prefix, remove prefix and retrun version. + /// + /// + /// + /// + /// + private static Version GetNormalizedVersion(string tag, string prefix) + { + if (string.IsNullOrEmpty(tag)) throw new ActionCommandException("tag missing"); + if (tag.StartsWith(prefix, StringComparison.Ordinal)) + { + var span = tag.AsSpan(); + var substring = span[prefix.Length..]; + return Version.Parse(substring); + } + else + { + return Version.Parse(tag); + } + } + + /// + /// Increment version for specific place + /// + /// + /// + /// + /// + private static Version IncrementVersion(Version version, VersionIncrement versionIncrement) => versionIncrement switch + { + VersionIncrement.Major => new Version(version.Major + 1, version.Minor, version.Build), + VersionIncrement.Minor => new Version(version.Major, version.Minor + 1, version.Build), + VersionIncrement.Patch => new Version(version.Major, version.Minor, version.Build + 1), + _ => throw new NotImplementedException(nameof(versionIncrement)), + }; + + /// + /// Format version + /// + /// + /// + /// + /// + /// + private static string FormatVersion(Version version, string prefix, bool isPrelease, string prerelease) + { + var preReleaseSuffix = isPrelease ? $"-{prerelease}" : ""; + return $"{prefix}{version}{preReleaseSuffix}"; + } +} diff --git a/src/Actions/Program.cs b/src/Actions/Program.cs index 3d2014f..eba15b9 100644 --- a/src/Actions/Program.cs +++ b/src/Actions/Program.cs @@ -1,3 +1,5 @@ +using Actions; +using Actions.Handlers; using ConsoleAppFramework; var app = ConsoleApp.Create(); @@ -13,7 +15,8 @@ public class ActionsCommand /// /// /// - public void Versioning(string tag, string prefix = "", VersionIncrement versionIncrement = VersionIncrement.Patch, bool isPrelease = false, string prerelease = "preview", OutputFormat outputFormat = global::OutputFormat.Console) + [Command("versioning")] + public void Versioning(string tag, string prefix = "", VersionIncrement versionIncrement = VersionIncrement.Patch, bool isPrelease = false, string prerelease = "preview", OutputFormatType outputFormat = OutputFormatType.Console) { var handler = new VersionHandler(tag, prefix, versionIncrement, isPrelease, prerelease); var versioning = handler.Versioning(); @@ -21,94 +24,14 @@ public void Versioning(string tag, string prefix = "", VersionIncrement versionI Console.WriteLine(OutputFormat("version", versioning, outputFormat)); } - private string OutputFormat(string key, string value, OutputFormat format) => format switch + private static string OutputFormat(string key, string value, OutputFormatType format) => format switch { - global::OutputFormat.Console => value, - global::OutputFormat.GitHubActions => $"{key}={value}", + OutputFormatType.Console => value, + OutputFormatType.GitHubActions => $"{key}={value}", _ => throw new NotImplementedException(nameof(format)), }; } -public class VersionHandler(string tag, string prefix, VersionIncrement versionIncrement, bool isPrelease, string prerelease) +public class ActionCommandException(string message) : Exception(message) { - /// - /// Handling versioning - /// - /// - public string Versioning() - { - var version = GetNormalizedVersion(tag, prefix); - var increment = IncrementVersion(version, versionIncrement); - var format = FormatVersion(increment, prefix, isPrelease, prerelease); - return format; - } - - /// - /// Normalize tag. Tag may contains prefix, remove prefix and retrun version. - /// - /// - /// - /// - /// - private Version GetNormalizedVersion(string tag, string prefix) - { - if (string.IsNullOrEmpty(tag)) throw new ActionCommandException("tag missing"); - if (tag.StartsWith(prefix, StringComparison.Ordinal)) - { - var span = tag.AsSpan(); - var substring = span.Slice(prefix.Length, span.Length - prefix.Length); - return Version.Parse(substring); - } - else - { - return Version.Parse(tag); - } - } - - /// - /// Increment version for specific place - /// - /// - /// - /// - /// - private Version IncrementVersion(Version version, VersionIncrement versionIncrement) => versionIncrement switch - { - VersionIncrement.Major => new Version(version.Major + 1, version.Minor, version.Build), - VersionIncrement.Minor => new Version(version.Major, version.Minor + 1, version.Build), - VersionIncrement.Patch => new Version(version.Major, version.Minor, version.Build + 1), - _ => throw new NotImplementedException(nameof(versionIncrement)), - }; - - /// - /// Format version - /// - /// - /// - /// - /// - /// - private string FormatVersion(Version version, string prefix, bool isPrelease, string prerelease) - { - var preReleaseSuffix = isPrelease ? $"-{prerelease}" : ""; - return $"{prefix}{version}{preReleaseSuffix}"; - } -} - -public enum VersionIncrement -{ - Major, - Minor, - Patch, - //Prerelease, // TODO: how to calculate count since last tag? -} - -public enum OutputFormat -{ - Console, - GitHubActions, -} -public class ActionCommandException : Exception -{ - public ActionCommandException(string message) : base(message) { } } From e04ce40cbe8a8b71742ecb3bc2435d2c5e2169cd Mon Sep 17 00:00:00 2001 From: Ikiru Yoshizaki <3856350+guitarrapc@users.noreply.github.com> Date: Wed, 11 Dec 2024 17:16:16 +0900 Subject: [PATCH 03/21] feat: add UpdateVersion command --- Actions.sln | 6 + src/Actions.Tests/Actions.Tests.csproj | 28 +++ src/Actions.Tests/UpdateVersionCommand.cs | 133 +++++++++++++++ src/Actions.Tests/UtilsSedTest.cs | 160 ++++++++++++++++++ src/Actions.Tests/VersioningCommandTest.cs | 47 +++++ src/Actions/Commands/UpdateVersionCommand.cs | 23 +++ .../VersioningCommand.cs} | 14 +- src/Actions/Program.cs | 42 ++++- src/Actions/Properties/launchSettings.json | 10 ++ src/Actions/Utils/Sed.cs | 41 +++++ 10 files changed, 489 insertions(+), 15 deletions(-) create mode 100644 src/Actions.Tests/Actions.Tests.csproj create mode 100644 src/Actions.Tests/UpdateVersionCommand.cs create mode 100644 src/Actions.Tests/UtilsSedTest.cs create mode 100644 src/Actions.Tests/VersioningCommandTest.cs create mode 100644 src/Actions/Commands/UpdateVersionCommand.cs rename src/Actions/{Handlers/VersionHandler.cs => Commands/VersioningCommand.cs} (81%) create mode 100644 src/Actions/Utils/Sed.cs diff --git a/Actions.sln b/Actions.sln index 89ea2b1..c0b1b9f 100644 --- a/Actions.sln +++ b/Actions.sln @@ -5,6 +5,8 @@ VisualStudioVersion = 17.12.35527.113 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Actions", "src\Actions\Actions.csproj", "{0371D0AA-BB43-4136-B9AA-A311A3E4615B}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Actions.Tests", "src\Actions.Tests\Actions.Tests.csproj", "{8DAE3F25-F3B7-4F98-A0FA-5585EDD0C22E}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -15,6 +17,10 @@ Global {0371D0AA-BB43-4136-B9AA-A311A3E4615B}.Debug|Any CPU.Build.0 = Debug|Any CPU {0371D0AA-BB43-4136-B9AA-A311A3E4615B}.Release|Any CPU.ActiveCfg = Release|Any CPU {0371D0AA-BB43-4136-B9AA-A311A3E4615B}.Release|Any CPU.Build.0 = Release|Any CPU + {8DAE3F25-F3B7-4F98-A0FA-5585EDD0C22E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8DAE3F25-F3B7-4F98-A0FA-5585EDD0C22E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8DAE3F25-F3B7-4F98-A0FA-5585EDD0C22E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8DAE3F25-F3B7-4F98-A0FA-5585EDD0C22E}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/Actions.Tests/Actions.Tests.csproj b/src/Actions.Tests/Actions.Tests.csproj new file mode 100644 index 0000000..36619f0 --- /dev/null +++ b/src/Actions.Tests/Actions.Tests.csproj @@ -0,0 +1,28 @@ + + + + net8.0 + enable + enable + + false + true + + + + + + + + + + + + + + + + + + + diff --git a/src/Actions.Tests/UpdateVersionCommand.cs b/src/Actions.Tests/UpdateVersionCommand.cs new file mode 100644 index 0000000..00cbe39 --- /dev/null +++ b/src/Actions.Tests/UpdateVersionCommand.cs @@ -0,0 +1,133 @@ +using Actions.Commands; +using FluentAssertions; + +namespace Actions.Tests +{ + public class UpdateVersionCommandTest + { + [Fact] + public void UpdateVersionUpmTest() + { + var version = "1.0.0"; + var path = $"{nameof(UpdateVersionCommandTest)}/package.json"; + var contents = """ + { + "name": "com.unity.plugin.example", + "version": "1.2.310", + "displayName": "Package Example Plugin", + "description": "This is an example package", + "unity": "2019.1", + "unityRelease": "0b5", + "dependencies": { + "com.unity.example": "1.0.0" + }, + "keywords": [ + "keyword1", + "keyword2", + "keyword3" + ], + "author": { + "name": "Unity", + "email": "unity@example.com", + "url": "https://www.unity3d.com" + } + } + """; + + var dir = Path.GetDirectoryName(path)!; + if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); + File.WriteAllText(path, contents); + + var command = new UpdateVersionCommand(version, path); + var (before, after) = command.UpdateVersion(false); + + after.Should().Be(""" + { + "name": "com.unity.plugin.example", + "version": "1.0.0", + "displayName": "Package Example Plugin", + "description": "This is an example package", + "unity": "2019.1", + "unityRelease": "0b5", + "dependencies": { + "com.unity.example": "1.0.0" + }, + "keywords": [ + "keyword1", + "keyword2", + "keyword3" + ], + "author": { + "name": "Unity", + "email": "unity@example.com", + "url": "https://www.unity3d.com" + } + } + """); + } + + [Fact] + public void UpdateVersionGodotTest() + { + var version = "1.0.0"; + var path = $"{nameof(UpdateVersionGodotTest)}/plugin.cfg"; + var contents = """ + [plugin] + + name="Sandbox.Godot" + description="Sample." + author="Cysharp" + version="1.2.310" + language="C-sharp" + script="GodotPlugin.cs" + """; + + var dir = Path.GetDirectoryName(path)!; + if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); + File.WriteAllText(path, contents); + + var command = new UpdateVersionCommand(version, path); + var (before, after) = command.UpdateVersion(false); + + after.Should().Be(""" + [plugin] + + name="Sandbox.Godot" + description="Sample." + author="Cysharp" + version="1.0.0" + language="C-sharp" + script="GodotPlugin.cs" + """); + } + + [Fact] + public void UpdateVersionDirectoryBuildPropsTest() + { + var version = "1.0.0"; + var path = $"{nameof(UpdateVersionDirectoryBuildPropsTest)}/Directory.Build.props"; + var contents = """ + + + 1.2.310 + + + """; + + var dir = Path.GetDirectoryName(path)!; + if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); + File.WriteAllText(path, contents); + + var command = new UpdateVersionCommand(version, path); + var (before, after) = command.UpdateVersion(false); + + after.Should().Be(""" + + + 1.0.0 + + + """); + } + } +} \ No newline at end of file diff --git a/src/Actions.Tests/UtilsSedTest.cs b/src/Actions.Tests/UtilsSedTest.cs new file mode 100644 index 0000000..da04e40 --- /dev/null +++ b/src/Actions.Tests/UtilsSedTest.cs @@ -0,0 +1,160 @@ +using FluentAssertions; + +namespace Actions.Tests +{ + public class UtilsSedTest + { + private readonly string _dummyMultilineText; + + public UtilsSedTest() + { + _dummyMultilineText = """ + 1 foobar + 2 abcde + 3 piyopiyo + 4 okonomiyaki + 5 takoyaki + """.NormalizeEol(); + } + + [Fact] + public void CharacterReplaceTest() + { + var input = @"Hello world!"; + var (_, after) = Utils.Sed.Replace(input, "world", "Japan"); + + after.Should().Be("Hello Japan!"); + } + + [Fact] + public void CharacterChainReplaceTest() + { + var input = @"/a/b/c"; + var (_, after) = Utils.Sed.Replace(input, "a", "A"); + var (_, after2) = Utils.Sed.Replace(after, "b", "B"); + var (_, after3) = Utils.Sed.Replace(after2, "c", "C"); + + after.Should().Be("/A/b/c"); + after2.Should().Be("/A/B/c"); + after3.Should().Be("/A/B/C"); + } + + [Fact] + public void CharacterInsertTest() + { + var input = @"ABC DEF"; + var (_, after) = Utils.Sed.Replace(input, "ABC", "ABCD"); + + after.Should().Be("ABCD DEF"); + } + + [Fact] + public void CharacterDeleteTest() + { + var input = @"ABC DEF"; + var (_, after) = Utils.Sed.Replace(input, "ABC", ""); + + after.Should().Be(" DEF"); + } + + [Fact] + public void SentenceInsertTest() + { + var input = _dummyMultilineText; + + // insert sentence before the line contains `abcde` + var (_, after) = Utils.Sed.Replace(input, $"^(.*?abcde.*?$)", "foo\n$1"); + + after.Should().Be(""" + 1 foobar + foo + 2 abcde + 3 piyopiyo + 4 okonomiyaki + 5 takoyaki + """.NormalizeEol()); + } + + [Fact] + public void SentenceDeleteTest() + { + var input = _dummyMultilineText; + // delete the line contains `abcde`, but keep brank line as is + var (_, after) = Utils.Sed.Replace(input, $"^(.*?abcde.*?$)", ""); + + after.Should().Be(""" + 1 foobar + + 3 piyopiyo + 4 okonomiyaki + 5 takoyaki + """.NormalizeEol()); + } + + [Fact] + public void SentenceDeleteCompactionTest() + { + var input = _dummyMultilineText; + + // delete the line contains `abcde`, then compaction deleted line. + var (_, after) = Utils.Sed.Replace(input, $"^(.*?abcde.*?$).*(\r?\n)?", ""); + + after.Should().Be(""" + 1 foobar + 3 piyopiyo + 4 okonomiyaki + 5 takoyaki + """.NormalizeEol()); + } + + [Fact] + public void NoWriteBackTest() + { + var path = $"{nameof(NoWriteBackTest)}.txt"; + if (File.Exists(path)) File.Delete(path); + + var input = _dummyMultilineText; + File.WriteAllText(path, input); + + // delete the line contains `abcde`, then compaction deleted line. + var (before, after) = Utils.Sed.Replace(path, $"^(.*?abcde.*?$).*(\r?\n)?", "", false); + + after.Should().Be(""" + 1 foobar + 3 piyopiyo + 4 okonomiyaki + 5 takoyaki + """.NormalizeEol()); + File.ReadAllText(path).Should().Be(before); + } + + [Fact] + public void WriteBackTest() + { + var path = $"{nameof(WriteBackTest)}.txt"; + if (File.Exists(path)) File.Delete(path); + + var input = _dummyMultilineText; + File.WriteAllText(path, input); + + // delete the line contains `abcde`, then compaction deleted line. + var (_, after) = Utils.Sed.Replace(path, $"^(.*?abcde.*?$).*(\r?\n)?", "", true); + + after.Should().Be(""" + 1 foobar + 3 piyopiyo + 4 okonomiyaki + 5 takoyaki + """.NormalizeEol()); + File.ReadAllText(path).Should().Be(after); + } + } + + public static class StringExtentions + { + public static string NormalizeEol(this string input) + { + return input.Replace("\r\n", "\n"); + } + } +} diff --git a/src/Actions.Tests/VersioningCommandTest.cs b/src/Actions.Tests/VersioningCommandTest.cs new file mode 100644 index 0000000..ec4eabd --- /dev/null +++ b/src/Actions.Tests/VersioningCommandTest.cs @@ -0,0 +1,47 @@ +using Actions.Commands; +using FluentAssertions; + +namespace Actions.Tests +{ + public class VersioningCommandTest + { + [Theory] + [InlineData("0.1.0", VersionIncrement.Major, "1.1.0")] + [InlineData("0.1.0", VersionIncrement.Minor, "0.2.0")] + [InlineData("0.1.0", VersionIncrement.Patch, "0.1.1")] + public void VersionIncrementTest(string tag, VersionIncrement versionIncrement, string actual) + { + var command = new VersioningCommand(tag, prefix: "", versionIncrement: versionIncrement, isPrelease: false, prerelease: ""); + var versioning = command.Versioning(); + + versioning.Should().Be(actual); + } + + [Theory] + [InlineData("v0.1.0", "v", true, "0.1.1")] + [InlineData("Ver0.1.0", "Ver", true, "0.1.1")] + [InlineData("Ver.0.1.0", "Ver.", true, "0.1.1")] + [InlineData("v0.1.0", "v", false, "v0.1.1")] + [InlineData("Ver0.1.0", "Ver", false, "Ver0.1.1")] + [InlineData("Ver.0.1.0", "Ver.", false, "Ver.0.1.1")] + public void VersionPrefixTest(string tag, string prefix, bool withoutPrefix, string actual) + { + var command = new VersioningCommand(tag, prefix: prefix, versionIncrement: VersionIncrement.Patch, isPrelease: false, prerelease: ""); + var versioning = command.Versioning(withoutPrefix); + + versioning.Should().Be(actual); + } + + [Theory] + [InlineData("0.1.0", "", "0.1.1")] + [InlineData("0.1.0", "alpha", "0.1.1-alpha")] + [InlineData("0.1.0", "preview", "0.1.1-preview")] + public void VersionPrereleaseTest(string tag, string prerelease, string actual) + { + var command = new VersioningCommand(tag, prefix: "", versionIncrement: VersionIncrement.Patch, isPrelease: true, prerelease: prerelease); + var versioning = command.Versioning(); + + versioning.Should().Be(actual); + } + } +} \ No newline at end of file diff --git a/src/Actions/Commands/UpdateVersionCommand.cs b/src/Actions/Commands/UpdateVersionCommand.cs new file mode 100644 index 0000000..d8f3afd --- /dev/null +++ b/src/Actions/Commands/UpdateVersionCommand.cs @@ -0,0 +1,23 @@ +using Actions.Utils; + +namespace Actions.Commands +{ + public class UpdateVersionCommand(string version, string path) + { + public (string before, string after) UpdateVersion(bool dryRun) + { + if (!File.Exists(path)) throw new FileNotFoundException(path); + var fileName = Path.GetFileName(path); + return fileName switch + { + // UPM + "package.json" => Sed.Replace(path, @"""version"":\s*""(.*?)""", $@"""version"": ""{version}""", dryRun), + // Godot + "plugin.cfg" => Sed.Replace(path, @"(version=)""(.*?)""", $@"$1""{version}""", dryRun), + // .NET + "Directory.Build.props" => Sed.Replace(path, @".*", $@"{version}", dryRun), + _ => throw new NotImplementedException(fileName), + }; + } + } +} diff --git a/src/Actions/Handlers/VersionHandler.cs b/src/Actions/Commands/VersioningCommand.cs similarity index 81% rename from src/Actions/Handlers/VersionHandler.cs rename to src/Actions/Commands/VersioningCommand.cs index d9af3cc..ea5c907 100644 --- a/src/Actions/Handlers/VersionHandler.cs +++ b/src/Actions/Commands/VersioningCommand.cs @@ -1,16 +1,16 @@ -namespace Actions.Handlers; +namespace Actions.Commands; -public class VersionHandler(string tag, string prefix, VersionIncrement versionIncrement, bool isPrelease, string prerelease) +public class VersioningCommand(string tag, string prefix, VersionIncrement versionIncrement, bool isPrelease, string prerelease) { /// /// Handling versioning /// /// - public string Versioning() + public string Versioning(bool withoutPrefix = false) { var version = GetNormalizedVersion(tag, prefix); var increment = IncrementVersion(version, versionIncrement); - var format = FormatVersion(increment, prefix, isPrelease, prerelease); + var format = FormatVersion(increment, prefix, isPrelease, prerelease, withoutPrefix); return format; } @@ -59,9 +59,9 @@ private static Version GetNormalizedVersion(string tag, string prefix) /// /// /// - private static string FormatVersion(Version version, string prefix, bool isPrelease, string prerelease) + private static string FormatVersion(Version version, string prefix, bool isPrelease, string prerelease, bool withoutPrefix) { - var preReleaseSuffix = isPrelease ? $"-{prerelease}" : ""; - return $"{prefix}{version}{preReleaseSuffix}"; + var preReleaseSuffix = isPrelease && prerelease != "" ? $"-{prerelease}" : ""; + return withoutPrefix ? $"{version}{preReleaseSuffix}" : $"{prefix}{version}{preReleaseSuffix}"; } } diff --git a/src/Actions/Program.cs b/src/Actions/Program.cs index eba15b9..6b8a7ec 100644 --- a/src/Actions/Program.cs +++ b/src/Actions/Program.cs @@ -1,12 +1,20 @@ using Actions; -using Actions.Handlers; +using Actions.Commands; using ConsoleAppFramework; -var app = ConsoleApp.Create(); -app.Add(); -app.Run(args); +namespace Actions; -public class ActionsCommand +public class Program +{ + private static void Main(string[] args) + { + var app = ConsoleApp.Create(); + app.Add(); + app.Run(args); + } +} + +public class ActionsBatch { /// Get version string from tag /// @@ -16,14 +24,32 @@ public class ActionsCommand /// /// [Command("versioning")] - public void Versioning(string tag, string prefix = "", VersionIncrement versionIncrement = VersionIncrement.Patch, bool isPrelease = false, string prerelease = "preview", OutputFormatType outputFormat = OutputFormatType.Console) + public void Versioning(string tag, string prefix = "", VersionIncrement versionIncrement = VersionIncrement.Patch, bool isPrelease = false, string prerelease = "preview", bool withoutPrefix = false, OutputFormatType outputFormat = OutputFormatType.Console) { - var handler = new VersionHandler(tag, prefix, versionIncrement, isPrelease, prerelease); - var versioning = handler.Versioning(); + var command = new VersioningCommand(tag, prefix, versionIncrement, isPrelease, prerelease); + var versioning = command.Versioning(withoutPrefix); Console.WriteLine(OutputFormat("version", versioning, outputFormat)); } + /// + /// Update Version for specified path + /// + /// + /// + /// + [Command("update-version")] + public void UpdateVersion(string version, string path, bool dryRun) + { + var command = new UpdateVersionCommand(version, path); + var (_, after) = command.UpdateVersion(dryRun); + + if (dryRun) + { + Console.WriteLine(after); + } + } + private static string OutputFormat(string key, string value, OutputFormatType format) => format switch { OutputFormatType.Console => value, diff --git a/src/Actions/Properties/launchSettings.json b/src/Actions/Properties/launchSettings.json index ad08cdd..de871ea 100644 --- a/src/Actions/Properties/launchSettings.json +++ b/src/Actions/Properties/launchSettings.json @@ -1,5 +1,10 @@ { "profiles": { + "help": { + "commandName": "Project", + "commandLineArgs": "--help" + }, + // versioning "versioning (help)": { "commandName": "Project", "commandLineArgs": "versioning --help" @@ -23,6 +28,11 @@ "versioning (patch - github actions)": { "commandName": "Project", "commandLineArgs": "versioning --tag 0.1.0 --output-format GitHubActions" + }, + // update-version + "update-version (help)": { + "commandName": "Project", + "commandLineArgs": "update-version --help" } } } \ No newline at end of file diff --git a/src/Actions/Utils/Sed.cs b/src/Actions/Utils/Sed.cs new file mode 100644 index 0000000..1fd72c9 --- /dev/null +++ b/src/Actions/Utils/Sed.cs @@ -0,0 +1,41 @@ +using System.Text.RegularExpressions; + +namespace Actions.Utils +{ + public static class Sed + { + /// + /// Replace file contents with pattern and replacement. + /// + /// + /// + /// + /// + /// + public static (string before, string after) Replace(string path, string pattern, string replacement, bool writeBack) + { + var input = File.ReadAllText(path); + var result = Replace(input, pattern, replacement); + + if (writeBack) + { + File.WriteAllText(path, result.after); + } + + return result; + } + + /// + /// Replace contents with pattern and replacement. + /// + /// + /// + /// + /// + public static (string before, string after) Replace(string input, string pattern, string replacement) + { + var updatedContent = Regex.Replace(input, pattern, replacement, RegexOptions.Multiline); + return (input, updatedContent); + } + } +} From 1451152a65311384593e01335dc1ec6674401e07 Mon Sep 17 00:00:00 2001 From: Ikiru Yoshizaki <3856350+guitarrapc@users.noreply.github.com> Date: Wed, 11 Dec 2024 18:08:26 +0900 Subject: [PATCH 04/21] chore: Validate version --- src/Actions/Commands/UpdateVersionCommand.cs | 95 +++++++++++++++++++- 1 file changed, 92 insertions(+), 3 deletions(-) diff --git a/src/Actions/Commands/UpdateVersionCommand.cs b/src/Actions/Commands/UpdateVersionCommand.cs index d8f3afd..f3d5def 100644 --- a/src/Actions/Commands/UpdateVersionCommand.cs +++ b/src/Actions/Commands/UpdateVersionCommand.cs @@ -1,4 +1,6 @@ using Actions.Utils; +using System.Text.Json; +using System.Text.Json.Serialization; namespace Actions.Commands { @@ -11,13 +13,100 @@ public class UpdateVersionCommand(string version, string path) return fileName switch { // UPM - "package.json" => Sed.Replace(path, @"""version"":\s*""(.*?)""", $@"""version"": ""{version}""", dryRun), + "package.json" => HandleUpm(dryRun), // Godot - "plugin.cfg" => Sed.Replace(path, @"(version=)""(.*?)""", $@"$1""{version}""", dryRun), + "plugin.cfg" => HandleGodot(dryRun), // .NET - "Directory.Build.props" => Sed.Replace(path, @".*", $@"{version}", dryRun), + "Directory.Build.props" => HandleDirectoryBuildProps(dryRun), + // Other _ => throw new NotImplementedException(fileName), }; } + + private (string before, string after) HandleUpm(bool dryRun) + { + // replace + var result = Sed.Replace(path, @"""version"":\s*""(.*?)""", $@"""version"": ""{version}""", dryRun); + + // validate + Validate(result.after, version); + + return result; + + static void Validate(string contents, string version) + { + var packageJson = JsonSerializer.Deserialize(contents); + if (packageJson is null) + throw new ActionCommandException($"UPM package.json updated, but failed to load as valid JSON. contents: {contents}"); + if (packageJson.Version != version) + throw new ActionCommandException($"UPM package.json updated, but version miss-match. actual {packageJson?.Version}, expected {version}"); + } + } + + private (string before, string after) HandleGodot(bool dryRun) + { + // replace + var result = Sed.Replace(path, @"(version=)""(.*?)""", $@"$1""{version}""", dryRun); + + // validate + Validate(result.after, version); + + return result; + + static void Validate(string contents, string version) + { + var lines = contents.Split("\n"); + Span destination = stackalloc Range[2]; + foreach (var line in lines) + { + // find the line befin with "version=", then split with = to get version + if (!line.StartsWith("version=")) + continue; + + var span = line.AsSpan(); + var range = span.Split(destination, '=', StringSplitOptions.TrimEntries); + if (range != 2) + continue; + + // validate version is expceted + var versionValue = span[destination[1]].ToString(); + if (versionValue != $"\"{version}\"") + { + throw new ActionCommandException($"Godot plugin.cfg updated, but version miss-match. actual {versionValue}, expected {version}"); + } + return; + } + throw new ActionCommandException($"Godot plugin.cfg updated, but version key not found."); + } + } + + private (string before, string after) HandleDirectoryBuildProps(bool dryRun) + { + // replace + var result = Sed.Replace(path, @".*", $@"{version}", dryRun); + + // validate + Validate(result.after, version); + + return result; + + static void Validate(string contents, string version) + { + var xmlDoc = new System.Xml.XmlDocument(); + xmlDoc.LoadXml(contents); + var versionPrefixNode = xmlDoc.SelectSingleNode("//VersionPrefix"); + if (versionPrefixNode == null) + throw new ActionCommandException($"Directory.Build.props updated, but VersionPrefix key not found."); + if (versionPrefixNode.InnerText != version) + throw new ActionCommandException($"Directory.Build.props updated, but version miss-match. actual {versionPrefixNode.InnerText}, expected {version}"); + + } + } + + private record UpmPackageJson + { + [JsonPropertyName("version")] + public required string Version { get; set; } + } } } From 28b131b82251e0c38c92e3cbc2c12eb491c80841 Mon Sep 17 00:00:00 2001 From: Ikiru Yoshizaki <3856350+guitarrapc@users.noreply.github.com> Date: Wed, 11 Dec 2024 18:40:15 +0900 Subject: [PATCH 05/21] fix: writeBack --- src/Actions/Commands/CreateDummyCommand.cs | 57 ++++++++++++++++++++ src/Actions/Commands/UpdateVersionCommand.cs | 19 +++---- src/Actions/Program.cs | 14 +++++ src/Actions/Properties/launchSettings.json | 23 +++++++- 4 files changed, 103 insertions(+), 10 deletions(-) create mode 100644 src/Actions/Commands/CreateDummyCommand.cs diff --git a/src/Actions/Commands/CreateDummyCommand.cs b/src/Actions/Commands/CreateDummyCommand.cs new file mode 100644 index 0000000..dcdc08a --- /dev/null +++ b/src/Actions/Commands/CreateDummyCommand.cs @@ -0,0 +1,57 @@ +namespace Actions.Commands +{ + public class CreateDummyCommand + { + public void CreateDummyFiles(string basePath) + { + var upm = ("package.json", """ + { + "name": "com.unity.plugin.example", + "version": "1.2.310", + "displayName": "Package Example Plugin", + "description": "This is an example package", + "unity": "2019.1", + "unityRelease": "0b5", + "dependencies": { + "com.unity.example": "1.0.0" + }, + "keywords": [ + "keyword1", + "keyword2", + "keyword3" + ], + "author": { + "name": "Unity", + "email": "unity@example.com", + "url": "https://www.unity3d.com" + } + } + """); + var godot = ("plugin.cfg", """ + [plugin] + name="Sandbox.Godot" + description="Sample." + author="Cysharp" + version="1.2.310" + language="C-sharp" + script="GodotPlugin.cs" + """); + var directoryBuildProps = ("Directory.Build.props", """ + + + 1.2.310 + + + """); + + foreach (var (file, contents) in new[] { upm, godot, directoryBuildProps }) + { + if (!Directory.Exists(basePath)) + Directory.CreateDirectory(basePath); + + var path = Path.Combine(basePath, file); + File.WriteAllText(path, contents); + } + } + } +} diff --git a/src/Actions/Commands/UpdateVersionCommand.cs b/src/Actions/Commands/UpdateVersionCommand.cs index f3d5def..4d75ec3 100644 --- a/src/Actions/Commands/UpdateVersionCommand.cs +++ b/src/Actions/Commands/UpdateVersionCommand.cs @@ -8,25 +8,26 @@ public class UpdateVersionCommand(string version, string path) { public (string before, string after) UpdateVersion(bool dryRun) { + var writeBack = !dryRun; if (!File.Exists(path)) throw new FileNotFoundException(path); var fileName = Path.GetFileName(path); return fileName switch { // UPM - "package.json" => HandleUpm(dryRun), + "package.json" => HandleUpm(writeBack), // Godot - "plugin.cfg" => HandleGodot(dryRun), + "plugin.cfg" => HandleGodot(writeBack), // .NET - "Directory.Build.props" => HandleDirectoryBuildProps(dryRun), + "Directory.Build.props" => HandleDirectoryBuildProps(writeBack), // Other _ => throw new NotImplementedException(fileName), }; } - private (string before, string after) HandleUpm(bool dryRun) + private (string before, string after) HandleUpm(bool writeBack) { // replace - var result = Sed.Replace(path, @"""version"":\s*""(.*?)""", $@"""version"": ""{version}""", dryRun); + var result = Sed.Replace(path, @"""version"":\s*""(.*?)""", $@"""version"": ""{version}""", writeBack); // validate Validate(result.after, version); @@ -43,10 +44,10 @@ static void Validate(string contents, string version) } } - private (string before, string after) HandleGodot(bool dryRun) + private (string before, string after) HandleGodot(bool writeBack) { // replace - var result = Sed.Replace(path, @"(version=)""(.*?)""", $@"$1""{version}""", dryRun); + var result = Sed.Replace(path, @"(version=)""(.*?)""", $@"$1""{version}""", writeBack); // validate Validate(result.after, version); @@ -80,10 +81,10 @@ static void Validate(string contents, string version) } } - private (string before, string after) HandleDirectoryBuildProps(bool dryRun) + private (string before, string after) HandleDirectoryBuildProps(bool writeBack) { // replace - var result = Sed.Replace(path, @".*", $@"{version}", dryRun); + var result = Sed.Replace(path, @".*", $@"{version}", writeBack); // validate Validate(result.after, version); diff --git a/src/Actions/Program.cs b/src/Actions/Program.cs index 6b8a7ec..c1834be 100644 --- a/src/Actions/Program.cs +++ b/src/Actions/Program.cs @@ -41,6 +41,9 @@ public void Versioning(string tag, string prefix = "", VersionIncrement versionI [Command("update-version")] public void UpdateVersion(string version, string path, bool dryRun) { + if (string.IsNullOrWhiteSpace(path)) + Console.WriteLine("Input is empty path, skip execution."); + var command = new UpdateVersionCommand(version, path); var (_, after) = command.UpdateVersion(dryRun); @@ -50,6 +53,17 @@ public void UpdateVersion(string version, string path, bool dryRun) } } + /// + /// Create dummy files + /// + /// + [Command("create-dummy")] + public void CreateDummy(string basePath) + { + var command = new CreateDummyCommand(); + command.CreateDummyFiles(basePath); + } + private static string OutputFormat(string key, string value, OutputFormatType format) => format switch { OutputFormatType.Console => value, diff --git a/src/Actions/Properties/launchSettings.json b/src/Actions/Properties/launchSettings.json index de871ea..85ef9d6 100644 --- a/src/Actions/Properties/launchSettings.json +++ b/src/Actions/Properties/launchSettings.json @@ -29,10 +29,31 @@ "commandName": "Project", "commandLineArgs": "versioning --tag 0.1.0 --output-format GitHubActions" }, - // update-version + // update-version (run create-dummy before run these) "update-version (help)": { "commandName": "Project", "commandLineArgs": "update-version --help" + }, + "update-version (upm)": { + "commandName": "Project", + "commandLineArgs": "update-version --version 1.0.0 --path ./dummy/package.json" + }, + "update-version (godot)": { + "commandName": "Project", + "commandLineArgs": "update-version --version 1.0.0 --path ./dummy/plugin.cfg" + }, + "update-version (Directory.Build.props)": { + "commandName": "Project", + "commandLineArgs": "update-version --version 1.0.0 --path ./dummy/Directory.Build.props" + }, + // create-dummy + "create-dummy (help)": { + "commandName": "Project", + "commandLineArgs": "create-dummy --help" + }, + "create-dummy (init)": { + "commandName": "Project", + "commandLineArgs": "create-dummy --base-path dummy/" } } } \ No newline at end of file From 1ad979bf2c9ded2dde2a53326a16e12f171e7a23 Mon Sep 17 00:00:00 2001 From: Ikiru Yoshizaki <3856350+guitarrapc@users.noreply.github.com> Date: Wed, 11 Dec 2024 19:50:06 +0900 Subject: [PATCH 06/21] chore: format output --- src/Actions/Commands/CreateDummyCommand.cs | 3 +- src/Actions/Commands/UpdateVersionCommand.cs | 38 +++++++++---------- src/Actions/Program.cs | 27 +++++++++---- src/Actions/Utils/GitHubActionsGroupLogger.cs | 12 ++++++ 4 files changed, 52 insertions(+), 28 deletions(-) create mode 100644 src/Actions/Utils/GitHubActionsGroupLogger.cs diff --git a/src/Actions/Commands/CreateDummyCommand.cs b/src/Actions/Commands/CreateDummyCommand.cs index dcdc08a..68b5dc2 100644 --- a/src/Actions/Commands/CreateDummyCommand.cs +++ b/src/Actions/Commands/CreateDummyCommand.cs @@ -46,10 +46,11 @@ public void CreateDummyFiles(string basePath) foreach (var (file, contents) in new[] { upm, godot, directoryBuildProps }) { + var path = Path.Combine(basePath, file); if (!Directory.Exists(basePath)) Directory.CreateDirectory(basePath); - var path = Path.Combine(basePath, file); + Console.WriteLine($"- {path} ..."); File.WriteAllText(path, contents); } } diff --git a/src/Actions/Commands/UpdateVersionCommand.cs b/src/Actions/Commands/UpdateVersionCommand.cs index 4d75ec3..1b937c8 100644 --- a/src/Actions/Commands/UpdateVersionCommand.cs +++ b/src/Actions/Commands/UpdateVersionCommand.cs @@ -4,12 +4,14 @@ namespace Actions.Commands { + public record struct UpdateVersionCommandResult(string Before, string After); public class UpdateVersionCommand(string version, string path) { - public (string before, string after) UpdateVersion(bool dryRun) + public UpdateVersionCommandResult UpdateVersion(bool dryRun) { - var writeBack = !dryRun; if (!File.Exists(path)) throw new FileNotFoundException(path); + + var writeBack = !dryRun; var fileName = Path.GetFileName(path); return fileName switch { @@ -24,35 +26,33 @@ public class UpdateVersionCommand(string version, string path) }; } - private (string before, string after) HandleUpm(bool writeBack) + private UpdateVersionCommandResult HandleUpm(bool writeBack) { // replace - var result = Sed.Replace(path, @"""version"":\s*""(.*?)""", $@"""version"": ""{version}""", writeBack); + var (before, after) = Sed.Replace(path, @"""version"":\s*""(.*?)""", $@"""version"": ""{version}""", writeBack); // validate - Validate(result.after, version); + Validate(after, version); - return result; + return new UpdateVersionCommandResult(before, after); static void Validate(string contents, string version) { - var packageJson = JsonSerializer.Deserialize(contents); - if (packageJson is null) - throw new ActionCommandException($"UPM package.json updated, but failed to load as valid JSON. contents: {contents}"); + var packageJson = JsonSerializer.Deserialize(contents) ?? throw new ActionCommandException($"UPM package.json updated, but failed to load as valid JSON. contents: {contents}"); if (packageJson.Version != version) throw new ActionCommandException($"UPM package.json updated, but version miss-match. actual {packageJson?.Version}, expected {version}"); } } - private (string before, string after) HandleGodot(bool writeBack) + private UpdateVersionCommandResult HandleGodot(bool writeBack) { // replace - var result = Sed.Replace(path, @"(version=)""(.*?)""", $@"$1""{version}""", writeBack); + var (before, after) = Sed.Replace(path, @"(version=)""(.*?)""", $@"$1""{version}""", writeBack); // validate - Validate(result.after, version); + Validate(after, version); - return result; + return new UpdateVersionCommandResult(before, after); static void Validate(string contents, string version) { @@ -81,23 +81,21 @@ static void Validate(string contents, string version) } } - private (string before, string after) HandleDirectoryBuildProps(bool writeBack) + private UpdateVersionCommandResult HandleDirectoryBuildProps(bool writeBack) { // replace - var result = Sed.Replace(path, @".*", $@"{version}", writeBack); + var (before, after) = Sed.Replace(path, @".*", $@"{version}", writeBack); // validate - Validate(result.after, version); + Validate(after, version); - return result; + return new UpdateVersionCommandResult(before, after); static void Validate(string contents, string version) { var xmlDoc = new System.Xml.XmlDocument(); xmlDoc.LoadXml(contents); - var versionPrefixNode = xmlDoc.SelectSingleNode("//VersionPrefix"); - if (versionPrefixNode == null) - throw new ActionCommandException($"Directory.Build.props updated, but VersionPrefix key not found."); + var versionPrefixNode = xmlDoc.SelectSingleNode("//VersionPrefix") ?? throw new ActionCommandException($"Directory.Build.props updated, but VersionPrefix key not found."); if (versionPrefixNode.InnerText != version) throw new ActionCommandException($"Directory.Build.props updated, but version miss-match. actual {versionPrefixNode.InnerText}, expected {version}"); diff --git a/src/Actions/Program.cs b/src/Actions/Program.cs index c1834be..11114bc 100644 --- a/src/Actions/Program.cs +++ b/src/Actions/Program.cs @@ -1,5 +1,6 @@ using Actions; using Actions.Commands; +using Actions.Utils; using ConsoleAppFramework; namespace Actions; @@ -29,7 +30,8 @@ public void Versioning(string tag, string prefix = "", VersionIncrement versionI var command = new VersioningCommand(tag, prefix, versionIncrement, isPrelease, prerelease); var versioning = command.Versioning(withoutPrefix); - Console.WriteLine(OutputFormat("version", versioning, outputFormat)); + var output = OutputFormat("version", versioning, outputFormat); + Console.WriteLine(output); } /// @@ -41,16 +43,23 @@ public void Versioning(string tag, string prefix = "", VersionIncrement versionI [Command("update-version")] public void UpdateVersion(string version, string path, bool dryRun) { + Console.WriteLine($"Update begin, {path} ..."); if (string.IsNullOrWhiteSpace(path)) - Console.WriteLine("Input is empty path, skip execution."); + { + Console.WriteLine("Empty path detected, skip execution."); + return; + } + + using (var githubGroup = new GitHubActionsGroupLogger("Before")) + Console.WriteLine(File.ReadAllText(path)); var command = new UpdateVersionCommand(version, path); - var (_, after) = command.UpdateVersion(dryRun); + var result = command.UpdateVersion(dryRun); - if (dryRun) - { - Console.WriteLine(after); - } + using (var githubGroup = new GitHubActionsGroupLogger("After")) + Console.WriteLine(result.After); + + Console.WriteLine($"Completed ..."); } /// @@ -60,8 +69,12 @@ public void UpdateVersion(string version, string path, bool dryRun) [Command("create-dummy")] public void CreateDummy(string basePath) { + Console.WriteLine($"Creating dummy files, under {basePath} ..."); + var command = new CreateDummyCommand(); command.CreateDummyFiles(basePath); + + Console.WriteLine($"Completed ..."); } private static string OutputFormat(string key, string value, OutputFormatType format) => format switch diff --git a/src/Actions/Utils/GitHubActionsGroupLogger.cs b/src/Actions/Utils/GitHubActionsGroupLogger.cs new file mode 100644 index 0000000..fd9636b --- /dev/null +++ b/src/Actions/Utils/GitHubActionsGroupLogger.cs @@ -0,0 +1,12 @@ +namespace Actions.Utils +{ + public class GitHubActionsGroupLogger : IDisposable + { + public GitHubActionsGroupLogger(string title) + { + Console.WriteLine($"::group::{title}"); + } + + public void Dispose() => Console.WriteLine("::endgroup::"); + } +} From 99628773217bca2b7198fcb630beb7899de51751 Mon Sep 17 00:00:00 2001 From: Ikiru Yoshizaki <3856350+guitarrapc@users.noreply.github.com> Date: Wed, 11 Dec 2024 19:56:47 +0900 Subject: [PATCH 07/21] ci: change Update files to version to use C# Actions --- .github/workflows/update-packagejson.yaml | 44 ++--------------------- 1 file changed, 2 insertions(+), 42 deletions(-) diff --git a/.github/workflows/update-packagejson.yaml b/.github/workflows/update-packagejson.yaml index 63fb23c..fa5ab37 100644 --- a/.github/workflows/update-packagejson.yaml +++ b/.github/workflows/update-packagejson.yaml @@ -72,6 +72,7 @@ jobs: - uses: actions/checkout@v4 with: ref: ${{ inputs.ref }} + - uses: Cysharp/Actions/.github/actions/setup-dotnet@main # package.json # "version": 1.2.3 -> "version": 2.0.0 @@ -81,49 +82,8 @@ jobs: # TIPS: `grep -v "^$"` is used to remove empty line. - name: Update files to version ${{ needs.validate.outputs.normalized_tag }} run: | - expected="${{ needs.validate.outputs.normalized_tag }}" while read -r file_path; do - if [[ "$file_path" == "" ]]; then continue; fi - - echo "Start $file_path" - file_name=$(basename "$file_path") - - echo "::group::Before" - cat "$file_path" - echo "::endgroup::" - - echo "::group::Updating" - if [[ "${file_name}" == "package.json" ]]; then - # Unity `"version": "VersionString",` - sed -i -e "s/\(\"version\":\) \"\(.*\)\",/\1 \"${{ needs.validate.outputs.normalized_tag }}\",/" "${file_path}" - actual=$(grep "version" "$file_path" | cut -d ':' -f 2 | tr -d ',' | tr -d '"' | tr -d ' ') - elif [[ "${file_name}" == "plugin.cfg" ]]; then - # Godot `version="VersionString"` - sed -i -e "s/\(version=\)\"\(.*\)\"/\1\"${{ needs.validate.outputs.normalized_tag }}\"/" "${file_path}" - actual=$(grep "version=" "$file_path" | cut -d '=' -f 2 | tr -d '"') - elif [[ "${file_name}" == "Directory.Build.props" ]]; then - # .NET `VersionString` - sed -i -e 's|.*|${{ needs.validate.outputs.normalized_tag }}|g' "${file_path}" - # -P is for perl regex, only available in GNU grep - actual=$(grep -oP '\K.*(?=)' "$file_path") - else - echo "Unknown file name ${file_name} is specified." - exit 1 - fi - echo "::endgroup::" - - echo "::group::After" - cat "$file_path" - echo "::endgroup::" - - echo "::group::Validate Change" - if [[ "$actual" != "$expected" ]]; then - echo "Failed. Path: $file_path, Expected: $expected, Actual: $actual" - exit 1 - else - echo "Success. Path: $file_path, Expected: $expected, Actual: $actual" - fi - echo "::endgroup::" + dotnet run --project "./src/Actions/Actions.csproj" -- update-version --version "${{ needs.validate.outputs.normalized_tag }}" --path "$file_path" done <<< "${{ inputs.file-path }}" # dotnet run From e2c3a6151a6169058e3bbef0b916ae59a8ebf7b4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 11 Dec 2024 14:05:18 +0000 Subject: [PATCH 08/21] feat: Update package.json to 1.2.313 Commit by [GitHub Actions](https://github.com/Cysharp/Actions/actions/runs/12277984382) --- Sandbox/Directory.Build.props | 2 +- Sandbox/Sandbox.Godot/addons/Foo/plugin.cfg | 2 +- Sandbox/Sandbox.Unity/Assets/Plugins/Foo.Plugin/package.json | 2 +- Sandbox/Sandbox.Unity/Assets/Plugins/Foo/package.json | 2 +- Sandbox/VersionOutput/version.txt | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Sandbox/Directory.Build.props b/Sandbox/Directory.Build.props index 602a29a..0b4f945 100644 --- a/Sandbox/Directory.Build.props +++ b/Sandbox/Directory.Build.props @@ -1,5 +1,5 @@ - 1.2.310 + 1.2.313 diff --git a/Sandbox/Sandbox.Godot/addons/Foo/plugin.cfg b/Sandbox/Sandbox.Godot/addons/Foo/plugin.cfg index af2b6a6..ba2a48b 100644 --- a/Sandbox/Sandbox.Godot/addons/Foo/plugin.cfg +++ b/Sandbox/Sandbox.Godot/addons/Foo/plugin.cfg @@ -3,6 +3,6 @@ name="Sandbox.Godot" description="Sample." author="Cysharp" -version="1.2.310" +version="1.2.313" language="C-sharp" script="GodotPlugin.cs" diff --git a/Sandbox/Sandbox.Unity/Assets/Plugins/Foo.Plugin/package.json b/Sandbox/Sandbox.Unity/Assets/Plugins/Foo.Plugin/package.json index f3d24cb..e0970d8 100644 --- a/Sandbox/Sandbox.Unity/Assets/Plugins/Foo.Plugin/package.json +++ b/Sandbox/Sandbox.Unity/Assets/Plugins/Foo.Plugin/package.json @@ -1,6 +1,6 @@ { "name": "com.unity.plugin.example", - "version": "1.2.310", + "version": "1.2.313", "displayName": "Package Example Plugin", "description": "This is an example package", "unity": "2019.1", diff --git a/Sandbox/Sandbox.Unity/Assets/Plugins/Foo/package.json b/Sandbox/Sandbox.Unity/Assets/Plugins/Foo/package.json index b91e42e..d456725 100644 --- a/Sandbox/Sandbox.Unity/Assets/Plugins/Foo/package.json +++ b/Sandbox/Sandbox.Unity/Assets/Plugins/Foo/package.json @@ -1,6 +1,6 @@ { "name": "com.unity.example", - "version": "1.2.310", + "version": "1.2.313", "displayName": "Package Example", "description": "This is an example package", "unity": "2019.1", diff --git a/Sandbox/VersionOutput/version.txt b/Sandbox/VersionOutput/version.txt index 335a70c..4493a5c 100644 --- a/Sandbox/VersionOutput/version.txt +++ b/Sandbox/VersionOutput/version.txt @@ -1 +1 @@ -1.2.310 \ No newline at end of file +1.2.313 \ No newline at end of file From cb4cbdbd5e93ef656c5e9af08a7fd4ec93a815fd Mon Sep 17 00:00:00 2001 From: Ikiru Yoshizaki <3856350+guitarrapc@users.noreply.github.com> Date: Tue, 17 Dec 2024 12:06:57 +0900 Subject: [PATCH 09/21] chore: update package, add editorconfig --- .editorconfig | 64 ++++- src/Actions.Tests/Actions.Tests.csproj | 14 +- src/Actions.Tests/UpdateVersionCommand.cs | 227 ++++++++-------- src/Actions.Tests/UtilsSedTest.cs | 301 +++++++++++----------- src/Actions/Actions.csproj | 2 +- src/Actions/Program.cs | 133 +++++----- 6 files changed, 399 insertions(+), 342 deletions(-) diff --git a/.editorconfig b/.editorconfig index 42c45f7..db65c34 100644 --- a/.editorconfig +++ b/.editorconfig @@ -6,11 +6,69 @@ indent_style = space indent_size = 2 end_of_line = lf -[{appsettings.json,appsettings.*.json}] +[*.cs] charset = utf-8-bom indent_style = space indent_size = 4 -[*.cs] +[*.{csproj,props}] +charset = utf-8 indent_style = space -indent_size = 4 +indent_size = 2 + +[{appsettings.json,appsettings.*.json}] +charset = utf-8-bom +indent_style = space +indent_size = 2 + +[*.cs] +# C# Standards +dotnet_diagnostic.CS1998.severity = none # This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread. + +# Nullable Reference Types +dotnet_diagnostic.CS8618.severity = error # Non-nullable field is uninitialized. Consider declaring as nullable. +dotnet_diagnostic.CS8604.severity = error # Possible null reference argument. +dotnet_diagnostic.CS8629.severity = error # Nullable value type may be null. +dotnet_diagnostic.CS8600.severity = error # Converting null literal or possible null value to non-nullable type. +dotnet_diagnostic.CS8603.severity = error # Possible null reference return. +dotnet_diagnostic.CS8610.severity = error # Nullability of reference types in type of parameter doesn't match overridden member. +dotnet_diagnostic.CS8625.severity = error # Cannot convert null literal to non-nullable reference type. +dotnet_diagnostic.CS8606.severity = error # Possible null reference assignment to iteration variable +dotnet_diagnostic.CS8602.severity = error # Dereference of a possibly null reference. +dotnet_diagnostic.CS8601.severity = error # Possible null reference assignment. +dotnet_diagnostic.CS8614.severity = error # Nullability of reference types in type of parameter doesn't match implicitly implemented member. +dotnet_diagnostic.CS8765.severity = error # Nullability of type of parameter 'obj' doesn't match overridden member (possibly because of nullability attributes). +dotnet_diagnostic.CS8619.severity = error # Nullability of reference types in value of type 'GenericType' doesn't match target type 'GenericType'. + +# ================= +# Analyzer Rulesets +# ================= + +# Microsoft.CodeAnalysis.BannedApiAnalyzers +dotnet_diagnostic.RS0030.severity = error # RS0030: Banned API + +# Microsoft.VisualStudio.Threading.Analyzers +dotnet_diagnostic.VSTHRD100.severity = error # VSTHRD100: Avoid async void methods +dotnet_diagnostic.VSTHRD101.severity = error # VSTHRD101: Avoid unsupported async delegates +dotnet_diagnostic.VSTHRD110.severity = error # VSTHRD110: Observe result of async calls +dotnet_diagnostic.VSTHRD003.severity = none # VSTHRD003 Avoid awaiting foreign Tasks + +# ================= +# Format Rulesets +# ================= + +# IDE0160: Convert to file-scoped namespace +csharp_style_namespace_declarations = file_scoped:warning + +# Microsoft.Analyzers.ManagedCodeAnalysis +dotnet_diagnostic.CA2200.severity = error # Rethrow to preserve stack details + +# ================= +# Too Match Detail Rulesets +# ================= + +# CONSIDER: Are IDE0051 and IDE0052 too noisy to be warnings for IDE editing scenarios? Should they be made build-only warnings? +dotnet_diagnostic.IDE0005.severity = warning # Remove unnecessary imports +dotnet_diagnostic.IDE0051.severity = warning # Remove unused private member +dotnet_diagnostic.IDE0052.severity = warning # Remove unread private member +dotnet_diagnostic.IDE0090.severity = none # Simplify new expression diff --git a/src/Actions.Tests/Actions.Tests.csproj b/src/Actions.Tests/Actions.Tests.csproj index 36619f0..417cfcd 100644 --- a/src/Actions.Tests/Actions.Tests.csproj +++ b/src/Actions.Tests/Actions.Tests.csproj @@ -10,11 +10,17 @@ - + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + - - - + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/src/Actions.Tests/UpdateVersionCommand.cs b/src/Actions.Tests/UpdateVersionCommand.cs index 00cbe39..51b71a2 100644 --- a/src/Actions.Tests/UpdateVersionCommand.cs +++ b/src/Actions.Tests/UpdateVersionCommand.cs @@ -1,133 +1,132 @@ using Actions.Commands; using FluentAssertions; -namespace Actions.Tests +namespace Actions.Tests; + +public class UpdateVersionCommandTest { - public class UpdateVersionCommandTest + [Fact] + public void UpdateVersionUpmTest() { - [Fact] - public void UpdateVersionUpmTest() - { - var version = "1.0.0"; - var path = $"{nameof(UpdateVersionCommandTest)}/package.json"; - var contents = """ - { - "name": "com.unity.plugin.example", - "version": "1.2.310", - "displayName": "Package Example Plugin", - "description": "This is an example package", - "unity": "2019.1", - "unityRelease": "0b5", - "dependencies": { - "com.unity.example": "1.0.0" - }, - "keywords": [ - "keyword1", - "keyword2", - "keyword3" - ], - "author": { - "name": "Unity", - "email": "unity@example.com", - "url": "https://www.unity3d.com" - } - } - """; + var version = "1.0.0"; + var path = $"{nameof(UpdateVersionCommandTest)}/package.json"; + var contents = """ + { + "name": "com.unity.plugin.example", + "version": "1.2.310", + "displayName": "Package Example Plugin", + "description": "This is an example package", + "unity": "2019.1", + "unityRelease": "0b5", + "dependencies": { + "com.unity.example": "1.0.0" + }, + "keywords": [ + "keyword1", + "keyword2", + "keyword3" + ], + "author": { + "name": "Unity", + "email": "unity@example.com", + "url": "https://www.unity3d.com" + } + } + """; - var dir = Path.GetDirectoryName(path)!; - if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); - File.WriteAllText(path, contents); + var dir = Path.GetDirectoryName(path)!; + if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); + File.WriteAllText(path, contents); - var command = new UpdateVersionCommand(version, path); - var (before, after) = command.UpdateVersion(false); + var command = new UpdateVersionCommand(version, path); + var (before, after) = command.UpdateVersion(false); - after.Should().Be(""" - { - "name": "com.unity.plugin.example", - "version": "1.0.0", - "displayName": "Package Example Plugin", - "description": "This is an example package", - "unity": "2019.1", - "unityRelease": "0b5", - "dependencies": { - "com.unity.example": "1.0.0" - }, - "keywords": [ - "keyword1", - "keyword2", - "keyword3" - ], - "author": { - "name": "Unity", - "email": "unity@example.com", - "url": "https://www.unity3d.com" - } - } - """); - } + after.Should().Be(""" + { + "name": "com.unity.plugin.example", + "version": "1.0.0", + "displayName": "Package Example Plugin", + "description": "This is an example package", + "unity": "2019.1", + "unityRelease": "0b5", + "dependencies": { + "com.unity.example": "1.0.0" + }, + "keywords": [ + "keyword1", + "keyword2", + "keyword3" + ], + "author": { + "name": "Unity", + "email": "unity@example.com", + "url": "https://www.unity3d.com" + } + } + """); + } - [Fact] - public void UpdateVersionGodotTest() - { - var version = "1.0.0"; - var path = $"{nameof(UpdateVersionGodotTest)}/plugin.cfg"; - var contents = """ - [plugin] + [Fact] + public void UpdateVersionGodotTest() + { + var version = "1.0.0"; + var path = $"{nameof(UpdateVersionGodotTest)}/plugin.cfg"; + var contents = """ + [plugin] - name="Sandbox.Godot" - description="Sample." - author="Cysharp" - version="1.2.310" - language="C-sharp" - script="GodotPlugin.cs" - """; + name="Sandbox.Godot" + description="Sample." + author="Cysharp" + version="1.2.310" + language="C-sharp" + script="GodotPlugin.cs" + """; - var dir = Path.GetDirectoryName(path)!; - if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); - File.WriteAllText(path, contents); + var dir = Path.GetDirectoryName(path)!; + if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); + File.WriteAllText(path, contents); - var command = new UpdateVersionCommand(version, path); - var (before, after) = command.UpdateVersion(false); + var command = new UpdateVersionCommand(version, path); + var (before, after) = command.UpdateVersion(false); - after.Should().Be(""" - [plugin] - - name="Sandbox.Godot" - description="Sample." - author="Cysharp" - version="1.0.0" - language="C-sharp" - script="GodotPlugin.cs" - """); - } + after.Should().Be(""" + [plugin] + + name="Sandbox.Godot" + description="Sample." + author="Cysharp" + version="1.0.0" + language="C-sharp" + script="GodotPlugin.cs" + """); + } - [Fact] - public void UpdateVersionDirectoryBuildPropsTest() - { - var version = "1.0.0"; - var path = $"{nameof(UpdateVersionDirectoryBuildPropsTest)}/Directory.Build.props"; - var contents = """ - - - 1.2.310 - - - """; + [Fact] + public void UpdateVersionDirectoryBuildPropsTest() + { + var version = "1.0.0"; + var path = $"{nameof(UpdateVersionDirectoryBuildPropsTest)}/Directory.Build.props"; + var contents = """ + + + 1.2.310 + + + """; - var dir = Path.GetDirectoryName(path)!; - if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); - File.WriteAllText(path, contents); + var dir = Path.GetDirectoryName(path)!; + if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); + File.WriteAllText(path, contents); - var command = new UpdateVersionCommand(version, path); - var (before, after) = command.UpdateVersion(false); + var command = new UpdateVersionCommand(version, path); + var (before, after) = command.UpdateVersion(false); - after.Should().Be(""" - - - 1.0.0 - - - """); - } + after.Should().Be(""" + + + 1.0.0 + + + """); } } \ No newline at end of file diff --git a/src/Actions.Tests/UtilsSedTest.cs b/src/Actions.Tests/UtilsSedTest.cs index da04e40..e07b7c9 100644 --- a/src/Actions.Tests/UtilsSedTest.cs +++ b/src/Actions.Tests/UtilsSedTest.cs @@ -1,160 +1,159 @@ using FluentAssertions; -namespace Actions.Tests +namespace Actions.Tests; + +public class UtilsSedTest { - public class UtilsSedTest + private readonly string _dummyMultilineText; + + public UtilsSedTest() + { + _dummyMultilineText = """ + 1 foobar + 2 abcde + 3 piyopiyo + 4 okonomiyaki + 5 takoyaki + """.NormalizeEol(); + } + + [Fact] + public void CharacterReplaceTest() + { + var input = @"Hello world!"; + var (_, after) = Utils.Sed.Replace(input, "world", "Japan"); + + after.Should().Be("Hello Japan!"); + } + + [Fact] + public void CharacterChainReplaceTest() + { + var input = @"/a/b/c"; + var (_, after) = Utils.Sed.Replace(input, "a", "A"); + var (_, after2) = Utils.Sed.Replace(after, "b", "B"); + var (_, after3) = Utils.Sed.Replace(after2, "c", "C"); + + after.Should().Be("/A/b/c"); + after2.Should().Be("/A/B/c"); + after3.Should().Be("/A/B/C"); + } + + [Fact] + public void CharacterInsertTest() + { + var input = @"ABC DEF"; + var (_, after) = Utils.Sed.Replace(input, "ABC", "ABCD"); + + after.Should().Be("ABCD DEF"); + } + + [Fact] + public void CharacterDeleteTest() + { + var input = @"ABC DEF"; + var (_, after) = Utils.Sed.Replace(input, "ABC", ""); + + after.Should().Be(" DEF"); + } + + [Fact] + public void SentenceInsertTest() { - private readonly string _dummyMultilineText; - - public UtilsSedTest() - { - _dummyMultilineText = """ - 1 foobar - 2 abcde - 3 piyopiyo - 4 okonomiyaki - 5 takoyaki - """.NormalizeEol(); - } - - [Fact] - public void CharacterReplaceTest() - { - var input = @"Hello world!"; - var (_, after) = Utils.Sed.Replace(input, "world", "Japan"); - - after.Should().Be("Hello Japan!"); - } - - [Fact] - public void CharacterChainReplaceTest() - { - var input = @"/a/b/c"; - var (_, after) = Utils.Sed.Replace(input, "a", "A"); - var (_, after2) = Utils.Sed.Replace(after, "b", "B"); - var (_, after3) = Utils.Sed.Replace(after2, "c", "C"); - - after.Should().Be("/A/b/c"); - after2.Should().Be("/A/B/c"); - after3.Should().Be("/A/B/C"); - } - - [Fact] - public void CharacterInsertTest() - { - var input = @"ABC DEF"; - var (_, after) = Utils.Sed.Replace(input, "ABC", "ABCD"); - - after.Should().Be("ABCD DEF"); - } - - [Fact] - public void CharacterDeleteTest() - { - var input = @"ABC DEF"; - var (_, after) = Utils.Sed.Replace(input, "ABC", ""); - - after.Should().Be(" DEF"); - } - - [Fact] - public void SentenceInsertTest() - { - var input = _dummyMultilineText; - - // insert sentence before the line contains `abcde` - var (_, after) = Utils.Sed.Replace(input, $"^(.*?abcde.*?$)", "foo\n$1"); - - after.Should().Be(""" - 1 foobar - foo - 2 abcde - 3 piyopiyo - 4 okonomiyaki - 5 takoyaki - """.NormalizeEol()); - } - - [Fact] - public void SentenceDeleteTest() - { - var input = _dummyMultilineText; - // delete the line contains `abcde`, but keep brank line as is - var (_, after) = Utils.Sed.Replace(input, $"^(.*?abcde.*?$)", ""); - - after.Should().Be(""" - 1 foobar - - 3 piyopiyo - 4 okonomiyaki - 5 takoyaki - """.NormalizeEol()); - } - - [Fact] - public void SentenceDeleteCompactionTest() - { - var input = _dummyMultilineText; - - // delete the line contains `abcde`, then compaction deleted line. - var (_, after) = Utils.Sed.Replace(input, $"^(.*?abcde.*?$).*(\r?\n)?", ""); - - after.Should().Be(""" - 1 foobar - 3 piyopiyo - 4 okonomiyaki - 5 takoyaki - """.NormalizeEol()); - } - - [Fact] - public void NoWriteBackTest() - { - var path = $"{nameof(NoWriteBackTest)}.txt"; - if (File.Exists(path)) File.Delete(path); - - var input = _dummyMultilineText; - File.WriteAllText(path, input); - - // delete the line contains `abcde`, then compaction deleted line. - var (before, after) = Utils.Sed.Replace(path, $"^(.*?abcde.*?$).*(\r?\n)?", "", false); - - after.Should().Be(""" - 1 foobar - 3 piyopiyo - 4 okonomiyaki - 5 takoyaki - """.NormalizeEol()); - File.ReadAllText(path).Should().Be(before); - } - - [Fact] - public void WriteBackTest() - { - var path = $"{nameof(WriteBackTest)}.txt"; - if (File.Exists(path)) File.Delete(path); - - var input = _dummyMultilineText; - File.WriteAllText(path, input); - - // delete the line contains `abcde`, then compaction deleted line. - var (_, after) = Utils.Sed.Replace(path, $"^(.*?abcde.*?$).*(\r?\n)?", "", true); - - after.Should().Be(""" - 1 foobar - 3 piyopiyo - 4 okonomiyaki - 5 takoyaki - """.NormalizeEol()); - File.ReadAllText(path).Should().Be(after); - } + var input = _dummyMultilineText; + + // insert sentence before the line contains `abcde` + var (_, after) = Utils.Sed.Replace(input, $"^(.*?abcde.*?$)", "foo\n$1"); + + after.Should().Be(""" + 1 foobar + foo + 2 abcde + 3 piyopiyo + 4 okonomiyaki + 5 takoyaki + """.NormalizeEol()); + } + + [Fact] + public void SentenceDeleteTest() + { + var input = _dummyMultilineText; + // delete the line contains `abcde`, but keep brank line as is + var (_, after) = Utils.Sed.Replace(input, $"^(.*?abcde.*?$)", ""); + + after.Should().Be(""" + 1 foobar + + 3 piyopiyo + 4 okonomiyaki + 5 takoyaki + """.NormalizeEol()); } - public static class StringExtentions + [Fact] + public void SentenceDeleteCompactionTest() + { + var input = _dummyMultilineText; + + // delete the line contains `abcde`, then compaction deleted line. + var (_, after) = Utils.Sed.Replace(input, $"^(.*?abcde.*?$).*(\r?\n)?", ""); + + after.Should().Be(""" + 1 foobar + 3 piyopiyo + 4 okonomiyaki + 5 takoyaki + """.NormalizeEol()); + } + + [Fact] + public void NoWriteBackTest() + { + var path = $"{nameof(NoWriteBackTest)}.txt"; + if (File.Exists(path)) File.Delete(path); + + var input = _dummyMultilineText; + File.WriteAllText(path, input); + + // delete the line contains `abcde`, then compaction deleted line. + var (before, after) = Utils.Sed.Replace(path, $"^(.*?abcde.*?$).*(\r?\n)?", "", false); + + after.Should().Be(""" + 1 foobar + 3 piyopiyo + 4 okonomiyaki + 5 takoyaki + """.NormalizeEol()); + File.ReadAllText(path).Should().Be(before); + } + + [Fact] + public void WriteBackTest() + { + var path = $"{nameof(WriteBackTest)}.txt"; + if (File.Exists(path)) File.Delete(path); + + var input = _dummyMultilineText; + File.WriteAllText(path, input); + + // delete the line contains `abcde`, then compaction deleted line. + var (_, after) = Utils.Sed.Replace(path, $"^(.*?abcde.*?$).*(\r?\n)?", "", true); + + after.Should().Be(""" + 1 foobar + 3 piyopiyo + 4 okonomiyaki + 5 takoyaki + """.NormalizeEol()); + File.ReadAllText(path).Should().Be(after); + } +} + +public static class StringExtentions +{ + public static string NormalizeEol(this string input) { - public static string NormalizeEol(this string input) - { - return input.Replace("\r\n", "\n"); - } + return input.Replace("\r\n", "\n"); } } diff --git a/src/Actions/Actions.csproj b/src/Actions/Actions.csproj index 7813782..b598772 100644 --- a/src/Actions/Actions.csproj +++ b/src/Actions/Actions.csproj @@ -8,7 +8,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Actions/Program.cs b/src/Actions/Program.cs index 11114bc..0b69e6a 100644 --- a/src/Actions/Program.cs +++ b/src/Actions/Program.cs @@ -3,88 +3,83 @@ using Actions.Utils; using ConsoleAppFramework; -namespace Actions; +var app = ConsoleApp.Create(); +app.Add(); +app.Run(args); -public class Program +namespace Actions { - private static void Main(string[] args) + public class ActionsBatch { - var app = ConsoleApp.Create(); - app.Add(); - app.Run(args); - } -} - -public class ActionsBatch -{ - /// Get version string from tag - /// - /// - /// - /// - /// - /// - [Command("versioning")] - public void Versioning(string tag, string prefix = "", VersionIncrement versionIncrement = VersionIncrement.Patch, bool isPrelease = false, string prerelease = "preview", bool withoutPrefix = false, OutputFormatType outputFormat = OutputFormatType.Console) - { - var command = new VersioningCommand(tag, prefix, versionIncrement, isPrelease, prerelease); - var versioning = command.Versioning(withoutPrefix); + /// Get version string from tag + /// + /// + /// + /// + /// + /// + [Command("versioning")] + public void Versioning(string tag, string prefix = "", VersionIncrement versionIncrement = VersionIncrement.Patch, bool isPrelease = false, string prerelease = "preview", bool withoutPrefix = false, OutputFormatType outputFormat = OutputFormatType.Console) + { + var command = new VersioningCommand(tag, prefix, versionIncrement, isPrelease, prerelease); + var versioning = command.Versioning(withoutPrefix); - var output = OutputFormat("version", versioning, outputFormat); - Console.WriteLine(output); - } + var output = OutputFormat("version", versioning, outputFormat); + Console.WriteLine(output); + } - /// - /// Update Version for specified path - /// - /// - /// - /// - [Command("update-version")] - public void UpdateVersion(string version, string path, bool dryRun) - { - Console.WriteLine($"Update begin, {path} ..."); - if (string.IsNullOrWhiteSpace(path)) + /// + /// Update Version for specified path + /// + /// + /// + /// + [Command("update-version")] + public void UpdateVersion(string version, string path, bool dryRun) { - Console.WriteLine("Empty path detected, skip execution."); - return; - } + Console.WriteLine($"Update begin, {path} ..."); + if (string.IsNullOrWhiteSpace(path)) + { + Console.WriteLine("Empty path detected, skip execution."); + return; + } - using (var githubGroup = new GitHubActionsGroupLogger("Before")) - Console.WriteLine(File.ReadAllText(path)); + using (var githubGroup = new GitHubActionsGroupLogger("Before")) + Console.WriteLine(File.ReadAllText(path)); - var command = new UpdateVersionCommand(version, path); - var result = command.UpdateVersion(dryRun); + var command = new UpdateVersionCommand(version, path); + var result = command.UpdateVersion(dryRun); - using (var githubGroup = new GitHubActionsGroupLogger("After")) - Console.WriteLine(result.After); + using (var githubGroup = new GitHubActionsGroupLogger("After")) + Console.WriteLine(result.After); - Console.WriteLine($"Completed ..."); - } + Console.WriteLine($"Completed ..."); + } - /// - /// Create dummy files - /// - /// - [Command("create-dummy")] - public void CreateDummy(string basePath) - { - Console.WriteLine($"Creating dummy files, under {basePath} ..."); + /// + /// Create dummy files + /// + /// + [Command("create-dummy")] + public void CreateDummy(string basePath) + { + Console.WriteLine($"Creating dummy files, under {basePath} ..."); - var command = new CreateDummyCommand(); - command.CreateDummyFiles(basePath); + var command = new CreateDummyCommand(); + command.CreateDummyFiles(basePath); + + Console.WriteLine($"Completed ..."); + } - Console.WriteLine($"Completed ..."); + private static string OutputFormat(string key, string value, OutputFormatType format) => format switch + { + OutputFormatType.Console => value, + OutputFormatType.GitHubActions => $"{key}={value}", + _ => throw new NotImplementedException(nameof(format)), + }; } - private static string OutputFormat(string key, string value, OutputFormatType format) => format switch + public class ActionCommandException(string message) : Exception(message) { - OutputFormatType.Console => value, - OutputFormatType.GitHubActions => $"{key}={value}", - _ => throw new NotImplementedException(nameof(format)), - }; -} - -public class ActionCommandException(string message) : Exception(message) -{ -} + } +} \ No newline at end of file From 3d44e8f18ae555f4e1c7964391acbc354b92ab2a Mon Sep 17 00:00:00 2001 From: Ikiru Yoshizaki <3856350+guitarrapc@users.noreply.github.com> Date: Tue, 17 Dec 2024 12:10:38 +0900 Subject: [PATCH 10/21] chore: remove unnecessary suggestion --- .editorconfig | 1 + src/Actions/Program.cs | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.editorconfig b/.editorconfig index db65c34..47db707 100644 --- a/.editorconfig +++ b/.editorconfig @@ -71,4 +71,5 @@ dotnet_diagnostic.CA2200.severity = error # Rethrow to preserve stack details dotnet_diagnostic.IDE0005.severity = warning # Remove unnecessary imports dotnet_diagnostic.IDE0051.severity = warning # Remove unused private member dotnet_diagnostic.IDE0052.severity = warning # Remove unread private member +dotnet_diagnostic.IDE0079.severity = none # Remove unnecessary suppression dotnet_diagnostic.IDE0090.severity = none # Simplify new expression diff --git a/src/Actions/Program.cs b/src/Actions/Program.cs index 0b69e6a..18288b0 100644 --- a/src/Actions/Program.cs +++ b/src/Actions/Program.cs @@ -1,4 +1,4 @@ -using Actions; +using Actions; using Actions.Commands; using Actions.Utils; using ConsoleAppFramework; @@ -11,6 +11,8 @@ namespace Actions { public class ActionsBatch { +#pragma warning disable CA1822 // Mark members as static + /// Get version string from tag /// /// @@ -71,6 +73,8 @@ public void CreateDummy(string basePath) Console.WriteLine($"Completed ..."); } +#pragma warning restore CA1822 // Mark members as static + private static string OutputFormat(string key, string value, OutputFormatType format) => format switch { OutputFormatType.Console => value, From b42dda70db6f9c00a31081f8cd4c0da50ace20a1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 17 Dec 2024 03:14:09 +0000 Subject: [PATCH 11/21] feat: Update package.json to 1.2.315 Commit by [GitHub Actions](https://github.com/Cysharp/Actions/actions/runs/12365618075) --- Sandbox/Directory.Build.props | 2 +- Sandbox/Sandbox.Godot/addons/Foo/plugin.cfg | 2 +- Sandbox/Sandbox.Unity/Assets/Plugins/Foo.Plugin/package.json | 2 +- Sandbox/Sandbox.Unity/Assets/Plugins/Foo/package.json | 2 +- Sandbox/VersionOutput/version.txt | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Sandbox/Directory.Build.props b/Sandbox/Directory.Build.props index 0b4f945..d3826a0 100644 --- a/Sandbox/Directory.Build.props +++ b/Sandbox/Directory.Build.props @@ -1,5 +1,5 @@ - 1.2.313 + 1.2.315 diff --git a/Sandbox/Sandbox.Godot/addons/Foo/plugin.cfg b/Sandbox/Sandbox.Godot/addons/Foo/plugin.cfg index ba2a48b..e163f35 100644 --- a/Sandbox/Sandbox.Godot/addons/Foo/plugin.cfg +++ b/Sandbox/Sandbox.Godot/addons/Foo/plugin.cfg @@ -3,6 +3,6 @@ name="Sandbox.Godot" description="Sample." author="Cysharp" -version="1.2.313" +version="1.2.315" language="C-sharp" script="GodotPlugin.cs" diff --git a/Sandbox/Sandbox.Unity/Assets/Plugins/Foo.Plugin/package.json b/Sandbox/Sandbox.Unity/Assets/Plugins/Foo.Plugin/package.json index e0970d8..4738518 100644 --- a/Sandbox/Sandbox.Unity/Assets/Plugins/Foo.Plugin/package.json +++ b/Sandbox/Sandbox.Unity/Assets/Plugins/Foo.Plugin/package.json @@ -1,6 +1,6 @@ { "name": "com.unity.plugin.example", - "version": "1.2.313", + "version": "1.2.315", "displayName": "Package Example Plugin", "description": "This is an example package", "unity": "2019.1", diff --git a/Sandbox/Sandbox.Unity/Assets/Plugins/Foo/package.json b/Sandbox/Sandbox.Unity/Assets/Plugins/Foo/package.json index d456725..d919226 100644 --- a/Sandbox/Sandbox.Unity/Assets/Plugins/Foo/package.json +++ b/Sandbox/Sandbox.Unity/Assets/Plugins/Foo/package.json @@ -1,6 +1,6 @@ { "name": "com.unity.example", - "version": "1.2.313", + "version": "1.2.315", "displayName": "Package Example", "description": "This is an example package", "unity": "2019.1", diff --git a/Sandbox/VersionOutput/version.txt b/Sandbox/VersionOutput/version.txt index 4493a5c..506a0b3 100644 --- a/Sandbox/VersionOutput/version.txt +++ b/Sandbox/VersionOutput/version.txt @@ -1 +1 @@ -1.2.313 \ No newline at end of file +1.2.315 \ No newline at end of file From 854cc09f25b0f0553e86e2f357dfa37d60fd9173 Mon Sep 17 00:00:00 2001 From: Ikiru Yoshizaki <3856350+guitarrapc@users.noreply.github.com> Date: Tue, 17 Dec 2024 12:36:58 +0900 Subject: [PATCH 12/21] chore: update test name --- src/Actions.Tests/UpdateVersionCommand.cs | 12 +- src/Actions.Tests/VersioningCommandTest.cs | 71 ++++---- src/Actions/Commands/CreateDummyCommand.cs | 99 ++++++----- src/Actions/Commands/UpdateVersionCommand.cs | 163 +++++++++---------- 4 files changed, 171 insertions(+), 174 deletions(-) diff --git a/src/Actions.Tests/UpdateVersionCommand.cs b/src/Actions.Tests/UpdateVersionCommand.cs index 51b71a2..96a95b7 100644 --- a/src/Actions.Tests/UpdateVersionCommand.cs +++ b/src/Actions.Tests/UpdateVersionCommand.cs @@ -1,4 +1,4 @@ -using Actions.Commands; +using Actions.Commands; using FluentAssertions; namespace Actions.Tests; @@ -6,7 +6,7 @@ namespace Actions.Tests; public class UpdateVersionCommandTest { [Fact] - public void UpdateVersionUpmTest() + public void UnityUpmTest() { var version = "1.0.0"; var path = $"{nameof(UpdateVersionCommandTest)}/package.json"; @@ -67,10 +67,10 @@ public void UpdateVersionUpmTest() } [Fact] - public void UpdateVersionGodotTest() + public void GodotPluginTest() { var version = "1.0.0"; - var path = $"{nameof(UpdateVersionGodotTest)}/plugin.cfg"; + var path = $"{nameof(GodotPluginTest)}/plugin.cfg"; var contents = """ [plugin] @@ -102,10 +102,10 @@ public void UpdateVersionGodotTest() } [Fact] - public void UpdateVersionDirectoryBuildPropsTest() + public void DirectoryBuildPropsTest() { var version = "1.0.0"; - var path = $"{nameof(UpdateVersionDirectoryBuildPropsTest)}/Directory.Build.props"; + var path = $"{nameof(DirectoryBuildPropsTest)}/Directory.Build.props"; var contents = """ diff --git a/src/Actions.Tests/VersioningCommandTest.cs b/src/Actions.Tests/VersioningCommandTest.cs index ec4eabd..026dc13 100644 --- a/src/Actions.Tests/VersioningCommandTest.cs +++ b/src/Actions.Tests/VersioningCommandTest.cs @@ -1,47 +1,46 @@ -using Actions.Commands; +using Actions.Commands; using FluentAssertions; -namespace Actions.Tests +namespace Actions.Tests; + +public class VersioningCommandTest { - public class VersioningCommandTest + [Theory] + [InlineData("0.1.0", VersionIncrement.Major, "1.1.0")] + [InlineData("0.1.0", VersionIncrement.Minor, "0.2.0")] + [InlineData("0.1.0", VersionIncrement.Patch, "0.1.1")] + public void VersionIncrementTest(string tag, VersionIncrement versionIncrement, string actual) { - [Theory] - [InlineData("0.1.0", VersionIncrement.Major, "1.1.0")] - [InlineData("0.1.0", VersionIncrement.Minor, "0.2.0")] - [InlineData("0.1.0", VersionIncrement.Patch, "0.1.1")] - public void VersionIncrementTest(string tag, VersionIncrement versionIncrement, string actual) - { - var command = new VersioningCommand(tag, prefix: "", versionIncrement: versionIncrement, isPrelease: false, prerelease: ""); - var versioning = command.Versioning(); + var command = new VersioningCommand(tag, prefix: "", versionIncrement: versionIncrement, isPrelease: false, prerelease: ""); + var versioning = command.Versioning(); - versioning.Should().Be(actual); - } + versioning.Should().Be(actual); + } - [Theory] - [InlineData("v0.1.0", "v", true, "0.1.1")] - [InlineData("Ver0.1.0", "Ver", true, "0.1.1")] - [InlineData("Ver.0.1.0", "Ver.", true, "0.1.1")] - [InlineData("v0.1.0", "v", false, "v0.1.1")] - [InlineData("Ver0.1.0", "Ver", false, "Ver0.1.1")] - [InlineData("Ver.0.1.0", "Ver.", false, "Ver.0.1.1")] - public void VersionPrefixTest(string tag, string prefix, bool withoutPrefix, string actual) - { - var command = new VersioningCommand(tag, prefix: prefix, versionIncrement: VersionIncrement.Patch, isPrelease: false, prerelease: ""); - var versioning = command.Versioning(withoutPrefix); + [Theory] + [InlineData("v0.1.0", "v", true, "0.1.1")] + [InlineData("Ver0.1.0", "Ver", true, "0.1.1")] + [InlineData("Ver.0.1.0", "Ver.", true, "0.1.1")] + [InlineData("v0.1.0", "v", false, "v0.1.1")] + [InlineData("Ver0.1.0", "Ver", false, "Ver0.1.1")] + [InlineData("Ver.0.1.0", "Ver.", false, "Ver.0.1.1")] + public void VersionPrefixTest(string tag, string prefix, bool withoutPrefix, string actual) + { + var command = new VersioningCommand(tag, prefix: prefix, versionIncrement: VersionIncrement.Patch, isPrelease: false, prerelease: ""); + var versioning = command.Versioning(withoutPrefix); - versioning.Should().Be(actual); - } + versioning.Should().Be(actual); + } - [Theory] - [InlineData("0.1.0", "", "0.1.1")] - [InlineData("0.1.0", "alpha", "0.1.1-alpha")] - [InlineData("0.1.0", "preview", "0.1.1-preview")] - public void VersionPrereleaseTest(string tag, string prerelease, string actual) - { - var command = new VersioningCommand(tag, prefix: "", versionIncrement: VersionIncrement.Patch, isPrelease: true, prerelease: prerelease); - var versioning = command.Versioning(); + [Theory] + [InlineData("0.1.0", "", "0.1.1")] + [InlineData("0.1.0", "alpha", "0.1.1-alpha")] + [InlineData("0.1.0", "preview", "0.1.1-preview")] + public void VersionPrereleaseTest(string tag, string prerelease, string actual) + { + var command = new VersioningCommand(tag, prefix: "", versionIncrement: VersionIncrement.Patch, isPrelease: true, prerelease: prerelease); + var versioning = command.Versioning(); - versioning.Should().Be(actual); - } + versioning.Should().Be(actual); } } \ No newline at end of file diff --git a/src/Actions/Commands/CreateDummyCommand.cs b/src/Actions/Commands/CreateDummyCommand.cs index 68b5dc2..06431ef 100644 --- a/src/Actions/Commands/CreateDummyCommand.cs +++ b/src/Actions/Commands/CreateDummyCommand.cs @@ -1,58 +1,57 @@ -namespace Actions.Commands +namespace Actions.Commands; + +public class CreateDummyCommand { - public class CreateDummyCommand + public void CreateDummyFiles(string basePath) { - public void CreateDummyFiles(string basePath) - { - var upm = ("package.json", """ - { - "name": "com.unity.plugin.example", - "version": "1.2.310", - "displayName": "Package Example Plugin", - "description": "This is an example package", - "unity": "2019.1", - "unityRelease": "0b5", - "dependencies": { - "com.unity.example": "1.0.0" - }, - "keywords": [ - "keyword1", - "keyword2", - "keyword3" - ], - "author": { - "name": "Unity", - "email": "unity@example.com", - "url": "https://www.unity3d.com" - } + var upm = ("package.json", """ + { + "name": "com.unity.plugin.example", + "version": "1.2.310", + "displayName": "Package Example Plugin", + "description": "This is an example package", + "unity": "2019.1", + "unityRelease": "0b5", + "dependencies": { + "com.unity.example": "1.0.0" + }, + "keywords": [ + "keyword1", + "keyword2", + "keyword3" + ], + "author": { + "name": "Unity", + "email": "unity@example.com", + "url": "https://www.unity3d.com" } - """); - var godot = ("plugin.cfg", """ - [plugin] - name="Sandbox.Godot" - description="Sample." - author="Cysharp" - version="1.2.310" - language="C-sharp" - script="GodotPlugin.cs" - """); - var directoryBuildProps = ("Directory.Build.props", """ - - - 1.2.310 - - - """); + } + """); + var godot = ("plugin.cfg", """ + [plugin] + name="Sandbox.Godot" + description="Sample." + author="Cysharp" + version="1.2.310" + language="C-sharp" + script="GodotPlugin.cs" + """); + var directoryBuildProps = ("Directory.Build.props", """ + + + 1.2.310 + + + """); - foreach (var (file, contents) in new[] { upm, godot, directoryBuildProps }) - { - var path = Path.Combine(basePath, file); - if (!Directory.Exists(basePath)) - Directory.CreateDirectory(basePath); + foreach (var (file, contents) in new[] { upm, godot, directoryBuildProps }) + { + var path = Path.Combine(basePath, file); + if (!Directory.Exists(basePath)) + Directory.CreateDirectory(basePath); - Console.WriteLine($"- {path} ..."); - File.WriteAllText(path, contents); - } + Console.WriteLine($"- {path} ..."); + File.WriteAllText(path, contents); } } } diff --git a/src/Actions/Commands/UpdateVersionCommand.cs b/src/Actions/Commands/UpdateVersionCommand.cs index 1b937c8..46d65b1 100644 --- a/src/Actions/Commands/UpdateVersionCommand.cs +++ b/src/Actions/Commands/UpdateVersionCommand.cs @@ -1,111 +1,110 @@ -using Actions.Utils; +using Actions.Utils; using System.Text.Json; using System.Text.Json.Serialization; -namespace Actions.Commands +namespace Actions.Commands; + +public record struct UpdateVersionCommandResult(string Before, string After); +public class UpdateVersionCommand(string version, string path) { - public record struct UpdateVersionCommandResult(string Before, string After); - public class UpdateVersionCommand(string version, string path) + public UpdateVersionCommandResult UpdateVersion(bool dryRun) { - public UpdateVersionCommandResult UpdateVersion(bool dryRun) - { - if (!File.Exists(path)) throw new FileNotFoundException(path); + if (!File.Exists(path)) throw new FileNotFoundException(path); - var writeBack = !dryRun; - var fileName = Path.GetFileName(path); - return fileName switch - { - // UPM - "package.json" => HandleUpm(writeBack), - // Godot - "plugin.cfg" => HandleGodot(writeBack), - // .NET - "Directory.Build.props" => HandleDirectoryBuildProps(writeBack), - // Other - _ => throw new NotImplementedException(fileName), - }; - } - - private UpdateVersionCommandResult HandleUpm(bool writeBack) + var writeBack = !dryRun; + var fileName = Path.GetFileName(path); + return fileName switch { - // replace - var (before, after) = Sed.Replace(path, @"""version"":\s*""(.*?)""", $@"""version"": ""{version}""", writeBack); + // UPM + "package.json" => HandleUpm(writeBack), + // Godot + "plugin.cfg" => HandleGodot(writeBack), + // .NET + "Directory.Build.props" => HandleDirectoryBuildProps(writeBack), + // Other + _ => throw new NotImplementedException(fileName), + }; + } - // validate - Validate(after, version); + private UpdateVersionCommandResult HandleUpm(bool writeBack) + { + // replace + var (before, after) = Sed.Replace(path, @"""version"":\s*""(.*?)""", $@"""version"": ""{version}""", writeBack); - return new UpdateVersionCommandResult(before, after); + // validate + Validate(after, version); - static void Validate(string contents, string version) - { - var packageJson = JsonSerializer.Deserialize(contents) ?? throw new ActionCommandException($"UPM package.json updated, but failed to load as valid JSON. contents: {contents}"); - if (packageJson.Version != version) - throw new ActionCommandException($"UPM package.json updated, but version miss-match. actual {packageJson?.Version}, expected {version}"); - } - } + return new UpdateVersionCommandResult(before, after); - private UpdateVersionCommandResult HandleGodot(bool writeBack) + static void Validate(string contents, string version) { - // replace - var (before, after) = Sed.Replace(path, @"(version=)""(.*?)""", $@"$1""{version}""", writeBack); + var packageJson = JsonSerializer.Deserialize(contents) ?? throw new ActionCommandException($"UPM package.json updated, but failed to load as valid JSON. contents: {contents}"); + if (packageJson.Version != version) + throw new ActionCommandException($"UPM package.json updated, but version miss-match. actual {packageJson?.Version}, expected {version}"); + } + } - // validate - Validate(after, version); + private UpdateVersionCommandResult HandleGodot(bool writeBack) + { + // replace + var (before, after) = Sed.Replace(path, @"(version=)""(.*?)""", $@"$1""{version}""", writeBack); - return new UpdateVersionCommandResult(before, after); + // validate + Validate(after, version); - static void Validate(string contents, string version) + return new UpdateVersionCommandResult(before, after); + + static void Validate(string contents, string version) + { + var lines = contents.Split("\n"); + Span destination = stackalloc Range[2]; + foreach (var line in lines) { - var lines = contents.Split("\n"); - Span destination = stackalloc Range[2]; - foreach (var line in lines) + // find the line befin with "version=", then split with = to get version + if (!line.StartsWith("version=")) + continue; + + var span = line.AsSpan(); + var range = span.Split(destination, '=', StringSplitOptions.TrimEntries); + if (range != 2) + continue; + + // validate version is expceted + var versionValue = span[destination[1]].ToString(); + if (versionValue != $"\"{version}\"") { - // find the line befin with "version=", then split with = to get version - if (!line.StartsWith("version=")) - continue; - - var span = line.AsSpan(); - var range = span.Split(destination, '=', StringSplitOptions.TrimEntries); - if (range != 2) - continue; - - // validate version is expceted - var versionValue = span[destination[1]].ToString(); - if (versionValue != $"\"{version}\"") - { - throw new ActionCommandException($"Godot plugin.cfg updated, but version miss-match. actual {versionValue}, expected {version}"); - } - return; + throw new ActionCommandException($"Godot plugin.cfg updated, but version miss-match. actual {versionValue}, expected {version}"); } - throw new ActionCommandException($"Godot plugin.cfg updated, but version key not found."); + return; } + throw new ActionCommandException($"Godot plugin.cfg updated, but version key not found."); } + } - private UpdateVersionCommandResult HandleDirectoryBuildProps(bool writeBack) - { - // replace - var (before, after) = Sed.Replace(path, @".*", $@"{version}", writeBack); + private UpdateVersionCommandResult HandleDirectoryBuildProps(bool writeBack) + { + // replace + var (before, after) = Sed.Replace(path, @".*", $@"{version}", writeBack); - // validate - Validate(after, version); + // validate + Validate(after, version); - return new UpdateVersionCommandResult(before, after); + return new UpdateVersionCommandResult(before, after); - static void Validate(string contents, string version) - { - var xmlDoc = new System.Xml.XmlDocument(); - xmlDoc.LoadXml(contents); - var versionPrefixNode = xmlDoc.SelectSingleNode("//VersionPrefix") ?? throw new ActionCommandException($"Directory.Build.props updated, but VersionPrefix key not found."); - if (versionPrefixNode.InnerText != version) - throw new ActionCommandException($"Directory.Build.props updated, but version miss-match. actual {versionPrefixNode.InnerText}, expected {version}"); + static void Validate(string contents, string version) + { + var xmlDoc = new System.Xml.XmlDocument(); + xmlDoc.LoadXml(contents); + var versionPrefixNode = xmlDoc.SelectSingleNode("//VersionPrefix") ?? throw new ActionCommandException($"Directory.Build.props updated, but VersionPrefix key not found."); + if (versionPrefixNode.InnerText != version) + throw new ActionCommandException($"Directory.Build.props updated, but version miss-match. actual {versionPrefixNode.InnerText}, expected {version}"); - } } + } - private record UpmPackageJson - { - [JsonPropertyName("version")] - public required string Version { get; set; } - } + private record UpmPackageJson + { + [JsonPropertyName("version")] + public required string Version { get; set; } } } From bff2c1b7eaaae7e4fab3d9af5aff09581861e2a6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 17 Dec 2024 03:39:11 +0000 Subject: [PATCH 13/21] feat: Update package.json to 1.2.317 Commit by [GitHub Actions](https://github.com/Cysharp/Actions/actions/runs/12365880311) --- Sandbox/Directory.Build.props | 2 +- Sandbox/Sandbox.Godot/addons/Foo/plugin.cfg | 2 +- Sandbox/Sandbox.Unity/Assets/Plugins/Foo.Plugin/package.json | 2 +- Sandbox/Sandbox.Unity/Assets/Plugins/Foo/package.json | 2 +- Sandbox/VersionOutput/version.txt | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Sandbox/Directory.Build.props b/Sandbox/Directory.Build.props index d3826a0..a3de16d 100644 --- a/Sandbox/Directory.Build.props +++ b/Sandbox/Directory.Build.props @@ -1,5 +1,5 @@ - 1.2.315 + 1.2.317 diff --git a/Sandbox/Sandbox.Godot/addons/Foo/plugin.cfg b/Sandbox/Sandbox.Godot/addons/Foo/plugin.cfg index e163f35..7e6b0c2 100644 --- a/Sandbox/Sandbox.Godot/addons/Foo/plugin.cfg +++ b/Sandbox/Sandbox.Godot/addons/Foo/plugin.cfg @@ -3,6 +3,6 @@ name="Sandbox.Godot" description="Sample." author="Cysharp" -version="1.2.315" +version="1.2.317" language="C-sharp" script="GodotPlugin.cs" diff --git a/Sandbox/Sandbox.Unity/Assets/Plugins/Foo.Plugin/package.json b/Sandbox/Sandbox.Unity/Assets/Plugins/Foo.Plugin/package.json index 4738518..5312b8a 100644 --- a/Sandbox/Sandbox.Unity/Assets/Plugins/Foo.Plugin/package.json +++ b/Sandbox/Sandbox.Unity/Assets/Plugins/Foo.Plugin/package.json @@ -1,6 +1,6 @@ { "name": "com.unity.plugin.example", - "version": "1.2.315", + "version": "1.2.317", "displayName": "Package Example Plugin", "description": "This is an example package", "unity": "2019.1", diff --git a/Sandbox/Sandbox.Unity/Assets/Plugins/Foo/package.json b/Sandbox/Sandbox.Unity/Assets/Plugins/Foo/package.json index d919226..0c99daf 100644 --- a/Sandbox/Sandbox.Unity/Assets/Plugins/Foo/package.json +++ b/Sandbox/Sandbox.Unity/Assets/Plugins/Foo/package.json @@ -1,6 +1,6 @@ { "name": "com.unity.example", - "version": "1.2.315", + "version": "1.2.317", "displayName": "Package Example", "description": "This is an example package", "unity": "2019.1", diff --git a/Sandbox/VersionOutput/version.txt b/Sandbox/VersionOutput/version.txt index 506a0b3..1ee8930 100644 --- a/Sandbox/VersionOutput/version.txt +++ b/Sandbox/VersionOutput/version.txt @@ -1 +1 @@ -1.2.315 \ No newline at end of file +1.2.317 \ No newline at end of file From e639f10b46a9a88244ebee56383904f1d5422bb0 Mon Sep 17 00:00:00 2001 From: Ikiru Yoshizaki <3856350+guitarrapc@users.noreply.github.com> Date: Tue, 17 Dec 2024 15:42:57 +0900 Subject: [PATCH 14/21] feat: add ValidateArtifactCommand --- src/Actions.Tests/FileExistsCommandTest.cs | 100 ++++++++++++++++++ ...Command.cs => UpdateVersionCommandTest.cs} | 6 +- src/Actions/Commands/CreateDummyCommand.cs | 24 ++++- src/Actions/Commands/FileExsistsCommand.cs | 95 +++++++++++++++++ src/Actions/Program.cs | 17 ++- src/Actions/Properties/launchSettings.json | 17 +++ 6 files changed, 253 insertions(+), 6 deletions(-) create mode 100644 src/Actions.Tests/FileExistsCommandTest.cs rename src/Actions.Tests/{UpdateVersionCommand.cs => UpdateVersionCommandTest.cs} (91%) create mode 100644 src/Actions/Commands/FileExsistsCommand.cs diff --git a/src/Actions.Tests/FileExistsCommandTest.cs b/src/Actions.Tests/FileExistsCommandTest.cs new file mode 100644 index 0000000..4616495 --- /dev/null +++ b/src/Actions.Tests/FileExistsCommandTest.cs @@ -0,0 +1,100 @@ +using Actions.Commands; + +namespace Actions.Tests; + +public class FileExistsCommandTest +{ + [Fact] + public void EmptyPathTest() + { + var command = new FileExsistsCommand(""); + Assert.Throws(() => command.Validate()); + } + + [Fact] + public void FullPathTest() + { + var path = $".tests/{nameof(FileExistsCommandTest)}/{nameof(FullPathTest)}/dummy.nupkg"; + var dir = Path.GetDirectoryName(path)!; + if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); + File.WriteAllText(path, ""); + + var command = new FileExsistsCommand(path); + command.Validate(); + } + + [Fact] + public void WildcardFileTest() + { + var dir = $".tests/{nameof(FileExistsCommandTest)}/{nameof(WildcardFileTest)}"; + var items = new[] { "foo", "bar", "piyo" }; + foreach (var item in items) { + if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); + File.WriteAllText(Path.Combine(dir, item), ""); + } + + var command = new FileExsistsCommand($"{dir}/*"); + command.Validate(); + + var command2 = new FileExsistsCommand($"{dir}/foo"); + command2.Validate(); + } + + [Fact] + public void WildcardDirectoryTest() + { + var dir = $".tests/{nameof(FileExistsCommandTest)}/{nameof(WildcardDirectoryTest)}"; + var items = new[] { "foo", "bar", "piyo" }; + foreach (var item in items) + { + if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); + File.WriteAllText(Path.Combine(dir, item), ""); + } + + var command = new FileExsistsCommand($".tests/{nameof(FileExistsCommandTest)}/*/foo"); + command.Validate(); + + var command2 = new FileExsistsCommand($".tests/{nameof(FileExistsCommandTest)}/{nameof(WildcardDirectoryTest)}/foo"); + command2.Validate(); + + var failCommand = new FileExsistsCommand($".tests/{nameof(FileExistsCommandTest)}/{nameof(WildcardDirectoryTest)}/*/foo"); + Assert.Throws(() => failCommand.Validate()); + } + + [Fact] + public void RecursiveWildcardDirectoryTest() + { + var dir = $".tests/{nameof(FileExistsCommandTest)}/{nameof(RecursiveWildcardDirectoryTest)}"; + var items = new[] { "foo", "bar", "piyo" }; + foreach (var item in items) + { + if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); + File.WriteAllText(Path.Combine(dir, item), ""); + } + + var command = new FileExsistsCommand($".tests/{nameof(FileExistsCommandTest)}/**/foo"); + command.Validate(); + + var command2 = new FileExsistsCommand($".tests/{nameof(FileExistsCommandTest)}/{nameof(WildcardDirectoryTest)}/**/foo"); + command2.Validate(); + } + + [Fact] + public void RecursiveWildcardDirectoryAndFileTest() + { + var dirBase = $".tests/{nameof(FileExistsCommandTest)}/{nameof(RecursiveWildcardDirectoryAndFileTest)}"; + var items = new[] { "foo", "bar", "piyo" }; + foreach (var item in items) + { + var dir = Path.Combine(dirBase, item); + if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); + File.WriteAllText(Path.Combine(dir, item), ""); + } + + var command = new FileExsistsCommand($"{dirBase}/**/*"); + command.Validate(); + + var command2 = new FileExsistsCommand($"{dirBase}/foo/foo"); + command2.Validate(); + } +} \ No newline at end of file diff --git a/src/Actions.Tests/UpdateVersionCommand.cs b/src/Actions.Tests/UpdateVersionCommandTest.cs similarity index 91% rename from src/Actions.Tests/UpdateVersionCommand.cs rename to src/Actions.Tests/UpdateVersionCommandTest.cs index 96a95b7..3b53e10 100644 --- a/src/Actions.Tests/UpdateVersionCommand.cs +++ b/src/Actions.Tests/UpdateVersionCommandTest.cs @@ -9,7 +9,7 @@ public class UpdateVersionCommandTest public void UnityUpmTest() { var version = "1.0.0"; - var path = $"{nameof(UpdateVersionCommandTest)}/package.json"; + var path = $".tests/{nameof(UpdateVersionCommandTest)}{nameof(UnityUpmTest)}/package.json"; var contents = """ { "name": "com.unity.plugin.example", @@ -70,7 +70,7 @@ public void UnityUpmTest() public void GodotPluginTest() { var version = "1.0.0"; - var path = $"{nameof(GodotPluginTest)}/plugin.cfg"; + var path = $".tests/{nameof(UpdateVersionCommandTest)}/{nameof(GodotPluginTest)}/plugin.cfg"; var contents = """ [plugin] @@ -105,7 +105,7 @@ public void GodotPluginTest() public void DirectoryBuildPropsTest() { var version = "1.0.0"; - var path = $"{nameof(DirectoryBuildPropsTest)}/Directory.Build.props"; + var path = $".tests/{nameof(UpdateVersionCommandTest)}/{nameof(DirectoryBuildPropsTest)}/Directory.Build.props"; var contents = """ diff --git a/src/Actions/Commands/CreateDummyCommand.cs b/src/Actions/Commands/CreateDummyCommand.cs index 06431ef..dde7581 100644 --- a/src/Actions/Commands/CreateDummyCommand.cs +++ b/src/Actions/Commands/CreateDummyCommand.cs @@ -2,7 +2,13 @@ public class CreateDummyCommand { - public void CreateDummyFiles(string basePath) + public void CreateDummy(string basePath) + { + DummyVersionFiles(basePath); + DummyAssetFiles(Path.Combine(basePath, "downloads/")); + } + + private void DummyVersionFiles(string basePath) { var upm = ("package.json", """ { @@ -44,6 +50,7 @@ public void CreateDummyFiles(string basePath) """); + Console.WriteLine($"{nameof(DummyVersionFiles)}"); foreach (var (file, contents) in new[] { upm, godot, directoryBuildProps }) { var path = Path.Combine(basePath, file); @@ -54,4 +61,19 @@ public void CreateDummyFiles(string basePath) File.WriteAllText(path, contents); } } + + private void DummyAssetFiles(string basePath) + { + Console.WriteLine($"{nameof(DummyAssetFiles)}"); + var items = new[] { "foo", "bar", "piyo" }; + foreach (var item in items) + { + var path = Path.Combine(basePath, item); + if (!Directory.Exists(basePath)) + Directory.CreateDirectory(basePath); + + Console.WriteLine($"- {path} ..."); + File.WriteAllText(path, ""); + } + } } diff --git a/src/Actions/Commands/FileExsistsCommand.cs b/src/Actions/Commands/FileExsistsCommand.cs new file mode 100644 index 0000000..b55441e --- /dev/null +++ b/src/Actions/Commands/FileExsistsCommand.cs @@ -0,0 +1,95 @@ +namespace Actions.Commands; + +public class FileExsistsCommand(string pathPattern) +{ + public void Validate() + { + // do nothing for empty input + if (string.IsNullOrWhiteSpace(pathPattern)) + { + throw new ActionCommandException("Input path was empty."); + } + + // Handle glob path pattern. + // /foo/bar/**/* + // /foo/bar/*.txt + if (ContainsGlobPattern(pathPattern)) + { + if (!FileExistsWithGlob(pathPattern)) + { + throw new ActionCommandException(pathPattern, new FileNotFoundException(pathPattern)); + } + return; + } + + // Specified full path pattern... + // /foo/bar/piyo/poyo.txt + if (!File.Exists(pathPattern)) + { + throw new ActionCommandException(pathPattern, new FileNotFoundException(pathPattern)); + } + } + + private static bool ContainsGlobPattern(string pattern) => pattern.Contains('*') || pattern.Contains('?'); + private static bool FileExistsWithGlob(string pattern) + { + try + { + pattern = pattern.Replace("\\", "/"); + string directory = GetParentDirectoryPath(pattern) ?? Directory.GetCurrentDirectory(); + string searchPattern = Path.GetFileName(pattern); + + if (pattern.Contains("/**/")) + { + return Directory.EnumerateFiles(directory, searchPattern, SearchOption.AllDirectories).Any(); + } + if (pattern.Contains("*/")) + { + return EnumerateFileWildcard(pattern, searchPattern, SearchOption.AllDirectories).Any(); + } + else + { + return Directory.EnumerateFiles(directory, searchPattern, SearchOption.TopDirectoryOnly).Any(); + } + } + catch (Exception ex) + { + throw new ActionCommandException($"Error happen on checking file. Is specified path correct? path: {pattern}", ex); + } + } + + private static string GetParentDirectoryPath(string path) + { + var limit = 5; + var current = 0; + var dir = path; + var fileName = Path.GetFileName(dir); + var next = false; + do + { + dir = Path.GetDirectoryName(dir) ?? ""; + fileName = Path.GetFileName(dir); + current++; + if (current >= limit) + { + throw new ActionCommandException($"Recursively approaced parent directory but reached limit. {current}/{limit}"); + } + next = fileName == "**" || fileName == "*"; + } while (next); + + return dir; + } + + private static IEnumerable EnumerateFileWildcard(string path, string searchPattern, SearchOption searchOption) + { + var fileName = Path.GetFileName(path); + if (fileName == "*") + { + return Directory.GetDirectories(Path.GetDirectoryName(path)!).SelectMany(x => Directory.GetFiles(x, searchPattern, searchOption)); + } + else + { + return EnumerateFileWildcard(Path.GetDirectoryName(path)!, searchPattern, searchOption); + } + } +} diff --git a/src/Actions/Program.cs b/src/Actions/Program.cs index 18288b0..2cf68a0 100644 --- a/src/Actions/Program.cs +++ b/src/Actions/Program.cs @@ -58,6 +58,19 @@ public void UpdateVersion(string version, string path, bool dryRun) Console.WriteLine($"Completed ..."); } + /// + /// Validate specified path contains file + /// + /// + [Command("validate-file-exists")] + public void ValidateFileExists(string pathPattern) + { + Console.WriteLine($"Validating path, {pathPattern}"); + var command = new FileExsistsCommand(pathPattern); + command.Validate(); + Console.WriteLine($"Completed ..."); + } + /// /// Create dummy files /// @@ -68,7 +81,7 @@ public void CreateDummy(string basePath) Console.WriteLine($"Creating dummy files, under {basePath} ..."); var command = new CreateDummyCommand(); - command.CreateDummyFiles(basePath); + command.CreateDummy(basePath); Console.WriteLine($"Completed ..."); } @@ -83,7 +96,7 @@ public void CreateDummy(string basePath) }; } - public class ActionCommandException(string message) : Exception(message) + public class ActionCommandException(string message, Exception? innterException = null) : Exception(message, innterException) { } } \ No newline at end of file diff --git a/src/Actions/Properties/launchSettings.json b/src/Actions/Properties/launchSettings.json index 85ef9d6..8c71e71 100644 --- a/src/Actions/Properties/launchSettings.json +++ b/src/Actions/Properties/launchSettings.json @@ -46,6 +46,23 @@ "commandName": "Project", "commandLineArgs": "update-version --version 1.0.0 --path ./dummy/Directory.Build.props" }, + // validate-file-exsits + "validate-file-exsits (path: foo)": { + "commandName": "Project", + "commandLineArgs": "validate-file-exists --path-pattern ./dummy/downloads/foo" + }, + "validate-file-exsits (path: *)": { + "commandName": "Project", + "commandLineArgs": "validate-file-exists --path-pattern ./dummy/downloads/*" + }, + "validate-file-exsits (path: */foo)": { + "commandName": "Project", + "commandLineArgs": "validate-file-exists --path-pattern ./dummy/*/foo" + }, + "validate-file-exsits (path: **/foo)": { + "commandName": "Project", + "commandLineArgs": "validate-file-exists --path-pattern ./dummy/**/foo" + }, // create-dummy "create-dummy (help)": { "commandName": "Project", From 6abba7c94b07f2cc2b2bbe87c68843d2361ec10b Mon Sep 17 00:00:00 2001 From: Ikiru Yoshizaki <3856350+guitarrapc@users.noreply.github.com> Date: Tue, 17 Dec 2024 17:46:59 +0900 Subject: [PATCH 15/21] ci: replace Validate package Exists Bash to C# --- .github/workflows/create-release.yaml | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/.github/workflows/create-release.yaml b/.github/workflows/create-release.yaml index d1d3d73..23073e7 100644 --- a/.github/workflows/create-release.yaml +++ b/.github/workflows/create-release.yaml @@ -136,25 +136,7 @@ jobs: if: ${{ inputs.release-upload }} run: | while read -r asset_path; do - if [[ "${asset_path}" == "" ]]; then continue; fi - # is it a wildcard? - # shellcheck disable=SC2086 - if [[ "$asset_path" == *\** || "$asset_path" == *\?* ]]; then - # shellcheck disable=SC2086 - if ! ls -l ${asset_path}; then - echo "Specified nuget package not found. path: $asset_path" - if [[ "${asset_path}" == *.nupkg ]]; then - echo ".nupkg must be included in the artifact." - exit 1 - fi - fi - continue - fi - # is it a file? - if [[ ! -f "${asset_path}" ]]; then - echo "Specified asset not found. path: ${asset_path}" - exit 1 - fi + dotnet run --project "./src/Actions/Actions.csproj" -- validate-file-exists --path-pattern "$asset_path" done <<< "${{ inputs.release-asset-path }}" - name: Validate package exists in artifact - NuGet if: ${{ inputs.nuget-push }} From dd91016ad6f203263cc04aa2f0fa2418030c5c65 Mon Sep 17 00:00:00 2001 From: Ikiru Yoshizaki <3856350+guitarrapc@users.noreply.github.com> Date: Tue, 17 Dec 2024 18:54:23 +0900 Subject: [PATCH 16/21] chore: skip on empty input --- src/Actions.Tests/FileExistsCommandTest.cs | 4 ++-- src/Actions/Commands/FileExsistsCommand.cs | 4 +--- src/Actions/Program.cs | 1 + 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Actions.Tests/FileExistsCommandTest.cs b/src/Actions.Tests/FileExistsCommandTest.cs index 4616495..0b2c5a3 100644 --- a/src/Actions.Tests/FileExistsCommandTest.cs +++ b/src/Actions.Tests/FileExistsCommandTest.cs @@ -5,10 +5,10 @@ namespace Actions.Tests; public class FileExistsCommandTest { [Fact] - public void EmptyPathTest() + public void SkipEmptyPathTest() { var command = new FileExsistsCommand(""); - Assert.Throws(() => command.Validate()); + command.Validate(); } [Fact] diff --git a/src/Actions/Commands/FileExsistsCommand.cs b/src/Actions/Commands/FileExsistsCommand.cs index b55441e..e9ac56d 100644 --- a/src/Actions/Commands/FileExsistsCommand.cs +++ b/src/Actions/Commands/FileExsistsCommand.cs @@ -6,9 +6,7 @@ public void Validate() { // do nothing for empty input if (string.IsNullOrWhiteSpace(pathPattern)) - { - throw new ActionCommandException("Input path was empty."); - } + return; // Handle glob path pattern. // /foo/bar/**/* diff --git a/src/Actions/Program.cs b/src/Actions/Program.cs index 2cf68a0..3aa54fc 100644 --- a/src/Actions/Program.cs +++ b/src/Actions/Program.cs @@ -68,6 +68,7 @@ public void ValidateFileExists(string pathPattern) Console.WriteLine($"Validating path, {pathPattern}"); var command = new FileExsistsCommand(pathPattern); command.Validate(); + Console.WriteLine($"Completed ..."); } From b07f3f2b260aa40c82587e9432e232690fc5ca64 Mon Sep 17 00:00:00 2001 From: Ikiru Yoshizaki <3856350+guitarrapc@users.noreply.github.com> Date: Tue, 17 Dec 2024 19:15:23 +0900 Subject: [PATCH 17/21] chore: enable verbose --- src/Actions/Program.cs | 40 ++++++++++++++++++++++++--------- src/Actions/Utils/DebugTools.cs | 8 +++++++ 2 files changed, 37 insertions(+), 11 deletions(-) create mode 100644 src/Actions/Utils/DebugTools.cs diff --git a/src/Actions/Program.cs b/src/Actions/Program.cs index 3aa54fc..afe739d 100644 --- a/src/Actions/Program.cs +++ b/src/Actions/Program.cs @@ -13,6 +13,8 @@ public class ActionsBatch { #pragma warning disable CA1822 // Mark members as static + private bool _verbose; + /// Get version string from tag /// /// @@ -27,7 +29,7 @@ public void Versioning(string tag, string prefix = "", VersionIncrement versionI var versioning = command.Versioning(withoutPrefix); var output = OutputFormat("version", versioning, outputFormat); - Console.WriteLine(output); + WriteLog(output); } /// @@ -39,37 +41,40 @@ public void Versioning(string tag, string prefix = "", VersionIncrement versionI [Command("update-version")] public void UpdateVersion(string version, string path, bool dryRun) { - Console.WriteLine($"Update begin, {path} ..."); + WriteLog($"Update begin, {path} ..."); if (string.IsNullOrWhiteSpace(path)) { - Console.WriteLine("Empty path detected, skip execution."); + WriteLog("Empty path detected, skip execution."); return; } using (var githubGroup = new GitHubActionsGroupLogger("Before")) - Console.WriteLine(File.ReadAllText(path)); + WriteLog(File.ReadAllText(path)); var command = new UpdateVersionCommand(version, path); var result = command.UpdateVersion(dryRun); using (var githubGroup = new GitHubActionsGroupLogger("After")) - Console.WriteLine(result.After); + WriteLog(result.After); - Console.WriteLine($"Completed ..."); + WriteLog($"Completed ..."); } /// /// Validate specified path contains file /// /// + /// [Command("validate-file-exists")] - public void ValidateFileExists(string pathPattern) + public void ValidateFileExists(string pathPattern, bool verbose) { - Console.WriteLine($"Validating path, {pathPattern}"); + _verbose = verbose; + WriteLog($"Validating path, {pathPattern} ..."); + WriteVerbose($"UTF8: {DebugTools.ToUtf8Base64String(pathPattern)}"); var command = new FileExsistsCommand(pathPattern); command.Validate(); - Console.WriteLine($"Completed ..."); + WriteLog($"Completed ..."); } /// @@ -79,12 +84,12 @@ public void ValidateFileExists(string pathPattern) [Command("create-dummy")] public void CreateDummy(string basePath) { - Console.WriteLine($"Creating dummy files, under {basePath} ..."); + WriteLog($"Creating dummy files, under {basePath} ..."); var command = new CreateDummyCommand(); command.CreateDummy(basePath); - Console.WriteLine($"Completed ..."); + WriteLog($"Completed ..."); } #pragma warning restore CA1822 // Mark members as static @@ -95,6 +100,19 @@ public void CreateDummy(string basePath) OutputFormatType.GitHubActions => $"{key}={value}", _ => throw new NotImplementedException(nameof(format)), }; + + void WriteLog(string value) + { + Console.WriteLine($"[{DateTime.Now:s}] {value}"); + } + + void WriteVerbose(string value) + { + if (_verbose) + { + Console.WriteLine($"[{DateTime.Now:s}] {value}"); + } + } } public class ActionCommandException(string message, Exception? innterException = null) : Exception(message, innterException) diff --git a/src/Actions/Utils/DebugTools.cs b/src/Actions/Utils/DebugTools.cs new file mode 100644 index 0000000..5f4deb2 --- /dev/null +++ b/src/Actions/Utils/DebugTools.cs @@ -0,0 +1,8 @@ +using System.Text; + +namespace Actions.Utils; + +public static class DebugTools +{ + public static string ToUtf8Base64String(string input) => string.Join(" ", Encoding.UTF8.GetBytes(input).Select(b => b.ToString("X2"))); +} From 66d8d727772a71cf80d549b8abef0500489074ff Mon Sep 17 00:00:00 2001 From: Ikiru Yoshizaki <3856350+guitarrapc@users.noreply.github.com> Date: Tue, 17 Dec 2024 19:26:15 +0900 Subject: [PATCH 18/21] chore: skip --- src/Actions/Program.cs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/Actions/Program.cs b/src/Actions/Program.cs index afe739d..928a100 100644 --- a/src/Actions/Program.cs +++ b/src/Actions/Program.cs @@ -68,9 +68,16 @@ public void UpdateVersion(string version, string path, bool dryRun) [Command("validate-file-exists")] public void ValidateFileExists(string pathPattern, bool verbose) { - _verbose = verbose; + SetOptions(verbose); + WriteLog($"Validating path, {pathPattern} ..."); WriteVerbose($"UTF8: {DebugTools.ToUtf8Base64String(pathPattern)}"); + if (string.IsNullOrWhiteSpace(pathPattern)) + { + WriteLog("Empty path detected, skip execution."); + return; + } + var command = new FileExsistsCommand(pathPattern); command.Validate(); @@ -101,6 +108,11 @@ public void CreateDummy(string basePath) _ => throw new NotImplementedException(nameof(format)), }; + private void SetOptions(bool verbose) + { + _verbose = verbose; + } + void WriteLog(string value) { Console.WriteLine($"[{DateTime.Now:s}] {value}"); From a78cc8ad04d80fca2f5b08e6c0ad0b69f2118a2f Mon Sep 17 00:00:00 2001 From: Ikiru Yoshizaki <3856350+guitarrapc@users.noreply.github.com> Date: Tue, 17 Dec 2024 20:31:34 +0900 Subject: [PATCH 19/21] feat: add ValidateNupkhExists command --- src/Actions.Tests/FileExistsCommandTest.cs | 11 ++- src/Actions/Commands/CreateDummyCommand.cs | 2 +- src/Actions/Commands/FileExsistsCommand.cs | 85 ++++------------------ src/Actions/Program.cs | 30 ++++++++ src/Actions/Properties/launchSettings.json | 11 ++- src/Actions/Utils/GlobFiles.cs | 74 +++++++++++++++++++ 6 files changed, 137 insertions(+), 76 deletions(-) create mode 100644 src/Actions/Utils/GlobFiles.cs diff --git a/src/Actions.Tests/FileExistsCommandTest.cs b/src/Actions.Tests/FileExistsCommandTest.cs index 0b2c5a3..237d278 100644 --- a/src/Actions.Tests/FileExistsCommandTest.cs +++ b/src/Actions.Tests/FileExistsCommandTest.cs @@ -27,8 +27,9 @@ public void FullPathTest() public void WildcardFileTest() { var dir = $".tests/{nameof(FileExistsCommandTest)}/{nameof(WildcardFileTest)}"; - var items = new[] { "foo", "bar", "piyo" }; - foreach (var item in items) { + var items = new[] { "foo", "bar", "piyo", "test.txt", "hoge.txt" }; + foreach (var item in items) + { if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); File.WriteAllText(Path.Combine(dir, item), ""); } @@ -38,6 +39,12 @@ public void WildcardFileTest() var command2 = new FileExsistsCommand($"{dir}/foo"); command2.Validate(); + + var command3 = new FileExsistsCommand($"{dir}/*.txt"); + command3.Validate(); + + var command4 = new FileExsistsCommand($"{dir}/hoge.*"); + command4.Validate(); } [Fact] diff --git a/src/Actions/Commands/CreateDummyCommand.cs b/src/Actions/Commands/CreateDummyCommand.cs index dde7581..a437ac6 100644 --- a/src/Actions/Commands/CreateDummyCommand.cs +++ b/src/Actions/Commands/CreateDummyCommand.cs @@ -65,7 +65,7 @@ private void DummyVersionFiles(string basePath) private void DummyAssetFiles(string basePath) { Console.WriteLine($"{nameof(DummyAssetFiles)}"); - var items = new[] { "foo", "bar", "piyo" }; + var items = new[] { "foo", "bar", "piyo", "foo.nupkg", "bar.nupkg" }; foreach (var item in items) { var path = Path.Combine(basePath, item); diff --git a/src/Actions/Commands/FileExsistsCommand.cs b/src/Actions/Commands/FileExsistsCommand.cs index e9ac56d..8b5372d 100644 --- a/src/Actions/Commands/FileExsistsCommand.cs +++ b/src/Actions/Commands/FileExsistsCommand.cs @@ -1,6 +1,8 @@ -namespace Actions.Commands; +using Actions.Utils; -public class FileExsistsCommand(string pathPattern) +namespace Actions.Commands; + +public class FileExsistsCommand(string pathPattern, bool allowMissing = false) { public void Validate() { @@ -8,86 +10,29 @@ public void Validate() if (string.IsNullOrWhiteSpace(pathPattern)) return; + var pattern = GlobFiles.Normalize(pathPattern); + // Handle glob path pattern. // /foo/bar/**/* // /foo/bar/*.txt - if (ContainsGlobPattern(pathPattern)) + if (GlobFiles.IsGlobPattern(pattern)) { - if (!FileExistsWithGlob(pathPattern)) + if (!GlobFiles.Exists(pattern)) { - throw new ActionCommandException(pathPattern, new FileNotFoundException(pathPattern)); + // allow file not exists option + if (allowMissing) + return; + + throw new ActionCommandException(pattern, new FileNotFoundException(pathPattern)); } return; } // Specified full path pattern... // /foo/bar/piyo/poyo.txt - if (!File.Exists(pathPattern)) - { - throw new ActionCommandException(pathPattern, new FileNotFoundException(pathPattern)); - } - } - - private static bool ContainsGlobPattern(string pattern) => pattern.Contains('*') || pattern.Contains('?'); - private static bool FileExistsWithGlob(string pattern) - { - try - { - pattern = pattern.Replace("\\", "/"); - string directory = GetParentDirectoryPath(pattern) ?? Directory.GetCurrentDirectory(); - string searchPattern = Path.GetFileName(pattern); - - if (pattern.Contains("/**/")) - { - return Directory.EnumerateFiles(directory, searchPattern, SearchOption.AllDirectories).Any(); - } - if (pattern.Contains("*/")) - { - return EnumerateFileWildcard(pattern, searchPattern, SearchOption.AllDirectories).Any(); - } - else - { - return Directory.EnumerateFiles(directory, searchPattern, SearchOption.TopDirectoryOnly).Any(); - } - } - catch (Exception ex) - { - throw new ActionCommandException($"Error happen on checking file. Is specified path correct? path: {pattern}", ex); - } - } - - private static string GetParentDirectoryPath(string path) - { - var limit = 5; - var current = 0; - var dir = path; - var fileName = Path.GetFileName(dir); - var next = false; - do - { - dir = Path.GetDirectoryName(dir) ?? ""; - fileName = Path.GetFileName(dir); - current++; - if (current >= limit) - { - throw new ActionCommandException($"Recursively approaced parent directory but reached limit. {current}/{limit}"); - } - next = fileName == "**" || fileName == "*"; - } while (next); - - return dir; - } - - private static IEnumerable EnumerateFileWildcard(string path, string searchPattern, SearchOption searchOption) - { - var fileName = Path.GetFileName(path); - if (fileName == "*") - { - return Directory.GetDirectories(Path.GetDirectoryName(path)!).SelectMany(x => Directory.GetFiles(x, searchPattern, searchOption)); - } - else + if (!File.Exists(pattern)) { - return EnumerateFileWildcard(Path.GetDirectoryName(path)!, searchPattern, searchOption); + throw new ActionCommandException(pattern, new FileNotFoundException(pathPattern)); } } } diff --git a/src/Actions/Program.cs b/src/Actions/Program.cs index 928a100..d8588bc 100644 --- a/src/Actions/Program.cs +++ b/src/Actions/Program.cs @@ -84,6 +84,36 @@ public void ValidateFileExists(string pathPattern, bool verbose) WriteLog($"Completed ..."); } + /// + /// Validate specified path contains nuget packages + /// + /// + /// + [Command("validate-nupkg-exists")] + public void ValidateNupkgExists(string pathPattern, bool verbose) + { + SetOptions(verbose); + var fileName = Path.GetFileName(pathPattern); + var allowMissing = Path.GetExtension(fileName) == ".snupkg"; + + WriteLog($"Validating path, {pathPattern} ..."); + WriteVerbose($"UTF8: {DebugTools.ToUtf8Base64String(pathPattern)}"); + if (string.IsNullOrWhiteSpace(pathPattern)) + { + WriteLog("Empty path detected, skip execution."); + return; + } + if (allowMissing) + { + WriteLog(".snupkg detected, allow missing file."); + } + + var command = new FileExsistsCommand(pathPattern, allowMissing); + command.Validate(); + + WriteLog($"Completed ..."); + } + /// /// Create dummy files /// diff --git a/src/Actions/Properties/launchSettings.json b/src/Actions/Properties/launchSettings.json index 8c71e71..952772e 100644 --- a/src/Actions/Properties/launchSettings.json +++ b/src/Actions/Properties/launchSettings.json @@ -63,11 +63,16 @@ "commandName": "Project", "commandLineArgs": "validate-file-exists --path-pattern ./dummy/**/foo" }, - // create-dummy - "create-dummy (help)": { + // validate-nupkg-exsits + "validate-nupkg-exsits (path: *.nupkg)": { + "commandName": "Project", + "commandLineArgs": "validate-nupkg-exists --path-pattern ./dummy/downloads/*.nupkg" + }, + "validate-nupkg-exsits (path: *.snupkg)": { "commandName": "Project", - "commandLineArgs": "create-dummy --help" + "commandLineArgs": "validate-nupkg-exists --path-pattern ./dummy/downloads/*.snupkg" }, + // create-dummy "create-dummy (init)": { "commandName": "Project", "commandLineArgs": "create-dummy --base-path dummy/" diff --git a/src/Actions/Utils/GlobFiles.cs b/src/Actions/Utils/GlobFiles.cs new file mode 100644 index 0000000..a6cd525 --- /dev/null +++ b/src/Actions/Utils/GlobFiles.cs @@ -0,0 +1,74 @@ +namespace Actions.Utils; + +public static class GlobFiles +{ + public static bool IsGlobPattern(string pattern) => pattern.Contains('*') || pattern.Contains('?'); + public static bool Exists(string pattern) + { + try + { + var directory = GetParentDirectoryPath(pattern) ?? Directory.GetCurrentDirectory(); + var searchPattern = Path.GetFileName(pattern); + + if (pattern.Contains("/**/")) + { + return Directory.EnumerateFiles(directory, searchPattern, SearchOption.AllDirectories).Any(); + } + if (pattern.Contains("*/")) + { + return EnumerateFileWildcard(pattern, searchPattern, SearchOption.AllDirectories).Any(); + } + else + { + return Directory.EnumerateFiles(directory, searchPattern, SearchOption.TopDirectoryOnly).Any(); + } + } + catch (Exception ex) + { + throw new ActionCommandException($"Error happen on checking file. Is specified path correct? path: {pattern}", ex); + } + } + + /// + /// Normalize \r\n to \n + /// + /// + /// + public static string Normalize(string pattern) => pattern.Replace("\\", "/"); + + private static string GetParentDirectoryPath(string path) + { + var limit = 5; + var current = 0; + var dir = path; + var fileName = Path.GetFileName(dir); + var next = false; + do + { + dir = Path.GetDirectoryName(dir) ?? ""; + fileName = Path.GetFileName(dir); + current++; + if (current >= limit) + { + throw new ActionCommandException($"Recursively approaced parent directory but reached limit. {current}/{limit}"); + } + next = fileName == "**" || fileName == "*"; + } while (next); + + return dir; + } + + private static IEnumerable EnumerateFileWildcard(string path, string searchPattern, SearchOption searchOption) + { + var fileName = Path.GetFileName(path); + if (fileName == "*") + { + return Directory.GetDirectories(Path.GetDirectoryName(path)!).SelectMany(x => Directory.GetFiles(x, searchPattern, searchOption)); + } + else + { + return EnumerateFileWildcard(Path.GetDirectoryName(path)!, searchPattern, searchOption); + } + } + +} From ac59662ac99802e1811a90d2b0baabf833084d04 Mon Sep 17 00:00:00 2001 From: Ikiru Yoshizaki <3856350+guitarrapc@users.noreply.github.com> Date: Tue, 17 Dec 2024 20:33:21 +0900 Subject: [PATCH 20/21] ci: change validate nupkg from Bash to C# --- .github/workflows/create-release.yaml | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/.github/workflows/create-release.yaml b/.github/workflows/create-release.yaml index 23073e7..e71f522 100644 --- a/.github/workflows/create-release.yaml +++ b/.github/workflows/create-release.yaml @@ -142,15 +142,7 @@ jobs: if: ${{ inputs.nuget-push }} run: | while read -r nuget_path; do - if [[ "${nuget_path}" == "" ]]; then continue; fi - # shellcheck disable=SC2086 - if ! ls -l ${nuget_path}; then - echo "Specified nuget package not found. path: $nuget_path" - if [[ "${nuget_path}" == *.nupkg ]]; then - echo ".nupkg must be included in the artifact." - exit 1 - fi - fi + dotnet run --project "./src/Actions/Actions.csproj" -- validate-nupkg-exists --path-pattern "$nuget_path" done <<< "${{ inputs.nuget-path }}" # Create Releases From 64dd52c713a49d84b0806b1224d1c901bf739451 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 18 Dec 2024 07:56:03 +0000 Subject: [PATCH 21/21] feat: Update package.json to 1.2.327 Commit by [GitHub Actions](https://github.com/Cysharp/Actions/actions/runs/12388648941) --- Sandbox/Directory.Build.props | 2 +- Sandbox/Sandbox.Godot/addons/Foo/plugin.cfg | 2 +- Sandbox/Sandbox.Unity/Assets/Plugins/Foo.Plugin/package.json | 2 +- Sandbox/Sandbox.Unity/Assets/Plugins/Foo/package.json | 2 +- Sandbox/VersionOutput/version.txt | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Sandbox/Directory.Build.props b/Sandbox/Directory.Build.props index a3de16d..8c0104a 100644 --- a/Sandbox/Directory.Build.props +++ b/Sandbox/Directory.Build.props @@ -1,5 +1,5 @@ - 1.2.317 + 1.2.327 diff --git a/Sandbox/Sandbox.Godot/addons/Foo/plugin.cfg b/Sandbox/Sandbox.Godot/addons/Foo/plugin.cfg index 7e6b0c2..782f91d 100644 --- a/Sandbox/Sandbox.Godot/addons/Foo/plugin.cfg +++ b/Sandbox/Sandbox.Godot/addons/Foo/plugin.cfg @@ -3,6 +3,6 @@ name="Sandbox.Godot" description="Sample." author="Cysharp" -version="1.2.317" +version="1.2.327" language="C-sharp" script="GodotPlugin.cs" diff --git a/Sandbox/Sandbox.Unity/Assets/Plugins/Foo.Plugin/package.json b/Sandbox/Sandbox.Unity/Assets/Plugins/Foo.Plugin/package.json index 5312b8a..ad84464 100644 --- a/Sandbox/Sandbox.Unity/Assets/Plugins/Foo.Plugin/package.json +++ b/Sandbox/Sandbox.Unity/Assets/Plugins/Foo.Plugin/package.json @@ -1,6 +1,6 @@ { "name": "com.unity.plugin.example", - "version": "1.2.317", + "version": "1.2.327", "displayName": "Package Example Plugin", "description": "This is an example package", "unity": "2019.1", diff --git a/Sandbox/Sandbox.Unity/Assets/Plugins/Foo/package.json b/Sandbox/Sandbox.Unity/Assets/Plugins/Foo/package.json index 0c99daf..ce44d51 100644 --- a/Sandbox/Sandbox.Unity/Assets/Plugins/Foo/package.json +++ b/Sandbox/Sandbox.Unity/Assets/Plugins/Foo/package.json @@ -1,6 +1,6 @@ { "name": "com.unity.example", - "version": "1.2.317", + "version": "1.2.327", "displayName": "Package Example", "description": "This is an example package", "unity": "2019.1", diff --git a/Sandbox/VersionOutput/version.txt b/Sandbox/VersionOutput/version.txt index 1ee8930..b33a052 100644 --- a/Sandbox/VersionOutput/version.txt +++ b/Sandbox/VersionOutput/version.txt @@ -1 +1 @@ -1.2.317 \ No newline at end of file +1.2.327 \ No newline at end of file