mirror of
https://github.com/apricote/releaser-pleaser.git
synced 2026-02-11 12:17:04 +00:00
feat: update version references in any files
This commit is contained in:
parent
589fdde401
commit
467adbe752
4 changed files with 122 additions and 18 deletions
|
|
@ -12,14 +12,19 @@ inputs:
|
|||
description: 'GitHub token for creating and grooming release PRs, defaults to using secrets.GITHUB_TOKEN'
|
||||
required: false
|
||||
default: ${{ github.token }}
|
||||
extra-files:
|
||||
description: 'List of files that are scanned for version references.'
|
||||
required: false
|
||||
default: ""
|
||||
outputs: {}
|
||||
runs:
|
||||
using: 'docker'
|
||||
image: ghcr.io/apricote/releaser-pleaser:v0.1.0
|
||||
image: ghcr.io/apricote/releaser-pleaser:v0.1.0 # x-releaser-pleaser-version
|
||||
args:
|
||||
- run
|
||||
- --forge=github
|
||||
- --branch=${{ inputs.branch }}
|
||||
- --extra-files="${{ inputs.extra-files }}"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ inputs.token }}
|
||||
GITHUB_USER: "oauth2"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
rp "github.com/apricote/releaser-pleaser"
|
||||
|
|
@ -17,6 +19,7 @@ var (
|
|||
flagBranch string
|
||||
flagOwner string
|
||||
flagRepo string
|
||||
flagExtraFiles string
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
|
@ -28,6 +31,7 @@ func init() {
|
|||
runCmd.PersistentFlags().StringVar(&flagBranch, "branch", "main", "")
|
||||
runCmd.PersistentFlags().StringVar(&flagOwner, "owner", "", "")
|
||||
runCmd.PersistentFlags().StringVar(&flagRepo, "repo", "", "")
|
||||
runCmd.PersistentFlags().StringVar(&flagExtraFiles, "extra-files", "", "")
|
||||
}
|
||||
|
||||
func run(cmd *cobra.Command, _ []string) error {
|
||||
|
|
@ -59,7 +63,31 @@ func run(cmd *cobra.Command, _ []string) error {
|
|||
})
|
||||
}
|
||||
|
||||
releaserPleaser := rp.New(forge, logger, flagBranch, rp.NewConventionalCommitsParser(), rp.SemVerNextVersion)
|
||||
extraFiles := parseExtraFiles(flagExtraFiles)
|
||||
|
||||
releaserPleaser := rp.New(
|
||||
forge,
|
||||
logger,
|
||||
flagBranch,
|
||||
rp.NewConventionalCommitsParser(),
|
||||
rp.SemVerNextVersion,
|
||||
extraFiles,
|
||||
[]rp.Updater{&rp.GenericUpdater{}},
|
||||
)
|
||||
|
||||
return releaserPleaser.Run(ctx)
|
||||
}
|
||||
|
||||
func parseExtraFiles(input string) []string {
|
||||
lines := strings.Split(input, "\n")
|
||||
|
||||
extraFiles := make([]string, 0, len(lines))
|
||||
for _, line := range lines {
|
||||
line = strings.TrimSpace(line)
|
||||
if len(line) > 0 {
|
||||
extraFiles = append(extraFiles, line)
|
||||
}
|
||||
}
|
||||
|
||||
return extraFiles
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,9 @@ package rp
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"log/slog"
|
||||
"os"
|
||||
|
||||
"github.com/go-git/go-git/v5"
|
||||
"github.com/go-git/go-git/v5/config"
|
||||
|
|
@ -20,15 +22,19 @@ type ReleaserPleaser struct {
|
|||
targetBranch string
|
||||
commitParser CommitParser
|
||||
nextVersion VersioningStrategy
|
||||
extraFiles []string
|
||||
updaters []Updater
|
||||
}
|
||||
|
||||
func New(forge Forge, logger *slog.Logger, targetBranch string, commitParser CommitParser, versioningStrategy VersioningStrategy) *ReleaserPleaser {
|
||||
func New(forge Forge, logger *slog.Logger, targetBranch string, commitParser CommitParser, versioningStrategy VersioningStrategy, extraFiles []string, updaters []Updater) *ReleaserPleaser {
|
||||
return &ReleaserPleaser{
|
||||
forge: forge,
|
||||
logger: logger,
|
||||
targetBranch: targetBranch,
|
||||
commitParser: commitParser,
|
||||
nextVersion: versioningStrategy,
|
||||
extraFiles: extraFiles,
|
||||
updaters: updaters,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -236,21 +242,60 @@ func (rp *ReleaserPleaser) runReconcileReleasePR(ctx context.Context) error {
|
|||
return fmt.Errorf("failed to check out branch: %w", err)
|
||||
}
|
||||
|
||||
err = RunUpdater(ctx, nextVersion, worktree)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to update files with new version: %w", err)
|
||||
}
|
||||
|
||||
changelogEntry, err := NewChangelogEntry(analyzedCommits, nextVersion, rp.forge.ReleaseURL(nextVersion), releaseOverrides.Prefix, releaseOverrides.Suffix)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to build changelog entry: %w", err)
|
||||
}
|
||||
|
||||
// TODO: Fold UpdateChangelogFile into generalized Updater
|
||||
err = UpdateChangelogFile(worktree, changelogEntry)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to update changelog file: %w", err)
|
||||
}
|
||||
|
||||
for _, extraFile := range rp.extraFiles {
|
||||
_, err := worktree.Filesystem.Stat(extraFile)
|
||||
if err != nil {
|
||||
// TODO: Check for non existing file or dirs
|
||||
return fmt.Errorf("failed to run file updater: %w", err)
|
||||
}
|
||||
|
||||
file, err := worktree.Filesystem.OpenFile(extraFile, os.O_RDWR, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
content, err := io.ReadAll(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
updatedContent := string(content)
|
||||
|
||||
for _, updater := range rp.updaters {
|
||||
updatedContent = updater.UpdateContent(updatedContent, nextVersion)
|
||||
}
|
||||
|
||||
err = file.Truncate(0)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to replace file content: %w", err)
|
||||
}
|
||||
_, err = file.Seek(0, 0)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to replace file content: %w", err)
|
||||
}
|
||||
_, err = file.Write([]byte(updatedContent))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to replace file content: %w", err)
|
||||
}
|
||||
|
||||
_, err = worktree.Add(extraFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to add updated file to git worktree: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
releaseCommitMessage := fmt.Sprintf("chore(%s): release %s", rp.targetBranch, nextVersion)
|
||||
releaseCommitHash, err := worktree.Commit(releaseCommitMessage, &git.CommitOptions{
|
||||
Author: GitSignature(),
|
||||
|
|
|
|||
38
updater.go
38
updater.go
|
|
@ -1,12 +1,38 @@
|
|||
package rp
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/go-git/go-git/v5"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func RunUpdater(ctx context.Context, version string, worktree *git.Worktree) error {
|
||||
// TODO: Implement updater for Go,Python,ExtraFilesMarkers
|
||||
return nil
|
||||
const (
|
||||
InlineUpdateMarker = "x-releaser-pleaser-version"
|
||||
)
|
||||
|
||||
var (
|
||||
SemVerRegex = regexp.MustCompile(`(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)(-(?<preRelease>[\w.]+))?(\+(?<build>[-\w.]+))?`)
|
||||
)
|
||||
|
||||
type Updater interface {
|
||||
UpdateContent(content, version string) string
|
||||
}
|
||||
|
||||
type GenericUpdater struct{}
|
||||
|
||||
func (u *GenericUpdater) UpdateContent(content, version string) string {
|
||||
// TODO: use buffered input/output
|
||||
output := strings.Builder{}
|
||||
output.Grow(len(content))
|
||||
for _, line := range strings.Split(content, "\n") {
|
||||
if strings.Contains(line, InlineUpdateMarker) {
|
||||
// We strip the "v" prefix to avoid adding/removing it from the users input.
|
||||
line = SemVerRegex.ReplaceAllLiteralString(line, strings.TrimPrefix(version, "v"))
|
||||
}
|
||||
|
||||
output.WriteString(line)
|
||||
// TODO: Fix added newline
|
||||
output.WriteByte('\n')
|
||||
}
|
||||
|
||||
return output.String()
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue