diff --git a/cmd/generate.go b/cmd/generate.go index 42e82af..58c45a0 100644 --- a/cmd/generate.go +++ b/cmd/generate.go @@ -21,8 +21,9 @@ var ( fromRef string toRef string writeTo string + repoURL string DefaultTimeout = 5 * time.Second - requiredFlags = []string{"base_url", "email_id", "api_token"} + requiredFlags = []string{"base_url", "email_id", "api_token", "repo_url"} ) var generateCmd = &cobra.Command{ @@ -35,6 +36,7 @@ gh-jira-changelog generate \ --to="" \ --api_token="" \ --email_id="jira-email-id" + --repo_url="https://github.com//" # using config file # all the jira config such as (base_url, api_token, email_id) can be stored in a config file @@ -79,13 +81,15 @@ gh jira-changelog generate --config=".yaml" --from="v0.1.0" jira.Config{ BaseUrl: viper.GetString("base_url"), ApiToken: viper.GetString("api_token"), - User: viper.GetString("email_id")}, + User: viper.GetString("email_id"), + }, fromRef, toRef, + repoURL, ) slog.Info("Generating changelog", "JiraConfig", changelog.JiraConfig, - "From", fromRef, "To", toRef) + "From", fromRef, "To", toRef, "repoURL", repoURL) changelog.Generate(ctx).Render(writer(writeTo)) }, } @@ -111,6 +115,7 @@ func init() { generateCmd.Flags().StringVar(&fromRef, "from", "", "Git ref to start from") generateCmd.Flags().StringVar(&toRef, "to", "main", "Git ref to end at") generateCmd.Flags().StringVar(&writeTo, "write_to", "/dev/stdout", "File stream to write the changelog") + generateCmd.Flags().StringVar(&repoURL, "repo_url", "", "Repo URL. Used to generate diff url. Currently only github is supported") generateCmd.MarkFlagRequired("from") diff --git a/cmd/root.go b/cmd/root.go index 86f6e3d..38c0732 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -56,6 +56,7 @@ func init() { rootCmd.PersistentFlags().String("email_id", "", "email id of the user") rootCmd.PersistentFlags().StringP("api_token", "t", "", "API token for jira") rootCmd.PersistentFlags().StringP("log_level", "v", "error", "log level. options: debug, info, warn, error") + rootCmd.PersistentFlags().StringVar(&repoURL, "repo_url", "", "Repo URL. Used to generate diff url. Currently only github is supported") viper.BindPFlags(rootCmd.PersistentFlags()) } diff --git a/pkg/jira_changelog/changelog.go b/pkg/jira_changelog/changelog.go index a916be6..599fab7 100644 --- a/pkg/jira_changelog/changelog.go +++ b/pkg/jira_changelog/changelog.go @@ -14,12 +14,18 @@ import ( //go:embed templates/*.tmpl var changeLogTmpl embed.FS +type Epic = string +type Changes = map[Epic][]jira.Issue + type Changelog struct { - Changes map[string][]jira.Issue + Changes Changes + fromRef string + toRef string + repoURL string } func (c *Changelog) Render(w io.Writer) { - slog.Info("rendering changelog") + slog.Info("rendering changelog", "number-of-changes", len(c.Changes)) tmpl, err := template.ParseFS(changeLogTmpl, "templates/changelog.tmpl") if err != nil { slog.Error("error parsing template", "error", err) @@ -34,3 +40,16 @@ func (c *Changelog) Render(w io.Writer) { fmt.Fprint(w, resultBuffer.String()) } + +func (c *Changelog) URL() string { + return fmt.Sprintf("%s/compare/%s...%s", c.repoURL, c.fromRef, c.toRef) +} + +func NewChangelog(fromRef, toRef, repoURL string, changes Changes) *Changelog { + return &Changelog{ + Changes: changes, + fromRef: fromRef, + toRef: toRef, + repoURL: repoURL, + } +} diff --git a/pkg/jira_changelog/changelog_test.go b/pkg/jira_changelog/changelog_test.go index 919e3c0..2dfe17d 100644 --- a/pkg/jira_changelog/changelog_test.go +++ b/pkg/jira_changelog/changelog_test.go @@ -25,7 +25,7 @@ func TestRender(t *testing.T) { }, }, }, - want: `## What has changed? + want: `## What's changed? ### TestEpic - [TEST-1] foobar is new @@ -45,7 +45,7 @@ func TestRender(t *testing.T) { }, }, }, - want: `## What has changed? + want: `## What's changed? ### TestEpic - [TEST-1] foobar is new @@ -71,7 +71,7 @@ func TestRender(t *testing.T) { }, }, }, - want: `## What has changed? + want: `## What's changed? ### TestEpic1 - [TEST-1] foobar is new diff --git a/pkg/jira_changelog/generator.go b/pkg/jira_changelog/generator.go index 4c44b8e..a0b9694 100644 --- a/pkg/jira_changelog/generator.go +++ b/pkg/jira_changelog/generator.go @@ -14,6 +14,7 @@ type Generator struct { JiraConfig jira.Config fromRef string toRef string + repoURL string client jira.Client } @@ -30,13 +31,15 @@ func (c Generator) Generate(ctx context.Context) *Changelog { commits, err := gitOutput.Commits() panicIfErr(err) - changelog, err := c.changelogFromCommits(commits) + changes, err := c.changesFromCommits(commits) panicIfErr(err) - return changelog + slog.Debug("changes fetched", "changes", changes) + + return NewChangelog(c.fromRef, c.toRef, c.repoURL, changes) } -func (c Generator) changelogFromCommits(commits []git.Commit) (*Changelog, error) { +func (c Generator) changesFromCommits(commits []git.Commit) (Changes, error) { slog.Debug("Total commit messages", "count", len(commits)) jiraIssues := make([]jira.Issue, 0) @@ -55,7 +58,7 @@ func (c Generator) changelogFromCommits(commits []git.Commit) (*Changelog, error slog.Debug("Total jira issues ids", "count", len(jiraIssues)) issuesByEpic := lo.GroupBy(jiraIssues, func(issue jira.Issue) string { return issue.Epic() }) - return &Changelog{Changes: issuesByEpic}, nil + return issuesByEpic, nil } func (c Generator) fetchJiraIssue(commit git.Commit) (jira.Issue, error) { @@ -73,12 +76,13 @@ func (c Generator) fetchJiraIssue(commit git.Commit) (jira.Issue, error) { return issue, nil } -func NewGenerator(jiraConfig jira.Config, fromRef, toRef string) *Generator { +func NewGenerator(jiraConfig jira.Config, fromRef, toRef, repoURL string) *Generator { client := jira.NewClient(jiraConfig) return &Generator{ jiraConfig, fromRef, toRef, + repoURL, client, } } diff --git a/pkg/jira_changelog/generator_test.go b/pkg/jira_changelog/generator_test.go index 14a7f7f..0f53de4 100644 --- a/pkg/jira_changelog/generator_test.go +++ b/pkg/jira_changelog/generator_test.go @@ -22,7 +22,7 @@ func TestChangelogFromCommits(t *testing.T) { } expected := &Changelog{ - Changes: map[string][]jira.Issue{ + Changes: Changes{ "Epic1": { jira.NewIssue("TEST-1234", "Ticket description", "done", "Epic1"), jira.NewIssue("TEST-12345", "Ticket description of another from same epic", "done", "Epic1"), @@ -44,7 +44,7 @@ func TestChangelogFromCommits(t *testing.T) { generator := Generator{} generator.client = mockedClient - result, err := generator.changelogFromCommits(commits) + result, err := generator.changesFromCommits(commits) assert.NoError(t, err) assert.Equal(t, expected, result) diff --git a/pkg/jira_changelog/git/commits.go b/pkg/jira_changelog/git/commits.go index 1859ebd..210490d 100644 --- a/pkg/jira_changelog/git/commits.go +++ b/pkg/jira_changelog/git/commits.go @@ -33,6 +33,18 @@ func ExecGitLog(ctx context.Context, fromRef, toRef string) (GitOutput, error) { return GitOutput(result), nil } +func FetchGitRemoteURL(ctx context.Context) (string, error) { + cmd := exec.CommandContext(ctx, "git", "remote", "get-url", "origin") + stdout, err := cmd.Output() + if err != nil { + return "", fmt.Errorf("failed to execute git command: %v", err) + } + + result := strings.TrimSpace(string(stdout)) + result = strings.TrimSuffix(result, ".git") + return result, nil +} + func (gt GitOutput) Commits() ([]Commit, error) { output := strings.TrimSpace(string(gt)) commits := make([]Commit, 0) diff --git a/pkg/jira_changelog/templates/changelog.tmpl b/pkg/jira_changelog/templates/changelog.tmpl index 3a821e2..458f930 100644 --- a/pkg/jira_changelog/templates/changelog.tmpl +++ b/pkg/jira_changelog/templates/changelog.tmpl @@ -1,4 +1,4 @@ -## What has changed? +## What's changed? {{- range $epic, $changes := .Changes }} ### {{$epic}} @@ -14,3 +14,5 @@ {{ end }} :warning: = Work in Progress. Ensure that these cards don't break things in production. + +Full changelog: [{{.URL}}]({{.URL}})