Skip to content

Commit d655f13

Browse files
committed
merged with v5.0
2 parents 0bae40b + 525d11f commit d655f13

29 files changed

+444
-37
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
name: Azure Static Web Apps CI/CD
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
types: [opened, synchronize, reopened, closed]
9+
branches:
10+
- main
11+
12+
jobs:
13+
build_and_deploy_job:
14+
if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.action != 'closed')
15+
runs-on: ubuntu-latest
16+
name: Build and Deploy Job
17+
steps:
18+
- uses: actions/checkout@v2
19+
with:
20+
submodules: true
21+
- name: Deploy Database
22+
uses: azure/sql-action@v1.3
23+
with:
24+
connection-string: ${{ secrets.AZURE_SQL_CONNECTION_STRING }}
25+
project-file: './database/declarative-deploy/todo_v5/todo_v5.sqlproj'
26+
build-arguments: '-c Release'
27+
- name: Build And Deploy
28+
id: builddeploy
29+
uses: Azure/static-web-apps-deploy@v1
30+
with:
31+
azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN }}
32+
repo_token: ${{ secrets.GITHUB_TOKEN }} # Used for Github integrations (i.e. PR comments)
33+
action: "upload"
34+
###### Repository/Build Configurations - These values can be configured to match your app requirements. ######
35+
# For more information regarding Static Web App workflow configurations, please visit: https://aka.ms/swaworkflowconfig
36+
app_location: "./client" # App source code path
37+
api_location: "./api" # Api source code path - optional
38+
output_location: "" # Built app content directory - optional
39+
###### End of Repository/Build Configurations ######
40+
41+
close_pull_request_job:
42+
if: github.event_name == 'pull_request' && github.event.action == 'closed'
43+
runs-on: ubuntu-latest
44+
name: Close Pull Request Job
45+
steps:
46+
- name: Close Pull Request
47+
id: closepullrequest
48+
uses: Azure/static-web-apps-deploy@v1
49+
with:
50+
azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN }}
51+
action: "close"

.github/workflows/azure-static-web-apps.yml.sample renamed to .github/workflows/azure-static-web-apps-imperative-db-deploy.yml.sample

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jobs:
2323
with:
2424
dotnet-version: '6.0.x'
2525
- name: Deploy Database
26-
working-directory: ./database/deploy
26+
working-directory: ./database/imperative-deploy/dbup
2727
env:
2828
ConnectionString: ${{ secrets.AZURE_SQL_CONNECTION_STRING }}
2929
run: dotnet build && dotnet run

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,4 +272,5 @@ __blobstorage__/
272272
.env.v*
273273
global.json
274274
log.txt
275-
client/dist/
275+
client/dist/
276+
client/node_modules/

.vscode/settings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@
33
"azureFunctions.projectLanguage": "C#",
44
"azureFunctions.projectRuntime": "~4",
55
"debug.internalConsoleOptions": "neverOpen",
6-
"azureFunctions.preDeployTask": "publish (functions)"
6+
"azureFunctions.preDeployTask": "publish (functions)"
77
}

README.md

Lines changed: 119 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ Learn how to implement a fully working, end-to-end, full-stack solution using Az
3939
This demo has been used in the Azure Serverless Conference 2021. Make sure to check out the recording and get the slides here:
4040

4141
- Slides: https://www.slideshare.net/davidemauri/azure-serverless-fullstack-kickstart
42-
- Recording: https://www.youtube.com/watch?v=TIh52zbi8Dk
42+
- Recording: https://www.youtube.com/watch?v=TIh52zbi8Dk
4343

4444
![Recording Screenshot](./docs/screenshot.jpg)
4545

@@ -49,12 +49,17 @@ To run this sample in your subscription, make sure to fork the repository into y
4949

5050
## Repo branches
5151

52-
This repo has different branches that shows the development at different stages. This is the branch 4.0.
52+
This repo has different branches that shows the development at different stages. This is the branch 5.0.
5353

