Skip to content

Commit 5e0af0c

Browse files
authored
Merge branch 'main' into feat/stop-on-nth-arg
2 parents 4905fd6 + 2799fd4 commit 5e0af0c

26 files changed

Lines changed: 538 additions & 235 deletions

.github/dependabot.yml

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
11
version: 2
22
updates:
3-
- package-ecosystem: "gomod"
4-
directory: "/"
3+
- package-ecosystem: gomod
4+
directory: /
55
schedule:
6-
interval: "weekly"
7-
- package-ecosystem: "github-actions"
8-
directory: "/"
6+
interval: weekly
7+
- package-ecosystem: github-actions
8+
directory: /
99
schedule:
10-
interval: "weekly"
10+
interval: weekly
11+
- package-ecosystem: pip
12+
directory: /
13+
schedule:
14+
interval: weekly
15+
groups:
16+
python-packages:
17+
patterns: ["*"]

.github/workflows/lint.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@ permissions:
1515

1616
jobs:
1717
golangci-lint:
18-
runs-on: ubuntu-latest
18+
runs-on: ubuntu-24.04
1919

2020
steps:
2121
- name: Clone repository
22-
uses: actions/checkout@v4
22+
uses: actions/checkout@v5
2323

2424
- name: Set up Go
2525
uses: actions/setup-go@v5

.github/workflows/publish-docs.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ permissions:
1313
jobs:
1414
test-docs:
1515
name: test-docs
16-
runs-on: ubuntu-latest
16+
runs-on: ubuntu-24.04
1717
steps:
18-
- uses: actions/checkout@v4
18+
- uses: actions/checkout@v5
1919

2020
- name: Set up Go
2121
uses: actions/setup-go@v5
@@ -44,17 +44,17 @@ jobs:
4444
if: startswith(github.ref, 'refs/tags/')
4545
name: publish
4646
needs: [test-docs]
47-
runs-on: ubuntu-latest
47+
runs-on: ubuntu-24.04
4848
steps:
49-
- uses: actions/checkout@v4
49+
- uses: actions/checkout@v5
5050
with:
5151
fetch-depth: 0
5252

5353
- uses: actions/setup-python@v5
5454
with:
5555
python-version: '3.13'
5656
cache: pip
57-
cache-dependency-path: mkdocs-reqs.txt
57+
cache-dependency-path: mkdocs-requirements.txt
5858

5959
- name: Ensure mkdocs is available
6060
run: make ensure-mkdocs

.github/workflows/test.yml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@ jobs:
1717
test:
1818
strategy:
1919
matrix:
20-
os: [ubuntu-latest, macos-latest, windows-latest]
20+
os: [ubuntu-24.04, macos-15, windows-2025]
2121
go: [stable, oldstable]
2222

2323
name: ${{ matrix.os }} @ Go ${{ matrix.go }}
2424
runs-on: ${{ matrix.os }}
2525

2626
steps:
27-
- uses: actions/checkout@v4
27+
- uses: actions/checkout@v5
2828

2929
- name: Set up Go
3030
uses: actions/setup-go@v5
@@ -34,25 +34,25 @@ jobs:
3434
- name: Set PATH
3535
run: echo "${GITHUB_WORKSPACE}/.local/bin" >>"${GITHUB_PATH}"
3636

37-
- if: matrix.go == 'stable' && matrix.os == 'ubuntu-latest'
37+
- if: matrix.go == 'stable' && matrix.os == 'ubuntu-24.04'
3838
run: make ensure-goimports
3939

40-
- if: matrix.go == 'stable' && matrix.os == 'ubuntu-latest'
40+
- if: matrix.go == 'stable' && matrix.os == 'ubuntu-24.04'
4141
run: make lint
4242

4343
- run: make vet
4444
- run: make test
4545
- run: make check-binary-size
4646

47-
- if: matrix.go == 'stable' && matrix.os == 'ubuntu-latest'
47+
- if: matrix.go == 'stable' && matrix.os == 'ubuntu-24.04'
4848
run: make generate
4949

5050
- run: make diffcheck
5151

52-
- if: matrix.go == 'stable' && matrix.os == 'ubuntu-latest'
52+
- if: matrix.go == 'stable' && matrix.os == 'ubuntu-24.04'
5353
run: make v3diff
5454

