@@ -3,9 +3,8 @@ package main
33import (
44 "context"
55 "fmt"
6- "path/filepath"
7-
86 "os"
7+ "path/filepath"
98 "regexp"
109 "strings"
1110
@@ -44,6 +43,11 @@ Build the present binaries and import in CDS:
4443$ cdsctl admin plugins binary-add artifactory-release-plugin artifactory-release-plugin-bin.yml <path-to-binary-file>
4544*/
4645
46+ type promotedArtifact struct {
47+ Pattern string
48+ Target string
49+ }
50+
4751type artifactoryReleasePlugin struct {
4852 integrationplugin.Common
4953}
@@ -102,19 +106,14 @@ func (e *artifactoryReleasePlugin) Run(_ context.Context, opts *integrationplugi
102106
103107 artSplitted := strings .Split (artifactList , "," )
104108 artRegs := make ([]* regexp.Regexp , 0 , len (artSplitted ))
105- for _ , art := range artSplitted {
106- r , err := regexp .Compile (art )
109+ for _ , arti := range artSplitted {
110+ r , err := regexp .Compile (arti )
107111 if err != nil {
108112 return fail ("unable compile regexp in artifact list: %v" , err )
109113 }
110114 artRegs = append (artRegs , r )
111115 }
112116
113- type promotedArtifact struct {
114- Pattern string
115- Target string
116- }
117-
118117 artifactPromoted := make ([]promotedArtifact , 0 )
119118 patternUsed := make (map [string ]struct {})
120119 for _ , r := range runResult {
@@ -169,37 +168,9 @@ func (e *artifactoryReleasePlugin) Run(_ context.Context, opts *integrationplugi
169168 }
170169
171170 // Release bundle
172- buildInfoName := fmt .Sprintf ("%s/%s/%s" , buildInfo , projectKey , workflowName )
173-
174- params := services .NewCreateReleaseBundleParams (strings .Replace (buildInfoName , "/" , "-" , - 1 ), version )
175- params .ReleaseNotes = releaseNote
176- params .ReleaseNotesSyntax = "plain_text"
177-
178- paramsBuild := fmt .Sprintf ("%s/%s" , strings .Replace (buildInfoName , "/" , "\\ /" , - 1 ), version )
179- if artifactList == "" {
180- params .SpecFiles = []* utils.ArtifactoryCommonParams {
181- {
182- Recursive : true ,
183- Build : paramsBuild ,
184- },
185- }
186- } else {
187- params .SpecFiles = make ([]* utils.ArtifactoryCommonParams , 0 , len (artifactPromoted ))
188- for _ , art := range artifactPromoted {
189- query := & utils.ArtifactoryCommonParams {
190- Recursive : true ,
191- Build : paramsBuild ,
192- Pattern : art .Pattern ,
193- Target : art .Target ,
194- }
195- params .SpecFiles = append (params .SpecFiles , query )
196- }
197- }
198- params .SignImmediately = true
199- fmt .Printf ("Creating release %s %s\n " , params .Name , params .Version )
200-
201- if _ , err := distriClient .CreateReleaseBundle (params ); err != nil {
202- return fail ("unable to create release bundle: %v" , err )
171+ releaseName , releaseVersion , err := e .createReleaseBundle (distriClient , projectKey , workflowName , version , buildInfo , artifactList , releaseNote , artifactPromoted , artifactoryURL , releaseToken )
172+ if err != nil {
173+ return fail (err .Error ())
203174 }
204175
205176 fmt .Printf ("Listing Edge nodes to distribute the release \n " )
@@ -209,8 +180,8 @@ func (e *artifactoryReleasePlugin) Run(_ context.Context, opts *integrationplugi
209180 }
210181 edges = e .removeNonEdge (edges )
211182
212- fmt .Printf ("Distribute Release %s %s\n " , params . Name , params . Version )
213- distributionParams := services .NewDistributeReleaseBundleParams (params . Name , params . Version )
183+ fmt .Printf ("Distribute Release %s %s\n " , releaseName , releaseVersion )
184+ distributionParams := services .NewDistributeReleaseBundleParams (releaseName , releaseVersion )
214185 distributionParams .DistributionRules = make ([]* distriUtils.DistributionCommonParams , 0 , len (edges ))
215186 for _ , e := range edges {
216187 distributionParams .DistributionRules = append (distributionParams .DistributionRules , & distriUtils.DistributionCommonParams {
@@ -219,15 +190,60 @@ func (e *artifactoryReleasePlugin) Run(_ context.Context, opts *integrationplugi
219190 CountryCodes : []string {e .City .CountryCode },
220191 })
221192 }
222- if err := distriClient .DistributeReleaseBundle (distributionParams ); err != nil {
223- return fail ("unable to distribution version: %v" , err )
193+ if err := distriClient .DistributeReleaseBundleSync (distributionParams , 10 ); err != nil {
194+ return fail ("unable to distribute version: %v" , err )
224195 }
225196
226197 return & integrationplugin.RunResult {
227198 Status : sdk .StatusSuccess ,
228199 }, nil
229200}
230201
202+ func (e * artifactoryReleasePlugin ) createReleaseBundle (distriClient * distribution.DistributionServicesManager , projectKey , workflowName , version , buildInfo string , artifactList , releaseNote string , artifactPromoted []promotedArtifact , artifactoryURL , releaseToken string ) (string , string , error ) {
203+ buildInfoName := fmt .Sprintf ("%s/%s/%s" , buildInfo , projectKey , workflowName )
204+
205+ params := services .NewCreateReleaseBundleParams (strings .Replace (buildInfoName , "/" , "-" , - 1 ), version )
206+
207+ exist , err := e .checkReleaseBundleExist (distriClient , artifactoryURL , releaseToken , params .Name , params .Version )
208+ if err != nil {
209+ return "" , "" , err
210+ }
211+ if ! exist {
212+ params .ReleaseNotes = releaseNote
213+ params .ReleaseNotesSyntax = "plain_text"
214+
215+ paramsBuild := fmt .Sprintf ("%s/%s" , strings .Replace (buildInfoName , "/" , "\\ /" , - 1 ), version )
216+ if artifactList == "" {
217+ params .SpecFiles = []* utils.ArtifactoryCommonParams {
218+ {
219+ Recursive : true ,
220+ Build : paramsBuild ,
221+ },
222+ }
223+ } else {
224+ params .SpecFiles = make ([]* utils.ArtifactoryCommonParams , 0 , len (artifactPromoted ))
225+ for _ , arti := range artifactPromoted {
226+ query := & utils.ArtifactoryCommonParams {
227+ Recursive : true ,
228+ Build : paramsBuild ,
229+ Pattern : arti .Pattern ,
230+ Target : arti .Target ,
231+ }
232+ params .SpecFiles = append (params .SpecFiles , query )
233+ }
234+ }
235+ params .SignImmediately = true
236+ fmt .Printf ("Creating release %s %s\n " , params .Name , params .Version )
237+
238+ if _ , err := distriClient .CreateReleaseBundle (params ); err != nil {
239+ return "" , "" , fmt .Errorf ("unable to create release bundle %s/%s: %v" , params .Name , params .Version , err )
240+ }
241+ } else {
242+ fmt .Printf ("Release bundle %s/%s already exist" , params .Name , params .Version )
243+ }
244+ return params .Name , params .Version , nil
245+ }
246+
231247func (e * artifactoryReleasePlugin ) listEdgeNodes (distriClient * distribution.DistributionServicesManager , url , token string ) ([]EdgeNode , error ) {
232248 // action=x distribute
233249 listEdgeNodePath := fmt .Sprintf ("api/ui/distribution/edge_nodes?action=x" )
@@ -274,14 +290,24 @@ func (e *artifactoryReleasePlugin) promoteFile(artiClient artifactory.Artifactor
274290 params .Pattern = fmt .Sprintf ("%s/%s" , srcRepo , data .Path )
275291 params .Target = fmt .Sprintf ("%s/%s" , targetRepo , data .Path )
276292 params .Flat = true
277- fmt .Printf ("Promoting file %s from %s to %s\n " , data .Name , srcRepo , targetRepo )
278- nbSuccess , nbFailed , err := artiClient .Move (params )
293+
294+ // Check if artifact already exist on destination
295+ exist , err := e .checkArtifactExists (artiClient , targetRepo , data .Path )
279296 if err != nil {
280297 return err
281298 }
282- if nbFailed > 0 || nbSuccess == 0 {
283- return fmt .Errorf ("%s: copy failed with no reason" , data .Name )
299+ if ! exist {
300+ fmt .Printf ("Promoting file %s from %s to %s\n " , data .Name , srcRepo , targetRepo )
301+ nbSuccess , nbFailed , err := artiClient .Move (params )
302+ if err != nil {
303+ return err
304+ }
305+ if nbFailed > 0 || nbSuccess == 0 {
306+ return fmt .Errorf ("%s: copy failed with no reason" , data .Name )
307+ }
308+ return nil
284309 }
310+ fmt .Printf ("%s has been already promoted" , data .Name )
285311 return nil
286312}
287313
@@ -290,8 +316,59 @@ func (e *artifactoryReleasePlugin) promoteDockerImage(artiClient artifactory.Art
290316 targetRepo := fmt .Sprintf ("%s-%s" , data .RepoName , highMaturity )
291317 params := artService .NewDockerPromoteParams (data .Path , sourceRepo , targetRepo )
292318 params .Copy = false
293- fmt .Printf ("Promoting docker image %s from %s to %s\n " , data .Name , params .SourceRepo , params .TargetRepo )
294- return artiClient .PromoteDocker (params )
319+
320+ // Check if artifact already exist on destination
321+ exist , err := e .checkArtifactExists (artiClient , targetRepo , data .Path )
322+ if err != nil {
323+ return err
324+ }
325+ if ! exist {
326+ fmt .Printf ("Promoting docker image %s from %s to %s\n " , data .Name , params .SourceRepo , params .TargetRepo )
327+ return artiClient .PromoteDocker (params )
328+ }
329+ fmt .Printf ("%s has been already promoted" , data .Name )
330+ return nil
331+ }
332+
333+ func (e * artifactoryReleasePlugin ) checkArtifactExists (artiClient artifactory.ArtifactoryServicesManager , repoName string , artiName string ) (bool , error ) {
334+ httpDetails := artiClient .GetConfig ().GetServiceDetails ().CreateHttpClientDetails ()
335+ fileInfoURL := fmt .Sprintf ("%sapi/storage/%s/%s" , artiClient .GetConfig ().GetServiceDetails ().GetUrl (), repoName , artiName )
336+ re , body , _ , err := artiClient .Client ().SendGet (fileInfoURL , true , & httpDetails )
337+ if err != nil {
338+ return false , fmt .Errorf ("unable to get file info %s/%s: %v" , repoName , artiName , err )
339+ }
340+ if re .StatusCode == 404 {
341+ return false , nil
342+ }
343+ if re .StatusCode >= 400 {
344+ return false , fmt .Errorf ("unable to call artifactory [HTTP: %d] %s %s" , re .StatusCode , fileInfoURL , string (body ))
345+ }
346+ return true , nil
347+ }
348+
349+ func (e * artifactoryReleasePlugin ) checkReleaseBundleExist (client * distribution.DistributionServicesManager , url string , token string , name string , version string ) (bool , error ) {
350+ getReleasePath := fmt .Sprintf ("api/v1/release_bundle/%s/%s?format=json" , name , version )
351+ dtb := authdistrib .NewDistributionDetails ()
352+ dtb .SetUrl (strings .Replace (url , "/artifactory/" , "/distribution/" , - 1 ))
353+ dtb .SetAccessToken (token )
354+
355+ fakeService := services .NewCreateReleaseBundleService (client .Client ())
356+ fakeService .DistDetails = dtb
357+ clientDetail := fakeService .DistDetails .CreateHttpClientDetails ()
358+ getReleaseURL := fmt .Sprintf ("%s%s" , fakeService .DistDetails .GetUrl (), getReleasePath )
359+ utils .SetContentType ("application/json" , & clientDetail .Headers )
360+
361+ resp , body , _ , err := client .Client ().SendGet (getReleaseURL , true , & clientDetail )
362+ if err != nil {
363+ return false , fmt .Errorf ("unable to get release bundle %s/%s from distribution: %v" , name , version , err )
364+ }
365+ if resp .StatusCode == 404 {
366+ return false , nil
367+ }
368+ if resp .StatusCode >= 400 {
369+ return false , fmt .Errorf ("http error %d: %s" , resp .StatusCode , string (body ))
370+ }
371+ return true , nil
295372}
296373
297374func main () {
0 commit comments