跳至主要内容

使用 Power Automate 自動化 Jira Service Management 報表

產生定期的 Jira Service Management (JSM) 報表可能非常耗時,特別是需要處理分頁、自訂欄位和 CSV 格式化需求時。本指南提供完整的實作教學,使用 Power AutomateJira Cloud APISharePoint 建立自動化報表工作流程。

本文章專為 IT 專業人員撰寫,提供實作方案且不包含任何組織敏感資訊。所有範例都使用匿名化的佔位符,您可以替換成自己的數值。


架構總覽


我們要建立什麼

一個 Power Automate 流程:

  1. 固定排程執行(例如每兩週一次)
  2. 呼叫 Jira Cloud REST API 並正確處理分頁
  3. 收集所有議題(即使超過 500+ 筆)
  4. 將巢狀 JSON 欄位(包含自訂欄位)扁平化為 CSV 檔案
  5. 將 CSV 儲存到 SharePoint
  6. 寄送 Email 附加 CSV 檔案

實作成果展示

想看看這個自動化能達成什麼效果?

查看包含實際儀表板和 KPI 視覺化的最終成果展示

JSM Sales Performance Dashboard - GitHub Repository

此儲存庫展示:

  • KPI 儀表板:從自動化 Jira 報表建立
  • 真實案例:銷售團隊績效追蹤
  • 資料視覺化範例:CSV 報表如何轉換為可操作的洞察
  • 正式環境部署:企業環境中的實際實作

前置需求

開始之前,請確認您有:

  • Jira Cloud
    • 已儲存的篩選條件(我們將使用其篩選條件 ID)
    • 用於認證的 Jira API token
  • Microsoft 365
    • Power Automate 存取權限
    • SharePoint Online
    • Outlook 信箱(用於郵件傳送)

步驟 1:取得 Jira 篩選條件 ID

