mirror of
https://github.com/apricote/releaser-pleaser.git
synced 2026-01-13 13:21:00 +00:00
refactor: let updaters define the files they want to run on (#233)
This change reverses the responsibility for which files the updaters are run on. Now each updater can specify the list of files and wether the files should be created when they do not exist yet. This simplifies the handling of each update in releaserpleaser.go, as we can just iterate over all updaters and call it for each file of that updater. Also update the flags to allow users to easily define which updaters should run.
This commit is contained in:
parent
1e9e0aa5d9
commit
f1aa1a2ef4
20 changed files with 307 additions and 151 deletions
|
|
@ -6,7 +6,6 @@ import (
|
|||
"io"
|
||||
"log/slog"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/go-git/go-git/v5"
|
||||
|
|
@ -14,8 +13,6 @@ import (
|
|||
"github.com/go-git/go-git/v5/plumbing"
|
||||
"github.com/go-git/go-git/v5/plumbing/object"
|
||||
"github.com/go-git/go-git/v5/plumbing/transport"
|
||||
|
||||
"github.com/apricote/releaser-pleaser/internal/updater"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -120,7 +117,7 @@ func (r *Repository) Checkout(_ context.Context, branch string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (r *Repository) UpdateFile(_ context.Context, path string, create bool, updaters []updater.Updater) error {
|
||||
func (r *Repository) UpdateFile(_ context.Context, path string, create bool, updateHook func(string) (string, error)) error {
|
||||
worktree, err := r.r.Worktree()
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -142,13 +139,9 @@ func (r *Repository) UpdateFile(_ context.Context, path string, create bool, upd
|
|||
return err
|
||||
}
|
||||
|
||||
updatedContent := string(content)
|
||||
|
||||
for _, update := range updaters {
|
||||
updatedContent, err = update(updatedContent, filepath.Base(path))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to run updater on file %s", path)
|
||||
}
|
||||
updatedContent, err := updateHook(string(content))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to run update hook on file %s", path)
|
||||
}
|
||||
|
||||
err = file.Truncate(0)
|
||||
|
|
|
|||
|
|
@ -14,8 +14,23 @@ var (
|
|||
ChangelogUpdaterHeaderRegex = regexp.MustCompile(`^# Changelog\n`)
|
||||
)
|
||||
|
||||
func Changelog(info ReleaseInfo) Updater {
|
||||
return func(content string, filename string) (string, error) {
|
||||
func Changelog() Updater {
|
||||
return changelog{}
|
||||
}
|
||||
|
||||
type changelog struct {
|
||||
}
|
||||
|
||||
func (c changelog) Files() []string {
|
||||
return []string{ChangelogFile}
|
||||
}
|
||||
|
||||
func (c changelog) CreateNewFiles() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (c changelog) Update(info ReleaseInfo) func(content string) (string, error) {
|
||||
return func(content string) (string, error) {
|
||||
headerIndex := ChangelogUpdaterHeaderRegex.FindStringIndex(content)
|
||||
if headerIndex == nil && len(content) != 0 {
|
||||
return "", fmt.Errorf("unexpected format of CHANGELOG.md, header does not match")
|
||||
|
|
|
|||
|
|
@ -6,15 +6,22 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestChangelogUpdater_UpdateContent(t *testing.T) {
|
||||
func TestChangelogUpdater_Files(t *testing.T) {
|
||||
assert.Equal(t, []string{"CHANGELOG.md"}, Changelog().Files())
|
||||
}
|
||||
|
||||
func TestChangelogUpdater_CreateNewFiles(t *testing.T) {
|
||||
assert.True(t, Changelog().CreateNewFiles())
|
||||
}
|
||||
|
||||
func TestChangelogUpdater_Update(t *testing.T) {
|
||||
tests := []updaterTestCase{
|
||||
{
|
||||
name: "empty file",
|
||||
content: "",
|
||||
filename: "CHANGELOG.md",
|
||||
info: ReleaseInfo{ChangelogEntry: "## v1.0.0\n"},
|
||||
want: "# Changelog\n\n## v1.0.0\n",
|
||||
wantErr: assert.NoError,
|
||||
name: "empty file",
|
||||
content: "",
|
||||
info: ReleaseInfo{ChangelogEntry: "## v1.0.0\n"},
|
||||
want: "# Changelog\n\n## v1.0.0\n",
|
||||
wantErr: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "well-formatted changelog",
|
||||
|
|
@ -28,8 +35,7 @@ func TestChangelogUpdater_UpdateContent(t *testing.T) {
|
|||
|
||||
### Bazuuum
|
||||
`,
|
||||
filename: "CHANGELOG.md",
|
||||
info: ReleaseInfo{ChangelogEntry: "## v1.0.0\n\n- Version 1, juhu.\n"},
|
||||
info: ReleaseInfo{ChangelogEntry: "## v1.0.0\n\n- Version 1, juhu.\n"},
|
||||
want: `# Changelog
|
||||
|
||||
## v1.0.0
|
||||
|
|
@ -47,17 +53,16 @@ func TestChangelogUpdater_UpdateContent(t *testing.T) {
|
|||
wantErr: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "error on invalid header",
|
||||
content: "What even is this file?",
|
||||
filename: "CHANGELOG.md",
|
||||
info: ReleaseInfo{ChangelogEntry: "## v1.0.0\n\n- Version 1, juhu.\n"},
|
||||
want: "",
|
||||
wantErr: assert.Error,
|
||||
name: "error on invalid header",
|
||||
content: "What even is this file?",
|
||||
info: ReleaseInfo{ChangelogEntry: "## v1.0.0\n\n- Version 1, juhu.\n"},
|
||||
want: "",
|
||||
wantErr: assert.Error,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
runUpdaterTest(t, Changelog, tt)
|
||||
runUpdaterTest(t, Changelog(), tt)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,8 +7,26 @@ import (
|
|||
|
||||
var GenericUpdaterSemVerRegex = regexp.MustCompile(`\d+\.\d+\.\d+(-[\w.]+)?(.*x-releaser-pleaser-version)`)
|
||||
|
||||
func Generic(info ReleaseInfo) Updater {
|
||||
return func(content string, filename string) (string, error) {
|
||||
func Generic(files []string) Updater {
|
||||
return generic{
|
||||
files: files,
|
||||
}
|
||||
}
|
||||
|
||||
type generic struct {
|
||||
files []string
|
||||
}
|
||||
|
||||
func (g generic) Files() []string {
|
||||
return g.files
|
||||
}
|
||||
|
||||
func (g generic) CreateNewFiles() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (g generic) Update(info ReleaseInfo) func(content string) (string, error) {
|
||||
return func(content string) (string, error) {
|
||||
// We strip the "v" prefix to avoid adding/removing it from the users input.
|
||||
version := strings.TrimPrefix(info.Version, "v")
|
||||
|
||||
|
|
|
|||
|
|
@ -6,12 +6,19 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestGenericUpdater_UpdateContent(t *testing.T) {
|
||||
func TestGenericUpdater_Files(t *testing.T) {
|
||||
assert.Equal(t, []string{"foo.bar", "version.txt"}, Generic([]string{"foo.bar", "version.txt"}).Files())
|
||||
}
|
||||
|
||||
func TestGenericUpdater_CreateNewFiles(t *testing.T) {
|
||||
assert.False(t, Generic([]string{}).CreateNewFiles())
|
||||
}
|
||||
|
||||
func TestGenericUpdater_Update(t *testing.T) {
|
||||
tests := []updaterTestCase{
|
||||
{
|
||||
name: "single line",
|
||||
content: "v1.0.0 // x-releaser-pleaser-version",
|
||||
filename: "version.txt",
|
||||
name: "single line",
|
||||
content: "v1.0.0 // x-releaser-pleaser-version",
|
||||
info: ReleaseInfo{
|
||||
Version: "v1.2.0",
|
||||
},
|
||||
|
|
@ -19,9 +26,8 @@ func TestGenericUpdater_UpdateContent(t *testing.T) {
|
|||
wantErr: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "multiline line",
|
||||
content: "Foooo\n\v1.2.0\nv1.0.0 // x-releaser-pleaser-version\n",
|
||||
filename: "version.txt",
|
||||
name: "multiline line",
|
||||
content: "Foooo\n\v1.2.0\nv1.0.0 // x-releaser-pleaser-version\n",
|
||||
info: ReleaseInfo{
|
||||
Version: "v1.2.0",
|
||||
},
|
||||
|
|
@ -29,9 +35,8 @@ func TestGenericUpdater_UpdateContent(t *testing.T) {
|
|||
wantErr: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "invalid existing version",
|
||||
content: "1.0 // x-releaser-pleaser-version",
|
||||
filename: "version.txt",
|
||||
name: "invalid existing version",
|
||||
content: "1.0 // x-releaser-pleaser-version",
|
||||
info: ReleaseInfo{
|
||||
Version: "v1.2.0",
|
||||
},
|
||||
|
|
@ -39,9 +44,8 @@ func TestGenericUpdater_UpdateContent(t *testing.T) {
|
|||
wantErr: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "complicated line",
|
||||
content: "version: v1.2.0-alpha.1 => Awesome, isnt it? x-releaser-pleaser-version foobar",
|
||||
filename: "version.txt",
|
||||
name: "complicated line",
|
||||
content: "version: v1.2.0-alpha.1 => Awesome, isnt it? x-releaser-pleaser-version foobar",
|
||||
info: ReleaseInfo{
|
||||
Version: "v1.2.0",
|
||||
},
|
||||
|
|
@ -51,7 +55,7 @@ func TestGenericUpdater_UpdateContent(t *testing.T) {
|
|||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
runUpdaterTest(t, Generic, tt)
|
||||
runUpdaterTest(t, Generic([]string{"version.txt"}), tt)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,11 +6,22 @@ import (
|
|||
)
|
||||
|
||||
// PackageJson creates an updater that modifies the version field in package.json files
|
||||
func PackageJson(info ReleaseInfo) Updater {
|
||||
return func(content string, filename string) (string, error) {
|
||||
if filename != "package.json" {
|
||||
return content, nil // No update needed for non-package.json files
|
||||
}
|
||||
func PackageJson() Updater {
|
||||
return packagejson{}
|
||||
}
|
||||
|
||||
type packagejson struct{}
|
||||
|
||||
func (p packagejson) Files() []string {
|
||||
return []string{"package.json"}
|
||||
}
|
||||
|
||||
func (p packagejson) CreateNewFiles() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (p packagejson) Update(info ReleaseInfo) func(content string) (string, error) {
|
||||
return func(content string) (string, error) {
|
||||
// We strip the "v" prefix to match npm versioning convention
|
||||
version := strings.TrimPrefix(info.Version, "v")
|
||||
|
||||
|
|
@ -23,8 +34,6 @@ func PackageJson(info ReleaseInfo) Updater {
|
|||
}
|
||||
|
||||
// Replace the version value while preserving the original formatting
|
||||
updatedContent := versionRegex.ReplaceAllString(content, `${1}"`+version+`"`)
|
||||
|
||||
return updatedContent, nil
|
||||
return versionRegex.ReplaceAllString(content, `${1}"`+version+`"`), nil
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,24 @@
|
|||
package updater
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestPackageJsonUpdater(t *testing.T) {
|
||||
func TestPackageJsonUpdater_Files(t *testing.T) {
|
||||
assert.Equal(t, []string{"package.json"}, PackageJson().Files())
|
||||
}
|
||||
|
||||
func TestPackageJsonUpdater_CreateNewFiles(t *testing.T) {
|
||||
assert.False(t, PackageJson().CreateNewFiles())
|
||||
}
|
||||
|
||||
func TestPackageJsonUpdater_Update(t *testing.T) {
|
||||
tests := []updaterTestCase{
|
||||
{
|
||||
name: "simple package.json",
|
||||
content: `{"name":"test","version":"1.0.0"}`,
|
||||
filename: "package.json",
|
||||
name: "simple package.json",
|
||||
content: `{"name":"test","version":"1.0.0"}`,
|
||||
info: ReleaseInfo{
|
||||
Version: "v2.0.5",
|
||||
},
|
||||
|
|
@ -20,19 +26,8 @@ func TestPackageJsonUpdater(t *testing.T) {
|
|||
wantErr: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "simple package.json, wrong name",
|
||||
content: `{"name":"test","version":"1.0.0"}`,
|
||||
filename: "nopackage.json",
|
||||
info: ReleaseInfo{
|
||||
Version: "v2.0.5",
|
||||
},
|
||||
want: `{"name":"test","version":"1.0.0"}`,
|
||||
wantErr: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "complex package.json",
|
||||
content: "{\n \"name\": \"test\",\n \"version\": \"1.0.0\",\n \"dependencies\": {\n \"foo\": \"^1.0.0\"\n }\n}",
|
||||
filename: "package.json",
|
||||
name: "complex package.json",
|
||||
content: "{\n \"name\": \"test\",\n \"version\": \"1.0.0\",\n \"dependencies\": {\n \"foo\": \"^1.0.0\"\n }\n}",
|
||||
info: ReleaseInfo{
|
||||
Version: "v2.0.0",
|
||||
},
|
||||
|
|
@ -40,9 +35,8 @@ func TestPackageJsonUpdater(t *testing.T) {
|
|||
wantErr: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "invalid json",
|
||||
content: `not json`,
|
||||
filename: "package.json",
|
||||
name: "invalid json",
|
||||
content: `not json`,
|
||||
info: ReleaseInfo{
|
||||
Version: "v2.0.0",
|
||||
},
|
||||
|
|
@ -50,9 +44,8 @@ func TestPackageJsonUpdater(t *testing.T) {
|
|||
wantErr: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "json without version",
|
||||
content: `{"name":"test"}`,
|
||||
filename: "package.json",
|
||||
name: "json without version",
|
||||
content: `{"name":"test"}`,
|
||||
info: ReleaseInfo{
|
||||
Version: "v2.0.0",
|
||||
},
|
||||
|
|
@ -63,8 +56,7 @@ func TestPackageJsonUpdater(t *testing.T) {
|
|||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
fmt.Println("Running updater test for PackageJson")
|
||||
runUpdaterTest(t, PackageJson, tt)
|
||||
runUpdaterTest(t, PackageJson(), tt)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,11 @@ type ReleaseInfo struct {
|
|||
ChangelogEntry string
|
||||
}
|
||||
|
||||
type Updater func(content string, filename string) (string, error)
|
||||
type Updater interface {
|
||||
Files() []string
|
||||
CreateNewFiles() bool
|
||||
Update(info ReleaseInfo) func(content string) (string, error)
|
||||
}
|
||||
|
||||
type NewUpdater func(ReleaseInfo) Updater
|
||||
|
||||
|
|
|
|||
|
|
@ -8,20 +8,19 @@ import (
|
|||
)
|
||||
|
||||
type updaterTestCase struct {
|
||||
name string
|
||||
content string
|
||||
filename string
|
||||
info ReleaseInfo
|
||||
want string
|
||||
wantErr assert.ErrorAssertionFunc
|
||||
name string
|
||||
content string
|
||||
info ReleaseInfo
|
||||
want string
|
||||
wantErr assert.ErrorAssertionFunc
|
||||
}
|
||||
|
||||
func runUpdaterTest(t *testing.T, constructor NewUpdater, tt updaterTestCase) {
|
||||
func runUpdaterTest(t *testing.T, u Updater, tt updaterTestCase) {
|
||||
t.Helper()
|
||||
|
||||
got, err := constructor(tt.info)(tt.content, tt.filename)
|
||||
if !tt.wantErr(t, err, fmt.Sprintf("Updater(%v, %v, %v)", tt.content, tt.filename, tt.info)) {
|
||||
got, err := u.Update(tt.info)(tt.content)
|
||||
if !tt.wantErr(t, err, fmt.Sprintf("Updater(%v, %v)", tt.content, tt.info)) {
|
||||
return
|
||||
}
|
||||
assert.Equalf(t, tt.want, got, "Updater(%v, %v, %v)", tt.content, tt.filename, tt.info)
|
||||
assert.Equalf(t, tt.want, got, "Updater(%v, %v)", tt.content, tt.info)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue