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 }