5
0
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:
Lea Anthony 2025-04-23 10:29:51 +10:00
parent 421b75ef21
commit da0da5fc69
No known key found for this signature in database
GPG Key ID: 33DAF7BB90A58405
5 changed files with 382 additions and 1 deletions

View File

@ -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)

View File

@ -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).

View File

@ -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)

View 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
}

View 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)
}
})
}
}