func copyChartToGCSBucket()

in hack/helm/release/internal/helm/helm.go [172:228]


func copyChartToGCSBucket(ctx context.Context, conf ReleaseConfig, chart chart, chartPackagePath string) error {
	repoURL, err := url.Parse(conf.ChartsRepoURL)
	if err != nil {
		return fmt.Errorf("while parsing url (%s): %w", conf.ChartsRepoURL, err)
	}

	// read the file to copy on disk
	chartPackageFile, err := os.Open(chartPackagePath)
	if err != nil {
		return fmt.Errorf("while opening chart (%s): %w", chartPackagePath, err)
	}
	defer chartPackageFile.Close()

	// trail the first / from the repo url path
	chartArchiveDest := filepath.Join(strings.TrimPrefix(repoURL.Path, "/"), chart.Name, filepath.Base(chartPackagePath))

	log.Printf("Writing chart archive to bucket path (%s)\n", chartArchiveDest)

	// create gcs client
	gcsClient, err := storage.NewClient(ctx)
	if err != nil {
		return fmt.Errorf("while creating gcs storage client: %w", err)
	}
	defer gcsClient.Close()
	chartArchiveObj := gcsClient.Bucket(conf.Bucket).Object(chartArchiveDest)

	// specify that the object must not exist for non-SNAPSHOT chart when publishing to prod Helm repo
	isNonSnapshot := !strings.HasSuffix(chart.Version, "-SNAPSHOT")
	isProdHelmRepo := !strings.HasSuffix(conf.Bucket, "-dev")
	if isNonSnapshot && isProdHelmRepo {
		chartArchiveObj = chartArchiveObj.If(storage.Conditions{DoesNotExist: true})
	}

	if conf.DryRun {
		log.Printf("Not uploading (%s) to %s as dry-run is set", chartPackagePath, chartArchiveDest)
		return nil
	}

	// upload the file to the bucket
	chartArchiveWriter := chartArchiveObj.NewWriter(ctx)
	if _, err = io.Copy(chartArchiveWriter, chartPackageFile); err != nil {
		return fmt.Errorf("while copying data to bucket: %w", err)
	}
	if err := chartArchiveWriter.Close(); err != nil {
		switch errType := err.(type) {
		case *googleapi.Error:
			if errType.Code == http.StatusPreconditionFailed && isNonSnapshot && isProdHelmRepo {
				return fmt.Errorf("file %s already exists in remote bucket; manually remove for this operation to succeed", chartPackagePath)
			}
			return fmt.Errorf("while writing data to bucket: %w", err)
		default:
			return fmt.Errorf("while writing data to bucket: %w", err)
		}
	}

	return nil
}