發表文章

Azure DevOps in Action - 如何避免開源套件的使用風險

圖片
近代軟體開發,不管是使用哪一種語言,幾乎都一定會使用到套件(Package),套件的使用都有著非常重大的意義。套件不只是讓開發變的更方便,套件的版本管理,能夠讓專案之間的相依性被有效管控,避免dependency hell的發生。 所以各大開發語言,不管是node.js、python、Java…都有自己的套件庫,微軟的.net當然也是,nuget就是.net開發人員的標準套件庫。如今,使用套件庫上的組件來開發企業內的專案,已經是理所當然的習慣了。 套件庫的使用風險 然而,使用套件並非100%毫無風險,由於開源軟體的觀念盛行,這個時代任何人都可以將自己開發的套件貢獻上nuget讓大家使用,雖然開發社群與nuget站台會針對有潛在或惡意風險的套件提出警訊,但由於這些資訊並非即時提供,且有可能因為開發人員的疏忽而沒有被發現,導致你的專案使用到有品質不佳,或是有安全疑慮的套件。 除此之外,套件還有許可授權的問題,並非每一個套件使用上都是毫無代價的,雖然nuget會要求套件開發人員具體標明套件的使用授權許可,但倘若開發人員不察,使用到一些並非可以免費使用的套件,或是使用到了標註為GPL的套件,那你依賴該套件開發的專案,也會被要求開源,這對於公司來說,可能會造成一場災難… 在CI Pipeline中掃描套件 因此,為了避免軟體開發人員一時疏忽,CI Pipeline有必要針對軟體套件的使用作一些掃描和檢查。而WhiteSourceBolt就是這樣的一套免費工具。 你可以在Azure DevOps Pipeline中,加入WhiteSourceBolt這個task,就可以輕易的掃描整個專案中使用的套件: 呈現出的報表如下: 你會發現,報表中清楚的告訴我們,哪些套件是高風險的,並且原因為何(上圖A)。如果你的專案有紅色高風險套件,強烈建議你要立即著手處裡(升級版本或尋找替代套件)。 要在Azure DevOps中啟用WhiteSourceBolt非常簡單,只需要為你的組織安裝Azure DevOps Marketplace中的外掛: 下載位置位於: https://marketplace.visualstudio.com/items?itemName=whitesource.ws-bolt 安裝好之後,你重新進入Azure DevOps,可以看到在...

內容審查(Content Moderator)服務

圖片
當網路上出現一則訊息,誰有權力判斷這則訊息的真假? 1.政府 2.平台業者 3.KOL(Key Opinion Leader, 意見領袖) 4.我自己 上面這個問題,不知道你的答案會選擇甚麼? 這兩天沸沸揚揚的中介法,造成了很多網路上的輿論。主因是平台業者被要求有責任管理(刪除或標註)不實言論,否則要罰款。 但這中間出現了兩個問題 1. 誰決定不實? 2. 如何做到有效即時的內容管理? 身為技術人員,我想從技術的角度談這件事情。首先,有沒有可能即時發現用戶將有問題的內容張貼到網站上? 技術上確實有可能。 現在微軟Azure, AWS, Google都有許多雲端AI服務,可以辨識圖片、影音、文字,近乎即時的判斷內容是否涉及情色、猥褻、或是具有冒犯意味甚至鼓吹自裁。這服務微軟叫做 Azure Content Moderator,內容仲裁 。總的來說,在當今的AI技術上,我們早就可以針對圖片、影像、或文字進行客觀的內容判斷,這些技術已經逐漸成熟,經驗上準確度大約八九成沒問題。 所以各大網站(像是FB)可能早已把這些技術用在內容分析上了(如果你的網站也需要,但不知道該怎麼做,可以與我聯繫)。但問題是,這些AI服務,可以判斷內容,無法知道對錯。 因為內容的正確與否,涉及價值觀的判斷。 在這個世界上,並不是所有事情都是非黑即白,一翻兩瞪眼的不是對就是錯,更何況,真假對錯很可能因為時間而有所改變。一開始你可能以為是對的(內容為真),但經過時間,很可能發現是錯的(內容為假),反之亦然。舉個更簡單的例子,不同世代對於同一件事情的看法,也往往南轅北轍。 如果第一時間不分青紅皂白的,就直接屏蔽刪除或標註某種論點,很可能事情將永遠沒有水落石出的一天。當然,如果你不在意真相(只在意管理),也就無所謂。 所以,從技術的角度來說,現在的科技就算不用靠誰立法、無須哪個單位協助,單單使用AI技術,就足以判斷內容是否違背善良風俗,這個也早就在做了。然而問題是,會不會我覺得的裸露、是你覺得的藝術呢? 這條界線該如何決定? 誰決定? 因為一旦涉及主觀價值判斷,所有的一切就變的不再簡單。 因此,AI就算能幫你辨識內容,卻無法幫你判斷真偽。 是非、對錯、真假,都很難由誰單方面說了算。 因此,我們再看一次這個問題。 當網路上出現一則訊息,誰有權力和責任判斷這則訊息的真假? 1...

