~dricottone/simple-builder

ref: 78239b8a599c83acbfaf3107b8576c27f2d9d68e simple-builder/docker.go -rw-r--r-- 2.3 KiB
78239b8aDominic Ricottone Initial commit 1 year, 4 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package main

import (
	"bufio"
	"context"
	"errors"
	"fmt"
	"os"
	"os/signal"

	"github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/container"
	"github.com/docker/docker/api/types/mount"
	"github.com/docker/docker/client"
	specs "github.com/opencontainers/image-spec/specs-go/v1"
)

// Create a container for building a package, start the build, and branch
// based on the result.
func build_package(pkg Package, srcdir, pkgdir, arch string) error {
	ctx := context.Background()

	cli, err := client.NewClientWithOpts(client.FromEnv)
	if (err != nil) {
		return err
	}

	conf := container.Config{
		Image: "registry.intra.dominic-ricottone.com/apkbuilder:latest",
		Cmd: []string{pkg.Name},
	}

	con_conf := container.HostConfig{
		Mounts: []mount.Mount{
			{
				Type: mount.TypeBind,
				Source: srcdir,
				Target: "/home/builder/src",
			},
			{
				Type: mount.TypeBind,
				Source: pkgdir,
				Target: "/home/builder/packages/src",
			},
		},
	}

	plats := specs.Platform{
		Architecture: arch,
		OS: "linux",
	}

	con, err := cli.ContainerCreate(ctx, &conf, &con_conf, nil, &plats, "")
	if (err != nil) {
		return err
	}

	start_opts := types.ContainerStartOptions{}

	cli.ContainerStart(ctx, con.ID, start_opts)

	err = check_result(cli, ctx, con.ID)
	if (err != nil) {
		return err
	}

	rm_opts := types.ContainerRemoveOptions{
		Force: true,
	}

	cli.ContainerRemove(ctx, con.ID, rm_opts)

	return nil
}

// Get the result of a build. Blocks until the build is complete.
func check_result(cli *client.Client, ctx context.Context, id string) error {
	statusC, errC := cli.ContainerWait(ctx, id, container.WaitConditionNotRunning)

	sigC := make(chan os.Signal)
	signal.Notify(sigC, os.Interrupt)

	select {
	case _ = <-sigC:
		return errors.New("Build interrupted")

	case err := <-errC:
		if (err != nil) {
			return err
		}

	case status := <-statusC:
		if status.StatusCode != 0 {
			dump_logs(cli, ctx, id)
			return errors.New("Build failed")
		}
	}

	return nil
}

// Dump logs from a build.
func dump_logs(cli *client.Client, ctx context.Context, id string) {
	conf := types.ContainerLogsOptions{
		ShowStdout: true,
	}

	out, err := cli.ContainerLogs(ctx, id, conf)
	if err != nil {
		panic(err)
	}
	defer out.Close()

	scanner := bufio.NewScanner(out)
	for scanner.Scan() {
		fmt.Println(scanner.Text())
	}
}