1
- name : ' DevOps Practices for Azure Cosmos DB - GitHub Actions Workflow '
1
+ name : ' DevOps Practices for Azure Cosmos DB'
2
2
on :
3
3
workflow_dispatch :
4
4
push :
10
10
11
11
jobs :
12
12
Build :
13
- name : ' Build Web App'
13
+ name : ' Build .NET Web App'
14
14
runs-on : ubuntu-latest
15
15
steps :
16
16
- name : Repository checkout
37
37
path : publish
38
38
39
39
Testing :
40
- name : ' Testing'
40
+ name : ' Testing with Cosmos DB Emulator '
41
41
runs-on : windows-latest # Azure Cosmos DB Emulator only supports Windows, although you can run it in a Docker container. https://learn.microsoft.com/azure/cosmos-db/local-emulator#run-on-linux-macos
42
42
steps :
43
43
- name : Repository checkout
@@ -69,79 +69,19 @@ jobs:
69
69
uses : actions/setup-node@v3
70
70
with :
71
71
node-version : latest
72
- - name : Install NPM Azure Cosmos dependency
72
+
73
+ - name : Install Azure Cosmos dependency
73
74
run : npm install @azure/cosmos
75
+
76
+ # The following steps are optional and are only used to demonstrate how to create and test Stored Procedures and Triggers with the Azure Cosmos DB Emulator.
74
77
- name : Create and test Stored Procedure with Azure Cosmos DB Emulator
75
- uses : actions/github-script@v6
76
- with :
77
- script : | # This is the default connection string for the Azure Cosmos DB Emulator and TLS Reject is disabled for the emulator self-certificate.
78
- process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
79
- async function createSP() {
80
- const { CosmosClient } = require("@azure/cosmos");
81
- const endpoint = "https://localhost:8081";
82
- const key = "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==";
83
- const client = new CosmosClient({ endpoint, key });
84
- const { database } = await client.databases.createIfNotExists({ id: 'SampleDatabase' });
85
- const { container } = await database.containers.createIfNotExists({ id: 'WebAppContext' });
86
- const { sampleStoredProcedure } = require('./StoredProcedures/SampleStoredProcedure.js');
87
- try {
88
- await container.scripts.storedProcedures.create(sampleStoredProcedure)
89
- } catch (e) {
90
- if (e.code === 409) {
91
- console.log('Stored procedure already exists replacing it with new version.')
92
- await container.scripts.storedProcedure(sampleStoredProcedure.id).replace(sampleStoredProcedure)
93
- } else {
94
- throw(e)
95
- }
96
- }
97
- finally{
98
- const { resource: results } = await container.scripts.storedProcedure(sampleStoredProcedure.id).execute();
99
- console.log(results);
100
- }
101
- }
102
- createSP().catch(error => {
103
- console.error("An error occurred: ", error);
104
- });
78
+ run : node Scripts/createSP.js https://localhost:8081 C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw== SampleDatabase WebAppContext StoredProcedures/SampleStoredProcedure.js 1
105
79
106
- - name : Create and test Trigger
107
- uses : actions/github-script@v6
108
- with :
109
- script : | # This is the default connection string for the Azure Cosmos DB Emulator and TLS Reject is disabled for the emulator self-certificate.
110
- process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
111
- async function createTrigger() {
112
- const { CosmosClient } = require("@azure/cosmos");
113
- const endpoint = "https://localhost:8081";
114
- const key = "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==";
115
- const client = new CosmosClient({ endpoint, key });
116
- const { database } = await client.databases.createIfNotExists({ id: 'SampleDatabase' });
117
- const { container } = await database.containers.createIfNotExists({ id: 'WebAppContext' });
118
- const { sampleTrigger } = require('./Triggers/SampleTrigger.js')
119
- try {
120
- await container.scripts.triggers.create(sampleTrigger)
121
- } catch (e) {
122
- if (e.code === 409) {
123
- console.log('Trigger already exists replacing it with new version.')
124
- await container.scripts.trigger(sampleTrigger.id).replace(sampleTrigger)
125
- } else {
126
- throw(e)
127
- }
128
- }
129
- finally {
130
- const newItem = {
131
- id: Math.floor(Math.random() * 10000).toString(),
132
- name: 'Sample Item'
133
- };
134
- const options = { preTriggerInclude: ['SampleTrigger'] };
135
- const { resource: trigger_result } = await container.items.create(newItem, options)
136
- console.log(trigger_result)
137
- }
138
- }
139
- createTrigger().catch(error => {
140
- console.error("An error occurred: ", error);
141
- });
80
+ - name : Create and test Trigger with Azure Cosmos DB Emulator
81
+ run : node Scripts/createTrigger.js https://localhost:8081 C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw== SampleDatabase WebAppContext Triggers/SampleTrigger.js 1
142
82
143
83
QA :
144
- name : ' Quality Assurance'
84
+ name : ' Quality Assurance in Azure Test Environment '
145
85
runs-on : ubuntu-latest
146
86
environment : QA
147
87
needs : [Build, Testing]
@@ -158,91 +98,35 @@ jobs:
158
98
az group create --name ${{ vars.RESOURCEGROUP }} --location eastus
159
99
160
100
- name : Provisioning Azure resources
161
- id : arm_deployment
101
+ id : arm_deploy
162
102
uses : azure/arm-deploy@v1
163
103
with :
164
104
resourceGroupName : ${{ vars.RESOURCEGROUP }}
165
105
template : IaC/cosmosdb.json
166
106
parameters : IaC/cosmosdb.QA-parameters.json
167
107
deploymentMode : ' Complete'
168
- env :
169
- cosmoskey : ::add-mask::${{ steps.arm_deployment.outputs.cosmosDBkey }}
108
+
109
+ - name : Get CosmosDB Key
110
+ id : get_cosmos_key
111
+ run : | # Mask the key in the logs
112
+ primary_key=$(az cosmosdb keys list --name ${{ steps.arm_deploy.outputs.cosmosDBName }} --resource-group ${{ vars.RESOURCEGROUP }} --query primaryMasterKey --output tsv)
113
+ echo "::add-mask::$primary_key"
114
+ echo "cosmosDBKey=$primary_key" >> $GITHUB_ENV
170
115
171
116
- name : Setup Node.js
172
117
uses : actions/setup-node@v3
173
118
with :
174
119
node-version : latest
175
120
176
- - name : Install NPM Azure Cosmos and Azure Identity dependencies
121
+ - name : Install Azure Cosmos dependency
177
122
run : npm install @azure/cosmos
178
-
179
- - name : Create and test Stored Procedure in Azure Cosmos DB
180
- uses : actions/github-script@v6
181
- with :
182
- script : | # The Cosmos DB Key never should be accesed as plain text. It is only for demo purposes.
183
- async function createSP() {
184
- const { CosmosClient } = require("@azure/cosmos");
185
- const endpoint = "${{ steps.arm_deployment.outputs.cosmosDBendpoint }}";
186
- const key = "${{ env.cosmoskey }} ";
187
- const client = new CosmosClient({ endpoint, key });
188
- const { database } = await client.databases.createIfNotExists({ id: 'SampleDatabase' });
189
- const { container } = await database.containers.createIfNotExists({ id: 'WebAppContext' });
190
- const { sampleStoredProcedure } = require('./StoredProcedures/SampleStoredProcedure.js');
191
- try {
192
- await container.scripts.storedProcedures.create(sampleStoredProcedure)
193
- } catch (e) {
194
- if (e.code === 409) {
195
- console.log('Stored procedure already exists replacing it with new version.')
196
- await container.scripts.storedProcedure(sampleStoredProcedure.id).replace(sampleStoredProcedure)
197
- } else {
198
- throw(e)
199
- }
200
- }
201
- finally{
202
- const { resource: results } = await container.scripts.storedProcedure(sampleStoredProcedure.id).execute();
203
- console.log(results);
204
- }
205
- }
206
- createSP().catch(error => {
207
- console.error("An error occurred: ", error);
208
- });
209
123
210
- - name : Create and test Trigger in Azure Cosmos DB
211
- uses : actions/github-script@v6
212
- with :
213
- script : | # The Cosmos DB Key never should be accesed as plain text. It is only for demo purposes.
214
- async function createTrigger() {
215
- const { CosmosClient } = require("@azure/cosmos");
216
- const endpoint = "${{ steps.arm_deployment.outputs.cosmosDBendpoint }}";
217
- const key = "${{ env.cosmoskey }}";
218
- const client = new CosmosClient({ endpoint, key });
219
- const { database } = await client.databases.createIfNotExists({ id: 'SampleDatabase' });
220
- const { container } = await database.containers.createIfNotExists({ id: 'WebAppContext' });
221
- const { sampleTrigger } = require('./Triggers/SampleTrigger.js')
222
- try {
223
- await container.scripts.triggers.create(sampleTrigger)
224
- } catch (e) {
225
- if (e.code === 409) {
226
- console.log('Trigger already exists replacing it with new version.')
227
- await container.scripts.trigger(sampleTrigger.id).replace(sampleTrigger)
228
- } else {
229
- throw(e)
230
- }
231
- }
232
- finally {
233
- const newItem = {
234
- id: Math.floor(Math.random() * 10000).toString(),
235
- name: 'Sample Item'
236
- };
237
- const options = { preTriggerInclude: ['SampleTrigger'] };
238
- const { resource: trigger_result } = await container.items.create(newItem, options)
239
- console.log(trigger_result)
240
- }
241
- }
242
- createTrigger().catch(error => {
243
- console.error("An error occurred: ", error);
244
- });
245
-
124
+ - name : Create and test Stored Procedure with Azure Cosmos DB Emulator
125
+ run : node Scripts/createSP.js ${{ steps.arm_deploy.outputs.cosmosDBendpoint }} ${{ env.cosmosDBKey }} SampleDatabase WebAppContext StoredProcedures/SampleStoredProcedure.js 1
126
+
127
+ - name : Create and test Trigger with Azure Cosmos DB Emulator
128
+ run : node Scripts/createTrigger.js ${{ steps.arm_deploy.outputs.cosmosDBendpoint }} ${{ env.cosmosDBKey }} SampleDatabase WebAppContext Triggers/SampleTrigger.js 1
129
+
246
130
- name : Download web app artifact
247
131
uses : actions/download-artifact@v3
248
132
with :
@@ -252,7 +136,7 @@ jobs:
252
136
- name : Deploy web app to Azure Web App
253
137
uses : azure/webapps-deploy@v2
254
138
with :
255
- app-name : ${{ steps.arm_deployment .outputs.webappname }}
139
+ app-name : ${{ steps.arm_deploy .outputs.webAppName }}
256
140
package : SampleApp
257
141
258
142
Production :
@@ -273,78 +157,40 @@ jobs:
273
157
az group create --name ${{ vars.RESOURCEGROUP }} --location eastus
274
158
275
159
- name : Provisioning Azure Cosmos DB resource with ARM
276
- id : arm_deployment
160
+ id : arm_deploy
277
161
uses : azure/arm-deploy@v1
278
162
with :
279
163
resourceGroupName : ${{ vars.RESOURCEGROUP }}
280
164
template : IaC/cosmosdb.json
281
165
parameters : IaC/cosmosdb.Prod-parameters.json
282
166
deploymentMode : ' Incremental'
283
- env :
284
- cosmoskey : ::add-mask::${{ steps.arm_deployment.outputs.cosmosDBkey }}
285
167
286
168
- name : Setup Node.js
287
169
uses : actions/setup-node@v3
288
170
with :
289
171
node-version : latest
290
-
291
- - name : Install NPM Azure Cosmos and Azure Identity dependencies
292
- run : npm install @azure/cosmos
172
+
173
+ - name : Get CosmosDB Key
174
+ id : get_cosmos_key
175
+ run : | # Mask the key in the logs
176
+ primary_key=$(az cosmosdb keys list --name ${{ steps.arm_deploy.outputs.cosmosDBName }} --resource-group ${{ vars.RESOURCEGROUP }} --query primaryMasterKey --output tsv)
177
+ echo "::add-mask::$primary_key"
178
+ echo "cosmosDBKey=$primary_key" >> $GITHUB_ENV
293
179
294
- - name : Create and test Stored Procedure in Azure Cosmos DB
295
- uses : actions/github-script@v6
180
+ - name : Setup Node.js
181
+ uses : actions/setup-node@v3
296
182
with :
297
- script : | # The Cosmos DB Key never should be accesed as plain text. It is only for demo purposes.
298
- async function createSP() {
299
- const { CosmosClient } = require("@azure/cosmos");
300
- const endpoint = "${{ steps.arm_deployment.outputs.cosmosDBendpoint }}";
301
- const key = "${{ env.cosmoskey }}";
302
- const client = new CosmosClient({ endpoint, key });
303
- const { database } = await client.databases.createIfNotExists({ id: 'SampleDatabase' });
304
- const { container } = await database.containers.createIfNotExists({ id: 'WebAppContext' });
305
- const { sampleStoredProcedure } = require('./StoredProcedures/SampleStoredProcedure.js');
306
- try {
307
- await container.scripts.storedProcedures.create(sampleStoredProcedure)
308
- } catch (e) {
309
- if (e.code === 409) {
310
- console.log('Stored procedure already exists replacing it with new version.')
311
- await container.scripts.storedProcedure(sampleStoredProcedure.id).replace(sampleStoredProcedure)
312
- } else {
313
- throw(e)
314
- }
315
- }
316
- }
317
- createSP().catch(error => {
318
- console.error("An error occurred: ", error);
319
- });
183
+ node-version : latest
184
+
185
+ - name : Install Azure Cosmos dependency
186
+ run : npm install @azure/cosmos
320
187
321
- - name : Create and test Trigger in Azure Cosmos DB
322
- uses : actions/github-script@v6
323
- with :
324
- script : | # The Cosmos DB Key never should be accesed as plain text. It is only for demo purposes.
325
- async function createTrigger() {
326
- const { CosmosClient } = require("@azure/cosmos");
327
- const endpoint = "${{ steps.arm_deployment.outputs.cosmosDBendpoint }}";
328
- const key = "${{ env.cosmoskey }}";
329
- const client = new CosmosClient({ endpoint, key });
330
- const { database } = await client.databases.createIfNotExists({ id: 'SampleDatabase' });
331
- const { container } = await database.containers.createIfNotExists({ id: 'WebAppContext' });
332
- const { sampleTrigger } = require('./Triggers/SampleTrigger.js')
333
- try {
334
- await container.scripts.triggers.create(sampleTrigger)
335
- } catch (e) {
336
- if (e.code === 409) {
337
- console.log('Trigger already exists replacing it with new version.')
338
- await container.scripts.trigger(sampleTrigger.id).replace(sampleTrigger)
339
- } else {
340
- throw(e)
341
- }
342
- }
343
- }
344
- createTrigger().catch(error => {
345
- console.error("An error occurred: ", error);
346
- });
347
-
188
+ - name : Create and test Stored Procedure with Azure Cosmos DB Emulator
189
+ run : node Scripts/createSP.js ${{ steps.arm_deploy.outputs.cosmosDBendpoint }} ${{ env.cosmosDBKey }} SampleDatabase WebAppContext StoredProcedures/SampleStoredProcedure.js 0
190
+
191
+ - name : Create and test Trigger with Azure Cosmos DB Emulator
192
+ run : node Scripts/createTrigger.js ${{ steps.arm_deploy.outputs.cosmosDBendpoint }} ${{ env.cosmosDBKey }} SampleDatabase WebAppContext Triggers/SampleTrigger.js 0
193
+
348
194
- name : Download web app artifact
349
195
uses : actions/download-artifact@v3
350
196
with :
@@ -354,5 +200,5 @@ jobs:
354
200
- name : Deploy web app to Azure Web App
355
201
uses : azure/webapps-deploy@v2
356
202
with :
357
- app-name : ${{ steps.arm_deployment .outputs.webappname }}
203
+ app-name : ${{ steps.arm_deploy .outputs.WebAppName }}
358
204
package : SampleApp
0 commit comments