【NuGet】使用NuGet打包併發布至ProGet過程 (打包再次詳解)【下篇】

1、前言html

      上篇[1]主要介紹了利用csproj文件使用NuGet打包至ProGet的過程,並附上了用於在Jenkins上運行的python腳本。本篇的主要內容分爲如下幾點:node

      1. Nuspec與Nupkg的關係python

      2. dll文件該如何打包程序員

      3. P4python的幾個操做算法

      4. 融入jenkinsapi

      5. 本週關於與組長的討論以及生活服務器

 

2、Nuspec與Nupkg的關係dom

      上篇咱們說到,nuspec文件是nupkg的清單文件。可是有時候你會發現,明明你的項目裏有依賴項(dependency),可你進行nuget spec操做後,發現清單文件裏並無項目中所包含的依賴項,這是爲何?爲何進行nuget pack操做後纔會有依賴項,nupkg不是由清單文件nuspec才產生的嗎??ui

      首先,咱們想一想整個過程。spa

      第一步,咱們進入了項目文件所在的路徑,在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文件,使其清單與打包內容正確,這時候項目中的依賴項就會正確的顯示在了包包中。

 

3、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文件已經能充分提供信息了。

 

4、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(" ",2)[1]
   changelistId = changelistNumber

   checkoutfiles=sys.argv[11]    #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

 

5、融入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(':', 1)[0]
  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)-1
 28     for i in range(flen):
 29          if lines[i].startswith("[assembly: AssemblyVersion"):
 30             versioncode = lines[i].split('"', 2)[1]       #得到當前assemblyinfo的
 31             break
 32     oldVersion = versioncode
 33     splitedVersion = oldVersion.split('.')
 34     lastSubVersion = int(splitedVersion[3])
 35     lastSubVersion += 1
 36     splitedVersion[3] = str(lastSubVersion)
 37     newVersion = '.'.join(splitedVersion)      #將當前的assemblyVersion+1
 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)!=15:
 71        sys.exit(-1)
 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[11]   #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(" ",2)[1]
 99    changelistId = changelistNumber
100 
101    checkoutfiles=sys.argv[12]    #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[13]  #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[14]   #搜索關鍵詞
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(':', 1)[0]
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 
25 def getFileVersion(file_name):
26     info = win32api.GetFileVersionInfo(file_name, os.sep)
27     ms = info['FileVersionMS']
28     ls = info['FileVersionLS']
29     version = '%d.%d.%d.%04d' % (win32api.HIWORD(ms), win32api.LOWORD(ms), win32api.HIWORD(ls), win32api.LOWORD(ls))
30     return version
31 
32 def modifynuspec(projectnuspec,dllfilepath):
33     tfile = projectnuspec
34     f = open(tfile,'r')
35     xmldata = f.read()
36     #oldversion = Checknode(tfile,"version")  按照默認版本號加1(預留)
37     #listindex=int(len(oldversion.split("."))-1)
38     #newversion = int(oldversion.split(".")[listindex])+1
39     #newversion = oldversion[:-1]+str(newversion)
40     dllversion = getFileVersion(dllfilepath)  #按照dll版本號
41     xmldata = re.sub('\<version>(.*?)\</version>', '<version>'+dllversion+'</version>', xmldata)
42     f.close()
43     f = open(tfile,'w')
44     f.write(xmldata)
45     f.close()
46 
47 def  findNugetpack(nuspecfilepath,searchKeywords):
48       li = os.listdir(nuspecfilepath)
49       for filename in li:
50           if filename.endswith(".nupkg") and searchKeywords in filename:
51               nupkgpath = nuspecfilepath+"\\"+ filename
52               return  nupkgpath
53 
54 
55 if __name__ == '__main__':
56    if len(sys.argv)!=13:
57       sys.exit(-1)
58 
59 
60    #鏈接P4並同步文件
61    p4 = P4()
62    p4.port = sys.argv[1]
63    p4.user = sys.argv[2]
64    p4.password = sys.argv[3]
65    p4.client = sys.argv[4]
66    p4.connect()
67    #鏈接P4並同步文件
68 
69    #打包參數設置
70    NuGetpath =sys.argv[5]
71    Nuspecfilepath =sys.argv[6]
72    Nuspecfilename = sys.argv[7]
73    ProGetSourceUrl = sys.argv[8]
74    ProGetAdmin =sys.argv[9]
75    ProGetPassword =sys.argv[19]
76    ProGetApiKey=sys.argv[11]
77    #打包參數設置
78 
79    #打包
80    NuGetdisc = getdisc(NuGetpath)
81    ProjectDisc = getdisc(Nuspecfilepath)
82    Projectnuspec =Nuspecfilepath+"\\"+Nuspecfilename+".nuspec"
83    Dllfilepath = sys.argv[12]
84    if  os.path.exists(Projectnuspec):
85        modifynuspec(Projectnuspec,Dllfilepath)
86        Projectnuspecname = Nuspecfilename+".nuspec"
87        os.system(''+ProjectDisc+'&&cd '+ Nuspecfilepath+'&&nuget pack '+Projectnuspecname+'')
88        Nupkgpath = findNugetpack(Nuspecfilepath,Nuspecfilename)
89        os.system(''+NuGetdisc+'&&cd '+NuGetpath+'&&nuget push '+Nupkgpath+' '+ProGetApiKey+' -Source '+ProGetSourceUrl+' -ApiKey '+ProGetAdmin+':'+ProGetPassword+'')
90    else:
91        sys.exit(-1)
92    p4.disconnect()

 

6、與組長的溝通以及生活

     工做快倆月了。這半個月過得不太順心,在工做與生活中都意識到了本身的不足。就拿打包這事來講吧,組長本想培養我自我探索自我理清思路的能力,可我只是把每一個具體的點搞清楚了,卻沒有從總體流程去思考,好比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

轉載請註明原文出處 , 謝謝合做

相關文章
相關標籤/搜索