feat: add admin publishing workflow and yar theme
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.
This commit is contained in:
parent
b78f4b39c9
commit
f0b50d13ea
121 changed files with 27139 additions and 550 deletions
91
backend/internal/admin/builder.go
Normal file
91
backend/internal/admin/builder.go
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
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
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue