一、前言

上篇[1]主要介绍了利用csproj文件使用NuGet打包至ProGet的过程,并附上了用于在Jenkins上运行的python脚本。本篇的主要内容分为以下几点:

1. Nuspec与Nupkg的关系

2. dll文件该如何打包

3. P4python的几个操作

4. 融入jenkins

5. 本周关于与组长的讨论以及生活

二、Nuspec与Nupkg的关系

上篇我们说到,nuspec文件是nupkg的清单文件。但是有时候你会发现,明明你的项目里有依赖项(dependency),可你进行nuget spec操作后,发现清单文件里并没有项目中所包含的依赖项,这是为什么?为什么进行nuget pack操作后才会有依赖项,nupkg不是由清单文件nuspec才产生的吗??

首先,我们想想整个过程。

第一步,我们进入了项目文件所在的路径,在CMD中执行了nuget spec操作。根据官方文档[2] ,这时候其实是你在初始化生成一个清单文件,一些基本的信息都是Token填充的($xxx$这样的),如果你装了Nuget package explorer,双击nuspec你会发现有左右两侧内容,左侧是清单,右侧是package content。而package content中的内容却是你nuspec当前路径下的所有文件。根据官方文档,如果你没提供需要打包的文件,它就会把当前nuspec所在文件夹中的所有内容放在package content中。那为什么之后执行nuget pack又正确的将内容打包了呢?接着往下走。

第二步,将部分标签的值修改,防止打包失败,例如<tags><description><releaseNotes>,不是默认就行

第三步,执行nuget pack XXX.csproj操作。这是非常重要的操作,大家都知道csproj文件其实是个xml格式的文件,它会把整个项目的文件信息都以xml的形式记录,在执行这个操作的时候,AssemblyInfo.cs与csproj 文件共同提供信息给nuspec文件,使其清单与打包内容正确,这时候项目中的依赖项就会正确的显示在了包包中。

三、dll如何打包

关于dll 打包,这周感慨良多。一开始组长让我搞通打包流程,我用的是csproj的打包方式,然后组长要求必须是dll。这下好,出现思想上的矛盾了。。。

组长的想法是这样的:

    我的想法是这样的:

    

大家看到差别了吧,一个是在服务器上已经有一个制作好的nuspec文件,而我只需要在jenkins上执行修改版本号和打包上传即可。另一个是获取dll后,在本地生成nuspec文件再打包上传。看起来好像没什么太大区别哦,其实。。。差的挺多的。组长问,"你怎么知道你打包需要哪些dll?""让需要打包的人告诉我啊"“那好,我再问你,你为什么把需要打包的文件再以脚本方式写入nuspec,这是要干什么” “因为它们要打包在nupkg里啊” “你不会先编辑好nuspec嘛,这么多打包的内容用list写到nuspec里,在jenkins里这么干合适吗?”

其实组长是把打包者与上传者这两个角色进行了拆分,而我是把两者结合在了一起。假设一个打包者把nuspec文件以及相关的dll放在perforce服务器上,jenkins上的每一个人都可以执行打包上传任务,因为他不需要知道nuspec里面的内容,只需要更新个版本号就可以了。相反的,如果在jenkins上操作的并不是打包者,那他并不知道需要打进哪些dll,需要添加或删除哪些依赖项。那他就无法打包了。

注意:csproj打包方式与dll不同,只要获取csproj文件,就能执行自动化,因为AssemblyInfo.cs以及csproj文件已经能充分提供信息了。

四、P4python的几个操作

说实话,p4python官方[3]的几个例子做的有点渣,好歹说一下怎么checkout吧。。。没办法,根据手上现有的资料和网上看看国外的论坛,分享三个比较实用的操作吧。

