diff --git a/Infrastructure/.drone.yml b/Infrastructure/.drone.yml index fc4faa2..6cf5ed4 100644 --- a/Infrastructure/.drone.yml +++ b/Infrastructure/.drone.yml @@ -19,21 +19,18 @@ steps: environment: ConnectionString: from_secret: ConnectionString - GitDomain: - from_secret: GitDomain - GitToken: - from_secret: GitToken BlogEndpoint: from_secret: BlogEndpoint + GitEndpoint: + from_secret: GitEndpoint commands: - curl -sL https://deb.nodesource.com/setup_12.x | bash - - apt-get install -y nodejs - chmod +x ./build.sh - ./build.sh - sed -i "s//$ConnectionString/g" output/appsettings.json - - sed -i "s//$GitDomain/g" output/appsettings.json - - sed -i "s//$GitToken/g" output/appsettings.json - sed -i "s//$BlogEndpoint/g" output/appsettings.json + - sed -i "s//$GitEndpoint/g" output/appsettings.json - cp Infrastructure/website.service output/ - cp -r ./output/* /output - name: restart service diff --git a/Website.Tests/Data/GitApiTests.cs b/Website.Tests/Data/GitApiTests.cs new file mode 100644 index 0000000..5262188 --- /dev/null +++ b/Website.Tests/Data/GitApiTests.cs @@ -0,0 +1,76 @@ +using System; +using System.Net.Http; +using System.Threading.Tasks; +using FluentAssertions; +using Website.Data; +using Website.Models.Git; +using Xunit; + +namespace Website.Tests.Data { + public class GitApiTests { + [Fact] + public async Task GetRepositories_WithUser_ReturnsRepositoryCollection() { + const string json = @"[{""name"":""name"",""url"":""url""}]"; + var httpClient = new HttpClientBuilder() + .WithMethod(HttpMethod.Get) + .WithUrl("/repositories") + .WithQueryString("user", "test") + .WithResponse(json) + .Build(); + + var expectation = new[] {new Repository {Url = "url", Name = "name"}}; + + var api = new GitApi(httpClient); + (await api.GetRepositories("test")).Should().BeEquivalentTo(expectation); + } + + [Fact] + public async Task GetBranches_WithUserAndRepository_ReturnsBranchCollection() { + const string json = @"[{""name"":""master"",""commit"":{""id"":""0923b554309ef562fca978c7e981b3812bc4af40"",""message"":""message"",""timestamp"":""2020-04-11T14:09:29+01:00"",""url"":null}}]"; + var httpClient = new HttpClientBuilder() + .WithMethod(HttpMethod.Get) + .WithUrl("/branches") + .WithQueryString("user", "test") + .WithQueryString("repository", "repo") + .WithResponse(json) + .Build(); + + var expectation = new[] { + new Branch { + Name = "master", + Commit = new Commit { + Id = "0923b554309ef562fca978c7e981b3812bc4af40", + Message = "message", + Timestamp = new DateTimeOffset(2020, 04, 11, 14, 09, 29, TimeSpan.FromHours(1)) + } + } + }; + + var api = new GitApi(httpClient); + (await api.GetBranches("test", "repo")).Should().BeEquivalentTo(expectation); + } + + [Fact] + public async Task GetCommit_WithUserAndRepositoryAndHash_ReturnsCommit() { + const string json = @"{""id"":""0923b554309ef562fca978c7e981b3812bc4af40"",""message"":""message"",""timestamp"":""2020-04-11T14:09:29+01:00"",""url"":""https://test.com/test/repo/commit/0923b554309ef562fca978c7e981b3812bc4af40""}"; + var httpClient = new HttpClientBuilder() + .WithMethod(HttpMethod.Get) + .WithUrl("/commit") + .WithQueryString("user", "test") + .WithQueryString("repository", "repo") + .WithQueryString("hash", "hash") + .WithResponse(json) + .Build(); + + var expectation = new Commit { + Id = "0923b554309ef562fca978c7e981b3812bc4af40", + Message = "message", + Timestamp = new DateTimeOffset(2020, 04, 11, 14, 09, 29, TimeSpan.FromHours(1)), + Url = "https://test.com/test/repo/commit/0923b554309ef562fca978c7e981b3812bc4af40" + }; + + var api = new GitApi(httpClient); + (await api.GetCommit("test", "repo", "hash")).Should().BeEquivalentTo(expectation); + } + } +} \ No newline at end of file diff --git a/Website/Controllers/HomeController.cs b/Website/Controllers/HomeController.cs index 465a2cc..5966b1e 100644 --- a/Website/Controllers/HomeController.cs +++ b/Website/Controllers/HomeController.cs @@ -7,18 +7,18 @@ using System.Linq; namespace Website.Controllers { public class HomeController : Controller { private readonly IBlogApi _blogApi; - private readonly GitServerApi _api; + private readonly IGitApi _api; - public HomeController(IBlogApi blogApi, GitServerApi api) { + public HomeController(IBlogApi blogApi, IGitApi api) { _api = api; _blogApi = blogApi; } public async Task Index() { var post = await _blogApi.GetLatestPostAsync(); - var repo = (await _api.GetRepositories()).First(); - var branch = (await _api.GetBranches(repo.Name)).First(); - var commit = await _api.GetCommit(repo.Name, branch.Commit.Id); + var repo = (await _api.GetRepositories("rob")).First(); + var branch = (await _api.GetBranches("rob", repo.Name)).First(); + var commit = await _api.GetCommit("rob", repo.Name, branch.Commit.Id); var model = new HomeViewModel { BlogPost = new BlogPostViewModel(post, false), diff --git a/Website/Data/GitApi.cs b/Website/Data/GitApi.cs new file mode 100644 index 0000000..58c7753 --- /dev/null +++ b/Website/Data/GitApi.cs @@ -0,0 +1,16 @@ +using System.Collections.Generic; +using System.Net.Http; +using System.Threading.Tasks; +using Website.Models.Git; + +namespace Website.Data { + public class GitApi : ApiClient, IGitApi { + + public GitApi(HttpClient client) : base(client) { + } + + public async Task> GetRepositories(string user) => await Get>("repositories", new { user }); + public async Task> GetBranches(string user, string repository) => await Get>("branches", new {user, repository}); + public async Task GetCommit(string user, string repository, string hash) => await Get("commit", new {user, repository, hash}); + } +} diff --git a/Website/Data/GitServerApi.cs b/Website/Data/GitServerApi.cs deleted file mode 100644 index e258cc7..0000000 --- a/Website/Data/GitServerApi.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using System.Net.Http; -using System.Threading.Tasks; -using Newtonsoft.Json; -using Website.Data.States.Git; -using Website.Models.Git; - -namespace Website.Data { - public class GitServerApi { - private readonly HttpClient _client; - private readonly string _domain; - private readonly string _token; - - public GitServerApi(HttpClient client, string domain, string token) { - _client = client; - _domain = domain; - _token = token; - } - - public async Task> GetRepositories() { - var response = await _client.GetStringAsync($"https://{_domain}/api/v1/users/rob/repos?token={_token}"); - var states = JsonConvert.DeserializeObject>(response); - return states.Select(state => new Repository(state)); - } - - public async Task> GetBranches(string repository) { - var response = await _client.GetStringAsync($"https://{_domain}/api/v1/repos/rob/{repository}/branches?token={_token}"); - var states = JsonConvert.DeserializeObject>(response); - return states.Select(state => new Branch(state)); - } - - public async Task GetCommit(string repository, string hash) { - var response = await _client.GetStringAsync($"https://{_domain}/api/v1/repos/rob/{repository}/commits/{hash}?token={_token}"); - var state = JsonConvert.DeserializeObject(response); - return new Commit(state); - } - } -} \ No newline at end of file diff --git a/Website/Data/IGitApi.cs b/Website/Data/IGitApi.cs new file mode 100644 index 0000000..c9711e7 --- /dev/null +++ b/Website/Data/IGitApi.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Website.Models.Git; + +namespace Website.Data { + public interface IGitApi { + Task> GetRepositories(string user); + Task> GetBranches(string user, string repository); + Task GetCommit(string user, string repository, string hash); + } +} \ No newline at end of file diff --git a/Website/Data/States/Git/AuthorState.cs b/Website/Data/States/Git/AuthorState.cs deleted file mode 100644 index b648f63..0000000 --- a/Website/Data/States/Git/AuthorState.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; - -namespace Website.Data.States.Git { - public class AuthorState { - public string name { get; set; } - public string email { get; set; } - public string username { get; set; } - public DateTimeOffset date { get; set; } - } -} diff --git a/Website/Data/States/Git/BranchState.cs b/Website/Data/States/Git/BranchState.cs deleted file mode 100644 index b8315f0..0000000 --- a/Website/Data/States/Git/BranchState.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Website.Data.States.Git { - public class BranchState - { - public string name { get; set; } - public CommitState commit { get; set; } - } -} diff --git a/Website/Data/States/Git/CommitDetailsState.cs b/Website/Data/States/Git/CommitDetailsState.cs deleted file mode 100644 index ff06dcc..0000000 --- a/Website/Data/States/Git/CommitDetailsState.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Website.Data.States.Git { - public class CommitDetailsState { - public string url { get; set; } - public string sha { get; set; } - public string html_url { get; set; } - public CommitState commit { get; set; } - public UserState author { get; set; } - public UserState committer { get; set; } - public CommitPointerState[] parents { get; set; } - } -} \ No newline at end of file diff --git a/Website/Data/States/Git/CommitPointerState.cs b/Website/Data/States/Git/CommitPointerState.cs deleted file mode 100644 index 2896437..0000000 --- a/Website/Data/States/Git/CommitPointerState.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Website.Data.States.Git { - public partial class CommitPointerState { - public string url { get; set; } - public string sha { get; set; } - } -} \ No newline at end of file diff --git a/Website/Data/States/Git/CommitState.cs b/Website/Data/States/Git/CommitState.cs deleted file mode 100644 index 9fcc02d..0000000 --- a/Website/Data/States/Git/CommitState.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; - -namespace Website.Data.States.Git { - public class CommitState { - public string id { get; set; } - public string message { get; set; } - public string url { get; set; } - public AuthorState author { get; set; } - public AuthorState committer { get; set; } - public object added { get; set; } - public object removed { get; set; } - public object modified { get; set; } - public DateTimeOffset timestamp { get; set; } - public CommitPointerState tree { get; set; } - } -} diff --git a/Website/Data/States/Git/RepositoryOwnerState.cs b/Website/Data/States/Git/RepositoryOwnerState.cs deleted file mode 100644 index 60b386f..0000000 --- a/Website/Data/States/Git/RepositoryOwnerState.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Website.Data.States.Git { - public class RepositoryOwnerState { - public int id { get; set; } - public string username { get; set; } - public string login { get; set; } - public string full_name { get; set; } - public string email { get; set; } - public string avatar_url { get; set; } - } -} \ No newline at end of file diff --git a/Website/Data/States/Git/RepositoryPermissionsState.cs b/Website/Data/States/Git/RepositoryPermissionsState.cs deleted file mode 100644 index 394b196..0000000 --- a/Website/Data/States/Git/RepositoryPermissionsState.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Website.Data.States.Git { - public class RepositoryPermissionsState { - public bool admin { get; set; } - public bool push { get; set; } - public bool pull { get; set; } - } -} \ No newline at end of file diff --git a/Website/Data/States/Git/RepositoryState.cs b/Website/Data/States/Git/RepositoryState.cs deleted file mode 100644 index 56330df..0000000 --- a/Website/Data/States/Git/RepositoryState.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; - -namespace Website.Data.States.Git { - public class RepositoryState { - public int id { get; set; } - public RepositoryOwnerState owner { get; set; } - public string name { get; set; } - public string full_name { get; set; } - public string description { get; set; } - public bool _private { get; set; } - public bool fork { get; set; } - public object parent { get; set; } - public bool empty { get; set; } - public bool mirror { get; set; } - public int size { get; set; } - public string html_url { get; set; } - public string ssh_url { get; set; } - public string clone_url { get; set; } - public string website { get; set; } - public int stars_count { get; set; } - public int forks_count { get; set; } - public int watchers_count { get; set; } - public int open_issues_count { get; set; } - public string default_branch { get; set; } - public DateTime created_at { get; set; } - public DateTime updated_at { get; set; } - public RepositoryPermissionsState permissions { get; set; } - } -} - - diff --git a/Website/Data/States/Git/UserState.cs b/Website/Data/States/Git/UserState.cs deleted file mode 100644 index f9dd601..0000000 --- a/Website/Data/States/Git/UserState.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Website.Data.States.Git { - public partial class UserState { - public long id { get; set; } - public string username { get; set; } - public string login { get; set; } - public string full_name { get; set; } - public string email { get; set; } - public string avatar_url { get; set; } - } -} \ No newline at end of file diff --git a/Website/Models/Git/Branch.cs b/Website/Models/Git/Branch.cs index b34c7be..43e2b3c 100644 --- a/Website/Models/Git/Branch.cs +++ b/Website/Models/Git/Branch.cs @@ -1,14 +1,6 @@ -using Website.Data.States.Git; - -namespace Website.Models.Git { +namespace Website.Models.Git { public class Branch { - - public Branch(BranchState state) { - Name = state.name; - Commit = new Commit(state.commit); - } - - public string Name { get; } - public Commit Commit { get; private set; } + public string Name { get; set; } + public Commit Commit { get; set; } } -} \ No newline at end of file +} diff --git a/Website/Models/Git/Commit.cs b/Website/Models/Git/Commit.cs index 8d0a44e..2fd26e0 100644 --- a/Website/Models/Git/Commit.cs +++ b/Website/Models/Git/Commit.cs @@ -1,24 +1,10 @@ -using System; -using Website.Data.States.Git; +using System; namespace Website.Models.Git { public class Commit { - public Commit(CommitState commit) { - Id = commit.id; - Message = commit.message; - Timestamp = commit.timestamp; - } - - public Commit(CommitDetailsState commit) { - Id = commit.sha; - Message = commit.commit.message; - Timestamp = commit.commit.author.date; - Url = commit.html_url.Replace("/commits/", "/commit/"); - } - - public string Id { get; } - public string Message { get; } - public DateTimeOffset Timestamp { get; } - public string Url { get; } + public string Id { get; set; } + public string Message { get; set; } + public DateTimeOffset Timestamp { get; set; } + public string Url { get; set; } } -} \ No newline at end of file +} diff --git a/Website/Models/Git/Repository.cs b/Website/Models/Git/Repository.cs index 362abd5..9747987 100644 --- a/Website/Models/Git/Repository.cs +++ b/Website/Models/Git/Repository.cs @@ -1,13 +1,6 @@ -using Website.Data.States.Git; - -namespace Website.Models.Git { +namespace Website.Models.Git { public class Repository { - public Repository(RepositoryState state) { - Name = state.name; - Url = state.html_url; - } - public string Name { get; set; } public string Url { get; set; } } -} \ No newline at end of file +} diff --git a/Website/Startup.cs b/Website/Startup.cs index 20ad655..2151cd3 100644 --- a/Website/Startup.cs +++ b/Website/Startup.cs @@ -32,7 +32,14 @@ namespace Website }); services.AddSingleton(Configuration); - RegisterRepositories(services); + services.AddSingleton() + .AddSingleton(); + + services.AddHttpClient(client => client.BaseAddress = new Uri(Configuration["gitApiEndpoint"])) + .ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler {ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true}); + + services.AddHttpClient(client => client.BaseAddress = new Uri(Configuration["blogApiEndpoint"])) + .ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler {ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true}); services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(); @@ -43,16 +50,6 @@ namespace Website ; } - private void RegisterRepositories(IServiceCollection services) => - services.AddSingleton() - .AddSingleton() - .AddSingleton() - .AddSingleton(new GitServerApi(new HttpClient(), Configuration["gitDomain"], Configuration["gitToken"])) - .AddHttpClient(client => client.BaseAddress = new Uri(Configuration["blogApiEndpoint"])) - .ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler { - ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true - }); - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { diff --git a/Website/ViewComponents/ProjectNavigationViewComponent.cs b/Website/ViewComponents/ProjectNavigationViewComponent.cs index da0beb9..4e6b304 100644 --- a/Website/ViewComponents/ProjectNavigationViewComponent.cs +++ b/Website/ViewComponents/ProjectNavigationViewComponent.cs @@ -5,14 +5,14 @@ using Website.Data; namespace Website.ViewComponents { public class ProjectNavigationViewComponent :ViewComponent { - private readonly GitServerApi _api; + private readonly IGitApi _api; - public ProjectNavigationViewComponent(GitServerApi api) { + public ProjectNavigationViewComponent(IGitApi api) { _api = api; } public async Task InvokeAsync() { - var repositories = await _api.GetRepositories(); + var repositories = await _api.GetRepositories("rob"); return View(repositories.Take(5)); } } diff --git a/Website/Website.csproj b/Website/Website.csproj index 02f1db5..8aedc9a 100644 --- a/Website/Website.csproj +++ b/Website/Website.csproj @@ -23,7 +23,7 @@ - - + diff --git a/Website/appsettings.Development.json b/Website/appsettings.Development.json index 996fc81..ff63028 100644 --- a/Website/appsettings.Development.json +++ b/Website/appsettings.Development.json @@ -9,7 +9,6 @@ "ConnectionStrings": { "database": "Server=localhost;User ID=user;Password=pass;Database=db" }, - "gitDomain": "", - "gitToken": "", - "blogApiEndpoint": "" + "blogApiEndpoint": "", + "gitApiEndpoint": "" } \ No newline at end of file diff --git a/Website/appsettings.json b/Website/appsettings.json index 3751044..afd4a11 100644 --- a/Website/appsettings.json +++ b/Website/appsettings.json @@ -7,9 +7,8 @@ "ConnectionStrings": { "database": "" }, - "gitDomain": "", - "gitToken": "", "blogApiEndpoint": "", + "gitApiEndpoint": "", "AllowedHosts": "*", "Kestrel": { "EndPoints": { diff --git a/clean-config.sh b/clean-config.sh index 0a87bd6..b52cc82 100644 --- a/clean-config.sh +++ b/clean-config.sh @@ -2,6 +2,6 @@ sed \ -e 's/"database": "Server=.*;User ID=.*;Password=.*;Database=.*"/"database": "Server=localhost;User ID=user;Password=pass;Database=db"/g' \ --e 's/"gitDomain": ".*"/"gitDomain": ""/g' \ --e 's/"gitToken": ".*"/"gitToken": ""/g' \ +-e 's/"blogApiEndpoint": ".*"/"blogApiEndpoint": ""/g' \ +-e 's/"gitApiEndpoint": ".*"/"gitApiEndpoint": ""/g' \ $1 \ No newline at end of file