Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Generator] Refine metadata and changelog #14528

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions tools/apidiff/report/report.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ func (p Package) writeNewContent(md *markdown.Writer) {
if !p.HasAdditiveChanges() {
return
}
md.WriteTopLevelHeader("Additive Changes")
writeConsts(p.AdditiveChanges.Consts, "New Constants", md)
writeFuncs(p.AdditiveChanges.Funcs, "New Funcs", md)
writeStructs(p.AdditiveChanges, "New Structs", "New Struct Fields", md)
Expand All @@ -140,7 +141,7 @@ func writeSigChanges(bc *BreakingChanges, md *markdown.Writer) {
if len(bc.Consts) == 0 && len(bc.Funcs) == 0 && len(bc.Structs) == 0 {
return
}
md.WriteTopLevelHeader("Signature Changes")
md.WriteHeader("Signature Changes")
if len(bc.Consts) > 0 {
items := make([]string, len(bc.Consts))
i := 0
Expand All @@ -149,7 +150,7 @@ func writeSigChanges(bc *BreakingChanges, md *markdown.Writer) {
i++
}
sort.Strings(items)
md.WriteHeader("Const Types")
md.WriteSubheader("Const Types")
for _, item := range items {
md.WriteLine(item)
}
Expand All @@ -163,7 +164,7 @@ func writeSigChanges(bc *BreakingChanges, md *markdown.Writer) {
i++
}
sort.Strings(items)
md.WriteHeader("Funcs")
md.WriteSubheader("Funcs")
for _, item := range items {
// now add params/returns info
changes := bc.Funcs[item]
Expand All @@ -184,7 +185,7 @@ func writeSigChanges(bc *BreakingChanges, md *markdown.Writer) {
}
}
sort.Strings(items)
md.WriteHeader("Struct Fields")
md.WriteSubheader("Struct Fields")
for _, item := range items {
md.WriteLine(item)
}
Expand Down Expand Up @@ -245,16 +246,16 @@ func writeStructs(content *delta.Content, sheader1, sheader2 string, md *markdow
if len(content.Structs) == 0 {
return
}
md.WriteTopLevelHeader("Struct Changes")
md.WriteHeader("Struct Changes")
if len(content.CompleteStructs) > 0 {
md.WriteHeader(sheader1)
md.WriteSubheader(sheader1)
for _, s := range content.CompleteStructs {
md.WriteLine(fmt.Sprintf("1. %s", s))
}
}
modified := content.GetModifiedStructs()
if len(modified) > 0 {
md.WriteHeader(sheader2)
md.WriteSubheader(sheader2)
items := make([]string, 0, len(content.Structs)-len(content.CompleteStructs))
for s, f := range modified {
for _, af := range f.AnonymousFields {
Expand Down
24 changes: 19 additions & 5 deletions tools/generator/autorest/autorest.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ import (
"fmt"
"io"
"os/exec"
"strings"

"github.com/Azure/azure-sdk-for-go/tools/generator/autorest/model"
)

// Generator collects all the related context of an autorest generation
type Generator struct {
arguments []string
arguments []model.Option
cmd *exec.Cmd
}

Expand All @@ -26,7 +27,7 @@ func NewGeneratorFromOptions(o model.Options) *Generator {

// WithOption appends an model.Option to the argument list of the autorest generation
func (g *Generator) WithOption(option model.Option) *Generator {
g.arguments = append(g.arguments, option.Format())
g.arguments = append(g.arguments, option)
return g
}

Expand Down Expand Up @@ -67,7 +68,16 @@ func (g *Generator) buildCommand() {
if g.cmd != nil {
return
}
g.cmd = exec.Command("autorest", g.arguments...)
arguments := make([]string, len(g.arguments))
for i, o := range g.arguments {
arguments[i] = o.Format()
}
g.cmd = exec.Command("autorest", arguments...)
}

// Arguments returns the arguments which are using in the autorest command ('autorest' itself excluded)
func (g *Generator) Arguments() []model.Option {
return g.arguments
}

// Start starts the generation
Expand Down Expand Up @@ -120,11 +130,15 @@ func (g *Generator) StderrPipe() (io.ReadCloser, error) {

// GenerateError ...
type GenerateError struct {
Arguments []string
Arguments []model.Option
Message string
}

// Error ...
func (e *GenerateError) Error() string {
return fmt.Sprintf("autorest error with arguments '%s': \n%s", e.Arguments, e.Message)
arguments := make([]string, len(e.Arguments))
for i, o := range e.Arguments {
arguments[i] = o.Format()
}
return fmt.Sprintf("autorest error with arguments '%s': \n%s", strings.Join(arguments, ", "), e.Message)
}
100 changes: 50 additions & 50 deletions tools/generator/autorest/changelog.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ package autorest

import (
"fmt"
"io"
"os"
"path/filepath"
"strings"

"github.com/Azure/azure-sdk-for-go/tools/apidiff/exports"
"github.com/Azure/azure-sdk-for-go/tools/apidiff/report"
Expand All @@ -18,10 +18,7 @@ import (
// ChangelogContext describes all necessary data that would be needed in the processing of changelogs
type ChangelogContext interface {
SDKRoot() string
SDKCloneRoot() string
SpecRoot() string
SpecCommitHash() string
CodeGenVersion() string
RepoContent() map[string]exports.Content
}

// ChangelogProcessor processes the metadata and output changelog with the desired format
Expand All @@ -38,30 +35,12 @@ func NewChangelogProcessorFromContext(ctx ChangelogContext) *ChangelogProcessor
}
}

// WithLocation adds the information of the metadata-output-folder
func (p *ChangelogProcessor) WithLocation(metadataLocation string) *ChangelogProcessor {
p.metadataLocation = metadataLocation
return p
}

// WithReadme adds the information of the path of readme.md file. This path could be relative or absolute.
func (p *ChangelogProcessor) WithReadme(readme string) *ChangelogProcessor {
// make sure the readme here is a relative path to the root of spec
readme = utils.NormalizePath(readme)
root := utils.NormalizePath(p.ctx.SpecRoot())
if filepath.IsAbs(readme) {
readme = strings.TrimPrefix(readme, root)
}
p.readme = readme
return p
}

// ChangelogResult describes the result of the generated changelog for one package
type ChangelogResult struct {
PackageName string
PackagePath string
GenerationMetadata GenerationMetadata
Changelog model.Changelog
Tag string
PackageName string
PackageFullPath string
Changelog model.Changelog
}

// ChangelogProcessError describes the errors during the processing
Expand Down Expand Up @@ -114,39 +93,43 @@ func (p *ChangelogProcessor) Process(metadataMap map[string]model.Metadata) ([]C
}

// GenerateChangelog generates a changelog for one package
func (p *ChangelogProcessor) GenerateChangelog(packagePath, tag string) (*ChangelogResult, error) {
// use the relative path to the sdk root as package name
packageName, err := filepath.Rel(p.ctx.SDKRoot(), packagePath)
func (p *ChangelogProcessor) GenerateChangelog(packageFullPath, tag string) (*ChangelogResult, error) {
relativePackagePath, err := p.getRelativePackagePath(packageFullPath)
if err != nil {
return nil, err
}
// normalize the package name
packageName = utils.NormalizePath(packageName)
lhs, err := getExportsForPackage(filepath.Join(p.ctx.SDKCloneRoot(), packageName))
lhs := p.getLHSContent(relativePackagePath)
rhs, err := getExportsForPackage(packageFullPath)
if err != nil {
return nil, fmt.Errorf("failed to get exports from package '%s' in the clone '%s': %+v", packageName, p.ctx.SDKCloneRoot(), err)
return nil, fmt.Errorf("failed to get exports from package '%s' in the sdk '%s': %+v", relativePackagePath, p.ctx.SDKRoot(), err)
}
rhs, err := getExportsForPackage(packagePath)
r, err := GetChangelogForPackage(lhs, rhs)
if err != nil {
return nil, fmt.Errorf("failed to get exports from package '%s' in the sdk '%s': %+v", packageName, p.ctx.SDKRoot(), err)
}
r, err := getChangelogForPackage(lhs, rhs)
if err != nil {
return nil, fmt.Errorf("failed to generate changelog for package '%s': %+v", packagePath, err)
return nil, fmt.Errorf("failed to generate changelog for package '%s': %+v", relativePackagePath, err)
}
return &ChangelogResult{
PackageName: packageName,
PackagePath: packagePath,
GenerationMetadata: GenerationMetadata{
CommitHash: p.ctx.SpecCommitHash(),
Readme: p.readme,
Tag: tag,
CodeGenVersion: p.ctx.CodeGenVersion(),
},
Changelog: *r,
Tag: tag,
PackageName: relativePackagePath,
PackageFullPath: packageFullPath,
Changelog: *r,
}, nil
}

func (p *ChangelogProcessor) getRelativePackagePath(fullPath string) (string, error) {
relative, err := filepath.Rel(p.ctx.SDKRoot(), fullPath)
if err != nil {
return "", err
}
return utils.NormalizePath(relative), nil
}

func (p *ChangelogProcessor) getLHSContent(relativePackagePath string) *exports.Content {
if v, ok := p.ctx.RepoContent()[relativePackagePath]; ok {
return &v
}
return nil
}

func getExportsForPackage(dir string) (*exports.Content, error) {
// The function exports.Get does not handle the circumstance that the package does not exist
// therefore we have to check if it exists and if not exit early to ensure we do not return an error
Expand All @@ -160,7 +143,8 @@ func getExportsForPackage(dir string) (*exports.Content, error) {
return &exp, nil
}

func getChangelogForPackage(lhs, rhs *exports.Content) (*model.Changelog, error) {
// GetChangelogForPackage generates the changelog report with the given two Contents
func GetChangelogForPackage(lhs, rhs *exports.Content) (*model.Changelog, error) {
if lhs == nil && rhs == nil {
return nil, fmt.Errorf("this package does not exist even after the generation, this should never happen")
}
Expand All @@ -182,3 +166,19 @@ func getChangelogForPackage(lhs, rhs *exports.Content) (*model.Changelog, error)
Modified: &p,
}, nil
}

// ToMarkdown convert this ChangelogResult to markdown string
func (r ChangelogResult) ToMarkdown() string {
return r.Changelog.ToMarkdown()
}

// Write writes this ChangelogResult to the specified writer in markdown format
func (r ChangelogResult) Write(writer io.Writer) error {
_, err := writer.Write([]byte(r.ToMarkdown()))
return err
}

const (
// ChangelogFilename ...
ChangelogFilename = "CHANGELOG.md"
)
Loading