Skip to content

Commit bdff66b

Browse files
cashwinichourasiaHarness
authored andcommitted
feat:[AH-2541]: Add support for bulk skip artifacts (#147)
* adc10a removed unused variable and code * f7442e added skip validation with API response data * 87846f added skip validation with mock data
1 parent 9adeccf commit bdff66b

8 files changed

Lines changed: 149 additions & 53 deletions

File tree

module/ar/migrate/adapter/adapter.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ type Adapter interface {
5454
fileName *types.File,
5555
artifactType types.ArtifactType,
5656
) (bool, error)
57+
GetAllFilesForVersion(
58+
ctx context.Context,
59+
registryRef, pkg, version string,
60+
) ([]string, error)
5761
CreateVersion(
5862
registry string,
5963
artifactName string,

module/ar/migrate/adapter/har/adapter.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package har
33
import (
44
"context"
55
"fmt"
6+
67
//"github.com/harness/harness-cli/module/ar/migrate"
78
//client2 "github.com/harness/harness-cli/util/client"
89
"io"
@@ -170,6 +171,13 @@ func (a *adapter) FileExists(
170171
return a.client.artifactFileExists(ctx, registryRef, pkg, version, file, artifactType)
171172
}
172173

174+
func (a *adapter) GetAllFilesForVersion(
175+
ctx context.Context,
176+
registryRef, pkg, version string,
177+
) ([]string, error) {
178+
return a.client.artifactGetFilesForVersion(ctx, registryRef, pkg, version)
179+
}
180+
173181
func (a *adapter) CreateVersion(
174182
registry string,
175183
artifactName string,

module/ar/migrate/adapter/har/client.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,41 @@ func (c *client) artifactFileExists(
561561
return false, nil
562562
}
563563

564+
func (c *client) artifactGetFilesForVersion(
565+
ctx context.Context,
566+
registryRef, pkg, version string,
567+
) ([]string, error) {
568+
page := int64(0)
569+
size := int64(100)
570+
571+
var allFileNames []string
572+
for {
573+
response, err := c.apiClient.GetArtifactFilesWithResponse(ctx, registryRef, pkg, version,
574+
&ar.GetArtifactFilesParams{
575+
Page: &page,
576+
Size: &size,
577+
SortOrder: nil,
578+
SortField: nil,
579+
})
580+
if err != nil {
581+
return allFileNames, fmt.Errorf("failed to get artifact files: %w", err)
582+
}
583+
if response.StatusCode() != http2.StatusOK {
584+
return allFileNames, fmt.Errorf("failed to get artifact files: %s", response.Status())
585+
}
586+
data := response.JSON200
587+
588+
for _, v := range data.Data.Files {
589+
allFileNames = append(allFileNames, v.Name)
590+
}
591+
if len(data.Data.Files) < int(size) || (nil != data.Data.PageCount && nil != data.Data.PageIndex && (*data.Data.PageIndex+1 >= *data.Data.PageCount)) {
592+
break
593+
}
594+
page++
595+
}
596+
return allFileNames, nil
597+
}
598+
564599
func (c *client) getRegistry(
565600
ctx context.Context,
566601
registry string,

module/ar/migrate/adapter/jfrog/adapter.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -768,6 +768,13 @@ func (a *adapter) FileExists(
768768
return false, fmt.Errorf("not implemented")
769769
}
770770

771+
func (a *adapter) GetAllFilesForVersion(
772+
ctx context.Context,
773+
registryRef, pkg, version string,
774+
) ([]string, error) {
775+
return nil, fmt.Errorf("not implemented")
776+
}
777+
771778
type repomdData struct {
772779
XMLName xml.Name `xml:"repomd"`
773780
Data []struct {

module/ar/migrate/adapter/mock_jfrog/adapter.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -829,6 +829,13 @@ func (a *adapter) FileExists(
829829
return false, nil
830830
}
831831

832+
func (a *adapter) GetAllFilesForVersion(
833+
ctx context.Context,
834+
registryRef, pkg, version string,
835+
) ([]string, error) {
836+
return nil, nil
837+
}
838+
832839
type repomdData struct {
833840
XMLName xml.Name `xml:"repomd"`
834841
Data []struct {

module/ar/migrate/adapter/nexus/adapter.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,13 @@ func (a *adapter) FileExists(
410410
return false, nil
411411
}
412412

413+
func (a *adapter) GetAllFilesForVersion(
414+
ctx context.Context,
415+
registryRef, pkg, version string,
416+
) ([]string, error) {
417+
return nil, fmt.Errorf("not implemented")
418+
}
419+
413420
func (a *adapter) constructFilePath(pkg, version, fileName string, artifactType types.ArtifactType) string {
414421
switch artifactType {
415422
case types.MAVEN:

module/ar/migrate/migratable/file.go

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import (
2323
"github.com/harness/harness-cli/module/ar/migrate/engine"
2424
"github.com/harness/harness-cli/module/ar/migrate/types"
2525
"github.com/harness/harness-cli/module/ar/migrate/types/npm"
26-
"github.com/harness/harness-cli/module/ar/migrate/util"
2726
"github.com/harness/harness-cli/util/common"
2827

2928
"github.com/google/uuid"
@@ -115,31 +114,6 @@ func (r *File) Pre(ctx context.Context) error {
115114
logger.Info().Msg("Starting version pre-migration step")
116115
startTime := time.Now()
117116

118-
if !r.config.Overwrite && (r.artifactType != types.MAVEN && r.pkg.Name != "" && r.version.Name != "" && r.file.Name != "") {
119-
exists, err := r.destAdapter.FileExists(ctx,
120-
r.registry.Path,
121-
r.pkg.Name, r.version.Name, r.file, r.artifactType)
122-
if err != nil {
123-
log.Error().Err(err).Msg("Failed to check if version exists")
124-
return nil
125-
}
126-
if exists {
127-
util.GetSkipPrinter().Println(fmt.Sprintf("Registry [%s], Package [%s/%s], File [%s] already exists",
128-
r.destRegistry,
129-
r.pkg.Name, r.version.Name, r.file.Name))
130-
r.skipMigration = true
131-
stat := types.FileStat{
132-
Name: r.file.Name,
133-
Registry: r.srcRegistry,
134-
Uri: r.file.Uri,
135-
Size: int64(r.file.Size),
136-
Status: types.StatusSkip,
137-
}
138-
r.stats.FileStats = append(r.stats.FileStats, stat)
139-
return nil
140-
}
141-
}
142-
143117
logger.Info().
144118
Dur("duration", time.Since(startTime)).
145119
Msg("Completed file pre-migration step")

module/ar/migrate/migratable/version.go

Lines changed: 81 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,26 +11,28 @@ import (
1111
"github.com/harness/harness-cli/module/ar/migrate/engine"
1212
"github.com/harness/harness-cli/module/ar/migrate/tree"
1313
"github.com/harness/harness-cli/module/ar/migrate/types"
14+
"github.com/harness/harness-cli/module/ar/migrate/util"
1415

1516
"github.com/google/uuid"
1617
"github.com/rs/zerolog"
1718
"github.com/rs/zerolog/log"
1819
)
1920

2021
type Version struct {
21-
srcRegistry string
22-
destRegistry string
23-
srcAdapter adapter.Adapter
24-
destAdapter adapter.Adapter
25-
artifactType types.ArtifactType
26-
logger zerolog.Logger
27-
pkg types.Package
28-
version types.Version
29-
node *types.TreeNode
30-
stats *types.TransferStats
31-
mapping *types.RegistryMapping
32-
config *types.Config
33-
registry types.RegistryInfo
22+
srcRegistry string
23+
destRegistry string
24+
srcAdapter adapter.Adapter
25+
destAdapter adapter.Adapter
26+
artifactType types.ArtifactType
27+
logger zerolog.Logger
28+
pkg types.Package
29+
version types.Version
30+
node *types.TreeNode
31+
stats *types.TransferStats
32+
mapping *types.RegistryMapping
33+
config *types.Config
34+
registry types.RegistryInfo
35+
existingFileMap map[string]bool
3436
}
3537

3638
func NewVersionJob(
@@ -59,19 +61,20 @@ func NewVersionJob(
5961
Logger()
6062

6163
return &Version{
62-
srcRegistry: srcRegistry,
63-
destRegistry: destRegistry,
64-
srcAdapter: src,
65-
destAdapter: dest,
66-
artifactType: artifactType,
67-
logger: jobLogger,
68-
pkg: pkg,
69-
version: version,
70-
node: node,
71-
stats: stats,
72-
mapping: mapping,
73-
config: config,
74-
registry: registry,
64+
srcRegistry: srcRegistry,
65+
destRegistry: destRegistry,
66+
srcAdapter: src,
67+
destAdapter: dest,
68+
artifactType: artifactType,
69+
logger: jobLogger,
70+
pkg: pkg,
71+
version: version,
72+
node: node,
73+
stats: stats,
74+
mapping: mapping,
75+
config: config,
76+
registry: registry,
77+
existingFileMap: make(map[string]bool),
7578
}
7679
}
7780

@@ -89,6 +92,20 @@ func (r *Version) Pre(ctx context.Context) error {
8992
logger.Info().Msg("Starting version pre-migration step")
9093
startTime := time.Now()
9194

95+
// reading all existing files for this version from destination
96+
97+
if !r.config.Overwrite && (r.artifactType != types.MAVEN && r.pkg.Name != "" && r.version.Name != "") {
98+
existingFiles, err := r.getAllExistingFilesForThisVersion(ctx)
99+
if err != nil {
100+
logger.Warn().Err(err).Msg("Failed to get existing files, will proceed with migration")
101+
} else {
102+
// Populate existingFileMap with file name
103+
for _, fileName := range existingFiles {
104+
r.existingFileMap[fileName] = true
105+
}
106+
logger.Info().Msgf("Found %d existing files for version %s", len(r.existingFileMap), r.version.Name)
107+
}
108+
}
92109
logger.Info().
93110
Dur("duration", time.Since(startTime)).
94111
Msg("Completed version pre-migration step")
@@ -101,7 +118,6 @@ func (r *Version) Migrate(ctx context.Context) error {
101118
Str("step", "migrate").
102119
Str("trace_id", traceID).
103120
Logger()
104-
105121
logger.Info().Msg("Starting version migration step")
106122
startTime := time.Now()
107123

@@ -115,6 +131,25 @@ func (r *Version) Migrate(ctx context.Context) error {
115131
return fmt.Errorf("get files from tree failed: %w", err)
116132
}
117133
for _, file := range files {
134+
// Check if file already exists in destination
135+
if r.existingFileMap[file.Name] {
136+
util.GetSkipPrinter().Println(fmt.Sprintf("Registry [%s], Package [%s/%s], File [%s] already exists",
137+
r.destRegistry,
138+
r.pkg.Name, r.version.Name, file.Name))
139+
logger.Info().Msgf("Skipping file %s as it already exists in destination", file.Uri)
140+
141+
// Add to statistics
142+
stat := types.FileStat{
143+
Name: file.Name,
144+
Registry: r.srcRegistry,
145+
Uri: file.Uri,
146+
Size: int64(file.Size),
147+
Status: types.StatusSkip,
148+
}
149+
r.stats.FileStats = append(r.stats.FileStats, stat)
150+
continue
151+
}
152+
118153
job := NewFileJob(r.srcAdapter, r.destAdapter, r.srcRegistry, r.destRegistry, r.artifactType, r.pkg,
119154
r.version, r.node, file, r.stats, r.mapping, r.config, r.registry)
120155
jobs = append(jobs, job)
@@ -202,3 +237,22 @@ func (r *Version) Post(ctx context.Context) error {
202237
Msg("Completed version post-migration step")
203238
return nil
204239
}
240+
241+
// getAllExistingFilesForThisVersion fetches existing files for this version from the destination API
242+
// Returns a slice of file paths that already exist
243+
func (r *Version) getAllExistingFilesForThisVersion(ctx context.Context) ([]string, error) {
244+
// Call the destination adapter API to get all files for this version
245+
allFileNames, err := r.destAdapter.GetAllFilesForVersion(
246+
ctx,
247+
r.registry.Path,
248+
r.pkg.Name,
249+
r.version.Name,
250+
)
251+
252+
if err != nil {
253+
return nil, fmt.Errorf("failed to get existing files from destination: %w", err)
254+
}
255+
256+
r.logger.Info().Msgf("Retrieved %d existing files from destination API for version %s", len(allFileNames), r.version.Name)
257+
return allFileNames, nil
258+
}

0 commit comments

Comments
 (0)