(1) 把文件checkout到一个新的changelist中(可不是default哦)

  1. #checkout到一个新的changelist中
  2. desc ={"Description":p4description,"Change":"new"}
  3. p4.input = desc
  4. info = p4.run("change","-i")
  5. for s in info:
  6. changelistNumber =s.split(" ",)[]
  7. changelistId = changelistNumber
  8.  
  9. checkoutfiles=sys.argv[] #checkout的路径
  10. submittedFiles=[checkoutfiles] #所需要checkout的文件路径
  11. for submittedFile in submittedFiles:
  12. p4.run("edit",["-c"+""+changelistId,submittedFile])
  13. #checkout

(2) revertunchangedfiles

  1. def revertunchangedFile(p4,files):
  2. try:
  3. for file in files:
  4. p4.run("revert",[ "-a",file])
  5. except Exception as ex:
  6. return False

(3) revertfiles

  1. def revertFile(p4,files):
  2. try:
  3. for file in files:
  4. p4.run("revert",file)
  5. except Exception as ex:
  6. return False

五、融入jenkins

(1)以csproj的方式打包,重新整理

  1. # coding=gbk
  2. import os
  3. import sys
  4. import re
  5. from P4 import P4
  6.  
  7. def getdisc(projectpath): #获得项目文件的当前盘
  8. disc = projectpath.split(':', )[]
  9. disc = disc+":"
  10. return disc
  11.  
  12. def modifynuspec(projectfilepath,projectname): #修改nuspec文件内容
  13. tfile = projectfilepath+"\\"+projectname+".nuspec"
  14. f = open(tfile,'r')
  15. xmldata = f.read()
  16. xmldata = re.sub('\<description>(.*?)\</description>', '<description>'+projectname+'</description>', xmldata)
  17. xmldata = re.sub('\<tags>(.*?)\</tags>', '', xmldata)
  18. xmldata = re.sub('\<releaseNotes>(.*?)\</releaseNotes>','', xmldata) #删除里面不用的字段
  19. f.close()
  20. f = open(tfile,'w')
  21. f.write(xmldata)
  22. f.close()
  23.  
  24. def autoversion(projectpath): #替换版本
  25. assemblyInfoFile = projectpath+"\\Properties\\AssemblyInfo.cs"
  26. lines= open(assemblyInfoFile, 'r+', encoding='iso-8859-15').readlines()
  27. flen=len(lines)-
  28. for i in range(flen):
  29. if lines[i].startswith("[assembly: AssemblyVersion"):
  30. versioncode = lines[i].split('"', )[] #获得当前assemblyinfo的
  31. break
  32. oldVersion = versioncode
  33. splitedVersion = oldVersion.split('.')
  34. lastSubVersion = int(splitedVersion[])
  35. lastSubVersion +=
  36. splitedVersion[] = str(lastSubVersion)
  37. newVersion = '.'.join(splitedVersion) #将当前的assemblyVersion+
  38. if not os.path.exists(assemblyInfoFile):
  39. return
  40. fileContent = open(assemblyInfoFile, 'r+', encoding='iso-8859-15').read()
  41. fileContent = fileContent.replace(oldVersion,newVersion) #把版本替换完重写文件
  42. file = open(assemblyInfoFile,'w+', encoding='iso-8859-15')
  43. file.write(fileContent)
  44. file.flush()
  45. file.close()
  46. return newVersion
  47.  
  48. def revertunchangedFile(p4,files):
  49. try:
  50. for file in files:
  51. p4.run("revert",[ "-a",file])
  52. except Exception as ex:
  53. return False
  54.  
  55. def revertFile(p4,files):
  56. try:
  57. for file in files:
  58. p4.run("revert",file)
  59. except Exception as ex:
  60. return False
  61.  
  62. def findNugetpack(projectfilepath,searchKeywords):
  63. li = os.listdir(projectfilepath)
  64. for filename in li:
  65. if filename.endswith(".nupkg") and searchKeywords in filename:
  66. nupkgpath = projectfilepath+"\\"+ filename
  67. return nupkgpath
  68.  
  69. if __name__ == '__main__':
  70. if len(sys.argv)!=:
  71. sys.exit(-)
  72.  
  73. #连接P4并同步文件
  74. p4 = P4()
  75. p4.port = sys.argv[1] #端口号
  76. p4.user =sys.argv[2] #用户
  77. p4.password = sys.argv[3] #密码
  78. p4.client =sys.argv[4] #本地盘
  79. p4.connect()
  80. #连接P4并同步文件
  81.  
  82. #打包参数设置
  83. NuGetpath =sys.argv[5] #NuGet.exe路径
  84. Projectfilepath =sys.argv[6] #项目路径
  85. Projectname =sys.argv[7] #项目名称
  86. ProGetSourceUrl =sys.argv[8] #上传的ProGet地址
  87. ProGetAdmin =sys.argv[9] #ProGet用户名
  88. ProGetPassword =sys.argv[10] #ProGet密码
  89. #打包参数设置
  90.  
  91. p4description = sys.argv[] #P4checkout时的描述
  92.  
  93. #checkout到一个新的changelist中
  94. desc ={"Description":p4description,"Change":"new"}
  95. p4.input = desc
  96. info = p4.run("change","-i")
  97. for s in info:
  98. changelistNumber =s.split(" ",)[]
  99. changelistId = changelistNumber
  100.  
  101. checkoutfiles=sys.argv[] #checkout的路径
  102. submittedFiles=[checkoutfiles] #所需要checkout的文件路径
  103. for submittedFile in submittedFiles:
  104. p4.run("edit",["-c"+""+changelistId,submittedFile])
  105. #checkout
  106.  
  107. # 改变版本
  108. Newversion = autoversion(Projectfilepath)
  109. # 改变版本
  110.  
  111. ProGetAPIKey = sys.argv[] #API key
  112. try:
  113. #打包
  114. NuGetdisc = getdisc(NuGetpath)
  115. ProjectDisc = getdisc(Projectfilepath)
  116. Projectnuspec =Projectfilepath+"\\"+Projectname+".nuspec"
  117. if not os.path.exists(Projectnuspec):
  118. os.system(''+NuGetdisc+'&&cd '+NuGetpath+'&&nuget setApiKey '+ProGetAPIKey+'')
  119. os.system(''+ProjectDisc+'&&cd '+Projectfilepath+'&&nuget spec')
  120. modifynuspec(Projectfilepath,Projectname)
  121. Projectnamecsproj = Projectname+".csproj"
  122. os.system(''+ProjectDisc+'&&cd '+Projectfilepath+'&&nuget pack '+Projectnamecsproj+' -Build')
  123.  
  124. SearchKeywords=sys.argv[] #搜索关键词
  125. Nupkgpath = findNugetpack(Projectfilepath,SearchKeywords)
  126. os.system(''+NuGetdisc+'&&cd '+NuGetpath+'&&nuget push '+Nupkgpath+' '+ProGetAPIKey+' -Source '+ProGetSourceUrl+' -ApiKey '+ProGetAdmin+':'+ProGetPassword+'')
  127. #打包
  128.  
  129. revertunchangedFile(p4,submittedFiles)
  130. p4.run("change",["-d"],changelistId)
  131. except Exception as ex:
  132. revertFile(p4,submittedFiles)
  133. p4.run("change",["-d"],changelistId)
  134. p4.disconnect()