Let it be

圖片
每當寫程式或文稿累了的時候,我會到河堤騎車。 最近這幾年,台北鄰靠基隆河的兩岸,都有了挺不錯的自行車道,幾乎沒甚麼難騎的上下坡,很適合以悠哉閒逛的心情慢慢騎吹吹風… 一天,忙了一整個下午,趁夜幕微微垂下,趕在日落前,我租了YoiuBike在河堤邊緩緩騎乘。岸邊隨風飄來青草的香味,讓人很是愉快。 正當我覺得身心放鬆,通體舒暢。卻不知耳邊何時傳來了一陣犀利(你要說淒厲也行)的對談聲,有點像是你去傳統菜市場會聽到的那種婆婆媽媽在攤販前理直氣壯的討價還價聲,聲音從遠而近,由小而大,漸漸飄了過來。 仔細一聽,位於六點鐘方位,後方。 一群騎著貌似淑女自行車的大媽,集團似的緩緩逼近。 我側眼一瞥,數了一數,五位。喔不,是六位,其中一位有些落單,奮力的在後面追趕。 前面五位大媽,領頭的三人,並排而行,佔據了來往雙線車道,伴隨著中氣十足的對談,讓人不注意到她們都很難。雖然距離有些遠,但言談中我依稀聽到關於某位大媽的兒子的太太的最近一些態度問題…呃…不關我事,非禮勿聽,我騎我的車。 加速前進。 可能是我租賃的YouBike齒輪比不佳,也可能是每天騎車的大媽中氣十足,我雖然加速超前了一定的距離,但每當我放鬆開始欣賞河邊的景色和迎風吹來的芬芳草香,一不注意,這群大媽集團立刻從後方逼近。一連數次,我在聽到了大媽們對談的特殊嗓音時,才意識到我快要被集團軍輾斃,只能瞬間加速遠離…但沒多久,我優閒的騎車氛圍就又會被身後堅持出現的音量所打破。 大媽們像是擁有裝上了勁量永備電池一樣的持久續航力,以堅毅且穩定(甚至我覺得似乎有愈來愈快)的速度屢屢逼近。 每當大媽集團軍從後方接近,我airpods裡的音樂聲量,總是不爭氣的敗陣下來… 當這條沿岸車道已經騎了約莫三分之二時…我,終於做出了決定。 在車道轉角處的某一個空曠處,我停了下來。站穩步伐,拍拍身上的風沙灰塵,好整以暇的,帶著敬佩與釋放的心情,目送大媽集團軍隊從我眼前騎過去… 喝了口從家中帶出來的水壺裡的氣泡水,整理了一下裝束,跨上自行車,我開始緩緩而行。 我何苦讓自己被身後追趕的雜音持續干擾著呢? 人生旅程上總是會碰到不同的人群,路程上人來人往、來來去去,我又不是要和誰比賽,幹嘛跟自己過不去,身後的雜音,不如就讓它從眼前過去。 等雜音遠離,我戴上耳機,依舊開始自在的騎自己的路,欣賞屬於自己的風景,以我自己習慣的速度,...

Azure DevOps in Action - 使用Deployment Group進行地端大量部署

