eng/tools/generator/cmd/v2/common/generation.go (751 lines of code) (raw):

// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. package common import ( "fmt" "log" "os" "path/filepath" "strings" "github.com/Azure/azure-sdk-for-go/eng/tools/generator/cmd/template" "github.com/Azure/azure-sdk-for-go/eng/tools/generator/repo" "github.com/Azure/azure-sdk-for-go/eng/tools/generator/typespec" "github.com/Azure/azure-sdk-for-go/eng/tools/internal/exports" "github.com/Masterminds/semver" ) type GenerateContext struct { SDKPath string SDKRepo *repo.SDKRepository SpecPath string SpecCommitHash string SpecReadmeFile string SpecReadmeGoFile string SpecRepoURL string UpdateSpecVersion bool // typespec TypeSpecConfig *typespec.TypeSpecConfig } type GenerateResult struct { Version string RPName string PackageName string PackageAbsPath string Changelog Changelog ChangelogMD string PullRequestLabels string PackageRelativePath string } type GenerateParam struct { RPName string NamespaceName string NamespaceConfig string SpecificVersion string SpecificPackageTitle string SpecRPName string ReleaseDate string SkipGenerateExample bool GoVersion string RemoveTagSet bool ForceStableVersion bool TypeSpecEmitOption string TspClientOptions []string ReleasedTags []string } type Generator interface { PreGenerate(generateParam *GenerateParam) error Generate(generateParam *GenerateParam) error PreChangeLog(generateParam *GenerateParam) (*exports.Content, error) GenChangeLog(oriExports *exports.Content, newExports *exports.Content) (*Changelog, error) AfterGenerate(generateParam *GenerateParam, changelog *Changelog, newExports exports.Content) (*GenerateResult, error) } // Common steps for onboard and normal service type SwaggerCommonGenerator struct { Version *semver.Version PackagePath string *GenerateContext } type SwaggerOnBoardGenerator struct { *SwaggerCommonGenerator } type SwaggerUpdateGenerator struct { *SwaggerCommonGenerator PreviousVersion string IsCurrentPreview bool } type TypeSpecCommonGenerator struct { PackageRelativePath string ModuleRelativePath string PackagePath string ModulePath string Version *semver.Version IsSubPackage bool *GenerateContext } type TypeSpecOnBoardGenerator struct { *TypeSpecCommonGenerator } type TypeSpecUpdateGeneraor struct { *TypeSpecCommonGenerator PreviousVersion string IsCurrentPreview bool } func (ctx *GenerateContext) GenerateForAutomation(readme, repo, goVersion string) ([]GenerateResult, []error) { absReadme, err := filepath.Abs(filepath.Join(ctx.SpecPath, readme)) if err != nil { return nil, []error{ fmt.Errorf("cannot get absolute path for spec path '%s': %+v", ctx.SpecPath, err), } } absReadmeGo := filepath.Join(filepath.Dir(absReadme), "readme.go.md") ctx.SpecReadmeFile = absReadme ctx.SpecReadmeGoFile = absReadmeGo specRPName := strings.Split(readme, "/")[0] var result []GenerateResult var errors []error log.Printf("Get all namespaces from readme file") rpMap, err := ReadV2ModuleNameToGetNamespace(absReadmeGo) if err != nil { return nil, []error{ fmt.Errorf("cannot get rp and namespaces from readme '%s': %+v", readme, err), } } for rpName, packageInfos := range rpMap { for _, packageInfo := range packageInfos { log.Printf("Start to process rp: %s, namespace: %s", rpName, packageInfo.Name) singleResult, err := ctx.GenerateForSingleRPNamespace(&GenerateParam{ RPName: rpName, NamespaceName: packageInfo.Name, SpecRPName: specRPName, SkipGenerateExample: true, NamespaceConfig: packageInfo.Config, GoVersion: goVersion, RemoveTagSet: true, }) if err != nil { errors = append(errors, fmt.Errorf("failed to generate for rp: %s, namespace: %s: %+v", rpName, packageInfo.Name, err)) continue } result = append(result, *singleResult) } } return result, errors } func (ctx *GenerateContext) GenerateForSingleRPNamespace(generateParam *GenerateParam) (*GenerateResult, error) { packagePath := filepath.Join(ctx.SDKPath, "sdk", "resourcemanager", generateParam.RPName, generateParam.NamespaceName) changelogPath := filepath.Join(packagePath, ChangelogFileName) version, err := semver.NewVersion("0.1.0") if err != nil { return nil, err } if generateParam.SpecificVersion != "" { log.Printf("Use specific version: %s", generateParam.SpecificVersion) version, err = semver.NewVersion(generateParam.SpecificVersion) if err != nil { return nil, err } } // check if the package is onboard or update, to init different generator var generator Generator commonGenerator := &SwaggerCommonGenerator{GenerateContext: ctx, PackagePath: packagePath, Version: version} if _, err := os.Stat(changelogPath); os.IsNotExist(err) { generator = &SwaggerOnBoardGenerator{SwaggerCommonGenerator: commonGenerator} } else { tags, err := GetAllVersionTags(fmt.Sprintf("sdk/resourcemanager/%s/%s", generateParam.RPName, generateParam.NamespaceName)) if err != nil { return nil, err } if len(tags) == 0 { generator = &SwaggerOnBoardGenerator{SwaggerCommonGenerator: commonGenerator} } else { generateParam.ReleasedTags = tags generator = &SwaggerUpdateGenerator{SwaggerCommonGenerator: commonGenerator} } } err = generator.PreGenerate(generateParam) if err != nil { return nil, err } err = generator.Generate(generateParam) if err != nil { return nil, err } oriExports, err := generator.PreChangeLog(generateParam) if err != nil { return nil, err } log.Printf("Start to generate changelog for package...") newExports, err := exports.Get(packagePath) if err != nil { return nil, err } changelog, err := generator.GenChangeLog(oriExports, &newExports) if err != nil { return nil, err } return generator.AfterGenerate(generateParam, changelog, newExports) } func (t *SwaggerCommonGenerator) PreGenerate(generateParam *GenerateParam) error { packagePath := t.PackagePath // same step for onboard and update if t.SpecCommitHash == "" { log.Printf("Change swagger config in `autorest.md` according to local path...") autorestMdPath := filepath.Join(packagePath, "autorest.md") if err := ChangeConfigWithLocalPath(autorestMdPath, t.SpecReadmeFile, t.SpecReadmeGoFile); err != nil { return err } } else { log.Printf("Change swagger config in `autorest.md` according to repo URL and commit ID...") autorestMdPath := filepath.Join(packagePath, "autorest.md") if t.UpdateSpecVersion { if err := ChangeConfigWithCommitID(autorestMdPath, t.SpecRepoURL, t.SpecCommitHash, generateParam.SpecRPName); err != nil { return err } } } // remove tag set if generateParam.RemoveTagSet { log.Printf("Remove tag set for swagger config in `autorest.md`...") autorestMdPath := filepath.Join(packagePath, "autorest.md") if err := RemoveTagSet(autorestMdPath); err != nil { return err } } return nil } func (t *SwaggerCommonGenerator) Generate(generateParam *GenerateParam) error { packagePath := t.PackagePath log.Printf("Start to run `go generate` to regenerate the code...") if err := ExecuteGoGenerate(packagePath); err != nil { return err } return nil } func (t *SwaggerCommonGenerator) PreChangeLog(generateParam *GenerateParam) (*exports.Content, error) { return nil, nil } func (t *SwaggerCommonGenerator) GenChangeLog(oriExports *exports.Content, newExports *exports.Content) (*Changelog, error) { changelog, err := GetChangelogForPackage(oriExports, newExports) if err != nil { return nil, err } log.Printf("filter changelog...") FilterChangelog(changelog, NonExportedFilter, MarshalUnmarshalFilter, EnumFilter, FuncFilter, LROFilter, PageableFilter, InterfaceToAnyFilter) return changelog, nil } func (t *SwaggerCommonGenerator) AfterGenerate(generateParam *GenerateParam, changelog *Changelog, newExports exports.Content) (*GenerateResult, error) { packagePath := t.PackagePath // Example generation should be the last step because the package import relay on the new calculated version if !generateParam.SkipGenerateExample { log.Printf("Start to generate examples...") var flags []string alwaysSetBodyParamRequiredFlag, err := GetAlwaysSetBodyParamRequiredFlag(filepath.Join(packagePath, "build.go")) if err != nil { return nil, err } if len(alwaysSetBodyParamRequiredFlag) > 0 { flags = append(flags, alwaysSetBodyParamRequiredFlag) } clientFactoryParamsFlag, err := GetFactoryGatherAllParamsFlag(filepath.Join(packagePath, "build.go")) if err != nil { return nil, err } if len(clientFactoryParamsFlag) > 0 { flags = append(flags, clientFactoryParamsFlag) } log.Println(flags) if err := ExecuteExampleGenerate(packagePath, filepath.Join("resourcemanager", generateParam.RPName, generateParam.NamespaceName), flags); err != nil { return nil, err } } return nil, nil } func (t *SwaggerOnBoardGenerator) PreGenerate(generateParam *GenerateParam) error { var err error version := t.Version packagePath := t.PackagePath log.Printf("Package '%s' changelog not exist, do onboard process", packagePath) if generateParam.SpecificPackageTitle == "" { generateParam.SpecificPackageTitle = strings.Title(generateParam.RPName) } log.Printf("Start to use template to generate new rp folder and basic package files...") if err = template.GeneratePackageByTemplate(generateParam.RPName, generateParam.NamespaceName, template.Flags{ SDKRoot: t.SDKPath, TemplatePath: "eng/tools/generator/template/rpName/packageName", PackageTitle: generateParam.SpecificPackageTitle, Commit: t.SpecCommitHash, PackageConfig: generateParam.NamespaceConfig, GoVersion: generateParam.GoVersion, PackageVersion: version.String(), ReleaseDate: generateParam.ReleaseDate, }); err != nil { return err } if err = t.SwaggerCommonGenerator.PreGenerate(generateParam); err != nil { return err } return nil } func (t *SwaggerOnBoardGenerator) AfterGenerate(generateParam *GenerateParam, changelog *Changelog, newExports exports.Content) (*GenerateResult, error) { var err error var prl PullRequestLabel version := t.Version packagePath := t.PackagePath log.Printf("Replace {{NewClientName}} placeholder in the README.md ") if err = ReplaceNewClientNamePlaceholder(packagePath, newExports); err != nil { return nil, err } if _, err := t.SwaggerCommonGenerator.AfterGenerate(generateParam, changelog, newExports); err != nil { return nil, err } // issue: https://github.com/Azure/azure-sdk-for-go/issues/23877 prl = FirstBetaLabel return &GenerateResult{ Version: version.String(), RPName: generateParam.RPName, PackageName: generateParam.NamespaceName, PackageAbsPath: packagePath, Changelog: *changelog, ChangelogMD: changelog.ToCompactMarkdown() + "\n" + changelog.GetChangeSummary(), PullRequestLabels: string(prl), }, nil } func (t *SwaggerUpdateGenerator) PreGenerate(generateParam *GenerateParam) error { packagePath := t.PackagePath var err error log.Printf("Package '%s' existed, do update process", packagePath) log.Printf("Remove all the generated files ...") if err = CleanSDKGeneratedFiles(packagePath); err != nil { return err } if err = t.SwaggerCommonGenerator.PreGenerate(generateParam); err != nil { return err } // add tag set if !generateParam.RemoveTagSet && generateParam.NamespaceConfig != "" { log.Printf("Add tag in `autorest.md`...") autorestMdPath := filepath.Join(packagePath, "autorest.md") if err := AddTagSet(autorestMdPath, generateParam.NamespaceConfig); err != nil { return err } } return nil } func (t *SwaggerUpdateGenerator) PreChangeLog(generateParam *GenerateParam) (*exports.Content, error) { var err error packagePath := t.PackagePath previousVersion := "" isCurrentPreview := false var oriExports *exports.Content isCurrentPreview, err = ContainsPreviewAPIVersion(packagePath) if err != nil { return nil, err } if isCurrentPreview && generateParam.ForceStableVersion { tag, err := GetTag(filepath.Join(packagePath, "autorest.md")) if err != nil { return nil, err } if tag != "" { if !strings.Contains(tag, "preview") { isCurrentPreview = false } } } log.Printf("Get ori exports for changelog generation...") tags := generateParam.ReleasedTags previousVersionTag := GetPreviousVersionTag(isCurrentPreview, tags) oriExports, err = GetExportsFromTag(*t.SDKRepo, packagePath, previousVersionTag) if err != nil && !strings.Contains(err.Error(), "doesn't contain any exports") { return nil, err } tagSplit := strings.Split(previousVersionTag, "/") previousVersion = strings.TrimLeft(tagSplit[len(tagSplit)-1], "v") t.PreviousVersion = previousVersion t.IsCurrentPreview = isCurrentPreview return oriExports, nil } func (t *SwaggerUpdateGenerator) AfterGenerate(generateParam *GenerateParam, changelog *Changelog, newExports exports.Content) (*GenerateResult, error) { var prl PullRequestLabel var err error version := t.Version isCurrentPreview := t.IsCurrentPreview previousVersion := t.PreviousVersion packagePath := t.PackagePath log.Printf("Calculate new version...") if generateParam.SpecificVersion == "" { version, prl, err = CalculateNewVersion(changelog, previousVersion, isCurrentPreview) if err != nil { return nil, err } } log.Printf("Add changelog to file...") changelogMd, err := AddChangelogToFile(changelog, version, packagePath, generateParam.ReleaseDate) if err != nil { return nil, err } log.Printf("Update module definition if v2+...") err = UpdateModuleDefinition(packagePath, fmt.Sprintf("sdk/resourcemanager/%s/%s", generateParam.RPName, generateParam.NamespaceName), version) if err != nil { return nil, err } oldModuleVersion, err := getModuleVersion(filepath.Join(packagePath, "autorest.md")) if err != nil { return nil, err } log.Printf("Replace version in autorest.md and constants...") if err = ReplaceVersion(packagePath, version.String()); err != nil { return nil, err } if _, err := os.Stat(filepath.Join(packagePath, "fake")); !os.IsNotExist(err) && oldModuleVersion.Major() != version.Major() { log.Printf("Replace fake module v2+...") if err = replaceModuleImport(packagePath, generateParam.RPName, generateParam.NamespaceName, oldModuleVersion.String(), version.String(), "fake", ".go"); err != nil { return nil, err } } // When sdk has major version bump, the live test needs to update the module referenced in the code. if oldModuleVersion.Major() != version.Major() && existSuffixFile(packagePath, "_live_test.go") { log.Printf("Replace live test module v2+...") if err = replaceModuleImport(packagePath, generateParam.RPName, generateParam.NamespaceName, oldModuleVersion.String(), version.String(), "", "_live_test.go"); err != nil { return nil, err } } log.Printf("Replace README.md module...") if err = replaceReadmeModule(packagePath, fmt.Sprintf("sdk/resourcemanager/%s/%s", generateParam.RPName, generateParam.NamespaceName), version.String()); err != nil { return nil, err } log.Printf("Replace README.md NewClient name...") if err = ReplaceReadmeNewClientName(packagePath, newExports); err != nil { return nil, err } if _, err := t.SwaggerCommonGenerator.AfterGenerate(generateParam, changelog, newExports); err != nil { return nil, err } return &GenerateResult{ Version: version.String(), RPName: generateParam.RPName, PackageName: generateParam.NamespaceName, PackageAbsPath: packagePath, Changelog: *changelog, ChangelogMD: changelogMd + "\n" + changelog.GetChangeSummary(), PullRequestLabels: string(prl), }, nil } func (ctx *GenerateContext) GenerateForTypeSpec(generateParam *GenerateParam) (*GenerateResult, error) { isSubPackage := false packageRelativePath := ctx.TypeSpecConfig.GetPackageRelativePath() if packageRelativePath == "" { return nil, fmt.Errorf("package module relative path not found in %s", ctx.TypeSpecConfig.Path) } moduleRelativePath := ctx.TypeSpecConfig.GetModuleRelativePath() // if module relative path is not provided, find it from the sdk path by go.mod if moduleRelativePath == "" { isSubPackage = true val, err := FindModuleDirByGoMod(filepath.Join(ctx.SDKPath, packageRelativePath)) if err != nil { return nil, err } moduleRelativePath, err = filepath.Rel(ctx.SDKPath, val) if err != nil { return nil, err } moduleRelativePath = filepath.ToSlash(moduleRelativePath) } if !strings.HasPrefix(packageRelativePath, moduleRelativePath) { return nil, fmt.Errorf("module relative path '%s' is not a prefix of package relative path '%s', please check your tspconfig.yaml file", moduleRelativePath, packageRelativePath) } if packageRelativePath != moduleRelativePath { isSubPackage = true } // if rp name and namespace name are not provided, extract them from the module path if len(generateParam.RPName) == 0 && len(generateParam.NamespaceName) == 0 { rpAndNamespaceName, err := ctx.TypeSpecConfig.GetRpAndPackageNameByModule(moduleRelativePath) if err != nil { return nil, err } generateParam.RPName = rpAndNamespaceName[0] generateParam.NamespaceName = rpAndNamespaceName[1] } packagePath := filepath.Join(ctx.SDKPath, packageRelativePath) modulePath := filepath.Join(ctx.SDKPath, moduleRelativePath) changelogPath := filepath.Join(modulePath, ChangelogFileName) version, err := semver.NewVersion("0.1.0") if err != nil { return nil, err } if generateParam.SpecificVersion != "" { log.Printf("Use specific version: %s", generateParam.SpecificVersion) version, err = semver.NewVersion(generateParam.SpecificVersion) if err != nil { return nil, err } } // check if the package is onboard or update, to init different generator var generator Generator commonGenerator := &TypeSpecCommonGenerator{ GenerateContext: ctx, PackagePath: packagePath, ModulePath: modulePath, PackageRelativePath: packageRelativePath, ModuleRelativePath: moduleRelativePath, Version: version, IsSubPackage: isSubPackage, } if _, err := os.Stat(changelogPath); os.IsNotExist(err) { generator = &TypeSpecOnBoardGenerator{TypeSpecCommonGenerator: commonGenerator} } else { tags, err := GetAllVersionTags(moduleRelativePath) if err != nil { return nil, err } if len(tags) == 0 { generator = &TypeSpecOnBoardGenerator{TypeSpecCommonGenerator: commonGenerator} } else { generateParam.ReleasedTags = tags generator = &TypeSpecUpdateGeneraor{TypeSpecCommonGenerator: commonGenerator} } } err = generator.PreGenerate(generateParam) if err != nil { return nil, err } err = generator.Generate(generateParam) if err != nil { return nil, err } oriExports, err := generator.PreChangeLog(generateParam) if err != nil { return nil, err } log.Printf("Start to generate changelog for package...") newExports, err := exports.Get(packagePath) if err != nil { return nil, err } changelog, err := generator.GenChangeLog(oriExports, &newExports) if err != nil { return nil, err } return generator.AfterGenerate(generateParam, changelog, newExports) } func (t *TypeSpecCommonGenerator) PreGenerate(generateParam *GenerateParam) error { return nil } func (t *TypeSpecCommonGenerator) Generate(generateParam *GenerateParam) error { version := t.Version ctx := t.GenerateContext log.Printf("Start to run `tsp-client init` to generate the code...") defaultModuleVersion := version.String() emitOption := "" if !t.IsSubPackage { emitOption = fmt.Sprintf("module-version=%s", defaultModuleVersion) } if generateParam.TypeSpecEmitOption != "" { emitOption = fmt.Sprintf("%s;%s", emitOption, generateParam.TypeSpecEmitOption) } err := ExecuteTypeSpecGenerate(ctx, emitOption, generateParam.TspClientOptions) if err != nil { return err } return nil } func (t *TypeSpecCommonGenerator) PreChangeLog(generateParam *GenerateParam) (*exports.Content, error) { return nil, nil } func (t *TypeSpecCommonGenerator) GenChangeLog(oriExports *exports.Content, newExports *exports.Content) (*Changelog, error) { changelog, err := GetChangelogForPackage(oriExports, newExports) if err != nil && !strings.Contains(err.Error(), "doesn't contain any exports") { return nil, err } log.Printf("filter changelog...") FilterChangelog(changelog, NonExportedFilter, MarshalUnmarshalFilter, EnumFilter, FuncFilter, LROFilter, PageableFilter, InterfaceToAnyFilter) return changelog, nil } func (t *TypeSpecCommonGenerator) AfterGenerate(generateParam *GenerateParam, changelog *Changelog, newExports exports.Content) (*GenerateResult, error) { packagePath := t.PackagePath modulePath := t.ModulePath if t.IsSubPackage { // remove go.mod for sub package goModPath := filepath.Join(packagePath, GoModFileName) if _, err := os.Stat(goModPath); !os.IsNotExist(err) { if err = os.Remove(goModPath); err != nil { return nil, err } } } log.Printf("##[command]Executing gofmt -s -w . in %s\n", modulePath) if err := ExecuteGoFmt(modulePath, "-s", "-w", "."); err != nil { return nil, err } log.Printf("##[command]Executing go mod tidy in %s\n", modulePath) if err := ExecuteGo(modulePath, "mod", "tidy"); err != nil { return nil, err } return nil, nil } func (t *TypeSpecOnBoardGenerator) PreGenerate(generateParam *GenerateParam) error { version := t.Version modulePath := t.ModulePath moduleRelativePath := t.ModuleRelativePath log.Printf("Module '%s' changelog not exist, do onboard process", modulePath) if generateParam.SpecificPackageTitle == "" { generateParam.SpecificPackageTitle = strings.Title(generateParam.RPName) } log.Printf("Start to use template to generate new rp folder and basic package files...") sdkBasicInfo := map[string]any{ "rpName": generateParam.RPName, "packageName": generateParam.NamespaceName, "moduleRelativePath": moduleRelativePath, "serviceDir": strings.Replace(moduleRelativePath, "sdk/", "", 1), "packageTitle": generateParam.SpecificPackageTitle, "packageVersion": version.String(), "releaseDate": generateParam.ReleaseDate, "goVersion": generateParam.GoVersion, } return typespec.ParseTypeSpecTemplates(filepath.Join(t.SDKPath, "eng/tools/generator/template/typespec"), modulePath, sdkBasicInfo, nil) } func (t *TypeSpecOnBoardGenerator) PreChangeLog(generateParam *GenerateParam) (*exports.Content, error) { return nil, nil } func (t *TypeSpecOnBoardGenerator) AfterGenerate(generateParam *GenerateParam, changelog *Changelog, newExports exports.Content) (*GenerateResult, error) { var err error version := t.Version modulePath := t.ModulePath packagePath := t.PackagePath packageRelativePath := t.PackageRelativePath var prl PullRequestLabel log.Printf("Replace {{NewClientName}} placeholder in the README.md ") if err = ReplaceNewClientNamePlaceholder(modulePath, newExports); err != nil { return nil, err } if !generateParam.SkipGenerateExample { log.Printf("Generate examples...") } // issue: https://github.com/Azure/azure-sdk-for-go/issues/23877 prl = FirstBetaLabel if _, err := t.TypeSpecCommonGenerator.AfterGenerate(generateParam, changelog, newExports); err != nil { return nil, err } return &GenerateResult{ Version: version.String(), RPName: generateParam.RPName, PackageName: generateParam.NamespaceName, PackageAbsPath: packagePath, Changelog: *changelog, ChangelogMD: changelog.ToCompactMarkdown() + "\n" + changelog.GetChangeSummary(), PullRequestLabels: string(prl), PackageRelativePath: packageRelativePath, }, nil } func (t *TypeSpecUpdateGeneraor) PreGenerate(generateParam *GenerateParam) error { log.Printf("Package '%s' existed, do update process", t.PackagePath) log.Printf("Remove all the generated files ...") if err := CleanSDKGeneratedFiles(t.PackagePath); err != nil { return err } return nil } func (t *TypeSpecUpdateGeneraor) PreChangeLog(generateParam *GenerateParam) (*exports.Content, error) { var err error version := t.Version packagePath := t.PackagePath previousVersion := "" isCurrentPreview := false var oriExports *exports.Content if generateParam.SpecificVersion != "" { isCurrentPreview, err = IsBetaVersion(version.String()) if err != nil { return nil, err } } else { isCurrentPreview, err = ContainsPreviewAPIVersion(packagePath) if err != nil { return nil, err } } log.Printf("Get ori exports for changelog generation...") tags := generateParam.ReleasedTags previousVersionTag := GetPreviousVersionTag(isCurrentPreview, tags) oriExports, err = GetExportsFromTag(*t.SDKRepo, packagePath, previousVersionTag) if err != nil && !strings.Contains(err.Error(), "doesn't contain any exports") { return nil, err } tagSplit := strings.Split(previousVersionTag, "/") previousVersion = strings.TrimLeft(tagSplit[len(tagSplit)-1], "v") t.PreviousVersion = previousVersion t.IsCurrentPreview = isCurrentPreview return oriExports, nil } func (t *TypeSpecUpdateGeneraor) AfterGenerate(generateParam *GenerateParam, changelog *Changelog, newExports exports.Content) (*GenerateResult, error) { var prl PullRequestLabel var err error version := t.Version defaultModuleVersion := version.String() packagePath := t.PackagePath modulePath := t.ModulePath packageRelativePath := t.PackageRelativePath moduleRelativePath := t.ModuleRelativePath previousVersion := t.PreviousVersion isCurrentPreview := t.IsCurrentPreview log.Printf("Calculate new version...") if generateParam.SpecificVersion == "" { version, prl, err = CalculateNewVersion(changelog, previousVersion, isCurrentPreview) if err != nil { return nil, err } } log.Printf("Add changelog to file...") changelogMd, err := AddChangelogToFile(changelog, version, modulePath, generateParam.ReleaseDate) if err != nil { return nil, err } log.Printf("Update module definition if v2+...") err = UpdateModuleDefinition(modulePath, moduleRelativePath, version) if err != nil { return nil, err } log.Printf("Replace version in constants.go...") if err = ReplaceConstModuleVersion(packagePath, version.String()); err != nil { return nil, err } oldModuleVersion, err := semver.NewVersion(defaultModuleVersion) if err != nil { return nil, err } baseModule := fmt.Sprintf("%s/%s", "github.com/Azure/azure-sdk-for-go", moduleRelativePath) if _, err := os.Stat(filepath.Join(packagePath, "fake")); !os.IsNotExist(err) && oldModuleVersion.Major() != version.Major() { log.Printf("Replace fake module v2+...") if err = ReplaceModule(version, packagePath, baseModule, ".go"); err != nil { return nil, err } } // When sdk has major version bump, the live test needs to update the module referenced in the code. if existSuffixFile(packagePath, "_live_test.go") { log.Printf("Replace live test module v2+...") if err = ReplaceModule(version, packagePath, baseModule, "_live_test.go"); err != nil { return nil, err } } log.Printf("Replace README.md module...") if err = replaceReadmeModule(modulePath, moduleRelativePath, version.String()); err != nil { return nil, err } log.Printf("Replace README.md NewClient name...") if err = ReplaceReadmeNewClientName(modulePath, newExports); err != nil { return nil, err } // Example generation should be the last step because the package import relay on the new calculated version if !generateParam.SkipGenerateExample { log.Printf("Generate examples...") } // remove autorest.md and build.go autorestMdPath := filepath.Join(packagePath, "autorest.md") if _, err := os.Stat(autorestMdPath); !os.IsNotExist(err) { log.Println("Remove autorest.md...") if err = os.Remove(autorestMdPath); err != nil { return nil, err } } buildGoPath := filepath.Join(packagePath, "build.go") if _, err := os.Stat(buildGoPath); !os.IsNotExist(err) { log.Println("Remove build.go...") if err = os.Remove(buildGoPath); err != nil { return nil, err } } if _, err := t.TypeSpecCommonGenerator.AfterGenerate(generateParam, changelog, newExports); err != nil { return nil, err } return &GenerateResult{ Version: version.String(), RPName: generateParam.RPName, PackageName: generateParam.NamespaceName, PackageAbsPath: packagePath, Changelog: *changelog, ChangelogMD: changelogMd + "\n" + changelog.GetChangeSummary(), PullRequestLabels: string(prl), PackageRelativePath: packageRelativePath, }, nil }