github.com/jonsyu1/godel@v0.0.0-20171017211503-64567a0cf169/apps/distgo/params/product.go (about)

     1  // Copyright 2016 Palantir Technologies, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package params
    16  
    17  import (
    18  	"sort"
    19  	"strings"
    20  
    21  	"github.com/pkg/errors"
    22  
    23  	"github.com/palantir/godel/apps/distgo/pkg/git"
    24  	"github.com/palantir/godel/apps/distgo/pkg/osarch"
    25  )
    26  
    27  // ProductBuildSpec defines all of the parameters for building a specific product.
    28  type ProductBuildSpec struct {
    29  	Product
    30  	ProjectDir     string
    31  	ProductName    string
    32  	ProductVersion string
    33  	VersionInfo    git.ProjectInfo
    34  }
    35  
    36  type ProductBuildSpecWithDeps struct {
    37  	Spec ProductBuildSpec
    38  	Deps map[string]ProductBuildSpec
    39  }
    40  
    41  func (p *ProductBuildSpecWithDeps) AllSpecs() []ProductBuildSpec {
    42  	allSpecs := make([]ProductBuildSpec, 0, len(p.Deps)+1)
    43  	allSpecs = append(allSpecs, p.Spec)
    44  	for _, spec := range p.Deps {
    45  		allSpecs = append(allSpecs, spec)
    46  	}
    47  	return allSpecs
    48  }
    49  
    50  const (
    51  	defaultBuildOutputDir = "build"
    52  	defaultDistOutputDir  = "dist"
    53  )
    54  
    55  func NewProductBuildSpecWithDeps(spec ProductBuildSpec, allSpecs map[string]ProductBuildSpec) (ProductBuildSpecWithDeps, error) {
    56  	deps := make(map[string]ProductBuildSpec)
    57  	for _, currDistCfg := range spec.Dist {
    58  		for _, currDepProduct := range currDistCfg.InputProducts {
    59  			currSpec, ok := allSpecs[currDepProduct]
    60  			if !ok {
    61  				allProducts := make([]string, 0, len(allSpecs))
    62  				for currName := range allSpecs {
    63  					allProducts = append(allProducts, currName)
    64  				}
    65  				sort.Strings(allProducts)
    66  				return ProductBuildSpecWithDeps{}, errors.Errorf("Spec %v declared %v as a dependent product, but could not find configuration for that product in %v", spec.ProductName, currDepProduct, allProducts)
    67  			}
    68  			deps[currDepProduct] = currSpec
    69  		}
    70  	}
    71  
    72  	return ProductBuildSpecWithDeps{
    73  		Spec: spec,
    74  		Deps: deps,
    75  	}, nil
    76  }
    77  
    78  // NewProductBuildSpec returns a fully initialized ProductBuildSpec that is a combination of the provided parameters.
    79  // If any of the required fields in the provided configuration is blank, the returned ProjectBuildSpec will have default
    80  // values populated in the returned object.
    81  func NewProductBuildSpec(projectDir, productName string, gitProductInfo git.ProjectInfo, productCfg Product, projectCfg Project) ProductBuildSpec {
    82  	buildSpec := ProductBuildSpec{
    83  		Product:        productCfg,
    84  		ProjectDir:     projectDir,
    85  		ProductName:    productName,
    86  		ProductVersion: gitProductInfo.Version,
    87  		VersionInfo:    gitProductInfo,
    88  	}
    89  
    90  	if buildSpec.Build.OutputDir == "" {
    91  		buildSpec.Build.OutputDir = firstNonEmpty(projectCfg.BuildOutputDir, defaultBuildOutputDir)
    92  	}
    93  
    94  	if len(buildSpec.Build.OSArchs) == 0 {
    95  		buildSpec.Build.OSArchs = []osarch.OSArch{osarch.Current()}
    96  	}
    97  
    98  	if len(buildSpec.Dist) == 0 {
    99  		// One dist with all default values.
   100  		buildSpec.Dist = []Dist{{}}
   101  	}
   102  	for i := range buildSpec.Dist {
   103  		currDistCfg := &buildSpec.Dist[i]
   104  
   105  		if currDistCfg.OutputDir == "" {
   106  			currDistCfg.OutputDir = firstNonEmpty(projectCfg.DistOutputDir, defaultDistOutputDir)
   107  		}
   108  
   109  		if currDistCfg.Info == nil || currDistCfg.Info.Type() == "" {
   110  			currDistCfg.Info = &OSArchsBinDistInfo{}
   111  		}
   112  
   113  		if currDistCfg.Publish.empty() {
   114  			currDistCfg.Publish = buildSpec.Publish
   115  		}
   116  
   117  		if currDistCfg.Publish.GroupID == "" {
   118  			currDistCfg.Publish.GroupID = projectCfg.GroupID
   119  		}
   120  
   121  		// if distribution is SLSv2, ensure that SLSv2 tag exists for Almanac
   122  		if currDistCfg.Info.Type() == SLSDistType {
   123  			slsv2TagExists := false
   124  			for _, currTag := range currDistCfg.Publish.Almanac.Tags {
   125  				if currTag == "slsv2" {
   126  					slsv2TagExists = true
   127  					break
   128  				}
   129  			}
   130  			if !slsv2TagExists {
   131  				currDistCfg.Publish.Almanac.Tags = append(currDistCfg.Publish.Almanac.Tags, "slsv2")
   132  			}
   133  		}
   134  
   135  		if osArchBinDistInfo, ok := currDistCfg.Info.(*OSArchsBinDistInfo); ok {
   136  			if len(osArchBinDistInfo.OSArchs) == 0 {
   137  				osArchBinDistInfo.OSArchs = buildSpec.Build.OSArchs
   138  			}
   139  		}
   140  
   141  		if projectCfg.DistScriptInclude != "" && currDistCfg.Script != "" {
   142  			currDistCfg.Script = strings.Join([]string{projectCfg.DistScriptInclude, currDistCfg.Script}, "\n")
   143  		}
   144  	}
   145  
   146  	for i := range buildSpec.DockerImages {
   147  		if buildSpec.DockerImages[i].Repository == "" {
   148  			buildSpec.DockerImages[i].Repository = productName
   149  		}
   150  		if buildSpec.DockerImages[i].Tag == "" {
   151  			buildSpec.DockerImages[i].Tag = gitProductInfo.Version
   152  		}
   153  	}
   154  
   155  	return buildSpec
   156  }
   157  
   158  func firstNonEmpty(first, second string) string {
   159  	if first != "" {
   160  		return first
   161  	}
   162  	return second
   163  }