diff --git a/.idea/.gitignore b/.idea/.gitignore
deleted file mode 100644
index 73f69e0..0000000
--- a/.idea/.gitignore
+++ /dev/null
@@ -1,8 +0,0 @@
-# Default ignored files
-/shelf/
-/workspace.xml
-# Datasource local storage ignored files
-/dataSources/
-/dataSources.local.xml
-# Editor-based HTTP Client requests
-/httpRequests/
diff --git a/.idea/grif-cli.iml b/.idea/cli.iml
similarity index 74%
rename from .idea/grif-cli.iml
rename to .idea/cli.iml
index 5398c41..53f41fe 100644
--- a/.idea/grif-cli.iml
+++ b/.idea/cli.iml
@@ -3,7 +3,8 @@
-
+
+
diff --git a/.idea/modules.xml b/.idea/modules.xml
index d40b60d..6fcc0dc 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -2,7 +2,7 @@
-
+
\ No newline at end of file
diff --git a/.idea/remote-targets.xml b/.idea/remote-targets.xml
deleted file mode 100644
index 100d818..0000000
--- a/.idea/remote-targets.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index 94a25f7..2ee9a0a 100644
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -2,5 +2,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..d9f53e2
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,99 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
\ No newline at end of file
diff --git a/src/api/API.go b/src/api/API.go
index 794a84c..d5c9a35 100644
--- a/src/api/API.go
+++ b/src/api/API.go
@@ -7,6 +7,7 @@ import (
"io"
"io/ioutil"
"net/http"
+ "os"
)
func Request(path string, data map[string]interface{}, hash interface{}) (response io.Reader,err error) {
@@ -70,4 +71,86 @@ func Request(path string, data map[string]interface{}, hash interface{}) (respon
return result,errors.New(errorInfo.Error.(string))
}
return result, err
+}
+
+func WorldWideWebRequest(url string, data map[string]interface{}) (response io.Reader,err error) {
+ var result io.Reader = nil
+ var body []byte
+ err = nil
+ client := &http.Client{}
+ if data != nil && len(data) > 0 {
+ postString, err := json.Marshal(&data)
+ if err!=nil {
+ return nil, err
+ }
+ req, err := http.NewRequest("POST",url, bytes.NewBuffer(postString))
+ if err!=nil {
+ return nil, err
+ }
+ req.Header.Set("Accept","application/json")
+ req.Header.Set("User-Agent","grifpkg/cli")
+ res, err := client.Do(req)
+ if err!=nil {
+ return nil, err
+ }
+ defer func(Body io.ReadCloser) {
+ err = Body.Close()
+ }(res.Body)
+ body, err = ioutil.ReadAll(res.Body)
+ if err!=nil {
+ return nil, err
+ }
+ result = bytes.NewReader(body)
+ } else {
+ req, err := http.NewRequest("GET",url, nil)
+ if err!=nil {
+ return nil, err
+ }
+ req.Header.Set("Accept","application/json")
+ req.Header.Set("User-Agent","grifpkg/cli")
+ res, err := client.Do(req)
+ defer func(Body io.ReadCloser) {
+ err = Body.Close()
+ }(res.Body)
+ body, err = ioutil.ReadAll(res.Body)
+ if err!=nil {
+ return nil, err
+ }
+ result = bytes.NewReader(body)
+ }
+ return result, err
+}
+
+func DownloadFile(URL string, outputDirectoryPath interface{}, outputName string) (outputPath string,err error){
+
+ var outputPathString string = ""
+ if outputDirectoryPath!=nil {
+ outputPathString=outputDirectoryPath.(string)
+ } else {
+ outputPathString, err = os.Getwd()
+ if err != nil {
+ return "", err
+ }
+ }
+ outputPath=outputPathString+string(os.PathSeparator)+outputName
+ resp, err := http.Get(URL)
+ if err != nil {
+ return "", err
+ }
+ defer resp.Body.Close()
+
+ err = os.Mkdir(outputPathString, 0700)
+ if err != nil && !os.IsExist(err) {
+ return "", err
+ }
+ out, err := os.Create(outputPath)
+ if err != nil && !os.IsExist(err) {
+ return "", err
+ }
+ defer out.Close()
+ _, err = io.Copy(out, resp.Body)
+ if err != nil {
+ return "", err
+ }
+ return outputPath, nil
}
\ No newline at end of file
diff --git a/src/api/Globals.go b/src/api/Globals.go
index 3c95aef..c4b1286 100644
--- a/src/api/Globals.go
+++ b/src/api/Globals.go
@@ -1,5 +1,5 @@
package api
-const Version = "1.1.0"
+const Version = "1.1.1"
const KeychainService = "grifpkg"
const KeychainHash = "session"
\ No newline at end of file
diff --git a/src/elements/deployment/Helper.go b/src/elements/deployment/Helper.go
new file mode 100644
index 0000000..667da26
--- /dev/null
+++ b/src/elements/deployment/Helper.go
@@ -0,0 +1,153 @@
+package deployment
+
+import (
+ "encoding/json"
+ "errors"
+ "github.com/grifpkg/cli/api"
+ "os/exec"
+ "runtime"
+ "strconv"
+ "strings"
+ "time"
+)
+
+// DirectDeploy deploys directly with a command, f.e. creating a java vm/**
+func DirectDeploy(fork string, version string, path string, args map[string]interface{}) (err error){
+ version=strings.ToLower(version)
+ if version=="latest" {
+ version, err = GetLatestVersion("minecraft")
+ if err != nil {
+ return err
+ }
+ }
+ downloadURL, err := GetLatestSoftwareVersion(fork,version)
+ api.LogOne(api.Progress,"downloading the server software")
+ _, err = api.DownloadFile(downloadURL,nil,"bin.jar")
+ if err != nil {
+ return err
+ }
+ api.LogOne(api.Progress, "downloaded, serving locally")
+ var cmd = "java -jar bin.jar"
+ if runtime.GOOS == "windows" {
+ _, err = exec.Command("cmd", "/c", cmd).Output()
+ if err != nil {
+ return err
+ }
+ } else {
+ _, err := exec.Command("bash", "-c", cmd).Output()
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// DockerDeploy deploys locally with a docker image
+func DockerDeploy(fork string, version string, path string, envs map[string]interface{}, image string) (err error){
+ return errors.New("not implemented")
+}
+
+// CloudDeploy deploys to a cloud service, AWS, Google Cloud or purecore hosting
+func CloudDeploy(fork string, version string, path string, opts map[string]interface{}, service string, token string, identifier interface{}) (err error){
+ return errors.New("not implemented")
+}
+
+func GetLatestSoftwareVersion(software string, gameVersion string) (downloadURL string, err error){
+ api.LogOne(api.Progress,"fetching latest software version")
+ software=strings.ToLower(software)
+ if software=="@papermc/paper" {
+
+ type PaperBuilds struct {
+ ProjectId string `json:"project_id"`
+ ProjectName string `json:"project_name"`
+ Version string `json:"version"`
+ Builds []int `json:"builds"`
+ }
+
+ type PaperBuild struct {
+ ProjectId string `json:"project_id"`
+ ProjectName string `json:"project_name"`
+ Version string `json:"version"`
+ Build int `json:"build"`
+ Time time.Time `json:"time"`
+ Changes []struct {
+ Commit string `json:"commit"`
+ Summary string `json:"summary"`
+ Message string `json:"message"`
+ } `json:"changes"`
+ Downloads struct {
+ Application struct {
+ Name string `json:"name"`
+ Sha256 string `json:"sha256"`
+ } `json:"application"`
+ } `json:"downloads"`
+ }
+
+ result, err := api.WorldWideWebRequest("https://papermc.io/api/v2/projects/paper/versions/" + gameVersion, map[string]interface{}{})
+ if err != nil {
+ return "", err
+ }
+
+ var buildData = PaperBuilds{}
+
+ err = json.NewDecoder(result).Decode(&buildData)
+ if err != nil {
+ return "", err
+ }
+
+ var latestBuildData = PaperBuild{}
+
+ result, err = api.WorldWideWebRequest("https://papermc.io/api/v2/projects/paper/versions/"+gameVersion+"/builds/"+strconv.Itoa(buildData.Builds[len(buildData.Builds)-1]), map[string]interface{}{})
+ if err != nil {
+ return "", err
+ }
+ err = json.NewDecoder(result).Decode(&latestBuildData)
+
+ return "https://papermc.io/api/v2/projects/paper/versions/"+gameVersion+"/builds/"+strconv.Itoa(buildData.Builds[len(buildData.Builds)-1])+"/downloads/"+latestBuildData.Downloads.Application.Name, nil
+
+ } else if software=="@spigotmc/bungeecord" {
+ return "https://ci.md-5.net/job/BungeeCord/lastStableBuild/artifact/bootstrap/target/BungeeCord.jar", nil
+ } else {
+ return "", errors.New("unsupported software")
+ }
+}
+
+func GetLatestVersion(game string) (version string,err error){
+ api.LogOne(api.Progress,"fetching latest game version")
+ if game=="minecraft" {
+
+ type MinecraftLatestReleaseStrings struct {
+ Release string `json:"release"`
+ Snapshot string `json:"snapshot"`
+ }
+
+ type MinecraftReleaseInfo struct {
+ Id string `json:"id"`
+ Type string `json:"type"`
+ URL string `json:"url"`
+ Time string `json:"time"`
+ ReleaseTime string `json:"releaseTime"`
+ }
+
+ type MinecraftVersionList struct {
+ Latest MinecraftLatestReleaseStrings `json:"latest"`
+ Versions []MinecraftReleaseInfo `json:"versions"`
+ }
+
+ var versionData = MinecraftVersionList{}
+
+ result, err := api.WorldWideWebRequest("https://launchermeta.mojang.com/mc/game/version_manifest.json",map[string]interface{}{})
+ if err != nil {
+ return "", err
+ }
+
+ err = json.NewDecoder(result).Decode(&versionData)
+ if err != nil {
+ return "", err
+ }
+
+ return versionData.Latest.Release, nil
+ } else {
+ return "", errors.New("unsupported game")
+ }
+}
diff --git a/src/elements/project/Project.go b/src/elements/project/Project.go
index 950d25c..f188713 100644
--- a/src/elements/project/Project.go
+++ b/src/elements/project/Project.go
@@ -6,6 +6,7 @@ import (
"fmt"
"github.com/AlecAivazis/survey/v2"
"github.com/grifpkg/cli/api"
+ "github.com/grifpkg/cli/elements/deployment"
"io/ioutil"
"os"
"strconv"
@@ -35,6 +36,18 @@ func GetProject() (project *Project, lock *ProjectLock, err error){
return &openedProject, &openedProjectLock, nil
}
+func (project Project) Deploy() (err error){
+ wd, err := os.Getwd()
+ if err != nil {
+ return err
+ }
+ err = deployment.DirectDeploy(project.Software, project.Version, wd, map[string]interface{}{})
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
func (project Project) InstallAll() (release []Release, err error) {
_, lock, err := GetProject()
if err != nil {
@@ -253,7 +266,7 @@ func createProjectFile(path string) (project Project, err error){
Name: "software",
Prompt: &survey.Select{
Message: "Which server software are you using (if you are using a fork, select the closest parent)",
- Options: []string{"@spigotmc/spigot", "@spigotmc/bungeecord", "@papermc/paper", "@papermc/waterfall"},
+ Options: []string{"@spigotmc/spigot", "@spigotmc/bungeecord", "@papermc/paper", "@papermc/waterfall", "@minecraft/java-server"},
Default: "@minecraft/java",
},
},
diff --git a/src/grif.go b/src/grif.go
index 0539006..ec8313d 100644
--- a/src/grif.go
+++ b/src/grif.go
@@ -40,6 +40,25 @@ var linkCMD = &cobra.Command{
},
}
+var deployCMD = &cobra.Command{
+ Use: "deploy",
+ Aliases: []string{"dep"},
+ Short: "deploys the server using local resources (directly or via Docker) or using an external cloud service such as AWS, GCloud or purecore hosting",
+ Run: func(cmd *cobra.Command, args []string) {
+ project, _, err := project.GetProject()
+ if err != nil {
+ api.LogOne(api.Warn, err.Error())
+ return
+ }
+ err = project.Deploy()
+ if err != nil {
+ api.LogOne(api.Warn, err.Error())
+ return
+ }
+ api.LogOne(api.Success, "deployed")
+ },
+}
+
var importCMD = &cobra.Command{
Use: "import",
Aliases: []string{"im"},
@@ -161,4 +180,5 @@ func init() {
rootCMD.AddCommand(importCMD)
rootCMD.AddCommand(excludeCMD)
rootCMD.AddCommand(linkCMD)
+ rootCMD.AddCommand(deployCMD)
}
\ No newline at end of file
diff --git a/src/installer/Windows.go b/src/installer/Windows.go
index 91636ea..c574d41 100644
--- a/src/installer/Windows.go
+++ b/src/installer/Windows.go
@@ -8,6 +8,7 @@ import (
"os"
"os/exec"
"path"
+ "strings"
)
func InstallWindows() (release grifRelease, err error){
@@ -17,7 +18,7 @@ func InstallWindows() (release grifRelease, err error){
api.LogOne(api.Progress,"getting config dir")
targetPath, _ := os.UserConfigDir()
installPath := targetPath+"\\grifpkg\\bin\\"
- randomId := ksuid.New().String()
+ randomId := ksuid.New().String()[0:3]
api.LogOne(api.Progress,"downloading latest release")
release, err = getLatest(installPath+randomId+"/")
if err != nil {
@@ -35,24 +36,36 @@ func InstallWindows() (release grifRelease, err error){
}
}
- api.LogOne(api.Progress,"creating install script")
- createInstallScript(installPath, randomId)
-
- api.LogOne(api.Progress,"running install script")
- err = exec.Command(installPath+"install.bat").Run()
+ api.LogOne(api.Progress,"creating path script")
+ err = createInstallScript(installPath,randomId)
if err != nil {
return grifRelease{}, err
}
+
+ api.LogOne(api.Progress,"running path script")
+ err = exec.Command(installPath+"install.bat").Run()
+
return release, nil
}
-func createInstallScript(installPath string, id string){
+func createInstallScript(installPath string, id string)(err error){
installScript, err := os.Create(installPath+"install.bat")
if os.IsExist(err) {
err = os.Remove(installPath+"install.bat")
- } else {
- // error
}
- _, err = installScript.WriteString("setx path \""+installPath+id+"\\;%PATH%\"")
+
+ // path value gen
+ envPath := os.Getenv("PATH")
+ programs := strings.Split(envPath,";")
+ finalPrograms := installPath+id+";"
+ for _, program := range programs {
+ if !strings.HasSuffix(program,installPath) {
+ finalPrograms+=strings.TrimSuffix(program,";")+";"
+ }
+ }
+
+ // path value set
+ _, err = installScript.WriteString("setx path \""+finalPrograms+"\"")
defer installScript.Close()
+ return nil
}
\ No newline at end of file