Skip to content

Commit

Permalink
Add post upload hook
Browse files Browse the repository at this point in the history
  • Loading branch information
mrmelon54 committed Jan 8, 2025
1 parent e778f6c commit eb36349
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 8 deletions.
14 changes: 11 additions & 3 deletions cmd/bluebell/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/1f349/bluebell"
"github.com/1f349/bluebell/api"
"github.com/1f349/bluebell/conf"
"github.com/1f349/bluebell/hook"
"github.com/1f349/bluebell/logger"
"github.com/1f349/bluebell/serve"
"github.com/1f349/bluebell/upload"
Expand Down Expand Up @@ -69,15 +70,21 @@ func main() {

wd := filepath.Dir(*configPath)
sitesDir := filepath.Join(wd, "sites")
sitesPostHookDir := filepath.Join(wd, "hooks/post")

keyStore, err := mjwt.NewKeyStoreFromPath(filepath.Join(wd, "keystore"))
if err != nil {
logger.Logger.Fatal("Failed to load MJWT keystore", "dir", filepath.Join(wd, "keystore"), "err", err)
}

_, err = os.Stat(sitesDir)
err = os.MkdirAll(sitesDir, 0770)
if err != nil {
logger.Logger.Fatal("Failed to find sites, does the directory exist? Error: ", err)
logger.Logger.Fatal("Failed to find or create sites directory. Error: ", err)
}

err = os.MkdirAll(sitesPostHookDir, 0770)
if err != nil {
logger.Logger.Fatal("Failed to find or create sites directory. Error: ", err)
}

sitesFs := afero.NewBasePathFs(afero.NewOsFs(), sitesDir)
Expand Down Expand Up @@ -112,7 +119,8 @@ func main() {
}

serveHandler := serve.New(sitesFs, db)
uploadHandler := upload.New(sitesFs, db)
postHook := hook.New(sitesPostHookDir, sitesDir)
uploadHandler := upload.New(sitesFs, db, postHook)
apiHandler := api.New(uploadHandler, keyStore, db)

serverHttp := &http.Server{
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ require (
github.com/1f349/syncmap v0.0.3
github.com/charmbracelet/log v0.4.0
github.com/cloudflare/tableflip v1.2.3
github.com/cyphar/filepath-securejoin v0.3.6
github.com/dustin/go-humanize v1.0.1
github.com/golang-migrate/migrate/v4 v4.18.1
github.com/google/uuid v1.6.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ github.com/charmbracelet/x/ansi v0.6.0 h1:qOznutrb93gx9oMiGf7caF7bqqubh6YIM0SWKy
github.com/charmbracelet/x/ansi v0.6.0/go.mod h1:KBUFw1la39nl0dLl10l5ORDAqGXaeurTQmwyyVKse/Q=
github.com/cloudflare/tableflip v1.2.3 h1:8I+B99QnnEWPHOY3fWipwVKxS70LGgUsslG7CSfmHMw=
github.com/cloudflare/tableflip v1.2.3/go.mod h1:P4gRehmV6Z2bY5ao5ml9Pd8u6kuEnlB37pUFMmv7j2E=
github.com/cyphar/filepath-securejoin v0.3.6 h1:4d9N5ykBnSp5Xn2JkhocYDkOpURL/18CYMpo6xB9uWM=
github.com/cyphar/filepath-securejoin v0.3.6/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
Expand Down
33 changes: 33 additions & 0 deletions hook/hook.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package hook

import (
"github.com/cyphar/filepath-securejoin"
"os/exec"
"path/filepath"
)

type Hook struct {
hookDir string
sitesDir string
}

func New(hookDir string, sitesDir string) *Hook {
return &Hook{hookDir: hookDir, sitesDir: sitesDir}
}

func (h *Hook) Run(site, branch string) error {
sitePath, err := securejoin.SecureJoin(h.sitesDir, site+"/@"+branch)
if err != nil {
return err
}
scriptPath, err := securejoin.SecureJoin(h.hookDir, site)
if err != nil {
return err
}
cmd := exec.Cmd{
Path: scriptPath,
Args: []string{filepath.Base(scriptPath)},
Dir: sitePath,
}
return cmd.Run()
}
12 changes: 10 additions & 2 deletions upload/upload.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"errors"
"fmt"
"github.com/1f349/bluebell/database"
"github.com/1f349/bluebell/hook"
"github.com/1f349/bluebell/validation"
"github.com/1f349/syncmap"
"github.com/dustin/go-humanize"
Expand All @@ -34,8 +35,8 @@ type uploadQueries interface {
UpdateBranch(ctx context.Context, arg database.UpdateBranchParams) error
}

func New(storage afero.Fs, db uploadQueries) *Handler {
return &Handler{storageFs: storage, db: db}
func New(storage afero.Fs, db uploadQueries, hook *hook.Hook) *Handler {
return &Handler{storageFs: storage, db: db, postHook: hook}
}

const maxFileSize = 1 * humanize.GiByte
Expand All @@ -44,6 +45,7 @@ type Handler struct {
storageFs afero.Fs
db uploadQueries
mu syncmap.Map[string, *sync.Mutex]
postHook *hook.Hook
}

func (h *Handler) Handle(rw http.ResponseWriter, req *http.Request, params httprouter.Params) {
Expand Down Expand Up @@ -165,6 +167,12 @@ func (h *Handler) extractTarGzUpload(fileData io.Reader, site, branch string) er
}
}

// call the post hook script
err = h.postHook.Run(site, branch)
if err != nil {
return err
}

// TODO(melon): I would love to use unix.Renameat2 but due to afero this will not work

err = h.storageFs.Rename(siteBranchPath, siteBranchOldPath)
Expand Down
6 changes: 3 additions & 3 deletions upload/upload_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ func (f *fakeUploadDB) UpdateBranch(ctx context.Context, arg database.UpdateBran

func TestHandler_Handle(t *testing.T) {
fs := afero.NewMemMapFs()
h := New(fs, new(fakeUploadDB))
h := New(fs, new(fakeUploadDB), nil)

r := httprouter.New()
r.POST("/u/:site/:branch", h.Handle)
Expand Down Expand Up @@ -168,7 +168,7 @@ func extractTarGzUploadTest(t *testing.T, db uploadQueries) {
for _, branch := range []string{"main", "test", "dev"} {
t.Run(branch+" branch", func(t *testing.T) {
fs := afero.NewMemMapFs()
h := New(fs, db)
h := New(fs, db, nil)
buffer := bytes.NewBuffer(testArchiveTarGz)
assert.NoError(t, h.extractTarGzUpload(buffer, "example.com", branch))

Expand All @@ -188,7 +188,7 @@ func TestHandler_extractTarGzUpload_memoryDB_multiple(t *testing.T) {

func extractTarGzUploadMultipleTest(t *testing.T, db uploadQueries) {
fs := afero.NewMemMapFs()
h := New(fs, db)
h := New(fs, db, nil)
sig := new(atomic.Bool)
wg := new(sync.WaitGroup)

Expand Down

0 comments on commit eb36349

Please sign in to comment.