Skip to content

Commit

Permalink
feat: add CreateRelease
Browse files Browse the repository at this point in the history
  • Loading branch information
guitarrapc committed Jan 15, 2025
1 parent 174f772 commit 7fecf9c
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 40 deletions.
38 changes: 5 additions & 33 deletions .github/workflows/create-release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,6 @@ jobs:
with:
ref: ${{ inputs.commit-id }}
- uses: Cysharp/Actions/.github/actions/setup-dotnet@main
if: ${{ inputs.nuget-push }}

# validate
- name: Validate and normalize tag
Expand All @@ -144,39 +143,12 @@ jobs:
run: dotnet run --project "./src/Actions/Actions.csproj" --no-launch-profile -- validate-nupkg-exists --path-pattern-string "${{ inputs.nuget-path }}"

# Create Releases
- name: Create Tag
run: |
git tag ${{ inputs.tag }}
git push origin ${{ inputs.tag }}
- name: Create Release
run: gh release create ${{ inputs.tag }} --draft --verify-tag --title "${{ format(inputs.release-format, inputs.tag) }}" --generate-notes
- name: Wait and Verify Release Name is expected
run: |
sleep 5s
actual=$(gh api --paginate /repos/${{ github.repository }}/releases?per_page=100 --jq '.[] | select(.tag_name == "${{ inputs.tag }}") | .name')
expected="${{ format(inputs.release-format, inputs.tag) }}"
if [[ "$actual" != "$expected" ]]; then
echo "Release name is not as expected. expected: $expected, actual: $actual"
exit 1
else
echo "Release name is expected! expected: $expected, actual: $actual"
fi
- name: Upload asset files to release
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
for file in ${asset_path}; do
gh release upload ${{ inputs.tag }} "${file}"
done
continue
fi
# is it a file?
gh release upload ${{ inputs.tag }} "${asset_path}"
done <<< "${{ inputs.release-asset-path }}"
if: ${{ inputs.release-upload }}
run: dotnet run --project "./src/Actions/Actions.csproj" --no-launch-profile -- create-release --tag "${{ inputs.tag }}" --release-title "${{ format(inputs.release-format, inputs.tag) }}" --release-asset-path-string "${{ inputs.release-asset-path }}"
env:
GH_REPO: ${{ github.repository }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_CONTEXT: ${{ toJson(github) }}

# Upload to NuGet
- name: Upload to NuGet (DryRun=${{ inputs.dry-run }})
Expand Down
68 changes: 68 additions & 0 deletions src/Actions.Tests/CreateReleaseCommandTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
using Actions.Commands;
using Zx;

namespace Actions.Tests;

public class CreateReleaseCommandTest
{
[Theory]
[InlineData("test.0.1.0", "Ver.test.0.1.0")]
[InlineData("test.1.0.0", "Ver.test.1.0.0")]
[InlineData("test.10.1.0", "Ver.test.10.1.0")]
public async Task ReleaseTest(string tag, string releaseTitle)
{
if (Environment.GetEnvironmentVariable("CI") is null)
return;
if (Environment.GetEnvironmentVariable("GH_REPO") is null)
throw new Exception("GH_REPO is not set");
if (Environment.GetEnvironmentVariable("GH_TOKEN") is null)
throw new Exception("GH_TOKEN is not set");

var dir = Path.Combine(Path.GetTempPath(), nameof(ReleaseTest));
var files = Enumerable.Range(0, 3)
.Select(x => Path.Combine(dir, Path.GetTempFileName()))
.ToArray();
try
{
CreateFiles(dir, files);
var command = new CreateReleaseCommand(tag, releaseTitle);
await command.CreateReleaseAsync();
await command.UploadAssetFiles(files);
}
finally
{
SafeDeleteDir(dir);

// clean up release
var list = await $"gh release list";
var exists = SplitByNewLine(list)
.Where(x => x.Contains("Draft"))
.Where(x => x.Contains("Ver.1.1.0"))
.Any();
if (exists)
{
await $"gh release delete {tag} --yes --cleanup-tag";
}
}
}

private static string[] SplitByNewLine(string stringsValue) => stringsValue.Split(["\r\n", "\n"], StringSplitOptions.RemoveEmptyEntries);

private void CreateFiles(string dir, string[] files)
{
if (!Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
foreach (var file in files)
{
File.WriteAllText(file, "");
}
}
}

private void SafeDeleteDir(string dir)
{
if (Directory.Exists(dir))
Directory.Delete(dir);
}
}
58 changes: 58 additions & 0 deletions src/Actions/Commands/CreateReleaseCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
using Actions.Utils;
using static Actions.Utils.ZxHelper;

namespace Actions.Commands;

public class CreateReleaseCommand(string tag, string releaseTitle)
{
/// <summary>
/// Create GitHub Release
/// </summary>
/// <returns></returns>
/// <exception cref="ActionCommandException"></exception>
public async Task CreateReleaseAsync()
{
// git tag
using (_ = new GitHubActionsGroupLogger("Create git tag"))
{
await $"git tag {tag}";
await $"git push origin {tag}";
}

// create release
using (_ = new GitHubActionsGroupLogger("Create Release"))
{
await $"gh release create {tag} --draft --verify-tag --title \"{releaseTitle}\" --generate-notes";
// wait a while
await Task.Delay(TimeSpan.FromSeconds(5));
}
}

/// <summary>
/// Upload asset files to the release
/// </summary>
/// <param name="tag"></param>
/// <param name="assetPaths"></param>
/// <returns></returns>
public async Task UploadAssetFiles(string[] assetPaths)
{
foreach (var assetPath in assetPaths)
{
if (GlobFiles.IsGlobPattern(assetPath))
{
// Is Wildcard?
foreach (var file in GlobFiles.EnumerateFiles(assetPath))
{
using var _ = new GitHubActionsGroupLogger($"Uploading asset. tag: {tag}. assetPath: {file}");
await $"gh release upload {tag} \"{EscapeArg(file)}\"";
}
}
else
{
// Is File?
using var _ = new GitHubActionsGroupLogger($"Uploading asset. tag: {tag}. assetPath: {assetPath}");
await $"gh release upload {tag} \"{EscapeArg(assetPath)}\"";
}
}
}
}
13 changes: 8 additions & 5 deletions src/Actions/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -158,16 +158,20 @@ public void ValidateNupkgExists(string pathPatternString)
/// <param name="releaseTitle">Release title</param>
/// <param name="releaseAssetPathString">Release assets to upload</param>
[ConsoleAppFilter<GitHubContextFilter>]
[ConsoleAppFilter<GitHubCliFilter>]
[Command("create-release")]
public async void CreateRelease(string tag, string releaseTitle, string releaseAssetPathString)
public async Task CreateRelease(string tag, string releaseTitle, string releaseAssetPathString)
{
var releaseAssets = SplitByNewLine(releaseAssetPathString);

var command = new CreateReleaseCommand(tag, releaseTitle);
await command.CreateReleaseAsync();

WriteLog($"Uploading assets ...");
await command.UploadAssetFiles(tag, releaseAssets);
if (releaseAssets.Length > 0)
{
WriteLog($"Uploading assets ...");
await command.UploadAssetFiles(releaseAssets);
}

WriteLog($"Completed ...");
}
Expand All @@ -177,7 +181,7 @@ public async void CreateRelease(string tag, string releaseTitle, string releaseA
/// </summary>
/// <param name="basePath"></param>
[Command("create-dummy")]
public void CreateDummy(string basePath)
public async Task CreateDummy(string basePath)
{
WriteLog($"Creating dummy files, under {basePath} ...");

Expand Down Expand Up @@ -248,7 +252,6 @@ public void Debug(string[] foo)
_ => throw new NotImplementedException(nameof(format)),
};

private static string[] SplitByNewLine(string stringsValue) => stringsValue.Split(["\r\n", "\n"], StringSplitOptions.RemoveEmptyEntries);
private static void WriteLog(string value) => Console.WriteLine($"[{DateTime.Now:s}] {value}");
private static void WriteError(string value) => Console.WriteLine($"[{DateTime.Now:s}] ERROR: {value}");

Expand Down
16 changes: 14 additions & 2 deletions src/Actions/Properties/launchSettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@
"commandName": "Project",
"commandLineArgs": "--help"
},
// create-release
"create-release (help)": {
"commandName": "Project",
"commandLineArgs": "create-release --help"
},
"create-release (1.3.0)": {
"commandName": "Project",
"commandLineArgs": "create-release --tag 1.3.0 --release-title \"Ver.1.3.0\" --release-asset-path-string \"\"",
"environmentVariables": {
"GITHUB_CONTEXT": "{\"server_url\":\"https://github.com\", \"run_id\":\"11350100787\", \"repository\":\"Cysharp/Actions\", \"repository_owner\":\"Cysharp\", \"event_name\": \"pull_request\"}"
}
},
// validate-tag
"validate-tag (help)": {
"commandName": "Project",
Expand Down Expand Up @@ -47,7 +59,7 @@
"commandName": "Project",
"commandLineArgs": "update-version --version 1.0.0 --path-string \"./dummy/package.json\\n./dummy/plugin.cfg\\n./dummy/Directory.Build.props\"",
"environmentVariables": {
"GITHUB_CONTEXT": "{\"server_url\":\"https://github.com\", \"run_id\":\"11350100787\", \"repository\":\"Actions\", \"repository_owner\":\"Cysharp\", \"event_name\": \"pull_request\"}"
"GITHUB_CONTEXT": "{\"server_url\":\"https://github.com\", \"run_id\":\"11350100787\", \"repository\":\"Cysharp/Actions\", \"repository_owner\":\"Cysharp\", \"event_name\": \"pull_request\"}"
}
},
// validate-nupkg-exsits
Expand Down Expand Up @@ -94,7 +106,7 @@
"distributionName": "",
"commandLineArgs": "\"{OutDir}/Actions.dll\" update-version --version 1.0.0 --path-string \"./dummy/package.json\n./dummy/plugin.cfg\n./dummy/Directory.Build.props\"",
"environmentVariables": {
"GITHUB_CONTEXT": "{\"server_url\":\"https://github.com\", \"run_id\":\"11350100787\", \"repository\":\"Actions\", \"repository_owner\":\"Cysharp\", \"event_name\": \"pull_request\"}"
"GITHUB_CONTEXT": "{\"server_url\":\"https://github.com\", \"run_id\":\"11350100787\", \"repository\":\"Cysharp/Actions\", \"repository_owner\":\"Cysharp\", \"event_name\": \"pull_request\"}"
}
},
"WSL (debug)": {
Expand Down
2 changes: 2 additions & 0 deletions src/Actions/Utils/ZxHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@ public static string EscapeArg(string command)
return "\"" + command + "\"";
}

public static string[] SplitByNewLine(string stringsValue) => stringsValue.Split(["\r\n", "\n"], StringSplitOptions.RemoveEmptyEntries);

}

0 comments on commit 7fecf9c

Please sign in to comment.