1
1
using Logicality . GitHub . Actions . Workflow ;
2
- using System . IO ;
3
2
4
- void WriteWorkflow ( Workflow workflow , string fileName )
5
- {
6
- var filePath = $ "../workflows/{ fileName } .yml";
7
- workflow . WriteYaml ( filePath ) ;
8
- Console . WriteLine ( $ "Wrote workflow to { filePath } ") ;
9
- }
3
+ Component [ ] components = [
4
+ new ( "ignore-this" ,
5
+ [ "IgnoreThis" ] ,
6
+ [ "IgnoreThis.Tests" ] ) ,
10
7
8
+ new ( "access-token-management" ,
9
+ [ "AccessTokenManagement" , "AccessTokenManagement.OpenIdConnect" ] ,
10
+ [ "AccessTokenManagement.Tests" ] ) ,
11
11
12
- Component [ ] components = [
13
- new ( "ignore-this" , [ "IgnoreThis" ] , [ "IgnoreThis.Tests" ] ) ,
14
- ] ;
15
-
16
- ( string Key , string Value ) EnvSecret ( string key ) => ( key , $ "${{secrets.{ key } }}") ;
12
+ new ( "identity-model" ,
13
+ [ "IdentityModel" ] ,
14
+ [ "IdentityModel.Tests" ] ) ,
17
15
16
+ new ( "identity-model-oidc-client" ,
17
+ [ "IdentityModel.OidcClient" , "IdentityModel.OidcClient.DPoP" , "IdentityModel.OidcClient.IdentityTokenValidator" ] ,
18
+ [ "IdentityModel.OidcClient.Tests" , "IdentityModel.OidcClient.DPoP.Tests" , "IdentityModel.OidcClient.IdentityTokenValidator.Tests" ] )
19
+ ] ;
18
20
19
21
foreach ( var component in components )
20
22
{
21
- var workflow = new Workflow ( $ "{ component . Name } -ci") ;
22
- var paths = new [ ] { $ ".github/workflows/{ component . Name } -ci", $ "src/{ component . Name } /**" } ;
23
+ GenerateCiWorkflow ( component ) ;
24
+ GenerateReleaseWorkflow ( component ) ;
25
+ }
26
+
27
+ void GenerateCiWorkflow ( Component component )
28
+ {
29
+ var workflow = new Workflow ( $ "{ component . Name } /ci") ;
30
+ var paths = new [ ] { $ ".github/workflows/{ component . Name } -**", $ "src/{ component . Name } /**" } ;
23
31
24
- workflow . On . WorkflowDispatch ( ) ;
32
+ workflow . On
33
+ . WorkflowDispatch ( ) ;
25
34
workflow . On
26
35
. Push ( )
27
- . Branches ( "main" ) ;
36
+ . Paths ( paths ) ;
28
37
workflow . On
29
38
. PullRequest ( )
30
39
. Paths ( paths ) ;
31
40
32
- workflow . Env (
33
- ( "DOTNETT_NOLOGO" , "true" ) ,
34
- ( "DOTNET_CLI_TELEMETRY_OPTOUT" , "true" ) ) ;
41
+ workflow . EnvDefaults ( ) ;
35
42
36
43
var job = workflow
37
44
. Job ( "build" )
38
45
. Name ( "Build" )
39
46
. RunsOn ( GitHubHostedRunners . UbuntuLatest )
47
+ . Defaults ( ) . Run ( "bash" , component . Name )
48
+ . Job ;
49
+
50
+ job . Step ( )
51
+ . ActionsCheckout ( ) ;
52
+
53
+ job . StepSetupDotNet ( ) ;
54
+
55
+ foreach ( var testProject in component . Tests )
56
+ {
57
+ job . StepTestAndReport ( component . Name , testProject ) ;
58
+ }
59
+
60
+ job . StepInstallCACerts ( ) ;
61
+
62
+ job . StepToolRestore ( ) ;
63
+
64
+ foreach ( var project in component . Projects )
65
+ {
66
+ job . StepPack ( component . Name , project ) ;
67
+ }
68
+
69
+ job . StepSign ( ) ;
70
+
71
+ job . StepPush ( "MyGet" , "https://www.myget.org/F/duende_identityserver/api/v2/package" , "MYGET" ) ;
72
+
73
+ job . StepPush ( "GitHub" , "https://nuget.pkg.github.com/DuendeSoftware/index.json" , "GITHUB_TOKEN" )
74
+ . Env ( ( "GITHUB_TOKEN" , "${{ secrets.GITHUB_TOKEN }}" ) ,
75
+ ( "NUGET_AUTH_TOKEN" , "${{ secrets.GITHUB_TOKEN }}" ) ) ;
76
+
77
+ job . StepUploadArtifacts ( component . Name ) ;
78
+
79
+ var fileName = $ "{ component . Name } -ci";
80
+ WriteWorkflow ( workflow , fileName ) ;
81
+ }
82
+
83
+ void GenerateReleaseWorkflow ( Component component )
84
+ {
85
+ var workflow = new Workflow ( $ "{ component . Name } /release") ;
86
+
87
+ workflow . On
88
+ . WorkflowDispatch ( )
89
+ . Inputs ( new StringInput ( "version" , "Version in format X.Y.Z or X.Y.Z-preview." , true , "0.0.0" ) ) ;
90
+
91
+ workflow . EnvDefaults ( ) ;
92
+
93
+ var tagJob = workflow . Job ( "tag" )
94
+ . Name ( "Tag and Pack" )
95
+ . RunsOn ( GitHubHostedRunners . UbuntuLatest )
96
+ . Permissions ( contents : Permission . Write , packages : Permission . Write )
40
97
. Defaults ( ) . Run ( "pwsh" , component . Name )
41
98
. Job ;
42
99
43
- job . Step ( ) . ActionsCheckout ( ) ;
100
+ tagJob . Step ( )
101
+ . ActionsCheckout ( ) ;
102
+
103
+ tagJob . StepSetupDotNet ( ) ;
104
+
105
+ tagJob . Step ( )
106
+ . Name ( "Git tag" )
107
+ . Run ( """
108
+ git config --global user.email "github-bot@duendesoftware.com"
109
+ git config --global user.name "Duende Software GitHub Bot"
110
+ git tag -a it-${{ github.event.inputs.version }} -m "Release v${{ github.event.inputs.version }}"
111
+ git push origin it-${{ github.event.inputs.version }}
112
+ """ ) ;
113
+
114
+ tagJob . StepInstallCACerts ( ) ;
115
+
116
+ foreach ( var project in component . Projects )
117
+ {
118
+ tagJob . StepPack ( component . Name , project ) ;
119
+ }
120
+
121
+ tagJob . StepSign ( ) ;
44
122
45
- job . Step ( ) . ActionsSetupDotNet ( "8.0.x ") ;
123
+ tagJob . StepPush ( "MyGet" , "https://www.myget.org/F/duende_identityserver/api/v2/package" , "MYGET ") ;
46
124
47
- foreach ( var testProject in component . Tests )
125
+ tagJob . StepPush ( "GitHub" , "https://nuget.pkg.github.com/DuendeSoftware/index.json" , "GITHUB_TOKEN" )
126
+ . Env ( ( "GITHUB_TOKEN" , "${{ secrets.GITHUB_TOKEN }}" ) ,
127
+ ( "NUGET_AUTH_TOKEN" , "${{ secrets.GITHUB_TOKEN }}" ) ) ;
128
+
129
+ tagJob . StepUploadArtifacts ( component . Name ) ;
130
+
131
+ var publishJob = workflow . Job ( "publish" )
132
+ . Name ( "Publish to nuget.org" )
133
+ . RunsOn ( GitHubHostedRunners . UbuntuLatest )
134
+ . Environment ( "nuget.org" , "" ) ;
135
+
136
+ publishJob . Step ( )
137
+ . Uses ( "actions/download-artifact@v4" )
138
+ . With ( ( "name" , "artifacts" ) , ( "path" , "artifacts" ) ) ;
139
+
140
+ publishJob . StepSetupDotNet ( ) ;
141
+
142
+ publishJob . Step ( )
143
+ . Name ( "List files" )
144
+ . Shell ( "bash" )
145
+ . Run ( "tree" ) ;
146
+
147
+ publishJob . StepPush ( "nuget.org" , "https://api.nuget.org/v3/index.json" , "NUGET_ORG_API_KEY" ) ;
148
+
149
+ var fileName = $ "{ component . Name } -release";
150
+ WriteWorkflow ( workflow , fileName ) ;
151
+ }
152
+
153
+ void WriteWorkflow ( Workflow workflow , string fileName )
154
+ {
155
+ var filePath = $ "../workflows/{ fileName } .yml";
156
+ workflow . WriteYaml ( filePath ) ;
157
+ Console . WriteLine ( $ "Wrote workflow to { filePath } ") ;
158
+ }
159
+
160
+
161
+
162
+
163
+ record Component ( string Name , string [ ] Projects , string [ ] Tests ) ;
164
+
165
+ public static class StepExtensions
166
+ {
167
+ public static void EnvDefaults ( this Workflow workflow )
168
+ => workflow . Env (
169
+ ( "DOTNETT_NOLOGO" , "true" ) ,
170
+ ( "DOTNET_CLI_TELEMETRY_OPTOUT" , "true" ) ) ;
171
+
172
+ public static void StepSetupDotNet ( this Job job )
173
+ => job . Step ( )
174
+ . Name ( "Setup .NET" )
175
+ . ActionsSetupDotNet ( "8.0.x" ) ;
176
+
177
+ public static Step IfRefMain ( this Step step )
178
+ => step . If ( "github.ref == 'refs/heads/main'" ) ;
179
+
180
+ public static void StepTestAndReport ( this Job job , string componentName , string testProject )
48
181
{
49
- var path = $ "{ component . Name } / test/{ testProject } ";
182
+ var path = $ "test/{ testProject } ";
50
183
var logFileName = "Tests.trx" ;
51
184
var flags = $ "--logger \" console;verbosity=normal\" " +
52
185
$ "--logger \" trx;LogFileName={ logFileName } \" " +
@@ -61,25 +194,77 @@ void WriteWorkflow(Workflow workflow, string fileName)
61
194
. If ( "success() || failure()" )
62
195
. With (
63
196
( "name" , "Test Report" ) ,
64
- ( "path" , $ "{ path } /TestResults/{ logFileName } ") ,
197
+ ( "path" , $ "{ componentName } / { path } /TestResults/{ logFileName } ") ,
65
198
( "reporter" , "dotnet-trx" ) ,
66
199
( "fail-on-error" , "true" ) ,
67
200
( "fail-on-empty" , "true" ) ) ;
68
201
}
69
202
70
- job . Step ( )
71
- . Name ( "Install Sectigo CodeSiging CA certificates" )
72
- . Run ( """
73
- sudo apt-get update
74
- sudo apt-get install -y ca-certificates
75
- sudo cp build/SectigoPublicCodeSigningRootCrossAAA.crt /usr/local/share/ca-certificates/
76
- sudo update-ca-certificates
77
-
78
- """ ) ;
79
-
80
- var fileName = $ "{ component . Name } -ci-gen";
203
+ public static void StepInstallCACerts ( this Job job )
204
+ => job . Step ( )
205
+ . Name ( "Install Sectigo CodeSiging CA certificates" )
206
+ . IfRefMain ( )
207
+ . Run ( """
208
+ sudo apt-get update
209
+ sudo apt-get install -y ca-certificates
210
+ sudo cp build/SectigoPublicCodeSigningRootCrossAAA.crt /usr/local/share/ca-certificates/
211
+ sudo update-ca-certificates
212
+ """ ) ;
81
213
82
- WriteWorkflow ( workflow , fileName ) ;
83
- }
214
+ public static void StepToolRestore ( this Job job )
215
+ => job . Step ( )
216
+ . Name ( "Tool restore" )
217
+ . IfRefMain ( )
218
+ . Run ( "dotnet tool restore" ) ;
84
219
85
- record Component ( string Name , string [ ] Projects , string [ ] Tests ) ;
220
+ public static void StepPack ( this Job job , string componentName , string project )
221
+ {
222
+ var path = $ "{ componentName } /src/{ project } ";
223
+ job . Step ( )
224
+ . Name ( $ "Pack { project } ")
225
+ . IfRefMain ( )
226
+ . Run ( $ "dotnet pack -c Release { path } --no-build -o artifacts") ;
227
+ }
228
+
229
+ public static void StepSign ( this Job job )
230
+ {
231
+ var flags = "--file-digest sha256 " +
232
+ "--timestamp-rfc3161 http://timestamp.digicert.com " +
233
+ "--azure-key-vault-url https://duendecodesigning.vault.azure.net/ " +
234
+ "--azure-key-vault-client-id 18e3de68-2556-4345-8076-a46fad79e474 " +
235
+ "--azure-key-vault-tenant-id ed3089f0-5401-4758-90eb-066124e2d907 " +
236
+ "--azure-key-vault-client-secret ${{ secrets.SignClientSecret }} " +
237
+ "--azure-key-vault-certificate CodeSigning" ;
238
+ job . Step ( )
239
+ . Name ( "Sign packages" )
240
+ . IfRefMain ( )
241
+ . Run ( $ """
242
+ for file in artifacts/*.nupkg; do
243
+ dotnet NuGetKeyVaultSignTool sign \"$file\" { flags }
244
+ done
245
+ """ ) ;
246
+ }
247
+
248
+ public static Step StepPush ( this Job job , string destination , string sourceUrl , string secretName )
249
+ {
250
+ var apiKey = $ "${{ secrets.{ secretName } }}";
251
+ return job . Step ( )
252
+ . Name ( $ "Push packages to { destination } ")
253
+ . IfRefMain ( )
254
+ . Run ( $ "dotnet nuget push artifacts/*.nupkg --source { sourceUrl } --api-key { apiKey } --skip-duplicate") ;
255
+ }
256
+
257
+ public static void StepUploadArtifacts ( this Job job , string componentName )
258
+ {
259
+ var path = $ "{ componentName } /artifacts/*.nupkg";
260
+ job . Step ( )
261
+ . Name ( "Upload Artifacts" )
262
+ . IfRefMain ( )
263
+ . Uses ( "actions/upload-artifact@v4" )
264
+ . With (
265
+ ( "name" , "artifacts" ) ,
266
+ ( "path" , path ) ,
267
+ ( "overwrite" , "true" ) ,
268
+ ( "retention-days" , "15" ) ) ;
269
+ }
270
+ }
0 commit comments