Skip to content

Commit

Permalink
Merge branch 'release/v0.8.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
justinyoo committed Feb 3, 2020
2 parents 8a02b56 + 76b6985 commit dd5e839
Show file tree
Hide file tree
Showing 11 changed files with 765 additions and 54 deletions.
34 changes: 31 additions & 3 deletions .github/workflows/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,46 @@ on:
push:
branches:
- master
- dev
- release/*
- dev
pull_request:
branches:
- dev

jobs:
build_and_test:
name: Build and test the GitHub Action
runs-on: ubuntu-latest
strategy:
matrix:
os: [ 'ubuntu-latest' ]
dotnet: [ '3.1.100' ]

runs-on: ${{ matrix.os }}

steps:
- name: Checkout the repository
uses: actions/checkout@v1

- name: Setup .NET SDK
uses: actions/setup-dotnet@v1
with:
dotnet-version: ${{ matrix.dotnet }}

- name: Restore NuGet packages
shell: bash
run: |
dotnet restore
- name: Build console app
shell: bash
run: |
dotnet build
- name: Test console app
shell: bash
run: |
dotnet test test/**/*.csproj
- name: Run the private action
uses: ./
with:
Expand All @@ -25,4 +53,4 @@ jobs:
text: ''
theme_color: ''
sections: '[{ "activityImage": "https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png", "activityTitle": "GitHub Action invoked", "activitySubtitle": "Event triggered by ${{ github.event.head_commit.author.name }}", "activityText": "Commit message: [${{ github.event.head_commit.message}}](${{ github.event.head_commit.url }})" }]'
actions: ''
actions: '[{ "@type": "OpenUri", "name": "View Commit", "targets": [{ "os": "default", "uri": "${{ github.event.head_commit.url }}" }] }]'
46 changes: 46 additions & 0 deletions src/GitHubActions.Teams.ConsoleApp/ActionConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using System;

