master
Paulo Simão 2021-09-29 08:55:11 -03:00
parent 85e464c559
commit 481ebc30e0
15 changed files with 856 additions and 5 deletions

4
.gitignore vendored 100644
View File

@ -0,0 +1,4 @@
/tmp/
/deploy/
.idea
.vscode

20
LICENSE
View File

@ -1,9 +1,21 @@
MIT License MIT License
Copyright (c) <year> <copyright holders> Copyright (c) 2021 digitalcircle-com-br
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

110
README.md
View File

@ -1,3 +1,111 @@
# mk # mk
mk - Make like tool for building, testing, etc. _Multiplatform make-like tool_
Ok, ok - you say - why another make tool clone? Oh lord, there we go again....
Indeed its a valid question... reasons are:
1 - Cuz I could not find a make tool that fit my needs as simple as this one
2 - Cuz windows is always a pain when it comes to compiling software
3 - Why not?
4 - Did I mention I hate verbose stuff?
So these are the drivers for writting mk
## Install
```shell
go install github.com/digitalcircle-com-br/mk@latest
```
## How it works:
mk will look for mk files (which may be named: mk, mk.yaml .mk or .mk.yaml)
you may create a new mk file by using ```mk -i``` bingo, thats all...
The file will look like this one:
```yaml
# SAMPLE mk file - Feel free to add your own header
default: a #This is the default task, in case you call command w/o parameters
env: # in case you want to add var to env, you may add it here
a: 1
b: 2
tasks: #now lets define the tasks
a_darwin_arm64: #this is the task name
cmd: |- # and this is the command - which may be multiline, no issues.
echo \"${TASK} / ${BASETASK}\"
ls -larth
pwd
deploy:
pre: [ build,test ] # pre is an array of predecessors
help: Deploys the project # help prints the help message
cmd: echo deploying
test:
pre: [ c ]
help: Tests project
cmd: echo testing
build:
help: Build binaries
cmd: echo building
main:
help: Main task
pre: [ build ]
cmd: |-
echo main
echo done%
```
And thats it.
## Some gotchas you should notice
### Name resolution
Tasks are resolved considering this rule: task_os_arch: In case you have a task with the os name and arch name, it will
have higher precedence at resolving it. Suppose you add 2 tasks in your mk file: a_windows_amd64 and a_darwin_arm64. In
case youre on a Mac with Apple silicon, and call make a, a_darwin_arm64 will be called. In case you have a task a_darwin
and a_windows, and call mk a from a Mac with Intel processor, it will call a_darwing. Lastly, in case you also define a
task a, it will be called in case none of these more restrictive rules find math.
> By adopting this approach same mk file will allow multiple platform compilation.
### Variables
You may place ${VAR} anywhere in your command, and it will be replaced by mk. It provides you some var, and also env
vars
## Help reference
```shell
Usage: mk [<tasks> ...]
Arguments:
[<tasks> ...] Tasks to be run - Default is main.
Flags:
-h, --help Show context-sensitive help.
-f, --file=STRING File to be used - Defaults are: .mk.yaml, .mk, mk, mk.yaml
-i, --init Creates a new empty file (default is .mk.yaml in case no filename is provided)
-v, --ver Prints version and exit
-l, --list Check file and print tasks
-d, --dbg Debugs execution
--dump-validator Dumps Validator JSON File
-e, --env Dumps env and vars
```
# TODO
- Output is pretty ugly, but the best I could think of so far...
- Integrate zip and git into "internal tasks"
- allow file to have tasks as strings in case no other props are required
- allow file include
- allow it to run as server
- Accepting recommendations on how to improve it

13
go.mod 100644
View File

@ -0,0 +1,13 @@
module go.digitalcircle.com.br/open/mk
go 1.17
require (
github.com/alecthomas/kong v0.2.17
github.com/fatih/color v1.13.0
github.com/mattn/go-colorable v0.1.9 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/pkg/errors v0.9.1 // indirect
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
)

29
go.sum 100644
View File

