Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ If you have multiple kickflip flows in the same workflow (for example deploying
kickflip github pull-request --repo <owner>/<repo> --ref <ref> --token <token> --action-name staging
kickflip github pull-request --repo <owner>/<repo> --ref <ref> --token <token> --action-name production

When running inside GitHub Actions, kickflip also writes the deployment change summary to the [job summary](https://github.blog/2022-05-09-supercharging-github-actions-with-job-summaries/) so it appears on the workflow run page. This happens automatically whenever the `GITHUB_STEP_SUMMARY` environment variable is present (which GitHub Actions sets for every step), in addition to posting the pull request comment.

## Github Actions

Github Actions `actions/checkout@v4` by default performs a shallow clone of the repo. In order for kickflip to work out all the changes it requires that a full clone be made. This can be achieve by:
Expand Down
6 changes: 6 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

71 changes: 71 additions & 0 deletions src/kickflip.Tests/GithubJobSummaryServiceTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
using kickflip.Services;

namespace kickflip.Tests;

public class GithubJobSummaryServiceTests
{
[Fact]
public void IsAvailable_ReturnsFalse_WhenPathIsNullOrEmpty()
{
Assert.False(new GithubJobSummaryService(null).IsAvailable);
Assert.False(new GithubJobSummaryService("").IsAvailable);
Assert.False(new GithubJobSummaryService(" ").IsAvailable);
}

[Fact]
public void IsAvailable_ReturnsTrue_WhenPathProvided()
{
Assert.True(new GithubJobSummaryService("/tmp/summary.md").IsAvailable);
}

[Fact]
public async Task AppendSummaryAsync_WritesContentToFile()
{
var path = Path.GetTempFileName();
try
{
var service = new GithubJobSummaryService(path);
var result = await service.AppendSummaryAsync("## Hello\ncontent");

Assert.True(result);
var written = await File.ReadAllTextAsync(path);
Assert.Contains("## Hello", written);
Assert.Contains("content", written);
}
finally
{
File.Delete(path);
}
}

[Fact]
public async Task AppendSummaryAsync_AppendsToExistingContent()
{
var path = Path.GetTempFileName();
try
{
await File.WriteAllTextAsync(path, "existing\n");

var service = new GithubJobSummaryService(path);
await service.AppendSummaryAsync("added");

var written = await File.ReadAllTextAsync(path);
Assert.Contains("existing", written);
Assert.Contains("added", written);
Assert.True(written.IndexOf("existing", StringComparison.Ordinal) <
written.IndexOf("added", StringComparison.Ordinal));
}
finally
{
File.Delete(path);
}
}

[Fact]
public async Task AppendSummaryAsync_ReturnsFalse_WhenNotAvailable()
{
var service = new GithubJobSummaryService(null);
var result = await service.AppendSummaryAsync("content");
Assert.False(result);
}
}
7 changes: 7 additions & 0 deletions src/kickflip/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,13 @@ private static async Task<int> HandleGithubPullRequest(string localPath, FindMod
}

Console.WriteLine("Github Pull Request Comment Successful!");

var jobSummaryService = new GithubJobSummaryService(Environment.GetEnvironmentVariable("GITHUB_STEP_SUMMARY"));
if (await jobSummaryService.AppendSummaryAsync(sectionContent))
{
Console.WriteLine("Github Job Summary updated!");
}

return (int) ExitCodes.Success;
}
}
Expand Down
40 changes: 40 additions & 0 deletions src/kickflip/Services/GithubJobSummaryService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
namespace kickflip.Services;

/// <summary>
/// Writes deployment change summaries to the GitHub Actions job summary.
/// GitHub Actions exposes the summary as a file via the GITHUB_STEP_SUMMARY
/// environment variable. Anything appended to that file (as markdown) is
/// rendered on the workflow run's summary page.
/// See https://github.blog/2022-05-09-supercharging-github-actions-with-job-summaries/
/// </summary>
public class GithubJobSummaryService
{
private readonly string? _summaryFilePath;

public GithubJobSummaryService(string? summaryFilePath)
{
_summaryFilePath = summaryFilePath;
}

/// <summary>
/// Whether a job summary file is available to write to. This is only the
/// case when running inside GitHub Actions.
/// </summary>
public bool IsAvailable => !string.IsNullOrWhiteSpace(_summaryFilePath);

/// <summary>
/// Appends the given markdown content to the GitHub Actions job summary.
/// Returns false when no job summary is available (i.e. not running in
/// GitHub Actions).
/// </summary>
public async Task<bool> AppendSummaryAsync(string content)
{
if (!IsAvailable)
{
return false;
}

await File.AppendAllTextAsync(_summaryFilePath!, content + Environment.NewLine);
return true;
}
}
Loading