<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>2021ironman 彙整 - 泰克哪裡去</title>
	<atom:link href="https://tech.uccu.website/tag/2021ironman/feed" rel="self" type="application/rss+xml" />
	<link>https://tech.uccu.website/tag/2021ironman</link>
	<description>一個科技相關的隨手記錄網站</description>
	<lastBuildDate>Sat, 17 Sep 2022 20:45:57 +0000</lastBuildDate>
	<language>zh-TW</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.8.1</generator>
<site xmlns="com-wordpress:feed-additions:1">119574712</site>	<item>
		<title>【2021鐵人賽】2021iThome鐵人賽結尾</title>
		<link>https://tech.uccu.website/2021ironman-day30-the-end.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=2021ironman-day30-the-end</link>
					<comments>https://tech.uccu.website/2021ironman-day30-the-end.html#respond</comments>
		
		<dc:creator><![CDATA[鳴人]]></dc:creator>
		<pubDate>Tue, 12 Oct 2021 14:07:28 +0000</pubDate>
				<category><![CDATA[2021鐵人賽]]></category>
		<category><![CDATA[iThome鐵人賽]]></category>
		<category><![CDATA[未分類]]></category>
		<category><![CDATA[2021ironman]]></category>
		<guid isPermaLink="false">https://tech.uccu.website/?p=1555</guid>

					<description><![CDATA[<p>終於來到了鐵人賽的最後一天，按照慣例在最後一天的文章是用來結尾的，所以並沒有任何的技術含量，只是聊聊這次鐵人賽的心得感想，也代表今年的連續30天不中斷發文挑戰完成。上次參加鐵人賽完賽好像有送T恤一件，今年不知道會有什麼東西？或許下個月有結果之後再來更新這篇文章吧！</p>
<p>這篇文章 <a href="https://tech.uccu.website/2021ironman-day30-the-end.html">【2021鐵人賽】2021iThome鐵人賽結尾</a> 最早出現於 <a href="https://tech.uccu.website">泰克哪裡去</a>。</p>
]]></description>
										<content:encoded><![CDATA[
<p>終於來到了鐵人賽的最後一天，按照慣例在最後一天的文章是用來結尾的，所以並沒有任何的技術含量，只是聊聊這次鐵人賽的心得感想，也代表今年的連續30天不中斷發文挑戰完成。</p>



<p>今年參加鐵人賽的文章連結都有放在<a href="https://tech.uccu.website/2021ironman" target="_blank" rel="noreferrer noopener">這個頁面</a>，算是一個文章目錄吧！裡面寫到了上次參加鐵人賽完賽的那次距離現在已經隔了八年，今年在一家尚未在台灣成立分公司的港商工作，所以在台灣辦公室這邊找了同一個團隊的同事與香港那邊起初有意願參加的同事加上我共三個人組成了一個團隊。</p>



<p>我今年參賽的文章主題就以Azure DevOps為主軸，將我在目前公司使用到的功能透過這30天不中斷的發文寫出來。當然，文章的內容不可能用目前工作上的東西來寫，所以需要重新思考一下怎麼樣用比較簡單的方式把功能和操作帶出來，沒有在公司用到的功能就先略過不寫，和Azure DevOps無關的也略過，不然寫文章的時間可能不夠…</p>



<p>其實今年以這個主題報名參加iThome的鐵人賽，說實在的並不是為了寫這些文章有其他人會看，而且有很多內容應該有不少地方寫得不錯，所以今年除了要挑戰30天不中斷的發表文章之外，另外一個目的就是把它當作是交接文件來寫。</p>



<p>今年鐵人賽的文章在這一篇之前應該都是和發表在iThome完全相同的內容，唯獨這篇文章的內容可能是兩邊不一樣。</p>



<p>除此之外，iThome那邊的文章發表是為了參加鐵人賽的30天發文不中斷，但是在這個部落格並不會中斷發文，只是不會像參賽一樣維持每天都發文的頻率，後續仍然會視情況將使用Azure DevOps的心得寫上來，只是不會將後續的文章繼續更新連結在「<a href="https://tech.uccu.website/2021ironman" target="_blank" rel="noreferrer noopener">iThome鐵人賽</a>」這個頁面。</p>



<p>不得不說，不管是先前參賽的時候或是這次參賽的過程，總是會碰到趕著寫文章的情況，所以其實從幾個文章內容中應該可以很明顯看得出來哪些是有比較花時間寫得比較多的內容，而哪些則是為了趕在發文時間截止之前儘快生出來的文章。</p>



<p>今年的鐵人賽除了個人參賽項目之外，因為和另外兩個同事一起組了團隊，所以也有團隊參賽的目標，最起碼不能另外兩個同事還沒有Game Over之前我就自己先挑戰失敗，所以再怎麼樣也要完成這個30天的挑戰。</p>



<p>只是沒想到團隊進度進行到三分之一的時候，香港的同事就已經放棄了。在那前兩天，他還提到寫了文章好像都沒什麼人在看，再加上可能公司有些事情他也很忙，所以最後在第10天的時候中斷了發文，放棄了挑戰，因此團隊項目最終是失敗的。反倒是台灣的這個新人同事堅持到了最後一天，完成了挑戰，著實應該給予鼓勵。</p>



<p>最終，也希望藉著參加這個30天不中斷發文的挑戰，帶動起自己寫文章的習慣，不然有時候真的是惰性大於一切，偏偏很多東西不記錄下來又不會時常用到，久了就容易忘記，所以花點時間寫文章也算是一種學習的筆記了。只是…這次又可以持續多久呢？</p>



<p>對了，上次參加鐵人賽完賽好像有送T恤一件(我的那件衣服應該只是因為完賽而得到的吧?)，今年不知道會有什麼東西？或許下個月有結果之後再來更新這篇文章吧！</p>
<p>這篇文章 <a href="https://tech.uccu.website/2021ironman-day30-the-end.html">【2021鐵人賽】2021iThome鐵人賽結尾</a> 最早出現於 <a href="https://tech.uccu.website">泰克哪裡去</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://tech.uccu.website/2021ironman-day30-the-end.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1555</post-id>	</item>
		<item>
		<title>【2021鐵人賽】再次建立Release pipeline：多個不同Artifacts來源</title>
		<link>https://tech.uccu.website/2021ironman-day29-create-new-release-pipeline-with-multiple-artifacts.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=2021ironman-day29-create-new-release-pipeline-with-multiple-artifacts</link>
					<comments>https://tech.uccu.website/2021ironman-day29-create-new-release-pipeline-with-multiple-artifacts.html#respond</comments>
		
		<dc:creator><![CDATA[鳴人]]></dc:creator>
		<pubDate>Mon, 11 Oct 2021 15:48:34 +0000</pubDate>
				<category><![CDATA[2021鐵人賽]]></category>
		<category><![CDATA[Azure DevOps]]></category>
		<category><![CDATA[iThome鐵人賽]]></category>
		<category><![CDATA[資訊科技]]></category>
		<category><![CDATA[2021ironman]]></category>
		<category><![CDATA[azure devops]]></category>
		<guid isPermaLink="false">https://tech.uccu.website/?p=1546</guid>

					<description><![CDATA[<p>前面的文章建立過了Release pipeline，但是那次並沒有加入多個不同的Artifacts來源，不過在前一篇文章中我們修改了Pipeline的識別文字格式，正好這篇就來再建立一個Release pipeline，同時加入不同的Artifact來源吧！</p>
<p>這篇文章 <a href="https://tech.uccu.website/2021ironman-day29-create-new-release-pipeline-with-multiple-artifacts.html">【2021鐵人賽】再次建立Release pipeline：多個不同Artifacts來源</a> 最早出現於 <a href="https://tech.uccu.website">泰克哪裡去</a>。</p>
]]></description>
										<content:encoded><![CDATA[
<p><a href="https://tech.uccu.website/2021ironman-day23-quick-create-new-release-pipeline.html" target="_blank" rel="noreferrer noopener">前面的文章</a>建立過了Release pipeline，但是那次並沒有加入多個不同的Artifacts來源，不過在<a href="https://tech.uccu.website/2021ironman-day28-change-build-number-and-release-name-format.html" target="_blank" rel="noreferrer noopener">前一篇文章</a>中我們修改了Pipeline的識別文字格式，正好這篇就來再建立一個Release pipeline，同時加入不同的Artifact來源吧！</p>



<p>有些前面的步驟在先前的文章就提過了，所以就直接略過，直接看關鍵截圖吧！</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" fetchpriority="high" decoding="async" width="615" height="807" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/d267a082-newrelease-multipleartifacts-reposource.png?resize=615%2C807&#038;ssl=1" alt="" class="wp-image-1561" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/d267a082-newrelease-multipleartifacts-reposource.png?w=615&amp;ssl=1 615w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/d267a082-newrelease-multipleartifacts-reposource.png?resize=229%2C300&amp;ssl=1 229w" sizes="(max-width: 615px) 100vw, 615px" /></figure></div>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" decoding="async" width="624" height="675" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/7ccdf698-newrelease-multipleartifacts-frompipeline-buildconsoleapp.png?resize=624%2C675&#038;ssl=1" alt="" class="wp-image-1564" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/7ccdf698-newrelease-multipleartifacts-frompipeline-buildconsoleapp.png?w=624&amp;ssl=1 624w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/7ccdf698-newrelease-multipleartifacts-frompipeline-buildconsoleapp.png?resize=277%2C300&amp;ssl=1 277w" sizes="(max-width: 624px) 100vw, 624px" /></figure></div>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" decoding="async" width="624" height="691" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/64803961-newrelease-multipleartifacts-frompipeline-buildspecifiedproject.png?resize=624%2C691&#038;ssl=1" alt="" class="wp-image-1567" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/64803961-newrelease-multipleartifacts-frompipeline-buildspecifiedproject.png?w=624&amp;ssl=1 624w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/64803961-newrelease-multipleartifacts-frompipeline-buildspecifiedproject.png?resize=271%2C300&amp;ssl=1 271w" sizes="(max-width: 624px) 100vw, 624px" /></figure></div>



<p>從上面的三張截圖中可以看到加入了三個Artifact，分別是Git Repo，裡面放著Dockerfile檔案，建立Docker image的時候會用到；第二個則是從BuildConsoleApp這個Build pipeline取得最新版本的Artifacts；第三個則是從BuildSpecifiedProject這個Build pipeline中取得Artifacts。第二個是直接從最新版本取得，第三個則是讓使用者在建立Release的時候手動從清單中選擇。Build pipeline中取得Artifact的部份必須要在Pipeline中有將檔案上傳到Pipeline的Artifacts，前面文章都有提過喔！</p>



<p>接著來看看Release中的Task內容：</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="388" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/e0310dc7-newrelease-multipleartifacts-task1-1024x388.png?resize=1024%2C388&#038;ssl=1" alt="" class="wp-image-1570" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/e0310dc7-newrelease-multipleartifacts-task1.png?resize=1024%2C388&amp;ssl=1 1024w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/e0310dc7-newrelease-multipleartifacts-task1.png?resize=300%2C114&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/e0310dc7-newrelease-multipleartifacts-task1.png?resize=768%2C291&amp;ssl=1 768w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/e0310dc7-newrelease-multipleartifacts-task1.png?w=1187&amp;ssl=1 1187w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure></div>



<div class="wp-block-image"><figure class="aligncenter size-large"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="395" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/6826836e-newrelease-multipleartifacts-task2-1024x395.png?resize=1024%2C395&#038;ssl=1" alt="" class="wp-image-1573" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/6826836e-newrelease-multipleartifacts-task2.png?resize=1024%2C395&amp;ssl=1 1024w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/6826836e-newrelease-multipleartifacts-task2.png?resize=300%2C116&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/6826836e-newrelease-multipleartifacts-task2.png?resize=768%2C296&amp;ssl=1 768w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/6826836e-newrelease-multipleartifacts-task2.png?w=1197&amp;ssl=1 1197w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure></div>



<p>從上面的兩張截圖可以看到內容很簡單，第一張的關鍵在於紅線的地方，也就是前面加入Artifacts的時候設定的名稱，在第二行與第三行後面的BuildOutputFiles這個名稱則是Build pipeline中我們上傳到Artifacts的時候取得資料夾名稱。</p>



<p>第二張截圖則是利用bash來執行docker build的指令，因為在這個Release的Agent部份我指定了使用Self-hosted的Agent，也就是前面文章提到的LinuxContainerAgent(因為Azure試用過期了…)，所以等於在Agent裡面執行透過Bash來執行docker指令，這部份就要確定Agent裡面有安裝才行。</p>



<p>最後是在建立Release的時候，可以從下圖看到在Module的部份就可以讓使用者自行選擇要挑選哪一個版本來作為這個Release的檔案了：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="611" height="819" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/865dd488-newrelease-multipleartifacts-selectartifactsversion.png?resize=611%2C819&#038;ssl=1" alt="" class="wp-image-1576" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/865dd488-newrelease-multipleartifacts-selectartifactsversion.png?w=611&amp;ssl=1 611w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/865dd488-newrelease-multipleartifacts-selectartifactsversion.png?resize=224%2C300&amp;ssl=1 224w" sizes="auto, (max-width: 611px) 100vw, 611px" /></figure></div>



<p>這樣在非全自動的情境下，就可以暫時不需要建立太多的Pipeline，尤其是Module很多的時候，每一個都要建立一個Pipeline的話數量也是不少呢！</p>
<p>這篇文章 <a href="https://tech.uccu.website/2021ironman-day29-create-new-release-pipeline-with-multiple-artifacts.html">【2021鐵人賽】再次建立Release pipeline：多個不同Artifacts來源</a> 最早出現於 <a href="https://tech.uccu.website">泰克哪裡去</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://tech.uccu.website/2021ironman-day29-create-new-release-pipeline-with-multiple-artifacts.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1546</post-id>	</item>
		<item>
		<title>【2021鐵人賽】設定Pipeline的識別文字格式</title>
		<link>https://tech.uccu.website/2021ironman-day28-change-build-number-and-release-name-format.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=2021ironman-day28-change-build-number-and-release-name-format</link>
					<comments>https://tech.uccu.website/2021ironman-day28-change-build-number-and-release-name-format.html#respond</comments>
		
		<dc:creator><![CDATA[鳴人]]></dc:creator>
		<pubDate>Sun, 10 Oct 2021 09:50:20 +0000</pubDate>
				<category><![CDATA[2021鐵人賽]]></category>
		<category><![CDATA[Azure DevOps]]></category>
		<category><![CDATA[iThome鐵人賽]]></category>
		<category><![CDATA[資訊科技]]></category>
		<category><![CDATA[2021ironman]]></category>
		<category><![CDATA[azure devops]]></category>
		<guid isPermaLink="false">https://tech.uccu.website/?p=1510</guid>

					<description><![CDATA[<p>Build pipeline與Release pipeline預設的識別格式預設以日期加上序號或是名稱加上序號的格式儲存，像是20211010.1、Release-1這樣的識別文字，其實這個識別文字的格式是可以設定的，改成更容易識別的格式的作法是…</p>
<p>這篇文章 <a href="https://tech.uccu.website/2021ironman-day28-change-build-number-and-release-name-format.html">【2021鐵人賽】設定Pipeline的識別文字格式</a> 最早出現於 <a href="https://tech.uccu.website">泰克哪裡去</a>。</p>
]]></description>
										<content:encoded><![CDATA[
<p>不知道各位在前面建立Pipeline執行之後，有沒有發現Pipeline執行結果列表的識別文字是像下圖的格式？</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="439" height="262" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/61abebe0-pipelineruns-buildnumberformat1.png?resize=439%2C262&#038;ssl=1" alt="" class="wp-image-1513" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/61abebe0-pipelineruns-buildnumberformat1.png?w=439&amp;ssl=1 439w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/61abebe0-pipelineruns-buildnumberformat1.png?resize=300%2C179&amp;ssl=1 300w" sizes="auto, (max-width: 439px) 100vw, 439px" /><figcaption>Build pipeline修改識別文字前</figcaption></figure></div>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="244" height="137" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/0c3071b6-releasepipeline-releasenameformat1.png?resize=244%2C137&#038;ssl=1" alt="" class="wp-image-1516"/><figcaption>Release pipeline修改識別文字前</figcaption></figure></div>



<p>如上圖的兩張截圖，不是以日期加序號的方式呈現，就是名稱加上序號，這種識別方式在Pipeline多的情況下其實會有些困擾，如果又是像前面文章「<a href="https://tech.uccu.website/2021ironman-day10-create-a-common-use-build-pipeline.html" target="_blank" rel="noreferrer noopener">CI/CD從這裡：第2個Pipeline，建立共用的Build Pipeline</a>」這種方式建立了共用的Build Pipeline，可以透過執行時輸入變數值的方式來讓Pipeline產生不同的結果時，這時候在識別上就會產生很大的問題，不知道哪一次的執行結果是做了些什麼。</p>



<p>不過這個識別編號的格式其實是可以修改的，下面幾張截圖是修改後的範例：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="409" height="194" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/0d6ca168-pipelineruns-buildnumberformat2.png?resize=409%2C194&#038;ssl=1" alt="" class="wp-image-1519" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/0d6ca168-pipelineruns-buildnumberformat2.png?w=409&amp;ssl=1 409w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/0d6ca168-pipelineruns-buildnumberformat2.png?resize=300%2C142&amp;ssl=1 300w" sizes="auto, (max-width: 409px) 100vw, 409px" /><figcaption>Build pipeline修改識別文字後</figcaption></figure></div>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="247" height="55" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/d286b418-releasepipeline-releasenameformat2.png?resize=247%2C55&#038;ssl=1" alt="" class="wp-image-1522"/><figcaption>Release pipeline修改識別文字後</figcaption></figure></div>



<p>上面第一張截圖就是共用的Build Pipeline修改後的結果，分別執行了三個不同專案的建置，並且從識別文字中可以看得出來是使用master這個Branch的原始碼來建置的，後面再加上日期和序號，這樣就可以知道哪一次執行是做了什麼動作。</p>



<p>第二張截圖則是Release Pipeline修改後的結果，從原本的Release-1、Release-2的格式內容，修改成了DevOpsAgent-20211010.1，從這樣的識別文字就可以直接知道是哪一個Release pipeline的執行結果，並且是哪個日期執行的，比起Release-1、Release-2這樣的內容看起來要好得多了。</p>



<p>下面就來看看要如何修改Pipeline的識別文字吧！</p>



<p>首先是Build pipeline的部份，因為分成兩種編輯模式(傳統編輯器與YAML)，所以修改的方式不太相同，傳統編輯器的修改方式是透過Options頁籤之下的Build number format的欄位進行修改，點擊旁邊的i符號會有提示說明與官網的文件連結(<a href="https://docs.microsoft.com/zh-tw/azure/devops/pipelines/process/run-number?view=azure-devops&amp;tabs=yaml" target="_blank" rel="noreferrer noopener">中文</a>/<a href="https://docs.microsoft.com/en-us/azure/devops/pipelines/process/run-number?view=azure-devops&amp;tabs=yaml" target="_blank" rel="noreferrer noopener">英文</a>)：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="611" height="298" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/efe9ee23-buildpipeline-classiceditor-setbuildnumberformat.png?resize=611%2C298&#038;ssl=1" alt="" class="wp-image-1528" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/efe9ee23-buildpipeline-classiceditor-setbuildnumberformat.png?w=611&amp;ssl=1 611w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/efe9ee23-buildpipeline-classiceditor-setbuildnumberformat.png?resize=300%2C146&amp;ssl=1 300w" sizes="auto, (max-width: 611px) 100vw, 611px" /><figcaption>Classic editor設定Build number format</figcaption></figure></div>



<p>以上面共用的Build pipeline執行結果的截圖為例，因為有ProjectName這個變數可供使用者設定，再加上取得Branch名稱的系統預先定義變數為SourceBranchName，日期的部份則是以Date:yyyyMMdd的方式輸出，最後的序列號則是Rev:.r的格式，最終在Build number format的部份就需要輸入：</p>



<pre class="wp-block-prismatic-blocks"><code class="language-">$(ProjectName)_$(SourceBranchName)_$(Date:yyyyMMdd)$(Rev:.r)</code></pre>



<p>至於同樣是使用Classic editor方式編輯的Release pipeline，同樣也是在Options的頁籤下進行設定，只是欄位名稱改為Release name format，而官網的文件連結也不相同(<a href="https://docs.microsoft.com/zh-tw/azure/devops/pipelines/release/?view=azure-devops#how-do-i-manage-the-names-for-new-releases" target="_blank" rel="noreferrer noopener">中文</a>/<a href="https://docs.microsoft.com/en-us/azure/devops/pipelines/release/?view=azure-devops#how-do-i-manage-the-names-for-new-releases" target="_blank" rel="noreferrer noopener">英文</a>)：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="626" height="259" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/3ec11750-releasepipeline-setreleasenameformat.png?resize=626%2C259&#038;ssl=1" alt="" class="wp-image-1531" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/3ec11750-releasepipeline-setreleasenameformat.png?w=626&amp;ssl=1 626w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/3ec11750-releasepipeline-setreleasenameformat.png?resize=300%2C124&amp;ssl=1 300w" sizes="auto, (max-width: 626px) 100vw, 626px" /><figcaption>Release pipeline設定Release name format</figcaption></figure></div>



<p>傳統編輯器有設定欄位可以方便設定，但是YAML格式的Build pipeline要怎麼設定呢？</p>



<p>其實上面在傳統編輯器的部份雖然已經寫出了整個Build number format的設定內容，但是最前面的截圖內容卻不是在傳統編輯器下設定的，因為前面文章「<a href="https://tech.uccu.website/2021ironman-day10-create-a-common-use-build-pipeline.html" target="_blank" rel="noreferrer noopener">CI/CD從這裡：第2個Pipeline，建立共用的Build Pipeline</a>」所建立的Pipeline是透過YAML格式設定的，所以我只是把設定的內容提前寫出來而已，詳細的YAML如下：</p>



<pre class="wp-block-prismatic-blocks"><code class="language-yaml">name: $(ProjectName)_$(SourceBranchName)_$(Date:yyyyMMdd)$(Rev:.r)

trigger:
- none

pool:
  vmImage: ubuntu-latest

steps:
- task: DotNetCoreCLI@2
  inputs:
    command: &#039;build&#039;
    projects: &#039;$(ProjectName)/*.csproj&#039;
    arguments: &#039;-o $(Build.BinariesDirectory)&#039;
- task: ArchiveFiles@2
  inputs:
    rootFolderOrFile: &#039;$(Build.BinariesDirectory)&#039;
    includeRootFolder: false
    archiveType: &#039;zip&#039;
    archiveFile: &#039;$(Build.ArtifactStagingDirectory)/$(Build.BuildNumber).zip&#039;
    replaceExistingArchive: true
- task: PublishPipelineArtifact@1
  inputs:
    targetPath: &#039;$(Build.ArtifactStagingDirectory)&#039;
    artifact: &#039;BuildOutputFiles&#039;
    publishLocation: &#039;pipeline&#039;</code></pre>



<p>從上面的YAML內容可以看到，設定的地方是在最上面的name的部份，在官網文件上(<a href="https://docs.microsoft.com/zh-tw/azure/devops/pipelines/process/run-number?view=azure-devops&amp;tabs=yaml" target="_blank" rel="noreferrer noopener">中文</a>/<a href="https://docs.microsoft.com/en-us/azure/devops/pipelines/process/run-number?view=azure-devops&amp;tabs=yaml" target="_blank" rel="noreferrer noopener">英文</a>)有提到，在YAML格式是以name這個名稱來設定，並且它是屬於根(root)層級，所以把它放在最上面的一行。</p>



<p>上面的YAML內容中還有一個地方也進行了修改，那就是在壓縮檔案的Task部份也使用了Build.BuildNumber這個變數，也就是我們在最上面的name的部份所設定的格式內容會放入Build.BuildNumber裡面，所以將這個變數值做為我們壓縮後的檔案名稱，最終從下圖也可以看到執行後所上傳到Artifacts中的檔案名稱的變化，以及Pipeline執行結果的識別名稱與之前的差異：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="765" height="322" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/99e984b3-pipelinerun-changebuildnumberformatforuploadfile.png?resize=765%2C322&#038;ssl=1" alt="" class="wp-image-1534" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/99e984b3-pipelinerun-changebuildnumberformatforuploadfile.png?w=765&amp;ssl=1 765w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/99e984b3-pipelinerun-changebuildnumberformatforuploadfile.png?resize=300%2C126&amp;ssl=1 300w" sizes="auto, (max-width: 765px) 100vw, 765px" /></figure></div>



<p></p>
<p>這篇文章 <a href="https://tech.uccu.website/2021ironman-day28-change-build-number-and-release-name-format.html">【2021鐵人賽】設定Pipeline的識別文字格式</a> 最早出現於 <a href="https://tech.uccu.website">泰克哪裡去</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://tech.uccu.website/2021ironman-day28-change-build-number-and-release-name-format.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1510</post-id>	</item>
		<item>
		<title>【2021鐵人賽】Build Pipeline的YAML結構描述：多個Agent Job</title>
		<link>https://tech.uccu.website/2021ironman-day27-defined-multiple-jobs-in-yaml.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=2021ironman-day27-defined-multiple-jobs-in-yaml</link>
					<comments>https://tech.uccu.website/2021ironman-day27-defined-multiple-jobs-in-yaml.html#respond</comments>
		
		<dc:creator><![CDATA[鳴人]]></dc:creator>
		<pubDate>Sat, 09 Oct 2021 14:54:14 +0000</pubDate>
				<category><![CDATA[2021鐵人賽]]></category>
		<category><![CDATA[Azure DevOps]]></category>
		<category><![CDATA[iThome鐵人賽]]></category>
		<category><![CDATA[資訊科技]]></category>
		<category><![CDATA[2021ironman]]></category>
		<category><![CDATA[azure devops]]></category>
		<guid isPermaLink="false">https://tech.uccu.website/?p=1483</guid>

					<description><![CDATA[<p>前一篇的文章中介紹了傳統編輯器並看到了一個Pipeline中可以有多個不同的Agent Job，實際上YAML格式的Pipeline也可以定義多個不同的Agent Job，這一篇就來看看該如何像Classic editor一樣加入多個不同的Agent Job吧！</p>
<p>這篇文章 <a href="https://tech.uccu.website/2021ironman-day27-defined-multiple-jobs-in-yaml.html">【2021鐵人賽】Build Pipeline的YAML結構描述：多個Agent Job</a> 最早出現於 <a href="https://tech.uccu.website">泰克哪裡去</a>。</p>
]]></description>
										<content:encoded><![CDATA[
<p>前一篇的「<a href="https://tech.uccu.website/2021ironman-day26-classic-pipeline-editor.html" target="_blank" rel="noreferrer noopener">YAML格式以外的Pipeline傳統編輯器(Classic Editor)</a>」文章內容中看到了一個Pipeline中可以有多個不同的Agent Job，在每一個Agent Job底下再各自加入不同的Task，在前面文章的範例中都只是很單純的加入Task，只在一個Agent的情況下執行Pipeline，這一篇就來看看該如何像Classic editor一樣加入多個不同的Agent Job吧！</p>



<p>底下先來部份回顧前面文章「<a href="https://tech.uccu.website/2021ironman-day7-first-pipeline-template-and-editor.html" target="_blank" rel="noreferrer noopener">CI/CD從這裡：設定第一個Pipeline(範本與編輯介面介紹)</a>」內的YAML內容，也就是.NET Desktop的YAML範本：</p>



<pre class="wp-block-prismatic-blocks"><code class="language-yaml">trigger:
- master

pool:
  vmImage: &#039;windows-latest&#039;

variables:
  solution: &#039;**/*.sln&#039;
  buildPlatform: &#039;Any CPU&#039;
  buildConfiguration: &#039;Release&#039;

steps:
- task: NuGetToolInstaller@1

- task: NuGetCommand@2
  inputs:
    restoreSolution: &#039;$(solution)&#039;

- task: VSBuild@1
  inputs:
    solution: &#039;$(solution)&#039;
    platform: &#039;$(buildPlatform)&#039;
    configuration: &#039;$(buildConfiguration)&#039;

- task: VSTest@2
  inputs:
    platform: &#039;$(buildPlatform)&#039;
    configuration: &#039;$(buildConfiguration)&#039;</code></pre>



<p>從上面的內容中可以看到在第一層有trigger、pool、variables、steps，而在steps的下一層有多個task，在Pipeline的YAML結構應該是下面的這個樣子：</p>



<ul class="wp-block-list"><li>YAML<ul><li>name</li><li>resources</li><li>trigger</li><li>pool</li><li>variables</li><li>stages<ul><li>jobs<ul><li>steps<ul><li>script/bash/pwsh/task &#8230;</li></ul></li></ul></li></ul></li></ul></li></ul>



<p>扣除掉前面幾個只會設定一個的項目，範例結構會像這樣：</p>



<ul class="wp-block-list"><li>stages<ul><li>階段A(stage)<ul><li>jobs<ul><li>作業1(job)<ul><li><strong>steps</strong><ul><li><strong>步驟1(task)</strong></li><li><strong>步驟2(script)</strong></li><li><strong>步驟3(pwsh)</strong></li></ul></li></ul></li><li>作業2(job)</li></ul></li></ul></li><li>階段B(stage)</li><li>階段C(stage)</li></ul></li></ul>



<p>所以在上面的YAML範例內容中，其實是省略了上層的許多結構描述，這部份在<a href="https://docs.microsoft.com/zh-tw/azure/devops/pipelines/yaml-schema?view=azure-devops&amp;tabs=schema%2Cparameter-schema#pipeline" target="_blank" rel="noreferrer noopener">官方的文件頁面</a>上有提到，如果只有單一階段(stage)，可以省略關鍵字stages並且直接使用jobs開始。如果只有單一階段(stage)和單一作業(job)，可以省略stages和jobs關鍵字，直接使用steps開始。所以在範本的YAML中才會看到只有steps開始定義底下的task的情況。</p>



<p>所以前一篇的「<a href="https://tech.uccu.website/2021ironman-day26-classic-pipeline-editor.html" target="_blank" rel="noreferrer noopener">YAML格式以外的Pipeline傳統編輯器(Classic Editor)</a>」文章內容中看到了一個Pipeline中可以有多個不同的Agent Job，實際上在YAML格式的內容中就只是在jobs底下定義多個不同的job，在job底下再放入steps底下的內容即可，下面我以前面文章「<a href="https://tech.uccu.website/2021ironman-day9-build-consoleapp-and-publish-artifacts.html" target="_blank" rel="noreferrer noopener">CI/CD從這裡：編譯專案與上傳成品</a>」內容中的YAML稍作修改，steps中使用相同的內容，多增加一個job，YAML如下：</p>



<pre class="wp-block-prismatic-blocks"><code class="language-yaml"># Starter pipeline
# Start with a minimal pipeline that you can customize to build and deploy your code.
# Add steps that build, run tests, deploy, and more:
# https://aka.ms/yaml

trigger:
- none

pool:
  vmImage: ubuntu-latest

jobs:
  - job:
    displayName: Job1
    steps:
    - task: DotNetCoreCLI@2
      inputs:
        command: &#039;build&#039;
        projects: &#039;ConsoleApp/*.csproj&#039;
        arguments: &#039;-o $(Build.BinariesDirectory)&#039;
    - task: ArchiveFiles@2
      inputs:
        rootFolderOrFile: &#039;$(Build.BinariesDirectory)&#039;
        includeRootFolder: true
        archiveType: &#039;zip&#039;
        archiveFile: &#039;$(Build.ArtifactStagingDirectory)/Job1-$(Build.BuildId).zip&#039;
        replaceExistingArchive: true
    - task: PublishBuildArtifacts@1
      inputs:
        PathtoPublish: &#039;$(Build.ArtifactStagingDirectory)&#039;
        ArtifactName: &#039;BuildOutputFiles&#039;
        publishLocation: &#039;Container&#039;

  - job:
    displayName: Job2
    pool:
      vmImage: windows-latest
    steps:
    - task: DotNetCoreCLI@2
      inputs:
        command: &#039;build&#039;
        projects: &#039;ConsoleApp/*.csproj&#039;
        arguments: &#039;-o $(Build.BinariesDirectory)&#039;
    - task: ArchiveFiles@2
      inputs:
        rootFolderOrFile: &#039;$(Build.BinariesDirectory)&#039;
        includeRootFolder: true
        archiveType: &#039;zip&#039;
        archiveFile: &#039;$(Build.ArtifactStagingDirectory)/Job2-$(Build.BuildId).zip&#039;
        replaceExistingArchive: true
    - task: PublishBuildArtifacts@1
      inputs:
        PathtoPublish: &#039;$(Build.ArtifactStagingDirectory)&#039;
        ArtifactName: &#039;BuildOutputFiles&#039;
        publishLocation: &#039;Container&#039;
</code></pre>



<p>從上面的YAML內容可以看到有兩個不同的Job，顯示的名稱分別是Job1、Job2，Job底下的steps幾乎都是相同的內容(複製的)，只有在壓縮檔案的名稱內多了Job1、Job2的前綴字來分別，但是在Job1的displayName底下並沒有額外的設定，在Job2的displayName底下卻另外設定了pool的內容，指定使用Windows的vmImage。也就是說，Job1使用最上層定義的Linux的vmImage(ubuntu)，Job2則是自行另外設定，改用Windows的vmImage。</p>



<p>實際執行的資訊頁如下，可以看到最下面有兩個不同的Job：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1000" height="496" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/223a768f-pipelinerun-2job.png?resize=1000%2C496&#038;ssl=1" alt="" class="wp-image-1486" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/223a768f-pipelinerun-2job.png?w=1000&amp;ssl=1 1000w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/223a768f-pipelinerun-2job.png?resize=300%2C149&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/223a768f-pipelinerun-2job.png?resize=768%2C381&amp;ssl=1 768w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /></figure></div>



<p>點擊任何一個Job都可以進入執行的Log頁面，可以看到下面兩個不同Job的Agent是來自不同的OS(Linux/Windows)：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1010" height="585" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/ab1b8011-pipelinerun-2jobslogs-job1.png?resize=1010%2C585&#038;ssl=1" alt="" class="wp-image-1489" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/ab1b8011-pipelinerun-2jobslogs-job1.png?w=1010&amp;ssl=1 1010w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/ab1b8011-pipelinerun-2jobslogs-job1.png?resize=300%2C174&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/ab1b8011-pipelinerun-2jobslogs-job1.png?resize=768%2C445&amp;ssl=1 768w" sizes="auto, (max-width: 1010px) 100vw, 1010px" /></figure></div>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="672" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/d376165e-pipelinerun-2jobslogs-job2.png?resize=1024%2C672&#038;ssl=1" alt="" class="wp-image-1492" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/d376165e-pipelinerun-2jobslogs-job2.png?w=1024&amp;ssl=1 1024w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/d376165e-pipelinerun-2jobslogs-job2.png?resize=300%2C197&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/d376165e-pipelinerun-2jobslogs-job2.png?resize=768%2C504&amp;ssl=1 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure></div>



<p>執行之後上傳的成品檔案也如預期以不同的Job名稱為開頭命名：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="227" height="269" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/d4567bf2-pipelinerun-2jobartifacts.png?resize=227%2C269&#038;ssl=1" alt="" class="wp-image-1495"/></figure></div>



<p>不同的Job除了可以定義不同的pool之外，也可以定義不同的variables等其它不同的設定，如果需要更多詳細的YAML結構描述內容的定義資訊，可以直接看官方的文件(<a href="https://docs.microsoft.com/zh-tw/azure/devops/pipelines/yaml-schema?view=azure-devops" target="_blank" rel="noreferrer noopener">中文</a>/<a href="https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=azure-devops" target="_blank" rel="noreferrer noopener">英文</a>)。</p>
<p>這篇文章 <a href="https://tech.uccu.website/2021ironman-day27-defined-multiple-jobs-in-yaml.html">【2021鐵人賽】Build Pipeline的YAML結構描述：多個Agent Job</a> 最早出現於 <a href="https://tech.uccu.website">泰克哪裡去</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://tech.uccu.website/2021ironman-day27-defined-multiple-jobs-in-yaml.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1483</post-id>	</item>
		<item>
		<title>【2021鐵人賽】YAML格式以外的Pipeline傳統編輯器(Classic Editor)</title>
		<link>https://tech.uccu.website/2021ironman-day26-classic-pipeline-editor.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=2021ironman-day26-classic-pipeline-editor</link>
					<comments>https://tech.uccu.website/2021ironman-day26-classic-pipeline-editor.html#respond</comments>
		
		<dc:creator><![CDATA[鳴人]]></dc:creator>
		<pubDate>Fri, 08 Oct 2021 15:42:37 +0000</pubDate>
				<category><![CDATA[2021鐵人賽]]></category>
		<category><![CDATA[Azure DevOps]]></category>
		<category><![CDATA[iThome鐵人賽]]></category>
		<category><![CDATA[資訊科技]]></category>
		<category><![CDATA[2021ironman]]></category>
		<category><![CDATA[azure devops]]></category>
		<guid isPermaLink="false">https://tech.uccu.website/?p=1445</guid>

					<description><![CDATA[<p>先前在「CI/CD從這裡：設定第一個Pipeline(範本與編輯介面介紹)」這篇文章內容建立Pipeline的 ... <a title="【2021鐵人賽】YAML格式以外的Pipeline傳統編輯器(Classic Editor)" class="read-more" href="https://tech.uccu.website/2021ironman-day26-classic-pipeline-editor.html" aria-label="Read more about 【2021鐵人賽】YAML格式以外的Pipeline傳統編輯器(Classic Editor)">閱讀全文</a></p>
<p>這篇文章 <a href="https://tech.uccu.website/2021ironman-day26-classic-pipeline-editor.html">【2021鐵人賽】YAML格式以外的Pipeline傳統編輯器(Classic Editor)</a> 最早出現於 <a href="https://tech.uccu.website">泰克哪裡去</a>。</p>
]]></description>
										<content:encoded><![CDATA[
<p>先前在「<a href="https://tech.uccu.website/2021ironman-day7-first-pipeline-template-and-editor.html" target="_blank" rel="noreferrer noopener">CI/CD從這裡：設定第一個Pipeline(範本與編輯介面介紹)</a>」這篇文章內容建立Pipeline的時候是使用新版本的YAML格式編輯器，Pipeline的所有設定都會以文字格式儲存(即Configuration as code)，但是其實在早期建立Pipeline的時候是透過UI畫面建立的。</p>



<p>當時在文章中有稍微提到Classic editor傳統編輯器，而在「<a href="https://tech.uccu.website/2021ironman-day23-quick-create-new-release-pipeline.html" target="_blank" rel="noreferrer noopener">CI/CD從這裡：建立第一個Releases Pipeline</a>」這篇文章中也亮相了UI編輯的畫面(因為目前Release Pipeline沒有YAML編輯畫面)，這篇就來談談這個Classic Editor。</p>



<p>建立Build Pipeline的時候，在選擇範本的最下面有一行「Use the classic editor to create a pipeline without YAML」(還記得<a href="https://tech.uccu.website/2021ironman-day7-first-pipeline-template-and-editor.html" target="_blank" rel="noreferrer noopener">前面文章</a>提到的嗎？)，如下圖點擊之後就可以進入傳統編輯器的流程：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="941" height="610" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/3fdc42a3-newpipeline-whereisyourcode-classiceditor.png?resize=941%2C610&#038;ssl=1" alt="" class="wp-image-1448" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/3fdc42a3-newpipeline-whereisyourcode-classiceditor.png?w=941&amp;ssl=1 941w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/3fdc42a3-newpipeline-whereisyourcode-classiceditor.png?resize=300%2C194&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/3fdc42a3-newpipeline-whereisyourcode-classiceditor.png?resize=768%2C498&amp;ssl=1 768w" sizes="auto, (max-width: 941px) 100vw, 941px" /></figure></div>



<p>接著選擇Source code的來源：</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="583" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/e217169b-newpipeline-classiceditor-selectasource-1024x583.png?resize=1024%2C583&#038;ssl=1" alt="" class="wp-image-1454" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/e217169b-newpipeline-classiceditor-selectasource.png?resize=1024%2C583&amp;ssl=1 1024w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/e217169b-newpipeline-classiceditor-selectasource.png?resize=300%2C171&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/e217169b-newpipeline-classiceditor-selectasource.png?resize=768%2C437&amp;ssl=1 768w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/e217169b-newpipeline-classiceditor-selectasource.png?w=1052&amp;ssl=1 1052w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure></div>



<p>選好Source來源之後就可以來到範本選擇的畫面：</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="463" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/973b09d1-newpipeline-classiceditor-selectatemplate-1024x463.png?resize=1024%2C463&#038;ssl=1" alt="" class="wp-image-1451" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/973b09d1-newpipeline-classiceditor-selectatemplate.png?resize=1024%2C463&amp;ssl=1 1024w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/973b09d1-newpipeline-classiceditor-selectatemplate.png?resize=300%2C136&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/973b09d1-newpipeline-classiceditor-selectatemplate.png?resize=768%2C347&amp;ssl=1 768w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/973b09d1-newpipeline-classiceditor-selectatemplate.png?w=1059&amp;ssl=1 1059w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure></div>



<p>我們選擇Empty job之後一開始出現的畫面如下：</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="447" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/33618fcb-newpipeline-classiceditor-pipelinesettings-1024x447.png?resize=1024%2C447&#038;ssl=1" alt="" class="wp-image-1457" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/33618fcb-newpipeline-classiceditor-pipelinesettings.png?resize=1024%2C447&amp;ssl=1 1024w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/33618fcb-newpipeline-classiceditor-pipelinesettings.png?resize=300%2C131&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/33618fcb-newpipeline-classiceditor-pipelinesettings.png?resize=768%2C335&amp;ssl=1 768w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/33618fcb-newpipeline-classiceditor-pipelinesettings.png?w=1086&amp;ssl=1 1086w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure></div>



<p>在上面這個畫面中可以修改Pipeline的名稱以及預設這個Pipeline使用的Agent pool和Agent規格，不過Agent的設定在Agent job裡面可以另外修改。</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="728" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/56e157bc-newpipeline-classiceditor-getsourcessettings-1024x728.png?resize=1024%2C728&#038;ssl=1" alt="" class="wp-image-1460" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/56e157bc-newpipeline-classiceditor-getsourcessettings.png?resize=1024%2C728&amp;ssl=1 1024w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/56e157bc-newpipeline-classiceditor-getsourcessettings.png?resize=300%2C213&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/56e157bc-newpipeline-classiceditor-getsourcessettings.png?resize=768%2C546&amp;ssl=1 768w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/56e157bc-newpipeline-classiceditor-getsourcessettings.png?w=1141&amp;ssl=1 1141w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure></div>



<p>如果前面的Source來源選錯或是要更換，以及更詳細的設定，則是可以點選左邊的Get sources之後就可以在右邊的對話框調整設定。</p>



<p>而Agent job的設定畫面則是如下圖：</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="724" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/749bf0e6-newpipeline-classiceditor-agentjobsettings-1024x724.png?resize=1024%2C724&#038;ssl=1" alt="" class="wp-image-1463" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/749bf0e6-newpipeline-classiceditor-agentjobsettings.png?resize=1024%2C724&amp;ssl=1 1024w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/749bf0e6-newpipeline-classiceditor-agentjobsettings.png?resize=300%2C212&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/749bf0e6-newpipeline-classiceditor-agentjobsettings.png?resize=768%2C543&amp;ssl=1 768w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/749bf0e6-newpipeline-classiceditor-agentjobsettings.png?w=1144&amp;ssl=1 1144w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure></div>



<p>在之前的文章建立Pipeline的時候都只有使用到一個Agent job，但是其實是可以另外增加許多個不同的Agent job，而不同的Agent job可以設定使用不同的Agent(可以Windows與Linux互相搭配)：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="693" height="171" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/a21c2d03-newpipeline-classiceditor-addmoreagentjob.png?resize=693%2C171&#038;ssl=1" alt="" class="wp-image-1466" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/a21c2d03-newpipeline-classiceditor-addmoreagentjob.png?w=693&amp;ssl=1 693w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/a21c2d03-newpipeline-classiceditor-addmoreagentjob.png?resize=300%2C74&amp;ssl=1 300w" sizes="auto, (max-width: 693px) 100vw, 693px" /></figure></div>



<p>在多個Agent/Agentless job的情況下就有些額外的設定可以調整：</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="631" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/5d860e3d-newpipeline-classiceditor-multipleagentjob-1024x631.png?resize=1024%2C631&#038;ssl=1" alt="" class="wp-image-1469" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/5d860e3d-newpipeline-classiceditor-multipleagentjob.png?resize=1024%2C631&amp;ssl=1 1024w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/5d860e3d-newpipeline-classiceditor-multipleagentjob.png?resize=300%2C185&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/5d860e3d-newpipeline-classiceditor-multipleagentjob.png?resize=768%2C474&amp;ssl=1 768w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/5d860e3d-newpipeline-classiceditor-multipleagentjob.png?w=1140&amp;ssl=1 1140w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure></div>



<p>而Task則是加在Agent job底下，設定的畫面和YAML版本右邊的assistant顯示的畫面相同：</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="732" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/4421fa63-newpipeline-classiceditor-tasksettings-1024x732.png?resize=1024%2C732&#038;ssl=1" alt="" class="wp-image-1472" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/4421fa63-newpipeline-classiceditor-tasksettings.png?resize=1024%2C732&amp;ssl=1 1024w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/4421fa63-newpipeline-classiceditor-tasksettings.png?resize=300%2C214&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/4421fa63-newpipeline-classiceditor-tasksettings.png?resize=768%2C549&amp;ssl=1 768w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/4421fa63-newpipeline-classiceditor-tasksettings.png?w=1125&amp;ssl=1 1125w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure></div>



<p>若是要同時設定Pipeline的Triggers也可以從上面切換到Triggers的頁籤，畫面和先前文章所提的完全一樣。Task那些的用法與設定也和前面文章所提的相同，所以這邊就不再重覆建立新的Pipeline。可以試著對照先前建立的YAML格式的Pipeline來改用傳統編輯器試試喔！</p>



<p>最後，因為Classic editor並不會將設定的內容存成檔案放在Repo裡，所以和YAML編輯器最大的不同就是不會看到Pipeline的設定檔案(所以也沒有Save之後的Commit觸發)。</p>
<p>這篇文章 <a href="https://tech.uccu.website/2021ironman-day26-classic-pipeline-editor.html">【2021鐵人賽】YAML格式以外的Pipeline傳統編輯器(Classic Editor)</a> 最早出現於 <a href="https://tech.uccu.website">泰克哪裡去</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://tech.uccu.website/2021ironman-day26-classic-pipeline-editor.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1445</post-id>	</item>
		<item>
		<title>【2021鐵人賽】接收Azure DevOps的通知：Microsoft Teams頻道中的連結器</title>
		<link>https://tech.uccu.website/2021ironman-day25-add-teams-channel-connector.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=2021ironman-day25-add-teams-channel-connector</link>
					<comments>https://tech.uccu.website/2021ironman-day25-add-teams-channel-connector.html#respond</comments>
		
		<dc:creator><![CDATA[鳴人]]></dc:creator>
		<pubDate>Thu, 07 Oct 2021 15:43:09 +0000</pubDate>
				<category><![CDATA[2021鐵人賽]]></category>
		<category><![CDATA[Azure DevOps]]></category>
		<category><![CDATA[iThome鐵人賽]]></category>
		<category><![CDATA[資訊科技]]></category>
		<category><![CDATA[2021ironman]]></category>
		<category><![CDATA[azure devops]]></category>
		<category><![CDATA[microsoft teams]]></category>
		<guid isPermaLink="false">https://tech.uccu.website/?p=1400</guid>

					<description><![CDATA[<p>我相信如果是使用微軟產品的公司，大多數也都有使用Microsoft Teams作為公司內部的IM訊息軟體，所以 ... <a title="【2021鐵人賽】接收Azure DevOps的通知：Microsoft Teams頻道中的連結器" class="read-more" href="https://tech.uccu.website/2021ironman-day25-add-teams-channel-connector.html" aria-label="Read more about 【2021鐵人賽】接收Azure DevOps的通知：Microsoft Teams頻道中的連結器">閱讀全文</a></p>
<p>這篇文章 <a href="https://tech.uccu.website/2021ironman-day25-add-teams-channel-connector.html">【2021鐵人賽】接收Azure DevOps的通知：Microsoft Teams頻道中的連結器</a> 最早出現於 <a href="https://tech.uccu.website">泰克哪裡去</a>。</p>
]]></description>
										<content:encoded><![CDATA[
<p>我相信如果是使用微軟產品的公司，大多數也都有使用Microsoft Teams作為公司內部的IM訊息軟體，所以這一篇就來看一下同為微軟產品的Azure DevOps與Teams的整合度如何吧！</p>



<p>Teams可以發送訊息的地方分為Chat與Teams底下的Channel，這篇主要是設定Channel中的連接器Connector。</p>



<p>首先，挑選要接收通知的Channel，然後將右邊的隱藏選單叫出來，接著選擇「連接器」或「Connectors」(下面以英文版為例)：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="422" height="296" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/a2b04cd4-teams-channelmenu.png?resize=422%2C296&#038;ssl=1" alt="" class="wp-image-1403" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/a2b04cd4-teams-channelmenu.png?w=422&amp;ssl=1 422w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/a2b04cd4-teams-channelmenu.png?resize=300%2C210&amp;ssl=1 300w" sizes="auto, (max-width: 422px) 100vw, 422px" /></figure></div>



<p>若是沒有設定過Azure DevOps的Connector的話，第一次會看到如下圖的Add：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="779" height="591" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/5dc47e9e-teams-manageconnectors-addazuredevopsconnector.png?resize=779%2C591&#038;ssl=1" alt="" class="wp-image-1406" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/5dc47e9e-teams-manageconnectors-addazuredevopsconnector.png?w=779&amp;ssl=1 779w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/5dc47e9e-teams-manageconnectors-addazuredevopsconnector.png?resize=300%2C228&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/5dc47e9e-teams-manageconnectors-addazuredevopsconnector.png?resize=768%2C583&amp;ssl=1 768w" sizes="auto, (max-width: 779px) 100vw, 779px" /></figure></div>



<p>點擊Add進入Connector的介紹畫面後再按下Add新增：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="886" height="703" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/dc87a002-teams-manageconnectors-addazuredevopsconnector2.png?resize=886%2C703&#038;ssl=1" alt="" class="wp-image-1409" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/dc87a002-teams-manageconnectors-addazuredevopsconnector2.png?w=886&amp;ssl=1 886w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/dc87a002-teams-manageconnectors-addazuredevopsconnector2.png?resize=300%2C238&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/dc87a002-teams-manageconnectors-addazuredevopsconnector2.png?resize=768%2C609&amp;ssl=1 768w" sizes="auto, (max-width: 886px) 100vw, 886px" /></figure></div>



<p>新增完之後，同一個Channel以後就只會看到如下圖的Configure：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="773" height="596" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/e087f6a0-teams-manageconnectors-configureazuredevopsconnector.png?resize=773%2C596&#038;ssl=1" alt="" class="wp-image-1412" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/e087f6a0-teams-manageconnectors-configureazuredevopsconnector.png?w=773&amp;ssl=1 773w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/e087f6a0-teams-manageconnectors-configureazuredevopsconnector.png?resize=300%2C231&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/e087f6a0-teams-manageconnectors-configureazuredevopsconnector.png?resize=768%2C592&amp;ssl=1 768w" sizes="auto, (max-width: 773px) 100vw, 773px" /></figure></div>



<p>點擊Configure進入之後第一次會要求Login，進行身份驗證與授權，代表這個Channel之後就會使用登入的帳號身份來使用Connector：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="778" height="286" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/5892e9d9-teams-manageconnectors-configureazuredevopsconnector-login.png?resize=778%2C286&#038;ssl=1" alt="" class="wp-image-1415" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/5892e9d9-teams-manageconnectors-configureazuredevopsconnector-login.png?w=778&amp;ssl=1 778w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/5892e9d9-teams-manageconnectors-configureazuredevopsconnector-login.png?resize=300%2C110&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/5892e9d9-teams-manageconnectors-configureazuredevopsconnector-login.png?resize=768%2C282&amp;ssl=1 768w" sizes="auto, (max-width: 778px) 100vw, 778px" /></figure></div>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="579" height="184" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/88b9f637-teams-manageconnectors-configureazuredevopsconnector-login2.png?resize=579%2C184&#038;ssl=1" alt="" class="wp-image-1418" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/88b9f637-teams-manageconnectors-configureazuredevopsconnector-login2.png?w=579&amp;ssl=1 579w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/88b9f637-teams-manageconnectors-configureazuredevopsconnector-login2.png?resize=300%2C95&amp;ssl=1 300w" sizes="auto, (max-width: 579px) 100vw, 579px" /></figure></div>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="635" height="665" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/a515fd3f-teams-manageconnectors-configureazuredevopsconnector-grantpermissions.png?resize=635%2C665&#038;ssl=1" alt="" class="wp-image-1421" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/a515fd3f-teams-manageconnectors-configureazuredevopsconnector-grantpermissions.png?w=635&amp;ssl=1 635w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/a515fd3f-teams-manageconnectors-configureazuredevopsconnector-grantpermissions.png?resize=286%2C300&amp;ssl=1 286w" sizes="auto, (max-width: 635px) 100vw, 635px" /></figure></div>



<p>完成登入與授權之後，進入Connector主要的設定畫面，可以從下圖看到能設定的選項有哪些：</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img data-recalc-dims="1" loading="lazy" decoding="async" width="659" height="1024" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/5339f390-teams-configureazuredevopsconnector-659x1024.png?resize=659%2C1024&#038;ssl=1" alt="" class="wp-image-1424" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/5339f390-teams-configureazuredevopsconnector.png?resize=659%2C1024&amp;ssl=1 659w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/5339f390-teams-configureazuredevopsconnector.png?resize=193%2C300&amp;ssl=1 193w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/5339f390-teams-configureazuredevopsconnector.png?resize=768%2C1194&amp;ssl=1 768w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/5339f390-teams-configureazuredevopsconnector.png?w=790&amp;ssl=1 790w" sizes="auto, (max-width: 659px) 100vw, 659px" /></figure></div>



<p>其中Event Type有下列可以選擇的項目，根據不同選擇而出現Event Type下方不同的選項，上圖選擇的是Build completed的時候發送通知到Teams channel中：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="283" height="362" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/eab09b9a-teams-manageconnectors-configureazuredevopsconnector-notifyeventtypes.png?resize=283%2C362&#038;ssl=1" alt="" class="wp-image-1427" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/eab09b9a-teams-manageconnectors-configureazuredevopsconnector-notifyeventtypes.png?w=283&amp;ssl=1 283w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/eab09b9a-teams-manageconnectors-configureazuredevopsconnector-notifyeventtypes.png?resize=235%2C300&amp;ssl=1 235w" sizes="auto, (max-width: 283px) 100vw, 283px" /></figure></div>



<p>設定完成之後在Connectors畫面的左邊選項Configured中就會列出Azure DevOps底下已設定的通知事件，可以設定多個不同的事件通知：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="774" height="579" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/942a6458-teams-manageconnectors-configureazuredevopsconnector-listnotifications.png?resize=774%2C579&#038;ssl=1" alt="" class="wp-image-1430" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/942a6458-teams-manageconnectors-configureazuredevopsconnector-listnotifications.png?w=774&amp;ssl=1 774w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/942a6458-teams-manageconnectors-configureazuredevopsconnector-listnotifications.png?resize=300%2C224&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/942a6458-teams-manageconnectors-configureazuredevopsconnector-listnotifications.png?resize=768%2C575&amp;ssl=1 768w" sizes="auto, (max-width: 774px) 100vw, 774px" /></figure></div>



<p>完成設定之後實際在Azure DevOps裡面執行相對應的操作之後，在Channel中就會出現如下的通知訊息(第一則是設定之後的通知訊息)：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="858" height="397" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/0f29d188-teams-azuredevopsnotifymsg.png?resize=858%2C397&#038;ssl=1" alt="" class="wp-image-1433" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/0f29d188-teams-azuredevopsnotifymsg.png?w=858&amp;ssl=1 858w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/0f29d188-teams-azuredevopsnotifymsg.png?resize=300%2C139&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/0f29d188-teams-azuredevopsnotifymsg.png?resize=768%2C355&amp;ssl=1 768w" sizes="auto, (max-width: 858px) 100vw, 858px" /></figure></div>



<p>不過這裡要特別提醒相關人員要將Channel的notification選項改為All activity，這樣才會在Teams的左邊出現紅色提醒，不然可能會很久沒發現有新的訊息通知喔！</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="696" height="283" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/42937e50-teams-channelnotifications.png?resize=696%2C283&#038;ssl=1" alt="" class="wp-image-1436" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/42937e50-teams-channelnotifications.png?w=696&amp;ssl=1 696w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/42937e50-teams-channelnotifications.png?resize=300%2C122&amp;ssl=1 300w" sizes="auto, (max-width: 696px) 100vw, 696px" /></figure></div>
<p>這篇文章 <a href="https://tech.uccu.website/2021ironman-day25-add-teams-channel-connector.html">【2021鐵人賽】接收Azure DevOps的通知：Microsoft Teams頻道中的連結器</a> 最早出現於 <a href="https://tech.uccu.website">泰克哪裡去</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://tech.uccu.website/2021ironman-day25-add-teams-channel-connector.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1400</post-id>	</item>
		<item>
		<title>【2021鐵人賽】設定Build Pipeline與Release Pipeline的執行權限</title>
		<link>https://tech.uccu.website/2021ironman-day24-set-pipeline-permissions.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=2021ironman-day24-set-pipeline-permissions</link>
					<comments>https://tech.uccu.website/2021ironman-day24-set-pipeline-permissions.html#respond</comments>
		
		<dc:creator><![CDATA[鳴人]]></dc:creator>
		<pubDate>Wed, 06 Oct 2021 15:44:44 +0000</pubDate>
				<category><![CDATA[2021鐵人賽]]></category>
		<category><![CDATA[Azure DevOps]]></category>
		<category><![CDATA[iThome鐵人賽]]></category>
		<category><![CDATA[資訊科技]]></category>
		<category><![CDATA[2021ironman]]></category>
		<category><![CDATA[azure devops]]></category>
		<guid isPermaLink="false">https://tech.uccu.website/?p=1373</guid>

					<description><![CDATA[<p>先前我們建立Build pipeline和Release pipeline的時候使用的都是管理者的帳號，可以建 ... <a title="【2021鐵人賽】設定Build Pipeline與Release Pipeline的執行權限" class="read-more" href="https://tech.uccu.website/2021ironman-day24-set-pipeline-permissions.html" aria-label="Read more about 【2021鐵人賽】設定Build Pipeline與Release Pipeline的執行權限">閱讀全文</a></p>
<p>這篇文章 <a href="https://tech.uccu.website/2021ironman-day24-set-pipeline-permissions.html">【2021鐵人賽】設定Build Pipeline與Release Pipeline的執行權限</a> 最早出現於 <a href="https://tech.uccu.website">泰克哪裡去</a>。</p>
]]></description>
										<content:encoded><![CDATA[
<p>先前我們建立Build pipeline和Release pipeline的時候使用的都是管理者的帳號，可以建立Pipeline自然在執行的部份也是沒有任何問題。問題是Pipeline建立完成之後，接下來手動觸發執行的動作可能是交待給別人去執行，所以就會需要替實際執行者設定權限才行。</p>



<p>首先，我在Project Settings的Permissions建立了兩個Group，分別是Build Pipeline Executor與Release Pipeline Executor：</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="626" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/aec196b5-projsettings-permissions-creategroupforexecutors-1024x626.png?resize=1024%2C626&#038;ssl=1" alt="" class="wp-image-1376" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/aec196b5-projsettings-permissions-creategroupforexecutors.png?resize=1024%2C626&amp;ssl=1 1024w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/aec196b5-projsettings-permissions-creategroupforexecutors.png?resize=300%2C184&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/aec196b5-projsettings-permissions-creategroupforexecutors.png?resize=768%2C470&amp;ssl=1 768w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/aec196b5-projsettings-permissions-creategroupforexecutors.png?w=1468&amp;ssl=1 1468w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure></div>



<p>接著到Build Pipeline或Release Pipeline叫出隱藏的選單，選擇Manage security/Security：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="519" height="356" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/96509e6b-pipelinemenu-managesecurity.png?resize=519%2C356&#038;ssl=1" alt="" class="wp-image-1379" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/96509e6b-pipelinemenu-managesecurity.png?w=519&amp;ssl=1 519w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/96509e6b-pipelinemenu-managesecurity.png?resize=300%2C206&amp;ssl=1 300w" sizes="auto, (max-width: 519px) 100vw, 519px" /></figure></div>



<p>設定權限的對話框長得都差不多，左邊會列出Groups與Users，透過上面的搜尋框搜尋到要設定的Group或User，然後在右邊進行設定：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="896" height="723" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/6f75c5ed-pipeline-setpermissionsforonepipeline.png?resize=896%2C723&#038;ssl=1" alt="" class="wp-image-1382" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/6f75c5ed-pipeline-setpermissionsforonepipeline.png?w=896&amp;ssl=1 896w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/6f75c5ed-pipeline-setpermissionsforonepipeline.png?resize=300%2C242&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/6f75c5ed-pipeline-setpermissionsforonepipeline.png?resize=768%2C620&amp;ssl=1 768w" sizes="auto, (max-width: 896px) 100vw, 896px" /></figure></div>



<p>像上面這張是設定單獨的Build pipeline的權限，我加入了Build Pipeline Executor這個Group，並且在右邊設定了四個項目的權限。</p>



<p>Build Pipeline的權限設定也可以設在整個Build Pipeline上，如下圖我在整個Build Pipeline的部份設定了一個User：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="907" height="715" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/7e612c94-pipeline-setpermissionsforproject.png?resize=907%2C715&#038;ssl=1" alt="" class="wp-image-1388" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/7e612c94-pipeline-setpermissionsforproject.png?w=907&amp;ssl=1 907w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/7e612c94-pipeline-setpermissionsforproject.png?resize=300%2C236&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/7e612c94-pipeline-setpermissionsforproject.png?resize=768%2C605&amp;ssl=1 768w" sizes="auto, (max-width: 907px) 100vw, 907px" /></figure></div>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="911" height="763" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/83c5f9a3-pipeline-permissionsinheritsfromproject.png?resize=911%2C763&#038;ssl=1" alt="" class="wp-image-1385" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/83c5f9a3-pipeline-permissionsinheritsfromproject.png?w=911&amp;ssl=1 911w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/83c5f9a3-pipeline-permissionsinheritsfromproject.png?resize=300%2C251&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/83c5f9a3-pipeline-permissionsinheritsfromproject.png?resize=768%2C643&amp;ssl=1 768w" sizes="auto, (max-width: 911px) 100vw, 911px" /></figure></div>



<p>上面第一張是設定在整個Build Pipeline的截圖，第二張則可以看到從其中的一個Build Pipeline看到相同的User在右邊權限項目是顯示為inhertied。</p>



<p>Release Pipeline的設定也差不多：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="922" height="653" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/3c888819-pipeline-setpermissionsforreleasepipeline.png?resize=922%2C653&#038;ssl=1" alt="" class="wp-image-1391" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/3c888819-pipeline-setpermissionsforreleasepipeline.png?w=922&amp;ssl=1 922w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/3c888819-pipeline-setpermissionsforreleasepipeline.png?resize=300%2C212&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/3c888819-pipeline-setpermissionsforreleasepipeline.png?resize=768%2C544&amp;ssl=1 768w" sizes="auto, (max-width: 922px) 100vw, 922px" /></figure></div>



<p>透過上面的這些設定，我們就可以將Pipeline的執行權限設定給其他人，目前的Azure DevOps也已經允許Stakeholder擁有執行Pipeline的權限，所以如果只是要執行Pipeline的任務，不一定要將使用者的角色設定為Basic(還記得嗎？Basic要計費的)。</p>



<p></p>
<p>這篇文章 <a href="https://tech.uccu.website/2021ironman-day24-set-pipeline-permissions.html">【2021鐵人賽】設定Build Pipeline與Release Pipeline的執行權限</a> 最早出現於 <a href="https://tech.uccu.website">泰克哪裡去</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://tech.uccu.website/2021ironman-day24-set-pipeline-permissions.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1373</post-id>	</item>
		<item>
		<title>【2021鐵人賽】CI/CD從這裡：建立第一個Releases Pipeline</title>
		<link>https://tech.uccu.website/2021ironman-day23-quick-create-new-release-pipeline.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=2021ironman-day23-quick-create-new-release-pipeline</link>
					<comments>https://tech.uccu.website/2021ironman-day23-quick-create-new-release-pipeline.html#respond</comments>
		
		<dc:creator><![CDATA[鳴人]]></dc:creator>
		<pubDate>Tue, 05 Oct 2021 15:48:05 +0000</pubDate>
				<category><![CDATA[2021鐵人賽]]></category>
		<category><![CDATA[Azure DevOps]]></category>
		<category><![CDATA[iThome鐵人賽]]></category>
		<category><![CDATA[資訊科技]]></category>
		<category><![CDATA[2021ironman]]></category>
		<category><![CDATA[azure devops]]></category>
		<guid isPermaLink="false">https://tech.uccu.website/?p=1319</guid>

					<description><![CDATA[<p>這篇我們來建立Release pipeline吧！ 從Azure DevOps Project左邊的Pipel ... <a title="【2021鐵人賽】CI/CD從這裡：建立第一個Releases Pipeline" class="read-more" href="https://tech.uccu.website/2021ironman-day23-quick-create-new-release-pipeline.html" aria-label="Read more about 【2021鐵人賽】CI/CD從這裡：建立第一個Releases Pipeline">閱讀全文</a></p>
<p>這篇文章 <a href="https://tech.uccu.website/2021ironman-day23-quick-create-new-release-pipeline.html">【2021鐵人賽】CI/CD從這裡：建立第一個Releases Pipeline</a> 最早出現於 <a href="https://tech.uccu.website">泰克哪裡去</a>。</p>
]]></description>
										<content:encoded><![CDATA[
<p>這篇我們來建立Release pipeline吧！</p>



<p>從Azure DevOps Project左邊的Pipelines選單底下的Releases點擊之後，第一次進入會看到下面這個空的畫面：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="479" height="307" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/f5152e59-pipelines-emptyreleases.png?resize=479%2C307&#038;ssl=1" alt="" class="wp-image-1322" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/f5152e59-pipelines-emptyreleases.png?w=479&amp;ssl=1 479w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/f5152e59-pipelines-emptyreleases.png?resize=300%2C192&amp;ssl=1 300w" sizes="auto, (max-width: 479px) 100vw, 479px" /></figure></div>



<p>點擊New pipeline之後右邊會跳出選擇範本的畫面，我們選擇Empty job：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="622" height="567" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/b24c0b16-pipelines-selectreleasetemplate.png?resize=622%2C567&#038;ssl=1" alt="" class="wp-image-1325" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/b24c0b16-pipelines-selectreleasetemplate.png?w=622&amp;ssl=1 622w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/b24c0b16-pipelines-selectreleasetemplate.png?resize=300%2C273&amp;ssl=1 300w" sizes="auto, (max-width: 622px) 100vw, 622px" /></figure></div>



<p>接著出現Stage的設定畫面，可以改一下容易識別的名稱，然後按右上角的X關閉對話框就行：</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="444" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/a85e06ec-newrelease-stage1-1024x444.png?resize=1024%2C444&#038;ssl=1" alt="" class="wp-image-1328" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/a85e06ec-newrelease-stage1.png?resize=1024%2C444&amp;ssl=1 1024w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/a85e06ec-newrelease-stage1.png?resize=300%2C130&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/a85e06ec-newrelease-stage1.png?resize=768%2C333&amp;ssl=1 768w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/a85e06ec-newrelease-stage1.png?w=1287&amp;ssl=1 1287w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure></div>



<p>接著點擊Artifacts的+ Add：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="208" height="302" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/2cbcd405-newrelease-addartifacts.png?resize=208%2C302&#038;ssl=1" alt="" class="wp-image-1331" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/2cbcd405-newrelease-addartifacts.png?w=208&amp;ssl=1 208w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/2cbcd405-newrelease-addartifacts.png?resize=207%2C300&amp;ssl=1 207w" sizes="auto, (max-width: 208px) 100vw, 208px" /></figure></div>



<p>這邊我將前面建立Liunx Container Image相關的檔案放到另外一個Git Repo用來作為這篇的範例：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="654" height="259" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/4ceb08f8-gitrepo-dockerfiles.png?resize=654%2C259&#038;ssl=1" alt="" class="wp-image-1334" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/4ceb08f8-gitrepo-dockerfiles.png?w=654&amp;ssl=1 654w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/4ceb08f8-gitrepo-dockerfiles.png?resize=300%2C119&amp;ssl=1 300w" sizes="auto, (max-width: 654px) 100vw, 654px" /></figure></div>



<p>所以在Add Artifacts Source的部份選擇第二個Azure Repo，並且選擇來源的Project、Source (repository)、Default branch等…，不一定要和Release pipeline相同的Project。</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="591" height="714" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/77fcbfdc-newrelease-addrepoartifacts.png?resize=591%2C714&#038;ssl=1" alt="" class="wp-image-1337" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/77fcbfdc-newrelease-addrepoartifacts.png?w=591&amp;ssl=1 591w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/77fcbfdc-newrelease-addrepoartifacts.png?resize=248%2C300&amp;ssl=1 248w" sizes="auto, (max-width: 591px) 100vw, 591px" /></figure></div>



<p>接著點擊右邊Stage底下的1 job, 0 task就可以進入Task的編輯畫面：</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="245" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/84b51484-newrelease-taskssettings-1024x245.png?resize=1024%2C245&#038;ssl=1" alt="" class="wp-image-1340" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/84b51484-newrelease-taskssettings.png?resize=1024%2C245&amp;ssl=1 1024w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/84b51484-newrelease-taskssettings.png?resize=300%2C72&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/84b51484-newrelease-taskssettings.png?resize=768%2C184&amp;ssl=1 768w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/84b51484-newrelease-taskssettings.png?w=1283&amp;ssl=1 1283w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure></div>



<p>因為是要建立Linux的Image，所以點擊Agent job要修改一下Agent改為Linux的Agent(這裡用的是雲端的Agent)：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="629" height="784" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/a3fa5ba9-newrelease-agentjobsettings.png?resize=629%2C784&#038;ssl=1" alt="" class="wp-image-1343" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/a3fa5ba9-newrelease-agentjobsettings.png?w=629&amp;ssl=1 629w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/a3fa5ba9-newrelease-agentjobsettings.png?resize=241%2C300&amp;ssl=1 241w" sizes="auto, (max-width: 629px) 100vw, 629px" /></figure></div>



<p>Agent Specification改為ubuntu-20.04之後，點擊Agent job右邊的+號新增Task，搜尋Docker這個Task並按下Add加入：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="632" height="418" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/7ac98552-newrelease-adddockertask.png?resize=632%2C418&#038;ssl=1" alt="" class="wp-image-1346" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/7ac98552-newrelease-adddockertask.png?w=632&amp;ssl=1 632w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/7ac98552-newrelease-adddockertask.png?resize=300%2C198&amp;ssl=1 300w" sizes="auto, (max-width: 632px) 100vw, 632px" /></figure></div>



<p>設定Task的屬性，Container registry第一次要先新增Service connection，Tags的部份如果需要額外的tag以每一行一個新增：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="636" height="786" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/ecbfaf09-newrelease-adddockertask-settings.png?resize=636%2C786&#038;ssl=1" alt="" class="wp-image-1349" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/ecbfaf09-newrelease-adddockertask-settings.png?w=636&amp;ssl=1 636w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/ecbfaf09-newrelease-adddockertask-settings.png?resize=243%2C300&amp;ssl=1 243w" sizes="auto, (max-width: 636px) 100vw, 636px" /></figure></div>



<p>改完之後也修改了Release pipeline的名稱就可以按下Save，旁邊的Create release按鈕就會變成可以按的狀態。按下之後會出現下面的對話框：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="611" height="610" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/c55ad3e3-newrelease-createnewrelease.png?resize=611%2C610&#038;ssl=1" alt="" class="wp-image-1352" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/c55ad3e3-newrelease-createnewrelease.png?w=611&amp;ssl=1 611w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/c55ad3e3-newrelease-createnewrelease.png?resize=300%2C300&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/c55ad3e3-newrelease-createnewrelease.png?resize=150%2C150&amp;ssl=1 150w" sizes="auto, (max-width: 611px) 100vw, 611px" /></figure></div>



<p>這邊因為沒有什麼特別要調整的，所以點擊對話框下面的Create就行。接著在左上角會有淺綠底的提示訊息，裡面有文字快速連結可以進入剛建立的Release：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="509" height="109" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/5cd408ec-newrelease-createnewrelease-quicklink.png?resize=509%2C109&#038;ssl=1" alt="" class="wp-image-1355" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/5cd408ec-newrelease-createnewrelease-quicklink.png?w=509&amp;ssl=1 509w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/5cd408ec-newrelease-createnewrelease-quicklink.png?resize=300%2C64&amp;ssl=1 300w" sizes="auto, (max-width: 509px) 100vw, 509px" /></figure></div>



<p>進入後可以看到建立的Release狀態(Queued等待中或In progress執行中)：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="670" height="492" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/53b8d565-newrelease-createnewrelease-running.png?resize=670%2C492&#038;ssl=1" alt="" class="wp-image-1358" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/53b8d565-newrelease-createnewrelease-running.png?w=670&amp;ssl=1 670w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/53b8d565-newrelease-createnewrelease-running.png?resize=300%2C220&amp;ssl=1 300w" sizes="auto, (max-width: 670px) 100vw, 670px" /></figure></div>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="665" height="516" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/3d0f5be8-newrelease-createnewrelease-running2.png?resize=665%2C516&#038;ssl=1" alt="" class="wp-image-1361" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/3d0f5be8-newrelease-createnewrelease-running2.png?w=665&amp;ssl=1 665w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/3d0f5be8-newrelease-createnewrelease-running2.png?resize=300%2C233&amp;ssl=1 300w" sizes="auto, (max-width: 665px) 100vw, 665px" /></figure></div>



<p>點擊底下的Logs就可以進入看各步驟詳細的Logs：</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="636" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/52273216-newrelease-createnewrelease-runninglogs-1024x636.png?resize=1024%2C636&#038;ssl=1" alt="" class="wp-image-1364" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/52273216-newrelease-createnewrelease-runninglogs.png?resize=1024%2C636&amp;ssl=1 1024w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/52273216-newrelease-createnewrelease-runninglogs.png?resize=300%2C186&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/52273216-newrelease-createnewrelease-runninglogs.png?resize=768%2C477&amp;ssl=1 768w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/52273216-newrelease-createnewrelease-runninglogs.png?w=1294&amp;ssl=1 1294w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure></div>



<p>這篇就先快速的帶大家簡單的建立一個Release pipeline，後續的文章再做複雜一點的說明。</p>
<p>這篇文章 <a href="https://tech.uccu.website/2021ironman-day23-quick-create-new-release-pipeline.html">【2021鐵人賽】CI/CD從這裡：建立第一個Releases Pipeline</a> 最早出現於 <a href="https://tech.uccu.website">泰克哪裡去</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://tech.uccu.website/2021ironman-day23-quick-create-new-release-pipeline.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1319</post-id>	</item>
		<item>
		<title>【2021鐵人賽】建立自管的Azure DevOps Agent(Linux Container agent)</title>
		<link>https://tech.uccu.website/2021ironman-day22-build-linux-container-image-for-azure-devops-agent.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=2021ironman-day22-build-linux-container-image-for-azure-devops-agent</link>
					<comments>https://tech.uccu.website/2021ironman-day22-build-linux-container-image-for-azure-devops-agent.html#respond</comments>
		
		<dc:creator><![CDATA[鳴人]]></dc:creator>
		<pubDate>Mon, 04 Oct 2021 15:40:42 +0000</pubDate>
				<category><![CDATA[2021鐵人賽]]></category>
		<category><![CDATA[Azure DevOps]]></category>
		<category><![CDATA[Docker]]></category>
		<category><![CDATA[iThome鐵人賽]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[資訊科技]]></category>
		<category><![CDATA[2021ironman]]></category>
		<category><![CDATA[azure devops]]></category>
		<category><![CDATA[container]]></category>
		<category><![CDATA[docker]]></category>
		<guid isPermaLink="false">https://tech.uccu.website/?p=1292</guid>

					<description><![CDATA[<p>前一篇文章建立了Azure DevOps Agent的Windows Container Image，已經知道了基本的概念就是：1.選擇基底映像檔、2.安裝所需要的額外套件與程式、3.將Azure DevOps Agent的開始程式start.ps/start.sh複製進去。</p>
<p>這篇文章 <a href="https://tech.uccu.website/2021ironman-day22-build-linux-container-image-for-azure-devops-agent.html">【2021鐵人賽】建立自管的Azure DevOps Agent(Linux Container agent)</a> 最早出現於 <a href="https://tech.uccu.website">泰克哪裡去</a>。</p>
]]></description>
										<content:encoded><![CDATA[
<p><a href="https://tech.uccu.website/2021ironman-day21-build-windows-container-image-for-azure-devops-agent.html" target="_blank" rel="noreferrer noopener">前一篇文章</a>建立了Azure DevOps Agent的Windows Container Image，已經知道了基本的概念就是：</p>



<ol class="wp-block-list"><li>選擇基底映像檔</li><li>安裝所需要的額外套件與程式</li><li>將Azure DevOps Agent的開始程式start.ps/start.sh複製進去</li></ol>



<p>既然已經知道了上面的概念，前一篇也有做過一次，那麼這篇就少浪費一些篇幅，直接把Code端上來看吧！</p>



<p>start.sh的內容如下，記得要改成Unix格式的結束符號(LF)喔！(或是透過dos2unix轉換)</p>



<pre class="wp-block-prismatic-blocks"><code class="language-bash">#!/bin/bash
set -e

if [ -z &quot;$AZP_URL&quot; ]; then
  echo 1&gt;&amp;2 &quot;error: missing AZP_URL environment variable&quot;
  exit 1
fi

if [ -z &quot;$AZP_TOKEN_FILE&quot; ]; then
  if [ -z &quot;$AZP_TOKEN&quot; ]; then
    echo 1&gt;&amp;2 &quot;error: missing AZP_TOKEN environment variable&quot;
    exit 1
  fi

  AZP_TOKEN_FILE=/azp/.token
  echo -n $AZP_TOKEN &gt; &quot;$AZP_TOKEN_FILE&quot;
fi

unset AZP_TOKEN

if [ -n &quot;$AZP_WORK&quot; ]; then
  mkdir -p &quot;$AZP_WORK&quot;
fi

export AGENT_ALLOW_RUNASROOT=&quot;1&quot;

cleanup() {
  if [ -e config.sh ]; then
    print_header &quot;Cleanup. Removing Azure Pipelines agent...&quot;

    # If the agent has some running jobs, the configuration removal process will fail.
    # So, give it some time to finish the job.
    while true; do
      ./config.sh remove --unattended --auth PAT --token $(cat &quot;$AZP_TOKEN_FILE&quot;) &amp;&amp; break

      echo &quot;Retrying in 30 seconds...&quot;
      sleep 30
    done
  fi
}

print_header() {
  lightcyan=&#039;\033[1;36m&#039;
  nocolor=&#039;\033[0m&#039;
  echo -e &quot;${lightcyan}$1${nocolor}&quot;
}

# Let the agent ignore the token env variables
export VSO_AGENT_IGNORE=AZP_TOKEN,AZP_TOKEN_FILE

source ./env.sh

print_header &quot;1. Configuring Azure Pipelines agent...&quot;

./config.sh --unattended \
  --agent &quot;${AZP_AGENT_NAME:-$(hostname)}&quot; \
  --url &quot;$AZP_URL&quot; \
  --auth PAT \
  --token $(cat &quot;$AZP_TOKEN_FILE&quot;) \
  --pool &quot;${AZP_POOL:-Default}&quot; \
  --work &quot;${AZP_WORK:-_work}&quot; \
  --replace \
  --acceptTeeEula &amp; wait $!

print_header &quot;2. Running Azure Pipelines agent...&quot;

trap &#039;cleanup; exit 0&#039; EXIT
trap &#039;cleanup; exit 130&#039; INT
trap &#039;cleanup; exit 143&#039; TERM

# To be aware of TERM and INT signals call run.sh
# Running it with the --once flag at the end will shut down the agent after the build is executed
./run.sh &quot;$@&quot;</code></pre>



<p>官方的Dockerfile內容如下：</p>



<pre class="wp-block-prismatic-blocks"><code class="language-dockerfile">FROM ubuntu:18.04

# To make it easier for build and release pipelines to run apt-get,
# configure apt to not require confirmation (assume the -y argument by default)
ENV DEBIAN_FRONTEND=noninteractive
RUN echo &quot;APT::Get::Assume-Yes \&quot;true\&quot;;&quot; &gt; /etc/apt/apt.conf.d/90assumeyes

RUN apt-get update &amp;&amp; apt-get install -y --no-install-recommends \
    ca-certificates \
    curl \
    jq \
    git \
    iputils-ping \
    libcurl4 \
    libicu60 \
    libunwind8 \
    netcat \
    libssl1.0 \
  &amp;&amp; rm -rf /var/lib/apt/lists/*

RUN curl -LsS https://aka.ms/InstallAzureCLIDeb | bash \
  &amp;&amp; rm -rf /var/lib/apt/lists/*

ARG TARGETARCH=amd64
ARG AGENT_VERSION=2.185.1

WORKDIR /azp
RUN if [ &quot;$TARGETARCH&quot; = &quot;amd64&quot; ]; then \
      AZP_AGENTPACKAGE_URL=https://vstsagentpackage.azureedge.net/agent/${AGENT_VERSION}/vsts-agent-linux-x64-${AGENT_VERSION}.tar.gz; \
    else \
      AZP_AGENTPACKAGE_URL=https://vstsagentpackage.azureedge.net/agent/${AGENT_VERSION}/vsts-agent-linux-${TARGETARCH}-${AGENT_VERSION}.tar.gz; \
    fi; \
    curl -LsS &quot;$AZP_AGENTPACKAGE_URL&quot; | tar -xz

COPY ./start.sh .
RUN chmod +x start.sh

ENTRYPOINT [ &quot;./start.sh&quot; ]</code></pre>



<p>同樣的，上面的Dockerfile並不包含dotnet sdk，所以仍然需要自行安裝進去。</p>



<p>也和上一篇提到的一樣，我們可以透過在Docker hub上找到官方的dotnet sdk映像檔，找到我們要的OS版本，然後取代Dockerfile第一行的FROM後面使用的image repository：</p>



<figure class="wp-block-image size-large"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="439" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/718841de-dotnetsdkimage-linuxamd64tags-1024x439.png?resize=1024%2C439&#038;ssl=1" alt="" class="wp-image-1298" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/718841de-dotnetsdkimage-linuxamd64tags.png?resize=1024%2C439&amp;ssl=1 1024w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/718841de-dotnetsdkimage-linuxamd64tags.png?resize=300%2C129&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/718841de-dotnetsdkimage-linuxamd64tags.png?resize=768%2C329&amp;ssl=1 768w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/718841de-dotnetsdkimage-linuxamd64tags.png?resize=1536%2C659&amp;ssl=1 1536w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/718841de-dotnetsdkimage-linuxamd64tags.png?w=1665&amp;ssl=1 1665w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>上圖的表格來自於微軟在<a href="https://hub.docker.com/_/microsoft-dotnet-sdk/" target="_blank" rel="noreferrer noopener">Docker Hub上的dotnet sdk頁面</a>，dotnet sdk的image repository是mcr.microsoft.com/dotnet/sdk:5.0，我們只需要將冒號後面的5.0改成需要的就行了，以上面紅框內容為例，就把5.0改為5.0-focal，這樣就是以Ubuntu 20.04為版本安裝了dotnet sdk 5.0製作的Docker image，再加上安裝PowerShell、Docker的話，最終的Dockerfile內容如下：</p>



<pre class="wp-block-prismatic-blocks"><code class="language-dockerfile">FROM mcr.microsoft.com/dotnet/sdk:5.0-focal

# To make it easier for build and release pipelines to run apt-get,
# configure apt to not require confirmation (assume the -y argument by default)
ENV DEBIAN_FRONTEND=noninteractive
RUN echo &quot;APT::Get::Assume-Yes \&quot;true\&quot;;&quot; &gt; /etc/apt/apt.conf.d/90assumeyes

#在這底下加入要額外裝在Docker Image內的程式

RUN apt-get update &amp;&amp; apt-get install -y --no-install-recommends \
    ca-certificates \
    curl \
    jq \
    git \
    iputils-ping \
    libcurl4 \
    libicu66 \
    libunwind8 \
    netcat \
    libssl1.0 \
	wget \
  &amp;&amp; rm -rf /var/lib/apt/lists/*

# 新增 Microsoft 存放庫金鑰和摘要
RUN wget https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb &amp;&amp; \
         dpkg -i packages-microsoft-prod.deb

# 安裝PowerShell
# Enable the &quot;universe&quot; repositories &amp; Install PowerShell
RUN apt-get update &amp;&amp; apt-get install -y powershell

# 安裝Docker
RUN apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common
RUN curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add
RUN add-apt-repository \
   &quot;deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable&quot;
RUN apt-get update &amp;&amp; apt-get install docker-ce docker-ce-cli containerd.io

#===========================================

RUN curl -LsS https://aka.ms/InstallAzureCLIDeb | bash \
  &amp;&amp; rm -rf /var/lib/apt/lists/*

ARG TARGETARCH=amd64
ARG AGENT_VERSION=2.185.1

WORKDIR /azp
RUN if [ &quot;$TARGETARCH&quot; = &quot;amd64&quot; ]; then \
      AZP_AGENTPACKAGE_URL=https://vstsagentpackage.azureedge.net/agent/${AGENT_VERSION}/vsts-agent-linux-x64-${AGENT_VERSION}.tar.gz; \
    else \
      AZP_AGENTPACKAGE_URL=https://vstsagentpackage.azureedge.net/agent/${AGENT_VERSION}/vsts-agent-linux-${TARGETARCH}-${AGENT_VERSION}.tar.gz; \
    fi; \
    curl -LsS &quot;$AZP_AGENTPACKAGE_URL&quot; | tar -xz

COPY ./start.sh .
RUN chmod +x start.sh

ENTRYPOINT [ &quot;./start.sh&quot; ]</code></pre>



<p>上面的Dockerfile內容中要特別提一下在官方的範例中安裝的libicu60 package只適用在Ubuntu 18.04(<a href="https://askubuntu.com/questions/1225781/unable-to-locate-package-libicu60" target="_blank" rel="noreferrer noopener">參考這篇</a>)，因為我是選Ubuntu 20.04，所以改成libicu66(<a href="https://github.com/dotnet/core/issues/4360#issuecomment-618638299" target="_blank" rel="noreferrer noopener">參考這篇</a>)。</p>



<p>準備好Dockerfile和start.sh這兩個檔案之後，執行下面的指令建立映像檔：</p>



<pre class="wp-block-prismatic-blocks"><code class="language-docker">docker build -t devopsagent .</code></pre>



<p>完成Build Image的動作之後，透過下面的指令建立一個名為azure-agent的Container：</p>



<pre class="wp-block-prismatic-blocks"><code class="language-docker">docker run --name azure-agent -d -v /var/run/docker.sock:/var/run/docker.sock -e AZP_URL=[AzureDevOpsURL] -e AZP_TOKEN=[AzureDevOpsPAT] -e AZP_AGENT_NAME=[AzureDevOpsAgentName] IMAGE:TAG</code></pre>



<p>docker run的指令和<a href="https://tech.uccu.website/2021ironman-day21-build-windows-container-image-for-azure-devops-agent.html" target="_blank" rel="noreferrer noopener">前一篇</a>的大同小異，主要差別在於如何繫結host的docker給container使用。</p>



<p>同樣的環境變數表再貼一次：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1025" height="408" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/4582d3e6-devopsagent-containerenvironmentvariables.png?resize=1025%2C408&#038;ssl=1" alt="" class="wp-image-1265" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/4582d3e6-devopsagent-containerenvironmentvariables.png?w=1025&amp;ssl=1 1025w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/4582d3e6-devopsagent-containerenvironmentvariables.png?resize=300%2C119&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/4582d3e6-devopsagent-containerenvironmentvariables.png?resize=768%2C306&amp;ssl=1 768w" sizes="auto, (max-width: 1025px) 100vw, 1025px" /><figcaption>Azure DevOps Agent所使用的環境變數</figcaption></figure></div>



<p>同樣貼一下執行的結果：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1006" height="669" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/b80fcbf2-devopsagent-runagentinlinuxcontainer.png?resize=1006%2C669&#038;ssl=1" alt="" class="wp-image-1301" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/b80fcbf2-devopsagent-runagentinlinuxcontainer.png?w=1006&amp;ssl=1 1006w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/b80fcbf2-devopsagent-runagentinlinuxcontainer.png?resize=300%2C200&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/b80fcbf2-devopsagent-runagentinlinuxcontainer.png?resize=768%2C511&amp;ssl=1 768w" sizes="auto, (max-width: 1006px) 100vw, 1006px" /></figure></div>



<p>還有Agent Pools裡的列表和Agent的Capabilities：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="793" height="344" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/4e5fe0f5-agentpools-default-linuxcontaineragent.png?resize=793%2C344&#038;ssl=1" alt="" class="wp-image-1304" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/4e5fe0f5-agentpools-default-linuxcontaineragent.png?w=793&amp;ssl=1 793w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/4e5fe0f5-agentpools-default-linuxcontaineragent.png?resize=300%2C130&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/4e5fe0f5-agentpools-default-linuxcontaineragent.png?resize=768%2C333&amp;ssl=1 768w" sizes="auto, (max-width: 793px) 100vw, 793px" /></figure></div>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="784" height="927" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/7b7c07bc-agentpools-default-linuxcontaineragent-capabilities.png?resize=784%2C927&#038;ssl=1" alt="" class="wp-image-1307" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/7b7c07bc-agentpools-default-linuxcontaineragent-capabilities.png?w=784&amp;ssl=1 784w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/7b7c07bc-agentpools-default-linuxcontaineragent-capabilities.png?resize=254%2C300&amp;ssl=1 254w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/7b7c07bc-agentpools-default-linuxcontaineragent-capabilities.png?resize=768%2C908&amp;ssl=1 768w" sizes="auto, (max-width: 784px) 100vw, 784px" /></figure></div>



<p>其它和前一篇的內容沒什麼太大的差別，至於Linux VM的部份意思差不多，所以就不再另外弄一篇安裝在Linux VM裡的文章了</p>
<p>這篇文章 <a href="https://tech.uccu.website/2021ironman-day22-build-linux-container-image-for-azure-devops-agent.html">【2021鐵人賽】建立自管的Azure DevOps Agent(Linux Container agent)</a> 最早出現於 <a href="https://tech.uccu.website">泰克哪裡去</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://tech.uccu.website/2021ironman-day22-build-linux-container-image-for-azure-devops-agent.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1292</post-id>	</item>
		<item>
		<title>【2021鐵人賽】建立自管的Azure DevOps Agent(Windows Container agent)</title>
		<link>https://tech.uccu.website/2021ironman-day21-build-windows-container-image-for-azure-devops-agent.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=2021ironman-day21-build-windows-container-image-for-azure-devops-agent</link>
					<comments>https://tech.uccu.website/2021ironman-day21-build-windows-container-image-for-azure-devops-agent.html#respond</comments>
		
		<dc:creator><![CDATA[鳴人]]></dc:creator>
		<pubDate>Sun, 03 Oct 2021 11:58:42 +0000</pubDate>
				<category><![CDATA[2021鐵人賽]]></category>
		<category><![CDATA[Azure DevOps]]></category>
		<category><![CDATA[Docker]]></category>
		<category><![CDATA[iThome鐵人賽]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[資訊科技]]></category>
		<category><![CDATA[2021ironman]]></category>
		<category><![CDATA[azure devops]]></category>
		<category><![CDATA[container]]></category>
		<category><![CDATA[docker]]></category>
		<guid isPermaLink="false">https://tech.uccu.website/?p=1235</guid>

					<description><![CDATA[<p>這篇延續前一篇在Windows VM中安裝Azure DevOps Agent的內容，講解了如何讓Agent在Windows Container中執行，從基底映像檔的差異到挑選適合的映像檔在Dockerfile中使用，也示範如何將Host中Docker提供給Container使用。</p>
<p>這篇文章 <a href="https://tech.uccu.website/2021ironman-day21-build-windows-container-image-for-azure-devops-agent.html">【2021鐵人賽】建立自管的Azure DevOps Agent(Windows Container agent)</a> 最早出現於 <a href="https://tech.uccu.website">泰克哪裡去</a>。</p>
]]></description>
										<content:encoded><![CDATA[
<p><a href="https://tech.uccu.website/2021ironman-day20-setup-azure-devops-agent-on-windows-vm.html" target="_blank" rel="noreferrer noopener">前一篇</a>提到了在Windows VM中安裝Azure DevOps Agent，步驟非常的簡單，不過Azure DevOps Agent也可以在Container內執行，這一篇就來看看如何在Windows Container內執行Azure DevOps Agent。(如果需要Windows Server安裝Docker的方式請看<a href="https://tech.uccu.website/install-docker-on-windows-server.html" target="_blank" rel="noreferrer noopener">這篇文章</a>)</p>



<p>首先，在Windows Container的部份有些基本的知識需要了解，那就是Windows Container區分不同的基底映像類型(Base Image)，分為Windows、Windows Server、Windows Server Core、Nano Server四種，越前面的映像檔大小所佔的容量越大，包含的功能越多，越後面的則越小，所包含的功能也越少。(參考官方文件：<a href="https://docs.microsoft.com/zh-tw/virtualization/windowscontainers/manage-containers/container-base-images" target="_blank" rel="noreferrer noopener">中文</a>/<a href="https://docs.microsoft.com/en-us/virtualization/windowscontainers/manage-containers/container-base-images" target="_blank" rel="noreferrer noopener">英文</a>)</p>



<p>另外就是Windows Container的隔離模式(Isolation  Modes)，分為Process和Hyper-V隔離這兩種，在Windows Server上執行的Windows Container預設以Process隔離方式執行，在Windows 10執行的Windows Container則預設以Hyper-V隔離方式執行。(參考官方文件：<a href="https://docs.microsoft.com/zh-tw/virtualization/windowscontainers/manage-containers/hyperv-container" target="_blank" rel="noreferrer noopener">中文</a>/<a href="https://docs.microsoft.com/en-us/virtualization/windowscontainers/manage-containers/hyperv-container" target="_blank" rel="noreferrer noopener">英文</a>)</p>



<p>在上面這兩個不同的差異之下，選擇建立Windows Container Image就會有很多的選擇，這牽涉到執行Container的主機(Host)所使用的是哪一個版本的OS，不同版本之間的相容性會有所差異，例如：Windows Server 2019與Windows Server 20H2這兩個版本的OS相容性：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="574" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/e7ee6766-oscompatibility-winserver2019.png?resize=1024%2C574&#038;ssl=1" alt="" class="wp-image-1238" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/e7ee6766-oscompatibility-winserver2019.png?w=1024&amp;ssl=1 1024w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/e7ee6766-oscompatibility-winserver2019.png?resize=300%2C168&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/e7ee6766-oscompatibility-winserver2019.png?resize=768%2C431&amp;ssl=1 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption>Windows Server 2019的OS相容性</figcaption></figure></div>



<div class="wp-block-image"><figure class="aligncenter size-large"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="573" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/d95ace76-oscompatibility-winserver20h2-1024x573.png?resize=1024%2C573&#038;ssl=1" alt="" class="wp-image-1241" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/d95ace76-oscompatibility-winserver20h2.png?resize=1024%2C573&amp;ssl=1 1024w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/d95ace76-oscompatibility-winserver20h2.png?resize=300%2C168&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/d95ace76-oscompatibility-winserver20h2.png?resize=768%2C430&amp;ssl=1 768w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/d95ace76-oscompatibility-winserver20h2.png?w=1031&amp;ssl=1 1031w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption>Windows Server 20H2的OS相容性</figcaption></figure></div>



<p>從上面兩張圖可以看到Windows Server 2019的Host可以支援以Windows Server 2019為基底的Container Image以Process隔離模式執行，若是以Hyper-V隔離模式執行，則是可以支援Windows Server 2019以下的版本。同樣的，Windows Server 20H2的Host可以支援同為Windows Server 20H2的Image以Process隔離模式執行，Hyper-V的隔離模式則是與Host相同版本以下的都能夠支援。</p>



<p>換成是Windows 10作為Host的話，支援性又有不同的差異：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1015" height="566" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/a65d2b83-oscompatibility-win10_1909.png?resize=1015%2C566&#038;ssl=1" alt="" class="wp-image-1244" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/a65d2b83-oscompatibility-win10_1909.png?w=1015&amp;ssl=1 1015w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/a65d2b83-oscompatibility-win10_1909.png?resize=300%2C167&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/a65d2b83-oscompatibility-win10_1909.png?resize=768%2C428&amp;ssl=1 768w" sizes="auto, (max-width: 1015px) 100vw, 1015px" /><figcaption>Windows 10 1909版本的OS相容性</figcaption></figure></div>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1016" height="574" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/06a1c852-oscompatibility-win10_2004.png?resize=1016%2C574&#038;ssl=1" alt="" class="wp-image-1247" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/06a1c852-oscompatibility-win10_2004.png?w=1016&amp;ssl=1 1016w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/06a1c852-oscompatibility-win10_2004.png?resize=300%2C169&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/06a1c852-oscompatibility-win10_2004.png?resize=768%2C434&amp;ssl=1 768w" sizes="auto, (max-width: 1016px) 100vw, 1016px" /><figcaption>Windows 10 2004版本的OS相容性</figcaption></figure></div>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1017" height="570" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/530b0e7f-oscompatibility-win10_20h2.png?resize=1017%2C570&#038;ssl=1" alt="" class="wp-image-1250" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/530b0e7f-oscompatibility-win10_20h2.png?w=1017&amp;ssl=1 1017w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/530b0e7f-oscompatibility-win10_20h2.png?resize=300%2C168&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/530b0e7f-oscompatibility-win10_20h2.png?resize=768%2C430&amp;ssl=1 768w" sizes="auto, (max-width: 1017px) 100vw, 1017px" /><figcaption>Windows 10 20H2版本的OS相容性</figcaption></figure></div>



<p>Windows 10的部份可以從上面三張圖看到一點點差異，就是Windows 10的1909版本並不能支援Windows Server任何版本為基底映像檔以Process隔離模式執行，Windows 10的2004版本之後才開始支援與Windows Server相對應的版本映像檔以Process隔離模式執行，但是以Hyper-V隔離模式執行的話則是支援相同版本以下的OS映像檔。</p>



<p>有點複雜，對吧？</p>



<p>簡單來說，要能夠支援以Process隔離模式執行，必須是Container Base Image和Host為相同版本的OS，若是以Hyper-V隔離模式執行，則必須挑選Host OS版本以下製成的Container Image，也就是說Windows Server 2016的選擇性非常少，只能使用同為Windows Server 2016為基底製作的映像檔，越新的OS版本則支援以Hyper-V隔離模式執行的Container Image選擇越多。</p>



<p>更多Windows Container版本相容性的部份可以參考官方文件的說明(<a href="https://docs.microsoft.com/zh-tw/virtualization/windowscontainers/deploy-containers/version-compatibility" target="_blank" rel="noreferrer noopener">中文</a>/<a href="https://docs.microsoft.com/en-us/virtualization/windowscontainers/deploy-containers/version-compatibility" target="_blank" rel="noreferrer noopener">英文</a>)。</p>



<p>回到Azure DevOps Agent，上面說了那麼多，主要是必須考量Agent要執行的任務需要多大的支援與資源，若是只需要能夠以dotnet sdk建置專案，那麼選擇任何一個OS版本的Image應該都可以，只要能夠在Image裡面安裝dotnet sdk即可。</p>



<p>以dotnet sdk這個例子來說，在官方文件「<a href="https://docs.microsoft.com/zh-tw/azure/devops/pipelines/agents/docker?view=azure-devops" target="_blank" rel="noreferrer noopener">在 Docker 中執行自我裝載的代理程式</a>」所提到的Dockerfile範例是使用Windows Server Core 2019的基底映像檔，裡面並沒有安裝dotnet sdk：</p>



<pre class="wp-block-prismatic-blocks"><code class="language-dockerfile">FROM mcr.microsoft.com/windows/servercore:ltsc2019

WORKDIR /azp

COPY start.ps1 .

CMD powershell .\start.ps1</code></pre>



<p>所以要讓Agent可以執行dotnet build的任務，可以選擇使用上面的範例，在Dockerfile中再另外加入安裝dotnet sdk的內容，或是從<a href="https://hub.docker.com/" target="_blank" rel="noreferrer noopener">Docker hub</a>上另外找<a href="https://hub.docker.com/_/microsoft-dotnet-sdk/" target="_blank" rel="noreferrer noopener">微軟官方製作的dotnet sdk映像檔</a>，找到對應的Container Repository與Image tag，例如：「mcr.microsoft.com/dotnet/sdk:5.0-windowsservercore-ltsc2019」這個就是同樣以Windows Server Core 2019為基底的Image，並且安裝了dotnet 5.0 sdk。</p>



<p>從官方文件「<a href="https://docs.microsoft.com/zh-tw/azure/devops/pipelines/agents/docker?view=azure-devops" target="_blank" rel="noreferrer noopener">在 Docker 中執行自我裝載的代理程式</a>」 中的範例可以看得出來，在Container中執行Azure DevOps Agent的關鍵在於下面這段PowerShell內容，將它複製之後以start.ps1儲存在與Dockerfile相同的位置即可：</p>



<pre class="wp-block-prismatic-blocks"><code class="language-powershell">if (-not (Test-Path Env:AZP_URL)) {
  Write-Error &quot;error: missing AZP_URL environment variable&quot;
  exit 1
}

if (-not (Test-Path Env:AZP_TOKEN_FILE)) {
  if (-not (Test-Path Env:AZP_TOKEN)) {
    Write-Error &quot;error: missing AZP_TOKEN environment variable&quot;
    exit 1
  }

  $Env:AZP_TOKEN_FILE = &quot;\azp\.token&quot;
  $Env:AZP_TOKEN | Out-File -FilePath $Env:AZP_TOKEN_FILE
}

Remove-Item Env:AZP_TOKEN

if ((Test-Path Env:AZP_WORK) -and -not (Test-Path $Env:AZP_WORK)) {
  New-Item $Env:AZP_WORK -ItemType directory | Out-Null
}

New-Item &quot;\azp\agent&quot; -ItemType directory | Out-Null

# Let the agent ignore the token env variables
$Env:VSO_AGENT_IGNORE = &quot;AZP_TOKEN,AZP_TOKEN_FILE&quot;

Set-Location agent

Write-Host &quot;1. Determining matching Azure Pipelines agent...&quot; -ForegroundColor Cyan

$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(&quot;:$(Get-Content ${Env:AZP_TOKEN_FILE})&quot;))
$package = Invoke-RestMethod -Headers @{Authorization=(&quot;Basic $base64AuthInfo&quot;)} &quot;$(${Env:AZP_URL})/_apis/distributedtask/packages/agent?platform=win-x64&amp;`$top=1&quot;
$packageUrl = $package[0].Value.downloadUrl

Write-Host $packageUrl

Write-Host &quot;2. Downloading and installing Azure Pipelines agent...&quot; -ForegroundColor Cyan

$wc = New-Object System.Net.WebClient
$wc.DownloadFile($packageUrl, &quot;$(Get-Location)\agent.zip&quot;)

Expand-Archive -Path &quot;agent.zip&quot; -DestinationPath &quot;\azp\agent&quot;

try
{
  Write-Host &quot;3. Configuring Azure Pipelines agent...&quot; -ForegroundColor Cyan

  .\config.cmd --unattended `
    --agent &quot;$(if (Test-Path Env:AZP_AGENT_NAME) { ${Env:AZP_AGENT_NAME} } else { ${Env:computername} })&quot; `
    --url &quot;$(${Env:AZP_URL})&quot; `
    --auth PAT `
    --token &quot;$(Get-Content ${Env:AZP_TOKEN_FILE})&quot; `
    --pool &quot;$(if (Test-Path Env:AZP_POOL) { ${Env:AZP_POOL} } else { &#039;Default&#039; })&quot; `
    --work &quot;$(if (Test-Path Env:AZP_WORK) { ${Env:AZP_WORK} } else { &#039;_work&#039; })&quot; `
    --replace

  Write-Host &quot;4. Running Azure Pipelines agent...&quot; -ForegroundColor Cyan

  .\run.cmd
}
finally
{
  Write-Host &quot;Cleanup. Removing Azure Pipelines agent...&quot; -ForegroundColor Cyan

  .\config.cmd remove --unattended `
    --auth PAT `
    --token &quot;$(Get-Content ${Env:AZP_TOKEN_FILE})&quot;
}</code></pre>



<p>接著就是準備我們要用的Dockerfile，這邊我以dotnet 5.0 sdk的Windows Server Core 2022映像檔為基底，它裡面包含了PowerShell與dotnet 5.0 sdk，並且我還要額外在Image裡面安裝Docker。若是需要dotnet core 3.1與其它OS基底映像檔的部份可以到<a href="https://hub.docker.com/_/microsoft-dotnet-sdk/" target="_blank" rel="noreferrer noopener">Docker hub的頁面</a>上去尋找相關的Tag：</p>



<pre class="wp-block-prismatic-blocks"><code class="language-dockerfile">FROM mcr.microsoft.com/dotnet/sdk:5.0-windowsservercore-ltsc2022

#在這底下加入要額外裝在Docker Image內的程式

SHELL [&quot;powershell&quot;, &quot;-Command&quot;, &quot;$ErrorActionPreference = &#039;Stop&#039;; $ProgressPreference = &#039;SilentlyContinue&#039;;&quot;]

RUN Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force
RUN Install-Module -Name DockerMsftProvider -Repository PSGallery -Force -verbose
RUN Install-Package -Name docker -ProviderName DockerMsftProvider -Force -verbose -ErrorAction SilentlyContinue; exit 0

#===========================================

WORKDIR /azp

COPY start.ps1 .

CMD powershell .\start.ps1</code></pre>



<p>準備好Dockerfile和start.ps1這兩個檔案之後，執行下面的指令建立映像檔：</p>



<pre class="wp-block-prismatic-blocks"><code class="language-docker">docker build -t devopsagent .</code></pre>



<p>完成Build Image的動作之後，透過下面的指令建立一個名為azure-agent的Container：</p>



<pre class="wp-block-prismatic-blocks"><code class="language-docker">docker run --name azure-agent -d -v \.\pipe\docker_engine:\.\pipe\docker_engine -e AZP_URL=[AzureDevOpsURL] -e AZP_TOKEN=[AzureDevOpsPAT] -e AZP_AGENT_NAME=[AzureDevOpsAgentName] IMAGE:TAG</code></pre>



<p>指令中比較特別的地方是透過mount的方式將host的docker轉給container內使用，也就是「-v \.\pipe\docker_engine:\.\pipe\docker_engine」這段，其它的除了IMAGE:TAG是根據上面的docker build所指定的Repository與Tag(預設為latest)之外，環境變數的部份則參考下面這張表：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1025" height="408" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/4582d3e6-devopsagent-containerenvironmentvariables.png?resize=1025%2C408&#038;ssl=1" alt="" class="wp-image-1265" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/4582d3e6-devopsagent-containerenvironmentvariables.png?w=1025&amp;ssl=1 1025w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/4582d3e6-devopsagent-containerenvironmentvariables.png?resize=300%2C119&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/4582d3e6-devopsagent-containerenvironmentvariables.png?resize=768%2C306&amp;ssl=1 768w" sizes="auto, (max-width: 1025px) 100vw, 1025px" /><figcaption>Azure DevOps Agent所使用的環境變數</figcaption></figure></div>



<p>五個環境變數中的最後兩個AZP_POOL、AZP_WORK是選擇性的，只有前三個是必須的，執行之後的結果如下：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="755" height="533" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/2af50f9a-devopsagent-runagentinwindowscontainer.png?resize=755%2C533&#038;ssl=1" alt="" class="wp-image-1268" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/2af50f9a-devopsagent-runagentinwindowscontainer.png?w=755&amp;ssl=1 755w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/2af50f9a-devopsagent-runagentinwindowscontainer.png?resize=300%2C212&amp;ssl=1 300w" sizes="auto, (max-width: 755px) 100vw, 755px" /><figcaption>Azure DevOps Agent執行在Windows Container中</figcaption></figure></div>



<p>從Azure DevOps中的Agent Pools列表中可以看到這個Agent：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="793" height="277" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/6ad9bba5-agentpools-default-wincontaineragent.png?resize=793%2C277&#038;ssl=1" alt="" class="wp-image-1271" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/6ad9bba5-agentpools-default-wincontaineragent.png?w=793&amp;ssl=1 793w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/6ad9bba5-agentpools-default-wincontaineragent.png?resize=300%2C105&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/6ad9bba5-agentpools-default-wincontaineragent.png?resize=768%2C268&amp;ssl=1 768w" sizes="auto, (max-width: 793px) 100vw, 793px" /></figure></div>



<p>進入查看Capabilities的部份也可以看到幾個比較不一樣的資訊，像是ComputerName是Docker產生的隨機名稱，還有docker的資訊：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="790" height="927" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/df70a783-agentpools-default-wincontaineragent-capabilities.png?resize=790%2C927&#038;ssl=1" alt="" class="wp-image-1274" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/df70a783-agentpools-default-wincontaineragent-capabilities.png?w=790&amp;ssl=1 790w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/df70a783-agentpools-default-wincontaineragent-capabilities.png?resize=256%2C300&amp;ssl=1 256w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/df70a783-agentpools-default-wincontaineragent-capabilities.png?resize=768%2C901&amp;ssl=1 768w" sizes="auto, (max-width: 790px) 100vw, 790px" /><figcaption>Azure DevOps Agent執行在Windows Container中的Capabilities資訊</figcaption></figure></div>



<p>至於為什麼需要將host的docker提供給Container中的docker使用，這部份則是為了讓Container中的docker可以共用host上的docker，從Container中的Agent執行docker build所產生的docker image也會儲存在host的docker images裡面，並且可以代替host執行docker run建立新的Container。不過這麼做也是有安全性的風險的，<a href="https://docs.microsoft.com/zh-tw/azure/devops/pipelines/agents/docker?view=azure-devops#use-docker-within-a-docker-container" target="_blank" rel="noreferrer noopener">官方就有提出警告</a>，是否要這麼做則是可以自行思考決定：</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1017" height="367" src="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/7582834f-waring-usedockerindocker.png?resize=1017%2C367&#038;ssl=1" alt="" class="wp-image-1277" srcset="https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/7582834f-waring-usedockerindocker.png?w=1017&amp;ssl=1 1017w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/7582834f-waring-usedockerindocker.png?resize=300%2C108&amp;ssl=1 300w, https://i0.wp.com/storage.googleapis.com/stateless-tech-uccu-website/2021/10/7582834f-waring-usedockerindocker.png?resize=768%2C277&amp;ssl=1 768w" sizes="auto, (max-width: 1017px) 100vw, 1017px" /></figure></div>



<p>會在這篇文章中這麼做的原因，純粹是為了提供Windows環境將docker轉給Container內使用的指令使用方式，因為這部份在微軟的文件頁面上似乎沒有提到(我忘了之前從哪裡看到的)。</p>
<p>這篇文章 <a href="https://tech.uccu.website/2021ironman-day21-build-windows-container-image-for-azure-devops-agent.html">【2021鐵人賽】建立自管的Azure DevOps Agent(Windows Container agent)</a> 最早出現於 <a href="https://tech.uccu.website">泰克哪裡去</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://tech.uccu.website/2021ironman-day21-build-windows-container-image-for-azure-devops-agent.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1235</post-id>	</item>
	</channel>
</rss>
