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
10
action.yml
10
action.yml
|
|
@ -14,13 +14,13 @@ 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: { }
|
||||
runs:
|
||||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package cmd
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
|
@ -26,7 +27,7 @@ var (
|
|||
flagOwner string
|
||||
flagRepo string
|
||||
flagExtraFiles string
|
||||
flagUpdatePackageJson bool
|
||||
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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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. | `""` | <pre><code>version/version.go<br>deploy/deployment.yaml</code></pre> |
|
||||
| `update-package-json` | Update version field in package.json file. | `false` | `true` |
|
||||
| `extra-files` | List of files that are scanned for version references by the generic updater. | `""` | <pre><code>version/version.go<br>deploy/deployment.yaml</code></pre> |
|
||||
| `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
|
||||
|
||||
|
|
|
|||
|
|
@ -19,10 +19,10 @@ 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. | `""` | <pre><code>version/version.go<br>deploy/deployment.yaml</code></pre> |
|
||||
| `update-package-json` | Update version field in package.json file. | `false` | `true` |
|
||||
| `extra-files` | List of files that are scanned for version references by the generic updater. | `""` | <pre><code>version/version.go<br>deploy/deployment.yaml</code></pre> |
|
||||
| `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. | `[]` | <pre><code>- validate-foo<br>- prepare-bar</code></pre> |
|
||||
|
|
|
|||
|
|
@ -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)"](<https://en.wikipedia.org/wiki/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.
|
||||
33
docs/reference/updaters.md
Normal file
33
docs/reference/updaters.md
Normal file
|
|
@ -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.
|
||||
|
|
@ -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))
|
||||
updatedContent, err := updateHook(string(content))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to run updater on file %s", path)
|
||||
}
|
||||
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,12 +6,19 @@ 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,
|
||||
|
|
@ -28,7 +35,6 @@ func TestChangelogUpdater_UpdateContent(t *testing.T) {
|
|||
|
||||
### Bazuuum
|
||||
`,
|
||||
filename: "CHANGELOG.md",
|
||||
info: ReleaseInfo{ChangelogEntry: "## v1.0.0\n\n- Version 1, juhu.\n"},
|
||||
want: `# Changelog
|
||||
|
||||
|
|
@ -49,7 +55,6 @@ func TestChangelogUpdater_UpdateContent(t *testing.T) {
|
|||
{
|
||||
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,
|
||||
|
|
@ -57,7 +62,7 @@ func TestChangelogUpdater_UpdateContent(t *testing.T) {
|
|||
}
|
||||
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",
|
||||
info: ReleaseInfo{
|
||||
Version: "v1.2.0",
|
||||
},
|
||||
|
|
@ -21,7 +28,6 @@ func TestGenericUpdater_UpdateContent(t *testing.T) {
|
|||
{
|
||||
name: "multiline line",
|
||||
content: "Foooo\n\v1.2.0\nv1.0.0 // x-releaser-pleaser-version\n",
|
||||
filename: "version.txt",
|
||||
info: ReleaseInfo{
|
||||
Version: "v1.2.0",
|
||||
},
|
||||
|
|
@ -31,7 +37,6 @@ func TestGenericUpdater_UpdateContent(t *testing.T) {
|
|||
{
|
||||
name: "invalid existing version",
|
||||
content: "1.0 // x-releaser-pleaser-version",
|
||||
filename: "version.txt",
|
||||
info: ReleaseInfo{
|
||||
Version: "v1.2.0",
|
||||
},
|
||||
|
|
@ -41,7 +46,6 @@ func TestGenericUpdater_UpdateContent(t *testing.T) {
|
|||
{
|
||||
name: "complicated line",
|
||||
content: "version: v1.2.0-alpha.1 => Awesome, isnt it? x-releaser-pleaser-version foobar",
|
||||
filename: "version.txt",
|
||||
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,38 +1,33 @@
|
|||
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",
|
||||
info: ReleaseInfo{
|
||||
Version: "v2.0.5",
|
||||
},
|
||||
want: `{"name":"test","version":"2.0.5"}`,
|
||||
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",
|
||||
info: ReleaseInfo{
|
||||
Version: "v2.0.0",
|
||||
},
|
||||
|
|
@ -42,7 +37,6 @@ func TestPackageJsonUpdater(t *testing.T) {
|
|||
{
|
||||
name: "invalid json",
|
||||
content: `not json`,
|
||||
filename: "package.json",
|
||||
info: ReleaseInfo{
|
||||
Version: "v2.0.0",
|
||||
},
|
||||
|
|
@ -52,7 +46,6 @@ func TestPackageJsonUpdater(t *testing.T) {
|
|||
{
|
||||
name: "json without version",
|
||||
content: `{"name":"test"}`,
|
||||
filename: "package.json",
|
||||
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
|
||||
|
||||
|
|
|
|||
|
|
@ -10,18 +10,17 @@ import (
|
|||
type updaterTestCase struct {
|
||||
name string
|
||||
content string
|
||||
filename 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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
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 update changelog file: %w", err)
|
||||
return fmt.Errorf("failed to run updater %T: %w", u, 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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 ]]"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue