一、前言

上篇[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哦)

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

(2) revertunchangedfiles

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

(3) revertfiles

def revertFile(p4,files):
try:
for file in files:
p4.run("revert",file)
except Exception as ex:
return False

五、融入jenkins

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

 # coding=gbk
import os
import sys
import re
from P4 import P4 def getdisc(projectpath): #获得项目文件的当前盘
disc = projectpath.split(':', )[]
disc = disc+":"
return disc def modifynuspec(projectfilepath,projectname): #修改nuspec文件内容
tfile = projectfilepath+"\\"+projectname+".nuspec"
f = open(tfile,'r')
xmldata = f.read()
xmldata = re.sub('\<description>(.*?)\</description>', '<description>'+projectname+'</description>', xmldata)
xmldata = re.sub('\<tags>(.*?)\</tags>', '', xmldata)
xmldata = re.sub('\<releaseNotes>(.*?)\</releaseNotes>','', xmldata) #删除里面不用的字段
f.close()
f = open(tfile,'w')
f.write(xmldata)
f.close() def autoversion(projectpath): #替换版本
assemblyInfoFile = projectpath+"\\Properties\\AssemblyInfo.cs"
lines= open(assemblyInfoFile, 'r+', encoding='iso-8859-15').readlines()
flen=len(lines)-
for i in range(flen):
if lines[i].startswith("[assembly: AssemblyVersion"):
versioncode = lines[i].split('"', )[] #获得当前assemblyinfo的
break
oldVersion = versioncode
splitedVersion = oldVersion.split('.')
lastSubVersion = int(splitedVersion[])
lastSubVersion +=
splitedVersion[] = str(lastSubVersion)
newVersion = '.'.join(splitedVersion) #将当前的assemblyVersion+
if not os.path.exists(assemblyInfoFile):
return
fileContent = open(assemblyInfoFile, 'r+', encoding='iso-8859-15').read()
fileContent = fileContent.replace(oldVersion,newVersion) #把版本替换完重写文件
file = open(assemblyInfoFile,'w+', encoding='iso-8859-15')
file.write(fileContent)
file.flush()
file.close()
return newVersion def revertunchangedFile(p4,files):
try:
for file in files:
p4.run("revert",[ "-a",file])
except Exception as ex:
return False def revertFile(p4,files):
try:
for file in files:
p4.run("revert",file)
except Exception as ex:
return False def findNugetpack(projectfilepath,searchKeywords):
li = os.listdir(projectfilepath)
for filename in li:
if filename.endswith(".nupkg") and searchKeywords in filename:
nupkgpath = projectfilepath+"\\"+ filename
return nupkgpath if __name__ == '__main__':
if len(sys.argv)!=:
sys.exit(-) #连接P4并同步文件
p4 = P4()
p4.port = sys.argv[1] #端口号
p4.user =sys.argv[2] #用户
p4.password = sys.argv[3] #密码
p4.client =sys.argv[4] #本地盘
p4.connect()
#连接P4并同步文件 #打包参数设置
NuGetpath =sys.argv[5] #NuGet.exe路径
Projectfilepath =sys.argv[6] #项目路径
Projectname =sys.argv[7] #项目名称
ProGetSourceUrl =sys.argv[8] #上传的ProGet地址
ProGetAdmin =sys.argv[9] #ProGet用户名
ProGetPassword =sys.argv[10] #ProGet密码
#打包参数设置 p4description = sys.argv[] #P4checkout时的描述 #checkout到一个新的changelist中
desc ={"Description":p4description,"Change":"new"}
p4.input = desc
info = p4.run("change","-i")
for s in info:
changelistNumber =s.split(" ",)[]
changelistId = changelistNumber checkoutfiles=sys.argv[] #checkout的路径
submittedFiles=[checkoutfiles] #所需要checkout的文件路径
for submittedFile in submittedFiles:
p4.run("edit",["-c"+""+changelistId,submittedFile])
#checkout # 改变版本
Newversion = autoversion(Projectfilepath)
# 改变版本 ProGetAPIKey = sys.argv[] #API key
try:
#打包
NuGetdisc = getdisc(NuGetpath)
ProjectDisc = getdisc(Projectfilepath)
Projectnuspec =Projectfilepath+"\\"+Projectname+".nuspec"
if not os.path.exists(Projectnuspec):
os.system(''+NuGetdisc+'&&cd '+NuGetpath+'&&nuget setApiKey '+ProGetAPIKey+'')
os.system(''+ProjectDisc+'&&cd '+Projectfilepath+'&&nuget spec')
modifynuspec(Projectfilepath,Projectname)
Projectnamecsproj = Projectname+".csproj"
os.system(''+ProjectDisc+'&&cd '+Projectfilepath+'&&nuget pack '+Projectnamecsproj+' -Build') SearchKeywords=sys.argv[] #搜索关键词
Nupkgpath = findNugetpack(Projectfilepath,SearchKeywords)
os.system(''+NuGetdisc+'&&cd '+NuGetpath+'&&nuget push '+Nupkgpath+' '+ProGetAPIKey+' -Source '+ProGetSourceUrl+' -ApiKey '+ProGetAdmin+':'+ProGetPassword+'')
#打包 revertunchangedFile(p4,submittedFiles)
p4.run("change",["-d"],changelistId)
except Exception as ex:
revertFile(p4,submittedFiles)
p4.run("change",["-d"],changelistId)
p4.disconnect()