55-
- if: success() && matrix.go == 'stable' && matrix.os == 'ubuntu-latest'
55+
- if: success() && matrix.go == 'stable' && matrix.os == 'ubuntu-24.04'
5656
uses: codecov/codecov-action@v5
5757
with:
5858
token: ${{ secrets.CODECOV_TOKEN }}

command.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,9 @@ type Command struct {
8585
Writer io.Writer `json:"-"`
8686
// ErrWriter writes error output
8787
ErrWriter io.Writer `json:"-"`
88-
// ExitErrHandler processes any error encountered while running an App before
89-
// it is returned to the caller. If no function is provided, HandleExitCoder
90-
// is used as the default behavior.
88+
// ExitErrHandler processes any error encountered while running a Command before it is
89+
// returned to the caller. If no function is provided, HandleExitCoder is used as the
90+
// default behavior.
9191
ExitErrHandler ExitErrHandlerFunc `json:"-"`
9292
// Other custom info
9393
Metadata map[string]interface{} `json:"metadata"`

command_run.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -180,9 +180,9 @@ func (cmd *Command) run(ctx context.Context, osArgs []string) (_ context.Context
180180
}
181181
if !cmd.hideHelp() {
182182
if cmd.parent == nil {
183-
tracef("running ShowAppHelp")
184-
if err := ShowAppHelp(cmd); err != nil {
185-
tracef("SILENTLY IGNORING ERROR running ShowAppHelp %[1]v (cmd=%[2]q)", err, cmd.Name)
183+
tracef("running ShowRootCommandHelp")
184+
if err := ShowRootCommandHelp(cmd); err != nil {
185+
tracef("SILENTLY IGNORING ERROR running ShowRootCommandHelp %[1]v (cmd=%[2]q)", err, cmd.Name)
186186
}
187187
} else {
188188
tracef("running ShowCommandHelp with %[1]q", cmd.Name)
@@ -319,7 +319,11 @@ func (cmd *Command) run(ctx context.Context, osArgs []string) (_ context.Context
319319

320320
if err := cmd.checkAllRequiredFlags(); err != nil {
321321
cmd.isInError = true
322-
_ = ShowSubcommandHelp(cmd)
322+
if cmd.OnUsageError != nil {
323+
err = cmd.OnUsageError(ctx, cmd, err, cmd.parent != nil)
324+
} else {
325+
_ = ShowSubcommandHelp(cmd)
326+
}
323327
return ctx, err
324328
}
325329

command_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4096,6 +4096,21 @@ func TestCheckRequiredFlags(t *testing.T) {
40964096
}
40974097
}
40984098

4099+
func TestCheckRequiredFlagsWithOnUsageError(t *testing.T) {
4100+
expectedError := errors.New("OnUsageError")
4101+
cmd := &Command{
4102+
Name: "foo",
4103+
Flags: []Flag{
4104+
&StringFlag{Name: "requiredFlag", Required: true},
4105+
},
4106+
OnUsageError: func(_ context.Context, _ *Command, _ error, _ bool) error {
4107+
return expectedError
4108+
},
4109+
}
4110+
actualError := cmd.Run(buildTestContext(t), []string{"requiredFlag"})
4111+
require.ErrorIs(t, actualError, expectedError)
4112+
}
4113+
40994114
func TestCommand_ParentCommand_Set(t *testing.T) {
41004115
cmd := &Command{
41014116
parent: &Command{
@@ -4296,6 +4311,9 @@ func TestCommandReadArgsFromStdIn(t *testing.T) {
42964311
},
42974312
&StringSliceFlag{
42984313
Name: "ssf",
4314+
Config: StringConfig{
4315+
TrimSpace: true,
4316+
},
42994317
},
43004318
}
43014319

docs/CONTRIBUTING.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,18 @@ verify one's changes are harmonious in nature. The same steps are also run durin
6666
[continuous integration
6767
phase](https://github.com/urfave/cli/blob/main/.github/workflows/test.yml).
6868

69+
`gfmrun` is required to run the examples, and without it `make all` will fail.
70+
71+
You can find `gfmrun` here:
72+
73+
- [urfave/gfmrun](https://github.com/urfave/gfmrun)
74+
75+
To install `gfmrun`, you can use `go install`:
76+
77+
```
78+
go install github.com/urfave/gfmrun/cmd/gfmrun@latest
79+
```
80+
6981
In the event that the `v3diff` target exits non-zero, this is a signal that the public API
7082
surface area has changed. If the changes are acceptable, then manually running the
7183
approval step will "promote" the current `go doc` output:

docs/index.md

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,12 @@ Go Modules are required when using this package. [See the go blog guide on using
4646

4747
### Using `v3` releases
4848

49-
The latest `v3` release may be installed via the `/v3` suffix. The state of the [`main`
50-
branch](https://github.com/urfave/cli/tree/main) at any given time may correspond to a
51-
`v3` series release or pre-release. Please see the [`v3` migration
52-
guide](./migrate-v2-to-v3.md) on using v3 if you are upgrading from v2.
49+
The latest `v3` release may be installed via the `/v3` suffix and is the
50+
recommended version for all new development. The state of the [`main`
51+
branch](https://github.com/urfave/cli/tree/main) at any given time **may**
52+
correspond to a `v3` series release or pre-release. Please see the [`v3`
53+
migration guide](./migrate-v2-to-v3.md) on using v3 if you are upgrading from
54+
v2.
5355

5456
```sh
5557
go get github.com/urfave/cli/v3@latest
@@ -63,10 +65,11 @@ import (
6365

6466
### Using `v2` releases
6567

66-
The `v2` series is the recommended version for new development. Ongoing
67-
maintenance is done on the [`v2-maint`
68-
branch](https://github.com/urfave/cli/tree/v2-maint) which receives **minor**
69-
improvements, bug fixes, and security fixes.
68+
:warning: The `v2` series is receiving **security and bug fixes only** via the
69+
[`v2-maint` branch](https://github.com/urfave/cli/tree/v2-maint) and **should
70+
not** be used in new development. Please see the [`v3` migration
71+
guide](./migrate-v2-to-v3.md) and feel free to open an issue or discussion if
72+
you need help with the migration to `v3`.
7073

7174
```sh
7275
go get github.com/urfave/cli/v2@latest
@@ -81,7 +84,7 @@ import (
8184
### Using `v1` releases
8285

8386
:warning: The `v1` series is receiving **security fixes only** via the
84-
[`v1-maint`](https://github.com/urfave/cli/tree/v1-maint) branch and **should
87+
[`v1-maint` branch](https://github.com/urfave/cli/tree/v1-maint) and **should
8588
not** be used in new development. Please see the [`v2` migration
8689
guide](./migrate-v1-to-v2.md) and feel free to open an issue or discussion if
8790
you need help with the migration to `v2`.

docs/v3/examples/arguments/advanced.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ search:
77

88
The [Basics] showed how to access arguments for a command. They are all retrieved as strings which is fine
99
but it we need to say get integers or timestamps the user would have to convert from string to desired type.
10-
To ease the burden on users the `cli` library offers predefined `{Type}Arg` and `{Type}Args` structure to faciliate this
10+
To ease the burden on users the `cli` library offers predefined `{Type}Arg` and `{Type}Args` structure to faciliate this.
1111
The value of the argument can be retrieved using the `command.{Type}Arg()` function. For e.g
1212

1313
<!-- {
@@ -152,9 +152,9 @@ func main() {
152152

153153
Some things to note about multi value arguments
154154

155-
1. They are of `{Type}Args` type rather than `{Type}Arg` to differentiate them from single value arguments
156-
2. The `Max` field needs to be defined to a non zero value without which it cannot be parsed
157-
3. `Max` field value needs to be greater than the `Min` field value
155+
1. They are of `{Type}Args` type rather than `{Type}Arg` to differentiate them from single value arguments.
156+
2. The `Max` field needs to be defined to a non zero value without which it cannot be parsed.
157+
3. `Max` field value needs to be greater than the `Min` field value.
158158

159159
As with single value args the destination field can be set
160160

@@ -221,4 +221,4 @@ the following to the end of the Arguments slice and retrieve them as a slice
221221
&StringArgs{
222222
Max: -1,
223223
},
224-
```
224+
```

0 commit comments

Comments
 (0)