Jenkins 自动构建Job

1.创建Job

  • 登录Jenkins,点击新建Item,创建项目
  • 选择Pipeline,然后点击确定
  • 接下来主要在Pipeline script中编写脚本

2.签出Git仓库

2.1配置Git账号

  • Manage Jenkins->Security->Credentials 在凭据界面,选择全局
  • 添加凭据,添加Git用户名和密码,ID是等下需要使用的。

2.2 编写Git签出脚本

  • 点击 Build Now,就会执行刚刚的脚本。并在Jenkin主目录->workspace->项目名称 下签出对应的Git仓库

3.配置何时执行

3.1 手动执行

直接点击 Build Now 按钮,会立马执行。

3.2 间隔执行

  • 定时获取Git代码,代码更新则构建 (每5分钟执行一次)
  • 定时构建,不管代码有没有更新(每5分钟执行一次)

3.3 Git有更新主动推送构建

  • 生成触发地址
  • 在Git中配置Web 钩子
    使用上面的地址(JENKINS_URL:替换成地址,TOKEN_NAME:替换为身份证令牌Vue1),配置到Git的Web钩子中。可以点击测试,看返回结果。
  • 禁用跨站请求伪造(解决错误:No valid crumb was included in the request)
    Git仓库的Web 钩子界面,点击测试推送,返回的响应信息中,提示:No valid crumb was included in the request。
    在Manage Jenkins -> Script Console中执行
bash 复制代码
hudson.security.csrf.GlobalCrumbIssuerConfiguration.DISABLE_CSRF_PROTECTION = true
  • 安装Build Authorization Token Root 插件(解决错误:Authentication required)
    Git仓库的Web 钩子界面,点击测试推送,返回的响应信息中,提示:Authentication required。
    Manage Jenkins->Plugins 搜索Build Authorization Token Root,并点击安装
  • Git仓库添加允许列表
    找到gitea的安装目录gitea\custom\conf,编辑app.ini文件

4.编写构建脚本

bash 复制代码
node {
    try {
      stage('SCM') {
        git branch: 'dev', credentialsId: 'Test', url: 'http://127.0.0.1:3000/Test.git'
        // 更新子模块
        bat 'git submodule update --init --recursive'
        bat 'git submodule update --remote'
      }
      stage('BUILD') {
        bat 'dotnet build'
      }
      stage('DEPLOY') {
        bat 'dotnet publish  Test.csproj -c Release -o D:/publish/Test'
      }
    }  catch(Exception e){
        
    }
}

5.发送邮件

当构建失败时,发送邮件通知。

5.1 配置邮件信息

  • 创建邮箱凭据,步骤参考【配置Git账号】
  • 配置邮箱服务器信息 Manage Jenkins->System->Extended E-mail Notification
  • 编写邮件发送脚本
bash 复制代码
node {
      stage('SCM') {
          emailext (
            subject: "编译失败: ${env.JOB_NAME} [${env.BUILD_NUMBER}]",
            body: """
                <p><b>${env.JOB_NAME} [${env.BUILD_NUMBER}]</b> <span style="color:red;">编译失败</span>.</p>
                <p>详情: <a href="${env.BUILD_URL}console">${env.BUILD_URL}console</a></p>
                <br>
            """,
            to: "[email protected]",
            mimeType: 'text/html',
            from: "[email protected]"
        )
      }
}

6.发布.NET Core 程序

一般Jenkins与应用站点不在同一台服务器,我们可以通过共享文件夹的方式,再使用命令,复制文件到应用站点服务器。

  • 编写powershell脚本文件 copy.ps1