(2)以dll的方式打包

 # coding=gbk
import os
import sys
import re
import xml.dom.minidom
import win32api from P4 import P4 def getdisc(projectpath): #获得项目文件的当前盘
disc = projectpath.split(':', )[]
disc = disc+":"
return disc def Checknode(filepath,nodename):
dom = xml.dom.minidom.parse(filepath)
root = dom.documentElement
for rt in root.childNodes:
for rt1 in rt.childNodes:
if rt1.nodeName == nodename:
for node in rt1.childNodes:
return node.nodeValue def getFileVersion(file_name):
info = win32api.GetFileVersionInfo(file_name, os.sep)
ms = info['FileVersionMS']
ls = info['FileVersionLS']
version = '%d.%d.%d.%04d' % (win32api.HIWORD(ms), win32api.LOWORD(ms), win32api.HIWORD(ls), win32api.LOWORD(ls))
return version def modifynuspec(projectnuspec,dllfilepath):
tfile = projectnuspec
f = open(tfile,'r')
xmldata = f.read()
#oldversion = Checknode(tfile,"version") 按照默认版本号加1(预留)
#listindex=int(len(oldversion.split("."))-)
#newversion = int(oldversion.split(".")[listindex])+
#newversion = oldversion[:-]+str(newversion)
dllversion = getFileVersion(dllfilepath) #按照dll版本号
xmldata = re.sub('\<version>(.*?)\</version>', '<version>'+dllversion+'</version>', xmldata)
f.close()
f = open(tfile,'w')
f.write(xmldata)
f.close() def findNugetpack(nuspecfilepath,searchKeywords):
li = os.listdir(nuspecfilepath)
for filename in li:
if filename.endswith(".nupkg") and searchKeywords in filename:
nupkgpath = nuspecfilepath+"\\"+ filename
return nupkgpath if __name__ == '__main__':
if len(sys.argv)!=:
sys.exit(-) #连接P4并同步文件
p4 = P4()
p4.port = sys.argv[1]
p4.user = sys.argv[2]
p4.password = sys.argv[3]
p4.client = sys.argv[4]
p4.connect()
#连接P4并同步文件 #打包参数设置
NuGetpath =sys.argv[5]
Nuspecfilepath =sys.argv[6]
Nuspecfilename = sys.argv[7]
ProGetSourceUrl = sys.argv[8]
ProGetAdmin =sys.argv[9]
ProGetPassword =sys.argv[19]
ProGetApiKey=sys.argv[]
#打包参数设置 #打包
NuGetdisc = getdisc(NuGetpath)
ProjectDisc = getdisc(Nuspecfilepath)
Projectnuspec =Nuspecfilepath+"\\"+Nuspecfilename+".nuspec"
Dllfilepath = sys.argv[]
if os.path.exists(Projectnuspec):
modifynuspec(Projectnuspec,Dllfilepath)
Projectnuspecname = Nuspecfilename+".nuspec"
os.system(''+ProjectDisc+'&&cd '+ Nuspecfilepath+'&&nuget pack '+Projectnuspecname+'')
Nupkgpath = findNugetpack(Nuspecfilepath,Nuspecfilename)
os.system(''+NuGetdisc+'&&cd '+NuGetpath+'&&nuget push '+Nupkgpath+' '+ProGetApiKey+' -Source '+ProGetSourceUrl+' -ApiKey '+ProGetAdmin+':'+ProGetPassword+'')
else:
sys.exit(-)
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】使用NuGet打包并发布至ProGet过程 (打包再次详解)【下篇】的更多相关文章

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

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

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

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

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

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

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

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

  5. Unity3D打包 将发布的exe文件打包成一个Windows安装文件(自解压文件)

    Unity打包Standalone时 会出现一个exe文件和一个data文件夹 可是我们平常见过的软件 基本没有这种像这种结构的 一般都是一个安装文件,然后点击安装,选择路径,生成快捷方式- 本篇博客 ...

  6. Activex打包于发布完整版---ActiveX打包

    前面介绍了数字证书的原理与制作:http://blog.csdn.net/jiangtongcn/article/details/13508365,下面来看一下ActiveX组件的打包. 我现在有一个 ...

  7. ios 8+ (xcode 6.0 +)应用程序Ad Hoc 发布前多设备测试流程详解

    我们开发的程序在经过simulator以及自己的iOS设备测试后,也基本完成应用程序了,这时候我们就可以把它发布出去了更更多的人去测试,我们可以在iOS平台使用ad hoc实现. 你在苹果购买的开发者 ...

  8. VS2015 使用 Web Deploy 发布网站到 WindowsServer2008 R2服务器详解

    使用原因:由于开发期间需要将开发出的网站随时提交到服务器以便公司高层随时访问所以要求将开发出的网站每天发布到服务器,频繁度比较高,因此不能再使用之前的方式(发布到本地后再拷贝文件到服务器),所以想到了 ...

  9. 使用autotools自动生成Makefile并在此之上使用dh-make生成可发布的deb程序包(详解)

    转自:http://blog.csdn.net/longerzone/article/details/12705507 一.前言 本文将介绍如何使用autotools生成一个Makefile文件,并在 ...

