Skip to content

Commit d76564d

Browse files
committed
Merge pull request #2 from bcomnes/bump-flag
2 parents 164e5c9 + bc8f48c commit d76564d

File tree

7 files changed

+1110
-10
lines changed

7 files changed

+1110
-10
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,4 @@ version: ## Run the goversion tool. Usage: make version bump="patch" [files="-fi
2929
exit 1; \
3030
fi
3131
@echo "Running goversion with bump: $(bump)"
32-
go run cmd/main.go $(bump)
32+
go run main.go $(bump)

cli_test.go

Lines changed: 293 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,3 +231,296 @@ var (
231231
t.Errorf("expected git tag v2.0.0; got tags: %v", tags)
232232
}
233233
}
234+
235+
// TestCLIBumpFileIntegration tests the -bump-file flag functionality.
236+
func TestCLIBumpFileIntegration(t *testing.T) {
237+
// Build the CLI binary
238+
tmpBuildDir, err := os.MkdirTemp("", "goversion_bumpfile_build")
239+
if err != nil {
240+
t.Fatal(err)
241+
}
242+
defer os.RemoveAll(tmpBuildDir)
243+
244+
binPath := filepath.Join(tmpBuildDir, "goversion")
245+
buildCmd := exec.Command("go", "build", "-o", binPath, "./")
246+
if out, err := buildCmd.CombinedOutput(); err != nil {
247+
t.Fatalf("failed to build CLI binary: %v; output: %s", err, out)
248+
}
249+
250+
// Set up test repository
251+
tmpRepo, err := os.MkdirTemp("", "goversion_bumpfile_test")
252+
if err != nil {
253+
t.Fatal(err)
254+
}
255+
defer os.RemoveAll(tmpRepo)
256+
257+
// Initialize git
258+
initCmd := exec.Command("git", "init")
259+
initCmd.Dir = tmpRepo
260+
if output, err := initCmd.CombinedOutput(); err != nil {
261+
t.Fatalf("git init failed: %v; output: %s", err, string(output))
262+
}
263+
264+
// Configure git
265+
configCmds := [][]string{
266+
{"git", "config", "user.email", "test@example.com"},
267+
{"git", "config", "user.name", "Test User"},
268+
}
269+
for _, args := range configCmds {
270+
cmd := exec.Command(args[0], args[1:]...)
271+
cmd.Dir = tmpRepo
272+
if output, err := cmd.CombinedOutput(); err != nil {
273+
t.Fatalf("git config failed: %v; output: %s", err, string(output))
274+
}
275+
}
276+
277+
// Create version.go
278+
versionFile := filepath.Join(tmpRepo, "version.go")
279+
versionContent := `package main
280+
281+
var (
282+
Version = "1.2.3"
283+
)
284+
`
285+
if err := os.WriteFile(versionFile, []byte(versionContent), 0644); err != nil {
286+
t.Fatalf("failed to write version file: %v", err)
287+
}
288+
289+
// Create package.json
290+
packageFile := filepath.Join(tmpRepo, "package.json")
291+
packageContent := `{
292+
"name": "test-package",
293+
"version": "1.2.3",
294+
"dependencies": {
295+
"express": "4.18.0",
296+
"lodash": "4.17.21"
297+
}
298+
}`
299+
if err := os.WriteFile(packageFile, []byte(packageContent), 0644); err != nil {
300+
t.Fatalf("failed to write package.json: %v", err)
301+
}
302+
303+
// Create Cargo.toml
304+
cargoFile := filepath.Join(tmpRepo, "Cargo.toml")
305+
cargoContent := `[package]
306+
name = "test-crate"
307+
version = "1.2.3"
308+
309+
[dependencies]
310+
serde = "1.0.130"
311+
tokio = { version = "1.21.0", features = ["full"] }`
312+
if err := os.WriteFile(cargoFile, []byte(cargoContent), 0644); err != nil {
313+
t.Fatalf("failed to write Cargo.toml: %v", err)
314+
}
315+
316+
// Stage and commit initial files
317+
gitAddCmd := exec.Command("git", "add", ".")
318+
gitAddCmd.Dir = tmpRepo
319+
if output, err := gitAddCmd.CombinedOutput(); err != nil {
320+
t.Fatalf("git add failed: %v; output: %s", err, string(output))
321+
}
322+
gitCommitCmd := exec.Command("git", "commit", "-m", "initial commit")
323+
gitCommitCmd.Dir = tmpRepo
324+
if output, err := gitCommitCmd.CombinedOutput(); err != nil {
325+
t.Fatalf("git commit failed: %v; output: %s", err, string(output))
326+
}
327+
328+
// Run CLI with bump-file flags
329+
cliCmd := exec.Command(binPath, "-version-file", versionFile, "-bump-file", packageFile, "-bump-file", cargoFile, "minor")
330+
cliCmd.Dir = tmpRepo
331+
var stdout, stderr bytes.Buffer
332+
cliCmd.Stdout = &stdout
333+
cliCmd.Stderr = &stderr
334+
if err := cliCmd.Run(); err != nil {
335+
t.Fatalf("CLI command failed: %v; stdout: %s; stderr: %s", err, stdout.String(), stderr.String())
336+
}
337+
338+
// Verify version.go was updated
339+
versionResult, err := os.ReadFile(versionFile)
340+
if err != nil {
341+
t.Fatalf("failed to read version file: %v", err)
342+
}
343+
if !strings.Contains(string(versionResult), `Version = "1.3.0"`) {
344+
t.Errorf("version.go not updated correctly; got:\n%s", versionResult)
345+
}
346+
347+
// Verify package.json was updated
348+
packageResult, err := os.ReadFile(packageFile)
349+
if err != nil {
350+
t.Fatalf("failed to read package.json: %v", err)
351+
}
352+
if !strings.Contains(string(packageResult), `"version": "1.3.0"`) {
353+
t.Errorf("package.json not updated correctly; got:\n%s", packageResult)
354+
}
355+
// Verify dependencies unchanged
356+
if !strings.Contains(string(packageResult), `"express": "4.18.0"`) {
357+
t.Errorf("package.json dependencies were modified")
358+
}
359+
360+
// Verify Cargo.toml was updated
361+
cargoResult, err := os.ReadFile(cargoFile)
362+
if err != nil {
363+
t.Fatalf("failed to read Cargo.toml: %v", err)
364+
}
365+
if !strings.Contains(string(cargoResult), `version = "1.3.0"`) {
366+
t.Errorf("Cargo.toml not updated correctly; got:\n%s", cargoResult)
367+
}
368+
// Verify dependencies unchanged
369+
if !strings.Contains(string(cargoResult), `serde = "1.0.130"`) {
370+
t.Errorf("Cargo.toml dependencies were modified")
371+
}
372+
373+
// Verify git tag
374+
gitTagCmd := exec.Command("git", "tag")
375+
gitTagCmd.Dir = tmpRepo
376+
tagOutput, err := gitTagCmd.CombinedOutput()
377+
if err != nil {
378+
t.Fatalf("git tag command failed: %v; output: %s", err, string(tagOutput))
379+
}
380+
tags := strings.Split(strings.TrimSpace(string(tagOutput)), "\n")
381+
if !slices.Contains(tags, "v1.3.0") {
382+
t.Errorf("expected git tag v1.3.0 not found; got tags: %v", tags)
383+
}
384+
}
385+
386+
// TestCLIPostBumpIntegration tests the -post-bump flag functionality.
387+
func TestCLIPostBumpIntegration(t *testing.T) {
388+
// Build the CLI binary
389+
tmpBuildDir, err := os.MkdirTemp("", "goversion_postbump_build")
390+
if err != nil {
391+
t.Fatal(err)
392+
}
393+
defer os.RemoveAll(tmpBuildDir)
394+
395+
binPath := filepath.Join(tmpBuildDir, "goversion")
396+
buildCmd := exec.Command("go", "build", "-o", binPath, "./")
397+
if out, err := buildCmd.CombinedOutput(); err != nil {
398+
t.Fatalf("failed to build CLI binary: %v; output: %s", err, out)
399+
}
400+
401+
// Set up test repository
402+
tmpRepo, err := os.MkdirTemp("", "goversion_postbump_cli_test")
403+
if err != nil {
404+
t.Fatal(err)
405+
}
406+
defer os.RemoveAll(tmpRepo)
407+
408+
// Initialize git
409+
initCmd := exec.Command("git", "init")
410+
initCmd.Dir = tmpRepo
411+
if output, err := initCmd.CombinedOutput(); err != nil {
412+
t.Fatalf("git init failed: %v; output: %s", err, string(output))
413+
}
414+
415+
// Configure git
416+
configCmds := [][]string{
417+
{"git", "config", "user.email", "test@example.com"},
418+
{"git", "config", "user.name", "Test User"},
419+
}
420+
for _, args := range configCmds {
421+
cmd := exec.Command(args[0], args[1:]...)
422+
cmd.Dir = tmpRepo
423+
if output, err := cmd.CombinedOutput(); err != nil {
424+
t.Fatalf("git config failed: %v; output: %s", err, string(output))
425+
}
426+
}
427+
428+
// Create version.go
429+
versionFile := filepath.Join(tmpRepo, "version.go")
430+
versionContent := `package main
431+
432+
var (
433+
Version = "1.0.0"
434+
)
435+
`
436+
if err := os.WriteFile(versionFile, []byte(versionContent), 0644); err != nil {
437+
t.Fatalf("failed to write version file: %v", err)
438+
}
439+
440+
// Create a post-bump script that generates a file
441+
scriptFile := filepath.Join(tmpRepo, "update-docs.sh")
442+
scriptContent := `#!/bin/sh
443+
cat > VERSION.md << EOF
444+
# Version Information
445+
Current Version: $GOVERSION_NEW_VERSION
446+
Previous Version: $GOVERSION_OLD_VERSION
447+
EOF
448+
echo "Generated VERSION.md"
449+
`
450+
if err := os.WriteFile(scriptFile, []byte(scriptContent), 0755); err != nil {
451+
t.Fatalf("failed to write post-bump script: %v", err)
452+
}
453+
454+
// Stage and commit initial files
455+
gitAddCmd := exec.Command("git", "add", ".")
456+
gitAddCmd.Dir = tmpRepo
457+
if output, err := gitAddCmd.CombinedOutput(); err != nil {
458+
t.Fatalf("git add failed: %v; output: %s", err, string(output))
459+
}
460+
gitCommitCmd := exec.Command("git", "commit", "-m", "initial commit")
461+
gitCommitCmd.Dir = tmpRepo
462+
if output, err := gitCommitCmd.CombinedOutput(); err != nil {
463+
t.Fatalf("git commit failed: %v; output: %s", err, string(output))
464+
}
465+
466+
// Run CLI with post-bump flag and -file for the generated VERSION.md
467+
cliCmd := exec.Command(binPath, "-version-file", versionFile, "-post-bump", scriptFile, "-file", filepath.Join(tmpRepo, "VERSION.md"), "minor")
468+
cliCmd.Dir = tmpRepo
469+
var stdout, stderr bytes.Buffer
470+
cliCmd.Stdout = &stdout
471+
cliCmd.Stderr = &stderr
472+
if err := cliCmd.Run(); err != nil {
473+
t.Fatalf("CLI command failed: %v; stdout: %s; stderr: %s", err, stdout.String(), stderr.String())
474+
}
475+
476+
// Verify the script output was shown
477+
if !strings.Contains(stdout.String(), "Generated VERSION.md") {
478+
t.Errorf("expected script output in stdout; got: %s", stdout.String())
479+
}
480+
481+
// Verify version.go was updated
482+
versionResult, err := os.ReadFile(versionFile)
483+
if err != nil {
484+
t.Fatalf("failed to read version file: %v", err)
485+
}
486+
if !strings.Contains(string(versionResult), `Version = "1.1.0"`) {
487+
t.Errorf("version.go not updated correctly; got:\n%s", versionResult)
488+
}
489+
490+
// Verify VERSION.md was created by the script
491+
versionMdPath := filepath.Join(tmpRepo, "VERSION.md")
492+
versionMdContent, err := os.ReadFile(versionMdPath)
493+
if err != nil {
494+
t.Fatalf("VERSION.md not created by post-bump script: %v", err)
495+
}
496+
expectedContent := `# Version Information
497+
Current Version: 1.1.0
498+
Previous Version: 1.0.0
499+
`
500+
if string(versionMdContent) != expectedContent {
501+
t.Errorf("VERSION.md content mismatch; got:\n%s\nwant:\n%s", versionMdContent, expectedContent)
502+
}
503+
504+
// Verify git tag
505+
gitTagCmd := exec.Command("git", "tag")
506+
gitTagCmd.Dir = tmpRepo
507+
tagOutput, err := gitTagCmd.CombinedOutput()
508+
if err != nil {
509+
t.Fatalf("git tag command failed: %v; output: %s", err, string(tagOutput))
510+
}
511+
tags := strings.Split(strings.TrimSpace(string(tagOutput)), "\n")
512+
if !slices.Contains(tags, "v1.1.0") {
513+
t.Errorf("expected git tag v1.1.0 not found; got tags: %v", tags)
514+
}
515+
516+
// Verify VERSION.md was committed
517+
logCmd := exec.Command("git", "log", "--name-only", "--oneline", "-1")
518+
logCmd.Dir = tmpRepo
519+
logOutput, err := logCmd.CombinedOutput()
520+
if err != nil {
521+
t.Fatalf("git log failed: %v; output: %s", err, string(logOutput))
522+
}
523+
if !strings.Contains(string(logOutput), "VERSION.md") {
524+
t.Errorf("VERSION.md was not included in commit; log output:\n%s", logOutput)
525+
}
526+
}

