Consolidate exec package with go-execute
This patch consolidates the exec package for docker build so that it uses the the go-execute package used in other OpenFaaS projects. The aim is to allow for conditional printing of stdio whilst also being able to capture the output. In a future PR a CLI animation can replace the Docker build, which will be default, but optional. If an error is found then the result of the build will be buffered and available to print to the user. This change stops Docker from printing progress bars when downloading layers. Instead a line is printed when pulling and when a layer is complete. * Tested for faas-cli build with multiple functions using the sample stack.yml and --parallel=1/4. * Adds StreamStdio option and updates Docker build version to use Go 1.12. * Add complete build time to output * Add duration of each build to output * Add --quiet flag for faas-cli build * The --quiet flag hides output from Docker during the execution of the docker build. Signed-off-by: Alex Ellis (OpenFaaS Ltd) <alexellis2@gmail.com>
This commit is contained in:
committed by
Alex Ellis
parent
83fd873d45
commit
38ecd73a60
15
.travis.yml
15
.travis.yml
@@ -1,14 +1,11 @@
|
|||||||
sudo: required
|
sudo: required
|
||||||
|
|
||||||
language: generic
|
language: generic
|
||||||
|
|
||||||
services:
|
|
||||||
- docker
|
|
||||||
|
|
||||||
addons:
|
services:
|
||||||
apt:
|
- docker
|
||||||
packages:
|
|
||||||
- docker-ce
|
before_script:
|
||||||
|
- curl -sSLf https://get.docker.com | sed s/sleep\ 20/sleep\ 0/g | sudo -E sh
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- make build
|
- make build
|
||||||
@@ -55,3 +52,5 @@ deploy:
|
|||||||
on:
|
on:
|
||||||
tags: true
|
tags: true
|
||||||
|
|
||||||
|
env:
|
||||||
|
- GO111MODULE=off
|
||||||
|
|||||||
13
Dockerfile
13
Dockerfile
@@ -1,5 +1,8 @@
|
|||||||
# Build stage
|
# Build stage
|
||||||
FROM golang:1.11 as builder
|
FROM golang:1.12 as builder
|
||||||
|
|
||||||
|
ENV GO111MODULE=off
|
||||||
|
ENV CGO_ENABLED=0
|
||||||
|
|
||||||
WORKDIR /usr/bin/
|
WORKDIR /usr/bin/
|
||||||
RUN curl -sLSf https://raw.githubusercontent.com/teamserverless/license-check/master/get.sh | sh
|
RUN curl -sLSf https://raw.githubusercontent.com/teamserverless/license-check/master/get.sh | sh
|
||||||
@@ -13,8 +16,10 @@ RUN test -z "$(gofmt -l $(find . -type f -name '*.go' -not -path "./vendor/*"))"
|
|||||||
# ldflags "-s -w" strips binary
|
# ldflags "-s -w" strips binary
|
||||||
# ldflags -X injects commit version into binary
|
# ldflags -X injects commit version into binary
|
||||||
RUN /usr/bin/license-check -path ./ --verbose=false "Alex Ellis" "OpenFaaS Author(s)"
|
RUN /usr/bin/license-check -path ./ --verbose=false "Alex Ellis" "OpenFaaS Author(s)"
|
||||||
RUN go test $(go list ./... | grep -v /vendor/ | grep -v /template/|grep -v /build/) -cover \
|
|
||||||
&& VERSION=$(git describe --all --exact-match `git rev-parse HEAD` | grep tags | sed 's/tags\///') \
|
RUN go test $(go list ./... | grep -v /vendor/ | grep -v /template/|grep -v /build/|grep -v /sample/) -cover
|
||||||
|
|
||||||
|
RUN VERSION=$(git describe --all --exact-match `git rev-parse HEAD` | grep tags | sed 's/tags\///') \
|
||||||
&& GIT_COMMIT=$(git rev-list -1 HEAD) \
|
&& GIT_COMMIT=$(git rev-list -1 HEAD) \
|
||||||
&& CGO_ENABLED=0 GOOS=linux go build --ldflags "-s -w \
|
&& CGO_ENABLED=0 GOOS=linux go build --ldflags "-s -w \
|
||||||
-X github.com/openfaas/faas-cli/version.GitCommit=${GIT_COMMIT} \
|
-X github.com/openfaas/faas-cli/version.GitCommit=${GIT_COMMIT} \
|
||||||
@@ -23,7 +28,7 @@ RUN go test $(go list ./... | grep -v /vendor/ | grep -v /template/|grep -v /bui
|
|||||||
-a -installsuffix cgo -o faas-cli
|
-a -installsuffix cgo -o faas-cli
|
||||||
|
|
||||||
# Release stage
|
# Release stage
|
||||||
FROM alpine:3.9
|
FROM alpine:3.10
|
||||||
|
|
||||||
RUN apk --no-cache add ca-certificates git
|
RUN apk --no-cache add ca-certificates git
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
# Build stage
|
# Build stage
|
||||||
FROM golang:1.11 as builder
|
FROM golang:1.12 as builder
|
||||||
|
|
||||||
|
ENV GO111MODULE=off
|
||||||
|
ENV CGO_ENABLED=0
|
||||||
|
|
||||||
WORKDIR /usr/bin/
|
WORKDIR /usr/bin/
|
||||||
RUN curl -sLSf https://raw.githubusercontent.com/teamserverless/license-check/master/get.sh | sh
|
RUN curl -sLSf https://raw.githubusercontent.com/teamserverless/license-check/master/get.sh | sh
|
||||||
@@ -44,7 +47,7 @@ RUN /usr/bin/license-check -path ./ --verbose=false "Alex Ellis" "OpenFaaS Autho
|
|||||||
-a -installsuffix cgo -o faas-cli-arm64
|
-a -installsuffix cgo -o faas-cli-arm64
|
||||||
|
|
||||||
# Release stage
|
# Release stage
|
||||||
FROM alpine:3.9
|
FROM alpine:3.10
|
||||||
|
|
||||||
RUN apk --no-cache add ca-certificates git
|
RUN apk --no-cache add ca-certificates git
|
||||||
|
|
||||||
|
|||||||
9
Gopkg.lock
generated
9
Gopkg.lock
generated
@@ -20,6 +20,14 @@
|
|||||||
revision = "839c75faf7f98a33d445d181f3018b5c3409a45e"
|
revision = "839c75faf7f98a33d445d181f3018b5c3409a45e"
|
||||||
version = "v1.4.2"
|
version = "v1.4.2"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
digest = "1:74860eb071d52337d67e9ffd6893b29affebd026505aa917ec23131576a91a77"
|
||||||
|
name = "github.com/alexellis/go-execute"
|
||||||
|
packages = ["pkg/v1"]
|
||||||
|
pruneopts = "UT"
|
||||||
|
revision = "961405ea754427780f2151adff607fa740d377f7"
|
||||||
|
version = "0.3.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:871b7cfa5fe18bfdbd4bf117c166c3cff8d3b61c8afe4e998b5b8ac0c160ca24"
|
digest = "1:871b7cfa5fe18bfdbd4bf117c166c3cff8d3b61c8afe4e998b5b8ac0c160ca24"
|
||||||
name = "github.com/alexellis/hmac"
|
name = "github.com/alexellis/hmac"
|
||||||
@@ -166,6 +174,7 @@
|
|||||||
analyzer-name = "dep"
|
analyzer-name = "dep"
|
||||||
analyzer-version = 1
|
analyzer-version = 1
|
||||||
input-imports = [
|
input-imports = [
|
||||||
|
"github.com/alexellis/go-execute/pkg/v1",
|
||||||
"github.com/alexellis/hmac",
|
"github.com/alexellis/hmac",
|
||||||
"github.com/docker/docker-credential-helpers/client",
|
"github.com/docker/docker-credential-helpers/client",
|
||||||
"github.com/docker/docker/pkg/term",
|
"github.com/docker/docker/pkg/term",
|
||||||
|
|||||||
@@ -49,3 +49,9 @@
|
|||||||
[[constraint]]
|
[[constraint]]
|
||||||
name = "github.com/pkg/errors"
|
name = "github.com/pkg/errors"
|
||||||
version = "v0.8.1"
|
version = "v0.8.1"
|
||||||
|
|
||||||
|
[[constraint]]
|
||||||
|
name = "github.com/alexellis/go-execute"
|
||||||
|
version = "0.3.0"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
16
build.sh
16
build.sh
@@ -1,4 +1,4 @@
|
|||||||
#!/bin/sh
|
#!/bin/bash
|
||||||
|
|
||||||
export eTAG="latest-dev"
|
export eTAG="latest-dev"
|
||||||
echo $1
|
echo $1
|
||||||
@@ -8,8 +8,14 @@ fi
|
|||||||
|
|
||||||
echo Building openfaas/faas-cli:$eTAG
|
echo Building openfaas/faas-cli:$eTAG
|
||||||
|
|
||||||
docker build --build-arg http_proxy=$http_proxy --build-arg https_proxy=$https_proxy -t openfaas/faas-cli:$eTAG . && \
|
docker build --build-arg http_proxy=$http_proxy --build-arg https_proxy=$https_proxy -t openfaas/faas-cli:$eTAG .
|
||||||
docker create --name faas-cli openfaas/faas-cli:$eTAG && \
|
|
||||||
docker cp faas-cli:/usr/bin/faas-cli . && \
|
|
||||||
docker rm -f faas-cli
|
|
||||||
|
|
||||||
|
if [ $? == 0 ] ; then
|
||||||
|
|
||||||
|
docker create --name faas-cli openfaas/faas-cli:$eTAG && \
|
||||||
|
docker cp faas-cli:/usr/bin/faas-cli . && \
|
||||||
|
docker rm -f faas-cli
|
||||||
|
|
||||||
|
else
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/openfaas/faas-cli/exec"
|
v1execute "github.com/alexellis/go-execute/pkg/v1"
|
||||||
"github.com/openfaas/faas-cli/schema"
|
"github.com/openfaas/faas-cli/schema"
|
||||||
"github.com/openfaas/faas-cli/stack"
|
"github.com/openfaas/faas-cli/stack"
|
||||||
vcs "github.com/openfaas/faas-cli/versioncontrol"
|
vcs "github.com/openfaas/faas-cli/versioncontrol"
|
||||||
@@ -22,7 +22,7 @@ import (
|
|||||||
const AdditionalPackageBuildArg = "ADDITIONAL_PACKAGE"
|
const AdditionalPackageBuildArg = "ADDITIONAL_PACKAGE"
|
||||||
|
|
||||||
// BuildImage construct Docker image from function parameters
|
// BuildImage construct Docker image from function parameters
|
||||||
func BuildImage(image string, handler string, functionName string, language string, nocache bool, squash bool, shrinkwrap bool, buildArgMap map[string]string, buildOptions []string, tagMode schema.BuildFormat, buildLabelMap map[string]string) error {
|
func BuildImage(image string, handler string, functionName string, language string, nocache bool, squash bool, shrinkwrap bool, buildArgMap map[string]string, buildOptions []string, tagMode schema.BuildFormat, buildLabelMap map[string]string, quietBuild bool) error {
|
||||||
|
|
||||||
if stack.IsValidTemplate(language) {
|
if stack.IsValidTemplate(language) {
|
||||||
branch, version, err := GetImageTagValues(tagMode)
|
branch, version, err := GetImageTagValues(tagMode)
|
||||||
@@ -67,9 +67,25 @@ func BuildImage(image string, handler string, functionName string, language stri
|
|||||||
BuildLabelMap: buildLabelMap,
|
BuildLabelMap: buildLabelMap,
|
||||||
}
|
}
|
||||||
|
|
||||||
spaceSafeCmdLine := getDockerBuildCommand(dockerBuildVal)
|
command, args := getDockerBuildCommand(dockerBuildVal)
|
||||||
|
|
||||||
|
task := v1execute.ExecTask{
|
||||||
|
Cwd: tempPath,
|
||||||
|
Command: command,
|
||||||
|
Args: args,
|
||||||
|
StreamStdio: !quietBuild,
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := task.Execute()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if res.ExitCode != 0 {
|
||||||
|
return fmt.Errorf("[%s] received non-zero exit code from build, error: %s", functionName, res.Stderr)
|
||||||
|
}
|
||||||
|
|
||||||
exec.Command(tempPath, spaceSafeCmdLine)
|
|
||||||
fmt.Printf("Image: %s built.\n", imageName)
|
fmt.Printf("Image: %s built.\n", imageName)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@@ -113,13 +129,15 @@ func GetImageTagValues(tagType schema.BuildFormat) (branch, version string, err
|
|||||||
return branch, version, nil
|
return branch, version, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getDockerBuildCommand(build dockerBuild) []string {
|
func getDockerBuildCommand(build dockerBuild) (string, []string) {
|
||||||
flagSlice := buildFlagSlice(build.NoCache, build.Squash, build.HTTPProxy, build.HTTPSProxy, build.BuildArgMap, build.BuildOptPackages, build.BuildLabelMap)
|
flagSlice := buildFlagSlice(build.NoCache, build.Squash, build.HTTPProxy, build.HTTPSProxy, build.BuildArgMap, build.BuildOptPackages, build.BuildLabelMap)
|
||||||
command := []string{"docker", "build"}
|
args := []string{"build"}
|
||||||
command = append(command, flagSlice...)
|
args = append(args, flagSlice...)
|
||||||
command = append(command, "-t", build.Image, ".")
|
args = append(args, "-t", build.Image, ".")
|
||||||
|
|
||||||
return command
|
command := "docker"
|
||||||
|
|
||||||
|
return command, args
|
||||||
}
|
}
|
||||||
|
|
||||||
type dockerBuild struct {
|
type dockerBuild struct {
|
||||||
|
|||||||
@@ -41,14 +41,20 @@ func Test_getDockerBuildCommand_NoOpts(t *testing.T) {
|
|||||||
BuildOptPackages: []string{},
|
BuildOptPackages: []string{},
|
||||||
}
|
}
|
||||||
|
|
||||||
values := getDockerBuildCommand(dockerBuildVal)
|
want := "build -t imagename:latest ."
|
||||||
|
wantCommand := "docker"
|
||||||
|
|
||||||
joined := strings.Join(values, " ")
|
command, args := getDockerBuildCommand(dockerBuildVal)
|
||||||
want := "docker build -t imagename:latest ."
|
|
||||||
|
joined := strings.Join(args, " ")
|
||||||
|
|
||||||
if joined != want {
|
if joined != want {
|
||||||
t.Errorf("getDockerBuildCommand want: \"%s\", got: \"%s\"", want, joined)
|
t.Errorf("getDockerBuildCommand want: \"%s\", got: \"%s\"", want, joined)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if command != wantCommand {
|
||||||
|
t.Errorf("getDockerBuildCommand want command: \"%s\", got: \"%s\"", wantCommand, command)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_getDockerBuildCommand_WithNoCache(t *testing.T) {
|
func Test_getDockerBuildCommand_WithNoCache(t *testing.T) {
|
||||||
@@ -62,14 +68,21 @@ func Test_getDockerBuildCommand_WithNoCache(t *testing.T) {
|
|||||||
BuildOptPackages: []string{},
|
BuildOptPackages: []string{},
|
||||||
}
|
}
|
||||||
|
|
||||||
values := getDockerBuildCommand(dockerBuildVal)
|
want := "build --no-cache -t imagename:latest ."
|
||||||
|
|
||||||
joined := strings.Join(values, " ")
|
wantCommand := "docker"
|
||||||
want := "docker build --no-cache -t imagename:latest ."
|
|
||||||
|
command, args := getDockerBuildCommand(dockerBuildVal)
|
||||||
|
|
||||||
|
joined := strings.Join(args, " ")
|
||||||
|
|
||||||
if joined != want {
|
if joined != want {
|
||||||
t.Errorf("getDockerBuildCommand want: \"%s\", got: \"%s\"", want, joined)
|
t.Errorf("getDockerBuildCommand want: \"%s\", got: \"%s\"", want, joined)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if command != wantCommand {
|
||||||
|
t.Errorf("getDockerBuildCommand want command: \"%s\", got: \"%s\"", wantCommand, command)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_getDockerBuildCommand_WithProxies(t *testing.T) {
|
func Test_getDockerBuildCommand_WithProxies(t *testing.T) {
|
||||||
@@ -83,14 +96,21 @@ func Test_getDockerBuildCommand_WithProxies(t *testing.T) {
|
|||||||
BuildOptPackages: []string{},
|
BuildOptPackages: []string{},
|
||||||
}
|
}
|
||||||
|
|
||||||
values := getDockerBuildCommand(dockerBuildVal)
|
want := "build --build-arg http_proxy=http://127.0.0.1:3128 --build-arg https_proxy=https://127.0.0.1:3128 -t imagename:latest ."
|
||||||
|
|
||||||
joined := strings.Join(values, " ")
|
wantCommand := "docker"
|
||||||
want := "docker build --build-arg http_proxy=http://127.0.0.1:3128 --build-arg https_proxy=https://127.0.0.1:3128 -t imagename:latest ."
|
|
||||||
|
command, args := getDockerBuildCommand(dockerBuildVal)
|
||||||
|
|
||||||
|
joined := strings.Join(args, " ")
|
||||||
|
|
||||||
if joined != want {
|
if joined != want {
|
||||||
t.Errorf("getDockerBuildCommand want: \"%s\", got: \"%s\"", want, joined)
|
t.Errorf("getDockerBuildCommand want: \"%s\", got: \"%s\"", want, joined)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if command != wantCommand {
|
||||||
|
t.Errorf("getDockerBuildCommand want command: \"%s\", got: \"%s\"", wantCommand, command)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_getDockerBuildCommand_WithBuildArg(t *testing.T) {
|
func Test_getDockerBuildCommand_WithBuildArg(t *testing.T) {
|
||||||
@@ -105,7 +125,7 @@ func Test_getDockerBuildCommand_WithBuildArg(t *testing.T) {
|
|||||||
BuildOptPackages: []string{},
|
BuildOptPackages: []string{},
|
||||||
}
|
}
|
||||||
|
|
||||||
values := getDockerBuildCommand(dockerBuildVal)
|
_, values := getDockerBuildCommand(dockerBuildVal)
|
||||||
|
|
||||||
joined := strings.Join(values, " ")
|
joined := strings.Join(values, " ")
|
||||||
wantArg1 := "--build-arg USERNAME=admin"
|
wantArg1 := "--build-arg USERNAME=admin"
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/morikuni/aec"
|
"github.com/morikuni/aec"
|
||||||
"github.com/openfaas/faas-cli/builder"
|
"github.com/openfaas/faas-cli/builder"
|
||||||
@@ -31,6 +32,7 @@ var (
|
|||||||
buildLabels []string
|
buildLabels []string
|
||||||
buildLabelMap map[string]string
|
buildLabelMap map[string]string
|
||||||
envsubst bool
|
envsubst bool
|
||||||
|
quietBuild bool
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -52,6 +54,8 @@ func init() {
|
|||||||
|
|
||||||
buildCmd.Flags().BoolVar(&envsubst, "envsubst", true, "Substitute environment variables in stack.yml file")
|
buildCmd.Flags().BoolVar(&envsubst, "envsubst", true, "Substitute environment variables in stack.yml file")
|
||||||
|
|
||||||
|
buildCmd.Flags().BoolVar(&quietBuild, "quiet", false, "Perform a quiet build, without showing output from Docker")
|
||||||
|
|
||||||
// Set bash-completion.
|
// Set bash-completion.
|
||||||
_ = buildCmd.Flags().SetAnnotation("handler", cobra.BashCompSubdirsInDir, []string{})
|
_ = buildCmd.Flags().SetAnnotation("handler", cobra.BashCompSubdirsInDir, []string{})
|
||||||
|
|
||||||
@@ -103,6 +107,10 @@ func preRunBuild(cmd *cobra.Command, args []string) error {
|
|||||||
|
|
||||||
buildLabelMap, err = parseMap(buildLabels, "build-label")
|
buildLabelMap, err = parseMap(buildLabels, "build-label")
|
||||||
|
|
||||||
|
if parallel < 1 {
|
||||||
|
return fmt.Errorf("the --parallel flag must be great than 0")
|
||||||
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,11 +164,7 @@ func runBuild(cmd *cobra.Command, args []string) error {
|
|||||||
return fmt.Errorf("could not pull templates for OpenFaaS: %v", pullErr)
|
return fmt.Errorf("could not pull templates for OpenFaaS: %v", pullErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(services.Functions) > 0 {
|
if len(services.Functions) == 0 {
|
||||||
|
|
||||||
build(&services, parallel, shrinkwrap)
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if len(image) == 0 {
|
if len(image) == 0 {
|
||||||
return fmt.Errorf("please provide a valid --image name for your Docker image")
|
return fmt.Errorf("please provide a valid --image name for your Docker image")
|
||||||
}
|
}
|
||||||
@@ -170,16 +174,29 @@ func runBuild(cmd *cobra.Command, args []string) error {
|
|||||||
if len(functionName) == 0 {
|
if len(functionName) == 0 {
|
||||||
return fmt.Errorf("please provide the deployed --name of your function")
|
return fmt.Errorf("please provide the deployed --name of your function")
|
||||||
}
|
}
|
||||||
err := builder.BuildImage(image, handler, functionName, language, nocache, squash, shrinkwrap, buildArgMap, buildOptions, tagFormat, buildLabelMap)
|
err := builder.BuildImage(image, handler, functionName, language, nocache, squash, shrinkwrap, buildArgMap, buildOptions, tagFormat, buildLabelMap, quietBuild)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
errors := build(&services, parallel, shrinkwrap, quietBuild)
|
||||||
|
if len(errors) > 0 {
|
||||||
|
errorSummary := "Errors received during build:\n"
|
||||||
|
for _, err := range errors {
|
||||||
|
errorSummary = errorSummary + "- " + err.Error() + "\n"
|
||||||
|
}
|
||||||
|
return fmt.Errorf("%s", aec.Apply(errorSummary, aec.RedF))
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func build(services *stack.Services, queueDepth int, shrinkwrap bool) {
|
func build(services *stack.Services, queueDepth int, shrinkwrap, quietBuild bool) []error {
|
||||||
|
startOuter := time.Now()
|
||||||
|
|
||||||
|
errors := []error{}
|
||||||
|
|
||||||
wg := sync.WaitGroup{}
|
wg := sync.WaitGroup{}
|
||||||
|
|
||||||
workChannel := make(chan stack.Function)
|
workChannel := make(chan stack.Function)
|
||||||
@@ -188,23 +205,28 @@ func build(services *stack.Services, queueDepth int, shrinkwrap bool) {
|
|||||||
for i := 0; i < queueDepth; i++ {
|
for i := 0; i < queueDepth; i++ {
|
||||||
go func(index int) {
|
go func(index int) {
|
||||||
for function := range workChannel {
|
for function := range workChannel {
|
||||||
|
start := time.Now()
|
||||||
|
|
||||||
fmt.Printf(aec.YellowF.Apply("[%d] > Building %s.\n"), index, function.Name)
|
fmt.Printf(aec.YellowF.Apply("[%d] > Building %s.\n"), index, function.Name)
|
||||||
if len(function.Language) == 0 {
|
if len(function.Language) == 0 {
|
||||||
fmt.Println("Please provide a valid language for your function.")
|
fmt.Println("Please provide a valid language for your function.")
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
combinedBuildOptions := combineBuildOpts(function.BuildOptions, buildOptions)
|
combinedBuildOptions := combineBuildOpts(function.BuildOptions, buildOptions)
|
||||||
err := builder.BuildImage(function.Image, function.Handler, function.Name, function.Language, nocache, squash, shrinkwrap, buildArgMap, combinedBuildOptions, tagFormat, buildLabelMap)
|
err := builder.BuildImage(function.Image, function.Handler, function.Name, function.Language, nocache, squash, shrinkwrap, buildArgMap, combinedBuildOptions, tagFormat, buildLabelMap, quietBuild)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
errors = append(errors, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fmt.Printf(aec.YellowF.Apply("[%d] < Building %s done.\n"), index, function.Name)
|
|
||||||
|
duration := time.Since(start)
|
||||||
|
fmt.Printf(aec.YellowF.Apply("[%d] < Building %s done in %1.2fs.\n"), index, function.Name, duration.Seconds())
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf(aec.YellowF.Apply("[%d] worker done.\n"), index)
|
fmt.Printf(aec.YellowF.Apply("[%d] Worker done.\n"), index)
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}(i)
|
}(i)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for k, function := range services.Functions {
|
for k, function := range services.Functions {
|
||||||
@@ -220,6 +242,9 @@ func build(services *stack.Services, queueDepth int, shrinkwrap bool) {
|
|||||||
|
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
|
||||||
|
duration := time.Since(startOuter)
|
||||||
|
fmt.Printf("\n%s\n", aec.Apply(fmt.Sprintf("Total build time: %1.2f", duration.Seconds()), aec.YellowF))
|
||||||
|
return errors
|
||||||
}
|
}
|
||||||
|
|
||||||
// PullTemplates pulls templates from specified git remote. templateURL may be a pinned repository.
|
// PullTemplates pulls templates from specified git remote. templateURL may be a pinned repository.
|
||||||
|
|||||||
@@ -26,6 +26,21 @@ func Test_build(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_preRunBuild_ParallelOverZero(t *testing.T) {
|
||||||
|
buildCmd.ParseFlags([]string{"--parallel=0"})
|
||||||
|
got := buildCmd.PreRunE(buildCmd, nil)
|
||||||
|
|
||||||
|
if got == nil {
|
||||||
|
t.Error("Parallel should have errored about being over zero")
|
||||||
|
t.Fail()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
want := "the --parallel flag must be great than 0"
|
||||||
|
if got.Error() != want {
|
||||||
|
t.Errorf("parsing error, want %s, got %s", want, got.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func Test_parseBuildArgs_ValidParts(t *testing.T) {
|
func Test_parseBuildArgs_ValidParts(t *testing.T) {
|
||||||
mapped, err := parseBuildArgs([]string{"k=v"})
|
mapped, err := parseBuildArgs([]string{"k=v"})
|
||||||
|
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ func pushStack(services *stack.Services, queueDepth int, tagMode schema.BuildFor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf(aec.YellowF.Apply("[%d] worker done.\n"), index)
|
fmt.Printf(aec.YellowF.Apply("[%d] Worker done.\n"), index)
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}(i)
|
}(i)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ func Command(tempPath string, builder []string) {
|
|||||||
targetCmd.Dir = tempPath
|
targetCmd.Dir = tempPath
|
||||||
targetCmd.Stdout = os.Stdout
|
targetCmd.Stdout = os.Stdout
|
||||||
targetCmd.Stderr = os.Stderr
|
targetCmd.Stderr = os.Stderr
|
||||||
|
|
||||||
targetCmd.Start()
|
targetCmd.Start()
|
||||||
err := targetCmd.Wait()
|
err := targetCmd.Wait()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM alpine:3.9
|
FROM alpine:3.10
|
||||||
|
|
||||||
# Alternatively use ADD https:// (which will not be cached by Docker builder)
|
# Alternatively use ADD https:// (which will not be cached by Docker builder)
|
||||||
RUN apk --no-cache add curl ca-certificates imagemagick \
|
RUN apk --no-cache add curl ca-certificates imagemagick \
|
||||||
|
|||||||
1
vendor/github.com/alexellis/go-execute
generated
vendored
Submodule
1
vendor/github.com/alexellis/go-execute
generated
vendored
Submodule
Submodule vendor/github.com/alexellis/go-execute added at d17947259f
Reference in New Issue
Block a user