圖片
使用Azure DevOps Services,部署到雲端相對容易,部署到地端環境,得考慮的事情就多了。主要的原因是,Azure DevOps Services在雲端,無法(也不應該)直接跳過防火牆存取地端環境上的伺服器。 另外,如果不管是雲端或地端伺服器,若是HA(高可用性)架構,做了負載平衡(Load Balance)或是Failover,部署站台時,需要把同樣的artfact一次部署到多台伺服器,在pipeline的設計上也有一定的難度。 上面提到的這些事情,解決方案就是『Deployment Group』。 功能說明 Deployment Group可以讓你把特定artifact一次部署到多台伺服器,同時,也可以突破防火牆的限制,從雲端部署到地端。其中的關鍵就在於,你必須在伺服器端安裝一個代理程式。 我們來看一下底下這個準備好的情境,我們準備了兩台Windows Server 2019 VM,名稱分別是testdpvm1與testdpvm2。並且,在這兩台伺服器上開啟了IIS,也運行了基本的網頁如下: 同時,我們也建立了一個Azure DevOps Team Project,其中的repo很簡單,只有一個html檔案: 並且,我們為這個repo的部署建立了一個CI Pipeline: 這個CI Pipeline的功能也超單純,只是打包這個 .html頁面成為 .zip檔案,然後放入(publish)到drop資料夾,準備給CD Pipeline使用。 建立Deployment Group 接著重點來了,我們待會要將drop資料夾中的artifact透過CD Pipeline如同『穿越防火牆』一般地『同時』發佈到那兩台剛才建好的VM上,為此,我們來建立Deployment Group。請在Pipeline功能中,找到Deployment Group,並且建立新的Deployment Group: 接著,為Deployment Group命名,一般採用的是你的環境名稱,例如Dev、QA、Production…等。 然後,請複製出現的PowerShell Script (別忘了要勾選Use a personal access token in the script for authentication): 運行代理程式 接著...

快速產生 .net core 測試程式碼覆蓋率報表

圖片
昨天,幫客戶介紹 .net core 的單元測試(Unit Test)開發。 其實,單元測試(Unit Test)是個非常簡單的概念,近代開發工具本身也都進化的超級方便,輕輕鬆鬆的就可以建立出單元測試專案的架構。 單元測試(Unit Test)看起來一點都不難。 這話只對了一半,單元測試難的地方並非撰寫單元測試程式碼本身(甚至,單元測試程式碼本來就應該盡可能的簡單,簡單到不該出現邏輯),難的地方是為了實施單元測試前的程式碼重構(如何增加程式碼的可測試性),以及如何在企業內真的推廣和實作。(因為上至主管下至開發人員,總有成千上百個看來非常合理的理由,解釋為何自己現階段無法導入單元測試) 不過,這些困難的問題,我們留到 課程 裡面再討論。 我們今天先來看一個簡單的,如何在 .net core 產生測試程式碼覆蓋率的報表。 其實,只有三個動作,第一個,請安裝 .net tool: dotnet tool install -g dotnet-reportgenerator-globaltool 然後 透過 dotnet CLI 跑一次單元測試進行資料蒐集,記得請在 .sln 或 .csproj 所在的目錄下執行: #收集資訊 dotnet test --collect:"XPlat Code Coverage" 請注意上面的 --collect:“XPlat Code Coverage” 參數,是為了蒐集單元測試涵蓋率資訊,執行完畢之後,會出現底下畫面,請特別注意XML檔案所在位置: 因為我們下一個指令需要該位置資訊。 最後,請執行: reportgenerator -reports:"路徑\coverage.cobertura.xml" -targetdir:"report" -reporttypes:Html 嘩啦,單元測試涵蓋率報表出來了(位於report資料夾中,還是HTML格式的),就這樣: 簡單吧~

迭代、敏捷 與 滾動式調整

圖片
今天上課的時候,跟同學聊到,最近很流行的一個詞彙 『滾動式修正』(或 滾動式調整)。 不知道你自己對這個詞的定義是什麼? 所謂的『滾動式調整』是不是走一步算一步? 是不是朝令夕改的美化版? 是不是先做再說,後面再看著辦? 儘管很多人不明所以,但『滾動式調整』這個詞彙這幾年仍被許多團隊理所當然地使用著。為何過去從沒聽過,這幾年卻如此盛行? 我自己覺得,和敏捷(Agile)似乎脫不了關係。 敏捷(Agile)存在的意義,是因為我們認知到並承認, 現今外在環境的變化實在太快了 ,快到我們再也沒法像過去一下,先妥善地做完計畫,然後再動手實行。如果堅持如此,將會錯失先機。 此外,更重要的是,倘若沒有先著手實施,試著得到外界真實的反饋,只在辦公室裡籌算,即便覺得計畫得再周密,一但拿到真實世界裡,很可能就會立刻破功。 這兩者都是同樣的前提 --> 這個世界變化得愈來愈快。 這也是敏捷之所以日趨主流的原因。 而敏捷的被認可,或多或少讓『滾動式修正』變得理所當然。然而,真的每一個組織,每一個單位,每一個計劃,都適合滾動式修正嗎? 今天上課談的是DevOps。 我問學員:『如今需求變化快速已不可避免。假設,持續交付 (所謂的持續交付,一般是指一天數次這樣的頻繁上版,最少也是一周數次,不會更低)是必須的,那什麼是持續交付的基礎?』『一家公司、一個團隊,一個專案,能夠毫無準備的就實施頻繁交付(CD-Continuous Delivery)嗎?』 答案是 : 『不能』。 因為, 沒有良好準備的頻繁交付,將會帶來災難 。 頻繁交付的前題是持續整合(CI-Continuous Integration),持續(密集)到什麼程度? 最好應該是一天數次,至少是一周數次,將程式碼頻繁的簽入並且合併至主線(main)。同時在合併前進行程式碼品質掃描、安全性掃描、單元測試。如果這些都沒做到,那請容我這麼說,目前這個團隊(專案)恐怕還不到可以實施頻繁交付(CD-Continuous Delivery)的程度。 所以,持續交付(或謂 頻繁交付,不過這兩者其實有些許不同)的前提,是良好的基礎建設(這邊指的基礎建設是指 CI - Continuous Integration)。 同樣的,若企業想要執行『滾動式修正』,你的團隊和行政體系必須要有足夠良好的體質,這體質指的是 : 快速...

