< Summary - go-semantic-release Coverage

Information
Line coverage
84%
Covered lines: 44
Uncovered lines: 8
Coverable lines: 52
Total lines: 109
Line coverage: 84.6%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
FormatTag0%0060%
ParseTag0%00100%
FindLatestTag0%0088.24%

File(s)

/home/runner/work/go-semantic-release/go-semantic-release/internal/adapters/git/tag_service.go

#LineLine coverage
 1package git
 2
 3import (
 4  "bytes"
 5  "fmt"
 6  "strings"
 7  "text/template"
 8
 9  "github.com/jedi-knights/go-semantic-release/internal/domain"
 10  "github.com/jedi-knights/go-semantic-release/internal/ports"
 11)
 12
 13// Compile-time interface compliance check.
 14var _ ports.TagService = (*TemplateTagService)(nil)
 15
 16// TemplateTagService formats and parses tags using Go templates.
 17type TemplateTagService struct {
 18  repoTemplate    string
 19  projectTemplate string
 20}
 21
 22// NewTemplateTagService creates a tag service with configurable templates.
 23func NewTemplateTagService(repoTemplate, projectTemplate string) *TemplateTagService {
 24  if repoTemplate == "" {
 25    repoTemplate = "v{{.Version}}"
 26  }
 27  if projectTemplate == "" {
 28    projectTemplate = "{{.Project}}/v{{.Version}}"
 29  }
 30  return &TemplateTagService{
 31    repoTemplate:    repoTemplate,
 32    projectTemplate: projectTemplate,
 33  }
 34}
 35
 36type tagData struct {
 37  Project string
 38  Version string
 39}
 40
 441func (s *TemplateTagService) FormatTag(project string, version domain.Version) (string, error) {
 442  tmplStr := s.repoTemplate
 243  if project != "" {
 244    tmplStr = s.projectTemplate
 245  }
 46
 447  tmpl, err := template.New("tag").Parse(tmplStr)
 048  if err != nil {
 049    return "", fmt.Errorf("parsing tag template: %w", err)
 050  }
 51
 452  var buf bytes.Buffer
 453  data := tagData{Project: project, Version: version.String()}
 054  if err := tmpl.Execute(&buf, data); err != nil {
 055    return "", fmt.Errorf("executing tag template: %w", err)
 056  }
 457  return buf.String(), nil
 58}
 59
 2060func (s *TemplateTagService) ParseTag(tagName string) (string, domain.Version, error) {
 2061  // Try project-scoped patterns first.
 2062  // Pattern: project/vX.Y.Z
 863  if idx := strings.Index(tagName, "/v"); idx > 0 {
 864    project := tagName[:idx]
 865    ver, err := domain.ParseVersion(tagName[idx+1:])
 866    if err == nil {
 867      return project, ver, nil
 868    }
 69  }
 70
 71  // Pattern: project@X.Y.Z
 172  if idx := strings.LastIndex(tagName, "@"); idx > 0 {
 173    project := tagName[:idx]
 174    ver, err := domain.ParseVersion(tagName[idx+1:])
 175    if err == nil {
 176      return project, ver, nil
 177    }
 78  }
 79
 80  // Repo-level: vX.Y.Z or X.Y.Z
 1181  ver, err := domain.ParseVersion(tagName)
 182  if err != nil {
 183    return "", domain.Version{}, fmt.Errorf("cannot parse tag %q: %w", tagName, err)
 184  }
 1085  return "", ver, nil
 86}
 87
 388func (s *TemplateTagService) FindLatestTag(tags []domain.Tag, project string) (*domain.Tag, error) {
 389  var latest *domain.Tag
 390
 391  for i := range tags {
 1592    proj, ver, err := s.ParseTag(tags[i].Name)
 093    if err != nil {
 094      continue
 95    }
 1096    if proj != project {
 1097      continue
 98    }
 99
 5100    tags[i].Version = ver
 5101    tags[i].Project = proj
 5102
 5103    if latest == nil || ver.GreaterThan(latest.Version) {
 5104      t := tags[i]
 5105      latest = &t
 5106    }
 107  }
 3108  return latest, nil
 109}

Methods/Properties

FormatTag
ParseTag
FindLatestTag