5454
- 1.0: First version, no database support
5555
- 2.0: Database support added
56-
- 3.0: Authentication and Authorization
57-
- 4.0: [This Branch] Resilient connections using Polly
56+
- 3.0: Authentication and Authorization
57+
- 4.0: Resilient connections using Polly
58+
- 5.0: [This Branch] Database imperative or declarative CI/CD
59+
60+
### V5.0 Notes
61+
62+
Continuing from V4.0, this branch focuses on including the database in the deployment pipeline and gives you the option to choose between an imperative or a declarative database deployment style.
5863

5964
### V4.0 Notes
6065

@@ -66,7 +71,7 @@ In this branch the backend REST API service and the database are modified so tha
6671

6772
### V2.0 Notes
6873

69-
In this branch the backend REST API service is modified so that the to-do list can be saved an manged using an Azure SQL database. Communication with the database is done using JSON too, as Azure SQL support [JSON natively](https://docs.microsoft.com/sql/relational-databases/json/json-data-sql-server?view=sql-server-ver15).
74+
In this branch the backend REST API service is modified so that the to-do list can be saved an manged using an Azure SQL database. Communication with the database is done using JSON too, as Azure SQL support [JSON natively](https://docs.microsoft.com/sql/relational-databases/json/json-data-sql-server).
7075

7176
### V1.0 Notes
7277

@@ -76,7 +81,7 @@ In this branch the solution will have a full working front-end, sending REST req
7681

7782
- `/api`: the NodeJs Azure Function code used to provide the backend API, called by the Vue.Js client.
7883
- `/client`: the Vue.Js client. Original source code has been taken from official Vue.js sample and adapted to call a REST client instead of using local storage to save and retrieve todos
79-
- `/database`: the database scripts and the database deployment tool
84+
- `/database`: the database scripts and the database deployment tools
8085

8186
## Install the dependencies
8287

@@ -98,38 +103,45 @@ npm i -g @azure/static-web-apps-cli
98103

99104
If you don't have a Azure SQL server already, you can create one (no additional costs for a server) running the following [AZ CLI](https://docs.microsoft.com/cli/azure/) command (via [WSL](https://docs.microsoft.com/windows/wsl/), or Linux or [Azure Cloud Shell](https://azure.microsoft.com/features/cloud-shell/)):
100105

101-
102106
```sh
103107
az sql server create -n <server-name> -l <location> --admin-user <admin-user> --admin-password <admin-password> -g <resource-group>
104108
```
105109

106110
Create a new Azure SQL database:
107111

108112
```sh
109-
az sql db create -g <resource-group> -s <server-name> -n todo_v4 --service-objective GP_Gen5_2
113+
az sql db create -g <resource-group> -s <server-name> -n todo_v5 --service-objective GP_Gen5_2
110114
```
111115

112-
Another option is to run the `azure-create-sql-db.sh` script in the `./databases` folder. The script uses the ARM template available in the same folder to create a server and a `todo_v4` database.
116+
Another option is to run the `azure-create-sql-db.sh` script in the `./databases` folder. The script uses the ARM template available in the same folder to create a server and a `todo_v5` database.
113117

114118
Make sure you have the firewall configured to allow your machine to access Azure SQL:
115119

116-
```
120+
```sh
117121
az sql server firewall-rule create --resource-group <resource-group> --server <server-name> --name AllowMyClientIP_1 --start-ip-address <your_public_ip> --end-ip-address <your_public_ip>
118122
```
119123

120124
you can get your public IP from here, for example: https://ifconfig.me/
121125

122126
## Deploy the database
123127

124-
Database is deployed using [DbUp](http://dbup.github.io/). Switch to the `./database/deploy` folder and create new `.env` file containing the connection string to the created Azure SQL database. You can use the provide `.env.template` as a guide. The connection string look like:
128+
There are two may strategies that can be used: imperative and declarative. The imperative approach is the one that has been used until now, where the script to create the database objects are applied in the defined order. The declarative approach is instead where you have the database state (a snapshot of the schema) you want to have and a tool will take care of making all the correct changes to bring the target database to that state.
129+
130+
In both cases the first step is to have at hand the connection string needed to connect to create Azure SQL database. Switch to the `./database/` folder:
131+
132+
```sh
133+
cd ./database
134+
```
135+
136+
and create new `.env` file, that will contain the aforementioned connection string. Use the provided `.env.template` as a guide. The connection string look like:
125137

126138
```text
127-
SERVER=<my-server>.database.windows.net;DATABASE=todo_v4;UID=<my_user_id>;PWD=<my_user_password>;
139+
Server=<my-server>.database.windows.net;Initial Catalog=todo_v5;User Id=<my_user_id>;Password=<my_user_password>;
128140
```
129141

130-
replace the placeholder with the correct value for your database, username and password and you're good to go. Make sure the database user specified in the connection string has enough permission to create objects (for example, make sure is a server administrator or in the db_owner database role).
142+
replace the placeholders with the correct value for your database, username and password and you're good to go. Make sure the database user specified in the connection string has enough permission to create objects (for example, make sure is a server administrator or in the db_owner database role).
131143

132-
Please note that using the server administrator login is not recommended as is way to powerful. If you are testing this on a sample server that you'll not use for production purposes, that shouldn't be an issue. But if want to be on the safe side and implement a correct security process you can create a user that will be used only for running the deployment script:
144+
Please note that using the server administrator login is not recommended as is way too powerful. If you are testing this on a sample server that you'll not use for production purposes, that shouldn't be an issue. But if want to be on the safe side and implement a correct security process you can create a user that will be used only for running the deployment script:
133145

134146
```sql
135147
create user [deployment_user] with password = '<a_strong_password>';
@@ -139,17 +151,19 @@ alter role [db_owner] add member [deployment_user]
139151
go
140152
```
141153

142-
Once you have configured the connection string, you can deploy the database objects:
154+
### Imperative Deployment
155+
156+
Database is deployed using [DbUp](http://dbup.github.io/). The scripts that will be deployed are in the `./imperative-deploy/sql` folder. Once you have configured the connection string as explained before, you can deploy the database objects:
143157

144158
```sh
145-
cd ./database/deploy
159+
cd ./imperative-deploy/dbup
146160
dotnet run
147161
```
148162

149-
you will see something like:
163+
you will see something like:
150164

151165
```sh
152-
Deploying database: todo_v4
166+
Deploying database: todo_v5
153167
Testing connection...
154168
Starting deployment...
155169
Beginning database upgrade
@@ -169,9 +183,72 @@ Success!
169183

170184
Database has been deployed successfully!
171185

186+
### Declarative Deployment
187+
188+
Database scripts are stored in the `./database/declarative-deploy/todo_v5` folder, which contains also the related [MSBuild SQL Project](https://techcommunity.microsoft.com/t5/azure-sql-blog/microsoft-build-sql-the-next-frontier-of-sql-projects/ba-p/3290628).
189+
190+
A SQL Project can be build using the standard `dotnet build` action and it will generate a `.dacpac` file that contains the description of all the database objects that are needed to make your solution work: the database state you need to have deployed. If you want to work on the database project is recommended that you use Visual Studio Code or Azure Data Studio with the "SQL Database Projects" extension.
191+
192+
Deployment will be done via the `sqlpackage` tool. Make sure it is installed and added to your PATH as per the instructions here: [Download and install SqlPackage](https://docs.microsoft.com/en-us/sql/tools/sqlpackage/sqlpackage-download).
193+
194+
Once `sqlpackage` is installed you can deploy the database using the `./database/declarative-deployment/azure-deploy-sql-db.sh` script to automate the whole (build + deploy) process:
195+
196+
```sh
197+
cd ./declarative-deployment
198+
./azure-deploy-sql-db.sh
199+
```
200+
201+
you'll see something like:
202+
203+
```sh
204+
Loading from ../.env
205+
Building .dacpac...
206+
MSBuild version 17.3.0+92e077650 for .NET
207+
Determining projects to restore...
208+
All projects are up-to-date for restore.
209+
Creating a model to represent the project...
210+
Loading project references...
211+
Loading project files...
212+
Building the project model and resolving object interdependencies...
213+
Validating the project model...
214+
Writing model to /mnt/w/_git/_owned/azure-sql-db-fullstack-serverless-kickstart/database/declarative-deploy/todo_v5/obj/Debug/Model.xml...
215+
todo_v5 -> /mnt/w/_git/_owned/azure-sql-db-fullstack-serverless-kickstart/database/declarative-deploy/todo_v5/bin/Debug/todo_v5.dll
216+
todo_v5 -> /mnt/w/_git/_owned/azure-sql-db-fullstack-serverless-kickstart/database/declarative-deploy/todo_v5/bin/Debug/todo_v5.dacpac
217+
218+
Build succeeded.
219+
0 Warning(s)
220+
0 Error(s)
221+
222+
Time Elapsed 00:00:03.17
223+
Publishing .dacpac...
224+
Server=zv6qimpc6cbrg.database.windows.net;Initial Catalog=todo_v5;User Id=db_admin;Password=EcivWb_xkzxiQ;
225+
Publishing to database 'todo_v5' on server 'zv6qimpc6cbrg.database.windows.net'.
226+
Initializing deployment (Start)
227+
Initializing deployment (Complete)
228+
Analyzing deployment plan (Start)
229+
Analyzing deployment plan (Complete)
230+
Updating database (Start)
231+
Creating SqlSchema [web]...
232+
Creating SqlTable [dbo].[todos]...
233+
Creating SqlDefaultConstraint unnamed constraint on [dbo].[todos]...
234+
Creating SqlSequence [dbo].[global_sequence]...
235+
Creating SqlDefaultConstraint unnamed constraint on [dbo].[todos]...
236+
Creating SqlProcedure [web].[delete_todo]...
237+
Creating SqlProcedure [web].[get_todo]...
238+
Creating SqlProcedure [web].[patch_todo]...
239+
Creating SqlProcedure [web].[post_todo]...
240+
Update complete.
241+
Updating database (Complete)
242+
Successfully published database.
243+
Time elapsed 0:00:44.97
244+
Done.
245+
```
246+
247+
Database has been deployed successfully!
248+
172249
## Test solution locally
173250

174-
Before starting the solution locally, you have to configure the Azure Function that is used to provide the backed API. In the `./api` folder create a `local.settings.json` file starting from the provided template. All you have to do is update the connection string with the value correct for you solution. If have created the Azure SQL database as described above you'll have a database named `todo_v4`. Just make sure you add the correct server name in the `local.settings.json`. The database name, user login and password are already set in the template file to match those used in this repository and in the `./database/sql/01-create-objects.sql` file.
251+
Before starting the solution locally, you have to configure the Azure Function that is used to provide the backed API. In the `./api` folder create a `local.settings.json` file starting from the provided template. All you have to do is update the connection string with the value correct for you solution. If have created the Azure SQL database as described above you'll have a database named `todo_v5`. Just make sure you add the correct server name in the `local.settings.json`. The database name, user login and password are already set in the template file to match those used in this repository and in the `./database/sql/01-create-objects.sql` file.
175252

176253
To run Azure Functions locally, for example to debug them, you also need a local Azure Storage emulator. You can use [Azurite](https://docs.microsoft.com/azure/storage/common/storage-use-azurite?tabs=visual-studio) that also has a VS Code extension.
177254

@@ -215,7 +292,9 @@ The generated GitHub Action doesn't know that we are using a database to store t
215292

216293
- AZURE_SQL_CONNECTION_STRING
217294

218-
The `AZURE_SQL_CONNECTION_STRING` is the connection string that can be used to deploy the database. You can use the same connection string used for deploying the database objects. You can find it in the `./database/deploy/.env` file.
295+
The `AZURE_SQL_CONNECTION_STRING` is the connection string that can be used to deploy the database. You can use the same connection string used for deploying the database objects. You can find it in the `./database/.env` file.
296+
297+
### Imperative Deployment on Azure
219298

220299
Then you have to add the following code, just before the `Build And Deploy` step, to the file you'll find in `./.github/workflow`:
221300

@@ -225,13 +304,31 @@ Then you have to add the following code, just before the `Build And Deploy` step
225304
with:
226305
dotnet-version: '6.0.x'
227306
- name: Deploy Database
228-
working-directory: ./database/deploy
307+
working-directory: ./database/imperative-deploy
229308
env:
230309
ConnectionString: ${{ secrets.AZURE_SQL_CONNECTION_STRING }}
231310
run: dotnet build && dotnet run
232311
```
233312
234-
The file `./.github/workflow/azure-static-web-apps.yml.sample` shows an example of how the yaml should look like. Commit and push the changes and the deployment will start again, this time deploying also the database objects.
313+
The file `./.github/workflow/azure-static-web-apps-imperative-db-deploy.yml.sample` shows an example of how the yaml should look like. Commit and push the changes and the deployment will start again, this time deploying also the database objects.
314+
315+
If you also want to deploy the Azure SQL server and database within the same pipeline, you can do so by using the provided ARM template `./database/azure-sql-db.arm.json` and the [Deploy ARM GitHub Action](https://github.com/Azure/arm-deploy).
316+
317+
318+
### Declarative Deployment on Azure
319+
320+
Then you have to add the following code, just before the `Build And Deploy` step, to the file you'll find in `./.github/workflow`:
321+
322+
```yml
323+
- name: Deploy Database
324+
uses: azure/sql-action@v1.3
325+
with:
326+
connection-string: ${{ secrets.AZURE_SQL_CONNECTION_STRING }}
327+
project-file: './database/declarative-deploy/todo_v5/todo_v5.sqlproj'
328+
build-arguments: '-c Release'
329+
```
330+
331+
The file `./.github/workflow/azure-static-web-apps-declarative-db-deploy.yml.sample` shows an example of how the yaml should look like. Commit and push the changes and the deployment will start again, this time deploying also the database objects.
235332

236333
If you also want to deploy the Azure SQL server and database within the same pipeline, you can do so by using the provided ARM template `./database/azure-sql-db.arm.json` and the [Deploy ARM GitHub Action](https://github.com/Azure/arm-deploy).
237334

api/local.settings.json.template

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
"Values": {
44
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
55
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
6-
"AzureSQL": "Server=tcp:.database.windows.net,1433;Initial Catalog=todo_v4;Persist Security Info=False;User ID=webapp;Password=Super_Str0ng*P4ZZword!;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;"
6+
"AzureSQL": "Server=tcp:.database.windows.net,1433;Initial Catalog=todo_v5;Persist Security Info=False;User ID=webapp;Password=Super_Str0ng*P4ZZword!;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;"
77
}
88
}

azure-deploy.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@ set -euo pipefail
55
FILE=".env"
66
if [[ -f $FILE ]]; then
77
echo "Loading from $FILE"
8-
eval $(egrep "^[^#;]" .env | xargs -d'\n' -n1 | sed 's/^/export /')
8+
eval $(egrep "^[^#;]" $FILE | xargs -0 -n1 | sed 's/^/export /')
99
else
1010
cat << EOF > .env
1111
resourceGroup=""
1212
appName=""
1313
location=""
1414
1515
# Connection string
16-
azureSQL='Server=tcp:.database.windows.net,1433;Initial Catalog=todo_v4;Persist Security Info=False;User ID=webapp;Password=Super_Str0ng*P4ZZword!;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;'
16+
azureSQL='Server=tcp:.database.windows.net,1433;Initial Catalog=todo_v5;Persist Security Info=False;User ID=webapp;Password=Super_Str0ng*P4ZZword!;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;'
1717
1818
gitSource="https://github.com/Azure-Samples/azure-sql-db-fullstack-serverless-kickstart"
1919
gitToken=""
@@ -39,7 +39,7 @@ az deployment group create \
3939
location=$location \
4040
repositoryToken=$gitToken \
4141
repositoryUrl=$gitSource \
42-
branch="v4.0" \
42+
branch="v5.0" \
4343
appLocation="./client" \
4444
apiLocation="./api" \
4545
azureSQL="$azureSQL"

database/.env.template

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ConnectionString="Server=.database.windows.net;Initial Catalog=;User Id=;Password=;"

0 commit comments

Comments
 (0)