Skip to content

Commit 04bf30f

Browse files
authored
Merge pull request #24 from ncode/juliano/updates
fix: address multiple bugs and improve reliability
2 parents 43d3164 + e7b7f80 commit 04bf30f

File tree

9 files changed

+468
-312
lines changed

9 files changed

+468
-312
lines changed

.github/workflows/ci.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,17 @@ jobs:
66
build:
77
runs-on: ubuntu-latest
88
steps:
9-
- uses: actions/checkout@v3
9+
- uses: actions/checkout@v4.2.2
1010
with:
1111
fetch-depth: 2
12-
- uses: actions/setup-go@v3
12+
- uses: actions/setup-go@v5.4.0
1313
with:
14-
go-version: '1.21'
14+
go-version: '1.25'
1515
- name: Run coverage
16-
run: go test -coverpkg=./... ./... -race -coverprofile=coverage.out -covermode=atomic
16+
run: go env -w GOTOOLCHAIN=go1.25.0+auto && go test -coverpkg=./... ./... -race -coverprofile=coverage.out -covermode=atomic
1717
- name: Upload coverage to Codecov
18-
uses: codecov/codecov-action@v3
18+
uses: codecov/codecov-action@v5
1919
with:
20-
verbose: true
20+
verbose: true
2121
env:
2222
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

.github/workflows/codeql.yml

Lines changed: 0 additions & 74 deletions
This file was deleted.

.github/workflows/go.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@ jobs:
1414
build:
1515
runs-on: ubuntu-latest
1616
steps:
17-
- uses: actions/checkout@v3
17+
- uses: actions/checkout@v4.2.2
1818

1919
- name: Set up Go
20-
uses: actions/setup-go@v4
20+
uses: actions/setup-go@v5.4.0
2121
with:
22-
go-version: '1.21'
22+
go-version: '1.25'
2323

2424
- name: Build
2525
run: go build -v ./...

cmd/root.go

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,18 @@ var cfgFile string
2828
// rootCmd represents the base command when called without any subcommands
2929
var rootCmd = &cobra.Command{
3030
Use: "ballot",
31-
Short: "A brief description of your application",
32-
Long: `A longer description that spans multiple lines and likely contains
33-
examples and usage of using your application. For example:
34-
35-
Cobra is a CLI library for Go that empowers applications.
36-
This application is a tool to generate the needed files
37-
to quickly create a Cobra application.`,
38-
// Uncomment the following line if your bare application
39-
// has an action associated with it:
40-
// Run: func(cmd *cobra.Command, args []string) { },
31+
Short: "Consul-based leader election with tagging support",
32+
Long: `Ballot is a distributed leader election tool built on Consul.
33+
34+
It uses Consul's session and KV store APIs to perform leader election
35+
among service instances. When a service becomes leader, it is tagged
36+
with a configurable primary tag and optional hooks can be executed.
37+
38+
Features:
39+
- Consul session-based leader election
40+
- Automatic primary tag management
41+
- Configurable promotion/demotion hooks
42+
- Health check aware leadership`,
4143
}
4244

4345
// Execute adds all child commands to the root command and sets flags appropriately.
@@ -52,15 +54,7 @@ func Execute() {
5254
func init() {
5355
cobra.OnInitialize(initConfig)
5456

55-
// Here you will define your flags and configuration settings.
56-
// Cobra supports persistent flags, which, if defined here,
57-
// will be global for your application.
58-
5957
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.ballot.yaml)")
60-
61-
// Cobra also supports local flags, which will only run
62-
// when this action is called directly.
63-
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
6458
}
6559

6660
// initConfig reads in config file and ENV variables if set.