Azure DevOps in Action - 部署到僅支援FTP的環境

圖片
除了採用Azure WebApp作為網站應用程式的運行環境之外,肯定有更多的開發人員,是採用其他的環境作網站的部署。有可能是主機代管,有可能是其他的雲端服務,也有可是地端環境。 那這些環境該如何進行部署呢? 最簡單的方式是透過FTP。 FTP是絕大部分網站肯定都支援的部署方式,也是傳統手動進行網站部署行為的時候,最常見的選擇。 要在Azure DevOps的pipeline當中進行FTP部署相當容易,你可以透過FTP Upload這個內建的task,即可完成上傳動作: 當你把該task加入job中之後,會看到底下設定: 上圖A的部分,是站台的身分驗證方式,你可以選擇為此站台建立一個connection或是直接輸入身帳號密碼,上圖中,我們選擇直接輸入帳密。 而上圖B、C、D三個欄位則是FTP伺服器的URL以及帳號密碼,這應沒什麽疑義。但需要注意的是上圖E,這個欄位需要輸入的是FTP來源檔案位置,也就是Pipeline當中,先前build好的artifacts所在的位置。這個位置從何而來? 由於目前我們展示的是CI Pipeline,因此該位置你應當參考前面Publish Task的結果: 參考上圖A,Buld好的結果預設的輸出位置使用了系統變數『$(build.artifactstagingdirectory)』,因此,我們在FTP Upload的Task中,Root Folder就是設定為『$(build.artifactstagingdirectory)』: 另外,請特別留意Publish Task中的『Zip published projects』選項,它預設是勾選的,你會發現我們將其取消了。原因是,勾選該項目,會讓publish task將發佈的成品壓縮成.zip檔案,但如此一來我們透過FTP送上站台的時候,反倒不能直接運行了。 因此,原本publish的zip選項必須取消。然後,我們再回頭看FTP Uploader task的Root foder,其設定就是先前Publish task的output位置: 最後,別忘了設定你上傳後這些檔案要放在遠端站台的哪一個路徑(上圖F),這個位置可能因為你選擇(或設定)的Web Server的不同而不同,上圖site/wwwroot是因為我們選用的是azure web app,其預設路徑就是...

自動幫用戶開啟RichMenu與鍵盤or語音輸入

圖片
LINE在2022/5/13增加了postbackAction的屬性,讓發人員可以藉由送出一個含有postbackAction的訊息(類似底下這樣),來幫用戶來開啟(或關閉)rich menu,甚至可以開啟輸入鍵盤和語音: 上圖 A 的部分,是一個 Buttons Template Message,其中有四個按鈕,其類型都是我們先前介紹過的 postbackAction。 在過去,當用戶點下postbackAction按鈕時,只會讓伺服器端的WebHook收到一則訊息,但LINE 2022/5/13 增加了此功能之後,postbackAction多了兩個重要的屬性,分別是inputOption與fillInText。 inputOption可以是底下的值: closeRichMenu : 關閉 rich menu openRichMenu : 開啟 rich menu openKeyboard : 開啟輸入鍵盤 openVoice : 開啟語音輸入 而 fillInText 則是當inputOption為openKeyboard時,開啟的文字輸入鍵盤中的預設文字。 例如,當建立 postbackAction 的程式碼如下: Actions.Add(new isRock.LineBot.PostbackAction() { label = "開鍵盤", data = "openKeyboard", displayText = "開鍵盤", fillInText = "預設文字", inputOption = "openKeyboard" }); 則用戶點選該選單後,結果如下: 當您建立 postbackAction 的程式碼如下: Actions.Add(new isRock.LineBot.PostbackAction() { label = "開選單", data = "openRichMenu", displayText = "開選單", inputOption = "openRichMenu" }); 則...

Azure DevOps 中的 Release Gate

圖片
在使用自動化上版的過程當中,你大概或多或少會想要使用簽核(Approval)的功能。簽核功能讓你可以自動佈署到特定站台(例如正式機)之前,形成一個 “把關” 的功能。 雖然感覺用起來很酷,但坦白說,我們對於上新版程式前的Approval行為,在態度上是不鼓勵的。因為多年下來,並沒有案例顯示,上版前的簽核真能夠減少什麼風險或是降低問題發生的機率。反倒是常常因為Approver卡住流程,造成自動化效率的降低。 如果企業是為了要有人負責,才配置這個Approver,那我們就更不鼓勵了。因為大部分的Approver其實無法在上版前真的做什麼檢查,常常有簽核權限的PM只是回頭問問工程師 : 『可以上正式機了嗎? 可以? 那我就按"同意"了唷』。這樣的橡皮圖章其實讓人很心酸。 事實上,大部分能做該做的檢查,根本早就在(也應該要在)自動化流程中被完成,而非靠人工的檢核。 更好用的機制 - Release Gate 比起Approvals的設定,Release Gate其實是配合自動化部署更好的選擇。 設定的方式類似 Approvals,只需要先將選項設為 Enabled即可啟動(下圖A),接下來就是設定要作為Gate的機制(下圖B): 按下Add之後,你可以選擇要作為Gate的機制: 系統已經內建不少的Gate類型可供選擇,其中比較常用的大概是『Invoke REST API』和『Query work items』。另外『SonarCloud Quality Gate』則是外掛的套件,配合SonarCloud軟體品質掃描用的。 當你設定了Release Gate這個機制,它將會每隔幾分鐘(最少五分鐘)檢查一次你設定的條件,當該條件成立的時候,才會允許Pipeline繼續往下進行。 這個功能可以幫助我們,在自動化的過程中減少不需要的人力介入或簽核,即可自動檢查特定條件是否成立。你也可以撰寫Azure Function,或是使用Invoke REST API方法來呼叫特定API,取得回傳值,以判斷是否可以讓Release Pipeline繼續往下運行。 在高強度(一天數次或一周數次)的頻繁交付過程中,Release Gate比起人工簽核(Approval)更是合作上版前的自動化關卡檢查機制。 來,以後試著放棄橡皮圖章吧。 參考資料...

Azure DevOps in Action - 建立Linux環境的Build Agent

圖片
Azure DevOps也可以輕易地建立在Linux環境上的Build Agent,底下我們將會採用Ubuntu的VM環境來示範這個動作。 首先,我們建議您用Azure上的Ubuntu 20.04虛擬機範本,相關的建立參數如下: 我採用D4s_v3的虛擬機等級,在East Asia資料中心建立該伺服器。同時為了讓我能夠從Windows環境連上該伺服器做後續設定,我選擇了開啟SSH(22) Port。 請牢記你建立時所輸入的帳號密碼。 在虛擬機建立完之後,可以透過PowerShell(我是使用 Windows Terminal)以ssh指令來連上該伺服器,並且輸入密碼: ssh 帳號@IP 例如: 遠端登入成功之後,即可對該伺服器下達指令。 先整理一下我們登入後要做的事情,分別是: 安裝 .net core SDK(為了可以進行 dotnet build) 下載Azure DevOps Agent套件(壓縮檔) 解壓縮套件 安裝套件並進行設定(過程中需用到PAT) 執行Agent 整個動作,可以從Azure DevOps的Orgnization Settings開始: 從Orgnization Settings選單點選Agent Pools,選擇Default(即為Self-Hosted Agent),接著點選New Agent。 在出現的畫面中,請點選Linux,你會看到安裝Linux Build Agent的步驟: 首先,請點選上圖A的部分,複製agent套件的下載位置,在筆者截稿時,該位置為: https://vstsagentpackage.azureedge.net/agent/2.202.1/vsts-agent-linux-x64-2.202.1.tar.gz 接著,請在powershell以ssh連線的ubuntu環境中,下達底下指令: mkdir myagent && cd myagent 這會建立一個myagent資料夾,並且進入該資料夾中。 接著,請執行底下指令,來下載agent: curl -O https://vstsagentpackage.azureedge.net/agent/2.202.1/vsts-agent-linux-x64-2.202.1....