func newReplenishFromS3Func()

in packages/cli/internal/pkg/version/replenish_func.go [25:102]


func newReplenishFromS3Func(s3Client S3Api, channel string) func(string) ([]Info, error) {
	return func(versionString string) ([]Info, error) {
		currentSemVersion, err := semver.Parse(versionString)
		if err != nil {
			return nil, err
		}
		bucket, prefix, err := parseS3Url(channel)
		if err != nil {
			return nil, err
		}
		prefix = stripLeadingSlashIfAny(prefix)
		input := &s3.ListObjectsV2Input{
			Bucket: aws.String(bucket),
			Prefix: aws.String(prefix),
		}
		index := make(map[string]*semanticVersion)
		var semanticVersions []*semanticVersion
		paginator := s3.NewListObjectsV2Paginator(s3Client, input)
		for paginator.HasMorePages() {
			output, err := paginator.NextPage(context.Background())
			if err != nil {
				return nil, err
			}
			s3Objects := output.Contents

			for _, s3Object := range s3Objects {
				// Skipping all unexpected objects in the bucket
				// We are looking only for:
				// - <prefix>/<semantic version>/deprecated
				// - <prefix>/<semantic version>/highlight

				key := aws.ToString(s3Object.Key)
				if !strings.HasPrefix(key, prefix) {
					continue
				}
				versionAndObjectName := strings.Split(key[len(prefix):], "/")
				if len(versionAndObjectName) != 2 {
					continue
				}
				versionString := versionAndObjectName[0]
				versionMeta, ok := index[versionString]
				if !ok {
					semVersion, err := semver.Parse(versionString)
					if err != nil {
						continue
					}
					versionMeta = &semanticVersion{Version: semVersion}
					versionMeta.Name = versionString
					semanticVersions = append(semanticVersions, versionMeta)
					index[versionString] = versionMeta
				}
				objectName := versionAndObjectName[1]
				if currentSemVersion.EQ(versionMeta.Version) && objectName == deprecationMessageObjectName {
					versionMeta.Deprecated = true
					versionMeta.DeprecationMessage, _ = readS3Object(s3Client, bucket, key)
					continue
				}
				if currentSemVersion.LT(versionMeta.Version) && objectName == highlightMessageObjectName {
					versionMeta.Highlight, _ = readS3Object(s3Client, bucket, key)
					continue
				}
			}
		}
		sort.Slice(semanticVersions, func(i, j int) bool {
			return semanticVersions[i].Version.LT(semanticVersions[j].Version)
		})
		currentVersionIndex := sort.Search(len(semanticVersions), func(i int) bool {
			return semanticVersions[i].Version.GTE(currentSemVersion)
		})
		currentAndNewer := semanticVersions[currentVersionIndex:]

		result := make([]Info, len(currentAndNewer))
		for i, ver := range currentAndNewer {
			result[i] = ver.Info
		}
		return result, nil
	}
}