220 lines
5.6 KiB
Go
220 lines
5.6 KiB
Go
package changelog
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestSanitizeSubject(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tests := []struct {
|
|
name string
|
|
subject string
|
|
want string
|
|
}{
|
|
{
|
|
name: "merge prefix with quotes",
|
|
subject: "Merge pull request 'Add classes overhaul (#123)'",
|
|
want: "Add classes overhaul",
|
|
},
|
|
{
|
|
name: "plain subject",
|
|
subject: "Add classes overhaul (#123)",
|
|
want: "Add classes overhaul",
|
|
},
|
|
{
|
|
name: "double quotes",
|
|
subject: `Merge pull request "Add classes overhaul (#123)"`,
|
|
want: "Add classes overhaul",
|
|
},
|
|
{
|
|
name: "direct push",
|
|
subject: "Fix direct push handling",
|
|
want: "Fix direct push handling",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
tt := tt
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
if got := sanitizeSubject(tt.subject); got != tt.want {
|
|
t.Fatalf("sanitizeSubject(%q) = %q, want %q", tt.subject, got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestShortCommitHash(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
if got := shortCommitHash("1234567890abcdef"); got != "1234567" {
|
|
t.Fatalf("shortCommitHash() = %q, want %q", got, "1234567")
|
|
}
|
|
if got := shortCommitHash("1234567"); got != "1234567" {
|
|
t.Fatalf("shortCommitHash() preserved %q unexpectedly as %q", "1234567", got)
|
|
}
|
|
}
|
|
|
|
func TestOwnerAndRepoFromURL(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
owner, repo, err := ownerAndRepoFromURL("https://gitea.example.test/org/repo.git")
|
|
if err != nil {
|
|
t.Fatalf("ownerAndRepoFromURL returned error: %v", err)
|
|
}
|
|
if owner != "org" || repo != "repo" {
|
|
t.Fatalf("ownerAndRepoFromURL returned %q/%q", owner, repo)
|
|
}
|
|
}
|
|
|
|
func TestDeriveAPIBaseURL(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
got := deriveAPIBaseURL("https://gitea.example.test/org/repo")
|
|
want := "https://gitea.example.test/api/v1"
|
|
if got != want {
|
|
t.Fatalf("deriveAPIBaseURL() = %q, want %q", got, want)
|
|
}
|
|
}
|
|
|
|
func TestNormalizeAPIBaseURL(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tests := []struct {
|
|
input string
|
|
want string
|
|
}{
|
|
{input: "https://gitea.example.test", want: "https://gitea.example.test/api/v1"},
|
|
{input: "https://gitea.example.test/api/v1", want: "https://gitea.example.test/api/v1"},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
if got := normalizeAPIBaseURL(tt.input); got != tt.want {
|
|
t.Fatalf("normalizeAPIBaseURL(%q) = %q, want %q", tt.input, got, tt.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestGenerateIncludesPullRequestsAndDirectPushes(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
repoRoot := t.TempDir()
|
|
runGit(t, repoRoot, "init")
|
|
runGit(t, repoRoot, "config", "user.name", "Test User")
|
|
runGit(t, repoRoot, "config", "user.email", "test@example.com")
|
|
|
|
writeFile(t, filepath.Join(repoRoot, "content", "entry.txt"), "initial\n")
|
|
runGit(t, repoRoot, "add", ".")
|
|
runGit(t, repoRoot, "commit", "-m", "Initial import")
|
|
runGit(t, repoRoot, "tag", "v1.0.0")
|
|
|
|
writeFile(t, filepath.Join(repoRoot, "content", "entry.txt"), "direct\n")
|
|
runGit(t, repoRoot, "add", ".")
|
|
runGit(t, repoRoot, "commit", "-m", "Fix direct push handling")
|
|
directHash := strings.TrimSpace(runGit(t, repoRoot, "rev-parse", "HEAD"))
|
|
|
|
writeFile(t, filepath.Join(repoRoot, "content", "entry.txt"), "pull\n")
|
|
runGit(t, repoRoot, "add", ".")
|
|
runGit(t, repoRoot, "commit", "-m", "Add release summary (#12)")
|
|
runGit(t, repoRoot, "tag", "v1.1.0")
|
|
|
|
configPath := filepath.Join(repoRoot, "scripts", "changelog.json")
|
|
writeFile(t, configPath, `{
|
|
"repo_url": "REPO_URL",
|
|
"categories": [
|
|
{
|
|
"title": "Content",
|
|
"sections": [
|
|
{
|
|
"title": "Entries",
|
|
"paths": ["content/"]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}`)
|
|
|
|
var pullRequests int
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.URL.Path != "/api/v1/repos/org/repo/pulls/12" {
|
|
t.Fatalf("unexpected API path %q", r.URL.Path)
|
|
}
|
|
pullRequests++
|
|
w.Header().Set("Content-Type", "application/json")
|
|
fmt.Fprint(w, `{"user":{"full_name":"Patch Author","login":"patch-author"}}`)
|
|
}))
|
|
defer server.Close()
|
|
|
|
repoURL := server.URL + "/org/repo"
|
|
configData, err := os.ReadFile(configPath)
|
|
if err != nil {
|
|
t.Fatalf("read changelog config: %v", err)
|
|
}
|
|
configData = bytes.ReplaceAll(configData, []byte("REPO_URL"), []byte(repoURL))
|
|
if err := os.WriteFile(configPath, configData, 0o644); err != nil {
|
|
t.Fatalf("write changelog config: %v", err)
|
|
}
|
|
|
|
var stdout bytes.Buffer
|
|
err = Generate(Options{
|
|
RepoRoot: repoRoot,
|
|
ConfigPath: configPath,
|
|
CurrentTag: "v1.1.0",
|
|
PreviousTag: "v1.0.0",
|
|
APIBaseURL: server.URL + "/api/v1",
|
|
Stdout: &stdout,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Generate() returned error: %v", err)
|
|
}
|
|
|
|
rendered := stdout.String()
|
|
for _, want := range []string{
|
|
"Add release summary",
|
|
repoURL + "/pulls/12",
|
|
"Patch Author",
|
|
"Fix direct push handling",
|
|
repoURL + "/commit/" + directHash,
|
|
"Test User",
|
|
} {
|
|
if !strings.Contains(rendered, want) {
|
|
t.Errorf("rendered changelog missing %q:\n%s", want, rendered)
|
|
}
|
|
}
|
|
if pullRequests != 1 {
|
|
t.Fatalf("expected 1 pull lookup, got %d", pullRequests)
|
|
}
|
|
}
|
|
|
|
func runGit(t *testing.T, repoRoot string, args ...string) string {
|
|
t.Helper()
|
|
|
|
cmd := exec.Command("git", append([]string{"-c", "commit.gpgsign=false", "-c", "tag.gpgsign=false"}, args...)...)
|
|
cmd.Dir = repoRoot
|
|
output, err := cmd.CombinedOutput()
|
|
if err != nil {
|
|
t.Fatalf("git %s failed: %v\n%s", strings.Join(args, " "), err, output)
|
|
}
|
|
return string(output)
|
|
}
|
|
|
|
func writeFile(t *testing.T, path string, content string) {
|
|
t.Helper()
|
|
|
|
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
|
|
t.Fatalf("MkdirAll(%q): %v", path, err)
|
|
}
|
|
if err := os.WriteFile(path, []byte(content), 0o644); err != nil {
|
|
t.Fatalf("WriteFile(%q): %v", path, err)
|
|
}
|
|
}
|