@@ -25,9 +25,12 @@ import (
2525 "text/template"
2626
2727 "github.com/bep/logg"
28+ "github.com/gohugoio/hugoreleaser-plugins-api/model"
2829 "github.com/gohugoio/hugoreleaser/cmd/corecmd"
30+ "github.com/gohugoio/hugoreleaser/internal/common/matchers"
2931 "github.com/gohugoio/hugoreleaser/internal/common/templ"
3032 "github.com/gohugoio/hugoreleaser/internal/config"
33+ "github.com/gohugoio/hugoreleaser/internal/publish/publishformats"
3134 "github.com/gohugoio/hugoreleaser/internal/releases"
3235 "github.com/gohugoio/hugoreleaser/staticfiles"
3336 "github.com/peterbourgon/ff/v3/ffcli"
@@ -46,7 +49,7 @@ func New(core *corecmd.Core) *ffcli.Command {
4649 return & ffcli.Command {
4750 Name : commandName ,
4851 ShortUsage : corecmd .CommandName + " publish [flags]" ,
49- ShortHelp : "Publish a draft release and update package managers." ,
52+ ShortHelp : "Publish releases and update package managers." ,
5053 FlagSet : fs ,
5154 Exec : publisher .Exec ,
5255 }
@@ -77,21 +80,43 @@ func (p *Publisher) Exec(ctx context.Context, args []string) error {
7780 return err
7881 }
7982
80- // Get release settings from config.
81- if len ( p . core . Config . Releases ) == 0 {
82- return fmt . Errorf ( "%s: no releases defined in config" , commandName )
83+ if len ( p . core . Config . Publishers ) == 0 {
84+ p . infoLog . Log ( logg . String ( "No publishers configured" ))
85+ return nil
8386 }
8487
85- // Use first release for settings (consistent with release command behavior).
86- release := p .core .Config .Releases [0 ]
87- settings := release .ReleaseSettings
88-
8988 logFields := logg.Fields {
9089 {Name : "tag" , Value : p .core .Tag },
91- {Name : "repository" , Value : fmt .Sprintf ("%s/%s" , settings .RepositoryOwner , settings .Repository )},
9290 }
9391 logCtx := p .infoLog .WithFields (logFields )
9492
93+ // Process each publisher.
94+ for i := range p .core .Config .Publishers {
95+ pub := & p .core .Config .Publishers [i ]
96+
97+ if len (pub .ReleasesCompiled ) == 0 {
98+ continue
99+ }
100+
101+ // Process each release that matches this publisher.
102+ for _ , release := range pub .ReleasesCompiled {
103+ if err := p .handlePublisher (ctx , logCtx , pub , release ); err != nil {
104+ return err
105+ }
106+ }
107+ }
108+
109+ return nil
110+ }
111+
112+ func (p * Publisher ) handlePublisher (
113+ ctx context.Context ,
114+ logCtx logg.LevelLogger ,
115+ pub * config.Publisher ,
116+ release * config.Release ,
117+ ) error {
118+ settings := release .ReleaseSettings
119+
95120 // Create client.
96121 var client releases.PublishClient
97122 if p .core .Try {
@@ -108,7 +133,31 @@ func (p *Publisher) Exec(ctx context.Context, args []string) error {
108133 }
109134 }
110135
111- // Step 1: Check and publish the GitHub release.
136+ switch pub .Type .FormatParsed {
137+ case publishformats .GitHubRelease :
138+ return p .publishGitHubRelease (ctx , logCtx , client , release )
139+ case publishformats .HomebrewCask :
140+ return p .updateHomebrewCask (ctx , logCtx , client , pub , release )
141+ case publishformats .Plugin :
142+ return fmt .Errorf ("%s: plugin publishers not yet implemented" , commandName )
143+ default :
144+ return fmt .Errorf ("%s: unknown publisher format: %s" , commandName , pub .Type .Format )
145+ }
146+ }
147+
148+ func (p * Publisher ) publishGitHubRelease (
149+ ctx context.Context ,
150+ logCtx logg.LevelLogger ,
151+ client releases.PublishClient ,
152+ release * config.Release ,
153+ ) error {
154+ settings := release .ReleaseSettings
155+
156+ logCtx = logCtx .WithFields (logg.Fields {
157+ {Name : "action" , Value : "github_release" },
158+ {Name : "repository" , Value : fmt .Sprintf ("%s/%s" , settings .RepositoryOwner , settings .Repository )},
159+ })
160+
112161 logCtx .Log (logg .String ("Checking release status" ))
113162
114163 releaseID , isDraft , err := client .GetReleaseByTag (ctx , settings .RepositoryOwner , settings .Repository , p .core .Tag )
@@ -126,17 +175,20 @@ func (p *Publisher) Exec(ctx context.Context, args []string) error {
126175 logCtx .Log (logg .String ("Release is already published" ))
127176 }
128177
129- // Step 2: Update Homebrew cask if enabled.
130- caskSettings := p .core .Config .PublishSettings .HomebrewCask
131- if caskSettings .Enabled {
132- if err := p .updateHomebrewCask (ctx , logCtx , client , release , caskSettings ); err != nil {
133- return fmt .Errorf ("%s: failed to update Homebrew cask: %v" , commandName , err )
134- }
135- }
136-
137178 return nil
138179}
139180
181+ // HomebrewCaskSettings holds the custom settings for homebrew_cask publisher.
182+ type HomebrewCaskSettings struct {
183+ BundleIdentifier string `mapstructure:"bundle_identifier"`
184+ TapRepository string `mapstructure:"tap_repository"`
185+ Name string `mapstructure:"name"`
186+ CaskPath string `mapstructure:"cask_path"`
187+ TemplateFilename string `mapstructure:"template_filename"`
188+ Description string `mapstructure:"description"`
189+ Homepage string `mapstructure:"homepage"`
190+ }
191+
140192// HomebrewCaskContext holds data for the Homebrew cask template.
141193type HomebrewCaskContext struct {
142194 Name string
@@ -154,17 +206,34 @@ func (p *Publisher) updateHomebrewCask(
154206 ctx context.Context ,
155207 logCtx logg.LevelLogger ,
156208 client releases.PublishClient ,
157- release config.Release ,
158- caskSettings config.HomebrewCaskSettings ,
209+ pub * config.Publisher ,
210+ release * config.Release ,
159211) error {
160- logCtx = logCtx .WithField ("action" , "homebrew-cask " )
212+ logCtx = logCtx .WithField ("action" , "homebrew_cask " )
161213 logCtx .Log (logg .String ("Updating Homebrew cask" ))
162214
163215 releaseSettings := release .ReleaseSettings
164216 version := strings .TrimPrefix (p .core .Tag , "v" )
165217
166- // Find the first .pkg archive matching the path pattern.
167- pkgInfo , err := p .findPkgArchive (release , caskSettings )
218+ // Read settings from custom_settings.
219+ settings , err := model.FromMap [any , HomebrewCaskSettings ](pub .CustomSettings )
220+ if err != nil {
221+ return fmt .Errorf ("failed to parse homebrew_cask settings: %w" , err )
222+ }
223+
224+ // Apply defaults.
225+ if settings .TapRepository == "" {
226+ settings .TapRepository = "homebrew-tap"
227+ }
228+ if settings .Name == "" {
229+ settings .Name = p .core .Config .Project
230+ }
231+ if settings .CaskPath == "" {
232+ settings .CaskPath = fmt .Sprintf ("Casks/%s.rb" , settings .Name )
233+ }
234+
235+ // Find the first .pkg archive matching the archive paths pattern.
236+ pkgInfo , err := p .findPkgArchive (release , pub .ArchivePathsCompiled )
168237 if err != nil {
169238 return err
170239 }
@@ -182,23 +251,23 @@ func (p *Publisher) updateHomebrewCask(
182251
183252 // Build cask context.
184253 caskCtx := HomebrewCaskContext {
185- Name : caskSettings .Name ,
254+ Name : settings .Name ,
186255 DisplayName : p .core .Config .Project ,
187256 Version : version ,
188257 SHA256 : pkgInfo .SHA256 ,
189258 URL : downloadURL ,
190- Description : caskSettings .Description ,
191- Homepage : caskSettings .Homepage ,
259+ Description : settings .Description ,
260+ Homepage : settings .Homepage ,
192261 PkgFilename : pkgInfo .Name ,
193- BundleIdentifier : caskSettings .BundleIdentifier ,
262+ BundleIdentifier : settings .BundleIdentifier ,
194263 }
195264
196265 // Render cask template.
197266 var caskContent bytes.Buffer
198267 var tmpl * template.Template
199268
200- if caskSettings .TemplateFilename != "" {
201- templatePath := caskSettings .TemplateFilename
269+ if settings .TemplateFilename != "" {
270+ templatePath := settings .TemplateFilename
202271 if ! filepath .IsAbs (templatePath ) {
203272 templatePath = filepath .Join (p .core .ProjectDir , templatePath )
204273 }
@@ -219,11 +288,11 @@ func (p *Publisher) updateHomebrewCask(
219288 }
220289
221290 // Update file in tap repository.
222- commitMessage := fmt .Sprintf ("Update %s to %s" , caskSettings .Name , p .core .Tag )
291+ commitMessage := fmt .Sprintf ("Update %s to %s" , settings .Name , p .core .Tag )
223292
224293 logCtx .WithFields (logg.Fields {
225- {Name : "tap" , Value : fmt .Sprintf ("%s/%s" , releaseSettings .RepositoryOwner , caskSettings .TapRepository )},
226- {Name : "path" , Value : caskSettings .CaskPath },
294+ {Name : "tap" , Value : fmt .Sprintf ("%s/%s" , releaseSettings .RepositoryOwner , settings .TapRepository )},
295+ {Name : "path" , Value : settings .CaskPath },
227296 }).Log (logg .String ("Committing cask update" ))
228297
229298 if p .core .Try {
@@ -234,8 +303,8 @@ func (p *Publisher) updateHomebrewCask(
234303 sha , err := client .UpdateFileInRepo (
235304 ctx ,
236305 releaseSettings .RepositoryOwner ,
237- caskSettings .TapRepository ,
238- caskSettings .CaskPath ,
306+ settings .TapRepository ,
307+ settings .CaskPath ,
239308 commitMessage ,
240309 caskContent .Bytes (),
241310 )
@@ -253,18 +322,16 @@ type pkgArchiveInfo struct {
253322 SHA256 string
254323}
255324
256- // findPkgArchive finds the first .pkg archive for darwin matching the path pattern.
257- func (p * Publisher ) findPkgArchive (release config.Release , caskSettings config.HomebrewCaskSettings ) (pkgArchiveInfo , error ) {
258- pathMatcher := caskSettings .PathCompiled
259-
325+ // findPkgArchive finds the first .pkg archive for darwin matching the archive paths pattern.
326+ func (p * Publisher ) findPkgArchive (release * config.Release , archivePathsMatcher matchers.Matcher ) (pkgArchiveInfo , error ) {
260327 for _ , archPath := range release .ArchsCompiled {
261328 // Only consider darwin archives.
262329 if archPath .Arch .Os == nil || archPath .Arch .Os .Goos != "darwin" {
263330 continue
264331 }
265332
266333 // Check if the path matches the pattern.
267- if pathMatcher != nil && ! pathMatcher .Match (archPath .Path ) {
334+ if archivePathsMatcher != nil && ! archivePathsMatcher .Match (archPath .Path ) {
268335 continue
269336 }
270337
@@ -277,5 +344,5 @@ func (p *Publisher) findPkgArchive(release config.Release, caskSettings config.H
277344 }
278345 }
279346
280- return pkgArchiveInfo {}, fmt .Errorf ("no .pkg archive found for darwin matching path pattern %q" , caskSettings . Path )
347+ return pkgArchiveInfo {}, fmt .Errorf ("no .pkg archive found for darwin" )
281348}
0 commit comments