cmd/run.go

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ package cmd
1818
import (
1919
"context"
2020
"os"
21+
"os/signal"
22+
"sync"
23+
"syscall"
2124

2225
"github.com/ncode/ballot/internal/ballot"
2326
log "github.com/sirupsen/logrus"
@@ -30,25 +33,39 @@ var runCmd = &cobra.Command{
3033
Use: "run",
3134
Short: "Run the ballot and starts all the defined elections",
3235
Run: func(cmd *cobra.Command, args []string) {
33-
ctx := context.Background()
34-
for _, name := range viper.GetStringSlice("election.enabled") {
36+
ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
37+
defer cancel()
38+
39+
var wg sync.WaitGroup
40+
enabledServices := viper.GetStringSlice("election.enabled")
41+
42+
for _, name := range enabledServices {
3543
b, err := ballot.New(ctx, name)
3644
if err != nil {
3745
log.WithFields(log.Fields{
38-
"caller": "run",
39-
"step": "New",
46+
"caller": "run",
47+
"step": "New",
48+
"service": name,
4049
}).Error(err)
4150
os.Exit(1)
4251
}
4352

44-
err = b.Run()
45-
if err != nil {
46-
log.WithFields(log.Fields{
47-
"caller": "run",
48-
"step": "runCmd",
49-
}).Error(err)
50-
}
53+
wg.Add(1)
54+
go func(b *ballot.Ballot, name string) {
55+
defer wg.Done()
56+
err := b.Run()
57+
if err != nil {
58+
log.WithFields(log.Fields{
59+
"caller": "run",
60+
"step": "runCmd",
61+
"service": name,
62+
}).Error(err)
63+
}
64+
}(b, name)
5165
}
66+
67+
wg.Wait()
68+
log.Info("All elections stopped, shutting down")
5269
},
5370
}
5471

go.mod

Lines changed: 22 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,49 @@
11
module github.com/ncode/ballot
22

3-
go 1.21
4-
toolchain go1.23.7
3+
go 1.25.5
54

65
require (
76
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
8-
github.com/hashicorp/consul/api v1.27.0
7+
github.com/hashicorp/consul/api v1.33.0
98
github.com/sirupsen/logrus v1.9.3
10-
github.com/spf13/cobra v1.8.0
11-
github.com/spf13/viper v1.18.2
12-
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a
9+
github.com/spf13/cobra v1.10.2
10+
github.com/spf13/viper v1.21.0
1311
)
1412

1513
require (
1614
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
15+
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
16+
github.com/hashicorp/go-metrics v0.5.4 // indirect
1717
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
18-
github.com/stretchr/objx v0.5.0 // indirect
19-
golang.org/x/net v0.36.0 // indirect
18+
github.com/stretchr/objx v0.5.2 // indirect
19+
go.yaml.in/yaml/v3 v3.0.4 // indirect
20+
golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93 // indirect
2021
)
2122

2223
require (
2324
github.com/armon/go-metrics v0.4.1 // indirect
24-
github.com/fatih/color v1.16.0 // indirect
25-
github.com/fsnotify/fsnotify v1.7.0 // indirect
25+
github.com/fatih/color v1.18.0 // indirect
26+
github.com/fsnotify/fsnotify v1.9.0 // indirect
2627
github.com/hashicorp/errwrap v1.1.0 // indirect
2728
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
28-
github.com/hashicorp/go-hclog v1.6.2 // indirect
29+
github.com/hashicorp/go-hclog v1.6.3 // indirect
2930
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
3031
github.com/hashicorp/go-multierror v1.1.1 // indirect
3132
github.com/hashicorp/go-rootcerts v1.0.2 // indirect
3233
github.com/hashicorp/golang-lru v1.0.2 // indirect
33-
github.com/hashicorp/hcl v1.0.0 // indirect
34-
github.com/hashicorp/serf v0.10.1 // indirect
34+
github.com/hashicorp/serf v0.10.2 // indirect
3535
github.com/inconshreveable/mousetrap v1.1.0 // indirect
36-
github.com/magiconair/properties v1.8.7 // indirect
37-
github.com/mattn/go-colorable v0.1.13 // indirect
36+
github.com/mattn/go-colorable v0.1.14 // indirect
3837
github.com/mattn/go-isatty v0.0.20 // indirect
3938
github.com/mitchellh/go-homedir v1.1.0 // indirect
40-
github.com/mitchellh/mapstructure v1.5.0 // indirect
41-
github.com/pelletier/go-toml/v2 v2.1.1 // indirect
42-
github.com/sagikazarmark/locafero v0.4.0 // indirect
43-
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
44-
github.com/sourcegraph/conc v0.3.0 // indirect
45-
github.com/spf13/afero v1.11.0 // indirect
46-
github.com/spf13/cast v1.6.0 // indirect
47-
github.com/spf13/pflag v1.0.5 // indirect
48-
github.com/stretchr/testify v1.8.4
39+
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
40+
github.com/sagikazarmark/locafero v0.12.0 // indirect
41+
github.com/spf13/afero v1.15.0 // indirect
42+
github.com/spf13/cast v1.10.0 // indirect
43+
github.com/spf13/pflag v1.0.10 // indirect
44+
github.com/stretchr/testify v1.11.1
4945
github.com/subosito/gotenv v1.6.0 // indirect
50-
go.uber.org/multierr v1.11.0 // indirect
51-
golang.org/x/sys v0.30.0 // indirect
52-
golang.org/x/text v0.22.0 // indirect
53-
gopkg.in/ini.v1 v1.67.0 // indirect
46+
golang.org/x/sys v0.39.0 // indirect
47+
golang.org/x/text v0.32.0 // indirect
5448
gopkg.in/yaml.v3 v3.0.1 // indirect
5549
)

0 commit comments

Comments
 (0)