Windows + Jenkins + .NetFramework + SVN 持续部署
Windows + Jenkins + .NetFramework + SVN 持续部署
环境准备
服务端环境
安装 Windows 服务器
1、阿里云购买临时服务器
2、使用虚拟机安装
可以使用VMWare、VisualBox等虚拟机管理工具来安装环境,本教程将使用虚拟机安装,且 Windows Server 版本为 2016。
Windows Server 2016 安装包:https://download.microsoft.com/download/B/5/F/B5F1A996-B590-45FD-BA99-DE7E745A0882/14393.0.161119-1705.RS1_REFRESH_SERVER_EVAL_X64FRE_ZH-CN.ISO
安装 IIS
必须安装 .net framework 4.6
。
安装 MSBuild
若要在没有 Visual Studio 的系统上安装 MSBuild,请转到 Visual Studio 下载并向下滚动到“所有下载”,然后展开 “Visual Studio 2019 工具” 。 安装 Visual Studio 2019 生成工具(包含 MSBuild)
在安装程序中,确保选择要为工作负载使用的 MSBuild 工具,然后选择“安装”。
其他版本:MSBuild V14.0
安装 SVN Server 和 SVN Client
SVN Server
1、下载 SVN 安装包
下载地址:https://www.visualsvn.com/downloads/
根据操作系统版本选择 32 位或 64 位安装包,这里选择 64 位安装包。
2、创建用户及 Repository
创建用户:
创建 Repository:
SVN Client
安装 Visual SVN
下载地址:https://www.visualsvn.com/downloads/
跟着安装流程走即可。
安装 nuget.exe CLI
nuget.exe
CLI(即 nuget.exe
)是适用于 Windows 的命令行实用工具,可提供所有 NuGet 功能;它也可以使用存在一些限制的 Mono 在 Mac OSX 和 Linux 上运行。
要了解如何在 nuget.exe
CLI 中使用基本命令,请参阅使用 nuget.exe CLI 安装并使用包。
Windows
备注
NuGet.exe 5.0 及更高版本需要 .NET Framework 4.7.2 或更高版本才能执行。
- 请访问 nuget.org/downloads,并选择 NuGet 3.3 或更高版本(2.8.6 与 Mono 不兼容)。 始终建议使用最新版。若要将包发布到 nuget.org,版本至少必须是 4.1.0。
- 每次下载都直接下载
nuget.exe
文件。 让浏览器将文件保存到选定文件夹。 此文件不 是安装程序;如果直接在浏览器中运行,就不会看到任何内容。 - 将文件夹添加到
nuget.exe
中放置 PATH 环境变量的位置,这样就可以从任意位置使用 CLI 工具。
由于我们使用的是 .net framework 4.6,下载 nuget.exe v4.9.4 ,然后放在 C:\nuget
目录下。
然后再配置环境变量。
验证效果:
nuget
安装 .net framework 4.6 Developer Pack
正常情况下,不允许在服务器上安装开发软件,而由于需要在服务器上构建项目,那就需要安装 Developer Pack。
下载地址:https://dotnet.microsoft.com/download/dotnet-framework/net46
客户端环境
安装 Visual Studio 及 Visual SVN
1、安装 Visual Studio 2019
这里安装 Visual Studio 2019 社区版,大家也可以安装专业版。
官网下载:https://visualstudio.microsoft.com/zh-hans/vs/
2、安装 Visual SVN
下载地址:https://www.visualsvn.com/downloads/
跟着安装流程走即可。
项目准备
1、Checkout 和 项目目录结构初始化
在本地电脑上,创建目录 D:\test\helloworld
(你也可以在任意位置创建)
-
将上面 SVN 的仓库 helloworld 签出。
-
初始化项目目录结构,如下:
- build:放构建的 bat 脚本
- lib:放第三方库
- src:放项目源代码
- test:放测试代码
2、创建一个初始项目
3、按 F5 运行,查看效果
4、编写 MSBuild
在 build 目录下创建两个文件。
build.bat:
SET MSBUILD="C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin"
SET APPCMD="C:\WINDOWS\System32\inetsrv\appcmd.exe"
SET YEAR=%date:~0,4%
SET MONTH=%date:~5,2%
SET DAY=%date:~8,2%
SET HOUR=%time:~0,2%
SET MINUTE=%time:~3,2%
SET SECOND=%time:~6,2%
%appcmd% stop site helloworld
%MSBUILD% build.proj /target:Default /property:Rebuild=true;Configuration=Debug;RELEASE=false;PatchVersion=%month: =0%%day: =0%;BuildVersion=%hour: =0%%minute: =0%;SolutionName=src\HelloWorld.sln;DeployDir=..\..\..\websites\helloworld
%appcmd% start site helloworld
这个批处理主要做了3件事:
- 设置变量:SET MSBUILD 等
- 停止/开始IIS站点:appcmd stop[start] site helloworld,更多请查看https://www.cnblogs.com/sharesdk/p/11290597.html
- 构建项目:msbuild build.proj
- /target:Default:表示要执行名字是 Default 的 Target,具体看 build.proj
- /property:表示要传进 build.proj 的参数,以
key=value
为一对,用分号(;)隔开
build.proj:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Default"
xmlns='http://schemas.microsoft.com/developer/msbuild/2003' ToolsVersion="4.0">
<!-- 设置属性值,后面可以使用 $(...) 来调用 -->
<!-- Condition 表示只有当条件成立,才进行设置,一般作为默认值。如果 msbuild.exe 执行时传值进来,就不会使用此默认值 -->
<PropertyGroup>
<MajorVersion Condition="$(MajorVersion) == ''">1</MajorVersion>
<MinorVersion Condition="$(MinorVersion) == ''">0</MinorVersion>
<PatchVersion Condition="$(PatchVersion) == ''">0</PatchVersion>
<BuildVersion Condition="$(BuildVersion) == ''">0</BuildVersion>
</PropertyGroup>
<PropertyGroup>
<BuildSolutionDir>$(MSBuildProjectDirectory)\..</BuildSolutionDir>
<SrcDir>$(BuildSolutionDir)\src</SrcDir>
<DeployDir Condition="$(DeployDir) == ''">deploy</DeployDir>
<SolutionName Condition="$(SolutionName) == ''">..\xx.sln</SolutionName>
<Configuration Condition="$(Configuration) == ''">Debug</Configuration>
<!--是否需要重新编译(会删除编译输出目录),编译时间较长-->
<Rebuild Condition="$(Rebuild) == ''">false</Rebuild>
<Version>$(MajorVersion).$(MinorVersion).$(PatchVersion).$(BuildVersion)</Version>
<UnstableTag Condition="$(RELEASE) == ''">-unstable</UnstableTag>
<PackageVersion>$(MajorVersion).$(MinorVersion).$(PatchVersion).$(BuildVersion)</PackageVersion>
<EnvVersion>$(MajorVersion).$(MinorVersion).$(PatchVersion)</EnvVersion>
</PropertyGroup>
<!-- Build依赖顺序,即执行顺序 -->
<PropertyGroup>
<DoBuildSolutionsDependsOn>
UpdateSVNReporitory;
BuildSolutions;
BackupWebsite;
DeployWebsite;
</DoBuildSolutionsDependsOn>
</PropertyGroup>
<!-- 默认任务 -->
<Target Name="Default" DependsOnTargets="$(DoBuildSolutionsDependsOn)" />
<!-- 从 SVN 更新最新代码 -->
<Target Name="UpdateSVNReporitory">
<Message Text="*****正在从SVN库拉取最新代码*****" Importance="high"/>
<Exec Command="svn update $(BuildSolutionDir)\src" ></Exec>
</Target>
<!--编译任务-->
<Target Name="BuildSolutions">
<Message Text="*****正在还原引用的程序包*****" Importance="high"/>
<Exec Command="nuget restore $(BuildSolutionDir)\$(SolutionName) "></Exec>
<!--排除web\bin目录垃圾组件影响-->
<Message Text="*****正在清空站点BIN目录文件和dist目录文件*****" Importance="high"/>
<RemoveDir Directories="$(BuildSolutionDir)\src\HelloWorld.Web\bin"></RemoveDir>
<RemoveDir Directories="$(BuildSolutionDir)\lib\dist"></RemoveDir>
<MSBuild Projects="$(BuildSolutionDir)\$(SolutionName) " Targets="Build"
Properties="Configuration=$(Configuration);Version=$(PackageVersion)" ContinueOnError="true"/>
</Target>
<!--备份原站点目录下的配置文件-->
<Target Name="BackupWebsite">
<Message Text="*****正在备份站点配置文件*****" Importance="high"/>
<Exec Command="XCOPY $(DeployDir)\Web.config $(DeployDir)\backup\ /y" ContinueOnError="true"></Exec>
<!--备份目录下上传的图片文件等资料-->
<!--<Exec Command="XCOPY $(BuildSolutionDir)\$(DeployDir)\files $(BuildSolutionDir)\$(DeployDir)\backup\ /y" ContinueOnError="true"></Exec>-->
</Target>
<!--部署站点任务-->
<Target Name="DeployWebsite">
<!--正在清空原部署站点-->
<Message Text="*****正在清空站点目录及文件*****" Importance="high"/>
<RemoveDir Directories="$(DeployDir)\bin" ContinueOnError="true"></RemoveDir>
<Message Text="*****正在合并站点文件*****" Importance="high"/>
<Exec Command="XCOPY $(BuildSolutionDir)\src\HelloWorld.Web\App_Data $(BuildSolutionDir)\lib\dist\App_Data\ /y /s /e"></Exec>
<Exec Command="XCOPY $(BuildSolutionDir)\src\HelloWorld.Web\Content $(BuildSolutionDir)\lib\dist\Content\ /y /s /e"></Exec>
<Exec Command="XCOPY $(BuildSolutionDir)\src\HelloWorld.Web\fonts $(BuildSolutionDir)\lib\dist\fonts\ /y /s /e"></Exec>
<Exec Command="XCOPY $(BuildSolutionDir)\src\HelloWorld.Web\Scripts $(BuildSolutionDir)\lib\dist\Scripts\ /y /s /e"></Exec>
<Exec Command="XCOPY $(BuildSolutionDir)\src\HelloWorld.Web\Views $(BuildSolutionDir)\lib\dist\Views\ /y /s /e"></Exec>
<Exec Command="XCOPY $(BuildSolutionDir)\src\HelloWorld.Web\bin $(BuildSolutionDir)\lib\dist\bin\ /y /s /e"></Exec>
<Exec Command="XCOPY $(BuildSolutionDir)\src\HelloWorld.Web\Web.config $(BuildSolutionDir)\lib\dist\ /y /D:m-d-"></Exec>
<Exec Command="XCOPY $(BuildSolutionDir)\src\HelloWorld.Web\favicon.ico $(BuildSolutionDir)\lib\dist\ /y /D:m-d-"></Exec>
<Exec Command="XCOPY $(BuildSolutionDir)\src\HelloWorld.Web\Global.asax $(BuildSolutionDir)\lib\dist\ /y /D:m-d-"></Exec>
<Message Text="*****正在拷贝站点文件*****" Importance="high"/>
<Exec Command="XCOPY $(BuildSolutionDir)\lib\dist $(DeployDir)\ /y /s /e"></Exec>
<Message Text="*****正在还原站点备份组件*****" Importance="high"/>
<Exec Command="XCOPY $(DeployDir)\backup $(DeployDir)\ /y /s /e" ContinueOnError="true"></Exec>
</Target>
</Project>
更多查看官网:https://docs.microsoft.com/zh-cn/visualstudio/msbuild/msbuild-batching?view=vs-2019
关于 XCOPY
的命令请查看:https://www.jianshu.com/p/83e5cb09d55b
注:在构建时,可能会出现 MSBuild 版本问题,看这篇文章解决:https://my.oschina.net/u/3797416/blog/3164082
再把 C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Microsoft\VisualStudio\v16.0
(注意 Visual Studio 版本不同,位置不同,这里是 Visual Studio 2019 社区版) 复制到源代码管理下的 BuildTargets
文件夹。
5、创建站点
在本地电脑创建站点 helloworld
注意:站点路径,这里与 build.bat 的参数 DeployDir 有关,站点可以放在任意地方,但是需要同时修改 build.bat
的参数 DeployDir
。
6、构建效果
在 build 目录下打开 cmd 或 powershell
在浏览器上打开 http://localhost:5000/
7、提交代码
将目录下的所有内容提交到 svn 服务器。
8、服务器签出代码
jenkins
什么是 jenkins?
Jenkins 是一个独立的开源自动化服务器,可用于自动化各种任务,如构建,测试和部署软件。Jenkins可以通过本机系统包 Docker 安装,甚至可以通过安装 Java Runtime Environment 的任何机器独立运行。
安装 jenkins
安装 JDK
下载 JDK8:https://www.oracle.com/cn/java/technologies/javase/javase-jdk8-downloads.html
由于官网下载比较慢,且要登录才能下载。可以使用以下地址下载:
链接:https://pan.baidu.com/s/1vJnHF1OMm_XuLNJvcOkoIg
提取码:zxin
配置 java
- 新建环境变更 JAVA_HOME
变量名:JAVA_HOME
变量值:C:\Java\jdk1.8.0_281
- 新建/修改 CLASSPATH 变量
变量名:CLASSPATH
变量值:.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;
- 修改 Path 变量
新建两条路径:
%JAVA_HOME%\bin
%JAVA_HOME%\jre\bin
验证 java 安装成功
java -version
下载 jenkins war 包
jenkins 的Web应用程序 ARchive(WAR)文件版本可以安装在任何支持 java 的操作系统或平台上。
要下载并运行 jenkins 的 WAR 文件版本,请执行以下操作:
- 将最新的稳定Jenkins WAR包 下载到您计算机上的相应目录。
- 在下载的目录内打开一个终端/命令提示符窗口到。
- 运行命令java -jar jenkins.war
- 浏览 http://localhost:8080 并等到 Unlock Jenkins 页面出现。
- 继续使用 Post-installation setup wizard 后面步骤设置向导。
将最新的稳定Jenkins WAR包下载到您计算机上的相应目录。
Notes:
- 不像在Docker中下载和运行有Blue Ocean的Jenkins,这个过程不会自动安装Blue Ocean功能, 这将分别需要在jenkins上通过 Manage Jenkins > Manage Plugins安装。 在Getting started with Blue Ocean有关于安装Blue Ocean的详细信息 。.
- 您可以通过
--httpPort
在运行java -jar jenkins.war
命令时指定选项来更改端口。例如,要通过端口9090访问Jenkins,请使用以下命令运行Jenkins:java -jar jenkins.war --httpPort=9090
配置 jenkins
1、运行 jenkins
cd /jenkins # 切换到 jenkins.war 的目录
java -jar jenkins.war # 运行,默认是 8080 端口
2、jenkins 初始化
- 输入密码
- 选择 ”安装推荐插件“
- 等待安装
- 创建第一个管理员用户
- 填写 jenkins url,默认是 http://localhost:8080,可以修改为自己外网的 IP 或者使用域名。
- 进入 jenkins
配置 jenkins svn
- 安装 svn plugin
- 等待安装完成
创建构建项目
- 点击 ”新建 Item“,创建一个 free style 类型项目
- 填写基本信息
- 设置工作空间
点击 “高级”,然后设置自定义的工作空间 C:\test\helloworld
。
- 配置源码管理
填写 Repository URL,这里使用的是本地的路径。
选择/添加 Credentials:
- 配置 ”构建“
选择 ”Execute Windows batch command“:
cd build
call build.bat
- 点击保存
立即构建
- 创建站点
- 点击 "Build Now"
- 点击 “构建历史”,再点击 “控制台输出”
- 查看到 SUCCSS,表示构建成功
- 在浏览器打开 http://localhost:5000
至此,一个简单的 .net 项目的持续部署配置完成。
如何自动构建
上面的构建是需要手动点击 "Build Now" 才执行的,正常情况下,我们希望是提交代码就触发构建。
由于 SVN 没有 Github、Gitee等 Git 工具的 push hook 功能,只能曲线求国,通过定时器来触发,判断版本号是否有更新。
总结
本教程主要是面向比较传统的 .net framework 开发方式,将其改造成持续部署。当然了,现在很多都已经在使用 git 系列的代码管理工具了,后面我们再来说说 .net core + git 的持续部署方式。