doc.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@
1616
// (Defaults to "./version.go")
1717
// -file: Specifies additional file(s) to be staged together with the version file.
1818
// This flag may be used multiple times.
19+
// -bump-file: Specifies additional file(s) to scan for the first semantic version and bump it.
20+
// This flag may be used multiple times. The found version is replaced with the same
21+
// version as the main version file. Only valid semver strings are matched (no "v" prefix).
22+
// -post-bump: Specifies a script to execute after version bump but before git commit.
23+
// The script receives GOVERSION_OLD_VERSION and GOVERSION_NEW_VERSION environment variables.
24+
// Files created or modified by the script must be specified with -file to be included in the commit.
1925
// -version: Displays the version of the goversion CLI tool and exits.
2026
//
2127
// Examples:
@@ -47,6 +53,16 @@
4753
// # Bump patch version and include README.md in the commit
4854
// goversion -version-file=./version.go -file=README.md patch
4955
//
56+
// # Bump version in multiple files (package.json, Cargo.toml, etc.)
57+
// goversion -bump-file=package.json -bump-file=Cargo.toml patch
58+
//
59+
// # Run a script after bumping but before committing
60+
// # Files created by the script must be explicitly included with -file
61+
// goversion -post-bump=./scripts/update-docs.sh -file=docs/version.md minor
62+
//
63+
// # Combine version file, bump files, and extra files
64+
// goversion -version-file=./version.go -bump-file=package.json -file=README.md minor
65+
//
5066
// This command bumps the patch version, updates the version file, stages the changes
5167
// (including README.md), commits using the new version as the commit message, and tags
5268
// the commit with the new version.

