feat: add versioning
This commit is contained in:
23
AGENTS.md
23
AGENTS.md
@@ -218,3 +218,26 @@ When behavior changes:
|
|||||||
If a product decision would materially affect persistence compatibility,
|
If a product decision would materially affect persistence compatibility,
|
||||||
GitHub writes, AI data exposure, destructive behavior, or default keybindings,
|
GitHub writes, AI data exposure, destructive behavior, or default keybindings,
|
||||||
ask the repository owner rather than guessing.
|
ask the repository owner rather than guessing.
|
||||||
|
|
||||||
|
## Semantic versioning
|
||||||
|
|
||||||
|
The application version lives in `version.go` and must use Semantic Versioning
|
||||||
|
in `MAJOR.MINOR.PATCH` form.
|
||||||
|
|
||||||
|
- Keep the major version at `0` until the repository owner explicitly requests
|
||||||
|
a `1.0.0` or later release.
|
||||||
|
- Increment `MINOR` and reset `PATCH` to zero for a completed new
|
||||||
|
backward-compatible feature. During `0.x`, also use a minor increment for an
|
||||||
|
intentional breaking change and document that break.
|
||||||
|
- Increment `PATCH` for a completed backward-compatible bug fix, refinement,
|
||||||
|
or other non-feature change.
|
||||||
|
- Apply one version increment per complete logical change, not per user prompt.
|
||||||
|
Follow-up questions and refinements that finish the same feature share that
|
||||||
|
feature's single version increment.
|
||||||
|
- Before incrementing, determine the logical change boundary from the
|
||||||
|
conversation and current work. When the boundary is unclear and Jujutsu is
|
||||||
|
available, inspect the current change and its parent read-only; an empty
|
||||||
|
described parent may identify the feature being developed. Never mutate
|
||||||
|
Jujutsu history merely to determine a version.
|
||||||
|
- If the current logical change already contains the appropriate version
|
||||||
|
increment, do not increment it again for another prompt in that same change.
|
||||||
|
|||||||
@@ -134,6 +134,7 @@ Adjust polling or inspect all command-line options:
|
|||||||
|
|
||||||
```sh
|
```sh
|
||||||
diple --poll 15s
|
diple --poll 15s
|
||||||
|
diple --version
|
||||||
diple --help
|
diple --help
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
17
cli.go
17
cli.go
@@ -8,6 +8,17 @@ import (
|
|||||||
|
|
||||||
var completionShells = []string{"bash", "zsh", "fish"}
|
var completionShells = []string{"bash", "zsh", "fish"}
|
||||||
|
|
||||||
|
func handleVersionCommand(args []string, output io.Writer) (bool, error) {
|
||||||
|
if len(args) == 0 || args[0] != "--version" {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
if len(args) != 1 {
|
||||||
|
return true, fmt.Errorf("usage: diple --version")
|
||||||
|
}
|
||||||
|
_, err := fmt.Fprintf(output, "diple %s\n", dipleVersion)
|
||||||
|
return true, err
|
||||||
|
}
|
||||||
|
|
||||||
func handleCompletionCommand(args []string, output io.Writer) (bool, error) {
|
func handleCompletionCommand(args []string, output io.Writer) (bool, error) {
|
||||||
if len(args) == 0 || args[0] != "completion" {
|
if len(args) == 0 || args[0] != "completion" {
|
||||||
return false, nil
|
return false, nil
|
||||||
@@ -55,6 +66,7 @@ func writeCLIHelp(output io.Writer, defaults Config, configPath string) {
|
|||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
diple [options]
|
diple [options]
|
||||||
|
diple --version
|
||||||
diple completion <bash|zsh|fish>
|
diple completion <bash|zsh|fish>
|
||||||
diple help
|
diple help
|
||||||
|
|
||||||
@@ -92,6 +104,7 @@ Local state:
|
|||||||
|
|
||||||
Other:
|
Other:
|
||||||
-h, --help Show this help and exit.
|
-h, --help Show this help and exit.
|
||||||
|
--version Show the application version and exit.
|
||||||
|
|
||||||
Boolean options accept explicit values, for example --cache=false.
|
Boolean options accept explicit values, for example --cache=false.
|
||||||
Command-line options override TOML settings. GH_REPO is used only when
|
Command-line options override TOML settings. GH_REPO is used only when
|
||||||
@@ -158,7 +171,7 @@ _diple_completion() {
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
local options="--repo --all --limit --poll --endpoint --theme --dashboard-mode --thread-list-width --fold-resolved --compact-reviews --path-scroll --path-scroll-interval --editor-mode --config --cache --cache-max-age --cache-dir --help -h"
|
local options="--repo --all --limit --poll --endpoint --theme --dashboard-mode --thread-list-width --fold-resolved --compact-reviews --path-scroll --path-scroll-interval --editor-mode --config --cache --cache-max-age --cache-dir --version --help -h"
|
||||||
COMPREPLY=($(compgen -W "${options}" -- "${current}"))
|
COMPREPLY=($(compgen -W "${options}" -- "${current}"))
|
||||||
}
|
}
|
||||||
complete -F _diple_completion diple
|
complete -F _diple_completion diple
|
||||||
@@ -202,6 +215,7 @@ _diple() {
|
|||||||
'--cache=[enable local read cache]:boolean:(true false)' \
|
'--cache=[enable local read cache]:boolean:(true false)' \
|
||||||
'--cache-max-age[maximum offline cache age]:duration:' \
|
'--cache-max-age[maximum offline cache age]:duration:' \
|
||||||
'--cache-dir[local read-cache directory]:directory:_directories' \
|
'--cache-dir[local read-cache directory]:directory:_directories' \
|
||||||
|
'--version[show application version]' \
|
||||||
'(-h --help)'{-h,--help}'[show help]'
|
'(-h --help)'{-h,--help}'[show help]'
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,5 +248,6 @@ complete -c diple -l config -r -F -d 'TOML configuration file'
|
|||||||
complete -c diple -l cache -d 'Enable local read cache'
|
complete -c diple -l cache -d 'Enable local read cache'
|
||||||
complete -c diple -l cache-max-age -x -d 'Maximum offline cache age'
|
complete -c diple -l cache-max-age -x -d 'Maximum offline cache age'
|
||||||
complete -c diple -l cache-dir -r -a '(__fish_complete_directories)' -d 'Local read-cache directory'
|
complete -c diple -l cache-dir -r -a '(__fish_complete_directories)' -d 'Local read-cache directory'
|
||||||
|
complete -c diple -l version -d 'Show application version'
|
||||||
complete -c diple -s h -l help -d 'Show help'
|
complete -c diple -s h -l help -d 'Show help'
|
||||||
`
|
`
|
||||||
|
|||||||
25
cli_test.go
25
cli_test.go
@@ -2,10 +2,34 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestVersionCommandPrintsSemanticVersion(t *testing.T) {
|
||||||
|
var output bytes.Buffer
|
||||||
|
handled, err := handleVersionCommand([]string{"--version"}, &output)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !handled || output.String() != "diple "+dipleVersion+"\n" {
|
||||||
|
t.Fatalf("version output = %q, handled=%t", output.String(), handled)
|
||||||
|
}
|
||||||
|
if !regexp.MustCompile(`^0\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$`).MatchString(dipleVersion) {
|
||||||
|
t.Fatalf("version %q is not a pre-1.0 semantic version", dipleVersion)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVersionCommandRejectsAdditionalArguments(t *testing.T) {
|
||||||
|
handled, err := handleVersionCommand(
|
||||||
|
[]string{"--version", "--help"}, &bytes.Buffer{},
|
||||||
|
)
|
||||||
|
if !handled || err == nil || !strings.Contains(err.Error(), "usage: diple --version") {
|
||||||
|
t.Fatalf("handled=%t error=%v", handled, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestCompletionCommandGeneratesSupportedShells(t *testing.T) {
|
func TestCompletionCommandGeneratesSupportedShells(t *testing.T) {
|
||||||
for _, shell := range completionShells {
|
for _, shell := range completionShells {
|
||||||
t.Run(shell, func(t *testing.T) {
|
t.Run(shell, func(t *testing.T) {
|
||||||
@@ -65,6 +89,7 @@ func TestCLIHelpIsGroupedAndActionable(t *testing.T) {
|
|||||||
"Appearance and navigation:",
|
"Appearance and navigation:",
|
||||||
"Local state:",
|
"Local state:",
|
||||||
"diple completion <bash|zsh|fish>",
|
"diple completion <bash|zsh|fish>",
|
||||||
|
"--version",
|
||||||
"--repo OWNER/REPOSITORY",
|
"--repo OWNER/REPOSITORY",
|
||||||
"--cache=false",
|
"--cache=false",
|
||||||
"gh auth login",
|
"gh auth login",
|
||||||
|
|||||||
6
main.go
6
main.go
@@ -11,6 +11,12 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
if handled, err := handleVersionCommand(os.Args[1:], os.Stdout); handled {
|
||||||
|
if err != nil {
|
||||||
|
exitf("%v", err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
if handled, err := handleCompletionCommand(os.Args[1:], os.Stdout); handled {
|
if handled, err := handleCompletionCommand(os.Args[1:], os.Stdout); handled {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
exitf("%v", err)
|
exitf("%v", err)
|
||||||
|
|||||||
3
version.go
Normal file
3
version.go
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
const dipleVersion = "0.1.0"
|
||||||
Reference in New Issue
Block a user