powershell 复制代码
if (!(Test-Path "Y:\")) { 
net use Y: \\192.168.1.100\website /user:administrator 123456
}
Start-Sleep 5
$source = "D:\publish\Test"  
$destination = "Y:\Test"  
$timeThreshold = (Get-Date).AddHours(-1) # 设置时间阈值为一个小时前  
  
# 定义要排除的文件扩展名或名称  
$excludeExtensions = @(".pdb")  
$excludeNames = @("tempfile.txt", "backup.log")  
  
# 使用Get-ChildItem获取文件,并通过管道传递给Where-Object进行筛选  
Get-ChildItem -Path $source -Recurse |   
    Where-Object {   
        # 检查文件的最后写入时间是否早于阈值  
        #$_.LastWriteTime -lt $timeThreshold -and  
        # 检查文件扩展名是否不在排除列表中  
        (-not $excludeExtensions.Contains($_.Extension.ToLower())) -and  
        # 检查文件名是否不在排除列表中  
        (-not $excludeNames.Contains($_.Name.ToLower()))  
    } |   
    ForEach-Object {  
    # 构造目标路径  
    $destinationPath = $_.FullName.Replace($source, $destination)  
    # 如果当前项是文件夹,则创建目标文件夹  
    if ($_.PSIsContainer) {  
        New-Item -ItemType Directory -Path $destinationPath -Force | Out-Null  
    } else {  
        # 否则,复制文件  
        Copy-Item -Path $_.FullName -Destination $destinationPath -Force  
    }  
}
  • 编写jenkins脚本
bash 复制代码
powershell  "D:/publish/Test.ps1"

7.启动/停止应用站点

替换.NET Core程序时,需要先停止IIS之后才能替换。我们可以在IIS中部署另外一个程序,该程序可以用来停止/启动应用程序池和应用站点。当我们需要发布.NET Core程序时,我们可以先停止应用程序和应用站点,发布成功后,在启动应用程序池和应用站点。

以下代码需要安装Microsoft.Web.Administration、System.ServiceProcess.ServiceController类库

csharp 复制代码
    [Route("api/[controller]/[Action]")]
    [ApiController]
    public class IISController : ControllerBase
    {
        public string GetName()
        {
            return "IIS";
        }

        /// <summary>
        /// 启动站点
        /// </summary>
        /// <param name="siteName"></param>
        /// <returns></returns>
        [HttpGet("{siteName}")]
        public bool StartSite(string siteName)
        {
            var webManager = new ServerManager();
            var startSite = webManager.Sites[siteName];
            if (startSite == null)
            {
                return false;
            }
            if (startSite.State.Equals(ObjectState.Stopped))
            {
                startSite.Start();
            }

            return true;
        }

        /// <summary>
        /// 停止站点
        /// </summary>
        /// <param name="siteName"></param>
        /// <returns></returns>
        [HttpGet("{siteName}")]
        public string StopSite(string siteName)
        {
            var webManager = new ServerManager();
            var startSite = webManager.Sites[siteName];
            if (startSite == null)
            {
                return "不存在";
            }
            if (startSite.State.Equals(ObjectState.Started))
            {
                startSite.Stop();
            }

            return "成功了";
        }

        /// <summary>
        /// 启动应用池
        /// </summary>
        /// <param name="poolName"></param>
        /// <returns></returns>
        [HttpGet("{poolName}")]
        public bool StartPool(string poolName)
        {
            var webManager = new ServerManager();
            var applicationPool = webManager.ApplicationPools[poolName];
            if (applicationPool == null)
            {
                return false;
            }
            if (applicationPool.State.Equals(ObjectState.Stopped))
            {
                applicationPool.Start();
            }

            return true;
        }

        /// <summary>
        /// 停止应用池
        /// </summary>
        /// <param name="poolName"></param>
        /// <returns></returns>
        [HttpGet("{poolName}")]
        public bool StopPool(string poolName)
        {
            var webManager = new ServerManager();
            var applicationPool = webManager.ApplicationPools[poolName];
            if (applicationPool == null)
            {
                return false;
            }
            if (applicationPool.State.Equals(ObjectState.Started))
            {
                applicationPool.Stop();
            }

            return true;
        }

        /// <summary>
        /// 启动服务
        /// </summary>
        /// <param name="serviceName"></param>
        /// <returns></returns>
        [HttpGet("{serviceName}")]
        public IActionResult StartService(string serviceName)
        {
            try
            {
                using (var serviceController = new ServiceController(serviceName))
                {
                    if (serviceController.Status == ServiceControllerStatus.Stopped || serviceController.Status == ServiceControllerStatus.Paused)
                    {
                        serviceController.Start();
                        serviceController.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromSeconds(30));
                    }

                    return Ok($"Service {serviceName} started successfully.");
                }
            }
            catch (Exception ex)
            {
                return StatusCode(500, $"An error occurred while trying to start the service: {ex.Message}");
            }
        }

        /// <summary>
        /// 启动服务
        /// </summary>
        /// <param name="serviceName"></param>
        /// <returns></returns>
        [HttpGet("{serviceName}")]
        public IActionResult StopService(string serviceName)
        {
            try
            {
                using (var serviceController = new ServiceController(serviceName))
                {
                    if (serviceController.Status == ServiceControllerStatus.Running)
                    {
                        serviceController.Stop();
                        serviceController.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(30));
                    }

                    return Ok($"Service {serviceName} stopped successfully.");
                }
            }
            catch (Exception ex)
            {
                return StatusCode(500, $"An error occurred while trying to stop the service: {ex.Message}");
            }
        }

    }

