Add Go/Postgres admin APIs, Angular admin UI, manual build flow, asset uploads, markdown import/export, configurable slug generation, and the Yar reading theme. Exclude local docs and generated development artifacts from version control.
91 lines
1.7 KiB
Go
91 lines
1.7 KiB
Go
package admin
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"fmt"
|
|
"os/exec"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
type Builder struct {
|
|
store *Store
|
|
exporter *Exporter
|
|
siteDir string
|
|
queue chan string
|
|
once sync.Once
|
|
}
|
|
|
|
func NewBuilder(store *Store, exporter *Exporter, siteDir string) *Builder {
|
|
return &Builder{
|
|
store: store,
|
|
exporter: exporter,
|
|
siteDir: siteDir,
|
|
queue: make(chan string, 32),
|
|
}
|
|
}
|
|
|
|
func (b *Builder) Start(ctx context.Context) {
|
|
b.once.Do(func() {
|
|
go b.loop(ctx)
|
|
})
|
|
}
|
|
|
|
func (b *Builder) Enqueue(jobID string) bool {
|
|
select {
|
|
case b.queue <- jobID:
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
func (b *Builder) loop(ctx context.Context) {
|
|
for {
|
|
select {
|
|
case <-ctx.Done():
|
|
return
|
|
case jobID := <-b.queue:
|
|
b.runBuildJob(ctx, jobID)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (b *Builder) runBuildJob(ctx context.Context, jobID string) {
|
|
log, err := b.run(ctx, jobID)
|
|
if err != nil {
|
|
_ = b.store.MarkBuildJobFailed(context.Background(), jobID, log, err.Error())
|
|
return
|
|
}
|
|
_ = b.store.MarkBuildJobSuccess(context.Background(), jobID, log)
|
|
}
|
|
|
|
func (b *Builder) run(ctx context.Context, jobID string) (string, error) {
|
|
if err := b.store.MarkBuildJobRunning(ctx, jobID); err != nil {
|
|
return "", err
|
|
}
|
|
|
|
posts, err := b.store.PublishedPostsForExport(ctx)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if err := b.exporter.ExportPublishedPosts(ctx, posts); err != nil {
|
|
return "", err
|
|
}
|
|
|
|
buildCtx, cancel := context.WithTimeout(ctx, 2*time.Minute)
|
|
defer cancel()
|
|
|
|
cmd := exec.CommandContext(buildCtx, "npm", "run", "build")
|
|
cmd.Dir = b.siteDir
|
|
|
|
var output bytes.Buffer
|
|
cmd.Stdout = &output
|
|
cmd.Stderr = &output
|
|
if err := cmd.Run(); err != nil {
|
|
return output.String(), fmt.Errorf("astro build failed: %w", err)
|
|
}
|
|
|
|
return output.String(), nil
|
|
}
|