---
# System prepended metadata

title: 'Hands-on: Logic App CI/CD with Azure DevOps'
tags: [Azure DevOps, '2022', Workshop, Logic App]

---

# Hands-on: Logic App CI/CD with Azure DevOps
###### tags: `Workshop` `Logic App` `Azure DevOps` `2022`
## Logic App Resouece Structure
- 目前 Logic App 支援兩種 Tier，分別為 Standard (Single-tenant) 及 Consumption (Multi-tenant) 
- 在 multi-tenant 模型中，Logic App 資源結構只能包含一個工作流。由於這種一對一的關係，Logic App 和 Workflow 通常被視為同義詞並引用。
- 而在 single-tenant 模型中，Logic App 資源結構可包含多個工作流。這種一對多的關係意味著在同一個 Logic App 中，工作流可以共享和重用其他資源。在 single-tenant 的模式下，也可使用到更多的功能，如獨立的 compute resource 及網路環境等

<!-- ### Single-tenant versus multi-tenant
In the multi-tenant Azure Logic Apps, resource deployment is based on Azure Resource Manager templates (ARM templates), which combine and handle resource provisioning for both logic apps and infrastructure. In single-tenant Azure Logic Apps, deployment becomes easier because you can separate resource provisioning between apps and infrastructure. -->