@ -0,0 +1,29 @@
github.com/alecthomas/kong v0.2.17 h1:URDISCI96MIgcIlQyoCAlhOmrSw6pZScBNkctg8r0W0=
github.com/alecthomas/kong v0.2.17/go.mod h1:ka3VZ8GZNPXv9Ov+j4YNLkI8mTuhXyr/0ktSlqIydQQ=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
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/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U=
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e h1:WUoyKPm6nCo1BnNUvPGnFG3T5DUVem42yDJZZ4CNxMA=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

19
lib/cli.go 100644
View File

@ -0,0 +1,19 @@
package lib
import "github.com/alecthomas/kong"
var CLI = struct {
File string `help:"File to be used - Defaults are: .mk.yaml, .mk, mk, mk.yaml" short:"f"`
Init bool `help:"Creates a new empty file (default is .mk.yaml in case no filename is provided)" short:"i"`
Tasks []string `arg:"" help:"Tasks to be run - Default is main." default:"."`
Ver bool `help:"Prints version and exit" short:"v"`
List bool `help:"Check file and print tasks" short:"l"`
Dbg bool `help:"Debugs execution" short:"d"`
DumpValidator bool `help:"Dumps Validator JSON File" default:"false"`
Env bool `help:"Dumps env and vars" default:"false" short:"e"`
}{}
func InitCli() {
kong.Parse(&CLI)
Ver(CLI.Ver)
}

95
lib/cmdmgr.go 100644
View File

@ -0,0 +1,95 @@
package lib
import (
"archive/zip"
"errors"
"fmt"
"io"
"os"
"path"
"path/filepath"
"strings"
"time"
)
const (
CMD_ZIP = "zip"
CMD_PACK = "pack"
)
func RecursiveZip(i int, pathToZip, destinationPath string) error {
Log(i, "mk:zip", "O", "Starting Zip")
destinationFile, err := os.Create(destinationPath)
if err != nil {
return err
}
myZip := zip.NewWriter(destinationFile)
err = filepath.Walk(pathToZip, func(filePath string, info os.FileInfo, err error) error {
Log(i, "mk:zip", "O", fmt.Sprintf("Adding file: %s", filePath))
if info.IsDir() {
return nil
}
if err != nil {
return err
}
relPath := strings.TrimPrefix(filePath, filepath.Dir(pathToZip))
zipFile, err := myZip.Create(relPath)
if err != nil {
return err
}
fsFile, err := os.Open(filePath)
if err != nil {
return err
}
_, err = io.Copy(zipFile, fsFile)
if err != nil {
return err
}
return nil
})
if err != nil {
return err
}
err = myZip.Close()
if err != nil {
return err
}
Log(i, "mk:zip", "O", fmt.Sprintf("Zip finished: %s", destinationPath))
return nil
}
func RunMkCmd(i int, line string) error {
parts := strings.Split(line, " ")
switch parts[0] {
case CMD_ZIP:
if len(parts) < 3 {
return errors.New(fmt.Sprintf("Not enought params: must be zip <dir> <zipfile>. Got: %s", strings.Join(parts, " ")))
}
return RecursiveZip(i, parts[1], parts[2])
case CMD_PACK:
var ptz string
if len(parts) > 1 {
ptz = parts[1]
} else {
for _, f := range []string{"stage", "deploy", "pack", "release"} {
st, err := os.Stat(f)
if err == nil && st.IsDir() {
ptz = f
break
}
}
}
dir, err := os.Getwd()
if err != nil {
return err
}
dname := path.Base(dir)
ts := time.Now().Format("060102150405")
fname := dname + "-" + ts + ".zip"
return RecursiveZip(i, ptz, fname)
default:
Log(i, parts[0], "E", fmt.Sprintf("mk:cmd %s is not known", parts[0]))
return errors.New(fmt.Sprintf("mk:cmd %s is not known", parts[0]))
}
}

20
lib/init.go 100644
View File

@ -0,0 +1,20 @@
package lib
import (
_ "embed"
"os"
)
//go:embed res/.mk.yaml
var sample []byte
//go:embed res/mk.json
var validator []byte
func InitFile() error {
return os.WriteFile(CLI.File, sample, 0600)
}
func DumpValidator() error {
return os.WriteFile(CLI.File, validator, 0600)
}

22
lib/res/.mk.yaml 100644
View File

@ -0,0 +1,22 @@
# SAMPLE mk file
default: main
env:
tasks:
deploy:
pre: [ build,test ]
help: Deploys the project
cmd: echo deploying
test:
pre: [ c ]
help: Tests project
cmd: echo testing
build:
help: Build binaries
cmd: echo building
main:
help: Main task
pre: [ build ]
cmd: |-
echo main
echo done

89
lib/res/mk.json 100644
View File

@ -0,0 +1,89 @@
{
"$id": "https://www.digitalticircle.com.br/_schemas/mk.json",
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Digital Circle - Make Instructions",
"type": "object",
"additionalProperties": false,
"$d": {
"task": {
"type": "object",
"properties": {
"pre": {
"description": "Predecessor tasks",
"type": "array",
"items": {
"type": "string"
}
},
"cmd": {
"description": "Command this task should run",
"type": "string"
},
"help": {
"description": "Help for this task",
"type": "string"
},
"onerror": {
"description": "What to do in case of error"
},
"env": {
"type": "object",
"description": "Global Env Var",
"patternProperties": {
".{1.}": {
"type": "string"
}
}
},
"vars": {
"type": "object",
"description": "Global Text Var",
"patternProperties": {
".{1.}": {
"type": "string"
}
}
}
},
"additionalProperties": "false"
}
},
"properties": {
"default": {
"type": "string",
"default": "main",
"description": "Default task to run"
},
"tasks": {
"type": "object",
"patternProperties": {
".{1,}": {
"allOf": [
{
"$ref": "#/$d/task"
}
]
}
},
"description": "Tasks configured for execution"
},
"env": {
"type": "object",
"description": "Global Env Var",
"patternProperties": {
".{1.}": {
"type": "string"
}
}
},
"vars": {
"type": "object",
"description": "Global Text Var",
"patternProperties": {
".{1.}": {
"type": "string"
}
}
}
}
}

396
lib/run.go 100644
View File

@ -0,0 +1,396 @@
package lib
import (
"bufio"
"errors"
"fmt"
"github.com/fatih/color"
"gopkg.in/yaml.v3"
"log"
"os"
"os/exec"
"os/user"
"runtime"
"sort"
"strings"
"sync"
"time"
)
var model *MkModel
func FileExists(filename string) bool {
info, err := os.Stat(filename)
if os.IsNotExist(err) {
return false
}
return !info.IsDir()
}
func ResolveConfig() (err error) {
if CLI.File != "" {
if CLI.Init && FileExists(CLI.File) {
println(fmt.Sprintf("Using file: %s", CLI.File))
return
} else {
err = errors.New(fmt.Sprintf("Config File %s not found", CLI.File))
}
}
deffiles := []string{".mk.yaml", ".mk", "mk", "mk.yaml"}
for _, v := range deffiles {
if CLI.Init || FileExists(v) {
println(fmt.Sprintf("Using file: %s", v))
CLI.File = v
return
}
}
err = errors.New(fmt.Sprintf("No Config File found"))
return
}
func ResolveTask(n string) *MkTask {
osname := runtime.GOOS
arch := runtime.GOARCH
vars["BASETASK"] = n
t, ok := model.Tasks[n+"_"+osname+"_"+arch]
if ok {
vars["TASK"] = n + "_" + osname + "_" + arch
return t
}
t, ok = model.Tasks[n+"_"+osname]
if ok {
vars["TASK"] = n + "_" + osname
return t
}
vars["TASK"] = n
return model.Tasks[n]
}
func Log(i int, task string, stream string, b string) {
timeLb := time.Now().Format("15:04:05")
tab := ""
for x := 0; x < i; x++ {
tab = tab + "\t"
}
if stream == "O" {
println(color.GreenString(fmt.Sprintf("%s %s [%s - %s]: %s", timeLb, tab, task, stream, b)))
} else if stream == "E" {
println(color.RedString(fmt.Sprintf("%s %s [%s - %s]: %s", timeLb, tab, task, stream, b)))
} else {
println(fmt.Sprintf("%s %s [%s - %s]: %s", timeLb, tab, task, stream, b))
}
}
func RunTask(name string, t *MkTask, l int) error {
for k, v := range t.Env {
env[k] = v
}
for k, v := range t.Vars {
vars[k] = v
}
Log(l, name, "**", fmt.Sprintf("Starting %s", name))
if len(t.Pre) > 0 {
Log(l, name, "**", fmt.Sprintf("Will run Pre tasks: [%s]", strings.Join(t.Pre, ",")))
for _, v := range t.Pre {
caller, repeat := model.Stack[v]
if repeat {
Log(l, name, "**", fmt.Sprintf("Task %s already called by %s - skipping.", v, caller))
continue
} else {
model.Stack[v] = name
}
pr, ok := model.Tasks[v]
if ok {
err := RunTask(v, pr, l+1)
if err != nil {
return err
}
} else {
return errors.New(fmt.Sprintf("Task %s, prereq of: %s not found in model", v, name))
}
}
}
var c *exec.Cmd
if runtime.GOOS == "windows" {
c = exec.Command("cmd.exe")
} else {
c = exec.Command("sh")
}
for k, v := range env {
c.Env = append(c.Env, fmt.Sprintf("%s=%s", k, v))
}
pi, _ := c.StdinPipe()
po, err := c.StdoutPipe()
if err != nil {
log.Printf(err.Error())
return err
}
scannero := bufio.NewScanner(po)
pe, err := c.StderrPipe()
if err != nil {
log.Printf(err.Error())
return err
}
scannere := bufio.NewScanner(pe)
wg := sync.WaitGroup{}
wg.Add(2)
ch := make(chan string)
go func() {
time.Sleep(time.Millisecond * 100)
defer wg.Done()
for scannero.Scan() {
line := scannero.Text()
if strings.Contains(line, "__CMD_ENDED__:") {
ret := strings.Split(line, "__CMD_ENDED__:")[1]
if ret != "%errorlevel%" {
ch <- ret
}
} else {
Log(l+1, name, "O", line)
}
}
}()
go func() {
time.Sleep(time.Millisecond * 100)
defer wg.Done()
for scannere.Scan() {
Log(l+1, name, "E", scannere.Text())
}
}()
err = c.Start()
if err != nil {
return err
}
lines := bufio.NewScanner(strings.NewReader(t.Cmd))
//if runtime.GOOS == "windows" {
// pi.Write([]byte("@echo off\n"))
//}
for lines.Scan() {
txt := lines.Text()
for k, v := range vars {
txt = strings.Replace(txt, fmt.Sprintf("${%s}", k), v, -1)
}
if strings.HasPrefix(txt, "@") {
txt = strings.TrimLeft(txt, "@")
} else {
Log(l+1, name, "I", txt)
}
if strings.HasPrefix(txt, "mk:") {
txt = strings.Replace(txt, "mk:", "", 1)
txt = strings.TrimSpace(txt)
err = RunMkCmd(l+1, txt)
if err != nil {
log.Printf("Error running: %s", txt)
}
} else {
_, err = pi.Write([]byte(txt + "\n"))
if runtime.GOOS == "windows" {
_, err = pi.Write([]byte("echo __CMD_ENDED__:%errorlevel%" + "\n"))
} else {
_, err = pi.Write([]byte("echo __CMD_ENDED__:$?" + "\n"))
}
ret := <-ch
if ret != "0" && t.Onerror == "skip" {
Log(l+1, name, "E", "Error Code: "+ret+" will continue, but watch out")
} else if ret != "0" && t.Onerror != "skip" {
Log(l+1, name, "E", "Error Code is: "+ret+" ABORTING")
break
}
}
}
_, err = pi.Write([]byte("exit\n"))
if err != nil {
return err
}
wg.Wait()
err = c.Wait()
Log(l, name, "**", "End")
return err
}
func DumpEnv() {
if CLI.Env {
println("Vars:")
varnames := make([]string, 0)
for k := range vars {
varnames = append(varnames, k)
}
sort.Strings(varnames)
for _, k := range varnames {
v := vars[k]
println(fmt.Sprintf("%s => %s", k, v))
}
println("========")
println("Env:")
envnames := make([]string, 0)
for k := range env {
envnames = append(envnames, k)
}
sort.Strings(envnames)
for _, k := range envnames {
v := env[k]
println(fmt.Sprintf("%s => %s", k, v))
}
os.Exit(0)
}
}
func Prepare() error {
InitCli()
err := ResolveConfig()
if err != nil {
return err
}
if CLI.Init {
err = InitFile()
if err != nil {
return err
}
os.Exit(0)
}
if CLI.DumpValidator {
err = DumpValidator()
if err != nil {
log.Printf("Error DumpValidator: %s", err.Error())
}
os.Exit(0)
}
bs, err := os.ReadFile(CLI.File)
if err != nil {
panic(err)
}
model = &MkModel{}
err = yaml.Unmarshal(bs, model)
if err != nil {
return err
}
if model.Default == "" {
model.Default = "main"
}
for k, v := range model.Tasks {
v.Name = k
}
if CLI.List {
println("Tasks:")
tasknames := make([]string, 0)
for k := range model.Tasks {
tasknames = append(tasknames, k)
}
sort.Strings(tasknames)
for _, k := range tasknames {
v := model.Tasks[k]
def := ""
if v.Name == model.Default {
def = "DEF>"
} else {
def = ""
}
println(fmt.Sprintf("%s %s [%s]: %s", def, k, strings.Join(v.Pre, ","), v.Help))
}
os.Exit(0)
}
if len(CLI.Tasks) < 1 || CLI.Tasks[0] == "" || CLI.Tasks[0] == "." {
CLI.Tasks = []string{model.Default}
}
return err
}
var env map[string]string
var vars map[string]string
func Run() error {
env = make(map[string]string)
vars = make(map[string]string)
envstrs := os.Environ()
for _, k := range envstrs {
parts := strings.Split(k, "=")
ek := strings.TrimSpace(parts[0])
ev := os.Getenv(ek)
env[ek] = ev
}
err := Prepare()
if err != nil {
log.Printf("Could not execute: %s", err.Error())
os.Exit(0)
}
for k, v := range model.Env {
env[k] = v
}
for k, v := range model.Vars {
vars[k] = v
}
now := time.Now()
vars["DT_YYMMDDHHmmss"] = now.Format("060102150405")
vars["DT_YYMMDD"] = now.Format("060102")
vars["DS_TS"] = fmt.Sprintf("%d", now.Unix())
u, err := user.Current()
if err != nil {
panic(err)
}
vars["USERNAME"] = u.Username
vars["HOMEDIR"] = u.HomeDir
if err != nil {
return err
}
DumpEnv()
model.Stack = make(map[string]string)
for _, v := range CLI.Tasks {
tasko := ResolveTask(v)
if tasko != nil {
err = RunTask(v, tasko, 0)
} else {
return errors.New(fmt.Sprintf("No task named %s found", v))
}
}
return err
}

18
lib/types.go 100644
View File

@ -0,0 +1,18 @@
package lib
type MkTask struct {
Name string
Help string
Cmd string `yaml:"cmd"`
Pre []string `yaml:"pre"`
Onerror string `yaml:"onerror"`
Env map[string]string `yaml:"env"`
Vars map[string]string `yaml:"vars"`
}
type MkModel struct {
Env map[string]string `yaml:"env"`
Vars map[string]string `yaml:"vars"`
Tasks map[string]*MkTask `yaml:"tasks"`
Default string `yaml:"default"`
Stack map[string]string `yaml:"-"`
}

15
lib/ver.go 100644
View File

@ -0,0 +1,15 @@
package lib
import "os"
import _ "embed"
//go:embed ver.txt
var ver string
func Ver(end bool) {
println("DC MK Tool - ver: " + ver)
if end {
os.Exit(0)
}
}

1
lib/ver.txt 100644
View File

@ -0,0 +1 @@
Sat Sep 18 20:38:27 -03 2021

10
main.go 100644
View File

@ -0,0 +1,10 @@
package main
import "go.digitalcircle.com.br/open/mk/lib"
func main() {
err := lib.Run()
if err != nil {
panic(err)
}
}