From fb32849896745acc6d08a823625750b86abbe95c Mon Sep 17 00:00:00 2001 From: nferraro Date: Fri, 11 Jan 2019 08:40:52 +0100 Subject: [PATCH] Fix #312: add publisher to release phase --- cmd/util/publisher/publisher.go | 113 ++++++++++++++++++++++++++++---- script/Makefile | 12 +++- script/publish_base_images.sh | 12 ++++ 3 files changed, 123 insertions(+), 14 deletions(-) create mode 100755 script/publish_base_images.sh diff --git a/cmd/util/publisher/publisher.go b/cmd/util/publisher/publisher.go index c52a76b847..857bbc0fb5 100644 --- a/cmd/util/publisher/publisher.go +++ b/cmd/util/publisher/publisher.go @@ -19,12 +19,15 @@ package main import ( "context" + "fmt" "io/ioutil" "os" "os/exec" "path" "path/filepath" + "sort" "strings" + "time" "github.com/apache/camel-k/deploy" "github.com/apache/camel-k/pkg/apis" @@ -32,11 +35,37 @@ import ( "github.com/apache/camel-k/pkg/builder" "github.com/apache/camel-k/pkg/util/camel" "github.com/apache/camel-k/pkg/util/kubernetes" + "github.com/pkg/errors" + "github.com/spf13/cobra" clientscheme "k8s.io/client-go/kubernetes/scheme" ) +// PublisherOptions -- +type PublisherOptions struct { + StartWith string + EndWith string + BuildAttempts int +} + // Publishes predefined images for all Camel components func main() { + + options := PublisherOptions{ + } + var cmd = cobra.Command{ + Use: "publisher", + Short: "Publisher allows to publish base images before a release", + Run: options.run, + } + + cmd.Flags().StringVar(&options.StartWith, "start-with", "", "The component to start with") + cmd.Flags().StringVar(&options.EndWith, "end-with", "", "The component to end with") + cmd.Flags().IntVar(&options.BuildAttempts, "attempts", 5, "The maximum number of build attempts") + + panicIfErr(cmd.Execute()) +} + +func (options *PublisherOptions) run(cmd *cobra.Command, args []string) { scheme := clientscheme.Scheme panicIfErr(apis.AddToScheme(scheme)) @@ -45,18 +74,58 @@ func main() { p := platRun.(*v1alpha1.IntegrationPlatform) - for _, a := range camel.Runtime.Artifacts { + started := options.StartWith == "" + + keys := make([]string, 0, len(camel.Runtime.Artifacts)) + for k := range camel.Runtime.Artifacts { + keys = append(keys, k) + } + sort.Strings(keys) + + for _, k := range keys { + a := camel.Runtime.Artifacts[k] if a.GroupID == "org.apache.camel" { component := strings.TrimPrefix(a.ArtifactID, "camel-") - build(component, p.Spec.Build.CamelVersion) + if options.StartWith == component { + started = true + } + + if started { + fmt.Printf("building component %s\n", component) + options.buildWithAttempts(component, p.Spec.Build.CamelVersion) + } else { + fmt.Printf("skipping component %s\n", component) + } + + if options.EndWith == component { + fmt.Println("reached final component") + break + } + } + } +} + +func (options *PublisherOptions) buildWithAttempts(component string, camelVersion string) { + var err error + for i := 0; i < options.BuildAttempts; i++ { + err = options.build(component, camelVersion) + if err != nil { + sleepTime := 5 * (i + 1) + fmt.Printf("waiting %d seconds to recover from error %v\n", sleepTime, err) + time.Sleep(time.Duration(sleepTime) * time.Second) + } else { + return } } + panicIfErr(errors.Wrap(err, "build failed after maximum number of attempts")) } -func build(component string, camelVersion string) { +func (options *PublisherOptions) build(component string, camelVersion string) error { dir, err := ioutil.TempDir(os.TempDir(), "camel-k-build-") - panicIfErr(err) - defer panicIfErr(os.RemoveAll(dir)) + if err != nil { + return err + } + defer os.RemoveAll(dir) ctx := builder.Context{ C: context.TODO(), @@ -77,26 +146,48 @@ func build(component string, camelVersion string) { }, } - panicIfErr(builder.GenerateProject(&ctx)) - panicIfErr(builder.ComputeDependencies(&ctx)) - panicIfErr(builder.StandardPackager(&ctx)) + err = builder.GenerateProject(&ctx) + if err != nil { + return err + } + err = builder.ComputeDependencies(&ctx) + if err != nil { + return err + } + err = builder.StandardPackager(&ctx) + if err != nil { + return err + } archiveDir, archiveName := filepath.Split(ctx.Archive) dockerfile := ` FROM fabric8/s2i-java:2.3 ADD ` + archiveName + ` /deployments/ ` - panicIfErr(ioutil.WriteFile(path.Join(archiveDir, "Dockerfile"), []byte(dockerfile), 0777)) + + err = ioutil.WriteFile(path.Join(archiveDir, "Dockerfile"), []byte(dockerfile), 0777) + if err != nil { + return err + } + image := builder.PredefinedImageNameFor(component) buildCmd := exec.Command("docker", "build", "-t", image, archiveDir) buildCmd.Stdout = os.Stdout buildCmd.Stderr = os.Stderr - panicIfErr(buildCmd.Run()) + err = buildCmd.Run() + if err != nil { + return err + } pushCmd := exec.Command("docker", "push", image) pushCmd.Stdout = os.Stdout pushCmd.Stderr = os.Stderr - panicIfErr(pushCmd.Run()) + err = pushCmd.Run() + if err != nil { + return err + } + + return nil } func panicIfErr(err error) { diff --git a/script/Makefile b/script/Makefile index a3815f7790..e53e306049 100644 --- a/script/Makefile +++ b/script/Makefile @@ -1,6 +1,6 @@ build: build-runtime build-operator build-kamel build-compile-integration-tests test -build-go: build-embed-resources build-operator build-kamel +build-go: build-embed-resources build-operator build-kamel build-publisher build-operator: build-embed-resources go build -o camel-k ./cmd/manager/*.go @@ -8,6 +8,9 @@ build-operator: build-embed-resources build-kamel: go build -o kamel ./cmd/kamel/*.go +build-publisher: + go build -o publisher ./cmd/util/publisher/*.go + build-embed-resources: ./script/embed_resources.sh deploy @@ -17,7 +20,7 @@ build-compile-integration-tests: build-runtime: ./mvnw clean install -f ./runtime/pom.xml -release: clean prepare-release build images-build images-push cross-compile package-examples git-tag +release: clean prepare-release build images-build images-push cross-compile package-examples git-tag publish-base-images prepare-release: ./script/prepare_release.sh @@ -36,6 +39,9 @@ package-examples: git-tag: ./script/git_tag.sh +publish-base-images: + ./script/publish_base_images.sh + dep: dep ensure -v @@ -76,4 +82,4 @@ check-integration: lint: golangci-lint run -.PHONY: build build-operator build-kamel build-embed-resources build-runtime dep codegen images images-build images-push test check test-integration check-integration clean release prepare-release cross-compile package-examples new-version git-tag increment-snapshot install-minishift +.PHONY: build build-operator build-kamel build-embed-resources build-runtime dep codegen images images-build images-push test check test-integration check-integration clean release prepare-release cross-compile package-examples new-version git-tag publish-base-images increment-snapshot install-minishift diff --git a/script/publish_base_images.sh b/script/publish_base_images.sh new file mode 100755 index 0000000000..4915dee6c9 --- /dev/null +++ b/script/publish_base_images.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +set -e + +location=$(dirname $0) +rootdir=$(realpath $location/../) + +echo "Start publishing base images" + +$rootdir/publisher + +echo "All base images have been published"