IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> 【DEVOPS】实现Inno Setup打包自动化 -> 正文阅读

[系统运维]【DEVOPS】实现Inno Setup打包自动化

借助Jenkins + Ansible,辅助一系列的COC实现Inno Setup打包自动化。

1. 流程图

相关的交互流程图参见:CI - Inno Setup打包

为了方便之后的叙述和读者的理解,以下穷举涉及到的服务器:

  1. 安装了Jenkins的Linux服务器250。
  2. 安装了自动部署工具Ansible的Linux服务器254。
  3. 安装了Inno Setup的WIndows服务器3。
  4. 安装了FTP Server的Windows服务器3。(服务器资源紧张,所以我们将Inno Setup和FTP Server的安装合并在了同一台服务器上;不过按照我们的设计来说,这两者并没有隐含依赖关系)

2. 环境准备

Jenkins和Ansible的基本安装和配置不是本文的重点,以下列举其他的一些关键性的前期环境准备。

2.1 lftp工具安装

在本文的设计实现中,我们需要使用lftp来实现如下效果:

  1. 将用户上传的待打包软件推送到FTP服务器上,以供Inno Setup打包时使用。这一步操作发生在250服务器。
  2. 将上一步推送到FTP服务器的待打包软件拉取到本地,以执行Inno Setup打包工作。这一步操作发生在3服务器。

因此这里我们需要分别在250服务器,3服务器上安装lftp:

# 250服务器(Centos7)
yum install lftp

# 3服务器(Windows Server2012)
1. 从 https://lftp.nwgat.ninja/lftp-4.4.15/  下载对应版本的压缩包
2. 解压到任意目录
3. 将以上目录添加到Windows环境变量
4. 验证: lftp /?
2.2 svn命令行工具

践行DevOps"一切皆版本控制"的思想,我们将Inno Setup脚本进行了源代码版本控制,因此每次打包前我们都需要从svn拉取最新的代码。

关于svn命令行工具,得益于对于zentao的了解,我们可以直接从zentao的安装目录下获取免安装的svn命令行工具(这一步操作也发生在3服务器上)。

2.3 7zip工具安装

本工具的安装发生在3服务器上,目的是为了在使用Inno Setup生成打包之后,将打包过程中收集的一些必要元信息汇总为专门的元文件,然后使用7zip压缩工具将它们合并为一个压缩包,以便于之后的版本追溯。

2.4 Inno Setup安装

作为主角的 Inno Setup,其安装操作发生在3服务器上,我们将借助其命令行工具来实现打包操作。

作为一款打包工具,Inno Setup的安装过程不出意料地非常简单 —— 一路"下一步"即可。

安装完毕之后,将安装路径添加到环境变量Path中,并进行如下验证:

ISCC.exe /?
2.5 Jenkins File Params

现阶段我们暂时没有实现C++应用的集成编译,所以在本文介绍的自动化流程中,待打包软件的提供还是由用户自行上传的,因此我们需要Jenkins的File Params支持。

安装过程参见 Jenkins Pipeline使用File parameter,具体的使用参见本文下面的细节。

3. 各脚本

脚本涉及三大块:

  1. Inno Setup打包脚本
  2. Jenkins Pipeline脚本
  3. Ansible部署脚本
3.1 Inno Setup打包脚本
; Script generated by the Inno Setup Script Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!

#define MyAppName "ZzCamera"
#define MyAppVersion "1.0.0"
#define MyAppPublisher "ZZZZ, Inc."
#define MyAppURL "http://www.ZZZZ.com/"
#define MyAppExeName "ZZZZ-camera.exe"

; // 以本脚本所在的目录为基础, 进行相对路径跳转
#define CompileBasePath ".\..\"         
#define AppFolderNameFromOutside "ZZZZ-camera-"  ; 由外部传入


[Setup]
; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications.
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
AppId={{33CD0F63-DE20-44E9-BF1D-8A82D45B97FD}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
;AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName=D:/{#MyAppName}
DisableProgramGroupPage=yes
; Uncomment the following line to run in non administrative install mode (install for current user only.)
;PrivilegesRequired=lowest
OutputDir={#CompileBasePath}\compileOutput
OutputBaseFilename=ZZZZ-camera-installer-{#MyAppVersion}
SetupIconFile={#CompileBasePath}\{#AppFolderNameFromOutside}\ZZZZCamera.ico
Compression=lzma
SolidCompression=yes
WizardStyle=modern

DefaultGroupName={#MyAppName}

[Languages]
Name: "chinesesimp"; MessagesFile: "compiler:Default.isl"

; 写入注册表进行protocol注册,以实现在浏览器输入 ZZZZCamera:// 打开应用的效果
[Registry]
Root: HKCR; Subkey: "ZZZZCamera"; Flags: uninsdeletekeyifempty; ValueType: expandsz; ValueName: "URL Protocol"; ValueData: "{app}\{#MyAppExeName}"
Root: HKCR; Subkey: "ZZZZCamera"; Flags: uninsdeletekeyifempty; ValueType: expandsz; ValueName: ""; ValueData: "ZZZZCamera"
Root: HKCR; Subkey: "ZZZZCamera\shell"; Flags: uninsdeletekeyifempty
Root: HKCR; Subkey: "ZZZZCamera\shell\open"; Flags: uninsdeletekeyifempty
Root: HKCR; Subkey: "ZZZZCamera\shell\open\command"; Flags: uninsdeletekeyifempty; ValueType: expandsz; ValueName: ""; ValueData: "{app}\{#MyAppExeName} %1"

[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: checkablealone
;Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: checkablealone

[Files]
Source: "{#CompileBasePath}\{#AppFolderNameFromOutside}\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#CompileBasePath}\{#AppFolderNameFromOutside}\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "{#CompileBasePath}\code\image\*"; DestDir: "{app}\image"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "{#CompileBasePath}\code\bin\uninstall.bat"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#CompileBasePath}\code\bin\stop.bat"; DestDir: "{app}"; Flags: ignoreversion
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
;Source: "{#CompileBasePath}\dll\ISTask.dll"; DestDir: {app}; Flags: ignoreversion; Attribs: hidden
;Source: "{#CompileBasePath}\dll\psvince.dll";DestDir: {app}; Flags: dontcopy noencryption 
; Source: compiler:psvince.dll   compile前缀为内置值,,,,

[Icons]
;Name: "{autoprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}";IconFilename: "{app}\ZZZZCamera.ico"; 
Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}";IconFilename: "{app}\ZZZZCamera.ico"; Tasks: desktopicon
Name:  "{group}\{#MyAppName}-启动服务"; Filename: "{app}\{#MyAppExeName}";IconFilename: "{app}\ZZZZCamera.ico"; 
Name:  "{group}\{#MyAppName}-停止服务"; Filename:"{app}\stop.bat";Tasks:desktopicon;IconFilename: "{app}\image\stop.ico";
Name:  "{group}\{#MyAppName}-卸载"; Filename:"{app}\uninstall.bat";IconFilename: "{app}\image\uninstall.ico";

[Run]
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent

[UninstallRun]
Filename: "{app}\uninstall.bat"; RunOnceId: "DelService"

[UninstallDelete]
Type: files; Name: "{app}\uninstall.bat"

; 新版本安装时,先卸载旧有安装版本
[Code]
// https://blog.csdn.net/qq_36190858/article/details/84893661 卸载之后再安装
function InitializeSetup(): boolean;  
var  
  ResultStr: String;  
  ResultCode: Integer;  
begin  
  if RegQueryStringValue(HKLM, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{33CD0F63-DE20-44E9-BF1D-8A82D45B97FD}_is1', 'UninstallString', ResultStr) then  
    begin
      
      if MsgBox('ZZZZCamera进程正在运行,需要先卸载它.', mbConfirmation, MB_OKCANCEL) = IDOK then
        begin
          ResultStr := RemoveQuotes(ResultStr);
          //MsgBox(ResultStr, mbConfirmation, MB_OKCANCEL) ;
          // ResultStr :  D:\ZZZZCamera\uninstall000.exe
          Exec('taskkill', '/f /t /fi "imagename eq ZZZZ-camera.exe"', '', SW_HIDE, ewWaitUntilTerminated, ResultCode);   
          Exec(ResultStr, '/silent', '', SW_HIDE, ewWaitUntilTerminated, ResultCode);
          Result := true;
        end
      else
        begin
          Result:= false;
        end;
    end
  else  
    begin
      Result := true;
    end;    
end;

// https://blog.csdn.net/qq_36190858/article/details/84894346  【卸载前删除某些文件】
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
begin
  if CurUninstallStep = usDone then
    begin
    DelTree(ExpandConstant('{app}'), True, True, True);
    end;
end;
3.2 Jenkins Pipeline脚本
properties([
    parameters([
        choice(name: 'SERVER', choices: ['windows_3'], description: '编译服务器'),
        file(name: 'FILE_TO_COMPILE',  description: '需要被Inno Setup打包的压缩包,请将待打包的文件夹打包为zip,直接根目录打包,不要包含一个根文件夹')  
    
    ])
])

library "jenkinsci-unstashParam-library"
@Library('global-shared-library') _
def msgTools = new org.devops.tools()
def file_upload
pipeline {
   agent any
   stages {
        stage('Initialize') {
            steps {
				echo "清空工作空间"
				cleanWs()
            }
        }
        stage('validate file params') {
            steps {
				script{
				    
				    if(!"${FILE_TO_COMPILE}".endsWith(".zip")){
				        error "请将待打包的文件夹打包为zip,直接根目录打包,不要包含一个根文件夹" 
				    }
				    println "${FILE_TO_COMPILE}"
				}
            }
        }
		stage('接收上传的文件'){
            steps {
				script{
                    file_upload = unstashParam "FILE_TO_COMPILE"
					// 统一压缩包的名称
					sh "cd ${WORKSPACE} && mv ${file_upload} ZZZZ-camera-needComiple.zip"
					file_upload = "ZZZZ-camera-needComiple.zip"
					sh "pwd ${file_upload}"
					// sh "cat ${file_upload}"
                    // sh "cat ${file_upload} |jq '.'"
					//sh "ls ${WORKSPACE}"
                    //println "curr file is: ${file_upload}"
                }
            }
        }

		stage('上传文件到Inno Setup编译服务器.3'){
            steps {
				sh """
					lftp 172.16.3.3 -p 21 -u webadmin,webadmin  -e "lcd ${WORKSPACE}/; cd /ZZZZCamera/;put ${file_upload}; quit"                                   
				"""
            }
        }
        stage('inno-setup-compile') {
            steps {          
                
                sshPublisher(
                    publishers: [
                        sshPublisherDesc(
                        configName: 'ansibleServerIn254',
                        transfers: [
                            sshTransfer(
                            excludes: '',
                            execCommand: '''
                              cd /etc/ansible/playbooks/common
                              ansible-playbook windows_inno_setup_common.yaml \
                              -e "TARGET=${SERVER}"
                            ''',
                            )
                        ],
                        verbose: true
                    )
                 ]
              )
            }
        }
		/*  */
		stage('show artifact download url'){
			 steps {
				 script{
			    		msgTools.PrintMes("ftp://xxx.xx.x.3/ZZZZCamera/ZZZZ-camera-installer-1.0.0.exe" , "red")
			 		}
				}
		}
		
   }
   post{
   
        success {
            echo 'pipeline post success'            
        }
   }                
  
}

3.3 Ansible 部署脚本
---
- hosts: "{{ TARGET  | default('windows_3') }}"
  vars:
    WORKPATH: "E:/_XXXXX/_compileTempOfInnoSetup"
    ZIP_FILE_NAME_INNER: "{{ZIP_FILE_NAME | default('ZZZZ-camera-needComiple.zip')}}"
    ZIP_FILE_NAME_FIRST_INNER: "{{ZIP_FILE_NAME_INNER.split('.')[0]}}"
  vars_files:
    - vars-common.json
  tasks:
    ##### Preparation steps
    # 我们将 inno setup打包脚本进行了版本管理, 所以每次执行inno setup打包前我们都拉取一次最新代码
    - name: remove old inno-setup-script in windows-server-compiler
      win_file: path="{{WORKPATH}}/code/" state=absent
    - name: download install.iss script of inno-setup from svn
      win_shell: |
        # sliksvn/ 是从 zentao的安装包中拷贝而来
        cd E:/_devops/sliksvn/
        ./svn.exe  checkout https://xxxx.xxx.xxx.xxx:888/svn/DEVOPS/ZZZZ-installer-camera {{WORKPATH}}  --username ccccc --password cccc
    # 这里我们为了优化执行速度,没有采用ftp拉取的方式
    - name: move package_will_compile to dest location {{WORKPATH}}
      win_shell: |
        mv D:\FTP\1WEB_SAVE\ZZZZCamera\{{ZIP_FILE_NAME_INNER}} {{WORKPATH}}\{{ZIP_FILE_NAME_INNER}} -Force
    - name: rm folder folder {{WORKPATH}}/{{ZIP_FILE_NAME_FIRST_INNER}}/
      win_file: path="{{WORKPATH}}/{{ZIP_FILE_NAME_FIRST_INNER}}/" state=absent
      ignore_errors: yes
    - name: unzip {{ZIP_FILE_NAME_INNER}} to {{WORKPATH}}
      win_unzip: creates=yes src="{{WORKPATH}}\{{ZIP_FILE_NAME_INNER}}" dest="{{WORKPATH}}\{{ZIP_FILE_NAME_FIRST_INNER}}" delete_archive=yes
    - name: call ISCC.exe to compile
      win_shell: |
        $env:path = $env:path + "; E:/_devops/Inno Setup 6"
        cd {{WORKPATH}}/code/
        echo "begin call iscc.exe"
        ISCC.exe /DAppFolderNameFromOutside={{ZIP_FILE_NAME_FIRST_INNER}} .\install.iss
    - name: push package to ftp server
      win_command: |
        lftp 172.16.3.3 -p 21 -u webadmin,webadmin  -e "lcd {{WORKPATH}}/compileOutput/; cd /ZZZZCamera/;put ZZZZ-camera-installer-1.0.0.exe; quit"

4. Links

  1. Jenkins Pipeline使用File parameter
  2. lftp For Windows
  3. Inno Setup官网
  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2021-07-22 14:38:04  更:2021-07-22 14:39:45 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/3 19:53:37-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码