Skip to content

Commit 5b39330

Browse files
authored
Merge pull request #147 from The-Standard-Organization/users/mabroukmahdhi/exposers-fluent-pipeline-builder
EXPOSERS: Fluent GitHub Pipeline Builder
2 parents 55d51f8 + 3e04bab commit 5b39330

File tree

7 files changed

+540
-1
lines changed

7 files changed

+540
-1
lines changed

ADotNet/ADotNet.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,4 +86,8 @@
8686
</None>
8787
</ItemGroup>
8888

89+
<ItemGroup>
90+
<InternalsVisibleTo Include="ADotNet.Tests.Unit" />
91+
</ItemGroup>
92+
8993
</Project>

ADotNet/Clients/ADotNetClient.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
namespace ADotNet.Clients
1212
{
13-
public class ADotNetClient
13+
public class ADotNetClient : IADotNetClient
1414
{
1515
private readonly IBuildService buildService;
1616

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
// ---------------------------------------------------------------------------
2+
// Copyright (c) Hassan Habib & Shri Humrudha Jagathisun All rights reserved.
3+
// Licensed under the MIT License.
4+
// See License.txt in the project root for license information.
5+
// ---------------------------------------------------------------------------
6+
7+
using System;
8+
using System.Collections.Generic;
9+
using ADotNet.Models.Pipelines.GithubPipelines.DotNets;
10+
11+
namespace ADotNet.Clients.Builders
12+
{
13+
/// <summary>
14+
/// Builder for creating a GitHub pipeline.
15+
/// </summary>
16+
public class GitHubPipelineBuilder
17+
{
18+
private readonly GithubPipeline githubPipeline;
19+
private readonly IADotNetClient aDotNetClient;
20+
21+
internal GitHubPipelineBuilder(IADotNetClient aDotNetClient)
22+
{
23+
this.githubPipeline = new GithubPipeline
24+
{
25+
OnEvents = new Events(),
26+
Jobs = new Dictionary<string, Job>()
27+
};
28+
29+
this.aDotNetClient = aDotNetClient;
30+
}
31+
32+
/// <summary>
33+
/// Creates a new instance of the <see cref="GitHubPipelineBuilder"/> class
34+
/// with a default <see cref="ADotNetClient"/>.
35+
/// </summary>
36+
/// <returns>A new instance of <see cref="GitHubPipelineBuilder"/>.</returns>
37+
public static GitHubPipelineBuilder CreateNewPipeline()
38+
{
39+
var aDotNetClient = new ADotNetClient();
40+
41+
return new GitHubPipelineBuilder(aDotNetClient);
42+
}
43+
44+
/// <summary>
45+
/// Sets the name of the GitHub pipeline.
46+
/// </summary>
47+
/// <param name="name">The name of the pipeline.</param>
48+
/// <returns>The current instance of <see cref="GitHubPipelineBuilder"/>.</returns>
49+
public GitHubPipelineBuilder SetName(string name)
50+
{
51+
this.githubPipeline.Name = name;
52+
53+
return this;
54+
}
55+
56+
/// <summary>
57+
/// Configures the pipeline to trigger on push events for specified branches.
58+
/// </summary>
59+
/// <param name="branches">The branches to trigger on push events.</param>
60+
/// <returns>The current instance of <see cref="GitHubPipelineBuilder"/>.</returns>
61+
public GitHubPipelineBuilder OnPush(params string[] branches)
62+
{
63+
this.githubPipeline.OnEvents.Push = new PushEvent
64+
{
65+
Branches = branches
66+
};
67+
68+
return this;
69+
}
70+
71+
/// <summary>
72+
/// Configures the pipeline to trigger on pull request events for specified branches.
73+
/// </summary>
74+
/// <param name="branches">The branches to trigger on pull request events.</param>
75+
/// <returns>The current instance of <see cref="GitHubPipelineBuilder"/>.</returns>
76+
public GitHubPipelineBuilder OnPullRequest(params string[] branches)
77+
{
78+
this.githubPipeline.OnEvents.PullRequest = new PullRequestEvent
79+
{
80+
Branches = branches
81+
};
82+
83+
return this;
84+
}
85+
86+
/// <summary>
87+
/// Adds a job to the GitHub pipeline.
88+
/// </summary>
89+
/// <param name="jobIdentifier">The unique identifier for the job.</param>
90+
/// <param name="configureJob">The action to configure the job.</param>
91+
/// <returns>The current instance of <see cref="GitHubPipelineBuilder"/>.</returns>
92+
public GitHubPipelineBuilder AddJob(string jobIdentifier, Action<JobBuilder> configureJob)
93+
{
94+
var jobBuilder = new JobBuilder();
95+
configureJob(jobBuilder);
96+
this.githubPipeline.Jobs[jobIdentifier] = jobBuilder.Build();
97+
98+
return this;
99+
}
100+
101+
/// <summary>
102+
/// Saves the configured pipeline (yml) to the specified file path.
103+
/// </summary>
104+
/// <param name="path">The file path where the pipeline will be saved.</param>
105+
public void SaveToFile(string path) =>
106+
this.aDotNetClient.SerializeAndWriteToFile(this.githubPipeline, path);
107+
}
108+
}
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
// ---------------------------------------------------------------------------
2+
// Copyright (c) Hassan Habib & Shri Humrudha Jagathisun All rights reserved.
3+
// Licensed under the MIT License.
4+
// See License.txt in the project root for license information.
5+
// ---------------------------------------------------------------------------
6+
7+
using System.Collections.Generic;
8+
using ADotNet.Models.Pipelines.GithubPipelines.DotNets;
9+
using ADotNet.Models.Pipelines.GithubPipelines.DotNets.Tasks;
10+
using ADotNet.Models.Pipelines.GithubPipelines.DotNets.Tasks.SetupDotNetTaskV1s;
11+
12+
namespace ADotNet.Clients.Builders
13+
{
14+
/// <summary>
15+
/// A builder to create a job for a GitHub Actions workflow.
16+
/// </summary>
17+
public class JobBuilder
18+
{
19+
private readonly Job job;
20+
21+
internal JobBuilder()
22+
{
23+
this.job = new Job
24+
{
25+
Steps = new List<GithubTask>(),
26+
EnvironmentVariables = null
27+
};
28+
}
29+
30+
/// <summary>
31+
/// Sets the name of the job.
32+
/// </summary>
33+
/// <param name="name">The name of the job.</param>
34+
/// <returns>The current instance of <see cref="JobBuilder"/>.</returns>
35+
public JobBuilder WithName(string name)
36+
{
37+
this.job.Name = name;
38+
39+
return this;
40+
}
41+
42+
/// <summary>
43+
/// Specifies the machine on which the job will run.
44+
/// </summary>
45+
/// <param name="machine">The machine or environment to run the job on.</param>
46+
/// <returns>The current instance of <see cref="JobBuilder"/>.</returns>
47+
public JobBuilder RunsOn(string machine)
48+
{
49+
this.job.RunsOn = machine;
50+
51+
return this;
52+
}
53+
54+
/// <summary>
55+
/// Adds an environment variable to the job.
56+
/// </summary>
57+
/// <param name="key">The key of the environment variable.</param>
58+
/// <param name="value">The value of the environment variable.</param>
59+
/// <returns>The current instance of <see cref="JobBuilder"/>.</returns>
60+
public JobBuilder AddEnvironmentVariable(string key, string value)
61+
{
62+
this.job.EnvironmentVariables ??= new Dictionary<string, string>();
63+
64+
this.job.EnvironmentVariables[key] = value;
65+
66+
return this;
67+
}
68+
69+
/// <summary>
70+
/// Adds multiple environment variables to the job.
71+
/// </summary>
72+
/// <param name="variables">A dictionary of environment variables to add.</param>
73+
/// <returns>The current instance of <see cref="JobBuilder"/>.</returns>
74+
public JobBuilder AddEnvironmentVariables(Dictionary<string, string> variables)
75+
{
76+
this.job.EnvironmentVariables ??= new Dictionary<string, string>();
77+
78+
foreach (var variable in variables)
79+
{
80+
this.job.EnvironmentVariables[variable.Key] = variable.Value;
81+
}
82+
83+
return this;
84+
}
85+
86+
/// <summary>
87+
/// Adds a checkout step to the job.
88+
/// </summary>
89+
/// <param name="name">The name of the checkout step (default: "Check out").</param>
90+
/// <returns>The current instance of <see cref="JobBuilder"/>.</returns>
91+
public JobBuilder AddCheckoutStep(string name = "Check out")
92+
{
93+
this.job.Steps.Add(new CheckoutTaskV2 { Name = name });
94+
95+
return this;
96+
}
97+
98+
/// <summary>
99+
/// Adds a setup step for a specific .NET version to the job.
100+
/// </summary>
101+
/// <param name="version">The version of .NET to set up.</param>
102+
/// <param name="stepName">The name of the setup step (default: "Setup Dot Net Version").</param>
103+
/// <param name="includePrerelease">Specifies whether to include prerelease versions.</param>
104+
/// <returns>The current instance of <see cref="JobBuilder"/>.</returns>
105+
public JobBuilder AddSetupDotNetStep(
106+
string version,
107+
string stepName = "Setup Dot Net Version",
108+
bool includePrerelease = false)
109+
{
110+
this.job.Steps.Add(new SetupDotNetTaskV1
111+
{
112+
Name = stepName,
113+
TargetDotNetVersion = new TargetDotNetVersion
114+
{
115+
DotNetVersion = version,
116+
IncludePrerelease = includePrerelease
117+
}
118+
});
119+
120+
return this;
121+
}
122+
123+
/// <summary>
124+
/// Adds a restore step to the job.
125+
/// </summary>
126+
/// <param name="name">The name of the restore step (default: "Restore").</param>
127+
/// <returns>The current instance of <see cref="JobBuilder"/>.</returns>
128+
public JobBuilder AddRestoreStep(string name = "Restore")
129+
{
130+
this.job.Steps.Add(new RestoreTask { Name = name });
131+
132+
return this;
133+
}
134+
135+
/// <summary>
136+
/// Adds a build step to the job.
137+
/// </summary>
138+
/// <param name="name">The name of the build step (default: "Build").</param>
139+
/// <returns>The current instance of <see cref="JobBuilder"/>.</returns>
140+
public JobBuilder AddBuildStep(string name = "Build")
141+
{
142+
this.job.Steps.Add(new DotNetBuildTask { Name = name });
143+
144+
return this;
145+
}
146+
147+
/// <summary>
148+
/// Adds a test step to the job.
149+
/// </summary>
150+
/// <param name="name">The name of the test step (default: "Test").</param>
151+
/// <param name="command">The command to execute the test
152+
/// (default: "dotnet test --no-build --verbosity normal").</param>
153+
/// <returns>The current instance of <see cref="JobBuilder"/>.</returns>
154+
public JobBuilder AddTestStep(string name = "Test", string command = null)
155+
{
156+
this.job.Steps.Add(new TestTask
157+
{
158+
Name = name,
159+
Run = command ?? "dotnet test --no-build --verbosity normal"
160+
});
161+
162+
return this;
163+
}
164+
165+
/// <summary>
166+
/// Adds a generic step to the job with a custom command.
167+
/// </summary>
168+
/// <param name="name">The name of the step.</param>
169+
/// <param name="runCommand">The command to execute for this step.</param>
170+
/// <returns>The current instance of <see cref="JobBuilder"/>.</returns>
171+
public JobBuilder AddGenericStep(string name, string runCommand)
172+
{
173+
this.job.Steps.Add(new GithubTask
174+
{
175+
Name = name,
176+
Run = runCommand
177+
});
178+
179+
return this;
180+
}
181+
182+
/// <summary>
183+
/// Builds and returns the configured job.
184+
/// </summary>
185+
/// <returns>The configured <see cref="Job"/> instance.</returns>
186+
public Job Build() => this.job;
187+
}
188+
}

AdoNet.Tests.Console/Program.cs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
using System.Collections.Generic;
88
using ADotNet.Clients;
9+
using ADotNet.Clients.Builders;
910
using ADotNet.Models.Pipelines.AdoPipelines.AspNets;
1011
using ADotNet.Models.Pipelines.AdoPipelines.AspNets.Tasks.DotNetExecutionTasks;
1112
using ADotNet.Models.Pipelines.AdoPipelines.AspNets.Tasks.PublishBuildArtifactTasks;
@@ -185,6 +186,42 @@ static void Main(string[] args)
185186
};
186187

187188
adoClient.SerializeAndWriteToFile(githubPipeline, "github-pipelines.yaml");
189+
190+
string projectName = "OtripleS.Api.Infrastructure.Provision";
191+
192+
GitHubPipelineBuilder.CreateNewPipeline()
193+
.SetName("Github")
194+
.OnPush("master")
195+
.OnPullRequest("master")
196+
197+
.AddJob("build", job => job
198+
.WithName("Build")
199+
.RunsOn(BuildMachines.WindowsLatest)
200+
.AddEnvironmentVariable("AzureClientId", "${{ secrets.AZURECLIENTID }}")
201+
202+
.AddEnvironmentVariables(new Dictionary<string, string>
203+
{
204+
{ "AzureTenantId", "${{ secrets.AZURETENANTID }}" },
205+
{ "AzureClientSecret", "${{ secrets.AZURECLIENTSECRET }}" },
206+
{ "AzureAdminName", "${{ secrets.AZUREADMINNAME }}" },
207+
{ "AzureAdminAccess", "${{ secrets.AZUREADMINACCESS }}" }
208+
})
209+
210+
.AddCheckoutStep("Check Out")
211+
212+
.AddSetupDotNetStep(
213+
version: "6.0.101",
214+
includePrerelease: true)
215+
216+
.AddRestoreStep()
217+
.AddBuildStep()
218+
219+
.AddGenericStep(
220+
name: "Provision",
221+
runCommand:
222+
"dotnet run --project .\\{projectName}\\{projectName}.csproj"))
223+
224+
.SaveToFile("github-pipelines-fluent.yaml");
188225
}
189226
}
190227
}

0 commit comments

Comments
 (0)