github.com/grahambrereton-form3/tilt@v0.10.18/cmd/buildkitapi/main.go (about)

     1  package main
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"flag"
     7  	"io"
     8  	"log"
     9  	"os"
    10  
    11  	"github.com/docker/docker/api/types"
    12  	"github.com/docker/docker/client"
    13  	"github.com/docker/docker/pkg/jsonmessage"
    14  	controlapi "github.com/moby/buildkit/api/services/control"
    15  	"github.com/pkg/errors"
    16  
    17  	"github.com/windmilleng/tilt/internal/build"
    18  )
    19  
    20  var useCache bool
    21  
    22  // A small utility for running Buildkit on the dockerfile
    23  // in the current directory printing out all the buildkit api
    24  // response protobufs.
    25  func main() {
    26  	flag.BoolVar(&useCache, "cache", false, "Enable docker caching")
    27  	flag.Parse()
    28  
    29  	err := run()
    30  	if err != nil {
    31  		log.Fatal(err)
    32  	}
    33  }
    34  
    35  func run() error {
    36  	ctx := context.Background()
    37  	d, err := client.NewEnvClient()
    38  	if err != nil {
    39  		return err
    40  	}
    41  
    42  	d.NegotiateAPIVersion(ctx)
    43  
    44  	pr, pw := io.Pipe()
    45  	go func() {
    46  		err := build.TarPath(ctx, pw, ".")
    47  		if err != nil {
    48  			_ = pw.CloseWithError(err)
    49  		} else {
    50  			_ = pw.Close()
    51  		}
    52  	}()
    53  
    54  	opts := types.ImageBuildOptions{}
    55  	opts.Version = types.BuilderBuildKit
    56  	opts.Dockerfile = "Dockerfile"
    57  	opts.Context = pr
    58  	if !useCache {
    59  		opts.NoCache = true
    60  	}
    61  
    62  	response, err := d.ImageBuild(ctx, pr, opts)
    63  	if err != nil {
    64  		return err
    65  	}
    66  	defer func() {
    67  		_ = response.Body.Close()
    68  	}()
    69  
    70  	return readDockerOutput(ctx, response.Body)
    71  }
    72  
    73  func readDockerOutput(ctx context.Context, reader io.Reader) error {
    74  	decoder := json.NewDecoder(reader)
    75  
    76  	for decoder.More() {
    77  		message := jsonmessage.JSONMessage{}
    78  		err := decoder.Decode(&message)
    79  		if err != nil {
    80  			return errors.Wrap(err, "decoding docker output")
    81  		}
    82  
    83  		if messageIsFromBuildkit(message) {
    84  			err := writeBuildkitStatus(message.Aux)
    85  			if err != nil {
    86  				return err
    87  			}
    88  		}
    89  	}
    90  	return nil
    91  }
    92  
    93  func writeBuildkitStatus(aux *json.RawMessage) error {
    94  	var resp controlapi.StatusResponse
    95  	var dt []byte
    96  	if err := json.Unmarshal(*aux, &dt); err != nil {
    97  		return err
    98  	}
    99  	if err := (&resp).Unmarshal(dt); err != nil {
   100  		return err
   101  	}
   102  
   103  	return json.NewEncoder(os.Stdout).Encode(resp)
   104  }
   105  
   106  func messageIsFromBuildkit(msg jsonmessage.JSONMessage) bool {
   107  	return msg.ID == "moby.buildkit.trace"
   108  }