(2)以dll的方式打包

  1. # coding=gbk
  2. import os
  3. import sys
  4. import re
  5. import xml.dom.minidom
  6. import win32api
  7.  
  8. from P4 import P4
  9.  
  10. def getdisc(projectpath): #获得项目文件的当前盘
  11. disc = projectpath.split(':', )[]
  12. disc = disc+":"
  13. return disc
  14.  
  15. def Checknode(filepath,nodename):
  16. dom = xml.dom.minidom.parse(filepath)
  17. root = dom.documentElement
  18. for rt in root.childNodes:
  19. for rt1 in rt.childNodes:
  20. if rt1.nodeName == nodename:
  21. for node in rt1.childNodes:
  22. return node.nodeValue
  23.  
  24. def getFileVersion(file_name):
  25. info = win32api.GetFileVersionInfo(file_name, os.sep)
  26. ms = info['FileVersionMS']
  27. ls = info['FileVersionLS']
  28. version = '%d.%d.%d.%04d' % (win32api.HIWORD(ms), win32api.LOWORD(ms), win32api.HIWORD(ls), win32api.LOWORD(ls))
  29. return version
  30.  
  31. def modifynuspec(projectnuspec,dllfilepath):
  32. tfile = projectnuspec
  33. f = open(tfile,'r')
  34. xmldata = f.read()
  35. #oldversion = Checknode(tfile,"version") 按照默认版本号加1(预留)
  36. #listindex=int(len(oldversion.split("."))-)
  37. #newversion = int(oldversion.split(".")[listindex])+
  38. #newversion = oldversion[:-]+str(newversion)
  39. dllversion = getFileVersion(dllfilepath) #按照dll版本号
  40. xmldata = re.sub('\<version>(.*?)\</version>', '<version>'+dllversion+'</version>', xmldata)
  41. f.close()
  42. f = open(tfile,'w')
  43. f.write(xmldata)
  44. f.close()
  45.  
  46. def findNugetpack(nuspecfilepath,searchKeywords):
  47. li = os.listdir(nuspecfilepath)
  48. for filename in li:
  49. if filename.endswith(".nupkg") and searchKeywords in filename:
  50. nupkgpath = nuspecfilepath+"\\"+ filename
  51. return nupkgpath
  52.  
  53. if __name__ == '__main__':
  54. if len(sys.argv)!=:
  55. sys.exit(-)
  56.  
  57. #连接P4并同步文件
  58. p4 = P4()
  59. p4.port = sys.argv[1]
  60. p4.user = sys.argv[2]
  61. p4.password = sys.argv[3]
  62. p4.client = sys.argv[4]
  63. p4.connect()
  64. #连接P4并同步文件
  65.  
  66. #打包参数设置
  67. NuGetpath =sys.argv[5]
  68. Nuspecfilepath =sys.argv[6]
  69. Nuspecfilename = sys.argv[7]
  70. ProGetSourceUrl = sys.argv[8]
  71. ProGetAdmin =sys.argv[9]
  72. ProGetPassword =sys.argv[19]
  73. ProGetApiKey=sys.argv[]
  74. #打包参数设置
  75.  
  76. #打包
  77. NuGetdisc = getdisc(NuGetpath)
  78. ProjectDisc = getdisc(Nuspecfilepath)
  79. Projectnuspec =Nuspecfilepath+"\\"+Nuspecfilename+".nuspec"
  80. Dllfilepath = sys.argv[]
  81. if os.path.exists(Projectnuspec):
  82. modifynuspec(Projectnuspec,Dllfilepath)
  83. Projectnuspecname = Nuspecfilename+".nuspec"
  84. os.system(''+ProjectDisc+'&&cd '+ Nuspecfilepath+'&&nuget pack '+Projectnuspecname+'')
  85. Nupkgpath = findNugetpack(Nuspecfilepath,Nuspecfilename)
  86. os.system(''+NuGetdisc+'&&cd '+NuGetpath+'&&nuget push '+Nupkgpath+' '+ProGetApiKey+' -Source '+ProGetSourceUrl+' -ApiKey '+ProGetAdmin+':'+ProGetPassword+'')
  87. else:
  88. sys.exit(-)
  89. p4.disconnect()

