diff --git a/action.yml b/action.yml
index 5a3d233..651ca09 100644
--- a/action.yml
+++ b/action.yml
@@ -14,15 +14,15 @@ inputs:
required: false
default: ${{ github.token }}
extra-files:
- description: 'List of files that are scanned for version references.'
+ description: 'List of files that are scanned for version references by the generic updater.'
required: false
default: ""
- update-package-json:
- description: 'Update version field in package.json file.'
+ updaters:
+ description: "List of updaters that are run. Default updaters can be removed by specifying them as -name. Multiple updaters should be concatenated with a comma. Default Updaters: changelog,generic"
required: false
- default: "false"
+ default: ""
# Remember to update docs/reference/github-action.md
-outputs: {}
+outputs: { }
runs:
using: 'docker'
image: docker://ghcr.io/apricote/releaser-pleaser:v0.6.1 # x-releaser-pleaser-version
@@ -31,7 +31,7 @@ runs:
- --forge=github
- --branch=${{ inputs.branch }}
- --extra-files="${{ inputs.extra-files }}"
- - ${{ inputs.update-package-json == 'true' && '--update-package-json' || '' }}
+ - --updaters="${{ inputs.updaters }}"
env:
GITHUB_TOKEN: "${{ inputs.token }}"
GITHUB_USER: "oauth2"
diff --git a/cmd/rp/cmd/run.go b/cmd/rp/cmd/run.go
index fa48cc0..202ba3d 100644
--- a/cmd/rp/cmd/run.go
+++ b/cmd/rp/cmd/run.go
@@ -2,6 +2,7 @@ package cmd
import (
"fmt"
+ "slices"
"strings"
"github.com/spf13/cobra"
@@ -21,12 +22,12 @@ var runCmd = &cobra.Command{
}
var (
- flagForge string
- flagBranch string
- flagOwner string
- flagRepo string
- flagExtraFiles string
- flagUpdatePackageJson bool
+ flagForge string
+ flagBranch string
+ flagOwner string
+ flagRepo string
+ flagExtraFiles string
+ flagUpdaters []string
)
func init() {
@@ -36,7 +37,7 @@ func init() {
runCmd.PersistentFlags().StringVar(&flagOwner, "owner", "", "")
runCmd.PersistentFlags().StringVar(&flagRepo, "repo", "", "")
runCmd.PersistentFlags().StringVar(&flagExtraFiles, "extra-files", "", "")
- runCmd.PersistentFlags().BoolVar(&flagUpdatePackageJson, "update-package-json", false, "")
+ runCmd.PersistentFlags().StringSliceVar(&flagUpdaters, "updaters", []string{}, "")
}
func run(cmd *cobra.Command, _ []string) error {
@@ -49,7 +50,6 @@ func run(cmd *cobra.Command, _ []string) error {
"branch", flagBranch,
"owner", flagOwner,
"repo", flagRepo,
- "update-package-json", flagUpdatePackageJson,
)
var f forge.Forge
@@ -83,11 +83,19 @@ func run(cmd *cobra.Command, _ []string) error {
extraFiles := parseExtraFiles(flagExtraFiles)
- updaters := []updater.NewUpdater{updater.Generic}
-
- if flagUpdatePackageJson {
- logger.DebugContext(ctx, "package.json updater enabled")
- updaters = append(updaters, updater.PackageJson)
+ updaterNames := parseUpdaters(flagUpdaters)
+ updaters := []updater.Updater{}
+ for _, name := range updaterNames {
+ switch name {
+ case "generic":
+ updaters = append(updaters, updater.Generic(extraFiles))
+ case "changelog":
+ updaters = append(updaters, updater.Changelog())
+ case "packagejson":
+ updaters = append(updaters, updater.PackageJson())
+ default:
+ return fmt.Errorf("unknown updater: %s", name)
+ }
}
releaserPleaser := rp.New(
@@ -122,3 +130,22 @@ func parseExtraFiles(input string) []string {
return extraFiles
}
+
+func parseUpdaters(input []string) []string {
+ names := []string{"changelog", "generic"}
+
+ for _, u := range input {
+ if strings.HasPrefix(u, "-") {
+ name := u[1:]
+ names = slices.DeleteFunc(names, func(existingName string) bool { return existingName == name })
+ } else {
+ names = append(names, u)
+ }
+ }
+
+ // Make sure we only have unique updaters
+ slices.Sort(names)
+ names = slices.Compact(names)
+
+ return names
+}
diff --git a/cmd/rp/cmd/run_test.go b/cmd/rp/cmd/run_test.go
index d4cea7a..8354478 100644
--- a/cmd/rp/cmd/run_test.go
+++ b/cmd/rp/cmd/run_test.go
@@ -57,3 +57,43 @@ dir/Chart.yaml"`,
})
}
}
+
+func Test_parseUpdaters(t *testing.T) {
+ tests := []struct {
+ name string
+ input []string
+ want []string
+ }{
+ {
+ name: "empty",
+ input: []string{},
+ want: []string{"changelog", "generic"},
+ },
+ {
+ name: "remove defaults",
+ input: []string{"-changelog", "-generic"},
+ want: []string{},
+ },
+ {
+ name: "remove unknown is ignored",
+ input: []string{"-fooo"},
+ want: []string{"changelog", "generic"},
+ },
+ {
+ name: "add new entry",
+ input: []string{"bar"},
+ want: []string{"bar", "changelog", "generic"},
+ },
+ {
+ name: "duplicates are removed",
+ input: []string{"bar", "bar", "changelog"},
+ want: []string{"bar", "changelog", "generic"},
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got := parseUpdaters(tt.input)
+ assert.Equal(t, tt.want, got)
+ })
+ }
+}
diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md
index b13bf24..0a22df1 100644
--- a/docs/SUMMARY.md
+++ b/docs/SUMMARY.md
@@ -25,6 +25,7 @@
- [Pull Request Options](reference/pr-options.md)
- [GitHub Action](reference/github-action.md)
- [GitLab CI/CD Component](reference/gitlab-cicd-component.md)
+- [Updaters](reference/updaters.md)
---
diff --git a/docs/guides/updating-arbitrary-files.md b/docs/guides/updating-arbitrary-files.md
index d4b65bf..e7df9a5 100644
--- a/docs/guides/updating-arbitrary-files.md
+++ b/docs/guides/updating-arbitrary-files.md
@@ -10,7 +10,8 @@ In some situations it makes sense to have the current version committed in files
## Markers
-The line that needs to be updated must have the marker `x-releaser-pleaser-version` somewhere after the version that should be updated.
+The line that needs to be updated must have the marker
+`x-releaser-pleaser-version` somewhere after the version that should be updated.
For example:
@@ -28,7 +29,8 @@ You need to tell `releaser-pleaser` which files it should update. This happens t
### GitHub Action
-In the GitHub Action you can set the `extra-files` input with a list of the files. They need to be formatted as a single multi-line string with one file path per line:
+In the GitHub Action you can set the
+`extra-files` input with a list of the files. They need to be formatted as a single multi-line string with one file path per line:
```yaml
jobs:
@@ -44,7 +46,8 @@ jobs:
### GitLab CI/CD Component
-In the GitLab CI/CD Component you can set the `extra-files` input with a list of files. They need to be formatted as a single multi-line string with one file path per line:
+In the GitLab CI/CD Component you can set the
+`extra-files` input with a list of files. They need to be formatted as a single multi-line string with one file path per line:
```yaml
include:
@@ -61,3 +64,4 @@ include:
- **Reference**
- [GitHub Action](../reference/github-action.md#inputs)
- [GitLab CI/CD Component](../reference/gitlab-cicd-component.md#inputs)
+ - [Updaters](../reference/updaters.md#generic-updater)
diff --git a/docs/reference/github-action.md b/docs/reference/github-action.md
index 3a849dc..c5d595a 100644
--- a/docs/reference/github-action.md
+++ b/docs/reference/github-action.md
@@ -8,18 +8,20 @@ The action is available as `apricote/releaser-pleaser` on GitHub.com.
The `apricote/releaser-pleaser` action is released together with `releaser-pleaser` and they share the version number.
-The action does not support floating tags (e.g. `v1`) right now ([#31](https://github.com/apricote/releaser-pleaser/issues/31)). You have to use the full version or commit SHA instead: `apricote/releaser-pleaser@v0.2.0`.
+The action does not support floating tags (e.g.
+`v1`) right now ([#31](https://github.com/apricote/releaser-pleaser/issues/31)). You have to use the full version or commit SHA instead:
+`apricote/releaser-pleaser@v0.2.0`.
## Inputs
The following inputs are supported by the `apricote/releaser-pleaser` GitHub Action.
-| Input | Description | Default | Example |
-| --------------------- | :------------------------------------------------------ | --------------: | -------------------------------------------------------------------: |
-| `branch` | This branch is used as the target for releases. | `main` | `master` |
-| `token` | GitHub token for creating and updating release PRs | `$GITHUB_TOKEN` | `${{secrets.RELEASER_PLEASER_TOKEN}}` |
-| `extra-files` | List of files that are scanned for version references. | `""` |
version/version.go
deploy/deployment.yaml
|
-| `update-package-json` | Update version field in package.json file. | `false` | `true` |
+| Input | Description | Default | Example |
+|---------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------:|---------------------------------------------------------------------:|
+| `branch` | This branch is used as the target for releases. | `main` | `master` |
+| `token` | GitHub token for creating and updating release PRs | `$GITHUB_TOKEN` | `${{secrets.RELEASER_PLEASER_TOKEN}}` |
+| `extra-files` | List of files that are scanned for version references by the generic updater. | `""` | version/version.go
deploy/deployment.yaml
|
+| `updaters` | List of updaters that are run. Default updaters can be removed by specifying them as -name. Multiple updaters should be concatenated with a comma. Default Updaters: changelog,generic | `""` | `-generic,packagejson` |
## Outputs
diff --git a/docs/reference/gitlab-cicd-component.md b/docs/reference/gitlab-cicd-component.md
index 01a6fc2..3080fcf 100644
--- a/docs/reference/gitlab-cicd-component.md
+++ b/docs/reference/gitlab-cicd-component.md
@@ -18,11 +18,11 @@ The component does not support floating tags (e.g.
The following inputs are supported by the component.
-| Input | Description | Default | Example |
-| ---------------------- | :-------------------------------------------------------- | ------: | -------------------------------------------------------------------: |
-| `branch` | This branch is used as the target for releases. | `main` | `master` |
-| `token` (**required**) | GitLab access token for creating and updating release PRs | | `$RELEASER_PLEASER_TOKEN` |
-| `extra-files` | List of files that are scanned for version references. | `""` | version/version.go
deploy/deployment.yaml
|
-| `update-package-json` | Update version field in package.json file. | `false` | `true` |
-| `stage` | Stage the job runs in. Must exists. | `build` | `test` |
-| `needs` | Other jobs the releaser-pleaser job depends on. | `[]` | - validate-foo
- prepare-bar
|
+| Input | Description | Default | Example |
+|------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------:|---------------------------------------------------------------------:|
+| `branch` | This branch is used as the target for releases. | `main` | `master` |
+| `token` (**required**) | GitLab access token for creating and updating release PRs | | `$RELEASER_PLEASER_TOKEN` |
+| `extra-files` | List of files that are scanned for version references by the generic updater. | `""` | version/version.go
deploy/deployment.yaml
|
+| `updaters` | List of updaters that are run. Default updaters can be removed by specifying them as -name. Multiple updaters should be concatenated with a comma. Default Updaters: changelog,generic | `""` | `-generic,packagejson` |
+| `stage` | Stage the job runs in. Must exists. | `build` | `test` |
+| `needs` | Other jobs the releaser-pleaser job depends on. | `[]` | - validate-foo
- prepare-bar
|
diff --git a/docs/reference/glossary.md b/docs/reference/glossary.md
index 543f970..8966f55 100644
--- a/docs/reference/glossary.md
+++ b/docs/reference/glossary.md
@@ -2,17 +2,21 @@
### Changelog
-The Changelog is a file in the repository (`CHANGELOG.md`) that contains the [Release Notes](#release-notes) for every release of that repository. Usually, new releases are added at the top of the file.
+The Changelog is a file in the repository (
+`CHANGELOG.md`) that contains the [Release Notes](#release-notes) for every release of that repository. Usually, new releases are added at the top of the file.
### Conventional Commits
-[Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) is a specification for commit messages. It is the only supported commit message schema in `releaser-pleaser`. Follow the link to learn more.
+[Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) is a specification for commit messages. It is the only supported commit message schema in
+`releaser-pleaser`. Follow the link to learn more.
### Forge
-A **forge** is a web-based collaborative software platform for both developing and sharing computer applications.[^wp-forge]
+A **forge
+** is a web-based collaborative software platform for both developing and sharing computer applications.[^wp-forge]
-Right now only **GitHub** is supported. We plan to support **GitLab** in the future ([#4](https://github.com/apricote/releaser-pleaser/issues/4)). For other forges like Forgejo or Gitea, please open an issue and submit a pull request.
+Right now only **GitHub** is supported. We plan to support **GitLab
+** in the future ([#4](https://github.com/apricote/releaser-pleaser/issues/4)). For other forges like Forgejo or Gitea, please open an issue and submit a pull request.
[^wp-forge]: Quote from [Wikipedia "Forge (software)"]()
@@ -24,7 +28,8 @@ In `releaser-pleaser` Markdown is used for most texts.
### Pre-release
-Pre-releases are a concept of [SemVer](#semantic-versioning-semver). They follow the normal versioning schema but use a suffix out of `-alpha.X`, `-beta.X` and `-rc.X`.
+Pre-releases are a concept of [SemVer](#semantic-versioning-semver). They follow the normal versioning schema but use a suffix out of
+`-alpha.X`, `-beta.X` and `-rc.X`.
Pre-releases are not considered "stable" and are usually not recommended for most users.
@@ -32,7 +37,9 @@ Learn more in the [Pre-releases](../guides/pre-releases.md) guide.
### Release Pull Request
-A Release Pull Request is opened by `releaser-pleaser` whenever it finds releasable commits in your project. It proposes a new version number and the Changelog. Once it is merged, `releaser-pleaser` creates a matching release.
+A Release Pull Request is opened by
+`releaser-pleaser` whenever it finds releasable commits in your project. It proposes a new version number and the Changelog. Once it is merged,
+`releaser-pleaser` creates a matching release.
Learn more in the [Release Pull Request](../explanation/release-pr.md) explanation.
@@ -44,4 +51,11 @@ Learn more in the [Release Notes customization](../guides/release-notes.md) guid
### Semantic Versioning (SemVer)
-[Semantic Versioning](https://semver.org/) is a specification for version numbers. It is the only supported versioning schema in `releaser-pleaser`. Follow the link to learn more.
+[Semantic Versioning](https://semver.org/) is a specification for version numbers. It is the only supported versioning schema in
+`releaser-pleaser`. Follow the link to learn more.
+
+### Updater
+
+Updaters can update or create files that will be included in [Release Pull Request](#release-pull-request). Examples of Updaters are
+`changelog` for `CHANGELOG.md`, `generic` that can update arbitrary files and
+`packagejson` that knows how to update Node.JS `package.json` files.
\ No newline at end of file
diff --git a/docs/reference/updaters.md b/docs/reference/updaters.md
new file mode 100644
index 0000000..6bafff4
--- /dev/null
+++ b/docs/reference/updaters.md
@@ -0,0 +1,33 @@
+# Updaters
+
+There are different updater for different purposes available.
+
+They each have a name and may be enabled by default. You can configure which updaters are used through the
+`updaters` input on GitHub Actions and GitLab CI/CD. This is a comma-delimited list of updaters that should be enabled, for updaters that are enabled by default you can remove them by adding a minus before its name:
+
+```
+updaters: -generic,packagejson
+```
+
+## Changelog
+
+- **Name**: `changelog`
+- **Default**: enabled
+
+This updater creates the `CHANGELOG.md` file and adds new release notes to it.
+
+## Generic Updater
+
+- **Name**: `generic`
+- **Default**: enabled
+
+This updater can update any file and only needs a marker on the line. It is enabled by default.
+
+Learn more about this updater in ["Updating arbitrary files"](../guides/updating-arbitrary-files.md).
+
+## Node.js `package.json` Updater
+
+- **Name**: `packagejson`
+- **Default**: disabled
+
+This updater can update the `version` field in Node.js `package.json` files. The updater is disabled by default.
diff --git a/internal/git/git.go b/internal/git/git.go
index b9c750e..ad5c0a3 100644
--- a/internal/git/git.go
+++ b/internal/git/git.go
@@ -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)
diff --git a/internal/updater/changelog.go b/internal/updater/changelog.go
index 8d6d68c..a7c7506 100644
--- a/internal/updater/changelog.go
+++ b/internal/updater/changelog.go
@@ -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")
diff --git a/internal/updater/changelog_test.go b/internal/updater/changelog_test.go
index 35878b9..c0becb5 100644
--- a/internal/updater/changelog_test.go
+++ b/internal/updater/changelog_test.go
@@ -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)
})
}
}
diff --git a/internal/updater/generic.go b/internal/updater/generic.go
index 1883c1a..11b21a4 100644
--- a/internal/updater/generic.go
+++ b/internal/updater/generic.go
@@ -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")
diff --git a/internal/updater/generic_test.go b/internal/updater/generic_test.go
index 4cc8952..7c007a4 100644
--- a/internal/updater/generic_test.go
+++ b/internal/updater/generic_test.go
@@ -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)
})
}
}
diff --git a/internal/updater/packagejson.go b/internal/updater/packagejson.go
index 58f2cc3..0fcb8a5 100644
--- a/internal/updater/packagejson.go
+++ b/internal/updater/packagejson.go
@@ -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
}
}
diff --git a/internal/updater/packagejson_test.go b/internal/updater/packagejson_test.go
index 4fd196e..9bff8b7 100644
--- a/internal/updater/packagejson_test.go
+++ b/internal/updater/packagejson_test.go
@@ -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)
})
}
}
diff --git a/internal/updater/updater.go b/internal/updater/updater.go
index f5fd677..6e27f37 100644
--- a/internal/updater/updater.go
+++ b/internal/updater/updater.go
@@ -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
diff --git a/internal/updater/updater_test.go b/internal/updater/updater_test.go
index 17162ef..5a90936 100644
--- a/internal/updater/updater_test.go
+++ b/internal/updater/updater_test.go
@@ -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)
}
diff --git a/releaserpleaser.go b/releaserpleaser.go
index a09aefe..b72b85f 100644
--- a/releaserpleaser.go
+++ b/releaserpleaser.go
@@ -34,10 +34,10 @@ type ReleaserPleaser struct {
commitParser commitparser.CommitParser
versioning versioning.Strategy
extraFiles []string
- updaters []updater.NewUpdater
+ updaters []updater.Updater
}
-func New(forge forge.Forge, logger *slog.Logger, targetBranch string, commitParser commitparser.CommitParser, versioningStrategy versioning.Strategy, extraFiles []string, updaters []updater.NewUpdater) *ReleaserPleaser {
+func New(forge forge.Forge, logger *slog.Logger, targetBranch string, commitParser commitparser.CommitParser, versioningStrategy versioning.Strategy, extraFiles []string, updaters []updater.Updater) *ReleaserPleaser {
return &ReleaserPleaser{
forge: forge,
logger: logger,
@@ -281,16 +281,12 @@ func (rp *ReleaserPleaser) runReconcileReleasePR(ctx context.Context) error {
// Info for updaters
info := updater.ReleaseInfo{Version: nextVersion, ChangelogEntry: changelogEntry}
- err = repo.UpdateFile(ctx, updater.ChangelogFile, true, updater.WithInfo(info, updater.Changelog))
- if err != nil {
- return fmt.Errorf("failed to update changelog file: %w", err)
- }
-
- for _, path := range rp.extraFiles {
- // TODO: Check for missing files
- err = repo.UpdateFile(ctx, path, false, updater.WithInfo(info, rp.updaters...))
- if err != nil {
- return fmt.Errorf("failed to run file updater: %w", err)
+ for _, u := range rp.updaters {
+ for _, file := range u.Files() {
+ err = repo.UpdateFile(ctx, file, u.CreateNewFiles(), u.Update(info))
+ if err != nil {
+ return fmt.Errorf("failed to run updater %T: %w", u, err)
+ }
}
}
diff --git a/templates/run.yml b/templates/run.yml
index 66037b1..79459d9 100644
--- a/templates/run.yml
+++ b/templates/run.yml
@@ -9,12 +9,12 @@ spec:
description: "GitLab token for creating and updating release MRs."
extra-files:
- description: 'List of files that are scanned for version references.'
+ description: 'List of files that are scanned for version references by the generic updater.'
default: ""
- update-package-json:
- description: 'Update version field in package.json file.'
- default: "false"
+ updaters:
+ description: "List of updaters that are run. Default updaters can be removed by specifying them as -name. Multiple updaters should be concatenated with a comma. Default Updaters: changelog,generic"
+ default: ""
stage:
default: build
@@ -54,4 +54,4 @@ releaser-pleaser:
--forge=gitlab \
--branch=$[[ inputs.branch ]] \
--extra-files="$[[ inputs.extra-files ]]" \
- $([[ inputs.update-package-json == "true" ]] && echo "--update-package-json" || echo "")
+ --updaters="$[[ inputs.updaters ]]"