-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Loading status checks…
chore: add back src
1 parent
154fe49
commit 48007f7
Showing
17 changed files
with
1,182 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net8.0</TargetFramework> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<Nullable>enable</Nullable> | ||
|
||
<IsPackable>false</IsPackable> | ||
<IsTestProject>true</IsTestProject> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="coverlet.collector" Version="6.0.2"> | ||
<PrivateAssets>all</PrivateAssets> | ||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||
</PackageReference> | ||
<PackageReference Include="FluentAssertions" Version="7.0.0" /> | ||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" /> | ||
<PackageReference Include="xunit" Version="2.9.2" /> | ||
<PackageReference Include="xunit.runner.visualstudio" Version="3.0.0"> | ||
<PrivateAssets>all</PrivateAssets> | ||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||
</PackageReference> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\Actions\Actions.csproj" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<Using Include="Xunit" /> | ||
</ItemGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
using Actions.Commands; | ||
|
||
namespace Actions.Tests; | ||
|
||
public class FileExistsCommandTest | ||
{ | ||
[Fact] | ||
public void SkipEmptyPathTest() | ||
{ | ||
var command = new FileExsistsCommand(""); | ||
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", "test.txt", "hoge.txt" }; | ||
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(); | ||
|
||
var command3 = new FileExsistsCommand($"{dir}/*.txt"); | ||
command3.Validate(); | ||
|
||
var command4 = new FileExsistsCommand($"{dir}/hoge.*"); | ||
command4.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<ActionCommandException>(() => 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(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
using Actions.Commands; | ||
using FluentAssertions; | ||
|
||
namespace Actions.Tests; | ||
|
||
public class UpdateVersionCommandTest | ||
{ | ||
[Fact] | ||
public void UnityUpmTest() | ||
{ | ||
var version = "1.0.0"; | ||
var path = $".tests/{nameof(UpdateVersionCommandTest)}{nameof(UnityUpmTest)}/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": "[email protected]", | ||
"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": "[email protected]", | ||
"url": "https://www.unity3d.com" | ||
} | ||
} | ||
"""); | ||
} | ||
|
||
[Fact] | ||
public void GodotPluginTest() | ||
{ | ||
var version = "1.0.0"; | ||
var path = $".tests/{nameof(UpdateVersionCommandTest)}/{nameof(GodotPluginTest)}/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 DirectoryBuildPropsTest() | ||
{ | ||
var version = "1.0.0"; | ||
var path = $".tests/{nameof(UpdateVersionCommandTest)}/{nameof(DirectoryBuildPropsTest)}/Directory.Build.props"; | ||
var contents = """ | ||
<Project> | ||
<PropertyGroup> | ||
<VersionPrefix>1.2.310</VersionPrefix> | ||
</PropertyGroup> | ||
</Project> | ||
"""; | ||
|
||
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(""" | ||
<Project> | ||
<PropertyGroup> | ||
<VersionPrefix>1.0.0</VersionPrefix> | ||
</PropertyGroup> | ||
</Project> | ||
"""); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
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"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
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); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<OutputType>Exe</OutputType> | ||
<TargetFramework>net8.0</TargetFramework> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<Nullable>enable</Nullable> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="ConsoleAppFramework" Version="5.3.0"> | ||
<PrivateAssets>all</PrivateAssets> | ||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||
</PackageReference> | ||
</ItemGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
namespace Actions.Commands; | ||
|
||
public class CreateDummyCommand | ||
{ | ||
public void CreateDummy(string basePath) | ||
{ | ||
DummyVersionFiles(basePath); | ||
DummyAssetFiles(Path.Combine(basePath, "downloads/")); | ||
} | ||
|
||
private void DummyVersionFiles(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", """ | ||
<Project> | ||
<PropertyGroup> | ||
<VersionPrefix>1.2.310</VersionPrefix> | ||
</PropertyGroup> | ||
</Project> | ||
"""); | ||
|
||
Console.WriteLine($"{nameof(DummyVersionFiles)}"); | ||
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); | ||
} | ||
} | ||
|
||
private void DummyAssetFiles(string basePath) | ||
{ | ||
Console.WriteLine($"{nameof(DummyAssetFiles)}"); | ||
var items = new[] { "foo", "bar", "piyo", "foo.nupkg", "bar.nupkg" }; | ||
foreach (var item in items) | ||
{ | ||
var path = Path.Combine(basePath, item); | ||
if (!Directory.Exists(basePath)) | ||
Directory.CreateDirectory(basePath); | ||
|
||
Console.WriteLine($"- {path} ..."); | ||
File.WriteAllText(path, ""); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
using Actions.Utils; | ||
|
||
namespace Actions.Commands; | ||
|
||
public class FileExsistsCommand(string pathPattern, bool allowMissing = false) | ||
{ | ||
public void Validate() | ||
{ | ||
// do nothing for empty input | ||
if (string.IsNullOrWhiteSpace(pathPattern)) | ||
return; | ||
|
||
var pattern = GlobFiles.Normalize(pathPattern); | ||
|
||
// Handle glob path pattern. | ||
// /foo/bar/**/* | ||
// /foo/bar/*.txt | ||
if (GlobFiles.IsGlobPattern(pattern)) | ||
{ | ||
if (!GlobFiles.Exists(pattern)) | ||
{ | ||
// 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(pattern)) | ||
{ | ||
throw new ActionCommandException(pattern, new FileNotFoundException(pathPattern)); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
using Actions.Utils; | ||
using System.Text.Json; | ||
using System.Text.Json.Serialization; | ||
|
||
namespace Actions.Commands; | ||
|
||
public record struct UpdateVersionCommandResult(string Before, string After); | ||
public class UpdateVersionCommand(string version, string path) | ||
{ | ||
public UpdateVersionCommandResult UpdateVersion(bool dryRun) | ||
{ | ||
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) | ||
{ | ||
// replace | ||
var (before, after) = Sed.Replace(path, @"""version"":\s*""(.*?)""", $@"""version"": ""{version}""", writeBack); | ||
|
||
// validate | ||
Validate(after, version); | ||
|
||
return new UpdateVersionCommandResult(before, after); | ||
|
||
static void Validate(string contents, string version) | ||
{ | ||
var packageJson = JsonSerializer.Deserialize<UpmPackageJson>(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 UpdateVersionCommandResult HandleGodot(bool writeBack) | ||
{ | ||
// replace | ||
var (before, after) = Sed.Replace(path, @"(version=)""(.*?)""", $@"$1""{version}""", writeBack); | ||
|
||
// validate | ||
Validate(after, version); | ||
|
||
return new UpdateVersionCommandResult(before, after); | ||
|
||
static void Validate(string contents, string version) | ||
{ | ||
var lines = contents.Split("\n"); | ||
Span<Range> 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 UpdateVersionCommandResult HandleDirectoryBuildProps(bool writeBack) | ||
{ | ||
// replace | ||
var (before, after) = Sed.Replace(path, @"<VersionPrefix>.*</VersionPrefix>", $@"<VersionPrefix>{version}</VersionPrefix>", writeBack); | ||
|
||
// validate | ||
Validate(after, version); | ||
|
||
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}"); | ||
|
||
} | ||
} | ||
|
||
private record UpmPackageJson | ||
{ | ||
[JsonPropertyName("version")] | ||
public required string Version { get; set; } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
namespace Actions.Commands; | ||
|
||
public class VersioningCommand(string tag, string prefix, VersionIncrement versionIncrement, bool isPrelease, string prerelease) | ||
{ | ||
/// <summary> | ||
/// Handling versioning | ||
/// </summary> | ||
/// <returns></returns> | ||
public string Versioning(bool withoutPrefix = false) | ||
{ | ||
var version = GetNormalizedVersion(tag, prefix); | ||
var increment = IncrementVersion(version, versionIncrement); | ||
var format = FormatVersion(increment, prefix, isPrelease, prerelease, withoutPrefix); | ||
return format; | ||
} | ||
|
||
/// <summary> | ||
/// Normalize tag. Tag may contains prefix, remove prefix and retrun version. | ||
/// </summary> | ||
/// <param name="tag"></param> | ||
/// <param name="prefix"></param> | ||
/// <returns></returns> | ||
/// <exception cref="ActionCommandException"></exception> | ||
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); | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Increment version for specific place | ||
/// </summary> | ||
/// <param name="version"></param> | ||
/// <param name="versionIncrement"></param> | ||
/// <returns></returns> | ||
/// <exception cref="NotImplementedException"></exception> | ||
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)), | ||
}; | ||
|
||
/// <summary> | ||
/// Format version | ||
/// </summary> | ||
/// <param name="version"></param> | ||
/// <param name="prefix"></param> | ||
/// <param name="isPrelease"></param> | ||
/// <param name="prerelease"></param> | ||
/// <returns></returns> | ||
private static string FormatVersion(Version version, string prefix, bool isPrelease, string prerelease, bool withoutPrefix) | ||
{ | ||
var preReleaseSuffix = isPrelease && prerelease != "" ? $"-{prerelease}" : ""; | ||
return withoutPrefix ? $"{version}{preReleaseSuffix}" : $"{prefix}{version}{preReleaseSuffix}"; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
using Actions; | ||
using Actions.Commands; | ||
using Actions.Utils; | ||
using ConsoleAppFramework; | ||
|
||
var app = ConsoleApp.Create(); | ||
app.Add<ActionsBatch>(); | ||
app.Run(args); | ||
|
||
namespace Actions | ||
{ | ||
public class ActionsBatch | ||
{ | ||
#pragma warning disable CA1822 // Mark members as static | ||
|
||
private bool _verbose; | ||
|
||
/// <summary>Get version string from tag</summary> | ||
/// <param name="tag"></param> | ||
/// <param name="prefix"></param> | ||
/// <param name="versionIncrement"></param> | ||
/// <param name="isPrelease"></param> | ||
/// <param name="prerelease"></param> | ||
/// <param name="outputFormat"></param> | ||
[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); | ||
WriteLog(output); | ||
} | ||
|
||
/// <summary> | ||
/// Update Version for specified path | ||
/// </summary> | ||
/// <param name="version"></param> | ||
/// <param name="path"></param> | ||
/// <param name="dryRun"></param> | ||
[Command("update-version")] | ||
public void UpdateVersion(string version, string path, bool dryRun) | ||
{ | ||
WriteLog($"Update begin, {path} ..."); | ||
if (string.IsNullOrWhiteSpace(path)) | ||
{ | ||
WriteLog("Empty path detected, skip execution."); | ||
return; | ||
} | ||
|
||
using (var githubGroup = new GitHubActionsGroupLogger("Before")) | ||
WriteLog(File.ReadAllText(path)); | ||
|
||
var command = new UpdateVersionCommand(version, path); | ||
var result = command.UpdateVersion(dryRun); | ||
|
||
using (var githubGroup = new GitHubActionsGroupLogger("After")) | ||
WriteLog(result.After); | ||
|
||
WriteLog($"Completed ..."); | ||
} | ||
|
||
/// <summary> | ||
/// Validate specified path contains file | ||
/// </summary> | ||
/// <param name="pathPattern"></param> | ||
/// <param name="verbose"></param> | ||
[Command("validate-file-exists")] | ||
public void ValidateFileExists(string pathPattern, bool 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(); | ||
|
||
WriteLog($"Completed ..."); | ||
} | ||
|
||
/// <summary> | ||
/// Validate specified path contains nuget packages | ||
/// </summary> | ||
/// <param name="pathPattern"></param> | ||
/// <param name="verbose"></param> | ||
[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 ..."); | ||
} | ||
|
||
/// <summary> | ||
/// Create dummy files | ||
/// </summary> | ||
/// <param name="basePath"></param> | ||
[Command("create-dummy")] | ||
public void CreateDummy(string basePath) | ||
{ | ||
WriteLog($"Creating dummy files, under {basePath} ..."); | ||
|
||
var command = new CreateDummyCommand(); | ||
command.CreateDummy(basePath); | ||
|
||
WriteLog($"Completed ..."); | ||
} | ||
|
||
#pragma warning restore CA1822 // Mark members as static | ||
|
||
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 void SetOptions(bool verbose) | ||
{ | ||
_verbose = verbose; | ||
} | ||
|
||
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) | ||
{ | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
{ | ||
"profiles": { | ||
"help": { | ||
"commandName": "Project", | ||
"commandLineArgs": "--help" | ||
}, | ||
// versioning | ||
"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" | ||
}, | ||
// 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" | ||
}, | ||
// 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" | ||
}, | ||
// 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": "validate-nupkg-exists --path-pattern ./dummy/downloads/*.snupkg" | ||
}, | ||
// create-dummy | ||
"create-dummy (init)": { | ||
"commandName": "Project", | ||
"commandLineArgs": "create-dummy --base-path dummy/" | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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"))); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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::"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Normalize \r\n to \n | ||
/// </summary> | ||
/// <param name="pattern"></param> | ||
/// <returns></returns> | ||
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<string> 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); | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
using System.Text.RegularExpressions; | ||
|
||
namespace Actions.Utils; | ||
|
||
public static class Sed | ||
{ | ||
/// <summary> | ||
/// Replace file contents with pattern and replacement. | ||
/// </summary> | ||
/// <param name="path"></param> | ||
/// <param name="pattern"></param> | ||
/// <param name="replacement"></param> | ||
/// <param name="writeBack"></param> | ||
/// <returns></returns> | ||
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; | ||
} | ||
|
||
/// <summary> | ||
/// Replace contents with pattern and replacement. | ||
/// </summary> | ||
/// <param name="input"></param> | ||
/// <param name="pattern"></param> | ||
/// <param name="replacement"></param> | ||
/// <returns></returns> | ||
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); | ||
} | ||
} |