發表文章

Azure DevOps In Action - 設計支援Docker/Container的Pipeline

圖片
近幾年Docker/Container技術相當被業界重視,而微軟的 .net 開發技術也適時的支援了容器化的功能。為了實現容器化, .net 開發技術必須支援跨平台,特別是 asp.net ,這也造就了 .net core的誕生。 因此,現在您不管用何種開發工具,也可以產出能運行在Linux環境上的asp.net應用程式,這同時也表示,asp.net理所當然的也可以支援Linux Container了。 Docker file 要讓asp.net專案產出支援Docker的image非常簡單,你可以在建立asp.net專案的時候,勾選『啟用Docker』,『Docker OS』選擇Linux: 或者,你也可以在一開始沒有啟用Docker支援的專案中,點選滑鼠右鍵,選擇加入→Docker支援: Visual Studio會幫你在專案中建立一個類似底下這樣的Docker File: FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base WORKDIR /app EXPOSE 80 EXPOSE 443 FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build WORKDIR /src COPY ["webapp01.csproj", ""] RUN dotnet restore "./webapp01.csproj" COPY . . WORKDIR "/src/." RUN dotnet build "webapp01.csproj" -c Release -o /app/build FROM build AS publish RUN dotnet publish "webapp01.csproj" -c Release -o /app/publish FROM base AS final WORKDIR /app COPY --from=publish /app/publish . ENTRYPOINT ["dotnet", "webapp01.dll...

Azure DevOps in Action - 在CI Pipeline中發佈NuGet套件

圖片
我們在前面的章節曾經介紹過,軟體重用性提升一個很大的要素就是套件化。時至今日,不管你用哪一種軟體開發語言,大概都離不開各式各樣的套件庫。 因此,我們在前面談到Azure Repos的章節中,曾經約略介紹過如何建立套件,也介紹過利用Azure DevOps的Artifacts功能來建立的私有(Private)套件庫: 你大概已經知道,我們可以將組件(.dll)封裝成具有版號的套件,以便於分享給團隊甚至網際網路上所有開發人員來使用。只是先前,我們封裝好的套件(.unpkg)都是以手動方式上傳到 nuget.org ,我們接著來看看,如何自動化完成這件事情。 設計自動發佈套件的Pipeline 一個自動化建置出NuGet套件並且上傳的CI Pipeline並不難設計,就建立 .net core的套件而言,你可以直接使用 ASP.NET Core的範本來修改即可: 接著將範本中的Publish改為(Pack): 因為套件本身不是網頁,因此沒必要『Publish』出什麼,倒是需要產生出 .unpkg檔案,因此我們需要執行dotnet的Pack command。 然而光Pack還不夠,你還得上傳到 nuget.org ,這部分則可以透過 NuGet push task(下圖B)來完成: 上圖中的NuGet push task,其實是在運行NuGet的push command(上圖D),該task會在預設(上圖E)的位置嘗試尋找我們先前透過 Pack Nuget命令所建置出的 .nupkg 檔案,然後將其上傳發送到指定的套件庫。 因此,我們需要進行上傳位置的設定。 第一次連線時你必須點選(上圖F)右方的『+New』按鈕,接著會出現底下畫面: 在出現的畫面中,我們必須輸入ApiKey(上圖C)以便於具有連線到NuGet的權限,後續可以讓Pipeline把套件檔案上傳到Nuget。 一般來說,公開的NuGet套件庫位於: https://api.nuget.org/v3/index.json 如同先前介紹過的,你只需要有Microsoft Account即可登入並且上傳套件。請先用你的Microsoft Account登入nuget.org : 登入後你會發現右上角的頭像圖示選單中,就有一個API Keys選項,透過該選項,你就可以取得一組...

頻繁交付已不是問題,真正的挑戰在於品質

圖片
上面這張圖,是我在講 Azure DevOps 的時候,時常跟學員分享的Pipeline,裡面粗略的談到了CI/CD Pipeline及其前段(版控)與後段(持續監控)所涉及的相關技術,可以讓對於DevOps完全沒概念的學員得以稍微一窺究竟。 但每當我繼續問學員:『你現在知道有這些內容了,那…CI/CD的目的到底是什麼? 實現CI/CD對於企業來說究竟有何好處呢? 』學員突然被問到,有時一下子會無法立刻反應過來。 我繼續說到:『倘若,CI Pipeline的主要目的是為了實現持續整合,而實現持續整合的主要目的則是為了持續交付。那…為何需要頻繁交付呢?』 過去一年,你一定有上網預約疫苗的經驗,如果沒有,你大概也有上網登記五倍券還是某種OO券的經驗,再沒有,你疫情期間總有過上網購物吧。 倘若,你上網登記或購物時,網站突然有問題,或是購物車的金額計算不太正確,你通知了網站營運單位,他們也告知您會立刻著手處理,這時候的你,會希望網站多久可以更新或修復? 一小時? 一天? 還是一兩個月? 同學幾乎都跟我說:『立刻,不然我就換一家網站購物囉~』。 是啊,立刻。 既然我們都這麼要求其他人,那我們自己所建立起來的網站呢? 能不能經得起這樣的要求? 當我們的網站有問題,或是客戶提出新的需求時,我們能夠多快的將新功能或修正交付到用戶手上? 而且你知道的,緊急狀況下,往往兵荒馬亂,即便你知道程式碼在某個地方可能有錯,但這段程式碼最初不是你寫的,你敢立刻改嗎? 你怎麼知道不會改了這邊,就壞了另一邊? 你怎麼知道這個修正會不會引起其他額外的副作用? 有些時候,程式碼明明在你的電腦上是好的,但整合了團隊中其他人開發的程式碼之後,佈署到測試機上,就是無法運行,怎麼回事呢!? 就算開發人員真的把所有問題都在測試機上改好了,是不是還要經過QA的人工測試把關才能交付給客戶呢? 但測試需要時間啊,如何才能實現『立刻』將成品交付給客戶? 上面這些,都是CI/CD想幫助你解決的問題。 持續交付,聽來很容易。也確實,因為技術的進步,現在要快速的把更新後的成品佈署到正式機上讓用戶使用,也許真的也不難。但你有把握在『快速』的同時,還能保有高品質與安全性嗎? 你有勇氣讓開發人員把程式碼修改完之後,透過Pipeline『全自動』的直接上版到正式機上嗎? 從你收到bugs或需求,一直到交付到...

Azure Cognitive Services - Speech to Text Demo 語音轉文字功能

圖片
昨天,在 .net conf 2021,明明講的主題是框架設計的延續 - 套件設計,但其中六七個demo當中,大家看起來最有反應和效果的反而是底下這個語音轉文字的CLI Demo。 影片: 這是一個透過CLI呼叫的語音辨識的服務,挺有趣吧,我只是把它變成command line tools, 也就是CLI工具,這個demo只是一個我想做的語音助理的一半,後半段沒demo出來的是一個語音助理的雛型,也就是透過語言來控制電腦。(還需要整合LUIS以及掛上特定 intent 的 actions) 若想要用語音來控制電腦,第一步當然是辨識語音,你可能沒想到過,現在即便 command line, console app也可以辨識語音(Speech to Text)。 拜 azure cognitive 所賜,如今這已經是簡單到不行的技術。主要的程式碼只有底下這幾行: async static Task FromMic(SpeechConfig speechConfig) { using var audioConfig = AudioConfig.FromDefaultMicrophoneInput(); using var recognizer = new SpeechRecognizer(speechConfig, "zh-tw", audioConfig); Console.WriteLine("嗨~ 請透過語音下達指令..."); var result = await recognizer.RecognizeOnceAsync(); Console.WriteLine($"語音命令 = '{result.Text}' "); } 我把整套 CLI tools的source code放 github上了: https://github.com/isdaviddong/demo-listenup-VoiceCommand 當然你得自己換掉 Namespace 與 Azure Cognitive Services 的key。 如果要申請 Azure Cognitive Services 的 語音轉文字服務,可以參考: https://portal.azure.com...

設定 unit test的code coverage report

圖片
在預設的 Azure DevOps Pipeline範本當中,針對 .net core的專案,你可以透過 dotnet task來運行單元測試,使用的指令是 dotnet test。底下是Yaml code, 這是一個很標準的做法: steps: - task: DotNetCoreCLI@2 displayName: Test inputs: command: test projects: '$(Parameters.TestProjects)' arguments: '--configuration $(BuildConfiguration)' 但使用預設的dotnet rest,並不會產生code coverage報表,雖然我們並沒有想追求很高的unit test code coverage,但出一下報表對我們來說還是很具有參考價值的。 如果你也想要檢視code coverage報表,可以做底下調整。 step 1: 修改 dotnet test task steps: - task: DotNetCoreCLI@2 displayName: Test inputs: command: test projects: '$(Parameters.TestProjects)' arguments: '--configuration $(BuildConfiguration) --collect:"XPlat Code Coverage" -- DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format=cobertura' 你會發現在參數的地方,我們加上了 --collect 等敍述,主要是告知 dotnet task運行test的時候,要蒐集相關資訊。 step 2: 增加Publish code coverage results task steps: - task: PublishCodeCoverageResults@1 displayName: 'Publish code coverage...

敏捷,其實很簡單

圖片
DevOpsDays 2021的會場,有個活動叫專家面對面好像(具體叫啥我忘了),主要是讓與會者能夠和現場講師有更多互動。當天分享結束後,主辦單位請我去那坐一下(我當然也從善如流的照做了),正當我回答完幾位學員的問題,準備離開的時候,有一位年紀比我稍長的先生坐了下來,有條不紊的介紹完自己的團隊與專案後,開口問了幾個問題。 其中,有一個很關鍵,大概是這樣的內容:『如果團隊手上非常多插單的情況,導致每個迭代都無法正常進行,這樣適合 run scrum嗎?』根據多年的經驗,這個問題肯定只是表象,背後一定有著其他沒說出來的狀況。 我想了想,反問他:『你們的迭代設定多長?』 『一周或兩周,每個團隊有點不同』他回答。 我疑惑的問:『所以用戶的需求等不及一周的時間? 非得立刻插單不可?』『因為都是一些非常嚴重bug,不立刻處理不行』他說 『那你們真正該面對的不是插單的問題,而是整個專案已經快失控了,這樣等於每天都在救火啊?』我看著他。 他有點不好意思的說:『的確是這樣的。』 『那我的建議會是…』我認真的回答他道:『你們應該停止任何新功能的開發,先把所有的bugs解決,然後找出系統架構上或開發上的核心問題,到底~是什麼原因導致系統bugs層出不窮? 先著手解決它,別讓團隊陷在持續救火的處境裡…』 如果團隊每天都必須救火,那不管你 run 什麼方法都是對專案沒有幫助的,敏捷或scrum的導入不會立刻改變團隊的體質,如果大家的習慣不改變,團隊面對的困境還是會持續僵在那裏。 『但是,如果不開發新功能,這樣專案就不會有進度了啊?』他似乎有些擔憂這個。 如果你不停止開發新功能,去面對團隊本該處理的核心問題,這樣你看到新功能的進度,也只是個假象,終有一天,層出不窮的bugs會在專案的後期吃掉你所有的進展,最終,你會無法交出任何一個功能給客戶。 『恩,我知道』他面有難色地回答。說完謝謝之後,就皺著眉頭離開了。 我知道他心裡的考量和難處。 回到根本,敏捷其實很簡單–就是務實的面對問題,努力交付出用戶真正可以用的軟體。但,在這世上,總是有很多事情,特別是技術面以外的事情,並非那麼的務實。有時候我們的思慮,可能還包含了人情、績效、政治…等等各種其他方面的考量。這時候,問題就被我們搞複雜了。 就如同我在DevOpsDays中說的,敏捷一直都很簡單,但讓一切複雜的,是人。如果...

Azure DevOps in Action - 實現PR觸發的CI自動化建置

圖片
在上Azure DevOps課程的時候,學員問了一個很好的問題。 如果我們採用 Feature Branch,那你會走一個底下這樣的團隊合作流程: 上圖中有一個很重要的部分是,在PR之後所觸發的自動化佈署。 也就是,在feature branch分支被commit/push準備合併到主線前,我們會透過PR進行code review和discussion,過程中當然應該要先針對分支進行build才對呀。如果 build fail 了,那或許根本沒啥好討論了,整個PR直接給個comment然後reject掉就得了。 所以,分支(特別是feature branch)在走PR合併回主線前,針對分支的auto build非常重要,但,這要如何實現? 在Azure DevOps中,是透過 branch policy來實現的: 你只需要設定特定分支(例如master)的branch policy,把開關打開,設定任何從只分支建立出的分支(像是feature branch),PR後都會觸發個定的build pipeline就行了。 如此一來,圖中PR就會自動觸發該分支的build,這樣,我們的repo owner或是reviewer就可以在code review之前,看看build是否成功: 當然,在build pipeline中,我們也可以先做像是 SonarCloud / Checkmarx 之類的程式碼掃描,如此一來,整個團隊的開發協同運作流程,就更加迷人了。 相關課程: 敏捷開發專案管理與Azure DevOps實戰 https://www.studyhost.tw/NewCourses/ALM

+壓力-身段×堅強÷任性

圖片
#一起看廣告 昨天晚上,做了個夢。 我夢到在駕駛座上睡著了,然後被後座的其他乘客叫醒,乘客急急忙忙地跟我說:『ㄟㄟ,David,你睡著了啦!! 車還在開耶…』 我回答:『對耶,啊…有自動駕駛啦…』 然後我就繼續睡了… 早上起床突然想到,跟老婆說。 她說:『好啦,收到,我知道你有多想買自動駕駛的車了…』 古人說:『日有所思,夜有所夢。』可能真的是因為,這陣子看了好多汽車廣告。 最近看到 Ford 的廣告拍得很好,分別是林依晨的 New Focus (很值得看) 還有先前張鈞甯的 KUGA: (超好看) 後來又補一個: 上面這兩個廣告我都超推,不看你會後悔。但某天,我看著看著,卻讓我回憶起十多年前的這一支廣告。總覺得 Ford 的車怎麼樣我不知道(沒開過),但廣告總是拍得很有意境: +壓力-身段×堅強÷任性 換算之後,你是否還記得真實的自己? 當初看上面這則廣告時,自己還是個帶著無限衝勁,剛站穩在職場上的少年。 但,這十幾年(也才十幾年),很多事情都改變了。環境變了,世界也變了。傲氣收斂成淡淡的執著,衝動則被多慮的思緒給撫平了。 年輕人總是想『做自己』(相信我,這並非時下青年的特色,每一個世代都是)。但,到了最近這個年紀,才發現,原來做自己之前,還得先找到自己。很顯然的,年輕時不顧後果地去凸顯自己的任性,並不是做自己。 當你找到並認識自己是誰,明白自己的能力和限制,還能無畏著外界的眼光,放下纏累自己的包袱,不跟他人比較、不被世俗的成功定義,還有勇氣和餘力踏上自己想走的路。持續走下去…這樣,才是做自己。 『做自己』要的不單單只是一股衝勁,而是認真的認識並面對自己的個性和缺點、堅持著持續超越和挑戰自己的毅力。

Azure WVD-讓你在瀏覽器中執行 Windows 10

圖片
如何在瀏覽器中執行 Windows? 要談這件事情前,我們得說說為何會有這個需要? 雖然對我而言,這個需求是顯而易見的。 虛擬桌面的美好想像 過去在企業環境中,使用vmware或hyper-v搭建一整套給用戶的虛擬工作環境,或是採用RDP以multi-session的形式提供用戶透過遠端連入的工作環境,都是企業內很常見的使用方式。 這樣做帶來幾個好處: 用戶端的實體設備等級不用太高,因為大量工作實際上都運行在遠端機房。 安全性容易控制,因為實際運行的程式大多也都在機房。 MIS/IT人員不再需要為每一台用戶端設備傷腦筋。用戶端隨便用任何一台設備,登入遠端虛擬桌面後,都可以立即讓同仁開始工作。 同仁即便在遠端(家裡、網咖)、拿自己的NB也可以隨時連入工作(WFH居家辦公一次搞定) … 隨手都能舉出好幾個理由,讓大部分MIT/IT人員對於遠端虛擬桌面有許多美好想像(包含我在內)。 自從有了Azure雲端之後,事實上我的桌機或NB的硬體更新頻率越來越低,因為大部分我工作都直接透過RDP用雲端上的VM來進行。這樣有許多好處。包含,有需要時隨手可以把VM升級成16或32G的記憶體,硬碟空間更是要多大有多大,只要網路速度可以,在遠端VM上工作比local實體機效率來的高上不少,算是一個頗奢侈豪華的享受。 對我個人來說,這樣做也有另一個好處,方便我把工作和個人電腦分開,工作我一律用雲端VM,個人NB則大多做些教育訓練或私人的事情,工作時只需要從NB連上雲端VM即可,環境乾淨不容易混亂或衝突。 需要克服的缺點 然而,使用RDP從NB連上雲端windows 10的VM,對很多人來說已經很美好,但我覺得還是有些缺點。當我想要大範圍的導入時,會碰到一些障礙: RDP採用3389 port,常常在企業內有被擋掉的可能。 RDP在MAC環境可以用,但在android和iOS上還是有不少限制。在Windows環境上用戶也需要一點基本概念,才能夠使用。 用戶端的RDP上會保留有連線位置等資訊,在網咖或是外部環境使用相對風險比較高。 Azure WVD解決方案 因此,當我聽到Azure上的WVD解決方案時,實在非常心動。比起單純的RDP和雲端VM(或是地端的hyper-v, vmware),它有底下好處: 用戶端只需要有瀏覽器(Chrome/Edg...

周末讀書會:時間真的等於金錢???

圖片
我正在讀一本奇書,裡面有個觀念頗有意思。但在分享之前,我先問你一個問題… 你覺得…過去一年,哪一段時間你的生產力最高? 那段時間會不會正好是你最忙的時候? 其實並不一定,對不對? 也就是說,你可能很忙,但完全沒產出甚麼有價值的成果(俗話說是「瞎忙」),也可能實際工時很少,但成果豐碩(特別是創作者)。 書中有一個章節告訴我們,如果想提高生產力,你必須減少工作時數(注意,不是增加)。作者覺得,傳統的時間管理很有問題,因為工作時數不等於生產力。這部分你可能跟我一樣,我始終覺得,企業用工時來計算薪資(或是專案成本)是件很奇怪的事情。老闆想要(買)的到底是"成果"? 還是想要 “看到我在辦公室出現”? 這是大家都知道的道理,但如今這個持續了那麼久,讓我們覺得不可思議的薪資和成本設計,是過去一百年來延續出的結果(這邊我要提到另一本過去介紹過的書『組織再進化』,有空可以自己去看看)。你知道,過去(工業革命時代),“時間就是金錢”,那時候生產線林立,勞工的上班時間就100%等於產出時間,下了班離開了工廠、沒了生產設備就什麼事都不能做(也就是沒有產出)。 因此,在那個時代,工時=薪資(或成本)是很有道理的。但,這已經是將近一百年前的事情了,想想好玩,如今我們的勞基法的基本精神卻還是基於那個年代? 而今天,對我們(特別是開發、創作人員來說),工時跟生產力之間根本沒有必然的關係。你一定有這種經驗,有時候你靈思泉湧、創作如同神來之筆,半小時內可以完成平時三四倍的工作量。而另一些時間,你可能沒睡飽或因為私事思緒混亂,這時就算在辦公室待上一整天也做不完任何一件事情。 所以這本書的作者認為,“時間” 根本並不重要,專注力與精力才是重點。(好啦,他其實沒這麼說,他覺得時間也很重要,但不是唯一重要) 同時,他還做了一個有趣的實驗,實驗結果顯示,當工時加倍,其實最終的有效工作產出只比工時減半時增加了 “一點點”。但有趣的部份是,當事人總會 “以為” 自己的產出很高(因為感覺自己很忙),但統計之後則是發現 “根本沒有”。 我覺得這也解釋了,為何辦公室中許多主管很喜歡一直開會,因為開會會讓自己主觀上覺得一直很忙、一直有產出,但其實…你知道的,根本沒有。 所以,總的來說。 工時越長,並不代表工作成果(或產出)會越好 傳統時間管理很有問題,因為重要的(你想要的...