mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-04 12:40:11 +08:00
Add wails3 tool version
command
This commit is contained in:
parent
421b75ef21
commit
da0da5fc69
@ -80,7 +80,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Add `SetMenu()` on window to allow for setting a menu on a window by [@leaanthony](https://github.com/leaanthony)
|
||||
- Add Notification support by [@popaprozac] in [#4098](https://github.com/wailsapp/wails/pull/4098)
|
||||
- Add File Association support for mac by [@wimaha](https://github.com/wimaha) in [#4177](https://github.com/wailsapp/wails/pull/4177)
|
||||
|
||||
- Add `wails3 tool version` for semantic version bumping by [@leaanthony](https://github.com/leaanthony)
|
||||
### Fixed
|
||||
|
||||
- Fixed Windows+Linux Edit Menu issues by [@leaanthony](https://github.com/leaanthony) in [#3f78a3a](https://github.com/wailsapp/wails/commit/3f78a3a8ce7837e8b32242c8edbbed431c68c062)
|
||||
|
@ -325,6 +325,32 @@ Shows build information about the application.
|
||||
wails3 tool buildinfo
|
||||
```
|
||||
|
||||
### `tool version`
|
||||
Bumps a semantic version based on the provided flags.
|
||||
|
||||
```bash
|
||||
wails3 tool version [flags]
|
||||
```
|
||||
|
||||
#### Flags
|
||||
| Flag | Description | Default |
|
||||
|---------------|--------------------------------------------------|---------|
|
||||
| `-v` | Current version to bump | |
|
||||
| `-major` | Bump major version | `false` |
|
||||
| `-minor` | Bump minor version | `false` |
|
||||
| `-patch` | Bump patch version | `false` |
|
||||
| `-prerelease` | Bump prerelease version (e.g., alpha.5 to alpha.6) | `false` |
|
||||
|
||||
The command follows the precedence order: major > minor > patch > prerelease. It preserves the "v" prefix if present in the input version, as well as any prerelease and metadata components.
|
||||
|
||||
Example usage:
|
||||
```bash
|
||||
wails3 tool version -v 1.2.3 -major # Output: 2.0.0
|
||||
wails3 tool version -v v1.2.3 -minor # Output: v1.3.0
|
||||
wails3 tool version -v 1.2.3-alpha -patch # Output: 1.2.4-alpha
|
||||
wails3 tool version -v v3.0.0-alpha.5 -prerelease # Output: v3.0.0-alpha.6
|
||||
```
|
||||
|
||||
### `tool package`
|
||||
Generates Linux packages (deb, rpm, archlinux).
|
||||
|
||||
|
@ -79,6 +79,7 @@ func main() {
|
||||
tool.NewSubCommandFunction("cp", "Copy files", commands.Cp)
|
||||
tool.NewSubCommandFunction("buildinfo", "Show Build Info", commands.BuildInfo)
|
||||
tool.NewSubCommandFunction("package", "Generate Linux packages (deb, rpm, archlinux)", commands.ToolPackage)
|
||||
tool.NewSubCommandFunction("version", "Bump semantic version", commands.ToolVersion)
|
||||
|
||||
app.NewSubCommandFunction("version", "Print the version", commands.Version)
|
||||
app.NewSubCommand("sponsor", "Sponsor the project").Action(openSponsor)
|
||||
|
123
v3/internal/commands/tool_version.go
Normal file
123
v3/internal/commands/tool_version.go
Normal file
@ -0,0 +1,123 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/wailsapp/wails/v3/internal/github"
|
||||
)
|
||||
|
||||
type ToolVersionOptions struct {
|
||||
Version string `name:"v" description:"Current version to bump"`
|
||||
Major bool `name:"major" description:"Bump major version"`
|
||||
Minor bool `name:"minor" description:"Bump minor version"`
|
||||
Patch bool `name:"patch" description:"Bump patch version"`
|
||||
Prerelease bool `name:"prerelease" description:"Bump prerelease version (e.g., alpha.5 to alpha.6)"`
|
||||
}
|
||||
|
||||
// bumpPrerelease increments the numeric part of a prerelease string
|
||||
// For example, "alpha.5" becomes "alpha.6"
|
||||
func bumpPrerelease(prerelease string) string {
|
||||
// If prerelease is empty, return it as is
|
||||
if prerelease == "" {
|
||||
return prerelease
|
||||
}
|
||||
|
||||
// Split the prerelease string by dots
|
||||
parts := strings.Split(prerelease, ".")
|
||||
|
||||
// If there's only one part (e.g., "alpha"), return it as is
|
||||
if len(parts) == 1 {
|
||||
return prerelease
|
||||
}
|
||||
|
||||
// Try to parse the last part as a number
|
||||
lastPart := parts[len(parts)-1]
|
||||
num, err := strconv.Atoi(lastPart)
|
||||
if err != nil {
|
||||
// If the last part is not a number, return the prerelease as is
|
||||
return prerelease
|
||||
}
|
||||
|
||||
// Increment the number
|
||||
num++
|
||||
|
||||
// Replace the last part with the incremented number
|
||||
parts[len(parts)-1] = strconv.Itoa(num)
|
||||
|
||||
// Join the parts back together
|
||||
return strings.Join(parts, ".")
|
||||
}
|
||||
|
||||
// ToolVersion bumps a semantic version based on the provided flags
|
||||
func ToolVersion(options *ToolVersionOptions) error {
|
||||
DisableFooter = true
|
||||
|
||||
if options.Version == "" {
|
||||
return fmt.Errorf("please provide a version using the -v flag")
|
||||
}
|
||||
|
||||
// Check if the version has a "v" prefix
|
||||
hasVPrefix := false
|
||||
versionStr := options.Version
|
||||
if len(versionStr) > 0 && versionStr[0] == 'v' {
|
||||
hasVPrefix = true
|
||||
versionStr = versionStr[1:]
|
||||
}
|
||||
|
||||
// Parse the current version
|
||||
semver, err := github.NewSemanticVersion(versionStr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid version format: %v", err)
|
||||
}
|
||||
|
||||
// Get the current version components
|
||||
major := semver.Version.Major()
|
||||
minor := semver.Version.Minor()
|
||||
patch := semver.Version.Patch()
|
||||
prerelease := semver.Version.Prerelease()
|
||||
metadata := semver.Version.Metadata()
|
||||
|
||||
// Check if at least one flag is specified
|
||||
if !options.Major && !options.Minor && !options.Patch && !options.Prerelease {
|
||||
return fmt.Errorf("please specify one of -major, -minor, -patch, or -prerelease")
|
||||
}
|
||||
|
||||
// Bump the version based on the flags (major takes precedence over minor, which takes precedence over patch)
|
||||
if options.Major {
|
||||
major++
|
||||
minor = 0
|
||||
patch = 0
|
||||
} else if options.Minor {
|
||||
minor++
|
||||
patch = 0
|
||||
} else if options.Patch {
|
||||
patch++
|
||||
} else if options.Prerelease {
|
||||
// If only prerelease flag is specified, bump the prerelease version
|
||||
if prerelease == "" {
|
||||
return fmt.Errorf("cannot bump prerelease version: no prerelease part in the version")
|
||||
}
|
||||
prerelease = bumpPrerelease(prerelease)
|
||||
}
|
||||
|
||||
// Format the new version
|
||||
newVersion := fmt.Sprintf("%d.%d.%d", major, minor, patch)
|
||||
if prerelease != "" {
|
||||
newVersion += "-" + prerelease
|
||||
}
|
||||
if metadata != "" {
|
||||
newVersion += "+" + metadata
|
||||
}
|
||||
|
||||
// Add the "v" prefix back if it was present in the input
|
||||
if hasVPrefix {
|
||||
newVersion = "v" + newVersion
|
||||
}
|
||||
|
||||
// Print the new version
|
||||
fmt.Println(newVersion)
|
||||
|
||||
return nil
|
||||
}
|
231
v3/internal/commands/tool_version_test.go
Normal file
231
v3/internal/commands/tool_version_test.go
Normal file
@ -0,0 +1,231 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestToolVersion(t *testing.T) {
|
||||
// Create a table of test cases
|
||||
testCases := []struct {
|
||||
name string
|
||||
options ToolVersionOptions
|
||||
expectedOutput string
|
||||
expectedError bool
|
||||
}{
|
||||
{
|
||||
name: "Bump major version",
|
||||
options: ToolVersionOptions{
|
||||
Version: "1.2.3",
|
||||
Major: true,
|
||||
},
|
||||
expectedOutput: "2.0.0",
|
||||
expectedError: false,
|
||||
},
|
||||
{
|
||||
name: "Bump minor version",
|
||||
options: ToolVersionOptions{
|
||||
Version: "1.2.3",
|
||||
Minor: true,
|
||||
},
|
||||
expectedOutput: "1.3.0",
|
||||
expectedError: false,
|
||||
},
|
||||
{
|
||||
name: "Bump patch version",
|
||||
options: ToolVersionOptions{
|
||||
Version: "1.2.3",
|
||||
Patch: true,
|
||||
},
|
||||
expectedOutput: "1.2.4",
|
||||
expectedError: false,
|
||||
},
|
||||
{
|
||||
name: "Bump major version with v prefix",
|
||||
options: ToolVersionOptions{
|
||||
Version: "v1.2.3",
|
||||
Major: true,
|
||||
},
|
||||
expectedOutput: "v2.0.0",
|
||||
expectedError: false,
|
||||
},
|
||||
{
|
||||
name: "Bump minor version with v prefix",
|
||||
options: ToolVersionOptions{
|
||||
Version: "v1.2.3",
|
||||
Minor: true,
|
||||
},
|
||||
expectedOutput: "v1.3.0",
|
||||
expectedError: false,
|
||||
},
|
||||
{
|
||||
name: "Bump patch version with v prefix",
|
||||
options: ToolVersionOptions{
|
||||
Version: "v1.2.3",
|
||||
Patch: true,
|
||||
},
|
||||
expectedOutput: "v1.2.4",
|
||||
expectedError: false,
|
||||
},
|
||||
{
|
||||
name: "Bump version with prerelease",
|
||||
options: ToolVersionOptions{
|
||||
Version: "1.2.3-alpha",
|
||||
Patch: true,
|
||||
},
|
||||
expectedOutput: "1.2.4-alpha",
|
||||
expectedError: false,
|
||||
},
|
||||
{
|
||||
name: "Bump version with metadata",
|
||||
options: ToolVersionOptions{
|
||||
Version: "1.2.3+build123",
|
||||
Patch: true,
|
||||
},
|
||||
expectedOutput: "1.2.4+build123",
|
||||
expectedError: false,
|
||||
},
|
||||
{
|
||||
name: "Bump version with prerelease and metadata",
|
||||
options: ToolVersionOptions{
|
||||
Version: "1.2.3-alpha+build123",
|
||||
Patch: true,
|
||||
},
|
||||
expectedOutput: "1.2.4-alpha+build123",
|
||||
expectedError: false,
|
||||
},
|
||||
{
|
||||
name: "Bump version with v prefix, prerelease and metadata",
|
||||
options: ToolVersionOptions{
|
||||
Version: "v1.2.3-alpha+build123",
|
||||
Patch: true,
|
||||
},
|
||||
expectedOutput: "v1.2.4-alpha+build123",
|
||||
expectedError: false,
|
||||
},
|
||||
{
|
||||
name: "No version provided",
|
||||
options: ToolVersionOptions{
|
||||
Major: true,
|
||||
},
|
||||
expectedOutput: "",
|
||||
expectedError: true,
|
||||
},
|
||||
{
|
||||
name: "No bump flag provided",
|
||||
options: ToolVersionOptions{
|
||||
Version: "1.2.3",
|
||||
},
|
||||
expectedOutput: "",
|
||||
expectedError: true,
|
||||
},
|
||||
{
|
||||
name: "Invalid version format",
|
||||
options: ToolVersionOptions{
|
||||
Version: "invalid",
|
||||
Major: true,
|
||||
},
|
||||
expectedOutput: "",
|
||||
expectedError: true,
|
||||
},
|
||||
{
|
||||
name: "Bump prerelease version with numeric component",
|
||||
options: ToolVersionOptions{
|
||||
Version: "1.2.3-alpha.5",
|
||||
Prerelease: true,
|
||||
},
|
||||
expectedOutput: "1.2.3-alpha.6",
|
||||
expectedError: false,
|
||||
},
|
||||
{
|
||||
name: "Bump prerelease version with v prefix",
|
||||
options: ToolVersionOptions{
|
||||
Version: "v1.2.3-alpha.5",
|
||||
Prerelease: true,
|
||||
},
|
||||
expectedOutput: "v1.2.3-alpha.6",
|
||||
expectedError: false,
|
||||
},
|
||||
{
|
||||
name: "Bump prerelease version with metadata",
|
||||
options: ToolVersionOptions{
|
||||
Version: "1.2.3-alpha.5+build123",
|
||||
Prerelease: true,
|
||||
},
|
||||
expectedOutput: "1.2.3-alpha.6+build123",
|
||||
expectedError: false,
|
||||
},
|
||||
{
|
||||
name: "Bump prerelease version without numeric component",
|
||||
options: ToolVersionOptions{
|
||||
Version: "1.2.3-alpha",
|
||||
Prerelease: true,
|
||||
},
|
||||
expectedOutput: "1.2.3-alpha",
|
||||
expectedError: false,
|
||||
},
|
||||
{
|
||||
name: "Bump prerelease version when no prerelease part exists",
|
||||
options: ToolVersionOptions{
|
||||
Version: "1.2.3",
|
||||
Prerelease: true,
|
||||
},
|
||||
expectedOutput: "",
|
||||
expectedError: true,
|
||||
},
|
||||
{
|
||||
name: "Bump prerelease version for issue example v3.0.0-alpha.5",
|
||||
options: ToolVersionOptions{
|
||||
Version: "v3.0.0-alpha.5",
|
||||
Prerelease: true,
|
||||
},
|
||||
expectedOutput: "v3.0.0-alpha.6",
|
||||
expectedError: false,
|
||||
},
|
||||
}
|
||||
|
||||
// Run each test case
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
// Capture stdout
|
||||
oldStdout := os.Stdout
|
||||
r, w, _ := os.Pipe()
|
||||
os.Stdout = w
|
||||
|
||||
// Call the function
|
||||
err := ToolVersion(&tc.options)
|
||||
|
||||
// Restore stdout
|
||||
err2 := w.Close()
|
||||
if err2 != nil {
|
||||
t.Fail()
|
||||
}
|
||||
os.Stdout = oldStdout
|
||||
|
||||
// Read captured output
|
||||
var buf bytes.Buffer
|
||||
_, err2 = io.Copy(&buf, r)
|
||||
if err2 != nil {
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
output := strings.TrimSpace(buf.String())
|
||||
|
||||
// Check error
|
||||
if tc.expectedError && err == nil {
|
||||
t.Errorf("Expected error but got none")
|
||||
}
|
||||
if !tc.expectedError && err != nil {
|
||||
t.Errorf("Expected no error but got: %v", err)
|
||||
}
|
||||
|
||||
// Check output
|
||||
if !tc.expectedError && output != tc.expectedOutput {
|
||||
t.Errorf("Expected output '%s' but got '%s'", tc.expectedOutput, output)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user