diff --git a/README.md b/README.md index 94b60f6..257ea7a 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,14 @@ # bids-hook Tiny CI server to run bids-validator using Gitea webhooks + + +## Deployment + +Results are placed in `%(GITEA_CUSTOM)/public/bids-validator/`; +this folder needs to be writable (and ideally created first and owned) +by the user running this daemon. + +It assumes the URL `%(ROOT_URL)s/static/assets/` loads from +Gitea's `%(GITEA_CUSTOM)/public/`; it is **not** compatible +with configuring Gitea's `%(STATIC_URL_PREFIX)` so that +static files are hosted on a different server or CDN. diff --git a/bids-hook.go b/bids-hook.go index 26c1ce5..a792ec6 100644 --- a/bids-hook.go +++ b/bids-hook.go @@ -16,7 +16,6 @@ import ( "net/url" "os" "os/exec" - "path" "path/filepath" "regexp" "strconv" @@ -43,27 +42,21 @@ var ( // this should be entered as-in in Gitea to configure the webhook bidsHookSecret []byte - // the base URL to reach Gitea's API - // read from environment variable GITEA_API_URL - // should end with "/api/v1" - giteaApiUrl *url.URL + // the base URL to reach Gitea + // read from environment variable GITEA_ROOT_URL + // should match Gitea's app.ini's [server].ROOT_URL + giteaRootUrl *url.URL // secret used to authenticate api calls from bids-hook to Gitea - // read from environment variable GITEA_API_SECRET + // read from environment variable GITEA_TOKEN // can be generated from a gitea admin account under "Settings" -> "Applications" - giteaApiSecret []byte + giteaToken []byte - // the base URL for writing links to Gitea's static assets - // read from environment variable GITEA_PUBLIC_URL - // should end with "/assets" - giteaPublicUrl *url.URL - - // the path to Gitea's static assets directory - // read from environment variable GITEA_PUBLIC_PATH + // the path to Gitea's custom/ directory + // read from environment variable GITEA_CUSTOM // used to save job result pages - // it should already exist - // should end with "/custom/public" - giteaPublicPath string + // see https://docs.gitea.io/en-us/config-cheat-sheet/#default-configuration-non-appini-configuration + giteaCustom string // executable run by the worker for each accepted job // read from environment variable WORKER_SCRIPT @@ -286,15 +279,13 @@ type job struct { // web link to the results page for this job // see also j.resultPath() func (j job) resultUrl() string { - url := *giteaPublicUrl - url.Path = path.Join(url.Path, fmt.Sprintf("%s.html", j.uuid)) - return url.String() + return giteaRootUrl.JoinPath("assets", fmt.Sprintf("%s.html", j.uuid)).String() } // file path to the results page for this job // see also j.resultUrl() func (j job) resultPath() string { - return filepath.Join(giteaPublicPath, fmt.Sprintf("%s.html", j.uuid)) + return filepath.Join(giteaCustom, "public", fmt.Sprintf("%s.html", j.uuid)) } // file path to the log file for this job @@ -305,8 +296,7 @@ func (j job) logPath() string { // postStatus posts a commit status to Gitea // 'state' should be one of the constants defined at the top of this module func (j job) postStatus(ctx context.Context, state string) error { - url := *giteaApiUrl - url.Path = path.Join(url.Path, "repos", j.user, j.repo, "statuses", j.commit) + url := giteaRootUrl.JoinPath("api", "v1", "repos", j.user, j.repo, "statuses", j.commit) var description, targetUrl string switch state { @@ -341,7 +331,7 @@ func (j job) postStatus(ctx context.Context, state string) error { if err != nil { return err } - req.Header.Add("Authorization", fmt.Sprintf("token %s", giteaApiSecret)) + req.Header.Add("Authorization", fmt.Sprintf("token %s", giteaToken)) req.Header.Add("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) @@ -451,44 +441,32 @@ func readConfig() { } bidsHookSecret = []byte(val) - val, ok = os.LookupEnv("GITEA_API_URL") + val, ok = os.LookupEnv("GITEA_ROOT_URL") if !ok { - log.Fatal("missing environment variable GITEA_API_URL") + log.Fatal("missing environment variable GITEA_ROOT_URL") } - giteaApiUrl, err = url.Parse(val) + giteaRootUrl, err = url.Parse(val) if err != nil { - log.Fatalf("error parsing GITEA_API_URL: %v", err) + log.Fatalf("error parsing GITEA_ROOT_URL: %v", err) } - val, ok = os.LookupEnv("GITEA_API_SECRET") + val, ok = os.LookupEnv("GITEA_TOKEN") if !ok { - log.Fatal("missing environment variable GITEA_API_SECRET") + log.Fatal("missing environment variable GITEA_TOKEN") } - giteaApiSecret = []byte(val) + giteaToken = []byte(val) - val, ok = os.LookupEnv("GITEA_PUBLIC_URL") + val, ok = os.LookupEnv("GITEA_CUSTOM") if !ok { - log.Fatal("missing environment variable GITEA_PUBLIC_URL") + log.Fatal("missing environment variable GITEA_CUSTOM") } - giteaPublicUrl, err = url.Parse(val) + giteaCustom, err = filepath.Abs(val) if err != nil { - log.Fatalf("error parsing GITEA_PUBLIC_URL: %v", err) - } - - val, ok = os.LookupEnv("GITEA_PUBLIC_PATH") - if !ok { - log.Fatal("missing environment variable GITEA_PUBLIC_PATH") + log.Fatalf("invalid GITEA_CUSTOM: %v", err) } - giteaPublicPath, err = filepath.Abs(val) + err = os.MkdirAll(filepath.Join(giteaCustom, "public"), 0750) if err != nil { - log.Fatalf("invalid GITEA_PUBLIC_PATH: %v", err) - } - info, err = os.Stat(giteaPublicPath) - if err != nil { - log.Fatalf("error opening GITEA_PUBLIC_PATH: %v", err) - } - if !info.IsDir() { - log.Fatal("GITEA_PUBLIC_PATH is not a directory") + log.Fatalf("error creating output folder: %v", err) } val, ok = os.LookupEnv("WORKER_SCRIPT") diff --git a/go.mod b/go.mod index 7b69f53..33f5627 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,3 @@ module github.com/neuropoly/bids-hook -go 1.18 +go 1.19 diff --git a/start b/start index c22ffb1..89be690 100755 --- a/start +++ b/start @@ -1,14 +1,26 @@ #!/bin/bash +set -e + +# this replicates the default location logic from https://docs.gitea.io/en-us/config-cheat-sheet/ +# any setting can be overridden just by setting its variable before calling this script +: ${GITEA_APP_PATH:=../gitea/gitea} +: ${GITEA_WORK_DIR:="$(dirname "$GITEA_APP_PATH")"} + +: ${GITEA_CUSTOM:="$GITEA_WORK_DIR/custom"} + +: ${GITEA_APP_DATA_PATH:="$GITEA_WORK_DIR/data"} +: ${GITEA_REPOSITORY_ROOT:="$GITEA_APP_DATA_PATH/gitea-repositories"} + +export GITEA_REPOSITORY_ROOT +export GITEA_CUSTOM + # 127.0.0.1 is localhost, and 2845 is 0xB1D export BIDS_HOOK_URL='http://127.0.0.1:2845/bids-hook' export BIDS_HOOK_SECRET='blabla' -export GITEA_API_URL='http://127.0.0.1:3000/api/v1' -export GITEA_API_SECRET='69e45fa9cfa75a7497633c6be8dd2347226e2f62' - -export GITEA_PUBLIC_URL='http://127.0.0.1:3000/assets' -export GITEA_PUBLIC_PATH='./custom/public' +export GITEA_ROOT_URL='http://127.0.0.1:3000' +export GITEA_TOKEN='69e45fa9cfa75a7497633c6be8dd2347226e2f62' export WORKER_SCRIPT='./worker' export WORKER_LOG_PATH='./log'