六、与组长的沟通以及生活

工作快俩月了。这半个月过得不太顺心,在工作与生活中都意识到了自己的不足。就拿打包这事来说吧,组长本想培养我自我探索自我理清思路的能力,可我只是把每个具体的点搞清楚了,却没有从整体流程去思考,比如dll打包过程中的想法,这是个能力的缺失点。用打刀塔的09的话说“缺少大菊观”。刚进公司我在组A,A组的领导让我实现基本的小模块功能就行,到了组B,开始搞整体流程的时候就蒙蔽了。

在学校,导师教会了我迎难而上,坚韧不拔的科研精神,因为有时候搞科研就是那一套复杂的方程组,你必须用一些方式去解,没有其他余地。在公司,组长教会了我灵活变通的去解决问题,从一个更高的层次去想每个流程是怎么样的,该以一个最有效率的方法去解决问题,而不是制造问题。

组长人特别好,每次都不厌其烦的给我洗脑,我挺愧疚的,好多次我都在想为什么不能做的更完美些,然后又给自己挖了个大坑,做了许多重复的事情。组长说,“要当一个有思想的程序员,不然就只是搬代码。很多时候应该想想,我为什么这么做,我做这件的事的意义在哪儿。”

生活上,这个月感情崩了,该来的还是要来,好聚好散,彼此都祝福了对方。

