├── .gitignore
├── Miro
├── .dockerignore
├── Models
│ ├── Github
│ │ ├── Entities
│ │ │ ├── Base.cs
│ │ │ ├── Issue.cs
│ │ │ ├── Branch.cs
│ │ │ ├── Team.cs
│ │ │ ├── User.cs
│ │ │ ├── Comment.cs
│ │ │ ├── Head.cs
│ │ │ ├── Repository.cs
│ │ │ ├── Review.cs
│ │ │ ├── CheckSuite.cs
│ │ │ ├── PullRequest.cs
│ │ │ └── FileContent.cs
│ │ ├── Responses
│ │ │ ├── ReviewsResponse.cs
│ │ │ ├── UpdatePrResponse.cs
│ │ │ ├── RequiredChecksResponse.cs
│ │ │ ├── MergePrResponse.cs
│ │ │ ├── ReviewRequestsResponse.cs
│ │ │ └── WebhookResponse.cs
│ │ ├── RequestPayloads
│ │ │ ├── CreateCommentPayload.cs
│ │ │ ├── PullRequestCheckStatus.cs
│ │ │ ├── UpdateBranchPayload.cs
│ │ │ ├── MergePrPayload.cs
│ │ │ └── UpdateStatusCheckPayload.cs
│ │ └── IncomingEvents
│ │ │ ├── PushEvent.cs
│ │ │ ├── CheckSuiteEvent.cs
│ │ │ ├── IssueComentEvent.cs
│ │ │ ├── PullRequestEvent.cs
│ │ │ ├── PullRequestReviewEvent.cs
│ │ │ └── StatusEvent.cs
│ ├── Validation
│ │ └── ValidationError.cs
│ ├── Checks
│ │ ├── CheckStatus.cs
│ │ └── CheckList.cs
│ ├── Merge
│ │ └── MergeRequest.cs
│ └── MiroConfig
│ │ └── RepoConfig.cs
├── Services
│ ├── Github
│ │ ├── EventHandlers
│ │ │ ├── IWebhookEventHandler.cs
│ │ │ ├── PullRequestReviewEventHandler.cs
│ │ │ ├── StatusEventHandler.cs
│ │ │ ├── PushEventHandler.cs
│ │ │ └── IssueCommentEventHandler.cs
│ │ ├── PullRequestMismatchException.cs
│ │ ├── ReviewsRetriever.cs
│ │ ├── FileRetriever.cs
│ │ ├── PrDeleter.cs
│ │ ├── PrStatusChecks.cs
│ │ ├── PrUpdater.cs
│ │ ├── PrMerger.cs
│ │ ├── GithubHttpClient.cs
│ │ └── CommentCreator.cs
│ ├── Logger
│ │ └── LoggerExt.cs
│ ├── Checks
│ │ ├── ChecksRepository.cs
│ │ ├── ChecksRetriever.cs
│ │ ├── MiroMergeCheck.cs
│ │ └── ChecksManager.cs
│ ├── Utils
│ │ └── DictionaryExt.cs
│ ├── MiroConfig
│ │ ├── RepoConfigRepository.cs
│ │ └── RepoConfigManager.cs
│ ├── Auth
│ │ ├── ApiKeyMiddleware.cs
│ │ └── InstallationTokenStore.cs
│ ├── MiroStats
│ │ └── MiroStatsProvider.cs
│ ├── Comments
│ │ └── CommentsConsts.cs
│ └── Merge
│ │ ├── MergeabilityValidator.cs
│ │ ├── MergeOperations.cs
│ │ └── MergeRequestsRepository.cs
├── Dockerfile
├── .gitignore
├── appsettings.Development.json
├── appsettings.json
├── Docs
│ └── event_handlers.md
├── Program.cs
├── Controllers
│ ├── IsAliveController.cs
│ └── GithubWebhookController.cs
├── Properties
│ └── launchSettings.json
├── Miro.csproj
└── Startup.cs
├── Miro.Tests
├── DummyConfigYamls
│ ├── strategyAll.yml
│ ├── defaultBranchOther.yml
│ ├── strategyNone.yml
│ ├── strategyOldest.yml
│ ├── default.yml
│ ├── defaultBranchSomeDefaultBranch.yml
│ ├── invalid.yml
│ └── quiet.yml
├── MockGithubApi
│ ├── .dockerignore
│ ├── package.json
│ ├── Dockerfile
│ ├── .gitignore
│ └── index.js
├── obj
│ ├── Debug
│ │ └── netcoreapp2.1
│ │ │ ├── Miro.Tests.csproj.CopyComplete
│ │ │ ├── Miro.Tests.AssemblyInfoInputs.cache
│ │ │ ├── Miro.Tests.csproj.CoreCompileInputs.cache
│ │ │ ├── Miro.Tests.dll
│ │ │ ├── Miro.Tests.pdb
│ │ │ ├── Miro.Tests.Program.cs
│ │ │ ├── Miro.Tests.assets.cache
│ │ │ ├── Miro.Tests.csprojAssemblyReference.cache
│ │ │ ├── .NETCoreApp,Version=v2.1.AssemblyAttributes.cs
│ │ │ ├── project.razor.json
│ │ │ ├── Miro.Tests.AssemblyInfo.cs
│ │ │ └── Miro.Tests.csproj.FileListAbsolute.txt
│ ├── Miro.Tests.csproj.nuget.cache
│ ├── Miro.Tests.csproj.nuget.g.targets
│ ├── Miro.Tests.csproj.nuget.g.props
│ └── Miro.Tests.csproj.nuget.dgspec.json
├── Helpers
│ ├── CheckStatus.cs
│ ├── Consts.cs
│ ├── MockMergeGithubCallHelper.cs
│ ├── MockRequiredChecksGithubCallHelper.cs
│ ├── MockReviewGithubCallHelper.cs
│ ├── MockRepoConfigGithubCallHelper.cs
│ ├── GithubUrlHelpers.cs
│ ├── CheckListsCollection.cs
│ ├── RepoConfigurationCollection.cs
│ ├── WebhookRequestSender.cs
│ ├── MockCommentGithubCallHelper.cs
│ ├── MergeRequestsCollection.cs
│ └── GithubApiMock.cs
├── DummyEvents
│ ├── Push.json
│ ├── IssueComment.json
│ ├── Status.json
│ ├── PullRequest.json
│ └── ReviewPullRequest.json
├── Dockerfile
├── Miro.Tests.csproj
├── docker-compose.yml
├── IssueInfoCommentEventProcessingTests.cs
├── IssueCancelCommentEventProcessingTests.cs
├── ReviewEventProcessingTests.cs
└── RepoConfigurationTests.cs
├── docs
├── only_miro_can_merge_img.png
├── CONTRIBUTING.md
└── DEPLOYING.md
├── SECURITY.md
├── LICENSE
├── Miro.sln
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | .vscode/
--------------------------------------------------------------------------------
/Miro/.dockerignore:
--------------------------------------------------------------------------------
1 | bin\
2 | obj\
--------------------------------------------------------------------------------
/Miro.Tests/DummyConfigYamls/strategyAll.yml:
--------------------------------------------------------------------------------
1 | updateBranchStrategy: all
--------------------------------------------------------------------------------
/Miro.Tests/MockGithubApi/.dockerignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | npm-debug.log
--------------------------------------------------------------------------------
/Miro.Tests/obj/Debug/netcoreapp2.1/Miro.Tests.csproj.CopyComplete:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Miro.Tests/DummyConfigYamls/defaultBranchOther.yml:
--------------------------------------------------------------------------------
1 | defaultBranch: other
--------------------------------------------------------------------------------
/Miro.Tests/DummyConfigYamls/strategyNone.yml:
--------------------------------------------------------------------------------
1 | updateBranchStrategy: none
--------------------------------------------------------------------------------
/Miro.Tests/DummyConfigYamls/strategyOldest.yml:
--------------------------------------------------------------------------------
1 | updateBranchStrategy: oldest
--------------------------------------------------------------------------------
/Miro.Tests/DummyConfigYamls/default.yml:
--------------------------------------------------------------------------------
1 | mergePolicy: whitelist-strict
2 | updateBranchStrategy: all
--------------------------------------------------------------------------------
/Miro.Tests/DummyConfigYamls/defaultBranchSomeDefaultBranch.yml:
--------------------------------------------------------------------------------
1 | defaultBranch: some-default-branch
--------------------------------------------------------------------------------
/Miro.Tests/DummyConfigYamls/invalid.yml:
--------------------------------------------------------------------------------
1 | updateBranchStrategy: something-bad
2 | mergePolicy: something-badder
--------------------------------------------------------------------------------
/Miro.Tests/DummyConfigYamls/quiet.yml:
--------------------------------------------------------------------------------
1 | mergePolicy: whitelist-strict
2 | updateBranchStrategy: all
3 | quiet: true
--------------------------------------------------------------------------------
/docs/only_miro_can_merge_img.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Soluto/Miro/HEAD/docs/only_miro_can_merge_img.png
--------------------------------------------------------------------------------
/Miro.Tests/obj/Debug/netcoreapp2.1/Miro.Tests.AssemblyInfoInputs.cache:
--------------------------------------------------------------------------------
1 | d97df3e93ac78fea6ff08ac887ad0d148bc70d9f
2 |
--------------------------------------------------------------------------------
/Miro.Tests/obj/Debug/netcoreapp2.1/Miro.Tests.csproj.CoreCompileInputs.cache:
--------------------------------------------------------------------------------
1 | b075ed513398b1d0c3920f5cb00f31955daa5955
2 |
--------------------------------------------------------------------------------
/Miro.Tests/obj/Debug/netcoreapp2.1/Miro.Tests.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Soluto/Miro/HEAD/Miro.Tests/obj/Debug/netcoreapp2.1/Miro.Tests.dll
--------------------------------------------------------------------------------
/Miro.Tests/obj/Debug/netcoreapp2.1/Miro.Tests.pdb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Soluto/Miro/HEAD/Miro.Tests/obj/Debug/netcoreapp2.1/Miro.Tests.pdb
--------------------------------------------------------------------------------
/Miro.Tests/obj/Debug/netcoreapp2.1/Miro.Tests.Program.cs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Soluto/Miro/HEAD/Miro.Tests/obj/Debug/netcoreapp2.1/Miro.Tests.Program.cs
--------------------------------------------------------------------------------
/Miro.Tests/obj/Debug/netcoreapp2.1/Miro.Tests.assets.cache:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Soluto/Miro/HEAD/Miro.Tests/obj/Debug/netcoreapp2.1/Miro.Tests.assets.cache
--------------------------------------------------------------------------------
/Miro/Models/Github/Entities/Base.cs:
--------------------------------------------------------------------------------
1 | namespace Miro.Models.Github.Entities
2 | {
3 | public class Base
4 | {
5 | public string Ref { get; set; }
6 | }
7 | }
--------------------------------------------------------------------------------
/Miro/Models/Github/Entities/Issue.cs:
--------------------------------------------------------------------------------
1 | namespace Miro.Models.Github.Entities
2 | {
3 | public class Issue
4 | {
5 | public int Number { get; set; }
6 | }
7 | }
--------------------------------------------------------------------------------
/Miro/Models/Github/Entities/Branch.cs:
--------------------------------------------------------------------------------
1 | namespace Miro.Models.Github.Entities
2 | {
3 | public class Branch
4 | {
5 | public string Name { get; set; }
6 | }
7 | }
--------------------------------------------------------------------------------
/Miro/Models/Validation/ValidationError.cs:
--------------------------------------------------------------------------------
1 | namespace Miro.Models.Validation
2 | {
3 |
4 | public class ValidationError
5 | {
6 | public string Error { get; set; }
7 | }
8 | }
--------------------------------------------------------------------------------
/Miro.Tests/obj/Debug/netcoreapp2.1/Miro.Tests.csprojAssemblyReference.cache:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Soluto/Miro/HEAD/Miro.Tests/obj/Debug/netcoreapp2.1/Miro.Tests.csprojAssemblyReference.cache
--------------------------------------------------------------------------------
/Miro.Tests/obj/Miro.Tests.csproj.nuget.cache:
--------------------------------------------------------------------------------
1 | {
2 | "version": 1,
3 | "dgSpecHash": "OaG6iESR/FC1zXGDj9RrqXiKMtl7hfNGXsbazLnrOGaZrkRIvTLO9aPOGYp13KUAqEfutMFPVGWPXiJGPYsOUw==",
4 | "success": true
5 | }
--------------------------------------------------------------------------------
/Miro.Tests/Helpers/CheckStatus.cs:
--------------------------------------------------------------------------------
1 | namespace Miro.Tests.Helpers
2 | {
3 | public class CheckStatus
4 | {
5 | public string Name { get; set; }
6 | public string Status { get; set; }
7 | }
8 | }
--------------------------------------------------------------------------------
/Miro/Models/Github/Entities/Team.cs:
--------------------------------------------------------------------------------
1 | namespace Miro.Models.Github.Entities
2 | {
3 | public class Team
4 | {
5 | public string Name { get; set; }
6 | public int Id { get; set; }
7 | }
8 | }
--------------------------------------------------------------------------------
/Miro/Models/Github/Entities/User.cs:
--------------------------------------------------------------------------------
1 | namespace Miro.Models.Github.Entities
2 | {
3 | public class User
4 | {
5 | public string Login { get; set; }
6 | public int Id { get; set; }
7 | }
8 | }
--------------------------------------------------------------------------------
/Miro/Models/Github/Entities/Comment.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Newtonsoft.Json;
3 |
4 | namespace Miro.Models.Github.Entities
5 | {
6 | public class Comment
7 | {
8 | public string Body { get; set; }
9 | }
10 | }
--------------------------------------------------------------------------------
/Miro.Tests/DummyEvents/Push.json:
--------------------------------------------------------------------------------
1 | {
2 | "ref": "master",
3 | "repository": {
4 | "id": 135493233,
5 | "name": "TEST-REPO",
6 | "owner": {
7 | "login": "TEST-OWNER",
8 | "id": 21031067
9 | }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Miro/Models/Github/Entities/Head.cs:
--------------------------------------------------------------------------------
1 | namespace Miro.Models.Github.Entities
2 | {
3 | public class Head
4 | {
5 | public string Ref { get; set; }
6 | public string Sha { get; set; }
7 | public Repository Repo { get; set; }
8 | }
9 | }
--------------------------------------------------------------------------------
/Miro/Models/Github/Entities/Repository.cs:
--------------------------------------------------------------------------------
1 | namespace Miro.Models.Github.Entities
2 | {
3 | public class Repository
4 | {
5 | public User Owner { get; set; }
6 | public string Name { get; set; }
7 | public bool Fork { get; set; }
8 | }
9 | }
--------------------------------------------------------------------------------
/Miro.Tests/obj/Debug/netcoreapp2.1/.NETCoreApp,Version=v2.1.AssemblyAttributes.cs:
--------------------------------------------------------------------------------
1 | //
2 | using System;
3 | using System.Reflection;
4 | [assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v2.1", FrameworkDisplayName = "")]
5 |
--------------------------------------------------------------------------------
/Miro/Models/Github/Responses/ReviewsResponse.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using Miro.Models.Github.Entities;
3 |
4 | namespace Miro.Models.Github.Responses
5 | {
6 | class ReviewesResponse
7 | {
8 | public List Reviews { get; set; }
9 | }
10 | }
--------------------------------------------------------------------------------
/Miro/Models/Github/Responses/UpdatePrResponse.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using Miro.Models.Github.Entities;
3 |
4 | namespace Miro.Models.Github.Responses
5 | {
6 | public class UpdatePrResponse
7 | {
8 | public string Message { get; set; }
9 | }
10 | }
--------------------------------------------------------------------------------
/Miro/Models/Github/RequestPayloads/CreateCommentPayload.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 |
3 | namespace Miro.Models.Github.RequestPayloads
4 | {
5 | public class CreateCommentPayload
6 | {
7 | [JsonProperty(PropertyName = "body")]
8 | public string Body;
9 | }
10 | }
--------------------------------------------------------------------------------
/Miro.Tests/Helpers/Consts.cs:
--------------------------------------------------------------------------------
1 | namespace Miro.Tests.Helpers
2 | {
3 | public class Consts
4 | {
5 | public static string DEFAULT_BRANCH = "some-branch";
6 | public static string TEST_CHECK_A = "some test a";
7 | public static string TEST_CHECK_B = "some test b";
8 | }
9 | }
--------------------------------------------------------------------------------
/Miro/Models/Github/Responses/RequiredChecksResponse.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using Miro.Models.Github.Entities;
3 |
4 | namespace Miro.Models.Github.Responses
5 | {
6 | public class RequiredChecksResponse
7 | {
8 | public string[] Contexts {get; set;}
9 | }
10 | }
--------------------------------------------------------------------------------
/Miro/Models/Github/Responses/MergePrResponse.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using Miro.Models.Github.Entities;
3 |
4 | namespace Miro.Models.Github.Responses
5 | {
6 | public class MergePrResponse
7 | {
8 | public bool Merged { get; set; }
9 | public string Message { get; set; } = "unknown";
10 | }
11 | }
--------------------------------------------------------------------------------
/Miro/Models/Checks/CheckStatus.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Miro.Models.Checks
4 | {
5 | public class CheckStatus
6 | {
7 | public string Name { get; set; }
8 | public string Status { get; set; }
9 | public DateTime UpdatedAt { get; set; }
10 | public string TargetUrl { get; set; }
11 | }
12 | }
--------------------------------------------------------------------------------
/Miro.Tests/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM microsoft/dotnet:sdk
2 | WORKDIR /app
3 |
4 |
5 | # Copy csproj and restore as distinct layers
6 | COPY *.csproj ./
7 | RUN dotnet restore
8 |
9 | # Copy everything else and build
10 | COPY . /app
11 |
12 | # Build runtime image
13 | WORKDIR /app
14 | CMD ["dotnet", "test", "--logger", "trx;LogFileName=test_results.trx"]
--------------------------------------------------------------------------------
/Miro.Tests/MockGithubApi/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "MockGithubApi",
3 | "version": "1.0.0",
4 | "main": "index.js",
5 | "license": "MIT",
6 | "dependencies": {
7 | "body-parser": "^1.18.3",
8 | "escape-string-regexp": "^1.0.5",
9 | "express": "^4.16.3",
10 | "simple-fake-server": "^2.1.0",
11 | "uuid": "^3.3.2"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/Miro/Models/Github/Responses/ReviewRequestsResponse.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using Miro.Models.Github.Entities;
3 |
4 | namespace Miro.Models.Github.Responses
5 | {
6 | public class RequestedReviewersResponse
7 | {
8 | public List Users { get; set; } = new List();
9 | public List Teams { get; set; } = new List();
10 | }
11 | }
--------------------------------------------------------------------------------
/Miro/Models/Github/Entities/Review.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Newtonsoft.Json;
3 |
4 | namespace Miro.Models.Github.Entities
5 | {
6 | public class Review
7 | {
8 | public User User { get; set; } = new User();
9 | public string State { get; set; }
10 | [JsonProperty(PropertyName = "submitted_at")]
11 | public DateTime SubmittedAt { get; set; }
12 | }
13 | }
--------------------------------------------------------------------------------
/Miro/Models/Github/IncomingEvents/PushEvent.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using Miro.Models.Github.Entities;
3 | using Newtonsoft.Json;
4 |
5 | namespace Miro.Models.Github.IncomingEvents
6 | {
7 | public class PushEvent
8 | {
9 | public string Ref { get; set; }
10 | public string After { get; set; }
11 | public Repository Repository { get; set; }
12 | }
13 | }
--------------------------------------------------------------------------------
/Miro.Tests/DummyEvents/IssueComment.json:
--------------------------------------------------------------------------------
1 | {
2 | "action": "created",
3 | "issue": {
4 | "number": 2
5 | },
6 | "comment": {
7 | "body": "Miro merge"
8 | },
9 | "repository": {
10 | "name": "TEST-REPO",
11 | "owner": {
12 | "login": "TEST-OWNER",
13 | "id": 21031067
14 | }
15 | },
16 | "sender": {
17 | "login": "TEST-OWNER",
18 | "id": 21031067
19 | }
20 | }
--------------------------------------------------------------------------------
/Miro/Models/Github/RequestPayloads/PullRequestCheckStatus.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 |
3 | namespace Miro.Models.Github.RequestPayloads
4 | {
5 | public class PullRequestCheckStatus
6 | {
7 | public string State { get; set; }
8 | public string Context { get; set; }
9 |
10 | [JsonProperty(PropertyName = "target_url")]
11 | public string TargetUrl { get; set; }
12 | }
13 | }
--------------------------------------------------------------------------------
/Miro/Services/Github/EventHandlers/IWebhookEventHandler.cs:
--------------------------------------------------------------------------------
1 | using System.Threading.Tasks;
2 | using Miro.Models.Github.Responses;
3 |
4 | namespace Miro.Services.Github.EventHandlers
5 | {
6 |
7 | public interface IWebhookEventHandler
8 | {
9 |
10 | }
11 |
12 | public interface IWebhookEventHandler : IWebhookEventHandler
13 | {
14 | Task Handle(T payload);
15 | }
16 | }
--------------------------------------------------------------------------------
/Miro/Models/Github/Entities/CheckSuite.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using Newtonsoft.Json;
3 |
4 | namespace Miro.Models.Github.Entities
5 | {
6 | public class CheckSuite
7 | {
8 | public string Status { get; set; }
9 | public string Conclusion { get; set; }
10 | [JsonProperty(PropertyName = "pull_requests")]
11 | public List PullRequests { get; set; }
12 | }
13 | }
--------------------------------------------------------------------------------
/Miro.Tests/DummyEvents/Status.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": 5,
3 | "sha": "a10867b14bb761a232cd80139fbd4c0d33264240",
4 | "branches": [{
5 | "name": "some-branch"
6 | }],
7 | "repository": {
8 | "id": 526,
9 | "node_id": "MDEwOlJlcG9zaXRvcnkxMzU0OTMyMzM=",
10 | "name": "hello-world",
11 | "full_name": "github/hello-world",
12 | "owner": {
13 | "login": "github",
14 | "id": 340
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Miro.Tests/obj/Debug/netcoreapp2.1/project.razor.json:
--------------------------------------------------------------------------------
1 | {
2 | "ProjectFilePath": "/Users/itay/Soluto/Miro/Miro.Tests/Miro.Tests.csproj",
3 | "TargetFramework": "netcoreapp2.1",
4 | "TagHelpers": [],
5 | "Configuration": {
6 | "ConfigurationName": "UnsupportedRazor",
7 | "LanguageVersion": "1.0",
8 | "Extensions": [
9 | {
10 | "ExtensionName": "UnsupportedRazorExtension"
11 | }
12 | ]
13 | }
14 | }
--------------------------------------------------------------------------------
/Miro/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM microsoft/dotnet:sdk AS build-env
2 | WORKDIR /app
3 |
4 | # Copy csproj and restore as distinct layers
5 | COPY *.csproj ./
6 |
7 | RUN dotnet restore
8 |
9 | # Copy everything else and build
10 | COPY . ./
11 | RUN dotnet publish -c Release -o out
12 |
13 | # Build runtime image
14 | FROM microsoft/dotnet:aspnetcore-runtime
15 | WORKDIR /app
16 |
17 | COPY --from=build-env /app/out .
18 |
19 | ENTRYPOINT ["dotnet", "Miro.dll"]
--------------------------------------------------------------------------------
/Miro/Models/Github/IncomingEvents/CheckSuiteEvent.cs:
--------------------------------------------------------------------------------
1 | using Miro.Models.Github.Entities;
2 | using Newtonsoft.Json;
3 |
4 | namespace Miro.Models.Github.IncomingEvents
5 | {
6 | public class CheckSuiteEvent
7 | {
8 | public string Action { get; set; }
9 | [JsonProperty(PropertyName = "check_suite")]
10 | public CheckSuite CheckSuite { get; set; }
11 |
12 | public Repository Repository { get; set; }
13 | }
14 | }
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Reporting Security Issues
2 |
3 | If you discover a security issue in Miro, please report it by sending an email to security@soluto.com.
4 |
5 | We have a [S/MIME](security/smime.p7m) certificate for this address, use it to send encrypted mail messages.
6 |
7 | This will allow us to assess the risk, and make a fix available before we add a bug report to the GitHub repository.
8 |
9 | Thanks for helping make Miro safe for everyone.
10 |
--------------------------------------------------------------------------------
/Miro/Models/Checks/CheckList.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using MongoDB.Bson;
4 |
5 | namespace Miro.Models.Checks
6 | {
7 | public class CheckList
8 | {
9 | public ObjectId Id { get; set; }
10 | public string Owner { get; set; }
11 | public string Repo { get; set; }
12 | public DateTime UpdatedAt { get; set; }
13 | public List CheckNames { get; set; } = new List();
14 | }
15 | }
--------------------------------------------------------------------------------
/Miro/Models/Github/IncomingEvents/IssueComentEvent.cs:
--------------------------------------------------------------------------------
1 | using Miro.Models.Github.Entities;
2 | using Newtonsoft.Json;
3 |
4 | namespace Miro.Models.Github.IncomingEvents
5 | {
6 | public class IssueCommentEvent
7 | {
8 | public string Action { get; set; }
9 | public Comment Comment { get; set; }
10 | public Issue Issue { get; set; }
11 | public User Sender { get; set; }
12 | public Repository Repository { get; set; }
13 | }
14 | }
--------------------------------------------------------------------------------
/Miro/.gitignore:
--------------------------------------------------------------------------------
1 | *.swp
2 | *.*~
3 | project.lock.json
4 | .DS_Store
5 | *.pyc
6 | nupkg/
7 |
8 | # Visual Studio Code
9 | # .vscode
10 |
11 | # User-specific files
12 | *.suo
13 | *.user
14 | *.userosscache
15 | *.sln.docstates
16 |
17 | # Build results
18 | [Dd]ebug/
19 | [Dd]ebugPublic/
20 | [Rr]elease/
21 | [Rr]eleases/
22 | x64/
23 | x86/
24 | build/
25 | bld/
26 | [Bb]in/
27 | [Oo]bj/
28 | [Oo]ut/
29 | msbuild.log
30 | msbuild.err
31 | msbuild.wrn
32 |
33 | # Visual Studio 2015
34 | .vs/
--------------------------------------------------------------------------------
/Miro/Models/Github/IncomingEvents/PullRequestEvent.cs:
--------------------------------------------------------------------------------
1 | using Miro.Models.Github.Entities;
2 | using Newtonsoft.Json;
3 |
4 | namespace Miro.Models.Github.IncomingEvents
5 | {
6 | public class PullRequestEvent
7 | {
8 | public string Action { get; set; }
9 | public int Number { get; set; }
10 |
11 | [JsonProperty(PropertyName = "pull_request")]
12 | public PullRequest PullRequest { get; set; }
13 | public Repository Repository { get; set; }
14 | }
15 | }
--------------------------------------------------------------------------------
/Miro.Tests/MockGithubApi/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:8
2 |
3 | # Create app directory
4 | WORKDIR /src
5 |
6 | # Install app dependencies
7 | # A wildcard is used to ensure both package.json AND package-lock.json are copied
8 | # where available (npm@5+)
9 | COPY package*.json ./
10 |
11 | RUN npm install
12 | # If you are building your code for production
13 | # RUN npm install --only=production
14 |
15 | # Bundle app source
16 | COPY . .
17 |
18 | EXPOSE 8080
19 | EXPOSE 1234
20 | CMD [ "node", "index.js" ]
--------------------------------------------------------------------------------
/Miro/Models/Github/IncomingEvents/PullRequestReviewEvent.cs:
--------------------------------------------------------------------------------
1 | using Miro.Models.Github.Entities;
2 | using Newtonsoft.Json;
3 |
4 | namespace Miro.Models.Github.IncomingEvents
5 | {
6 | public class PullRequestReviewEvent
7 | {
8 | public string Action { get; set; }
9 | public Review Review { get; set; }
10 |
11 | [JsonProperty(PropertyName = "pull_request")]
12 | public PullRequest PullRequest { get; set; }
13 | public Repository Repository { get; set; }
14 | }
15 | }
--------------------------------------------------------------------------------
/Miro/Models/Github/RequestPayloads/UpdateBranchPayload.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 |
3 | namespace Miro.Models.Github.RequestPayloads
4 | {
5 | public class UpdateBranchPayload
6 | {
7 | [JsonProperty(PropertyName = "head")]
8 | public string Head { get; set; }
9 |
10 | [JsonProperty(PropertyName = "base")]
11 | public string Base { get; set; }
12 |
13 | [JsonProperty(PropertyName = "commit_message")]
14 | public string CommitMessage { get; set; }
15 | }
16 | }
--------------------------------------------------------------------------------
/Miro/Models/Github/Responses/WebhookResponse.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using Miro.Models.Github.Entities;
3 | using Newtonsoft.Json;
4 |
5 | namespace Miro.Models.Github.Responses
6 | {
7 | public class WebhookResponse
8 | {
9 | public WebhookResponse(bool handled, string message)
10 | {
11 | this.Handled = handled;
12 | this.Message = message;
13 | }
14 |
15 | public bool Handled { get; set; }
16 | public string Message { get; set; }
17 | }
18 | }
--------------------------------------------------------------------------------
/Miro/Models/Github/RequestPayloads/MergePrPayload.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 |
3 | namespace Miro.Models.Github.RequestPayloads
4 | {
5 | public class MergePrPayload
6 | {
7 | [JsonProperty(PropertyName = "commit_title")]
8 | public string CommitTitle { get; set; }
9 |
10 | [JsonProperty(PropertyName = "commit_message")]
11 | public string CommitMessage { get; set; }
12 |
13 | [JsonProperty(PropertyName = "merge_method")]
14 | public string MergeMethod { get; set; }
15 |
16 | public string Sha { get; set; }
17 | }
18 | }
--------------------------------------------------------------------------------
/Miro/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Serilog": {
3 | "Using": [ "Serilog.Sinks.Console" ],
4 | "MinimumLevel": {
5 | "Default": "Information",
6 | "Override": {
7 | "Microsoft": "Warning",
8 | "System": "Warning"
9 | }
10 | },
11 | "WriteTo": [
12 | {
13 | "Name": "Console",
14 | "Args": {
15 | "formatter": "Serilog.Formatting.Json.JsonFormatter, Serilog"
16 | }
17 | }
18 | ],
19 | "Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ]
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Miro/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Serilog": {
3 | "Using": [ "Serilog.Sinks.Console" ],
4 | "MinimumLevel": {
5 | "Default": "Information",
6 | "Override": {
7 | "Microsoft": "Warning",
8 | "System": "Warning"
9 | }
10 | },
11 | "WriteTo": [
12 | {
13 | "Name": "Console",
14 | "Args": {
15 | "formatter": "Serilog.Formatting.Json.JsonFormatter, Serilog"
16 | }
17 | }
18 | ],
19 | "Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ]
20 | },
21 | "AllowedHosts": "*"
22 | }
23 |
--------------------------------------------------------------------------------
/Miro/Models/Github/Entities/PullRequest.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Newtonsoft.Json;
3 |
4 | namespace Miro.Models.Github.Entities
5 | {
6 | public class PullRequest
7 | {
8 | public int Number { get; set; }
9 | public string State { get; set; }
10 | public string Title { get; set; }
11 | public User User { get; set; }
12 | public Head Head { get; set; }
13 | public Base Base { get; set; }
14 | public bool Merged { get; set; }
15 |
16 | [JsonProperty(PropertyName = "created_at")]
17 | public DateTime CreatedAt { get; set; }
18 | }
19 | }
--------------------------------------------------------------------------------
/Miro/Models/Github/IncomingEvents/StatusEvent.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using Miro.Models.Github.Entities;
3 | using Newtonsoft.Json;
4 |
5 | namespace Miro.Models.Github.IncomingEvents
6 | {
7 | public class StatusEvent
8 | {
9 | public string Sha { get; set; }
10 | public Repository Repository { get; set; }
11 | public string State { get; set; }
12 | public string Context { get; set; }
13 |
14 | [JsonProperty(PropertyName = "target_url")]
15 | public string TargetUrl { get; set; }
16 | public List Branches { get; set; }
17 | }
18 | }
--------------------------------------------------------------------------------
/Miro/Models/Github/RequestPayloads/UpdateStatusCheckPayload.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 |
3 | namespace Miro.Models.Github.RequestPayloads
4 | {
5 | public class UpdateStatusCheckPayload
6 | {
7 | [JsonProperty(PropertyName = "state")]
8 | public string State { get; set; }
9 |
10 | [JsonProperty(PropertyName = "target_url")]
11 | public string TargetUrl { get; set; }
12 |
13 | [JsonProperty(PropertyName = "description")]
14 | public string Description { get; set; }
15 |
16 | [JsonProperty(PropertyName = "context")]
17 | public string Context { get; set; }
18 | }
19 | }
--------------------------------------------------------------------------------
/Miro/Docs/event_handlers.md:
--------------------------------------------------------------------------------
1 | issueCommet -->
2 | when receiving merge command, check if all checks for the pr already passed (pr.status == READY). If true, merge the PR. if false, change it's status to QUEUED
3 |
4 | pullRequest -->
5 | when receiving an event saying a new PR was created, insert a new document to the MergeRequests collection with status PENDING
6 |
7 | checkSuite -->
8 | when receiving an event saying a check suite is completed, check if it succeded.
9 | If true AND pr status is QUEUED --> merge the PR.
10 | If true AND pr status is PENDING --> update PR status to READY
11 | If false, change the PR status to FAILED.
12 |
--------------------------------------------------------------------------------
/Miro.Tests/Helpers/MockMergeGithubCallHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading.Tasks;
3 | using Newtonsoft.Json;
4 | using static Miro.Tests.Helpers.GithubApiMock;
5 | using static Miro.Tests.Helpers.GithubUrlHelpers;
6 |
7 | namespace Miro.Tests.Helpers
8 | {
9 | public static class MockMergeGithubCallHelper
10 | {
11 | public static Task MockMergeCall(string owner, string repo, int prId, bool success = true)
12 | {
13 | var mergeResponse = new
14 | {
15 | merged = success
16 | };
17 | return MockGithubCall("put", $"{PrUrlFor(owner, repo, prId)}/merge", JsonConvert.SerializeObject(mergeResponse), true);
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/Miro/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 | using Microsoft.AspNetCore;
7 | using Microsoft.AspNetCore.Hosting;
8 | using Microsoft.Extensions.Configuration;
9 | using Microsoft.Extensions.Logging;
10 |
11 | namespace Miro
12 | {
13 | public class Program
14 | {
15 | public static void Main(string[] args)
16 | {
17 | CreateWebHostBuilder(args).Build().Run();
18 | }
19 |
20 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
21 | WebHost.CreateDefaultBuilder(args)
22 | .UseStartup();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Miro.Tests/Miro.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.1
5 |
6 | false
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/Miro.Tests/Helpers/MockRequiredChecksGithubCallHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading.Tasks;
3 | using Newtonsoft.Json;
4 | using static Miro.Tests.Helpers.GithubApiMock;
5 | using static Miro.Tests.Helpers.GithubUrlHelpers;
6 |
7 | namespace Miro.Tests.Helpers
8 | {
9 | public static class MockRequiredChecksGithubCallHelper
10 | {
11 | public static async Task MockRequiredChecks(string owner, string repo, string[] requiredChecks = null, string branch = "master")
12 | {
13 | var mockedRequiredTests = new {
14 | contexts = requiredChecks ?? new string[]{Consts.TEST_CHECK_A, Consts.TEST_CHECK_B}
15 | };
16 | return await MockGithubCall("get", RequiredChecksUrlFor(owner, repo, branch), JsonConvert.SerializeObject(mockedRequiredTests), true);
17 | }
18 | }
19 | }
--------------------------------------------------------------------------------
/Miro/Controllers/IsAliveController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Net.Http;
6 | using System.Net.Http.Headers;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using Microsoft.AspNetCore.Mvc;
10 | using Microsoft.AspNetCore.WebHooks;
11 | using Microsoft.Extensions.Logging;
12 | using Miro.Models.Github.IncomingEvents;
13 | using Miro.Models.Github.Responses;
14 | using Miro.Services.Github;
15 | using Miro.Services.Github.EventHandlers;
16 | using Miro.Services.Merge;
17 | using Newtonsoft.Json.Linq;
18 |
19 | namespace Miro.Controllers
20 | {
21 |
22 | [Route("api/isAlive")]
23 | public class IsAliveController : ControllerBase
24 | {
25 |
26 | [HttpGet]
27 | public bool IsAlive()
28 | {
29 | return true;
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Miro.Tests/DummyEvents/PullRequest.json:
--------------------------------------------------------------------------------
1 | {
2 | "action": "opened",
3 | "number": 1,
4 | "pull_request": {
5 | "id": 191568743,
6 | "number": 1,
7 | "locked": false,
8 | "title": "Update the README with new information",
9 | "user": {
10 | "login": "TEST-PR-AUTHOR",
11 | "id": 21031067
12 | },
13 | "head": {
14 | "ref": "some-branch",
15 | "sha": "b49ce9dd575f4faebac17220e82368c1"
16 | },
17 | "base": {
18 | "ref": "master"
19 | },
20 | "body": "This is a pretty simple change that we need to pull into master.",
21 | "mergeable": true,
22 | "rebaseable": true,
23 | "mergeable_state": "clean"
24 | },
25 | "repository": {
26 | "id": 135493233,
27 | "name": "TEST-REPO",
28 | "owner": {
29 | "login": "TEST-OWNER",
30 | "id": 21031067
31 | }
32 | },
33 | "sender": {
34 | "login": "TEST-PR-AUTHOR"
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/Miro/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json.schemastore.org/launchsettings.json",
3 | "iisSettings": {
4 | "windowsAuthentication": false,
5 | "anonymousAuthentication": true,
6 | "iisExpress": {
7 | "applicationUrl": "http://localhost:50911",
8 | "sslPort": 44351
9 | }
10 | },
11 | "profiles": {
12 | "IIS Express": {
13 | "commandName": "IISExpress",
14 | "launchBrowser": true,
15 | "launchUrl": "api/values",
16 | "environmentVariables": {
17 | "ASPNETCORE_ENVIRONMENT": "Development"
18 | }
19 | },
20 | "Miro": {
21 | "commandName": "Project",
22 | "launchBrowser": true,
23 | "launchUrl": "api/values",
24 | "applicationUrl": "https://localhost:5001;http://localhost:5000",
25 | "environmentVariables": {
26 | "ASPNETCORE_ENVIRONMENT": "Development"
27 | }
28 | }
29 | }
30 | }
--------------------------------------------------------------------------------
/Miro/Services/Github/PullRequestMismatchException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.Serialization;
3 |
4 | namespace Miro.Services.Github
5 | {
6 | [Serializable]
7 | internal class PullRequestMismatchException : Exception
8 | {
9 | private object httpResponse;
10 |
11 | public PullRequestMismatchException()
12 | {
13 | }
14 |
15 | public PullRequestMismatchException(object httpResponse)
16 | {
17 | this.httpResponse = httpResponse;
18 | }
19 |
20 | public PullRequestMismatchException(string message) : base(message)
21 | {
22 | }
23 |
24 | public PullRequestMismatchException(string message, Exception innerException) : base(message, innerException)
25 | {
26 | }
27 |
28 | protected PullRequestMismatchException(SerializationInfo info, StreamingContext context) : base(info, context)
29 | {
30 | }
31 | }
32 | }
--------------------------------------------------------------------------------
/Miro/Miro.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.1
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/Miro/Services/Logger/LoggerExt.cs:
--------------------------------------------------------------------------------
1 | using Miro.Models.Merge;
2 | using Serilog;
3 |
4 | namespace Miro.Services.Logger
5 | {
6 | public static class LoggerExt
7 | {
8 | public static ILogger WithExtraData(this ILogger logger, object extraData)
9 | {
10 | return logger.ForContext("ExtraData", extraData, true);
11 | }
12 |
13 | public static ILogger WithMergeRequestData(this ILogger logger, MergeRequest mergeRequest)
14 | {
15 | return logger.ForContext("MergeRequestData", new
16 | {
17 | owner = mergeRequest.Owner,
18 | repo = mergeRequest.Repo,
19 | branch = mergeRequest.Branch,
20 | prId = mergeRequest.PrId,
21 | sha = mergeRequest.Sha,
22 | title = mergeRequest.Title,
23 | receivedMergeCommand = mergeRequest.ReceivedMergeCommand,
24 | });
25 | }
26 |
27 | }
28 | }
--------------------------------------------------------------------------------
/Miro.Tests/DummyEvents/ReviewPullRequest.json:
--------------------------------------------------------------------------------
1 | {
2 | "action": "submitted",
3 | "review": {
4 | "state": "approved",
5 | "id": 191568743,
6 | "title": "Update the README with new information",
7 | "user": {
8 | "login": "TEST-PR-AUTHOR",
9 | "id": 21031067
10 | }
11 | },
12 | "pull_request": {
13 | "id": 191568743,
14 | "number": 1,
15 | "locked": false,
16 | "title": "Update the README with new information",
17 | "user": {
18 | "login": "TEST-PR-AUTHOR",
19 | "id": 21031067
20 | },
21 | "head": {
22 | "ref": "some-branch"
23 | },
24 | "body": "This is a pretty simple change that we need to pull into master.",
25 | "mergeable": true,
26 | "rebaseable": true,
27 | "mergeable_state": "clean"
28 | },
29 | "repository": {
30 | "id": 135493233,
31 | "name": "TEST-REPO",
32 | "owner": {
33 | "login": "TEST-OWNER",
34 | "id": 21031067
35 | }
36 | },
37 | "sender": {
38 | "login": "TEST-PR-AUTHOR"
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Miro.Tests/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 |
3 | services:
4 | miro-app:
5 | build: ../Miro
6 | depends_on:
7 | - mock_github_api
8 | - mongo
9 | environment:
10 | - ASPNETCORE_ENVIRONMENT=Development
11 | - GITHUB_API_URL=http://mock_github_api:1234/
12 | - MONGO_CONNECTION_STRING=mongodb://mongo:27017
13 | - WEBHOOKS__GITHUB__SECRETKEY__DEFAULT=614d038b841a4846e27a92cc4b25ce5e54e1ae4a
14 | ports:
15 | - "5000:80"
16 |
17 | mock_github_api:
18 | build: ./MockGithubApi
19 | ports:
20 | - "3000:3000"
21 | - "1234:1234"
22 |
23 | mongo:
24 | image: mongo:4.1
25 | ports:
26 | - "27017:27017"
27 |
28 | miro-tests:
29 | build: .
30 | depends_on:
31 | - mock_github_api
32 | - mongo
33 | - miro-app
34 | environment:
35 | - MONGO_CONNECTION_STRING=mongodb://mongo:27017
36 | - SERVER_URL=http://miro-app:80
37 | - GITHUB_API_URL=http://mock_github_api:3000
38 | volumes:
39 | - ./logs:/app/TestResults
40 |
41 |
--------------------------------------------------------------------------------
/Miro.Tests/obj/Debug/netcoreapp2.1/Miro.Tests.AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | using System;
12 | using System.Reflection;
13 |
14 | [assembly: System.Reflection.AssemblyCompanyAttribute("Miro.Tests")]
15 | [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
16 | [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
17 | [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")]
18 | [assembly: System.Reflection.AssemblyProductAttribute("Miro.Tests")]
19 | [assembly: System.Reflection.AssemblyTitleAttribute("Miro.Tests")]
20 | [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
21 |
22 | // Generated by the MSBuild WriteCodeFragment class.
23 |
24 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Soluto by Asurion
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Miro/Services/Github/ReviewsRetriever.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Net.Http;
4 | using System.Threading.Tasks;
5 | using Miro.Models.Github.Entities;
6 | using Miro.Models.Github.Responses;
7 |
8 | namespace Miro.Services.Github
9 | {
10 | public class ReviewsRetriever
11 | {
12 | private readonly GithubHttpClient githubHttpClient;
13 |
14 | public ReviewsRetriever(GithubHttpClient githubHttpClient)
15 | {
16 | this.githubHttpClient = githubHttpClient;
17 | }
18 | public async Task GetRequestedReviewers(string owner, string repo, int prId)
19 | {
20 | var reviewRequests = await githubHttpClient.Get($"/repos/{owner}/{repo}/pulls/{prId}/requested_reviewers");
21 |
22 | return reviewRequests;
23 | }
24 |
25 | public async Task> GetReviews(string owner, string repo, int prId)
26 | {
27 | var reviews = await githubHttpClient.Get>($"/repos/{owner}/{repo}/pulls/{prId}/reviews");
28 |
29 | return reviews;
30 | }
31 | }
32 | }
--------------------------------------------------------------------------------
/docs/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to MIRO
2 |
3 |
4 |
5 | - [Contributing to MIRO](#contributing-to-miro)
6 | - [Set up environment](#set-up-environment)
7 | - [Testing](#testing)
8 | - [Testing Locally](#testing-locally)
9 |
10 |
11 |
12 | ## Set up environment
13 | 1. install .net core sdk
14 | 2. if working with vs code --> install c# extension
15 |
16 | ## Testing
17 |
18 | Run the test suite
19 | 1. `cd Miro.Tests && docker-compose up --build --abort-on-container-exit`
20 |
21 | If you want to run the tests separately without re-building the app
22 | 1. `cd Miro.Tests`
23 | 2. `docker-compose build` - Will Build the bot, GithubApi, MongoDb
24 | 3. `docker-compose run --rm --name miro-tests miro-tests` - Will Run the tests
25 |
26 | To run a single test, replace step (3) with this:
27 | 1. `docker-compose run --rm --name miro-tests --entrypoint 'dotnet test --filter "Miro.Tests.."' miro-tests`
28 |
29 | ## Testing Locally
30 | If you want to run the tests without docker
31 | 1. `cd Miro.Tests`
32 | 2. `docker-compose build`
33 | 3. `docker-compose run --rm --service-ports --name miro-app miro-app`
34 | 4. `dotnet restore && dotnet test`
35 |
36 |
37 |
--------------------------------------------------------------------------------
/Miro.Tests/Helpers/MockReviewGithubCallHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading.Tasks;
3 | using Newtonsoft.Json;
4 | using static Miro.Tests.Helpers.GithubApiMock;
5 | using static Miro.Tests.Helpers.GithubUrlHelpers;
6 |
7 | namespace Miro.Tests.Helpers
8 | {
9 | public static class MockReviewGithubCallHelper
10 | {
11 | public static async Task MockReviewsResponses(string requestedReviews, string madeReviews, string owner, string repo, int prId)
12 | {
13 | await MockGithubCall("get", $"{PrUrlFor(owner, repo, prId)}/requested_reviewers", requestedReviews);
14 | await MockGithubCall("get", $"{PrUrlFor(owner, repo, prId)}/reviews", madeReviews);
15 | }
16 |
17 | public static Task MockAllReviewsPassedResponses(string owner, string repo, int prId)
18 | {
19 | var requestedReviewsMockedResponse = new
20 | {
21 | teams = Array.Empty