mirror of
https://github.com/stashapp/stash.git
synced 2025-12-06 08:26:00 +01:00
Build UI artifacts (#4824)
* Flag/env var for stash UI location * Include UI in build artifacts
This commit is contained in:
parent
237a904ca4
commit
408d6fc988
6 changed files with 90 additions and 29 deletions
15
.github/workflows/build.yml
vendored
15
.github/workflows/build.yml
vendored
|
|
@ -92,13 +92,16 @@ jobs:
|
|||
docker exec -t build /bin/bash -c "make build-cc-linux-arm32v6"
|
||||
docker exec -t build /bin/bash -c "make build-cc-freebsd"
|
||||
|
||||
- name: Zip UI
|
||||
run: docker exec -t build /bin/bash -c "make zip-ui"
|
||||
|
||||
- name: Cleanup build container
|
||||
run: docker rm -f -v build
|
||||
|
||||
- name: Generate checksums
|
||||
run: |
|
||||
git describe --tags --exclude latest_develop | tee CHECKSUMS_SHA1
|
||||
sha1sum dist/Stash.app.zip dist/stash-* | sed 's/dist\///g' | tee -a CHECKSUMS_SHA1
|
||||
sha1sum dist/Stash.app.zip dist/stash-* dist/stash-ui.zip | sed 's/dist\///g' | tee -a CHECKSUMS_SHA1
|
||||
echo "STASH_VERSION=$(git describe --tags --exclude latest_develop)" >> $GITHUB_ENV
|
||||
echo "RELEASE_DATE=$(date +'%Y-%m-%d %H:%M:%S %Z')" >> $GITHUB_ENV
|
||||
|
||||
|
|
@ -126,6 +129,14 @@ jobs:
|
|||
name: stash-linux
|
||||
path: dist/stash-linux
|
||||
|
||||
- name: Upload UI
|
||||
# only upload for pull requests
|
||||
if: ${{ github.event_name == 'pull_request' && github.base_ref != 'refs/heads/develop' && github.base_ref != 'refs/heads/master'}}
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: stash-ui.zip
|
||||
path: dist/stash-ui.zip
|
||||
|
||||
- name: Update latest_develop tag
|
||||
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/develop' }}
|
||||
run : git tag -f latest_develop; git push -f --tags
|
||||
|
|
@ -147,6 +158,7 @@ jobs:
|
|||
dist/stash-linux-arm32v7
|
||||
dist/stash-linux-arm32v6
|
||||
dist/stash-freebsd
|
||||
dist/stash-ui.zip
|
||||
CHECKSUMS_SHA1
|
||||
|
||||
- name: Master release
|
||||
|
|
@ -166,6 +178,7 @@ jobs:
|
|||
dist/stash-linux-arm32v7
|
||||
dist/stash-linux-arm32v6
|
||||
dist/stash-freebsd
|
||||
dist/stash-ui.zip
|
||||
CHECKSUMS_SHA1
|
||||
gzip: false
|
||||
|
||||
|
|
|
|||
5
Makefile
5
Makefile
|
|
@ -353,6 +353,11 @@ endif
|
|||
ui: ui-env
|
||||
cd ui/v2.5 && yarn build
|
||||
|
||||
.PHONY: zip-ui
|
||||
zip-ui:
|
||||
rm -f dist/stash-ui.zip
|
||||
cd ui/v2.5/build && zip -r ../../../dist/stash-ui.zip .
|
||||
|
||||
.PHONY: ui-start
|
||||
ui-start: ui-env
|
||||
cd ui/v2.5 && yarn start --host
|
||||
|
|
|
|||
|
|
@ -53,6 +53,28 @@ type Server struct {
|
|||
manager *manager.Manager
|
||||
}
|
||||
|
||||
// TODO - os.DirFS doesn't implement ReadDir, so re-implement it here
|
||||
// This can be removed when we upgrade go
|
||||
type osFS string
|
||||
|
||||
func (dir osFS) ReadDir(name string) ([]os.DirEntry, error) {
|
||||
fullname := string(dir) + "/" + name
|
||||
entries, err := os.ReadDir(fullname)
|
||||
if err != nil {
|
||||
var e *os.PathError
|
||||
if errors.As(err, &e) {
|
||||
// See comment in dirFS.Open.
|
||||
e.Path = name
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return entries, nil
|
||||
}
|
||||
|
||||
func (dir osFS) Open(name string) (fs.File, error) {
|
||||
return os.DirFS(string(dir)).Open(name)
|
||||
}
|
||||
|
||||
// Called at startup
|
||||
func Initialize() (*Server, error) {
|
||||
mgr := manager.GetInstance()
|
||||
|
|
@ -213,25 +235,31 @@ func Initialize() (*Server, error) {
|
|||
r.Mount("/custom", getCustomRoutes(customServedFolders))
|
||||
}
|
||||
|
||||
customUILocation := cfg.GetCustomUILocation()
|
||||
staticUI := statigz.FileServer(ui.UIBox.(fs.ReadDirFS))
|
||||
var uiFS fs.FS
|
||||
var staticUI *statigz.Server
|
||||
customUILocation := cfg.GetUILocation()
|
||||
if customUILocation != "" {
|
||||
logger.Debugf("Serving UI from %s", customUILocation)
|
||||
uiFS = osFS(customUILocation)
|
||||
staticUI = statigz.FileServer(uiFS.(fs.ReadDirFS))
|
||||
} else {
|
||||
logger.Debug("Serving embedded UI")
|
||||
uiFS = ui.UIBox
|
||||
staticUI = statigz.FileServer(ui.UIBox.(fs.ReadDirFS))
|
||||
}
|
||||
|
||||
// Serve the web app
|
||||
r.HandleFunc("/*", func(w http.ResponseWriter, r *http.Request) {
|
||||
ext := path.Ext(r.URL.Path)
|
||||
|
||||
if customUILocation != "" {
|
||||
if r.URL.Path == "index.html" || ext == "" {
|
||||
r.URL.Path = "/"
|
||||
}
|
||||
|
||||
http.FileServer(http.Dir(customUILocation)).ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
if ext == ".html" || ext == "" {
|
||||
w.Header().Set("Content-Type", "text/html")
|
||||
setPageSecurityHeaders(w, r, pluginCache.ListPlugins())
|
||||
}
|
||||
|
||||
if ext == "" || r.URL.Path == "/" || r.URL.Path == "/index.html" {
|
||||
themeColor := cfg.GetThemeColor()
|
||||
data, err := fs.ReadFile(ui.UIBox, "index.html")
|
||||
data, err := fs.ReadFile(uiFS, "index.html")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
|
@ -241,9 +269,6 @@ func Initialize() (*Server, error) {
|
|||
indexHtml = strings.ReplaceAll(indexHtml, "%COLOR%", themeColor)
|
||||
indexHtml = strings.Replace(indexHtml, `<base href="/"`, fmt.Sprintf(`<base href="%s/"`, prefix), 1)
|
||||
|
||||
w.Header().Set("Content-Type", "text/html")
|
||||
setPageSecurityHeaders(w, r, pluginCache.ListPlugins())
|
||||
|
||||
utils.ServeStaticContent(w, r, []byte(indexHtml))
|
||||
} else {
|
||||
isStatic, _ := path.Match("/assets/*", r.URL.Path)
|
||||
|
|
|
|||
|
|
@ -159,7 +159,10 @@ const (
|
|||
|
||||
// UI directory. Overrides to serve the UI from a specific location
|
||||
// rather than use the embedded UI.
|
||||
CustomUILocation = "custom_ui_location"
|
||||
UILocation = "ui_location"
|
||||
|
||||
// backwards compatible name
|
||||
LegacyCustomUILocation = "custom_ui_location"
|
||||
|
||||
// Gallery Cover Regex
|
||||
GalleryCoverRegex = "gallery_cover_regex"
|
||||
|
|
@ -1057,8 +1060,12 @@ func (i *Config) GetCustomServedFolders() utils.URLMap {
|
|||
return i.getStringMapString(CustomServedFolders)
|
||||
}
|
||||
|
||||
func (i *Config) GetCustomUILocation() string {
|
||||
return i.getString(CustomUILocation)
|
||||
func (i *Config) GetUILocation() string {
|
||||
if ret := i.getString(UILocation); ret != "" {
|
||||
return ret
|
||||
}
|
||||
|
||||
return i.getString(LegacyCustomUILocation)
|
||||
}
|
||||
|
||||
// Interface options
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ func TestConcurrentConfigAccess(t *testing.T) {
|
|||
i.GetCredentials()
|
||||
i.Set(MaxSessionAge, i.GetMaxSessionAge())
|
||||
i.Set(CustomServedFolders, i.GetCustomServedFolders())
|
||||
i.Set(CustomUILocation, i.GetCustomUILocation())
|
||||
i.Set(LegacyCustomUILocation, i.GetUILocation())
|
||||
i.Set(MenuItems, i.GetMenuItems())
|
||||
i.Set(SoundOnPreview, i.GetSoundOnPreview())
|
||||
i.Set(WallShowTitle, i.GetWallShowTitle())
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import (
|
|||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
"github.com/spf13/viper"
|
||||
|
|
@ -26,6 +27,7 @@ func init() {
|
|||
pflag.Int("port", 9999, "port to serve from")
|
||||
pflag.StringVarP(&flags.configFilePath, "config", "c", "", "config file to use")
|
||||
pflag.BoolVar(&flags.nobrowser, "nobrowser", false, "Don't open a browser window after launch")
|
||||
pflag.StringP("ui-location", "u", "", "path to the webui")
|
||||
}
|
||||
|
||||
// Called at startup
|
||||
|
|
@ -82,8 +84,8 @@ func InitializeEmpty() *Config {
|
|||
return instance
|
||||
}
|
||||
|
||||
func bindEnv(v *viper.Viper, key string) {
|
||||
if err := v.BindEnv(key); err != nil {
|
||||
func bindEnv(v *viper.Viper, key ...string) {
|
||||
if err := v.BindEnv(key...); err != nil {
|
||||
panic(fmt.Sprintf("unable to set environment key (%v): %v", key, err))
|
||||
}
|
||||
}
|
||||
|
|
@ -91,6 +93,14 @@ func bindEnv(v *viper.Viper, key string) {
|
|||
func (i *Config) initOverrides() {
|
||||
v := i.overrides
|
||||
|
||||
// replace dashes with underscores in the flag names
|
||||
normalizeFn := pflag.CommandLine.GetNormalizeFunc()
|
||||
pflag.CommandLine.SetNormalizeFunc(func(f *pflag.FlagSet, name string) pflag.NormalizedName {
|
||||
result := normalizeFn(f, name)
|
||||
name = strings.ReplaceAll(string(result), "-", "_")
|
||||
return pflag.NormalizedName(name)
|
||||
})
|
||||
|
||||
if err := v.BindPFlags(pflag.CommandLine); err != nil {
|
||||
logger.Infof("failed to bind flags: %v", err)
|
||||
}
|
||||
|
|
@ -103,6 +113,7 @@ func (i *Config) initOverrides() {
|
|||
bindEnv(v, "metadata") // STASH_METADATA
|
||||
bindEnv(v, "cache") // STASH_CACHE
|
||||
bindEnv(v, "stash") // STASH_STASH
|
||||
bindEnv(v, "ui_location", "STASH_UI") // STASH_UI
|
||||
}
|
||||
|
||||
func (i *Config) initConfig() error {
|
||||
|
|
|
|||
Loading…
Reference in a new issue