Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make it build on darwin #172

Merged
merged 3 commits into from
Dec 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ builds:
- CGO_ENABLED=0
ldflags:
- -s -w -X github.com/gitpod-io/leeway/pkg/leeway.Version={{.Version}}-{{.ShortCommit}}
ignore:
- goos: darwin

archives:
- replacements:
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,12 @@ leeway collect components -l someConstant
LEEWAY_EXPERIMENTAL=true leeway export --strict /some/destination
```

### macOS: leeway fails with "cp --parents" not being a valid command
The way depends on GNU utilities. Install them and make sure they're in your path.
```
brew install coreutils
```

# Contributing

## Creating a new release
Expand Down
Binary file added leeway
Binary file not shown.
130 changes: 0 additions & 130 deletions pkg/leeway/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ import (
"time"

"github.com/in-toto/in-toto-golang/in_toto"
"github.com/opencontainers/runc/libcontainer/specconv"
"github.com/opencontainers/runtime-spec/specs-go"
log "github.com/sirupsen/logrus"
"golang.org/x/mod/modfile"
"golang.org/x/sync/semaphore"
Expand Down Expand Up @@ -1607,134 +1605,6 @@ func executeCommandsForPackage(buildctx *buildContext, p *Package, wd string, co
return nil
}

func executeCommandsForPackageSafe(buildctx *buildContext, p *Package, wd string, commands [][]string) error {
tmpdir, err := os.MkdirTemp("", "leeway-*")
if err != nil {
return err
}

jc, err := json.Marshal(commands)
if err != nil {
return err
}
commandsFN := filepath.Join(tmpdir, "commands")
err = os.WriteFile(commandsFN, []byte(base64.StdEncoding.EncodeToString(jc)), 0644)
if err != nil {
return err
}

if !log.IsLevelEnabled(log.DebugLevel) {
defer os.RemoveAll(tmpdir)
}

log.WithField("tmpdir", tmpdir).WithField("package", p.FullName()).Debug("preparing build runc environment")
err = os.MkdirAll(filepath.Join(tmpdir, "rootfs"), 0755)
if err != nil {
return err
}

version, err := p.Version()
if err != nil {
return err
}
name := fmt.Sprintf("b%s", version)

spec := specconv.Example()
specconv.ToRootless(spec)

// we assemble the root filesystem from the outside world
for _, d := range []string{"home", "bin", "dev", "etc", "lib", "lib64", "opt", "sbin", "sys", "usr", "var"} {
spec.Mounts = append(spec.Mounts, specs.Mount{
Destination: "/" + d,
Source: "/" + d,
Type: "bind",
Options: []string{"rbind", "rprivate"},
})
}

spec.Mounts = append(spec.Mounts, specs.Mount{Destination: "/build", Source: wd, Type: "bind", Options: []string{"bind", "private"}})
spec.Mounts = append(spec.Mounts, specs.Mount{Destination: "/commands", Source: commandsFN, Type: "bind", Options: []string{"bind", "private"}})

for _, p := range []string{"tmp", "root"} {
fn := filepath.Join(tmpdir, p)
err = os.MkdirAll(fn, 0777)
if err != nil {
return err
}
spec.Mounts = append(spec.Mounts, specs.Mount{Destination: "/" + p, Source: fn, Type: "bind", Options: []string{"bind", "private"}})
}

buildCache, _ := buildctx.LocalCache.Location(p)
buildCache = filepath.Dir(buildCache)
spec.Mounts = append(spec.Mounts, specs.Mount{Destination: buildCache, Source: buildCache, Type: "bind", Options: []string{"bind", "private"}})

self, err := os.Executable()
if err != nil {
return err
}
spec.Mounts = append(spec.Mounts, specs.Mount{Destination: "/leeway", Source: self, Type: "bind", Options: []string{"bind", "private"}})

if p := os.Getenv("GOPATH"); p != "" {
spec.Mounts = append(spec.Mounts, specs.Mount{Destination: p, Source: p, Type: "bind", Options: []string{"bind", "private"}})
}
if p := os.Getenv("GOROOT"); p != "" {
spec.Mounts = append(spec.Mounts, specs.Mount{Destination: p, Source: p, Type: "bind", Options: []string{"bind", "private"}})
}
if p := os.Getenv("DOCKER_HOST"); strings.HasPrefix(p, "file://") {
p = strings.TrimPrefix(p, "file://")
spec.Mounts = append(spec.Mounts, specs.Mount{Destination: p, Source: p, Type: "bind", Options: []string{"bind", "private"}})
} else if _, err := os.Stat("/var/run/docker.sock"); err == nil {
p = "/var/run/docker.sock"
spec.Mounts = append(spec.Mounts, specs.Mount{Destination: p, Source: p, Type: "bind", Options: []string{"bind", "private"}})
}

var env []string
for _, e := range []string{"PATH", "TERM", "GOROOT", "GOPATH"} {
val := os.Getenv(e)
if val == "" {
continue
}
env = append(env, fmt.Sprintf("%s=%s", e, val))
}

spec.Hostname = name
spec.Process.Terminal = false
spec.Process.NoNewPrivileges = true
spec.Process.Args = []string{"/leeway", "plumbing", "exec", "/commands"}
if log.IsLevelEnabled(log.DebugLevel) {
spec.Process.Args = append(spec.Process.Args, "--verbose")

}
spec.Process.Cwd = "/build"
spec.Process.Env = env

fc, err := json.MarshalIndent(spec, "", " ")
if err != nil {
return err
}
err = os.WriteFile(filepath.Join(tmpdir, "config.json"), fc, 0644)
if err != nil {
return err
}

args := []string{
"--root", "state",
"--log-format", "json",
}
if log.IsLevelEnabled(log.DebugLevel) {
args = append(args, "--debug")
}
args = append(args,
"run", name,
)

cmd := exec.Command("runc", args...)
cmd.Dir = tmpdir
cmd.Stdout = &reporterStream{R: buildctx.Reporter, P: p, IsErr: false}
cmd.Stderr = &reporterStream{R: buildctx.Reporter, P: p, IsErr: true}
return cmd.Run()
}

func run(rep Reporter, p *Package, env []string, cwd, name string, args ...string) error {
log.WithField("package", p.FullName()).WithField("command", strings.Join(append([]string{name}, args...), " ")).Debug("running")

Expand Down
9 changes: 9 additions & 0 deletions pkg/leeway/build_darwin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package leeway

import (
"fmt"
)

func executeCommandsForPackageSafe(buildctx *buildContext, p *Package, wd string, commands [][]string) error {
return fmt.Errorf("not implemented")
}
143 changes: 143 additions & 0 deletions pkg/leeway/build_linux.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
package leeway

import (
"encoding/base64"
"encoding/json"
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"

"github.com/opencontainers/runc/libcontainer/specconv"
"github.com/opencontainers/runtime-spec/specs-go"
log "github.com/sirupsen/logrus"
)

func executeCommandsForPackageSafe(buildctx *buildContext, p *Package, wd string, commands [][]string) error {
tmpdir, err := os.MkdirTemp("", "leeway-*")
if err != nil {
return err

Check warning on line 20 in pkg/leeway/build_linux.go

View check run for this annotation

Codecov / codecov/patch

pkg/leeway/build_linux.go#L18-L20

Added lines #L18 - L20 were not covered by tests
}

jc, err := json.Marshal(commands)
if err != nil {
return err

Check warning on line 25 in pkg/leeway/build_linux.go

View check run for this annotation

Codecov / codecov/patch

pkg/leeway/build_linux.go#L23-L25

Added lines #L23 - L25 were not covered by tests
}
commandsFN := filepath.Join(tmpdir, "commands")
err = os.WriteFile(commandsFN, []byte(base64.StdEncoding.EncodeToString(jc)), 0644)
if err != nil {
return err

Check warning on line 30 in pkg/leeway/build_linux.go

View check run for this annotation

Codecov / codecov/patch

pkg/leeway/build_linux.go#L27-L30

Added lines #L27 - L30 were not covered by tests
}

if !log.IsLevelEnabled(log.DebugLevel) {
defer os.RemoveAll(tmpdir)

Check warning on line 34 in pkg/leeway/build_linux.go

View check run for this annotation

Codecov / codecov/patch

pkg/leeway/build_linux.go#L33-L34

Added lines #L33 - L34 were not covered by tests
}

log.WithField("tmpdir", tmpdir).WithField("package", p.FullName()).Debug("preparing build runc environment")
err = os.MkdirAll(filepath.Join(tmpdir, "rootfs"), 0755)
if err != nil {
return err

Check warning on line 40 in pkg/leeway/build_linux.go

View check run for this annotation

Codecov / codecov/patch

pkg/leeway/build_linux.go#L37-L40

Added lines #L37 - L40 were not covered by tests
}

version, err := p.Version()
if err != nil {
return err

Check warning on line 45 in pkg/leeway/build_linux.go

View check run for this annotation

Codecov / codecov/patch

pkg/leeway/build_linux.go#L43-L45

Added lines #L43 - L45 were not covered by tests
}
name := fmt.Sprintf("b%s", version)

Check warning on line 47 in pkg/leeway/build_linux.go

View check run for this annotation

Codecov / codecov/patch

pkg/leeway/build_linux.go#L47

Added line #L47 was not covered by tests

spec := specconv.Example()
specconv.ToRootless(spec)

Check warning on line 50 in pkg/leeway/build_linux.go

View check run for this annotation

Codecov / codecov/patch

pkg/leeway/build_linux.go#L49-L50

Added lines #L49 - L50 were not covered by tests

// we assemble the root filesystem from the outside world
for _, d := range []string{"home", "bin", "dev", "etc", "lib", "lib64", "opt", "sbin", "sys", "usr", "var"} {
spec.Mounts = append(spec.Mounts, specs.Mount{
Destination: "/" + d,
Source: "/" + d,
Type: "bind",
Options: []string{"rbind", "rprivate"},
})

Check warning on line 59 in pkg/leeway/build_linux.go

View check run for this annotation

Codecov / codecov/patch

pkg/leeway/build_linux.go#L54-L59

Added lines #L54 - L59 were not covered by tests
}

spec.Mounts = append(spec.Mounts, specs.Mount{Destination: "/build", Source: wd, Type: "bind", Options: []string{"bind", "private"}})
spec.Mounts = append(spec.Mounts, specs.Mount{Destination: "/commands", Source: commandsFN, Type: "bind", Options: []string{"bind", "private"}})

Check warning on line 63 in pkg/leeway/build_linux.go

View check run for this annotation

Codecov / codecov/patch

pkg/leeway/build_linux.go#L62-L63

Added lines #L62 - L63 were not covered by tests

for _, p := range []string{"tmp", "root"} {
fn := filepath.Join(tmpdir, p)
err = os.MkdirAll(fn, 0777)
if err != nil {
return err

Check warning on line 69 in pkg/leeway/build_linux.go

View check run for this annotation

Codecov / codecov/patch

pkg/leeway/build_linux.go#L66-L69

Added lines #L66 - L69 were not covered by tests
}
spec.Mounts = append(spec.Mounts, specs.Mount{Destination: "/" + p, Source: fn, Type: "bind", Options: []string{"bind", "private"}})

Check warning on line 71 in pkg/leeway/build_linux.go

View check run for this annotation

Codecov / codecov/patch

pkg/leeway/build_linux.go#L71

Added line #L71 was not covered by tests
}

buildCache, _ := buildctx.LocalCache.Location(p)
buildCache = filepath.Dir(buildCache)
spec.Mounts = append(spec.Mounts, specs.Mount{Destination: buildCache, Source: buildCache, Type: "bind", Options: []string{"bind", "private"}})

Check warning on line 76 in pkg/leeway/build_linux.go

View check run for this annotation

Codecov / codecov/patch

pkg/leeway/build_linux.go#L74-L76

Added lines #L74 - L76 were not covered by tests

self, err := os.Executable()
if err != nil {
return err

Check warning on line 80 in pkg/leeway/build_linux.go

View check run for this annotation

Codecov / codecov/patch

pkg/leeway/build_linux.go#L78-L80

Added lines #L78 - L80 were not covered by tests
}
spec.Mounts = append(spec.Mounts, specs.Mount{Destination: "/leeway", Source: self, Type: "bind", Options: []string{"bind", "private"}})

Check warning on line 82 in pkg/leeway/build_linux.go

View check run for this annotation

Codecov / codecov/patch

pkg/leeway/build_linux.go#L82

Added line #L82 was not covered by tests

if p := os.Getenv("GOPATH"); p != "" {
spec.Mounts = append(spec.Mounts, specs.Mount{Destination: p, Source: p, Type: "bind", Options: []string{"bind", "private"}})

Check warning on line 85 in pkg/leeway/build_linux.go

View check run for this annotation

Codecov / codecov/patch

pkg/leeway/build_linux.go#L84-L85

Added lines #L84 - L85 were not covered by tests
}
if p := os.Getenv("GOROOT"); p != "" {
spec.Mounts = append(spec.Mounts, specs.Mount{Destination: p, Source: p, Type: "bind", Options: []string{"bind", "private"}})

Check warning on line 88 in pkg/leeway/build_linux.go

View check run for this annotation

Codecov / codecov/patch

pkg/leeway/build_linux.go#L87-L88

Added lines #L87 - L88 were not covered by tests
}
if p := os.Getenv("DOCKER_HOST"); strings.HasPrefix(p, "file://") {
p = strings.TrimPrefix(p, "file://")
spec.Mounts = append(spec.Mounts, specs.Mount{Destination: p, Source: p, Type: "bind", Options: []string{"bind", "private"}})
} else if _, err := os.Stat("/var/run/docker.sock"); err == nil {
p = "/var/run/docker.sock"
spec.Mounts = append(spec.Mounts, specs.Mount{Destination: p, Source: p, Type: "bind", Options: []string{"bind", "private"}})

Check warning on line 95 in pkg/leeway/build_linux.go

View check run for this annotation

Codecov / codecov/patch

pkg/leeway/build_linux.go#L90-L95

Added lines #L90 - L95 were not covered by tests
}

var env []string

Check warning on line 98 in pkg/leeway/build_linux.go

View check run for this annotation

Codecov / codecov/patch

pkg/leeway/build_linux.go#L98

Added line #L98 was not covered by tests
for _, e := range []string{"PATH", "TERM", "GOROOT", "GOPATH"} {
val := os.Getenv(e)
if val == "" {
continue

Check warning on line 102 in pkg/leeway/build_linux.go

View check run for this annotation

Codecov / codecov/patch

pkg/leeway/build_linux.go#L100-L102

Added lines #L100 - L102 were not covered by tests
}
env = append(env, fmt.Sprintf("%s=%s", e, val))

Check warning on line 104 in pkg/leeway/build_linux.go

View check run for this annotation

Codecov / codecov/patch

pkg/leeway/build_linux.go#L104

Added line #L104 was not covered by tests
}

spec.Hostname = name
spec.Process.Terminal = false
spec.Process.NoNewPrivileges = true
spec.Process.Args = []string{"/leeway", "plumbing", "exec", "/commands"}
if log.IsLevelEnabled(log.DebugLevel) {
spec.Process.Args = append(spec.Process.Args, "--verbose")

Check warning on line 112 in pkg/leeway/build_linux.go

View check run for this annotation

Codecov / codecov/patch

pkg/leeway/build_linux.go#L107-L112

Added lines #L107 - L112 were not covered by tests

}
spec.Process.Cwd = "/build"
spec.Process.Env = env

Check warning on line 116 in pkg/leeway/build_linux.go

View check run for this annotation

Codecov / codecov/patch

pkg/leeway/build_linux.go#L115-L116

Added lines #L115 - L116 were not covered by tests

fc, err := json.MarshalIndent(spec, "", " ")
if err != nil {
return err

Check warning on line 120 in pkg/leeway/build_linux.go

View check run for this annotation

Codecov / codecov/patch

pkg/leeway/build_linux.go#L118-L120

Added lines #L118 - L120 were not covered by tests
}
err = os.WriteFile(filepath.Join(tmpdir, "config.json"), fc, 0644)
if err != nil {
return err

Check warning on line 124 in pkg/leeway/build_linux.go

View check run for this annotation

Codecov / codecov/patch

pkg/leeway/build_linux.go#L122-L124

Added lines #L122 - L124 were not covered by tests
}

args := []string{
"--root", "state",
"--log-format", "json",

Check warning on line 129 in pkg/leeway/build_linux.go

View check run for this annotation

Codecov / codecov/patch

pkg/leeway/build_linux.go#L127-L129

Added lines #L127 - L129 were not covered by tests
}
if log.IsLevelEnabled(log.DebugLevel) {
args = append(args, "--debug")

Check warning on line 132 in pkg/leeway/build_linux.go

View check run for this annotation

Codecov / codecov/patch

pkg/leeway/build_linux.go#L131-L132

Added lines #L131 - L132 were not covered by tests
}
args = append(args,
"run", name,
)

Check warning on line 136 in pkg/leeway/build_linux.go

View check run for this annotation

Codecov / codecov/patch

pkg/leeway/build_linux.go#L134-L136

Added lines #L134 - L136 were not covered by tests

cmd := exec.Command("runc", args...)
cmd.Dir = tmpdir
cmd.Stdout = &reporterStream{R: buildctx.Reporter, P: p, IsErr: false}
cmd.Stderr = &reporterStream{R: buildctx.Reporter, P: p, IsErr: true}
return cmd.Run()

Check warning on line 142 in pkg/leeway/build_linux.go

View check run for this annotation

Codecov / codecov/patch

pkg/leeway/build_linux.go#L138-L142

Added lines #L138 - L142 were not covered by tests
}
Loading