using MessageCardModel;
using MessageCardModel.Actions;

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Aliencube.GitHubActions.Teams.ConsoleApp
{
public class ActionConverter : JsonConverter
{
/// <inheritdoc />
public override bool CanWrite => false;

/// <inheritdoc />
public override bool CanRead => true;

/// <inheritdoc />
public override bool CanConvert(Type objectType) => objectType == typeof(BaseAction);

/// <inheritdoc />
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) => throw new NotImplementedException();

/// <inheritdoc />
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var jsonObject = JObject.Load(reader);

var actionType = jsonObject.GetValue("@type").Value<string>();

BaseAction target = actionType switch
{
"ActionCard" => new ActionCardAction(),
"HttpPOST" => new HttpPostAction(),
"OpenUri" => new OpenUriAction(),

string type => throw new NotSupportedException($"Cannot deserialize action type: {type}")
};

serializer.Populate(jsonObject.CreateReader(), target);

return target;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<LangVersion>latest</LangVersion>
</PropertyGroup>

<ItemGroup>
Expand Down
36 changes: 36 additions & 0 deletions src/GitHubActions.Teams.ConsoleApp/IMessageHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System.Net.Http;
using System.Threading.Tasks;

using Newtonsoft.Json;

namespace Aliencube.GitHubActions.Teams.ConsoleApp
{
/// <summary>
/// This provides interfaces to the <see cref="MessageHandler" /> class.
/// </summary>
public interface IMessageHandler
{
/// <summary>
/// Gets the JSON serialised message.
/// </summary>
string Converted { get; }

/// <summary>
/// Gets the incoming webhook URI to Microsoft Teams.
/// </summary>
string RequestUri { get; }

/// <summary>
/// Builds a message in Actionable Message Format.
/// </summary>
/// <param name="options"><see cref="Options" /> instance.</param>
/// <param name="settings"><see cref="JsonSerializerSettings" /> instance.</param>
IMessageHandler BuildMessage(Options options, JsonSerializerSettings settings);

/// <summary>
/// Sends a message to a Microsoft Teams channel.
/// </summary>
/// <param name="client"><see cref="HttpClient" /> instance.</param>
Task<int> SendMessageAsync(HttpClient client);
}
}
109 changes: 109 additions & 0 deletions src/GitHubActions.Teams.ConsoleApp/MessageHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

using MessageCardModel;

using Newtonsoft.Json;

namespace Aliencube.GitHubActions.Teams.ConsoleApp
{
/// <summary>
/// This represents the console app entity.
/// </summary>
public class MessageHandler : IMessageHandler
{
/// <inheritdoc />
public virtual string Converted { get; private set; }

/// <inheritdoc />
public virtual string RequestUri { get; private set; }

/// <inheritdoc />
public IMessageHandler BuildMessage(Options options, JsonSerializerSettings settings)
{
if (options == null)
{
throw new ArgumentNullException(nameof(options));
}

if (settings == null)
{
throw new ArgumentNullException(nameof(settings));
}

var card = new MessageCard()
{
Title = ParseString(options.Title),
Summary = ParseString(options.Summary),
Text = ParseString(options.Text),
ThemeColor = ParseString(options.ThemeColor),
Sections = ParseCollection<Section>(options.Sections, settings),
Actions = ParseCollection<BaseAction>(options.Actions, settings)
};

this.Converted = JsonConvert.SerializeObject(card, settings);
this.RequestUri = options.WebhookUri;

return this;
}

/// <inheritdoc />
public async Task<int> SendMessageAsync(HttpClient client)
{
if (client == null)
{
throw new ArgumentNullException(nameof(client));
}

if (string.IsNullOrWhiteSpace(this.RequestUri))
{
throw new InvalidOperationException("Webhook URI not ready");
}

var message = default(string);
var exitCode = default(int);

using (var content = new StringContent(this.Converted, Encoding.UTF8, "application/json"))
using (var response = await client.PostAsync(this.RequestUri, content).ConfigureAwait(false))
{
try
{
response.EnsureSuccessStatusCode();

message = $"Message sent: {this.Converted}";
exitCode = 0;
}
catch (HttpRequestException ex)
{
message = $"Error: {ex.Message}";
exitCode = (int) response.StatusCode;
}
}

Console.WriteLine(message);

return exitCode;
}

private static string ParseString(string value)
{
var parsed = string.IsNullOrWhiteSpace(value)
? null
: value;

return parsed;
}

private static List<T> ParseCollection<T>(string value, JsonSerializerSettings settings)
{
var parsed = string.IsNullOrWhiteSpace(value)
? null
: JsonConvert.DeserializeObject<List<T>>(value, settings);

return parsed;
}
}
}
75 changes: 24 additions & 51 deletions src/GitHubActions.Teams.ConsoleApp/Program.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;

using CommandLine;

using MessageCardModel;

using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;

Expand All @@ -17,79 +15,54 @@ namespace Aliencube.GitHubActions.Teams.ConsoleApp
/// </summary>
public static class Program
{
/// <summary>
/// Gets or sets the <see cref="IMessageHandler"/> instance.
/// </summary>
public static IMessageHandler MessageHandler { get; set; } = new MessageHandler();

/// <summary>
/// Gets or sets the <see cref="HttpClient"/> instance.
/// </summary>
public static HttpClient HttpClient { get; set; } = new HttpClient();

private static JsonSerializerSettings settings { get; } =
new JsonSerializerSettings()
{
Formatting = Formatting.Indented,
ContractResolver = new DefaultContractResolver() { NamingStrategy = new CamelCaseNamingStrategy() },
NullValueHandling = NullValueHandling.Ignore,
MissingMemberHandling = MissingMemberHandling.Ignore,
Converters = new List<JsonConverter> { new ActionConverter() },
};

/// <summary>
/// Invokes the console app.
/// </summary>
/// <param name="args">List of arguments passed.</param>
public static void Main(string[] args)
public static int Main(string[] args)
{
using (var parser = new Parser(with => { with.EnableDashDash = true; with.HelpWriter = Console.Out; }))
{
parser.ParseArguments<Options>(args)
.WithParsed<Options>(options => Process(options));
}
}

private static void Process(Options options)
{
var card = new MessageCard()
{
Title = ParseString(options.Title),
Summary = ParseString(options.Summary),
Text = ParseString(options.Text),
ThemeColor = ParseString(options.ThemeColor),
Sections = ParseCollection<Section>(options.Sections),
Actions = ParseCollection<BaseAction>(options.Actions)
};

var converted = JsonConvert.SerializeObject(card, settings);
var message = (string)null;
var requestUri = options.WebhookUri;
var result = parser.ParseArguments<Options>(args)
.MapResult(options => OnParsed(options), errors => OnNotParsed(errors))
;

using (var client = new HttpClient())
using (var content = new StringContent(converted, Encoding.UTF8, "application/json"))
using (var response = client.PostAsync(requestUri, content).Result)
{
try
{
response.EnsureSuccessStatusCode();

message = converted;
}
catch (HttpRequestException ex)
{
message = ex.Message;
}
return result;
}

Console.WriteLine($"Message sent: {message}");
}

private static string ParseString(string value)
private static int OnParsed(Options options)
{
var parsed = string.IsNullOrWhiteSpace(value)
? null
: value;
var result = MessageHandler.BuildMessage(options, settings)
.SendMessageAsync(HttpClient)
.Result;

return parsed;
return result;
}

private static List<T> ParseCollection<T>(string value)
private static int OnNotParsed(IEnumerable<Error> errors)
{
var parsed = string.IsNullOrWhiteSpace(value)
? null
: JsonConvert.DeserializeObject<List<T>>(value, settings);

return parsed;
return errors.Count();
}
}
}
Loading

0 comments on commit dd5e839

Please sign in to comment.