这个月唯一的好消息是,毕业前发的一篇SCI总算要出刊了,看到样稿非常开心,特别感谢编辑们的辛勤排版。还有一篇关于算法的SCI还在审。。。都快5个月了我也是醉了。

最后,感谢我的组长!!!并祝各位博友能一切顺利,人生不如意之事十之八九,还是要以积极心态去面对,我相信只要肯努力,肯动脑,终究会成功的。有什么可以讨论的欢迎留言,多多指教~

References:

[1]  http://www.cnblogs.com/lovecsharp094/p/5527204.html

[2]  https://docs.nuget.org/create/nuspec-reference

[3]  https://www.perforce.com/perforce/doc.current/manuals/p4script/03_python.html

作者:airforce094

出处:http://www.cnblogs.com/lovecsharp094/p/5551120.html

转载请注明原文出处 , 谢谢合作

使用NuGet打包并发布至ProGet过程 (打包再次详解)【下篇】的更多相关文章

  1. 使用NuGet打包并发布至ProGet过程 (步骤详细,附python脚本)【上篇】

    一.基本知识 (1)NuGet : NuGet是一个为大家所熟知的Visual Studio扩展,通过这个扩展,开发人员可以非常方便地在Visual Studio中安装或更新项目中所需要的第三方组件, ...

  2. 【NuGet】使用NuGet打包并发布至ProGet过程 (打包再次详解)【下篇】

    一.前言 上篇[1]主要介绍了利用csproj文件使用NuGet打包至ProGet的过程,并附上了用于在Jenkins上运行的python脚本.本篇的主要内容分为以下几点: 1. Nuspec与Nup ...

  3. 【NuGet】使用NuGet打包并发布至ProGet过程 (步骤详细,附python脚本)【上篇】

    一.基本知识 (1)NuGet : NuGet是一个为大家所熟知的Visual Studio扩展,通过这个扩展,开发人员可以非常方便地在Visual Studio中安装或更新项目中所需要的第三方组件, ...

  4. 全网最详细的PLSQL Developer + Oracle client的客户端 或者 PLSQL Developer + Oracle server服务端的下载与安装过程(图文详解)

    不多说,直接上干货! 环境说明: 本地没有安装Oracle服务端,oracle服务端64位,是远程连接,因此本地配置PLSQL Developer64位. Oracle database使用在本机部署 ...

  5. VBA的过程及参数详解

    VBA的过程及参数详解 VBA中的过程(Procedure)有两种,一种叫函数(Function),另外一种叫子程序(Subroutine),分别使用Function和Sub关键字.它们都是一个可以获 ...

  6. 直播预告 | 猪齿鱼V1.1发布,线上新功能详解邀您参加

    2021年11月11日,数智化效能平台猪齿鱼 Choerodon发布 V1.1版本,多项功能新增或优化,多管齐下,全面提升团队工作效能! 通过提供体系化方法论和协作.测试.DevOps及容器工具,猪齿 ...

  7. PHP安装过程中问题详解

    安装Apace时我就犯了一个大错误.因为我的母语是JAVA,我以为Tomcat就是Apache.其实不然,Tomcat是给Java用的,处理JSP等的动态页面. 而PHP则是单纯的用Apache安装A ...

  8. Android中measure过程、WRAP_CONTENT详解以及 xml布局文件解析流程浅析

    转自:http://www.uml.org.cn/mobiledev/201211221.asp 今天,我着重讲解下如下三个内容: measure过程 WRAP_CONTENT.MATCH_PAREN ...

  9. TCP协议的3次握手与4次挥手过程【深度详解】

    一.前沿 尽管TCP和UDP都使用相同的网络层(IP),TCP却向应用层提供与UDP完全不同的服务.TCP提供一种面向连接的.可靠的字节流服务.面向连接意味着两个使用TCP的应用(通常是一个客户和一个 ...

随机推荐

  1. 《C#图解教程》读书笔记之四:类和继承

    本篇已收录至<C#图解教程>读书笔记目录贴,点击访问该目录可获取更多内容. 一.万物之宗:Object (1)除了特殊的Object类,其他所有类都是派生类,即使他们没有显示基类定义. ( ...

  2. 一个App完成入门篇(四)- 完成反馈页面

    上一节中我们学会了如何通过点击不同按钮切换页面,这节专注于完成反馈页面的功能以及细节动画. 导入项目 添加新组件 同步新组件 完成页面布局 输入时加动画效果 弹出日期选择 直接引用UI页面 将要学习的 ...

  3. Java程序员的日常——存储过程知识普及

    存储过程是保存可以接受或返回用户提供参数的SQL语句集合.在日常的使用中,经常会遇到复杂的业务逻辑和对数据库的操作,使用存储过程可以进行封装.可以在数据库中定义子程序,然后把子程序存储在数据库服务器, ...

  4. Android开发学习之路-下拉刷新以及GridView的使用

    GridView是类似于ListView的控件,只是GridView可以使用多个列来呈现内容,而ListView是以行为单位,所以用法上是差不多的. 主布局文件,因为要做下拉刷新,所以加了一个Prog ...

  5. Atitit 图像处理知识点  知识体系 知识图谱v2

    Atitit 图像处理知识点  知识体系 知识图谱v2 霍夫变换(Hough Transform) 霍夫变换是图像处理中从图像中识别几何形状的基本方法之一,应用很广泛,也有很多改进算法.主要用来从图像 ...

  6. 阿里云ecs Linux下安装MySQL后设置root密码 【转】

    方法一:最简单的方法,也是安装完mysql后,系统提示的方法.使用mysqladmin来完成.shell> mysqladmin -u root password "newpwd&qu ...

  7. ubuntu下在apache部署python站点

    ubuntu下在apache部署python站点 我的是ubuntu14 32为的虚拟机,默认安装的python为3.4 环境:apache + mysql + django + python3 软件 ...

  8. Git使用相关

    Git使用相关 使用git这么久还是时不时碰到小问题,根本原因在于没有仔细研究和做笔记 Git修改remote地址 之前一直使用的ssh的地址,估计是没配置好,每次都需要输密码烦死了,今天看到个用ht ...

  9. 【WP 8.1开发】电子罗盘

    罗盘,估计也不用我过多介绍,学过初中物理的都知道,不管是指南针,还是指北针,其本质就是用来辨别方向的. 操作电子罗盘伟感器也不复杂,主要就是两个角度: 1.当前方向与磁北的夹角: 2.当前方向与地北的 ...

  10. sublime text2小技巧

    1. 文件快速导航: 这是sublime上面很好用的功能之一,ctrl+p可以调出窗口,菜单上的解释是gotoanythings ,确实如其所言,调出窗口后,直接输入关键字,可以在已打开的项目文件夹中 ...