8.完整Jenkins脚本

bash 复制代码
node {
    try {
      stage('SCM') {
        git branch: 'dev', credentialsId: 'Test1', url: 'http://127.0.0.1:3000/Test.git'
        // 更新子模块
        bat 'git submodule update --init --recursive'
        bat 'git submodule update --remote'
      }
      stage('BUILD') {
        bat 'dotnet build'
      }
      stage('DEPLOY') {
        bat 'dotnet publish  Test/Test.csproj -c Release -o D:/publish/Test'
      }
      stage('STOPSITE') {
        bat "curl -X GET \"http://192.168.1.100:2000/api/iis/StopSite/Test\""
      }
      stage('STOPPOOL') {
        bat "curl -X GET \"http://192.168.1.100:2000/api/iis/StopPool/Test\""
      }
      stage('COPY') {
        powershell  "D:/publish/test.ps1"
      }
      stage('STARTPOOL') {
        bat "curl -X GET \"http://192.168.1.100:2000/api/iis/StartPool/Test\""
      }
      stage('STARTSITE') {
        bat "curl -X GET \"http://192.168.1.100:2000/api/iis/StartSite/Test\""
      }
    }  catch(Exception e){
         // 构建失败时捕获异常并发送邮件
        emailext (
            subject: "编译失败: ${env.JOB_NAME} [${env.BUILD_NUMBER}]",
            body: """
                <p><b>${env.JOB_NAME} [${env.BUILD_NUMBER}]</b> <span style="color:red;">编译失败</span>.</p>
                <p>详情: <a href="${env.BUILD_URL}console">${env.BUILD_URL}console</a></p>
                <br>
            """,
            to: "[email protected]",
            mimeType: 'text/html',
            from: "[email protected]"
        )
    }
}
相关推荐
kfhj2 小时前
负载均衡是什么,Kubernetes如何自动实现负载均衡
运维·kubernetes·负载均衡
MarkHD5 小时前
第八天 - paramiko/ssh模块 - 远程服务器管理 - 练习:批量服务器命令执行工具
运维·服务器·ssh
GalaxyPokemon6 小时前
MySQL基础 [一] - Ubuntu版本安装
linux·运维·ubuntu
柳鲲鹏7 小时前
UBUNTU编译datalink
linux·运维·ubuntu
三阶码叟7 小时前
centos7 yum install docker 安装错误
运维·docker·容器
CaliXz8 小时前
野草云防火墙风险分析及 Docker 使用注意事项
运维·docker·容器
计算机学无涯8 小时前
Docker 命令简写配置
运维·docker·容器
kk小源8 小时前
Docker常用操作教程
运维·docker·容器
Y淑滢潇潇9 小时前
RHCSA Linux 系统创建文件
linux·运维·服务器
奔跑的废柴9 小时前
Jenkins学习(B站教程)
运维·学习·jenkins