2
2
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
3
3
4
4
using Logicality . GitHub . Actions . Workflow ;
5
+ using System . ComponentModel ;
6
+ using System . IO ;
5
7
using static GitHubContexts ;
6
8
7
9
var contexts = Instance ;
31
33
{
32
34
GenerateCiWorkflow ( component ) ;
33
35
GenerateReleaseWorkflow ( component ) ;
36
+ GenerateUploadTestResultsWorkflow ( component ) ;
34
37
}
35
38
36
39
void GenerateCiWorkflow ( Component component )
37
40
{
38
- var workflow = new Workflow ( $ " { component . Name } /ci" ) ;
41
+ var workflow = new Workflow ( component . CiWorkflowName ) ;
39
42
var paths = new [ ]
40
43
{
41
44
$ ".github/workflows/{ component . Name } -**",
@@ -57,6 +60,7 @@ void GenerateCiWorkflow(Component component)
57
60
var job = workflow
58
61
. Job ( "build" )
59
62
. Name ( "Build" )
63
+ . RunEitherOnBranchOrAsPR ( )
60
64
. RunsOn ( GitHubHostedRunners . UbuntuLatest )
61
65
. Defaults ( ) . Run ( "bash" , component . Name )
62
66
. Job ;
@@ -76,9 +80,11 @@ void GenerateCiWorkflow(Component component)
76
80
77
81
foreach ( var testProject in component . Tests )
78
82
{
79
- job . StepTestAndReport ( component . Name , testProject ) ;
83
+ job . StepTest ( component . Name , testProject ) ;
80
84
}
81
85
86
+ job . StepUploadTestResultsAsArtifact ( component . Tests ) ;
87
+
82
88
job . StepToolRestore ( ) ;
83
89
84
90
foreach ( var project in component . Projects )
@@ -102,7 +108,7 @@ void GenerateCiWorkflow(Component component)
102
108
103
109
void GenerateReleaseWorkflow ( Component component )
104
110
{
105
- var workflow = new Workflow ( $ " { component . Name } /release" ) ;
111
+ var workflow = new Workflow ( component . ReleaseWorkflowName ) ;
106
112
107
113
workflow . On
108
114
. WorkflowDispatch ( )
@@ -169,17 +175,69 @@ git tag -a {component.TagPrefix}-{contexts.Event.Input.Version} -m ""Release v{c
169
175
WriteWorkflow ( workflow , fileName ) ;
170
176
}
171
177
178
+ void GenerateUploadTestResultsWorkflow ( Component component )
179
+ {
180
+ var workflow = new Workflow ( component . TestResultWorkflowName ) ;
181
+ workflow . On
182
+ . WorkflowRun ( )
183
+ . Workflows ( component . TestResultWorkflowName )
184
+ . Types ( "completed" ) ;
185
+
186
+ var job = workflow
187
+ . Job ( "report" )
188
+ . Name ( "report" )
189
+ . RunsOn ( GitHubHostedRunners . UbuntuLatest ) ;
190
+
191
+ job . Permissions (
192
+ actions : Permission . Read ,
193
+ contents : Permission . Read ,
194
+ checks : Permission . Write ,
195
+ packages : Permission . Write ) ;
196
+
197
+ foreach ( var testProject in component . Tests )
198
+ {
199
+ job . StepGenerateReportFromTestArtifact ( component . Name , testProject ) ;
200
+ }
201
+
202
+ }
203
+
172
204
void WriteWorkflow ( Workflow workflow , string fileName )
173
205
{
174
206
var filePath = $ "../workflows/{ fileName } .yml";
175
207
workflow . WriteYaml ( filePath ) ;
176
208
Console . WriteLine ( $ "Wrote workflow to { filePath } ") ;
177
209
}
178
210
179
- record Component ( string Name , string [ ] Projects , string [ ] Tests , string TagPrefix ) ;
211
+ record Component ( string Name , string [ ] Projects , string [ ] Tests , string TagPrefix )
212
+ {
213
+ public string CiWorkflowName => $ "{ Name } /ci";
214
+ public string ReleaseWorkflowName => $ "{ Name } /release";
215
+ public string TestResultWorkflowName => $ "{ Name } /test-results";
216
+ }
180
217
181
218
public static class StepExtensions
182
219
{
220
+
221
+ /// <summary>
222
+ /// The build triggers both on branch AND on pull_request.
223
+ ///
224
+ /// Only (trusted) contributors can open branches in the main repo, so these builds can run with a higher trust level.
225
+ /// So, they are running with trigger 'push'. These builds have access to the secrets and thus they can do things like
226
+ /// sign, push the packages, etc..
227
+ ///
228
+ /// External contributors can only create branches on external repo's. These builds run with a lower trust level.
229
+ /// So, they are running with trigger 'pull_request'. These builds do not have access to the secrets and thus they can't
230
+ /// sign, push the packages, etc..
231
+ ///
232
+ /// Now, if a trusted contributor creates a branch in the main repo, then creates a PR, we don't want to run the build twice.
233
+ /// This prevents that. The build will only run once, on the branch with the higher trust level.
234
+ ///
235
+ /// </summary>
236
+ public static Job RunEitherOnBranchOrAsPR ( this Job job )
237
+ => job . If (
238
+ "(github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) || (github.event_name == 'push')" ) ;
239
+
240
+
183
241
public static void EnvDefaults ( this Workflow workflow )
184
242
=> workflow . Env (
185
243
( "DOTNET_NOLOGO" , "true" ) ,
@@ -193,7 +251,7 @@ public static void StepSetupDotNet(this Job job)
193
251
public static Step IfRefMain ( this Step step )
194
252
=> step . If ( "github.ref == 'refs/heads/main'" ) ;
195
253
196
- public static void StepTestAndReport ( this Job job , string componentName , string testProject )
254
+ public static void StepTest ( this Job job , string componentName , string testProject )
197
255
{
198
256
var path = $ "test/{ testProject } ";
199
257
var logFileName = "Tests.trx" ;
@@ -204,13 +262,34 @@ public static void StepTestAndReport(this Job job, string componentName, string
204
262
. Name ( $ "Test - { testProject } ")
205
263
. Run ( $ "dotnet test -c Release { path } { flags } ") ;
206
264
265
+ }
266
+
267
+ private static readonly string LogFileName = "Tests.trx" ;
268
+
269
+ public static void StepUploadTestResultsAsArtifact ( this Job job , string [ ] testProjects )
270
+ {
271
+ job . Step ( )
272
+ . Name ( "Upload test artifact" )
273
+ . If ( "success() || failure()" )
274
+ . Uses ( "actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882" ) // 4.4.3
275
+ . With (
276
+ ( "name" , "test-results" ) ,
277
+ ( "path" , string . Join ( Environment . NewLine , testProjects
278
+ . Select ( testProject => $ "test/{ testProject } /TestResults/{ LogFileName } ") ) ) ,
279
+ ( "retention-days" , "5" ) ) ;
280
+ }
281
+
282
+ public static void StepGenerateReportFromTestArtifact ( this Job job , string componentName , string testProject )
283
+ {
284
+ var path = $ "test/{ testProject } ";
207
285
job . Step ( )
208
286
. Name ( $ "Test report - { testProject } ")
209
287
. Uses ( "dorny/test-reporter@31a54ee7ebcacc03a09ea97a7e5465a47b84aea5" ) // v1.9.1
210
288
. If ( "github.event == 'push' && (success() || failure())" )
211
289
. With (
290
+ ( "artifact" , "test-results" ) ,
212
291
( "name" , $ "Test Report - { testProject } ") ,
213
- ( "path" , $ "{ componentName } /{ path } /TestResults/{ logFileName } ") ,
292
+ ( "path" , $ "{ componentName } /{ path } /TestResults/{ LogFileName } ") ,
214
293
( "reporter" , "dotnet-trx" ) ,
215
294
( "fail-on-error" , "true" ) ,
216
295
( "fail-on-empty" , "true" ) ) ;
0 commit comments