如何找到篩選條件 ID

  1. 在瀏覽器中開啟 Jira

  2. 前往 Filters → View all filters

  3. 點選您要用於報表的篩選條件

  4. 查看瀏覽器網址列:

    https://yourtenant.atlassian.net/issues/?filter=12345
  5. filter= 後面的數字就是您的篩選條件 ID(此例中為 12345

在 API 請求本文中,您將使用:

"jql": "filter = 12345"

12345 替換成您實際的篩選條件 ID。


步驟 2:產生 Jira API Token

  1. 前往 https://id.atlassian.com/manage-profile/security/api-tokens
  2. 點選 Create API token
  3. 輸入標籤(例如 "Power Automate Integration")
  4. 複製 token 並妥善保存
  5. 此 token 將作為 HTTP Basic Authentication 中的密碼

步驟 3:了解 Jira Search API

API 端點

POST https://<YOUR_TENANT>.atlassian.net/rest/api/3/search/jql

請求本文(範例)

{
"jql": "filter = 12345",
"maxResults": 100,
"fields": [
"key",
"summary",
"status",
"duedate",
"resolution",
"created",
"customfield_10001",
"customfield_10002",
"customfield_10003",
"assignee",
"reporter",
"priority",
"description"
],
"nextPageToken": ""
}

關鍵參數

參數說明
jqlJQL 查詢(建議使用篩選條件 ID)
maxResults每頁議題數量(建議:100)
fields要取得的欄位 ID 陣列(包含 customfield_XXXXX)
nextPageToken第一次呼叫使用空字串,後續使用回應中的值

API 回應(簡化版)

{
"issues": [ /* 議題物件陣列 */ ],
"isLast": false,
"nextPageToken": "eyJwYWdlIjoyfQ=="
}

關鍵欄位:

  • issues - 議題物件陣列(每頁最多 100 筆)
  • isLast - 布林值,表示是否為最後一頁
  • nextPageToken - 取得下一頁的 token

步驟 4:建立 Power Automate 流程

Power Automate 流程架構

開始建立之前,先看完整的流程結構:

流程區段:

區段顏色動作目的
初始化藍色Recurrence + 3 個變數設定觸發器和儲存空間
分頁迴圈黃色HTTP + Parse + Append + Update跨頁面收集所有議題
資料轉換綠色Select + CSV將 JSON 扁平化為 CSV
輸出紫色/紅色SharePoint + Email傳遞結果

重點:

  • 迴圈結構:持續執行直到 Jira API 回傳 isLast = true
  • 變數更新:在迴圈內每頁處理後發生
  • 平行輸出:CSV 同時傳送到 SharePoint 和 Email
  • 安全限制:迴圈最多 60 次迭代和 1 小時逾時

4.1 建立新的排程流程

  1. 前往 Power Automate
  2. 點選 Create → Scheduled cloud flow
  3. 設定:
    • Flow nameJira Biweekly CSV Report
    • Starting:選擇開始日期/時間
    • Repeat every2Weeks
  4. 點選 Create

4.2 設定週期性觸發器

Recurrence 觸發器中設定這些值:

屬性
FrequencyWeek
Interval2
Time zone您的時區(例如 (UTC+08:00) Taipei
At these hours9
At these minutes0

這表示:每兩週的 09:00 執行


4.3 初始化變數

新增三個 Initialize variable 動作:

變數 1:varAllIssues(陣列)

  • NamevarAllIssues
  • TypeArray
  • Value:(保持空白)

變數 2:varNextPageToken(字串)

  • NamevarNextPageToken
  • TypeString
  • Value:(保持空白 - 代表 ""

變數 3:varIsLast(布林值)

  • NamevarIsLast
  • TypeBoolean
  • Valuefalse

4.4 新增 "Do until" 迴圈

新增動作:Do until

條件設定:

  • 左側:variables('varIsLast')
  • 運算子:is equal to
  • 右側:true

變更限制:

  • Count60(最多 60 次迭代)
  • TimeoutPT1H(1 小時)

這確保迴圈將:

  • 持續執行直到 Jira 表示最後一頁(isLast = true
  • 有安全限制以防止無限迴圈

4.5 在 "Do until" 內 - HTTP 呼叫 Jira

動作:HTTP

屬性
MethodPOST
URIhttps://<YOUR_TENANT>.atlassian.net/rest/api/3/search/jql
HeadersContent-Type: application/json
AuthenticationBasic
Username您的 Jira 帳號 email
Password您的 Jira API token(來自步驟 2)

Body(使用程式碼檢視較易編輯):

{
"jql": "filter = 12345",
"maxResults": 100,
"fields": [
"key",
"summary",
"status",
"duedate",
"resolution",
"created",
"customfield_10001",
"customfield_10002",
"customfield_10003",
"assignee",
"reporter",
"priority",
"description"
],
"nextPageToken": "@{variables('varNextPageToken')}"
}

重要注意事項:

  • <YOUR_TENANT> 替換為您的 Jira 租戶名稱
  • 12345 替換為您實際的篩選條件 ID
  • customfield_XXXXX 替換為您實際的自訂欄位 ID
  • @{variables('varNextPageToken')} 表達式將由 Power Automate 評估

4.6 在 "Do until" 內 - 解析 JSON

新增動作:Parse JSON

屬性
Content動態內容:Body(來自 HTTP 步驟)
Schema參見下方架構

JSON Schema(範例):

{
"type": "object",
"properties": {
"issues": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": { "type": "string" },
"key": { "type": "string" },
"fields": { "type": "object" }
},
"required": ["id", "key", "fields"]
}
},
"nextPageToken": {
"type": ["string", "null"]
},
"isLast": {
"type": "boolean"
}
},
"required": ["issues", "isLast"]
}

提示: 您可以自動產生此架構:

  1. 使用 Postman 或類似工具手動執行一次 HTTP 呼叫
  2. 複製回應 JSON
  3. 在 Power Automate 的 Parse JSON 動作中,點選 Use sample payload to generate schema
  4. 貼上您的範例回應

4.7 在 "Do until" 內 - 附加每個議題

新增動作:Apply to each

屬性
Select an output from previous stepsbody('Parse_JSON')?['issues']

在此 Apply to each 內,新增動作:Append to array variable

屬性
NamevarAllIssues
Valueitem()(表達式)

重要:絕對不要使用 union()

絕對不要使用:

union(variables('varAllIssues'), variables('varAllIssues'))

這會導致自我參照錯誤。永遠使用 Append to array variable


4.8 在 "Do until" 內 - 更新分頁變數

Apply to each 之後(仍在 Do until 迴圈內),新增兩個 Set variable 動作:

設定變數 1:varNextPageToken

屬性
NamevarNextPageToken
Valuebody('Parse_JSON')?['nextPageToken']

設定變數 2:varIsLast

屬性
NamevarIsLast
Valuebody('Parse_JSON')?['isLast']

重要:絕不硬編碼 true

永遠使用 API 回應值,而不是硬編碼布林值。這確保正確的分頁處理。


步驟 5:將議題扁平化為 CSV 格式

5.1 Select 動作(欄位對應)

Do until 迴圈之後(在迴圈外),新增動作:Select

屬性
Fromvariables('varAllIssues')

欄位對應(透過 GUI 逐列新增):

欄位名稱值(表達式)
IssueKeyitem()?['key']
IssueIditem()?['id']
Summaryitem()?['fields']?['summary']
Statusitem()?['fields']?['status']?['name']
DueDateitem()?['fields']?['duedate']
Resolutionitem()?['fields']?['resolution']?['name']
Createditem()?['fields']?['created']
CustomField1item()?['fields']?['customfield_10001']?['value']
CustomField2item()?['fields']?['customfield_10002']
CustomField3item()?['fields']?['customfield_10003']?['displayName']
AssigneeNameitem()?['fields']?['assignee']?['displayName']
AssigneeEmailitem()?['fields']?['assignee']?['emailAddress']
ReporterNameitem()?['fields']?['reporter']?['displayName']
Priorityitem()?['fields']?['priority']?['name']
Descriptionitem()?['fields']?['description']

重要提示:

  • 透過 GUI 逐列新增每個對應
  • 不要貼上大型 JSON 物件 - Power Automate 會拒絕
  • 使用 ? 運算子進行安全的 null 處理
  • 根據您的自訂欄位結構調整欄位路徑

5.2 建立 CSV 表格

新增動作:Create CSV table

屬性
FromSelect 動作的輸出
ColumnsAutomatic(或需要時選 Custom

此動作將 JSON 陣列轉換為帶標題的 CSV 格式。


步驟 6:將 CSV 儲存到 SharePoint

新增動作:Create file

屬性
Site Addresshttps://contoso.sharepoint.com/sites/YourSite
Folder Path/Shared Documents/JiraReports
File NameJiraReport-@{formatDateTime(utcNow(),'yyyyMMddHHmmss')}.csv
File ContentCreate CSV table 的輸出

替換佔位符:

  • contoso → 您的租戶名稱
  • YourSite → 您的 SharePoint 網站名稱
  • JiraReports → 您的文件庫路徑

這會建立帶時間戳記的檔案,例如:

JiraReport-20251121093015.csv
JiraReport-20251205093022.csv

步驟 7:傳送 Email 附加檔案

新增動作:Send an email (V2)

屬性
Toreports@contoso.com
Subject[Biweekly Jira Report] Filter 12345 - @{formatDateTime(utcNow(),'yyyy-MM-dd')}
Body參見下方 HTML 本文

Email 本文(HTML 範例):

<p>團隊您好,</p>
<p>請查收最新的 Jira Service Management 報表(篩選條件 12345)。</p>
<p>此報表包含:</p>
<ul>
<li>所有開啟和關閉的議題</li>
<li>自訂欄位值</li>
<li>經辦人和回報者資訊</li>
</ul>
<p>CSV 檔案也已儲存在 SharePoint:</p>
<p><strong>/Shared Documents/JiraReports</strong></p>
<br/>
<p>此致,<br/>自動化系統</p>

附件:

屬性
Attachments NameJiraReport-@{formatDateTime(utcNow(),'yyyyMMdd')}.csv
Attachments ContentCreate CSV table 的輸出

疑難排解指南

常見問題與解決方案

1. varAllIssues 的自我參照錯誤

錯誤訊息:

The action 'Set_variable' cannot use the variable 'varAllIssues' in its inputs

原因:

使用了 union(variables('varAllIssues'), variables('varAllIssues'))

解決方案:

永遠在 Apply to each 內使用 Append to array variable


2. Parse JSON 持續失敗

錯誤訊息:

Invalid type. Expected Object but got Array.

原因:

架構與實際 API 回應結構不符

解決方案:

  1. 使用 Postman 或類似工具取得真實的 API 回應
  2. 複製完整的 JSON 回應
  3. 在 Power Automate Parse JSON 動作中,點選 Use sample payload to generate schema
  4. 貼上您的真實回應
  5. 檢視並調整產生的架構

3. Select 動作顯示 "Enter valid JSON"

錯誤訊息:

Invalid expression: expected JSON object

原因:

將整個 JSON 物件貼到單一對應欄位中

解決方案:

  • 透過 GUI 逐一新增每個欄位對應
  • 每個欄位只輸入一個表達式
  • 範例:item()?['fields']?['summary'](不是整個物件)

4. 流程只回傳前 100 筆議題

問題:

報表總是剛好包含 100 筆議題,即使篩選條件有 500+ 筆

原因:

  • Do until 條件設定不正確
  • varIsLast 未從 API 回應更新
  • nextPageToken 未在 HTTP body 中傳遞

解決方案檢查清單:

  • Do until 條件檢查 varIsLast = true
  • varIsLast 使用 body('Parse_JSON')?['isLast'] 更新
  • nextPageToken 在 HTTP body 中作為 @{variables('varNextPageToken')} 傳遞
  • 變數更新中沒有硬編碼的 truefalse

5. 認證 401 或 403 錯誤

錯誤訊息:

401 Unauthorized
403 Forbidden

原因:

  • API token 無效
  • 權限不足
  • 使用者名稱/密碼格式錯誤

解決方案:

  1. 驗證 API token 有效(必要時重新產生)
  2. 確認您的 Jira 使用者有權限:
    • 檢視篩選條件
    • 存取篩選條件中的所有議題
    • 檢視使用的所有自訂欄位
  3. 確保使用者名稱是您的 email 地址(不是顯示名稱)
  4. 確保密碼是 API token(不是您的 Jira 密碼)

最佳實踐

效能最佳化

  1. 使用 maxResults = 100

    • 這是 Jira API 的最佳批次大小
    • 較大的值可能導致逾時
    • 較小的值會增加 API 呼叫開銷
  2. 使用已儲存的篩選條件而非複雜的 JQL

    • "jql": "filter = 12345" 更易維護
    • 複雜的 JQL 可以在 Jira UI 中測試後再硬編碼
  3. 設定適當的迴圈限制

    • Count:60(處理最多 6000 筆議題)
    • Timeout:PT1H(最長執行時間 1 小時)

資安考量

API Token 管理 - 選擇您的安全等級

重要:本教學使用 Level 1(基本保護) - 直接將 API token 儲存在 Power Automate 的 HTTP 動作中。這對大多數使用情境來說是安全且實用的方法。Level 2(Azure Key Vault)是選用的,僅在特定企業情境下需要。

Level 1:基本保護(本教學使用)✓

直接將 API token 儲存在 HTTP 動作的 Authentication 欄位:

屬性
AuthenticationBasic
Usernameyour.email@company.com
PasswordATATT3xFfGF0...(API Token)

安全功能:

  • Power Automate 自動加密 token
  • Token 不會顯示在匯出的流程定義中
  • 存取由 Power Automate 權限控制

適用時機:

  • 個人專案或概念驗證
  • 小型團隊(< 5 人)
  • 非受監管環境

不建議在以下情況使用:

  • ❌ 多個流程共用相同 token(輪換變得困難)
  • ❌ 合規要求強制集中式密鑰管理
  • ❌ 需要定期 token 輪換

Level 2:Azure Key Vault(選用 - 僅企業需求)

注意:此等級僅在組織要求集中式密鑰管理時需要。大多數使用者可以跳過此章節。

動態從 Azure Key Vault 取得 token:

步驟 1:將 token 儲存在 Azure Key Vault

az keyvault secret set \
--vault-name "YourKeyVault" \
--name "JiraApiToken" \
--value "ATATT3xFfGF0..."

步驟 2:在 Power Automate 新增 "Get secret" 動作

在 "Do until" 迴圈之前,新增:

動作Get secret (Azure Key Vault)
Vault nameYourKeyVault
Secret nameJiraApiToken
Output variablebody('Get_secret')?['value']

步驟 3:在 HTTP 動作中參照

屬性
AuthenticationBasic
Usernameyour.email@company.com
Password@{body('Get_secret')?['value']}

優點:

  • ✅ 集中式 token 管理
  • ✅ 輕鬆輪換(更新 Key Vault,所有流程自動更新)
  • ✅ 存取稽核日誌
  • ✅ 使用 Managed Identity 的細緻存取控制
  • ✅ 符合合規要求(SOC2、ISO 27001)

僅在以下情況使用:

  • ❗ 強制性合規要求(SOC2、ISO 27001、HIPAA)
  • ❗ 超過 10 個流程共用相同憑證
  • ❗ 嚴格的 token 輪換政策(每 30 天或更短)
  • ❗ 專職的 Azure 基礎設施團隊

對大多數使用者:Level 1 已足夠且更易維護。


絕對不要做的事 ❌

絕不以明文嵌入 token:

// ❌ 不要:在 JSON body 中硬編碼
{
"jql": "filter = 12345",
"apiToken": "ATATT3xFfGF0..." // 在流程定義中暴露!
}
// ❌ 不要:以明文儲存在變數中
Initialize variable: varApiToken = "ATATT3xFfGF0..."
// ❌ 不要:手動建構 Authorization header
Headers: {
"Authorization": "Basic base64encodedtoken..." // 在日誌中可見!
}

為什麼這些很危險:

  • Token 出現在流程匯出檔案中
  • 在執行歷程日誌中可見
  • 任何有流程讀取權限的人都可以提取

其他安全最佳實踐

2. 使用服務帳號

  • 為自動化建立專用的 Jira 服務帳號
    • 範例:automation-bot@company.com
  • 更容易稽核和輪換憑證
  • 防止個人帳號鎖定影響自動化
  • 人類和機器身份的明確分離

3. 限制 SharePoint 權限

  • 僅授予特定文件庫的寫入權限
  • 使用最小權限原則
  • 如可能,建立專用的 SharePoint 應用程式註冊

4. 啟用稽核記錄

  • 監控流程執行歷程以發現異常
  • 設定認證失敗的警示
  • 每月檢視 Key Vault 存取日誌

5. 實施 token 輪換

  • Level 1:每 90 天手動輪換
  • Level 2:使用 Azure Functions 自動輪換
  • 記錄輪換程序

6. 保護流程本身

  • 限制流程編輯權限給授權使用者
  • 使用環境特定的流程(Dev/Test/Prod)
  • 在 Git 中版本控制流程定義

遷移路徑:從基本到企業級

如果您從 Level 1 開始並需要升級:

步驟 1:建立 Azure Key Vault

az keyvault create --name "CompanyJiraVault" --resource-group "RG-Automation"

步驟 2:將現有 token 移至 Key Vault

az keyvault secret set --vault-name "CompanyJiraVault" \
--name "JiraApiToken" --value "<your-existing-token>"

步驟 3:更新流程(無需重建)

  • 在 HTTP 呼叫前新增 "Get secret" 動作
  • 更新 HTTP Authentication 密碼欄位以參照密鑰
  • 使用手動觸發測試
  • 刪除舊的硬編碼 token

停機時間:零 - 可在維護時段完成

可維護性

  1. 使用描述性的變數名稱

    • varAllIssuesvar1
    • varNextPageToken 是自我記錄的
  2. 為複雜表達式新增註解

    • 使用動作的 "Rename" 功能
    • 新增說明業務邏輯的註記
  3. 版本控制您的流程

    • 定期匯出流程定義
    • 儲存在原始碼控制系統(Git)

預期結果

成功實作後,您將擁有:

  • 自動化 CSV 報表:每兩週自動產生
  • 完整議題擷取:無論結果數量(處理 500+、1000+ 等)
  • 結構化資料:所有自訂欄位已扁平化
  • SharePoint 存檔:歷史報表
  • Email 通知:傳送給利害關係人
  • 零人工操作:初始設定後無需手動介入

總結

此解決方案展示了 Power Automate 如何與 Jira Cloud API 整合,建立完全自動化、正式環境等級的報表工作流程。透過正確處理:

  • 使用 nextPageToken 的 API 分頁
  • 無自我參照的變數管理
  • 巢狀 JSON 轉換為平面 CSV
  • SharePoint 整合以進行存檔
  • Email 傳送以進行分發

您可以建立在企業環境中處理數千筆議題的強大整合。

重點回顧

最佳實踐為何重要
使用 API 分頁 token確保所有記錄都被擷取
使用 "Append to array variable"避免自我參照錯誤
透過 GUI 建立 Select 對應防止 JSON 解析錯誤
保持 maxResults = 100最佳效能和可靠性
絕不硬編碼 isLast確保正確的迴圈終止
在 JQL 中使用篩選條件 ID比複雜查詢更易維護

下一步

準備好實作此解決方案了嗎?以下是一些資源:

實際運作展示

造訪 JSM Sales Performance Dashboard GitHub 儲存庫以查看:

  • 即時儀表板範例:展示自動化報表如何驅動業務洞察
  • KPI 視覺化:銷售和支援團隊的技術
  • 真實環境實作:在正式環境中
  • 端到端工作流程:從 Jira 議題到主管儀表板
  • 績效指標:追蹤和趨勢分析

延伸閱讀


此處展示的所有技術模式都經過正式環境測試並匿名化以供公開分享。歡迎根據您的組織需求調整此架構。