随机推荐

  1. 强化学习读书笔记 - 12 - 资格痕迹(Eligibility Traces)

    强化学习读书笔记 - 12 - 资格痕迹(Eligibility Traces) 学习笔记: Reinforcement Learning: An Introduction, Richard S. S ...

  2. 《More Effective C++ 》读书笔记(二)Exception 异常

    这事篇读书笔记,只记录自己的理解和总结,一般情况不对其举例子具体说明,因为那正是书本身做的事情,我的笔记作为梳理和复习之用,划重点.我推荐学C++的人都好好读一遍Effective C++ 系列,真是 ...

  3. 【转】PHPCMS+PHPExcel实现后台数据导入导出功能

    首先,上图之中的红色框框是没有的,我们想要给他加上,当然是要改HTML页面啦,废话,我们跟ECSHOP一样由PHP路径找模板: 看看路由原理: 首先,上图之中的红色框框是没有的,我们想要给他加上,当然 ...

  4. mysql 无法启动,错误1067,进程意外终止

    在做项目启动mysql数据库时,经常出现 这个错误,今天总结一下 //查看了网上很多的方法,都不适用,但或许对你适用.ps:网上只提供了怎么解决这个问题,但是没有将怎么去发现问题,对症下药才是王道.而 ...

  5. HackRF One硬件架构及参数简介

    本文内容.开发板及配件仅限用于学校或科研院所开展科研实验! 淘宝店铺名称:开源SDR实验室 HackRF链接:https://item.taobao.com/item.htm?spm=a1z10.1- ...

  6. Spark之spark shell

    前言:要学习spark程序开发,建议先学习spark-shell交互式学习,加深对spark程序开发的理解.spark-shell提供了一种学习API的简单方式,以及一个能够进行交互式分析数据的强大工 ...

  7. 华为云分布式缓存服务DCS与开源服务差异对比

    华为云分布式缓存DCS提供单机.主备.集群等丰富的实例类型,满足用户高读写性能及快速数据访问的业务诉求.支持丰富的实例管理操作,帮助用户省去运维烦恼.用户可以聚焦于业务逻辑本身,而无需过多考虑部署.监 ...

  8. leetcode27_C++Remove Element

    给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度. 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成 ...

  9. Python爬虫入门(3-4):Urllib库的高级用法

    1.分分钟扒一个网页下来 怎样扒网页呢?其实就是根据URL来获取它的网页信息,虽然我们在浏览器中看到的是一幅幅优美的画面,但是其实是由浏览器解释才呈现出来的,实质它 是一段HTML代码,加 JS.CS ...

  10. idea的快捷键(复制)

    IntelliJ Idea 常用快捷键列表 Ctrl+Shift + Enter,语句完成“!”,否定完成,输入表达式时按 “!”键Ctrl+E,最近的文件Ctrl+Shift+E,最近更改的文件Sh ...