weiro/services/publisher/service.go

110 lines
2.4 KiB
Go

package publisher
import (
"context"
"log"
"os"
"emperror.dev/errors"
"github.com/go-openapi/runtime"
"github.com/go-openapi/strfmt"
"github.com/netlify/open-api/v2/go/porcelain"
netlify_ctx "github.com/netlify/open-api/v2/go/porcelain/context"
"lmika.dev/lmika/weiro/layouts/simplecss"
"lmika.dev/lmika/weiro/models"
"lmika.dev/lmika/weiro/models/pubmodel"
"lmika.dev/lmika/weiro/providers/db"
"lmika.dev/lmika/weiro/providers/sitebuilder"
)
type Publisher struct {
db *db.Provider
}
func New(db *db.Provider) *Publisher {
return &Publisher{
db: db,
}
}
func (p *Publisher) Publish(ctx context.Context, siteID int64) error {
// Fetch site, ensure user is owner
site, err := p.db.SelectSiteByID(ctx, siteID)
if err != nil {
return err
}
user, ok := models.GetUser(ctx)
if !ok {
return models.UserRequiredError
} else if user.ID != site.OwnerID {
return models.PermissionError
}
targets, err := p.db.SelectPublishTargetsOfSite(ctx, siteID)
if err != nil {
return err
}
// Fetch all content of site
posts, err := p.db.SelectPostsOfSite(ctx, siteID)
if err != nil {
return err
}
for _, target := range targets {
pubSite := pubmodel.Site{
Site: site,
Posts: posts,
BaseURL: target.BaseURL,
}
if err := p.publishSite(ctx, pubSite, target); err != nil {
return err
}
}
return nil
}
func (p *Publisher) publishSite(ctx context.Context, pubSite pubmodel.Site, target models.SitePublishTarget) error {
sb, err := sitebuilder.New(pubSite, sitebuilder.Options{
BasePosts: "/posts",
TemplatesFS: simplecss.FS,
})
if err != nil {
return err
}
switch target.TargetType {
case "localfs":
log.Printf("Building site at %s", target.TargetRef)
return sb.BuildSite(target.TargetRef)
case "netlify":
return func() error {
tmpDir, err := os.MkdirTemp("", "weiro-publish")
if err != nil {
return err
}
defer os.RemoveAll(tmpDir)
if err := sb.BuildSite(tmpDir); err != nil {
return err
}
ctx = netlify_ctx.WithAuthInfo(ctx, runtime.ClientAuthInfoWriterFunc(func(r runtime.ClientRequest, _ strfmt.Registry) error {
return r.SetHeaderParam("Authorization", "Bearer "+target.TargetKey)
}))
client := porcelain.Default
_, err = client.DeploySite(ctx, porcelain.DeployOptions{
SiteID: target.TargetRef,
Dir: tmpDir,
})
return err
}()
}
return errors.New("unknown target type")
}