Skip to content

Commit

Permalink
Merge branch 'main' into feat/flag-action
Browse files Browse the repository at this point in the history
  • Loading branch information
meatballhat committed May 7, 2022
2 parents fe814ab + c6f7393 commit 239dab5
Show file tree
Hide file tree
Showing 35 changed files with 5,773 additions and 536 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/cli.yml
Expand Up @@ -87,3 +87,8 @@ jobs:

- name: toc
run: go run internal/build/build.go toc docs/v2/manual.md

- name: diff check
run: |
git diff --exit-code
git diff --cached --exit-code
32 changes: 32 additions & 0 deletions Makefile
@@ -0,0 +1,32 @@
# NOTE: this Makefile is meant to provide a simplified entry point for humans to
# run all of the critical steps to verify one's changes are harmonious in
# nature. Keeping target bodies to one line each and abstaining from make magic
# are very important so that maintainers and contributors can focus their
# attention on files that are primarily Go.

.PHONY: all
all: generate vet tag-test test check-binary-size tag-check-binary-size gfmrun toc v2diff

# NOTE: this is a special catch-all rule to run any of the commands
# defined in internal/build/build.go with optional arguments passed
# via GFLAGS (global flags) and FLAGS (command-specific flags), e.g.:
#
# $ make test GFLAGS='--packages cli'
%:
go run internal/build/build.go $(GFLAGS) $* $(FLAGS)

.PHONY: tag-test
tag-test:
go run internal/build/build.go -tags urfave_cli_no_docs test

.PHONY: tag-check-binary-size
tag-check-binary-size:
go run internal/build/build.go -tags urfave_cli_no_docs check-binary-size

.PHONY: gfmrun
gfmrun:
go run internal/build/build.go gfmrun docs/v2/manual.md

.PHONY: toc
toc:
go run internal/build/build.go toc docs/v2/manual.md
2 changes: 1 addition & 1 deletion cli.go
Expand Up @@ -20,4 +20,4 @@
// }
package cli

//go:generate go run flag-gen/main.go flag-gen/assets_vfsdata.go
//go:generate go run internal/genflags/cmd/genflags/main.go
135 changes: 119 additions & 16 deletions docs/CONTRIBUTING.md
@@ -1,18 +1,121 @@
## Contributing

Use @urfave/cli to ping the maintainers.

Feel free to put up a pull request to fix a bug or maybe add a feature. We will
give it a code review and make sure that it does not break backwards
compatibility. If collaborators agree that it is in line with
the vision of the project, we will work with you to get the code into
a mergeable state and merge it into the main branch.

If you have contributed something significant to the project, we will most
likely add you as a collaborator. As a collaborator you are given the ability
to merge others pull requests. It is very important that new code does not
break existing code, so be careful about what code you do choose to merge.

If you feel like you have contributed to the project but have not yet been added
as a collaborator, we probably forgot to add you :sweat_smile:. Please open an
issue!
Welcome to the `urfave/cli` contributor docs! This goal of this document is to help those
interested in joining the 200+ humans who have contributed to this project over the years.

> As a general guiding principle, the current maintainers may be notified via the
> @urfave/cli GitHub team.
All of the current maintainers are *volunteers* who live in various timezones with
different scheduling needs, so please understand that your contribution or question may
not get a response for many days.

### semantic versioning adherence

