#60: Bugfixes for production
This commit is contained in:
@@ -3,10 +3,13 @@ ORG_ID=Shuffle
|
|||||||
ENVIRONMENT_NAME=Shuffle
|
ENVIRONMENT_NAME=Shuffle
|
||||||
|
|
||||||
# Different locations etc
|
# Different locations etc
|
||||||
APP_DOWNLOAD_LOCATION=https://github.com/frikky/shuffle-apps
|
APP_DOWNLOAD_LOCATION=https://github.com/frikky/shuffle-apps # Remote location to download
|
||||||
APP_DOWNLOAD_AUTH_USERNAME=""
|
APP_DOWNLOAD_AUTH_USERNAME=""
|
||||||
APP_DOWNLOAD_AUTH_PASSWORD=""
|
APP_DOWNLOAD_AUTH_PASSWORD=""
|
||||||
|
|
||||||
|
# Local location of your app directory. Can't use ~/ or ./
|
||||||
|
APP_HOTLOAD_LOCATION="shuffle-apps"
|
||||||
|
|
||||||
# Other configs
|
# Other configs
|
||||||
BACKEND_HOSTNAME=shuffle-backend
|
BACKEND_HOSTNAME=shuffle-backend
|
||||||
BACKEND_PORT=5001
|
BACKEND_PORT=5001
|
||||||
|
|||||||
+10
-7
@@ -39,7 +39,6 @@ import (
|
|||||||
|
|
||||||
"github.com/go-git/go-billy/v5"
|
"github.com/go-git/go-billy/v5"
|
||||||
"github.com/go-git/go-billy/v5/memfs"
|
"github.com/go-git/go-billy/v5/memfs"
|
||||||
"github.com/go-git/go-billy/v5/osfs"
|
|
||||||
"github.com/go-git/go-git/v5"
|
"github.com/go-git/go-git/v5"
|
||||||
"github.com/go-git/go-git/v5/storage/memory"
|
"github.com/go-git/go-git/v5/storage/memory"
|
||||||
|
|
||||||
@@ -5794,8 +5793,9 @@ func healthCheckHandler(resp http.ResponseWriter, request *http.Request) {
|
|||||||
|
|
||||||
// Creates osfs from folderpath with a basepath as directory base
|
// Creates osfs from folderpath with a basepath as directory base
|
||||||
func createFs(basepath, pathname string) (billy.Filesystem, error) {
|
func createFs(basepath, pathname string) (billy.Filesystem, error) {
|
||||||
fs := osfs.New("")
|
log.Printf("base: %s, pathname: %s", basepath, pathname)
|
||||||
|
|
||||||
|
fs := memfs.New()
|
||||||
err := filepath.Walk(pathname,
|
err := filepath.Walk(pathname,
|
||||||
func(path string, info os.FileInfo, err error) error {
|
func(path string, info os.FileInfo, err error) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -5806,7 +5806,10 @@ func createFs(basepath, pathname string) (billy.Filesystem, error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
fullpath := fmt.Sprintf("%s%s", basepath, path)
|
// Fix the inner path here
|
||||||
|
newpath := strings.ReplaceAll(path, pathname, "")
|
||||||
|
fullpath := fmt.Sprintf("%s%s", basepath, newpath)
|
||||||
|
log.Printf("Fullpath: %s", fullpath)
|
||||||
switch mode := info.Mode(); {
|
switch mode := info.Mode(); {
|
||||||
case mode.IsDir():
|
case mode.IsDir():
|
||||||
err = fs.MkdirAll(fullpath, 0644)
|
err = fs.MkdirAll(fullpath, 0644)
|
||||||
@@ -5845,23 +5848,23 @@ func createFs(basepath, pathname string) (billy.Filesystem, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Hotloads new apps from a folder
|
// Hotloads new apps from a folder
|
||||||
// FIXME: Not finished
|
|
||||||
func handleAppHotload(location string) error {
|
func handleAppHotload(location string) error {
|
||||||
basepath := "base"
|
basepath := "base"
|
||||||
fs, err := createFs(basepath, location)
|
fs, err := createFs(basepath, location)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Failed making files and stuff: %s", err)
|
log.Printf("Failed memfs creation - probably bad path: %s", err)
|
||||||
return err
|
return err
|
||||||
} else {
|
} else {
|
||||||
log.Printf("Hotloading from %s finished", location)
|
log.Printf("Memfs creation from %s done", location)
|
||||||
}
|
}
|
||||||
|
|
||||||
dir, err := fs.ReadDir(basepath)
|
dir, err := fs.ReadDir("")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Failed reading folder: %s", err)
|
log.Printf("Failed reading folder: %s", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Printf("Reading app folder: %#v", dir)
|
||||||
err = iterateAppGithubFolders(fs, dir, "", "")
|
err = iterateAppGithubFolders(fs, dir, "", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Err: %s", err)
|
log.Printf("Err: %s", err)
|
||||||
|
|||||||
+17
-12
@@ -3444,6 +3444,7 @@ func handleAppHotloadRequest(resp http.ResponseWriter, request *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Printf("Hotloading from %s", location)
|
||||||
err = handleAppHotload(location)
|
err = handleAppHotload(location)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resp.WriteHeader(500)
|
resp.WriteHeader(500)
|
||||||
@@ -3699,13 +3700,13 @@ func iterateWorkflowGithubFolders(fs billy.Filesystem, dir []os.FileInfo, extra
|
|||||||
dir, err := fs.ReadDir(tmpExtra)
|
dir, err := fs.ReadDir(tmpExtra)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Failed to read dir: %s", err)
|
log.Printf("Failed to read dir: %s", err)
|
||||||
break
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Go routine? Hmm, this can be super quick I guess
|
// Go routine? Hmm, this can be super quick I guess
|
||||||
err = iterateWorkflowGithubFolders(fs, dir, tmpExtra, "")
|
err = iterateWorkflowGithubFolders(fs, dir, tmpExtra, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
continue
|
||||||
}
|
}
|
||||||
case mode.IsRegular():
|
case mode.IsRegular():
|
||||||
// Check the file
|
// Check the file
|
||||||
@@ -3759,28 +3760,32 @@ func iterateAppGithubFolders(fs billy.Filesystem, dir []os.FileInfo, extra strin
|
|||||||
dir, err := fs.ReadDir(tmpExtra)
|
dir, err := fs.ReadDir(tmpExtra)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Failed to read dir: %s", err)
|
log.Printf("Failed to read dir: %s", err)
|
||||||
break
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Go routine? Hmm, this can be super quick I guess
|
// Go routine? Hmm, this can be super quick I guess
|
||||||
err = iterateAppGithubFolders(fs, dir, tmpExtra, "")
|
err = iterateAppGithubFolders(fs, dir, tmpExtra, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
log.Printf("Error reading folder: %s", err)
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
case mode.IsRegular():
|
case mode.IsRegular():
|
||||||
// Check the file
|
// Check the file
|
||||||
filename := file.Name()
|
filename := file.Name()
|
||||||
if filename == "Dockerfile" {
|
if filename == "Dockerfile" {
|
||||||
|
|
||||||
// Quick Dockerfile check
|
// Quick Dockerfile check
|
||||||
dockerdata, err := ioutil.ReadFile(fmt.Sprintf("%sDockerfile", extra))
|
//dockerfile := fmt.Sprintf("%sDockerfile", extra)
|
||||||
if err != nil {
|
//log.Printf("Handling Dockerfile %s", dockerfile)
|
||||||
continue
|
//dockerdata, err := ioutil.ReadFile(dockerfile)
|
||||||
}
|
//if err != nil {
|
||||||
|
// log.Printf("Failed to read dockerfile")
|
||||||
|
// continue
|
||||||
|
//}
|
||||||
|
|
||||||
if len(dockerdata) == 0 {
|
//if len(dockerdata) == 0 {
|
||||||
continue
|
// log.Printf("Dockerfile is empty")
|
||||||
}
|
// continue
|
||||||
|
//}
|
||||||
|
|
||||||
log.Printf("Handle Dockerfile in location %s", extra)
|
log.Printf("Handle Dockerfile in location %s", extra)
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -1,7 +1,7 @@
|
|||||||
version: '3'
|
version: '3'
|
||||||
services:
|
services:
|
||||||
frontend:
|
frontend:
|
||||||
#build: ./frontend
|
build: ./frontend
|
||||||
image: frikky/shuffle:frontend
|
image: frikky/shuffle:frontend
|
||||||
container_name: shuffle-frontend
|
container_name: shuffle-frontend
|
||||||
hostname: shuffle-frontend
|
hostname: shuffle-frontend
|
||||||
@@ -25,6 +25,7 @@ services:
|
|||||||
- shuffle
|
- shuffle
|
||||||
volumes:
|
volumes:
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
- ${APP_HOTLOAD_LOCATION}=/shuffle-apps # Local
|
||||||
environment:
|
environment:
|
||||||
- ORG_ID=${ORG_ID}
|
- ORG_ID=${ORG_ID}
|
||||||
- DATASTORE_EMULATOR_HOST=shuffle-database:8000
|
- DATASTORE_EMULATOR_HOST=shuffle-database:8000
|
||||||
|
|||||||
+45
-2
@@ -20,6 +20,7 @@ import YAML from 'yaml'
|
|||||||
import {Link} from 'react-router-dom';
|
import {Link} from 'react-router-dom';
|
||||||
import Breadcrumbs from '@material-ui/core/Breadcrumbs';
|
import Breadcrumbs from '@material-ui/core/Breadcrumbs';
|
||||||
|
|
||||||
|
import CachedIcon from '@material-ui/icons/Cached';
|
||||||
import CloudDownloadIcon from '@material-ui/icons/CloudDownload';
|
import CloudDownloadIcon from '@material-ui/icons/CloudDownload';
|
||||||
import PublishIcon from '@material-ui/icons/Publish';
|
import PublishIcon from '@material-ui/icons/Publish';
|
||||||
import CloudDownload from '@material-ui/icons/CloudDownload';
|
import CloudDownload from '@material-ui/icons/CloudDownload';
|
||||||
@@ -348,7 +349,7 @@ const Apps = (props) => {
|
|||||||
Activate App
|
Activate App
|
||||||
</Button></Link> : null
|
</Button></Link> : null
|
||||||
|
|
||||||
var deleteButton = ((selectedApp.private_id !== undefined && selectedApp.private_id.length > 0 && selectedApp.generated) || (selectedApp.downloaded != undefined && selectedApp.downloaded === true)) && activateButton === null ?
|
var deleteButton = ((selectedApp.private_id !== undefined && selectedApp.private_id.length > 0 && selectedApp.generated) || (selectedApp.downloaded != undefined && selectedApp.downloaded == true)) && activateButton === null ?
|
||||||
<Button
|
<Button
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
component="label"
|
component="label"
|
||||||
@@ -536,7 +537,7 @@ const Apps = (props) => {
|
|||||||
<div style={{flex: 1, marginLeft: 10, marginRight: 10}}>
|
<div style={{flex: 1, marginLeft: 10, marginRight: 10}}>
|
||||||
<div style={{display: "flex"}}>
|
<div style={{display: "flex"}}>
|
||||||
<div style={{flex: 1}}>
|
<div style={{flex: 1}}>
|
||||||
<h2>Available integrations</h2>
|
<h2>All apps</h2>
|
||||||
</div>
|
</div>
|
||||||
{isLoading ? <CircularProgress style={{marginTop: 13, marginRight: 15}} /> : null}
|
{isLoading ? <CircularProgress style={{marginTop: 13, marginRight: 15}} /> : null}
|
||||||
<FormControlLabel
|
<FormControlLabel
|
||||||
@@ -547,6 +548,19 @@ const Apps = (props) => {
|
|||||||
setSearchBackend(!searchBackend)}
|
setSearchBackend(!searchBackend)}
|
||||||
} />}
|
} />}
|
||||||
/>
|
/>
|
||||||
|
<Tooltip title={"Reload apps locally"} style={{marginTop: "28px", width: "100%"}} aria-label={"Upload"}>
|
||||||
|
<Button
|
||||||
|
variant="outlined"
|
||||||
|
component="label"
|
||||||
|
color="primary"
|
||||||
|
style={{margin: 5, maxHeight: 50, marginTop: 10}}
|
||||||
|
onClick={() => {
|
||||||
|
hotloadApps()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CachedIcon />
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
<Tooltip title={"Download from Github"} style={{marginTop: "28px", width: "100%"}} aria-label={"Upload"}>
|
<Tooltip title={"Download from Github"} style={{marginTop: "28px", width: "100%"}} aria-label={"Upload"}>
|
||||||
<Button
|
<Button
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
@@ -667,6 +681,35 @@ const Apps = (props) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Locally hotloads app from folder
|
||||||
|
const hotloadApps = () => {
|
||||||
|
alert.info("Hotloading apps from location in .env")
|
||||||
|
setIsLoading(true)
|
||||||
|
fetch(globalUrl+"/api/v1/apps/run_hotload", {
|
||||||
|
mode: "cors",
|
||||||
|
headers: {
|
||||||
|
'Accept': 'application/json',
|
||||||
|
},
|
||||||
|
credentials: "include",
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
setIsLoading(false)
|
||||||
|
if (response.status === 200) {
|
||||||
|
alert.success("Hotloaded apps!")
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.json()
|
||||||
|
})
|
||||||
|
.then((responseJson) => {
|
||||||
|
if (responseJson.reason !== undefined && responseJson.reason.length > 0) {
|
||||||
|
alert.info("Hotloading: ", responseJson.reason)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
alert.error(error.toString())
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Gets the URL itself (hopefully this works in most cases?
|
// Gets the URL itself (hopefully this works in most cases?
|
||||||
// Will then forward the data to an internal endpoint to validate the api
|
// Will then forward the data to an internal endpoint to validate the api
|
||||||
const validateUrl = () => {
|
const validateUrl = () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user