## 課程實作大綱
[TOC]
## 0) 建置 Azure DevOps Organization
### 建立新組織
- 到 [Azure DevOps](https://dev.azure.com/) 頁面，選擇 開始免費使用
    ![](https://i.imgur.com/6Dc0BRJ.png)
- 選擇 Taiwan
    ![](https://i.imgur.com/uyRKTJf.png)
- 填寫你的組織名稱、地區(建議可以選擇 Central US)
    ![](https://i.imgur.com/CddAOwm.png)
- 點選 Continuous，開始進行服務的建立
    ![](https://i.imgur.com/48vvVPv.png)
- 完成後，會跳轉至以下畫面，建立第一個專案，選擇 Private
    ![](https://i.imgur.com/S5WUy2n.png)

### 第一個專案
- 建立完成後會看到一個開好的專案
    ![](https://i.imgur.com/NetSWhH.png)
- 點選左上角的 ![](https://i.imgur.com/doL8aJn.png =200x) 回到組織首頁
    
### Billing 設定 
:::info
:bulb: 因目前免費的一條 pipeline 須提前申請，因此需綁定 billing 才可使用 pipeline，免費 pipeline 申請方式請參考 [Reference](https://hackmd.io/@msazuredev/HkaaHy2AO)
:::
- 在首頁中，點選左下方的 Organization Setting
    ![](https://i.imgur.com/3rSjVaL.png)
- 點選 Billing，選擇 Set up billing，選擇你可使用的訂閱 (免費試用/MSDN 訂閱不可使用)
    ![](htt**ps://i.imgur.com/IDrt2BG.png)
- 將 MS Hosted CI/CD 數量調整為 1
    ![](https://i.imgur.com/QlTrovc.png)

### 建置今日 Project 所使用之專案
- 回到首頁，點選右上角 ![](https://i.imgur.com/1sXFXRL.png =100x)
    ![](https://i.imgur.com/pfaYvzf.png)
- 填寫 Project name `logic-app-workshop`，Visibility 選擇 Private，完成後 Create
    ![](https://i.imgur.com/FDPE7gs.png)

## 1) Initial Logic App Enviornment 
Region 可設定於 Japan East / East Asia，此章節會建立 2* Consumption Logic App 及 2* Standard Logic App，分別為 dev 及 prod 環境所使用


- 到 [Azure Portal](https://portal.azure.com/) 上，建立 Logic App 的資源
    ![](https://i.imgur.com/L85gduL.png)
- 設定 Logic App 參數，建立一個全新的 resource group 為今日 lab 所使用，並選擇 **Consumption** 的 plan type，設定完成後點選 Review + Create
    ![](https://i.imgur.com/rOmDYs9.png)
- 確認資料正確後點選 Create
![](https://i.imgur.com/S6pUazt.png =500x)
- 部屬完成後點選 Go to resource
    ![](https://i.imgur.com/dN13T5O.png)
- 點選後會直接跳轉至 Logic App Designer，選擇 When a HTTP request is received
    ![](https://i.imgur.com/EGB28Wq.png)
- trigger 建立完成後，點選 Save，後續會透過程式碼式的方式添加 Action
    ![](https://i.imgur.com/JcjbMbk.png)
- 再新增一個 **Consumption** plan type 的 production Logic App
    ![](https://i.imgur.com/TELGoz9.png)
- 新增一個 plan type 為 **Standard** 的 Dev Logic App
    - 選擇 Standard
    ![](https://i.imgur.com/F3PwC7s.png)
    - Windows Plan 選擇 Create New
    ![](https://i.imgur.com/osnIHL3.png)
    - Sku and size 選擇 WS1
    ![](https://i.imgur.com/P1oeGLR.png)
    - Stroage 選擇 Create New (storage命名僅可字母+數字)
    ![](https://i.imgur.com/OEiIFgW.png)
    - Application Insight 選擇 Create New
    ![](https://i.imgur.com/UOPNDSz.png)
    - Review 確認沒問題後點選 Create
    ![](https://i.imgur.com/iS4wphM.png =500x)
- 再新增一個 Prod 的 Standard Logic App (步驟同 Dev)
    ![](https://i.imgur.com/prG7dpH.png =500x)
<!--     - 選擇 Standard
    ![](https://i.imgur.com/6PLtrfQ.png)
    - Windows Plan 選擇 Create New
    ![](https://i.imgur.com/TOPwt60.png)
    - Sku and size 選擇 WS1
    ![](https://i.imgur.com/rtRkK8c.png)
    - Stroage 選擇 Create New (storage命名僅可字母+數字)
    ![](https://i.imgur.com/9cn5VuH.png)
    - Application Insight 選擇 Create New
    ![](https://i.imgur.com/gGgVpD7.png)
    - Review 確認沒問題後點選 Create
    ![](https://i.imgur.com/prG7dpH.png =500x) -->



## 2) Consumption Tier Logic App (Multi-tenant) 的開發
### 使用 Visual Studio Code
- 安裝 **[Azure Logic App (Consumption)](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-logicapps)** Extension
    ![](https://i.imgur.com/UtRU9EH.png)
- 到桌面，建立新的資料夾，命名為`consumption` (或任意命名)
- 開啟 Visual Studio Code，選擇 Open Folder，選到剛剛建立的新資料夾
    ![](https://i.imgur.com/9dybb15.png)
- 選擇左邊菜單，點選 ![](https://i.imgur.com/S9eImdE.png =30x)，找到 Azure Logic App (CONSUMPTION) 的 Extension，點選 Sign in to Azure
    ![](https://i.imgur.com/8XQgwHp.png)
- 輸入帳號
    ![](https://i.imgur.com/b0qzdS8.png)
- 登入完成後，顯示以下畫面
    ![](https://i.imgur.com/eXc8cLZ.png)
- 回到 Visual Studio Code，會出現此帳號可用之訂閱，如果訂閱太多，可以用 filter
    ![](https://i.imgur.com/Z50XHp5.png)
- 在先前建立 Logic App 的訂閱下找到 Dev Logic App 資源，選擇 Dev Logic App > 右鍵 > Open in Designer，可查看目前 Azure 上 Logic App 設定的流程
    ![](https://i.imgur.com/Cx3qAKI.png)
- Logic App > 右鍵 > Open in Editor，可透過編輯 json 修改流程
    ![](https://i.imgur.com/3lg4DdV.png)
- 添加 `HTTP` 及 `Response` 兩個 action，在 `"actions": {}` 區塊內將以下程式碼加入
    ```json=15
    "HTTP": {
        "runAfter": {},
        "type": "Http",
        "inputs": {
            "method": "GET",
            "uri": "https://cat-fact.herokuapp.com/facts/"
        }
    },
    "Response": {
        "runAfter": {
            "HTTP": [
                "Succeeded"
            ]
        },
        "type": "Response",
        "kind": "Http",
        "inputs": {
            "statusCode": "@outputs('HTTP')['statusCode']",
            "headers": {
                "devops_test": "0602"
            },
            "body": "@body('HTTP')"
        }
    }
    ```
    ![](https://i.imgur.com/7NMfm7P.png)

- 儲存後會直接 update Logic App
    ![](https://i.imgur.com/UcTz1uU.png =500x)
- Output 顯示 Updated 後，點選 Dev Logic App 的 ![](https://i.imgur.com/crmBuf0.png =25x) 圖示可直接開啟 Designer，確認 actions 經更新
    ![](https://i.imgur.com/ZXwds6O.png)
- 透過 Dev Logic App > Versions 可查看過去編輯版本
    ![](https://i.imgur.com/UyTnotb.png)
- 測試 API
    - 回到 [Azure Portal](https://portal.azure.com) ，找到測試用的 Dev Logic App 環境，點選 Logic app desgigner > When a HTTP request is received，取得 HTTP POST URL
    ![](https://i.imgur.com/TRxX1jD.png)
    - 使用 POSTMAN，選擇 POST，並將 HTTP POST URL 填入
        ![](https://i.imgur.com/hFs0QsX.png)

    - 使用 curl
        ```
        curl -d "Content-Length:0" -X POST "<Logic_App_HTTP_POST URL>"
        ```
        ![](https://i.imgur.com/GeF6cxE.jpg)

### 調整 ARM template 參數
- 如果怕改錯，可直接使用 sample code for logic app [huier23/logic-app-consumption](https://github.com/huier23/logic-app-consumption)，
- 將 logic app 部屬檔添加至 project 中，點選左邊菜單的 ![](https://i.imgur.com/tvTthjC.png =35x)，選擇 Dev Logic App > Add to Project
    ![](https://i.imgur.com/QWk1WGa.png =550x)
- 點選左邊菜單的 ![](https://i.imgur.com/H8L29px.png =35x) ，會出現兩個檔案，分別為 xxxxx.definition.json 和 xxxxx.parameters.json
![](https://i.imgur.com/br1VbOg.png =500x)
- 將 `xxxxxxx.definition.json` 修改檔名為 `logicapp.definition.json`
    - `parameters` 區域之內容取代為以下
    ```json=5
    "workflows_logicapp_name": {
        "defaultValue": "<dev-logic-app-name>",
        "type": "string"
    },
    "workflows_logicapp_location": {
        "defaultValue": "<logic-app-location>",
        "type": "string"
    },
    "workflows_http_URL": {
        "defaultValue": "",
        "type": "string"
    }
    ```
    - resources 內的 `location` 及 `name` 修改引用參數之名稱
    ```json=22
    "location": "[parameters('workflows_logicapp_location')]",
    "name": "[parameters('workflows_logicapp_name')]",
    ```
    - resources 內的 actions > HTTP 區域取代為
    ```json=39
    "HTTP": {
        "runAfter": {},
        "type": "Http",
        "inputs": {
            "method": "GET",
            "uri": "[parameters('workflows_http_URL')]"
        }
    },
    ```
- 將 `xxxxxxx.parameters.json` 修改檔名為 `logicapp.parameters.json`
    - 調整 parameters 區域內的內容取代為以下
    ```json=5
    "workflows_logicapp_name": {
        "value": "<dev-logic-app-name>"
    },
    "workflows_logicapp_location": {
        "value": "<logic-app-location>"
    },
    "workflows_http_URL": {
        "value": "https://cat-fact.herokuapp.com/facts/"
    }
    ```
- 完成後儲存

### 設定 CI/CD on Azure DevOps
<!-- - 新增一個 Project，命名為 `logic-app-lab` -->
- 到 [Azure DevOps](https://dev.azure.com/)，點選 Repos，新增一個 Repo
    ![](https://i.imgur.com/03hCjER.png)
- 設定 Repository Name，完成後點選 Create
    ![](https://i.imgur.com/P7h7WNl.png =400x)
- 複製 URL 網址
    ![](https://i.imgur.com/Ofa5dOK.png)
<!-- - 回到 Visual Studio Code，選擇開發用的 logic app 環境 > 右鍵 > Add to Project
![](https://i.imgur.com/UhmiDZO.png =600x)
- Explorer 中，會出現兩個 json 檔案
![](https://i.imgur.com/3QGNGYa.png) -->
- 回到 Visual Studio Code，開啟 terminal
![](https://i.imgur.com/8qbAPvD.png)
- 如果習慣用 cmd，terminal 右上的 + 可以新增 Command Prompt
![](https://i.imgur.com/RgD9u60.png =500x)
- 將程式碼推送至遠端 repository
    - 使用 git 將程式碼推送至遠端程式庫
        ```.sh
        git init .
        git add .
        git commit -m "first commit"
        git remote add origin <remote-repo-url>
        git push origin master
        ```
    - 登入
    ![](https://i.imgur.com/2LCy0Sw.png =450x)
      
    
    :::info
    :bulb: 如需使用 PAT 做驗證， 為 Azure DevOps 之 PAT token
    
    - 點選 Azure DevOps 畫面右上人頭， … > User Settings
    ![](https://i.imgur.com/gtlSxCK.png =300x)
    - 選擇 Personal Access Token
    ![](https://i.imgur.com/pIT1zZ9.png =300x)
    - New Token，並給予 Code Full access 的權限，完成後將 PAT 記下
    ![](https://i.imgur.com/swBpazq.png)
    - 在 terminal 中填入 PAT
    :::

- 回到 [Azure DevOps](https://dev.azure.com)，確認檔案已上傳
    ![](https://i.imgur.com/NRtiToZ.png)
- 選擇 Pepeline > Release > Create Pipeline
    ![](https://i.imgur.com/Hmx37Xr.png)
- 點選 Empty Job
    ![](https://i.imgur.com/8GO95nJ.png)
- 將 Stage 命名為 `Prod`，完成後點選 X
    ![](https://i.imgur.com/t4J3skF.png)
- 點選 Add an artifact
    ![](https://i.imgur.com/y475QXj.png)
- 設定 Artifacts，完成後點選 Add
    - Source type: Azure Repo
    - project: 目前的 porject
    - Source (repository): 選擇存放 consumption logic app json 檔案的 repository
    - Default branch: master
    ![](https://i.imgur.com/HP28FS5.png)
- 設定 continuous deployment，點選 Artifact 右上方的 ![](https://i.imgur.com/zoBUnNd.png =40x)，並將 Continuous deployment trigger 切換至 Enabled
    ![](https://i.imgur.com/GyDjKat.png)
- 修改 satge 的 job，點選 `Prod` stage 的 1 job, 0 task
    ![](https://i.imgur.com/Fa2nEtH.png =600x)
- 在 Agent job 區塊，點選 +，搜尋 `arm`，將 ARM template deployment 添加至 job 中
    ![](https://i.imgur.com/puGAnjv.png)
- 點選 ARM Template deployment: Resource Group scope 的 task 進行設定
    - **Deployment scope**: Resource Group
    - **Azure Resource Manager connection**: xxx's subscription
    - **Subscription**: xxx's subscription
    - **Action**: Create or update resource group
    - **Resource group**: `$(RESOURCE_GROUP)`
    - **Location**: `$(LOCATION)`
    - **Template location**: Linked artifact
    - **Template**: `$(System.DefaultWorkingDirectory)/**/**.definition.json`
    - **Override template parameters**: `-workflows_logicapp_name "$(LOGIC_APP)" -workflows_http_URL "$(REQUEST_URL)"`
    - **Deployment mode**: Incremental
    - 
    ![](https://i.imgur.com/T5V8c1v.png)
    ![](https://i.imgur.com/x0votD9.png)
- 設定 pipeline variable，Variables > Variable groups > Manage variable groups
    ![](https://i.imgur.com/iJYMG1p.png)
- 點選 ![](https://i.imgur.com/aJcLNEP.png =120x) 新增一組 variable group
    ![](https://i.imgur.com/9cKFxMr.png)
- 修改 Variable group name，並將 `RESOURCE_GROUP` 及 `LOCATION` 添加至 Variables 的 key，並分別填上正確的 value，完成後點選 Save
    ![](https://i.imgur.com/EGAlFZo.png)
- 回到 release pipeline > variables > variable groups > link variable group，點選剛剛建立的 variable group，完成後點選 link
    ![](https://i.imgur.com/76jNvKz.png)
- 回到 Pipeline 設定 pepeline variables，新增兩組 key-value
    - `LOGIC_APP` = Prod Logic App 名稱
    - `REQUEST_URL` = `https://cat-fact.herokuapp.com/facts/`
    ![](https://i.imgur.com/9922rKJ.png)
- 回到 Pipeline 設定 Per-deployment conditions，點選 Prod stage 的![](https://i.imgur.com/GHaiFed.png =40x)，將 Pre-deployment approvals 改為 Enabled
![](https://i.imgur.com/GAHQ2u7.png)
- 修改 release pipeline 的名稱 `Release to Logic App (Consumption)`
![](https://i.imgur.com/watOA4x.png =500x)
- 點選 Save > Create release，此時可以查看 Relese-1 的執行狀況
![](https://i.imgur.com/AZkQmry.png)
- 同意部屬至 Prod Stage
![](https://i.imgur.com/YEJu8BO.png)
- 回到 [Azure Portal](https://portal.azure.com) 上，查看 Prod Logic App，確認已有更新，並透過 postman 確認
![](https://i.imgur.com/WYwON8T.png)

## 3) Standard Tier Logic App (Single-tenant)
### About
![](https://i.imgur.com/OeSslzt.png)
When you create logic apps using the Logic App (Standard) resource type, your workflows are powered by the redesigned single-tenant Azure Logic Apps runtime. This runtime uses the Azure Functions extensibility model extensibility and is hosted as an extension on the Azure Functions runtime. 

By using standard build and deploy options, you can focus on app development separately from infrastructure deployment. 

- You can locally run and test logic app workflows in the Visual Studio Code development environment.
- Your logic app can include multiple stateful and stateless workflows.
- Workflows in the same logic app and tenant run in the same process as the Azure Logic Apps runtime, so they share the same resources and provide better performance.

#### Logic app project structure
![](https://i.imgur.com/Ih6bXKa.png)

### Prerequisites
- **Visual Studio Code**
    - **[Azure Logic App (Standard)](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-azurelogicapps)**
    ![](https://i.imgur.com/VQwkhjs.png)
        :::info
        :bulb: 安裝完成後，點選左邊菜單的 Extensions，找到 Azure Logic Apps (Standard)，點選齒輪，選擇 Extension Settings，在 Azure Logic Apps Standard: Template Version 地方填入 `~3`
        ![](https://i.imgur.com/GwNBpxR.png)
        :::
        
    - **[Azure Function](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-azurefunctions)**
    ![](https://i.imgur.com/825fJIz.png)
    - **[Azure Account extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode.azure-account)**
    ![](https://i.imgur.com/AFD20he.png)
    - **[C# for Visual Studio Code extension](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csharp)**
    ![](https://i.imgur.com/gDsPfmj.png)
- **[Azure Functions Core Tools - 3.x version](https://github.com/Azure/azure-functions-core-tools/releases/tag/3.0.3904)** by using the Microsoft Installer (MSI) version, which is func-cli-X.X.XXXX-x*.msi. Don't install the 4.x version, which isn't supported and won't work.
    - 安裝完成後執行 `func --version` 確認
    ![](https://i.imgur.com/UrwrdMy.png =300x)
- **[.NET Core 3.1 SDK](https://dotnet.microsoft.com/en-us/download/dotnet/3.1)**: references the .NET Core runtime 3.x version that you have that's later than 3.1.201
- **[Postman](https://www.postman.com/downloads/)**: 測試 API 使用，或使用 curl 也可以
- [Logic App Environment for Win Package](https://1drv.ms/u/s!AtAJk4ApWmAFhJM2rhZC-CREO1yGtg?e=qlbgQ0)
### 使用 Visual Studio Code
- 建立新的資料夾，命名為`CatFactProj`
- 開啟 Visual Studio Code，選擇 Open Folder
    ![](https://i.imgur.com/TZbr2Of.png)
- 開啟剛剛建立的新資料夾
    ![](https://i.imgur.com/hV0HqjV.png)
- 左邊菜單點選 ![](https://i.imgur.com/iPXUC57.png =35x) > Azure Logic App (Standard) 的 Extension，點選 Sign in to Azure (如先前已有登入此處無須再登)
    ![](https://i.imgur.com/8XQgwHp.png)
- 登入完成後，點選 Logic Apps (STANDARD) 的![](https://i.imgur.com/Slbrk5m.png =30x) 新增一個 Logic App Project
    ![](https://i.imgur.com/Zb9w5l5.png)
- 選擇 Stateful Workflow
    ![](https://i.imgur.com/xaWhVZD.png)
- 填入 workflow 的名稱 `catfact-api` (可任意命名)
    ![](https://i.imgur.com/1QjKfcX.png)
- 點選左邊菜單的 Explorer (第一個)，找到在 `catfact-api` 資料夾底下的 workflow.json > 右鍵 > Open in Designer 
    ![](https://i.imgur.com/svKeur1.png)
    :::info
    :bulb: 第一次開啟 Designer 會需要時間
    :::
- 選擇 Use Connectors from Azure
    ![](https://i.imgur.com/tniwYd8.png)
- 選擇先前建立 Logic App 資源的資源群組 
    ![](https://i.imgur.com/RapvyFu.png)
- Designer 開啟完成後，選擇 trigger 為 When a HTTP request is received
    ![](https://i.imgur.com/XLz2V5k.png)
- 點選 + > Add an action 來新增下一動
    ![](https://i.imgur.com/RzWDkPz.png =600x)
- 在 Add an action 區塊中搜尋 `http`，選擇 ![](https://i.imgur.com/UF4L4sH.png =100x) 的 action，並設定參數
    ![](https://i.imgur.com/REHpEfj.png)
    - **Method**: GET
    - **URI**: `https://cat-fact.herokuapp.com/facts/`
    ![](https://i.imgur.com/KLrbzmS.png)
- 點選 + > Add an action 來新增下一動
    ![](https://i.imgur.com/FxrEa4K.png =600x)
- 在 Add an action 區塊中搜尋 `response`，選擇 ![](https://i.imgur.com/eZ1UhzU.png =120x) 的 action，並設定參數
    ![](https://i.imgur.com/vK46TMV.png)
    - **Status Code**: ![](https://i.imgur.com/vFMlnMs.png =140x)
        ![](https://i.imgur.com/0QU1L2m.png)    
    - **Body**: ![](https://i.imgur.com/1wbPDtK.png =80x)
        ![](https://i.imgur.com/jMbrNBw.png)
- 完成後點選 Save
    ![](https://i.imgur.com/6umHbg6.png =600x)
- 確認 `workflow.json` 有更新
    ![](https://i.imgur.com/Aoa3m9r.png)

### (無環境不操作) Local 測試
- 到 [Azure Portal](https://portal.azure.com)，找到 Logic App 建立時一併建立的 Azure Storage Account (使用 Dev Logic App 的 Storage)
    ![](https://i.imgur.com/Nk5AeTe.png)
- 點選 Storage 進入後，找到 Access Keys > Show Keys，將 Connection String 記下 (使用 key1 或 key2 都可以)
    ![](https://i.imgur.com/QNZziP0.png)
- 回到 Visual Studio Code，找到 local.settings.json 的檔案，開啟編輯，將原本的 `"AzureWebJobsStorage": "UseDevelopmentStorage=true",` 取代成 `"AzureWebJobsStorage": "<storage-access-key>",`後，儲存
    ![](https://i.imgur.com/UfPFDGq.png)
- 在 .vscode 資料夾底下，編輯 launch.json 檔案，將內容全部取代成以下
    ```json=1
    {
        "version": "0.2.0",
        "configurations": [
            {
                "name": "Attach to .NET Functions",
                "type": "coreclr",
                "request": "attach",
                "processId": "${command:azureLogicAppsStandard.pickProcess}"
            }
        ]
    }
    ```
- 點選左邊菜單，![](https://i.imgur.com/f9GqiZ0.png =30x) Run and debug > ![](https://i.imgur.com/dwuiaiN.png =190x)
    ![](https://i.imgur.com/xrzaS7I.png)
- 開始執行後出現以下畫面
    ![](https://i.imgur.com/GRRkZIi.png)
- 回到 ![](https://i.imgur.com/xq59AGE.png =30x) Explorer，選擇 catfact-api 資料夾下的 workflow.json，右鍵選擇 Overview
    ![](https://i.imgur.com/CMhz8xq.png =500x)
- 將 Callback URL 複製下來
    ![](https://i.imgur.com/KcZIeRY.png)
- 到 Postman 上，使用 POST 測試
    ![](https://i.imgur.com/8ssm7L2.png)
- 回到 Visual Studio Code > Overview 上，可察看執行紀錄，點選 show run
    ![](https://i.imgur.com/ZrSDnRw.png)
- 查看每一動的執行時間及結果
    ![](https://i.imgur.com/xCakD02.png)
- 點選上放的![](https://i.imgur.com/9EhxMS2.png =30x)，進行 disconnect
    ![](https://i.imgur.com/p5y6NcS.png)
- 手動部屬到 Azure Logic App (Standard)
    - 在 Explorer 空白處點選右建 > Deploy to Logic App
    ![](https://i.imgur.com/lPls0ku.png =450x)
    - 選擇 Logic App (Standard) in Azure 為測試用的 Logic App 資源
    ![](https://i.imgur.com/Pr1Ramo.png)
    - 如有警示窗告知會進行覆蓋，選擇 Deploy
    ![](https://i.imgur.com/tdN8wdV.png)
    - 右下的通知點選 Output window 可查看部屬狀況
    ![](https://i.imgur.com/J1aOSCy.png =300x)
    - 部屬完成
    ![](https://i.imgur.com/Ahushd3.png)
- 到 [Azure Portal](https://portal.azure.com) Dev Logic App 環境確認 workflow 已部屬完成
    ![](https://i.imgur.com/oyifuDc.png)
- 透過 ![](https://i.imgur.com/RrRwQfR.png =100x) > Run 驗證，
![](https://i.imgur.com/Q4r7bjE.png)
    
### (無環境操作) 使用 sample code
:::info
:bulb: 若本機尚未安裝環境或安裝有狀況，可先使用 sample 進行後續課程
:::
- 下載 [huier23/logic-app-standard](https://github.com/huier23/logic-app-standard) 
    ```
    git clone https://github.com/huier23/logic-app-standard.git
    ```
- 將 logic-app-standard 開啟，把 pet-food-facts-api 剪下貼到桌面
![](https://i.imgur.com/dzPi8Ds.png)
- 用 Visual Studio Code 將 logic-app-standard 開啟
- 編輯 local.settings.json 檔案，修改以下內容為個人資訊後儲存
    ![](https://i.imgur.com/6HZARYT.png)
    - "WORKFLOWS_TENANT_ID": "tenant-id",
    - "WORKFLOWS_SUBSCRIPTION_ID": "subscription-id",
    - "WORKFLOWS_RESOURCE_GROUP_NAME": "rg-name",
    - "WORKFLOWS_LOCATION_NAME": "location-with-no-space",
    - tenant-id 取得：Azure Active Directory 中可取得 Tenant ID
        ![](https://i.imgur.com/m0P1THG.png)
    - subsctiption-id 取得：resource group 中的 overview
        ![](https://i.imgur.com/n7BDu7b.png)
- 開啟終端機，輸入指令`git remote remove origin`
    ![](https://i.imgur.com/eBGhBX3.png)

    
### 設定 CI/CD on Azure DevOps
- 到 [Azure DevOps](https://dev.azure.com)，選擇 Repos，建立新的 Repository
![](https://i.imgur.com/MWUMnup.png)
- 將新的 Repository 命名為 `logic-app-standard` (或任意命名)
![](https://i.imgur.com/hex6YeP.png =400x)
- 複製 git repository url
![](https://i.imgur.com/lrhSq1w.png)
- 回到 Visual Studio Code 上，上方選單 Terminal > New Terminal，開啟終端機
![](https://i.imgur.com/xX4IVK0.png)
- 可改成使用 cmd
![](https://i.imgur.com/ZBlWqkO.png)
- 使用 git 將程式碼推送至遠端程式庫
    ```.sh
    git init .
    git add .
    git commit -m "first commit"
    git remote add origin <remote-repo-url>
    git push origin master
    ```
    ![](https://i.imgur.com/apiYe3Z.png)

- 確認程式碼已有推送成功
![](https://i.imgur.com/fL0M3cF.png)
- 點選左方菜單 > Pipelines > Create Pipeline
![](https://i.imgur.com/lbQvcZ6.png)
- 選擇 Use the classic editor
![](https://i.imgur.com/BG0VObv.png =600x)
- 選擇 standard 的 repo
![](https://i.imgur.com/G1SQ4Zo.png)
- 使用空白的 template，選擇 Empty Job
![](https://i.imgur.com/FHiKWVa.png)
- 點選 Agent Job 1 的 ，搜尋 `copy`，將 Copy files > Add
![](https://i.imgur.com/gpj8cXj.png)
- 設定 Copy files
    - **Source Folder**: (留白)
    - **Contens**: `**`
    - **Target Folder**: `$(Build.ArtifactStagingDirectory)/$(Build.BuildId)`
    ![](https://i.imgur.com/9sMBS14.png =600x)
- 再新增一個，搜尋 `Archive`，將 Archive files > Add
    ![](https://i.imgur.com/d3ESJN0.png)
- 設定 Archive files
    - **Root folder or file to archive**: `$(Build.ArtifactStagingDirectory)/$(Build.BuildId)`
    - **Prepend root folder name to archive paths**: **不勾選**
    - **Archive type**: `zip`
    - **Archive file to create**: `$(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip`
    ![](https://i.imgur.com/4qzUGIW.png =600x)
- 新增第三個，搜尋 `Publish`，將 Publish build artifacts > Add
    ![](https://i.imgur.com/BYLF094.png)
- 設定 Publish Artifact
    - **Path to publish**: `$(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip`
    ![](https://i.imgur.com/Mp80ZXo.png =600x)
- 修改 Pipeline 名稱為 `logic-app-standard-CI` (或任意命名)
    ![](https://i.imgur.com/f1uYBN1.png)
- 設定 Continuous Integration，點選上方 Trigger > Enable continuous integration
![](https://i.imgur.com/QfCw3sj.png)
- 完成後點選 Save & queue > Save and run
    ![](https://i.imgur.com/sNdfxFp.png)
- 建立 Release Piplien，點選 Release > ![](https://i.imgur.com/swx8w0S.png =85x) > ![](https://i.imgur.com/oml5xaG.png =200x)

    ![](https://i.imgur.com/auwSNLn.png)

- 選擇 Empty job
    ![](https://i.imgur.com/rtKuxuy.png)
- Stage 命名為 `Prod` (或任意命名)
    ![](https://i.imgur.com/Bxefv1m.png)
- 新增部屬來源，點選 + Add an artifact，並新增來源為 build pipeline
    - **Source Type**: Build
    - **Source (build pipeline)**: Logic App standard CI
    - **Default version**: Latest    
    ![](https://i.imgur.com/e4ku31c.png)
- 設定 Continuous deployment，點選 artifact 的![](https://i.imgur.com/wbnTSlI.png =30x)，將 Continuous deployment trigger 做 Enable
    ![](https://i.imgur.com/wWM3Mg5.png)
- 設定 Prod 的 task，點選 1job, 0 task
    ![](https://i.imgur.com/iYdDc85.png =600x)
- 點選 Agent job 的 + > 搜尋 `function` > Azure Functions > Add
    ![](https://i.imgur.com/x2NkqYh.png)
- 設定 Azure Function App Deploy 的 task
    - **Azure subscription**: xxxx's subscription
    - **App type**: Function App on Windows
    - **App name**: `$(LOGIC_APP)`
    - **Package or folder**: `$(System.DefaultWorkingDirectory)/**/drop/*.zip`
    - A**dditional Deployment Options** | **Deployment method**: Zip Deploy
    ![](https://i.imgur.com/TtPAjxc.png)
- 設定 Pipeline variable，點選 上方 Variables > + Add，將 `LOGIC_APP` 及 value 設定 (value 為要部屬的 logic app resource name)
    ![](https://i.imgur.com/Nli4SBL.png)
- 完成後點選 Pepeline，點選 Prod stage 的![](https://i.imgur.com/6OCUaiZ.png =30x)，將 Pre-deployment approvals 設定為 Enabled，並加入審核人
    ![](https://i.imgur.com/KRO6Dr7.png)
- 修改 release pipeline 名稱後 Save
    ![](https://i.imgur.com/tVYN2zD.png)
- 點選右上方的 Create Relase > Create ，開始執行 release-1
![](https://i.imgur.com/OIkzpdQ.png =500x)
- 點擊狀態列出現的 Release-1，可查看此次 release 狀況
![](https://i.imgur.com/HsdmTBR.png)
- 因 Prod 有設定審核機制，點選 Approve，允許部屬
![](https://i.imgur.com/LLv99kq.png)
- 點選 Logs 可查看 raw log
![](https://i.imgur.com/3qY2EwO.png =500x)

### (無環境不操作) 新增新 workflow
- 回到 Visual Studio Code，選擇左方菜單的![](https://i.imgur.com/kheRC61.png =30x)
- 點選![](https://i.imgur.com/Yh3A3YO.png =30x)Create new project
- 選擇同樣的 `CatFactProj`
    ![](https://i.imgur.com/pio3GDV.png)
- 選擇 Stateless
    ![](https://i.imgur.com/OB4wlgK.png)
- 將API命名為 `pet-food-facts-api` (或任意命名)
    ![](https://i.imgur.com/E9IyUu0.png)
- host.json、local.settings.json、.gitignore.json、.funcignore.json 皆不覆蓋，選擇 **NO**
    ![](https://i.imgur.com/kKGcZsZ.png =500x)
    ![](https://i.imgur.com/vKuAoOL.png =470x)
    ![](https://i.imgur.com/ZLEvVLX.png =450x)
    ![](https://i.imgur.com/832LasY.png =450x)
    :::info
    :bulb: 確認 local.settings.json 檔案中的 `AzureWebJobsStorage` 設定是否為 Azure Blob Storage
    :::
- 選擇 pet-food-facts-api 資料夾下的 workflow.json，右鍵 > Open in Designer
    ![](https://i.imgur.com/Na4Q93i.png =500x)
- 新增 When a HTTP request is received 的 trigger，及 HTTP 的 action，HTTP 同樣使用 GET，URI 設定為 `https://world.openpetfoodfacts.org/api/v0/product/20106836.json`
    ![](https://i.imgur.com/tfykNN0.png)
- 添加 Response 並設定，完成後點選 Save
    ![](https://i.imgur.com/MQIQmb0.png)
- 測試
    ![](https://i.imgur.com/mRnHUfI.png)
- 從 Overview 中確認 Callback URL
    ![](https://i.imgur.com/u00HsBV.png)
- 使用本機 postman 驗證
    ![](https://i.imgur.com/8nlmhRv.png)
- 部屬
    ![](https://i.imgur.com/mt8DWjV.png)
    ![](https://i.imgur.com/rmateDx.png)
    ![](https://i.imgur.com/bHjvccK.png)
- 驗證 Azure 中的測試環境中有多一個 workflow
### (無環境操作) 新增新 workflow 
- 將原本移動到桌面的 pet-food-facts-api 移動回 logic-app=standard 的資料夾下
    ![](https://i.imgur.com/2y97tIc.png)
### Checkin 程式碼並驗證自動化流程
- 回到 Visual Studio Code，開啟 terminal，執行 git 做推送
    ```
    git add .
    git commit -m "add pet-food-facts-api workflow"
    git push origin master
    ```
    ![](https://i.imgur.com/CdqxU9G.png)
- 回到 [Azure DevOps](https://dev.azure.com)，確認 build pipeline 有自動執行
    ![](https://i.imgur.com/0RqDOqa.png)
- 到 Release 確認工作有執行
    ![](https://i.imgur.com/0sThOE9.png)
- 點選![](https://i.imgur.com/NYz1kua.png =100x)做 approve 允許部屬至 Prod
    ![](https://i.imgur.com/YH5wejL.png =450x)
- 確認有成功部屬
    ![](https://i.imgur.com/mtQ38DG.png)
- 到 prod-logic-app 上確認新的 workflow
    ![](https://i.imgur.com/QE2Km6Z.png)

## 資源移除
- Remove Azure DevOps Organization: Organization Setting > Delete
    ![](https://i.imgur.com/prnTnwB.png)
- Remove Azure DevOps Project: Project Setting > Delete
    ![](https://i.imgur.com/lrISbT8.png)
- Azure Resource Reomove
    ![](https://i.imgur.com/N80KbFe.png)


## Reference
- [Public REST APIs | POSTMAN](https://documenter.getpostman.com/view/8854915/Szf7znEe)
- [Overview: Automate deployment for Azure Logic Apps by using Azure Resource Manager templates | Microsoft Doc](https://docs.microsoft.com/en-us/azure/logic-apps/logic-apps-azure-resource-manager-templates-overview)
- [DevOps deployment for single-tenant Azure Logic Apps | Microsoft Doc](https://docs.microsoft.com/en-us/azure/logic-apps/devops-deployment-single-tenant-azure-logic-apps)
- [Create an integration workflow with single-tenant Azure Logic Apps (Standard) in Visual Studio Code | Microsoft Doc](https://docs.microsoft.com/en-us/azure/logic-apps/create-single-tenant-workflows-visual-studio-code)
- [TODO API](https://app-todo-crud-api.azurewebsites.net/api/Todo)
- [Azure DevOps 免費申請教學](https://hackmd.io/W10Lp86YR2SnPtlrFyalMw?view)
- [API Management - Backend | Microsoft Doc](https://docs.microsoft.com/en-us/rest/api/apimanagement/current-ga/backend)
- [Logic Apps (Single-tenant) | GitHub](https://github.com/Azure/logicapps/tree/master/azure-devops-sample)
- [Microsoft-hosted agents | Microsoft Doc](https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/hosted?view=azure-devops&tabs=yaml)
- [Use predefined variables | Microsoft Doc](https://docs.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=azure-devops&tabs=yaml)