main.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ and tags the commit with the version prefixed with "v". For major version bumps
3333
Examples:
3434
goversion minor
3535
goversion 1.2.3
36+
goversion -bump-file package.json -bump-file Cargo.toml patch
37+
goversion -post-bump ./scripts/update-docs.sh -file docs/version.md patch
3638
3739
Positional arguments:
3840
<version-bump> One of: major, minor, patch, premajor, preminor, prepatch, prerelease, from-git, or an explicit version like 1.2.3
@@ -48,6 +50,9 @@ func main() {
4850
versionFile := flag.String("version-file", "./version.go", "Path to the Go file containing the version declaration")
4951
var extraFiles arrayFlags
5052
flag.Var(&extraFiles, "file", "Additional file to stage and commit. May be repeated.")
53+
var bumpFiles arrayFlags
54+
flag.Var(&bumpFiles, "bump-file", "Additional file to scan for first semver and bump it. May be repeated.")
55+
postBump := flag.String("post-bump", "", "Script to execute after version bump but before git commit. Receives GOVERSION_OLD_VERSION and GOVERSION_NEW_VERSION env vars.")
5156
dryRun := flag.Bool("dry", false, "Perform a dry run without modifying any files or git repository")
5257
showVersion := flag.Bool("version", false, "Show CLI version and exit")
5358
help := flag.Bool("help", false, "Show help message and exit")
@@ -90,9 +95,9 @@ func main() {
9095
var err error
9196

9297
if *dryRun {
93-
meta, err = goversion.DryRun(*versionFile, versionArg)
98+
meta, err = goversion.DryRun(*versionFile, versionArg, bumpFiles)
9499
} else {
95-
meta, err = goversion.Run(*versionFile, versionArg, extraFiles)
100+
meta, err = goversion.Run(*versionFile, versionArg, extraFiles, bumpFiles, *postBump)
96101
}
97102
if err != nil {
98103
fmt.Fprintln(os.Stderr, "Error:", err)

pkg/example_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ func ExampleRun() {
8282
}
8383

8484
// Call Run to bump the version ("patch" will bump 1.2.3 to 1.2.4).
85-
_, err = Run(versionFile, "patch", []string{versionFile})
85+
_, err = Run(versionFile, "patch", []string{versionFile}, []string{}, "")
8686
if err != nil {
8787
fmt.Println("error bumping version:", err)
8888
return

0 commit comments

Comments
 (0)