@@ -72,6 +72,28 @@ func (rm *ReleaseManager) CreateAggregatedRelease(
7272 "runtime" , runtimeName ,
7373 "versions" , versions )
7474
75+ // Collect all artifact files BEFORE creating the release
76+ // This allows us to skip release creation if there are no artifacts
77+ var allArtifactFiles []string
78+ for _ , version := range versions {
79+ artifactFiles , err := rm .collectArtifactFiles (outputDir , runtimeName , version )
80+ if err != nil {
81+ rm .stderr .Warn ("failed to collect artifact files for version" , "version" , version , "error" , err )
82+ continue
83+ }
84+ allArtifactFiles = append (allArtifactFiles , artifactFiles ... )
85+ }
86+
87+ // Skip release creation if there are no artifacts to upload
88+ if len (allArtifactFiles ) == 0 {
89+ rm .stdout .Info ("skipping release creation - no artifacts to upload" ,
90+ "runtime" , runtimeName ,
91+ "versions" , versions )
92+ return nil , nil
93+ }
94+
95+ rm .stdout .Info ("collected artifacts for upload" , "count" , len (allArtifactFiles ))
96+
7597 // Use first version for semver (or could use latest)
7698 // For aggregated releases, semver is less meaningful
7799 var major , minor , patch int
@@ -96,12 +118,14 @@ func (rm *ReleaseManager) CreateAggregatedRelease(
96118 return nil , err
97119 }
98120
99- // Upload all artifacts (across all versions)
100- uploadedArtifacts , err := rm .uploadAllAggregatedArtifacts (ghRelease .GetID (), outputDir , runtimeName , versions )
121+ // Upload all collected artifacts
122+ uploadedArtifacts , err := rm .uploadArtifacts (ghRelease .GetID (), allArtifactFiles )
101123 if err != nil {
102124 return nil , err
103125 }
104126
127+ rm .stdout .Info ("all artifacts uploaded successfully" , "count" , len (uploadedArtifacts ))
128+
105129 // Build artifacts JSON structure
106130 artifactsJSON , err := rm .buildArtifactsJSON (uploadedArtifacts , downloadResults )
107131 if err != nil {
@@ -146,34 +170,9 @@ func (rm *ReleaseManager) createGitHubRelease(tag, name, body string, draft bool
146170 return ghRelease , releaseURL , nil
147171}
148172
149- // uploadAllAggregatedArtifacts collects and uploads artifacts for multiple versions.
150- func (rm * ReleaseManager ) uploadAllAggregatedArtifacts (releaseID int64 , outputDir , runtimeName string , versions []string ) (map [string ]artifactInfo , error ) {
151- var allArtifactFiles []string
152-
153- // Collect artifacts for all versions
154- for _ , version := range versions {
155- artifactFiles , err := rm .collectArtifactFiles (outputDir , runtimeName , version )
156- if err != nil {
157- rm .stderr .Warn ("failed to collect artifact files for version" , "version" , version , "error" , err )
158- continue
159- }
160- allArtifactFiles = append (allArtifactFiles , artifactFiles ... )
161- }
162-
163- rm .stdout .Info ("collected artifacts for upload" , "count" , len (allArtifactFiles ))
164-
165- uploadedArtifacts , err := rm .uploadArtifacts (releaseID , allArtifactFiles )
166- if err != nil {
167- return nil , fmt .Errorf ("failed to upload artifacts: %w" , err )
168- }
169-
170- rm .stdout .Info ("all artifacts uploaded successfully" , "count" , len (uploadedArtifacts ))
171-
172- return uploadedArtifacts , nil
173- }
174-
175173// collectArtifactFiles scans the output directory for all artifact files related to this release.
176- // This includes binaries, audit.json files, signatures (.sig), and certificates (.cert).
174+ // This includes binaries, audit.json files, signatures (.sig/.asc), and certificates (.cert).
175+ // Empty (0-byte) files are skipped as they indicate failed downloads.
177176func (rm * ReleaseManager ) collectArtifactFiles (outputDir , runtimeName , version string ) ([]string , error ) {
178177 var files []string
179178
@@ -187,6 +186,12 @@ func (rm *ReleaseManager) collectArtifactFiles(outputDir, runtimeName, version s
187186 return nil
188187 }
189188
189+ // Skip empty files (failed downloads create 0-byte files)
190+ if info .Size () == 0 {
191+ rm .stdout .Debug ("skipping empty file" , "file" , info .Name ())
192+ return nil
193+ }
194+
190195 // Include all files that match the version pattern
191196 // This covers binaries, audit.json, signatures, and certificates
192197 if strings .Contains (info .Name (), version ) {
@@ -308,7 +313,7 @@ func (rm *ReleaseManager) buildArtifactsJSON(
308313 URL : info .URL ,
309314 UploadedAt : time .Now (),
310315 }
311- case strings .HasSuffix (filename , ".sig" ):
316+ case strings .HasSuffix (filename , ".sig" ), strings . HasSuffix ( filename , ".asc" ) :
312317 plat .Signature = & storage.ArtifactFile {
313318 Filename : filename ,
314319 Size : fileInfo .Size ,
@@ -425,6 +430,7 @@ func getFileInfo(filename, url string, downloadResults []runtime.DownloadResult)
425430
426431// formatReleaseName generates the release name from template.
427432// This function is used in tests.
433+ //
428434//nolint:unused // Used in release_test.go
429435func (rm * ReleaseManager ) formatReleaseName (template , runtime , version string ) string {
430436 if template == "" {
0 commit comments