The `urfave/cli` project strives to strictly adhere to [semantic
versioning](https://semver.org/spec/v2.0.0.html). The active development branches and the
milestones and import paths to which they correspond are:

#### `main` branch

<https://github.com/urfave/cli/tree/main>

The majority of active development and issue management is targeting the `main` branch,
which **MUST** *only* receive bug fixes and feature *additions*.

- :arrow_right: [`v2.x`](https://github.com/urfave/cli/milestone/16)
- :arrow_right: `github.com/urfave/cli/v2`

The `main` branch in particular includes tooling to help with keeping the `v2.x` series
backward compatible. More details on this process are in the development workflow section
below.

#### `v1` branch

<https://github.com/urfave/cli/tree/v1>

The `v1` branch **MUST** only receive bug fixes in the `v1.22.x` series. There is no
strict rule regarding bug fixes to the `v2.x` series being backported to the `v1.22.x`
series.

- :arrow_right: [`v1.22.x`](https://github.com/urfave/cli/milestone/11)
- :arrow_right: `github.com/urfave/cli`

#### `v3-dev-main` branch

<https://github.com/urfave/cli/tree/v3-dev-main>

The `v3-dev-branch` **MUST** receive all bug fixes and features added to the `main` branch
and **MAY** receive feature *removals* and other changes that are otherwise
*backward-incompatible* with the `v2.x` series.

- :arrow_right: [`v3.x`](https://github.com/urfave/cli/milestone/5)
- unreleased / unsupported

### development workflow

Most of the tooling around the development workflow strives for effective
[dogfooding](https://en.wikipedia.org/wiki/Eating_your_own_dog_food). There is a top-level
`Makefile` that is maintained strictly for the purpose of easing verification of one's
development environment and any changes one may have introduced:

```sh
make
```

Running the default `make` target (`all`) will ensure all of the critical steps are run to
verify one's changes are harmonious in nature. The same steps are also run during the
[continuous integration
phase](https://github.com/urfave/cli/blob/main/.github/workflows/cli.yml).

In the event that the `v2diff` target exits non-zero, this is a signal that the public API
surface area has changed. If the changes adhere to semantic versioning, meaning they are
*additions* or *bug fixes*, then manually running the approval step will "promote" the
current `go doc` output:

```sh
make v2approve
```

Because the `generate` step includes updating `godoc-current.txt` and
`testdata/godoc-v2.x.txt`, these changes *MUST* be part of any proposed pull request so
that reviewers have an opportunity to also make an informed decision about the "promotion"
step.

#### generated code

A significant portion of the project's source code is generated, with the goal being to
eliminate repetetive maintenance where other type-safe abstraction is impractical or
impossible with Go versions `< 1.18`. In a future where the eldest Go version supported is
`1.18.x`, there will likely be efforts to take advantage of
[generics](https://go.dev/doc/tutorial/generics).

The built-in `go generate` command is used to run the commands specified in
`//go:generate` directives. Each such command runs a file that also supports a command
line help system which may be consulted for further information, e.g.:

```sh
go run internal/genflags/cmd/genflags/main.go --help
```

### pull requests

Please feel free to open a pull request to fix a bug or add a feature. The @urfave/cli
team will review it as soon as possible, giving special attention to maintaining backward
compatibility. If the @urfave/cli team agrees that your contribution is in line with the
vision of the project, they will work with you to get the code into a mergeable state,
merged, and then released.

### granting of commit bit / admin mode

Those with a history of contributing to this project will likely be invited to join the
@urfave/cli team. As a member of the @urfave/cli team, you will have the ability to fully
administer pull requests, issues, and other repository bits.

If you feel that you should be a member of the @urfave/cli team but have not yet been
added, the most likely explanation is that this is an accidental oversight! :sweat_smile:.
Please open an issue!

<!--
vim:tw=90
-->
50 changes: 50 additions & 0 deletions flag-spec.yaml
@@ -0,0 +1,50 @@
# NOTE: this file is used by the tool defined in
# ./internal/genflags/cmd/genflags/main.go which uses the
# `genflags.Spec` type that maps to this file structure.

flag_types:
bool: {}
float64: {}
int64: {}
int: {}
time.Duration: {}
uint64: {}
uint: {}

string:
struct_fields:
- { name: TakesFile, type: bool }
Generic:
struct_fields:
- { name: TakesFile, type: bool }
Path:
struct_fields:
- { name: TakesFile, type: bool }

Float64Slice:
value_pointer: true
skip_interfaces:
- fmt.Stringer
Int64Slice:
value_pointer: true
skip_interfaces:
- fmt.Stringer
IntSlice:
value_pointer: true
skip_interfaces:
- fmt.Stringer
StringSlice:
value_pointer: true
skip_interfaces:
- fmt.Stringer
struct_fields:
- { name: TakesFile, type: bool }
Timestamp:
value_pointer: true
struct_fields:
- { name: Layout, type: string }

# TODO: enable UintSlice
# UintSlice: {}
# TODO: enable Uint64Slice once #1334 lands
# Uint64Slice: {}
2 changes: 1 addition & 1 deletion flag.go
Expand Up @@ -264,7 +264,7 @@ func withEnvHint(envVars []string, str string) string {
return str + envText
}

func flagNames(name string, aliases []string) []string {
func FlagNames(name string, aliases []string) []string {
var ret []string

for _, part := range append([]string{name}, aliases...) {
Expand Down
32 changes: 0 additions & 32 deletions flag_bool.go
Expand Up @@ -6,38 +6,6 @@ import (
"strconv"
)

// BoolFlag is a flag with type bool
type BoolFlag struct {
Name string
Aliases []string
Usage string
EnvVars []string
FilePath string
Required bool
Hidden bool
Value bool
DefaultText string
Destination *bool
HasBeenSet bool
Action func(*Context, bool) error
}

// IsSet returns whether or not the flag has been set through env or file
func (f *BoolFlag) IsSet() bool {
return f.HasBeenSet
}

// String returns a readable representation of this value
// (for usage defaults)
func (f *BoolFlag) String() string {
return FlagStringer(f)
}

// Names returns the names of the flag
func (f *BoolFlag) Names() []string {
return flagNames(f.Name, f.Aliases)
}

// IsRequired returns whether or not the flag is required
func (f *BoolFlag) IsRequired() bool {
return f.Required
Expand Down
32 changes: 0 additions & 32 deletions flag_duration.go
Expand Up @@ -6,38 +6,6 @@ import (
"time"
)

// DurationFlag is a flag with type time.Duration (see https://golang.org/pkg/time/#ParseDuration)
type DurationFlag struct {
Name string
Aliases []string
Usage string
EnvVars []string
FilePath string
Required bool
Hidden bool
Value time.Duration
DefaultText string
Destination *time.Duration
HasBeenSet bool
Action func(*Context, time.Duration) error
}

// IsSet returns whether or not the flag has been set through env or file
func (f *DurationFlag) IsSet() bool {
return f.HasBeenSet
}

// String returns a readable representation of this value
// (for usage defaults)
func (f *DurationFlag) String() string {
return FlagStringer(f)
}

// Names returns the names of the flag
func (f *DurationFlag) Names() []string {
return flagNames(f.Name, f.Aliases)
}

// IsRequired returns whether or not the flag is required
func (f *DurationFlag) IsRequired() bool {
return f.Required
Expand Down
32 changes: 0 additions & 32 deletions flag_float64.go
Expand Up @@ -6,38 +6,6 @@ import (
"strconv"
)

// Float64Flag is a flag with type float64
type Float64Flag struct {
Name string
Aliases []string
Usage string
EnvVars []string
FilePath string
Required bool
Hidden bool
Value float64
DefaultText string
Destination *float64
HasBeenSet bool
Action func(*Context, float64) error
}

// IsSet returns whether or not the flag has been set through env or file
func (f *Float64Flag) IsSet() bool {
return f.HasBeenSet
}

// String returns a readable representation of this value
// (for usage defaults)
func (f *Float64Flag) String() string {
return FlagStringer(f)
}

// Names returns the names of the flag
func (f *Float64Flag) Names() []string {
return flagNames(f.Name, f.Aliases)
}

// IsRequired returns whether or not the flag is required
func (f *Float64Flag) IsRequired() bool {
return f.Required
Expand Down

0 comments on commit 239dab5

Please sign in to comment.