diff --git a/.github/actions/setup-mdbook/action.yaml b/.github/actions/setup-mdbook/action.yaml new file mode 100644 index 0000000..23e0665 --- /dev/null +++ b/.github/actions/setup-mdbook/action.yaml @@ -0,0 +1,16 @@ +name: "Setup mdbook" +inputs: + version: + description: "mdbook version" + +runs: + using: composite + steps: + - name: Setup mdbook + shell: bash + env: + url: https://github.com/rust-lang/mdbook/releases/download/${{ inputs.version }}/mdbook-${{ inputs.version }}-x86_64-unknown-linux-gnu.tar.gz + run: | + mkdir mdbook + curl -sSL "$url" | tar -xz --directory=./mdbook + echo `pwd`/mdbook >> $GITHUB_PATH diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 5110561..83d07be 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -69,15 +69,6 @@ ': (?.+) # renovate: datasource=(?[a-z-]+) depName=(?[^\\s]+)(?: lookupName=(?[^\\s]+))?(?: versioning=(?[a-z-]+))?(?: extractVersion=(?[^\\s]+))?', ], }, - { - customType: 'regex', - managerFilePatterns: [ - '/.+\\.toml$/' - ], - matchStrings: [ - '= "(?.+)" # renovate: datasource=(?[a-z-]+) depName=(?[^\\s]+)(?: lookupName=(?[^\\s]+))?(?: versioning=(?[a-z-]+))?(?: extractVersion=(?[^\\s]+))?', - ], - } ], postUpdateOptions: [ 'gomodUpdateImportPaths', diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 65aed30..f0b8517 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -2,7 +2,7 @@ name: ci on: push: - branches: [ main ] + branches: [main] pull_request: jobs: @@ -10,29 +10,35 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - - uses: jdx/mise-action@5ac50f778e26fac95da98d50503682459e86d566 # v3 + - name: Set up Go + uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5 + with: + go-version-file: go.mod - name: Run golangci-lint uses: golangci/golangci-lint-action@4afd733a84b1f43292c63897423277bb7f4313a9 # v8 with: - install-mode: none + version: v2.4.0 # renovate: datasource=github-releases depName=golangci/golangci-lint args: --timeout 5m test: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - - uses: jdx/mise-action@5ac50f778e26fac95da98d50503682459e86d566 # v3 + - name: Set up Go + uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5 + with: + go-version-file: go.mod - name: Run tests run: go test -v -race -coverpkg=./... -coverprofile=coverage.txt ./... - name: Upload results to Codecov - uses: codecov/codecov-action@fdcc8476540edceab3de004e990f80d881c6cc00 # v5 + uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24 # v5 with: token: ${{ secrets.CODECOV_TOKEN }} flags: unit @@ -69,9 +75,12 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - - uses: jdx/mise-action@5ac50f778e26fac95da98d50503682459e86d566 # v3 + - name: Set up Go + uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5 + with: + go-version-file: go.mod - name: Run go mod tidy run: go mod tidy diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index b7c6dfe..f1fb5d1 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -13,10 +13,14 @@ jobs: id-token: write # To update the deployment status steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 with: lfs: "true" + - uses: ./.github/actions/setup-mdbook + with: + version: v0.4.52 # renovate: datasource=github-releases depName=rust-lang/mdbook + - name: Build Book working-directory: docs run: mdbook build @@ -25,7 +29,7 @@ jobs: uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5 - name: Upload artifact - uses: actions/upload-pages-artifact@7b1f4a764d45c48632c6b24a0339c27f5614fb0b # v4 + uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3 with: # Upload entire repository path: "docs/book" diff --git a/.github/workflows/mirror.yaml b/.github/workflows/mirror.yaml index 940d149..e287aed 100644 --- a/.github/workflows/mirror.yaml +++ b/.github/workflows/mirror.yaml @@ -11,7 +11,7 @@ jobs: REMOTE: mirror steps: - name: Checkout - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 with: # Need all to fetch all tags so we can push them fetch-depth: 0 diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 7a0c0df..6da204d 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -14,8 +14,12 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - - uses: jdx/mise-action@5ac50f778e26fac95da98d50503682459e86d566 # v3 + - name: Set up Go + uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5 + with: + go-version-file: go.mod + - uses: ko-build/setup-ko@d006021bd0c28d1ce33a07e7943d48b079944c8d # v0.9 - run: ko build --bare --tags ${{ github.ref_name }} github.com/apricote/releaser-pleaser/cmd/rp diff --git a/.github/workflows/releaser-pleaser.yaml b/.github/workflows/releaser-pleaser.yaml index e40d6cd..aa5097f 100644 --- a/.github/workflows/releaser-pleaser.yaml +++ b/.github/workflows/releaser-pleaser.yaml @@ -2,7 +2,7 @@ name: releaser-pleaser on: push: - branches: [ main ] + branches: [main] # Using pull_request_target to avoid tainting the actual release PR with code from open feature pull requests pull_request_target: types: @@ -17,7 +17,7 @@ concurrency: group: releaser-pleaser cancel-in-progress: true -permissions: { } +permissions: {} jobs: releaser-pleaser: @@ -25,15 +25,19 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 with: ref: main - - uses: jdx/mise-action@5ac50f778e26fac95da98d50503682459e86d566 # v3 + - name: Set up Go + uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5 + with: + go-version-file: go.mod # Build container image from current commit and replace image ref in `action.yml` # Without this, any new flags in `action.yml` would break the job in this repository until the new # version is released. But a new version can only be released if this job works. + - uses: ko-build/setup-ko@d006021bd0c28d1ce33a07e7943d48b079944c8d # v0.9 - run: ko build --bare --local --platform linux/amd64 --tags ci github.com/apricote/releaser-pleaser/cmd/rp - run: mkdir -p .github/actions/releaser-pleaser diff --git a/CHANGELOG.md b/CHANGELOG.md index 7038de1..1cb192f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,27 +1,5 @@ # Changelog -## [v0.7.0](https://github.com/apricote/releaser-pleaser/releases/tag/v0.7.0) - -### Highlights :sparkles: - -#### Update version in `package.json` - -Thanks to @Mattzi it is now possible to use `releaser-pleaser` in Javascript/Node.js projects with a `package.json` file. - -You can enable this with the option `updaters: packagejson` in the GitHub Actions / GitLab CI/CD config. - -All updaters, including the defaults `changelog` and `generic` can now be enabled and disabled through this field. You can find a full list in the [documentation](https://apricote.github.io/releaser-pleaser/reference/updaters.html). - -### Features - -- add updater for package.json (#213) -- highlight breaking changes in release notes (#234) - -### Bug Fixes - -- filter out empty updaters in input (#235) -- **github**: duplicate release pr when process is stopped at wrong moment (#236) - ## [v0.6.1](https://github.com/apricote/releaser-pleaser/releases/tag/v0.6.1) ### Bug Fixes diff --git a/action.yml b/action.yml index a6de20c..225e3cc 100644 --- a/action.yml +++ b/action.yml @@ -14,24 +14,19 @@ inputs: required: false default: ${{ github.token }} extra-files: - description: 'List of files that are scanned for version references by the generic updater.' - required: false - default: "" - 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" + description: 'List of files that are scanned for version references.' required: false default: "" # Remember to update docs/reference/github-action.md -outputs: { } +outputs: {} runs: using: 'docker' - image: docker://ghcr.io/apricote/releaser-pleaser:v0.7.0 # x-releaser-pleaser-version + image: docker://ghcr.io/apricote/releaser-pleaser:v0.6.1 # x-releaser-pleaser-version args: - run - --forge=github - --branch=${{ inputs.branch }} - --extra-files="${{ inputs.extra-files }}" - - --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 3d575b0..eef84e6 100644 --- a/cmd/rp/cmd/run.go +++ b/cmd/rp/cmd/run.go @@ -3,7 +3,6 @@ package cmd import ( "fmt" "log/slog" - "slices" "strings" "github.com/spf13/cobra" @@ -26,7 +25,6 @@ func newRunCommand() *cobra.Command { flagOwner string flagRepo string flagExtraFiles string - flagUpdaters []string flagAPIURL string flagAPIToken string @@ -94,21 +92,6 @@ func newRunCommand() *cobra.Command { extraFiles := parseExtraFiles(flagExtraFiles) - 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( f, logger, @@ -116,7 +99,7 @@ func newRunCommand() *cobra.Command { conventionalcommits.NewParser(logger), versioning.SemVer, extraFiles, - updaters, + []updater.NewUpdater{updater.Generic}, ) return releaserPleaser.Run(ctx) @@ -128,8 +111,6 @@ func newRunCommand() *cobra.Command { cmd.PersistentFlags().StringVar(&flagOwner, "owner", "", "") cmd.PersistentFlags().StringVar(&flagRepo, "repo", "", "") cmd.PersistentFlags().StringVar(&flagExtraFiles, "extra-files", "", "") - cmd.PersistentFlags().StringSliceVar(&flagUpdaters, "updaters", []string{}, "") - cmd.PersistentFlags().StringVar(&flagAPIURL, "api-url", "", "") cmd.PersistentFlags().StringVar(&flagAPIToken, "api-token", "", "") cmd.PersistentFlags().StringVar(&flagUsername, "username", "", "") @@ -156,26 +137,3 @@ func parseExtraFiles(input string) []string { return extraFiles } - -func parseUpdaters(input []string) []string { - names := []string{"changelog", "generic"} - - for _, u := range input { - if u == "" { - continue - } - - 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 4c6ceff..d4cea7a 100644 --- a/cmd/rp/cmd/run_test.go +++ b/cmd/rp/cmd/run_test.go @@ -57,48 +57,3 @@ 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"}, - }, - { - name: "remove empty entries", - input: []string{""}, - want: []string{"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 0a22df1..b13bf24 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -25,7 +25,6 @@ - [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 e7df9a5..d4b65bf 100644 --- a/docs/guides/updating-arbitrary-files.md +++ b/docs/guides/updating-arbitrary-files.md @@ -10,8 +10,7 @@ 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: @@ -29,8 +28,7 @@ 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: @@ -46,8 +44,7 @@ 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: @@ -64,4 +61,3 @@ 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 c5d595a..eec9789 100644 --- a/docs/reference/github-action.md +++ b/docs/reference/github-action.md @@ -8,20 +8,17 @@ 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 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` | +| 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
| ## Outputs diff --git a/docs/reference/gitlab-cicd-component.md b/docs/reference/gitlab-cicd-component.md index 3080fcf..b22d5b2 100644 --- a/docs/reference/gitlab-cicd-component.md +++ b/docs/reference/gitlab-cicd-component.md @@ -18,11 +18,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 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
| +| 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
| +| `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 8966f55..543f970 100644 --- a/docs/reference/glossary.md +++ b/docs/reference/glossary.md @@ -2,21 +2,17 @@ ### 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)"]() @@ -28,8 +24,7 @@ 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. @@ -37,9 +32,7 @@ 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. @@ -51,11 +44,4 @@ 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. - -### 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 +[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. diff --git a/docs/reference/updaters.md b/docs/reference/updaters.md deleted file mode 100644 index 6bafff4..0000000 --- a/docs/reference/updaters.md +++ /dev/null @@ -1,33 +0,0 @@ -# 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/go.mod b/go.mod index 3034969..c1ed9ec 100644 --- a/go.mod +++ b/go.mod @@ -2,14 +2,14 @@ module github.com/apricote/releaser-pleaser go 1.24 -toolchain go1.25.0 +toolchain go1.24.6 require ( codeberg.org/mvdkleijn/forgejo-sdk/forgejo/v2 v2.0.0-00010101000000-000000000000 github.com/blang/semver/v4 v4.0.0 github.com/go-git/go-billy/v5 v5.6.2 github.com/go-git/go-git/v5 v5.16.2 - github.com/google/go-github/v74 v74.0.0 + github.com/google/go-github/v72 v72.0.0 github.com/leodido/go-conventionalcommits v0.12.0 github.com/lmittmann/tint v1.1.2 github.com/spf13/cobra v1.9.1 diff --git a/go.sum b/go.sum index f0a4935..3431f15 100644 --- a/go.sum +++ b/go.sum @@ -48,8 +48,8 @@ github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUv github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/go-github/v74 v74.0.0 h1:yZcddTUn8DPbj11GxnMrNiAnXH14gNs559AsUpNpPgM= -github.com/google/go-github/v74 v74.0.0/go.mod h1:ubn/YdyftV80VPSI26nSJvaEsTOnsjrxG3o9kJhcyak= +github.com/google/go-github/v72 v72.0.0 h1:FcIO37BLoVPBO9igQQ6tStsv2asG4IPcYFi655PPvBM= +github.com/google/go-github/v72 v72.0.0/go.mod h1:WWtw8GMRiL62mvIquf1kO3onRHeWWKmK01qdCY8c5fg= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= diff --git a/internal/changelog/changelog.md.tpl b/internal/changelog/changelog.md.tpl index 0a73dd5..50907eb 100644 --- a/internal/changelog/changelog.md.tpl +++ b/internal/changelog/changelog.md.tpl @@ -1,5 +1,5 @@ {{define "entry" -}} -- {{ if .BreakingChange}}**BREAKING**: {{end}}{{ if .Scope }}**{{.Scope}}**: {{end}}{{.Description}} +- {{ if .Scope }}**{{.Scope}}**: {{end}}{{.Description}} {{ end }} {{- if not .Formatting.HideVersionTitle }} diff --git a/internal/changelog/changelog_test.go b/internal/changelog/changelog_test.go index e4fe52f..a969730 100644 --- a/internal/changelog/changelog_test.go +++ b/internal/changelog/changelog_test.go @@ -54,23 +54,6 @@ func Test_NewChangelogEntry(t *testing.T) { want: "## [1.0.0](https://example.com/1.0.0)\n\n### Features\n\n- Foobar!\n", wantErr: assert.NoError, }, - { - name: "single breaking change", - args: args{ - analyzedCommits: []commitparser.AnalyzedCommit{ - { - Commit: git.Commit{}, - Type: "feat", - Description: "Foobar!", - BreakingChange: true, - }, - }, - version: "1.0.0", - link: "https://example.com/1.0.0", - }, - want: "## [1.0.0](https://example.com/1.0.0)\n\n### Features\n\n- **BREAKING**: Foobar!\n", - wantErr: assert.NoError, - }, { name: "single fix", args: args{ diff --git a/internal/forge/github/github.go b/internal/forge/github/github.go index d01e529..3bff3e6 100644 --- a/internal/forge/github/github.go +++ b/internal/forge/github/github.go @@ -12,7 +12,7 @@ import ( "github.com/blang/semver/v4" "github.com/go-git/go-git/v5/plumbing/transport" "github.com/go-git/go-git/v5/plumbing/transport/http" - "github.com/google/go-github/v74/github" + "github.com/google/go-github/v72/github" "github.com/apricote/releaser-pleaser/internal/forge" "github.com/apricote/releaser-pleaser/internal/git" @@ -296,13 +296,6 @@ func (g *GitHub) PullRequestForBranch(ctx context.Context, branch string) (*rele } func (g *GitHub) CreatePullRequest(ctx context.Context, pr *releasepr.ReleasePullRequest) error { - // If the Pull Request is created without the labels releaser-pleaser will create a new PR in the run. The user may merge both and have duplicate entries in the changelog. - // We try to avoid this situation by checking for a cancelled context first, and then running both API calls without passing along any cancellations. - if ctx.Err() != nil { - return ctx.Err() - } - ctx = context.WithoutCancel(ctx) - ghPR, _, err := g.client.PullRequests.Create( ctx, g.options.Owner, g.options.Repo, &github.NewPullRequest{ @@ -316,6 +309,7 @@ func (g *GitHub) CreatePullRequest(ctx context.Context, pr *releasepr.ReleasePul return err } + // TODO: String ID? pr.ID = ghPR.GetNumber() err = g.SetPullRequestLabels(ctx, pr, []releasepr.Label{}, pr.Labels) diff --git a/internal/git/git.go b/internal/git/git.go index ad5c0a3..d1db11b 100644 --- a/internal/git/git.go +++ b/internal/git/git.go @@ -13,6 +13,8 @@ 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 ( @@ -117,7 +119,7 @@ func (r *Repository) Checkout(_ context.Context, branch string) error { return nil } -func (r *Repository) UpdateFile(_ context.Context, path string, create bool, updateHook func(string) (string, error)) error { +func (r *Repository) UpdateFile(_ context.Context, path string, create bool, updaters []updater.Updater) error { worktree, err := r.r.Worktree() if err != nil { return err @@ -139,9 +141,13 @@ func (r *Repository) UpdateFile(_ context.Context, path string, create bool, upd return err } - updatedContent, err := updateHook(string(content)) - if err != nil { - return fmt.Errorf("failed to run update hook on file %s", path) + updatedContent := string(content) + + for _, update := range updaters { + updatedContent, err = update(updatedContent) + if err != nil { + return fmt.Errorf("failed to run updater on file %s", path) + } } err = file.Truncate(0) diff --git a/internal/updater/changelog.go b/internal/updater/changelog.go index a7c7506..8bdb9f6 100644 --- a/internal/updater/changelog.go +++ b/internal/updater/changelog.go @@ -14,22 +14,7 @@ var ( ChangelogUpdaterHeaderRegex = regexp.MustCompile(`^# Changelog\n`) ) -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) { +func Changelog(info ReleaseInfo) Updater { return func(content string) (string, error) { headerIndex := ChangelogUpdaterHeaderRegex.FindStringIndex(content) if headerIndex == nil && len(content) != 0 { diff --git a/internal/updater/changelog_test.go b/internal/updater/changelog_test.go index c0becb5..917cd14 100644 --- a/internal/updater/changelog_test.go +++ b/internal/updater/changelog_test.go @@ -6,15 +6,7 @@ import ( "github.com/stretchr/testify/assert" ) -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) { +func TestChangelogUpdater_UpdateContent(t *testing.T) { tests := []updaterTestCase{ { name: "empty file", @@ -62,7 +54,7 @@ func TestChangelogUpdater_Update(t *testing.T) { } 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 11b21a4..b8d73b0 100644 --- a/internal/updater/generic.go +++ b/internal/updater/generic.go @@ -7,25 +7,7 @@ import ( var GenericUpdaterSemVerRegex = regexp.MustCompile(`\d+\.\d+\.\d+(-[\w.]+)?(.*x-releaser-pleaser-version)`) -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) { +func Generic(info ReleaseInfo) Updater { 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 7c007a4..e0a8d1d 100644 --- a/internal/updater/generic_test.go +++ b/internal/updater/generic_test.go @@ -6,15 +6,7 @@ import ( "github.com/stretchr/testify/assert" ) -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) { +func TestGenericUpdater_UpdateContent(t *testing.T) { tests := []updaterTestCase{ { name: "single line", @@ -55,7 +47,7 @@ func TestGenericUpdater_Update(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - runUpdaterTest(t, Generic([]string{"version.txt"}), tt) + runUpdaterTest(t, Generic, tt) }) } } diff --git a/internal/updater/packagejson.go b/internal/updater/packagejson.go deleted file mode 100644 index 0fcb8a5..0000000 --- a/internal/updater/packagejson.go +++ /dev/null @@ -1,39 +0,0 @@ -package updater - -import ( - "regexp" - "strings" -) - -// PackageJson creates an updater that modifies the version field in 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") - - // Regex to match "version": "..." with flexible whitespace and quote styles - versionRegex := regexp.MustCompile(`("version"\s*:\s*)"[^"]*"`) - - // Check if the file contains a version field - if !versionRegex.MatchString(content) { - return content, nil - } - - // Replace the version value while preserving the original formatting - return versionRegex.ReplaceAllString(content, `${1}"`+version+`"`), nil - } -} diff --git a/internal/updater/packagejson_test.go b/internal/updater/packagejson_test.go deleted file mode 100644 index 9bff8b7..0000000 --- a/internal/updater/packagejson_test.go +++ /dev/null @@ -1,62 +0,0 @@ -package updater - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -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"}`, - info: ReleaseInfo{ - Version: "v2.0.5", - }, - want: `{"name":"test","version":"2.0.5"}`, - 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}", - info: ReleaseInfo{ - Version: "v2.0.0", - }, - want: "{\n \"name\": \"test\",\n \"version\": \"2.0.0\",\n \"dependencies\": {\n \"foo\": \"^1.0.0\"\n }\n}", - wantErr: assert.NoError, - }, - { - name: "invalid json", - content: `not json`, - info: ReleaseInfo{ - Version: "v2.0.0", - }, - want: `not json`, - wantErr: assert.NoError, - }, - { - name: "json without version", - content: `{"name":"test"}`, - info: ReleaseInfo{ - Version: "v2.0.0", - }, - want: `{"name":"test"}`, - wantErr: assert.NoError, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - runUpdaterTest(t, PackageJson(), tt) - }) - } -} diff --git a/internal/updater/updater.go b/internal/updater/updater.go index 6e27f37..fb773b4 100644 --- a/internal/updater/updater.go +++ b/internal/updater/updater.go @@ -5,11 +5,7 @@ type ReleaseInfo struct { ChangelogEntry string } -type Updater interface { - Files() []string - CreateNewFiles() bool - Update(info ReleaseInfo) func(content string) (string, error) -} +type Updater func(string) (string, error) type NewUpdater func(ReleaseInfo) Updater diff --git a/internal/updater/updater_test.go b/internal/updater/updater_test.go index 5a90936..0c0c40e 100644 --- a/internal/updater/updater_test.go +++ b/internal/updater/updater_test.go @@ -15,10 +15,10 @@ type updaterTestCase struct { wantErr assert.ErrorAssertionFunc } -func runUpdaterTest(t *testing.T, u Updater, tt updaterTestCase) { +func runUpdaterTest(t *testing.T, constructor NewUpdater, tt updaterTestCase) { t.Helper() - got, err := u.Update(tt.info)(tt.content) + got, err := constructor(tt.info)(tt.content) if !tt.wantErr(t, err, fmt.Sprintf("Updater(%v, %v)", tt.content, tt.info)) { return } diff --git a/mise.toml b/mise.toml deleted file mode 100644 index 4618b9c..0000000 --- a/mise.toml +++ /dev/null @@ -1,25 +0,0 @@ -[tools] -go = "1.25.0" -golangci-lint = "v2.4.0" -goreleaser = "v2.9.0" -mdbook = "v0.4.52" # renovate: datasource=github-releases depName=rust-lang/mdbook -ko = "v0.18.0" # renovate: datasource=github-releases depName=ko-build/ko - -[settings] -# Experimental features are needed for the Go backend -experimental = true - -[tasks.lint] -run = "golangci-lint run" - -[tasks.test] -run = "go test -v -race ./..." - -[tasks.test-e2e] -run = "go test -tags e2e_forgejo -v -race ./test/e2e/forgejo" - -[tasks.e2e-forgejo-start] -run = "docker compose --project-directory ./test/e2e/forgejo up -d --wait" - -[tasks.e2e-forgejo-stop] -run = "docker compose --project-directory ./test/e2e/forgejo down" diff --git a/releaserpleaser.go b/releaserpleaser.go index b72b85f..a09aefe 100644 --- a/releaserpleaser.go +++ b/releaserpleaser.go @@ -34,10 +34,10 @@ type ReleaserPleaser struct { commitParser commitparser.CommitParser versioning versioning.Strategy extraFiles []string - updaters []updater.Updater + updaters []updater.NewUpdater } -func New(forge forge.Forge, logger *slog.Logger, targetBranch string, commitParser commitparser.CommitParser, versioningStrategy versioning.Strategy, extraFiles []string, updaters []updater.Updater) *ReleaserPleaser { +func New(forge forge.Forge, logger *slog.Logger, targetBranch string, commitParser commitparser.CommitParser, versioningStrategy versioning.Strategy, extraFiles []string, updaters []updater.NewUpdater) *ReleaserPleaser { return &ReleaserPleaser{ forge: forge, logger: logger, @@ -281,12 +281,16 @@ func (rp *ReleaserPleaser) runReconcileReleasePR(ctx context.Context) error { // Info for updaters info := updater.ReleaseInfo{Version: nextVersion, ChangelogEntry: changelogEntry} - 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) - } + 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) } } diff --git a/templates/run.yml b/templates/run.yml index 0d71f84..c18a330 100644 --- a/templates/run.yml +++ b/templates/run.yml @@ -9,11 +9,7 @@ spec: description: "GitLab token for creating and updating release MRs." extra-files: - description: 'List of files that are scanned for version references by the generic updater.' - default: "" - - 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" + description: 'List of files that are scanned for version references.' default: "" stage: @@ -44,7 +40,7 @@ releaser-pleaser: resource_group: releaser-pleaser image: - name: ghcr.io/apricote/releaser-pleaser:v0.7.0 # x-releaser-pleaser-version + name: ghcr.io/apricote/releaser-pleaser:v0.6.1 # x-releaser-pleaser-version entrypoint: [ "" ] variables: GITLAB_TOKEN: $[[ inputs.token ]] @@ -53,5 +49,4 @@ releaser-pleaser: rp run \ --forge=gitlab \ --branch=$[[ inputs.branch ]] \ - --extra-files="$[[ inputs.extra-files ]]" \ - --updaters="$[[ inputs.updaters ]]" + --extra-files="$[[ inputs.extra-files ]]" diff --git a/test/e2e/forgejo/forge.go b/test/e2e/forgejo/forge.go index c631cb8..692c0cd 100644 --- a/test/e2e/forgejo/forge.go +++ b/test/e2e/forgejo/forge.go @@ -43,7 +43,6 @@ func (f *TestForge) Init(ctx context.Context, runID string) error { func (f *TestForge) initUser(ctx context.Context, runID string) error { f.username = fmt.Sprintf(TestUserNameTemplate, runID) - //gosec:disable G204 if output, err := exec.CommandContext(ctx, "docker", "compose", "exec", "--user=1000", "forgejo", "forgejo", "admin", "user", "create", @@ -56,7 +55,6 @@ func (f *TestForge) initUser(ctx context.Context, runID string) error { return fmt.Errorf("failed to create forgejo user: %w", err) } - //gosec:disable G204 token, err := exec.CommandContext(ctx, "docker", "compose", "exec", "--user=1000", "forgejo", "forgejo", "admin", "user", "generate-access-token",