mirror of
https://github.com/mappu/miqt.git
synced 2025-05-11 14:10:23 +00:00
miqt-docker: support 'native', add -build task, conditional isatty
This commit is contained in:
parent
b2536be8d5
commit
c6ff8e0533
@ -51,18 +51,12 @@ func usage(dockerfiles []fs.DirEntry) {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
// getDockerRunArgsForGlob returns a []string array of all the {busywork} arguments
|
||||||
|
// for a `docker {run -e -v ...} go build` command.
|
||||||
|
// It does glob matching for the target container, and builds it if it does not yet exist.
|
||||||
|
func getDockerRunArgsForGlob(dockerfiles []fs.DirEntry, containerNameGlob string, isatty bool) ([]string, error) {
|
||||||
|
|
||||||
dockerfiles, err := docker.Dockerfiles.ReadDir(`.`)
|
requestEnvironment := glob2regex(containerNameGlob)
|
||||||
if err != nil {
|
|
||||||
log.Panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(os.Args) < 3 {
|
|
||||||
usage(dockerfiles)
|
|
||||||
}
|
|
||||||
|
|
||||||
requestEnvironment := glob2regex(os.Args[1])
|
|
||||||
var match string
|
var match string
|
||||||
for _, ff := range dockerfiles {
|
for _, ff := range dockerfiles {
|
||||||
if !requestEnvironment.MatchString(ff.Name()) {
|
if !requestEnvironment.MatchString(ff.Name()) {
|
||||||
@ -74,7 +68,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if match == "" {
|
if match == "" {
|
||||||
log.Fatalf("No available environment matches the request %q\n", os.Args[1])
|
return nil, fmt.Errorf("No available environment matches the request %q\n", containerNameGlob)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !(match == os.Args[1] || match == os.Args[1]+`.Dockerfile`) {
|
if !(match == os.Args[1] || match == os.Args[1]+`.Dockerfile`) {
|
||||||
@ -84,7 +78,7 @@ func main() {
|
|||||||
|
|
||||||
dockerFileContent, err := docker.ReadFile(match)
|
dockerFileContent, err := docker.ReadFile(match)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panic(err) // shouldn't happen
|
return nil, err // shouldn't happen
|
||||||
}
|
}
|
||||||
|
|
||||||
dockerfileHash := shasum(dockerFileContent)[:8] // First 8 characters of content hash
|
dockerfileHash := shasum(dockerFileContent)[:8] // First 8 characters of content hash
|
||||||
@ -96,20 +90,19 @@ func main() {
|
|||||||
_, err = dockerFindImage(containerName, dockerfileHash)
|
_, err = dockerFindImage(containerName, dockerfileHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err != os.ErrNotExist {
|
if err != os.ErrNotExist {
|
||||||
log.Panic(err) // real error
|
return nil, err // real error
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("No matching docker image, creating...")
|
log.Printf("No matching docker image, creating...")
|
||||||
err = dockerBuild(dockerFileContent, containerName, dockerfileHash)
|
err = dockerBuild(dockerFileContent, containerName, dockerfileHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panic(err)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search again
|
// Search again
|
||||||
_, err = dockerFindImage(containerName, dockerfileHash)
|
_, err = dockerFindImage(containerName, dockerfileHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Failed to build container for %s:%s", containerName, dockerfileHash)
|
return nil, fmt.Errorf("Failed to build container for %s:%s: %w", containerName, dockerfileHash, err) // Any error now is a real error
|
||||||
log.Panic(err) // Any error now is a real error
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,10 +129,10 @@ func main() {
|
|||||||
|
|
||||||
// Container match found - safe to run our command
|
// Container match found - safe to run our command
|
||||||
|
|
||||||
fullCommand := []string{"run"}
|
fullCommand := []string{"run", "--rm", "-i"}
|
||||||
|
|
||||||
if isatty() {
|
if isatty {
|
||||||
fullCommand = append(fullCommand, "-it")
|
fullCommand = append(fullCommand, "-t")
|
||||||
}
|
}
|
||||||
|
|
||||||
if runtime.GOOS != "windows" {
|
if runtime.GOOS != "windows" {
|
||||||
@ -154,7 +147,7 @@ func main() {
|
|||||||
// Find the GOMODCACHE and GOCACHE to populate mapped volumes
|
// Find the GOMODCACHE and GOCACHE to populate mapped volumes
|
||||||
gomodcache, err := exec.Command(`go`, `env`, `GOMODCACHE`).Output()
|
gomodcache, err := exec.Command(`go`, `env`, `GOMODCACHE`).Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panic(err)
|
return nil, fmt.Errorf("Finding GOMODCACHE: %w", err)
|
||||||
}
|
}
|
||||||
if gomodcache_sz := strings.TrimSpace(string(gomodcache)); len(gomodcache_sz) > 0 {
|
if gomodcache_sz := strings.TrimSpace(string(gomodcache)); len(gomodcache_sz) > 0 {
|
||||||
_ = os.MkdirAll(gomodcache_sz, 0755) // Might not exist if no Go modules have been used yet
|
_ = os.MkdirAll(gomodcache_sz, 0755) // Might not exist if no Go modules have been used yet
|
||||||
@ -164,7 +157,7 @@ func main() {
|
|||||||
|
|
||||||
gocache, err := exec.Command(`go`, `env`, `GOCACHE`).Output()
|
gocache, err := exec.Command(`go`, `env`, `GOCACHE`).Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panic(err)
|
return nil, fmt.Errorf("Finding GOCACHE: %w", err)
|
||||||
}
|
}
|
||||||
if gocache_sz := strings.TrimSpace(string(gocache)); len(gocache_sz) > 0 {
|
if gocache_sz := strings.TrimSpace(string(gocache)); len(gocache_sz) > 0 {
|
||||||
_ = os.MkdirAll(gocache_sz, 0755) // Might not exist if no Go packages have been built yet
|
_ = os.MkdirAll(gocache_sz, 0755) // Might not exist if no Go packages have been built yet
|
||||||
@ -179,7 +172,7 @@ func main() {
|
|||||||
var parentPaths []string
|
var parentPaths []string
|
||||||
gomod, err := exec.Command(`go`, `env`, `GOMOD`).Output()
|
gomod, err := exec.Command(`go`, `env`, `GOMOD`).Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panic(err)
|
return nil, fmt.Errorf("Finding GOMOD: %w", err)
|
||||||
}
|
}
|
||||||
if gomod_sz := strings.TrimSpace(string(gomod)); len(gomod_sz) > 0 {
|
if gomod_sz := strings.TrimSpace(string(gomod)); len(gomod_sz) > 0 {
|
||||||
parentPaths = append(parentPaths, gomod_sz)
|
parentPaths = append(parentPaths, gomod_sz)
|
||||||
@ -187,7 +180,7 @@ func main() {
|
|||||||
|
|
||||||
gowork, err := exec.Command(`go`, `env`, `GOWORK`).Output()
|
gowork, err := exec.Command(`go`, `env`, `GOWORK`).Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panic(err)
|
return nil, fmt.Errorf("Finding GOWORK: %w", err)
|
||||||
}
|
}
|
||||||
if gowork_sz := strings.TrimSpace(string(gowork)); len(gowork_sz) > 0 {
|
if gowork_sz := strings.TrimSpace(string(gowork)); len(gowork_sz) > 0 {
|
||||||
parentPaths = append(parentPaths, gowork_sz)
|
parentPaths = append(parentPaths, gowork_sz)
|
||||||
@ -205,19 +198,19 @@ func main() {
|
|||||||
|
|
||||||
cwd, err := os.Getwd()
|
cwd, err := os.Getwd()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panic(err)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
parentPaths = append(parentPaths, cwd) // It's an option too
|
parentPaths = append(parentPaths, cwd) // It's an option too
|
||||||
|
|
||||||
basedir, err := highestCommonParent(parentPaths)
|
basedir, err := highestCommonParent(parentPaths)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panic(err)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
relCwd, err := filepath.Rel(basedir, cwd)
|
relCwd, err := filepath.Rel(basedir, cwd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panic(err)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
fullCommand = append(fullCommand, `-v`, basedir+`:/src`, `-w`, filepath.Join(`/src`, relCwd))
|
fullCommand = append(fullCommand, `-v`, basedir+`:/src`, `-w`, filepath.Join(`/src`, relCwd))
|
||||||
@ -225,12 +218,49 @@ func main() {
|
|||||||
// Final standard docker commands
|
// Final standard docker commands
|
||||||
|
|
||||||
fullCommand = append(fullCommand, containerName+`:`+dockerfileHash) // , `/bin/bash`, `-c`)
|
fullCommand = append(fullCommand, containerName+`:`+dockerfileHash) // , `/bin/bash`, `-c`)
|
||||||
fullCommand = append(fullCommand, os.Args[2:]...)
|
|
||||||
|
|
||||||
cmd := dockerCommand(fullCommand...)
|
return fullCommand, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
dockerfiles, err := docker.Dockerfiles.ReadDir(`.`)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(os.Args) < 3 {
|
||||||
|
usage(dockerfiles)
|
||||||
|
}
|
||||||
|
|
||||||
|
taskArgs, taskOp, taskAllowTty, err := evaluateTask(os.Args[2:])
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var cmd *exec.Cmd
|
||||||
|
if os.Args[1] == "native" {
|
||||||
|
|
||||||
|
if taskArgs[0] == `/bin/bash` && runtime.GOOS == "windows" {
|
||||||
|
log.Fatal("This command can't be used in 'native' mode on Windows.")
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd = exec.Command(taskArgs[0], taskArgs[1:]...) // n.b. [1:] may be an empty slice
|
||||||
|
|
||||||
|
} else {
|
||||||
|
dockerArgs, err := getDockerRunArgsForGlob(dockerfiles, os.Args[1], taskAllowTty && isatty())
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
dockerArgs = append(dockerArgs, taskArgs...)
|
||||||
|
cmd = dockerCommand(dockerArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
cmd.Stdin = os.Stdin
|
cmd.Stdin = os.Stdin
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
|
taskOp(cmd)
|
||||||
err = cmd.Run()
|
err = cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
44
cmd/miqt-docker/tasks.go
Normal file
44
cmd/miqt-docker/tasks.go
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"os/exec"
|
||||||
|
)
|
||||||
|
|
||||||
|
// evaluateTask turns the supplied process arguments into real arguments to
|
||||||
|
// execute, handling quick command recipes as well as arbitrary execution
|
||||||
|
func evaluateTask(taskArgs []string) (retArgs []string, fixup func(*exec.Cmd), allowTty bool, err error) {
|
||||||
|
|
||||||
|
if len(taskArgs) == 0 {
|
||||||
|
return nil, nil, false, errors.New("No task specified")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(taskArgs[0]) == 0 {
|
||||||
|
return nil, nil, false, errors.New("Empty-string first command")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up defaults
|
||||||
|
|
||||||
|
retArgs = []string{}
|
||||||
|
fixup = func(*exec.Cmd) {} // no-op
|
||||||
|
allowTty = true
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
if taskArgs[0][0] != '-' {
|
||||||
|
// Task does not start with a hyphen = plain command
|
||||||
|
retArgs = taskArgs
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch taskArgs[0] {
|
||||||
|
case `-build`:
|
||||||
|
retArgs = []string{"go", "build", "-ldflags", "-s -w"}
|
||||||
|
retArgs = append(retArgs, taskArgs[1:]...)
|
||||||
|
return
|
||||||
|
|
||||||
|
default:
|
||||||
|
return nil, nil, false, fmt.Errorf("Unrecognized task %q", taskArgs[0])
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user