1// Copyright (c) Microsoft Corporation. All rights reserved. 2// Licensed under the MIT License. See License.txt in the project root for license information. 3 4package common 5 6import ( 7 "fmt" 8 "log" 9 "os" 10 "path/filepath" 11 "strings" 12 13 "github.com/Azure/azure-sdk-for-go/tools/generator/autorest" 14 "github.com/Azure/azure-sdk-for-go/tools/generator/autorest/model" 15 "github.com/Azure/azure-sdk-for-go/tools/generator/cmd/template" 16 "github.com/Azure/azure-sdk-for-go/tools/generator/common" 17 "github.com/Azure/azure-sdk-for-go/tools/internal/exports" 18 "github.com/Masterminds/semver" 19) 20 21type GenerateContext struct { 22 SdkPath string 23 SpecPath string 24 CommitHash string 25} 26 27type GenerateResult struct { 28 Version string 29 RpName string 30 PackageName string 31 PackageAbsPath string 32 Changelog model.Changelog 33 ChangelogMd string 34} 35 36func (ctx GenerateContext) SDKRoot() string { 37 return ctx.SdkPath 38} 39 40func (ctx GenerateContext) SpecRoot() string { 41 return ctx.SpecPath 42} 43 44func (ctx GenerateContext) GenerateForAutomation(readme string, repo string) ([]GenerateResult, []error) { 45 absReadme := filepath.Join(ctx.SpecPath, readme) 46 absReadmeGo := filepath.Join(filepath.Dir(absReadme), "readme.go.md") 47 48 var result []GenerateResult 49 var errors []error 50 51 log.Printf("Get all namespaces from readme file") 52 rpMap, err := ReadV2ModuleNameToGetNamespace(absReadmeGo) 53 if err != nil { 54 return nil, []error{ 55 fmt.Errorf("cannot get rp and namespaces from readme '%s': %+v", readme, err), 56 } 57 } 58 59 for rpName, namespaceNames := range rpMap { 60 for _, namespaceName := range namespaceNames { 61 log.Printf("Process rp: %s, namespace: %s", rpName, namespaceName) 62 singleResult, err := ctx.GenerateForSingleRpNamespace(rpName, namespaceName, "", "", repo) 63 if err != nil { 64 errors = append(errors, err) 65 continue 66 } 67 result = append(result, *singleResult) 68 } 69 } 70 return result, errors 71} 72 73func (ctx GenerateContext) GenerateForSingleRpNamespace(rpName, namespaceName, specficPackageTitle, specficVersion, specficRepoURL string) (*GenerateResult, error) { 74 packagePath := filepath.Join(ctx.SdkPath, "sdk", rpName, namespaceName) 75 changelogPath := filepath.Join(packagePath, common.ChangelogFilename) 76 if _, err := os.Stat(changelogPath); os.IsNotExist(err) { 77 log.Printf("Package '%s' changelog not exist, do onboard process", packagePath) 78 79 if specficPackageTitle == "" { 80 specficPackageTitle = strings.Title(rpName) 81 } 82 83 log.Printf("Use template to generate new rp folder and basic package files...") 84 if err = template.GeneratePackageByTemplate(rpName, namespaceName, template.Flags{ 85 SDKRoot: ctx.SdkPath, 86 TemplatePath: "tools/generator/template/rpName/packageName", 87 PackageTitle: specficPackageTitle, 88 Commit: ctx.CommitHash, 89 }); err != nil { 90 return nil, err 91 } 92 93 if specficRepoURL != "" { 94 log.Printf("Change the repo url in `autorest.md`...") 95 autorestMdPath := filepath.Join(packagePath, "autorest.md") 96 if err = ReplaceRepoURL(autorestMdPath, specficRepoURL); err != nil { 97 return nil, err 98 } 99 } 100 101 log.Printf("Run `go generate` to regenerate the code...") 102 if err = ExecuteGoGenerate(packagePath); err != nil { 103 return nil, err 104 } 105 106 log.Printf("Generate changelog for package...") 107 newExports, err := exports.Get(packagePath) 108 if err != nil { 109 return nil, err 110 } 111 changelog, err := autorest.GetChangelogForPackage(nil, &newExports) 112 if err != nil { 113 return nil, err 114 } 115 116 log.Printf("Replace {{NewClientMethod}} placeholder in the README.md ") 117 if err = ReplaceNewClientMethodPlaceholder(packagePath, newExports); err != nil { 118 return nil, err 119 } 120 121 return &GenerateResult{ 122 Version: "0.1.0", 123 RpName: rpName, 124 PackageName: namespaceName, 125 PackageAbsPath: packagePath, 126 Changelog: *changelog, 127 ChangelogMd: changelog.ToCompactMarkdown(), 128 }, nil 129 } else { 130 log.Printf("Package '%s' existed, do update process", packagePath) 131 132 log.Printf("Get ori exports for changelog generation...") 133 oriExports, err := exports.Get(packagePath) 134 if err != nil { 135 return nil, err 136 } 137 138 log.Printf("Remove all the files that start with `zz_generated_`...") 139 if err = CleanSDKGeneratedFiles(packagePath); err != nil { 140 return nil, err 141 } 142 143 log.Printf("Change the commit hash in `autorest.md` to a new commit that corresponds to the new release...") 144 autorestMdPath := filepath.Join(packagePath, "autorest.md") 145 if err = ReplaceCommitID(autorestMdPath, ctx.CommitHash); err != nil { 146 return nil, err 147 } 148 149 if specficRepoURL != "" { 150 log.Printf("Change the repo url in `autorest.md`...") 151 if err = ReplaceRepoURL(autorestMdPath, specficRepoURL); err != nil { 152 return nil, err 153 } 154 } 155 156 log.Printf("Run `go generate` to regenerate the code...") 157 if err = ExecuteGoGenerate(packagePath); err != nil { 158 return nil, err 159 } 160 161 log.Printf("Generate changelog for package...") 162 newExports, err := exports.Get(packagePath) 163 if err != nil { 164 return nil, err 165 } 166 changelog, err := autorest.GetChangelogForPackage(&oriExports, &newExports) 167 if err != nil { 168 return nil, err 169 } 170 171 log.Printf("Calculate new version...") 172 var version *semver.Version 173 if specficVersion == "" { 174 version, err = CalculateNewVersion(changelog, packagePath) 175 if err != nil { 176 return nil, err 177 } 178 } else { 179 log.Printf("Use specfic version: %s", specficVersion) 180 version, err = semver.NewVersion(specficVersion) 181 if err != nil { 182 return nil, err 183 } 184 } 185 186 log.Printf("Add changelog to file...") 187 changelogMd, err := AddChangelogToFile(changelog, version, packagePath) 188 if err != nil { 189 return nil, err 190 } 191 192 log.Printf("Remove all the files that start with `zz_generated_`...") 193 if err = CleanSDKGeneratedFiles(packagePath); err != nil { 194 return nil, err 195 } 196 197 log.Printf("Replace version in autorest.md...") 198 if err = ReplaceVersion(packagePath, version.String()); err != nil { 199 return nil, err 200 } 201 202 log.Printf("Run `go generate` to regenerate the code for new version...") 203 if err = ExecuteGoGenerate(packagePath); err != nil { 204 return nil, err 205 } 206 207 return &GenerateResult{ 208 Version: version.String(), 209 RpName: rpName, 210 PackageName: namespaceName, 211 PackageAbsPath: packagePath, 212 Changelog: *changelog, 213 ChangelogMd: changelogMd, 214 }, nil 215 } 216} 217