背景
最近入職了一家新公司,公司各個方面都讓我非常的滿意,我也懷著緊張與興奮的心情入職後,在第一天接到了領導給我的第一個任務——把整個專案的依賴引用重新整理並實施專案的CI/CD。
本篇的重點主要分享這次在Windows平臺使用Jenkins做.Net Framework的自動化,真是所謂一波N折。
有關注過我的部落格的朋友們,應該知道我之前都是在Linux上實施.Net Core,好不容易把Linux技能點起來,現在玩回Windows+.Net Framework感覺有一種回到鑽木取火的年代。
在實施過程中讓我感悟最多的是,dotnet core命令的便捷性,Linux運維的便捷性,下文我有很多構建指令碼都是shell指令碼來的,當時想著學習一次就不需要學習bat指令碼了,最終還是躲不過。
在遠端傳送並遠端執行命令我折騰得最久,開始想著用FTP與Telnet,誰知道Telnet命令沒有附帶賬號密碼引數,指令碼不好寫,後改成PsExec.exe,使用過程中很多奇怪的問題,後來不得不去折騰OpenSSH,說實話還是SSH好用,直接代替了FTP與PsExec。中間還遇到Jenkins使用本機賬號執行的許可權問題。所有“坑”的我在下面步驟儘可能給大家規避了。
引用整理
專案(包含所以依賴的專案)依賴引用丟失,主要體現以下幾點:
- 官方依賴包沒有使用NuGet
- 內部專案引用通過本地引用,專案沒有拉取則編譯失敗
- NuGet包多個版本的引用
- 同屬一個解決方案,但是專案分散到各個倉庫
依賴沒有規範化對軟體工程主要帶來以下幾點影響:
- 缺少程式碼或者程式碼路徑不一致則無法正常編譯通過
- 對於新人同事不友好
- 實現CI/CD會有很大的阻力
解決方案與順序:
- 整理元件庫到統一解決方案,日後有需要拆分再按需拆分,優先保證需要依賴的在一個方案。
- 實現元件庫的自動釋出到私有Nuget
- 整理API專案的依賴,拋棄以前本地依賴的方式,統一使用Nuget
- 實現API專案的自動釋出到IIS
工具準備
工具名稱 | 下載地址 | 描述 |
jdk-8u261-windows-i586.exe | https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html | Jenkins依賴 |
nuget.exe CLI | https://dist.nuget.org/win-x86-commandline/latest/nuget.exe | 釋出、還原.Net依賴包 |
MsBuild | https://visualstudio.microsoft.com/zh-hans/vs/community/ | msbuild在vs安裝程式裡 |
Jenkins | https://www.jenkins.io/zh/download/ | |
git | https://git-scm.com/download/win | |
OpenSSH服務端 | https://github.com/PowerShell/Win32-OpenSSH/releases | 遠端傳輸與遠端執行命令 |
物理部署圖
文章會分享跨網路環境的場景,我們使用了Gitee的企業倉儲,Jenkins與Nuget.Server會放在阿里雲伺服器,機房會開放一臺伺服器與阿里雲伺服器進行SSH的通訊。
以上是基本的資訊概要,下面會進入具體的實施步驟。
NuGet.Server的部署
新建一個ASP.Net Web應用程式(.NetFramework),並選擇空模板,搜尋NuGet.Server選擇3.4.1版本安裝後,開啟Web.config檔案設定apiKey,然後就可以部署到47.115.111.58的IIS了。
官方部署文件可以檢視 https://docs.microsoft.com/zh-cn/nuget/hosting-packages/nuget-server
安裝MsBuild
在伺服器47.115.111.58開啟通過上面表格的連結下載VS的安裝包,點開單個元件選項卡,勾選Msbuild,等待一會即可完成。
MsBuild的命令參考:https://docs.microsoft.com/zh-cn/visualstudio/msbuild/msbuild-command-line-reference?view=vs-2019
配置nuget.exe CLI
在伺服器47.115.111.58根據上面表格nuget.exe CLI,下載後放到一個合適的檔案目錄,並在【環境變數配置】配置好路徑,開啟cmd並輸入指令nuget help出現以下畫面證明成功。
相關指令參考:https://docs.microsoft.com/zh-cn/nuget/reference/nuget-exe-cli-reference
新增NuGet還原源配置項
在部署Jenkins伺服器47.115.111.58,開啟C:\Windows\system32\config\systemprofile\AppData\Roaming\NuGet\NuGet.Config,沒有的化可以自己建一個,輸入以下指令碼。
如果沒有配置好,接下來的應用專案可能會編譯時還原包失敗導致無法編譯通過。
<?xml version="1.0" encoding="utf-8"?> <configuration> <packageSources> <add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" /> <add key="私有NuGet服務" value="http://47.115.11.58:8008/nuget" /> <add key="Microsoft Visual Studio Offline Packages" value="C:\Program Files (x86)\Microsoft SDKs\NuGetPackages\" /> </packageSources> </configuration>
安裝OpenSSH服務端
cd C:\tools\OpenSSH-Win64 #安裝服務端 powershell.exe -ExecutionPolicy Bypass -File install-sshd.ps1 #啟動服務 net start ssh-agent sc config ssh-agent start= auto net start sshd sc config sshd start= auto #防火牆開啟22埠 #大於等於 Windows Server 2012 New-NetFirewallRule -Name sshd -DisplayName 'OpenSSH Server (sshd)' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22 #小於 Windows Server 2012 netsh advfirewall firewall add rule name=sshd dir=in action=allow protocol=TCP localport=22
這樣就可以通過administrator賬號或者管理員賬號在客戶端用ssh登入了。
以上是各個伺服器基本依賴安裝。
安裝Jenkins
在伺服器47.115.111.58,先把jdk與git安裝好後,點開Jenkins安裝,選擇預設路徑下一步,遇到設定服務登入賬戶的時候,必須選擇以administrator安裝,不然後續會有很多執行的許可權問題。
如果點選Test Credentials無法通過,可以在執行輸入mmc開啟策略編輯器,並在計算機配置-[windows設定]-[安全設定]-[本地策略]-[使用者許可權分配]-[作為服務登入],填寫administrator或者您的管理員賬號。
接著點選下一步等待完成後,會彈出一個localhost:8080的頁面,根據他的指示初始化介面就可以了。輸入完管理員賬號後這個時候可以去修改workspace的地址,當時我沒有修改地址的時候,因為路徑有特殊字元導致無論如何都無法用msbuild編譯通過。
開啟C:\Windows\System32\config\systemprofile\AppData\Local\Jenkins.jenkins\config.xml,修改workspaceDir屬性的值為C:/jenkins_workspace/${ITEM_FULL_NAME},儘可能給一個簡單純英文的路徑。
配置Jenkins
在主介面點選【Manage Jenkins】-【Configure System】介面,定位到Shell,輸入您剛安裝的git路徑的sh.exe,C:\Program Files\Git\bin\sh.exe
同樣介面定位到SSH Servers點選Add Server把剛剛安裝OpenSSL的伺服器47.115.151.108填寫進去,賬號密碼是47.115.151.108伺服器管理員的賬號密碼。
在主介面點選【Manage Jenkins】-【Global Tool Configuration】介面,定位到Git,輸入您剛安裝的git路徑的git.exe,C:\Program Files\Git\bin\git.exe
到這裡Jenkins的配置基本上完成了。
自動釋出元件包到NuGet
新建Freestyle project,並在【原始碼管理】、【構建】填入您的構建資訊,構建指令碼我是儲存在伺服器上,因為儲存在伺服器上更加可靠。
構建指令碼shell示例
#!/bin/bash #指令碼開始執行 echo '指令碼開始執行' base_path=C:/jenkins_workspace/Librariy nuget_url=http://47.115.111.58:8008/nuget nuget_api_key=B82D6DDB-C6F958E8C945 nuget restore $base_path for project_name in $base_path/* do project_path=$project_name package_path=$project_path/packages rm -rf $package_path nuget pack $project_path -Build -IncludeReferencedProjects -Properties Configuration=Release -OutputDirectory $package_path && nuget push -ApiKey $nuget_api_key -Source $nuget_url $package_path/*.nupkg if [ $? -eq 0 ]; then echo '釋出成功:'$project_name'' else echo '釋出失敗:'$project_name'' fi done echo '指令碼執行結束'
以上釋出元件包到私有NuGet的步驟就實施完畢了。
自動釋出Web應用到IIS
新建Freestyle project,並在【原始碼管理】、【構建】填入您的構建資訊。[Publish Over SSH]外掛跟OpenSSL能把編譯好的檔案傳送到相應的伺服器,並執行對應的叢集分發指令碼。
示例構建shell指令碼
#!/bin/bash echo '指令碼開始執行' base_path=C:/jenkins_workspace/API project_path=$base_path/API.csproj publish_path=$base_path/publish rm -rf $publish_path nuget restore $base_path && MSBuild.exe $project_path -t:"rebuild;publish;ResolveReferences;_CopyWebApplication" -p:"Configuration=Release;OutputPath=$publish_path" if [ $? -eq 0 ]; then echo '釋出成功:'$project_name'' else echo '釋出失敗:'$project_name'' fi echo '指令碼執行結束'
示例分發bat指令碼
記得在區域網把相應伺服器的共享資料夾啟動
net use \\192.168.1.2\app "password" /user:"administrator" xcopy/a/s/h/y C:\app\ftp\SFNovelAPI \\192.168.1.2\app\API
net use \\192.168.1.3\app "password" /user:"administrator"
xcopy/a/s/h/y C:\app\ftp\SFNovelAPI \\192.168.1.3\app\API
xcopy/a/s/h/y C:\app\ftp\SFNovelAPI C:\app\SFNovelAPI
結束
以上記錄並分享了我在Windows實施自動化的過程與步驟,如果大家有更好的建議與提議,可以在下方評論反饋給我。
除了以上使用SSH的方式之外,在Windows平臺還可以使用Web Deploy進行遠端釋出與執行命令,參考文件:https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/dd569106(v=ws.10)