Merge pull request #1385 from urfave/semver-approval-gate
Introduce a v2.x semver approval gate
This commit is contained in:
commit
c6f7393473
28
Makefile
28
Makefile
@ -5,30 +5,22 @@
|
|||||||
# attention on files that are primarily Go.
|
# attention on files that are primarily Go.
|
||||||
|
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
all: generate lint tag-test test check-bin tag-check-bin gfmrun toc
|
all: generate vet tag-test test check-binary-size tag-check-binary-size gfmrun toc v2diff
|
||||||
|
|
||||||
.PHONY: generate
|
# NOTE: this is a special catch-all rule to run any of the commands
|
||||||
generate:
|
# defined in internal/build/build.go with optional arguments passed
|
||||||
go run internal/build/build.go generate
|
# via GFLAGS (global flags) and FLAGS (command-specific flags), e.g.:
|
||||||
|
#
|
||||||
.PHONY: lint
|
# $ make test GFLAGS='--packages cli'
|
||||||
lint:
|
%:
|
||||||
go run internal/build/build.go vet
|
go run internal/build/build.go $(GFLAGS) $* $(FLAGS)
|
||||||
|
|
||||||
.PHONY: tag-test
|
.PHONY: tag-test
|
||||||
tag-test:
|
tag-test:
|
||||||
go run internal/build/build.go -tags urfave_cli_no_docs test
|
go run internal/build/build.go -tags urfave_cli_no_docs test
|
||||||
|
|
||||||
.PHONY: test
|
.PHONY: tag-check-binary-size
|
||||||
test:
|
tag-check-binary-size:
|
||||||
go run internal/build/build.go test
|
|
||||||
|
|
||||||
.PHONY: check-bin
|
|
||||||
check-bin:
|
|
||||||
go run internal/build/build.go check-binary-size
|
|
||||||
|
|
||||||
.PHONY: tag-check-bin
|
|
||||||
tag-check-bin:
|
|
||||||
go run internal/build/build.go -tags urfave_cli_no_docs check-binary-size
|
go run internal/build/build.go -tags urfave_cli_no_docs check-binary-size
|
||||||
|
|
||||||
.PHONY: gfmrun
|
.PHONY: gfmrun
|
||||||
|
@ -12,8 +12,9 @@ not get a response for many days.
|
|||||||
|
|
||||||
### semantic versioning adherence
|
### semantic versioning adherence
|
||||||
|
|
||||||
The `urfave/cli` project strives to strictly adhere to semantic versioning. The active
|
The `urfave/cli` project strives to strictly adhere to [semantic
|
||||||
development branches and the milestones and import paths to which they correspond are:
|
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
|
#### `main` branch
|
||||||
|
|
||||||
@ -25,6 +26,10 @@ which **MUST** *only* receive bug fixes and feature *additions*.
|
|||||||
- :arrow_right: [`v2.x`](https://github.com/urfave/cli/milestone/16)
|
- :arrow_right: [`v2.x`](https://github.com/urfave/cli/milestone/16)
|
||||||
- :arrow_right: `github.com/urfave/cli/v2`
|
- :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
|
#### `v1` branch
|
||||||
|
|
||||||
<https://github.com/urfave/cli/tree/v1>
|
<https://github.com/urfave/cli/tree/v1>
|
||||||
@ -63,6 +68,20 @@ verify one's changes are harmonious in nature. The same steps are also run durin
|
|||||||
[continuous integration
|
[continuous integration
|
||||||
phase](https://github.com/urfave/cli/blob/main/.github/workflows/cli.yml).
|
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
|
#### generated code
|
||||||
|
|
||||||
A significant portion of the project's source code is generated, with the goal being to
|
A significant portion of the project's source code is generated, with the goal being to
|
||||||
|
2090
godoc-current.txt
Normal file
2090
godoc-current.txt
Normal file
File diff suppressed because it is too large
Load Diff
@ -10,11 +10,29 @@ import (
|
|||||||
"math"
|
"math"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
badNewsEmoji = "🚨"
|
||||||
|
goodNewsEmoji = "✨"
|
||||||
|
checksPassedEmoji = "✅"
|
||||||
|
|
||||||
|
v2diffWarning = `
|
||||||
|
# The unified diff above indicates that the public API surface area
|
||||||
|
# has changed. If you feel that the changes are acceptable and adhere
|
||||||
|
# to the semantic versioning promise of the v2.x series described in
|
||||||
|
# docs/CONTRIBUTING.md, please run the following command to promote
|
||||||
|
# the current go docs:
|
||||||
|
#
|
||||||
|
# make v2approve
|
||||||
|
#
|
||||||
|
`
|
||||||
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
top, err := func() (string, error) {
|
top, err := func() (string, error) {
|
||||||
if v, err := sh("git", "rev-parse", "--show-toplevel"); err == nil {
|
if v, err := sh("git", "rev-parse", "--show-toplevel"); err == nil {
|
||||||
@ -57,6 +75,17 @@ func main() {
|
|||||||
Name: "generate",
|
Name: "generate",
|
||||||
Action: GenerateActionFunc,
|
Action: GenerateActionFunc,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "v2diff",
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
&cli.BoolFlag{Name: "color", Value: false},
|
||||||
|
},
|
||||||
|
Action: V2Diff,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "v2approve",
|
||||||
|
Action: V2Approve,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
app.Flags = []cli.Flag{
|
app.Flags = []cli.Flag{
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
@ -206,9 +235,6 @@ func checkBinarySizeActionFunc(c *cli.Context) (err error) {
|
|||||||
helloSourceFilePath = "./internal/example-hello-world/example-hello-world.go"
|
helloSourceFilePath = "./internal/example-hello-world/example-hello-world.go"
|
||||||
helloBuiltFilePath = "./internal/example-hello-world/built-example"
|
helloBuiltFilePath = "./internal/example-hello-world/built-example"
|
||||||
desiredMaxBinarySize = 2.2
|
desiredMaxBinarySize = 2.2
|
||||||
badNewsEmoji = "🚨"
|
|
||||||
goodNewsEmoji = "✨"
|
|
||||||
checksPassedEmoji = "✅"
|
|
||||||
mbStringFormatter = "%.1fMB"
|
mbStringFormatter = "%.1fMB"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -290,9 +316,68 @@ func checkBinarySizeActionFunc(c *cli.Context) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GenerateActionFunc(cCtx *cli.Context) error {
|
func GenerateActionFunc(cCtx *cli.Context) error {
|
||||||
|
top := cCtx.Path("top")
|
||||||
|
|
||||||
|
cliDocs, err := sh("go", "doc", "-all", top)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
altsrcDocs, err := sh("go", "doc", "-all", filepath.Join(top, "altsrc"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := os.WriteFile(
|
||||||
|
filepath.Join(top, "godoc-current.txt"),
|
||||||
|
[]byte(cliDocs+altsrcDocs),
|
||||||
|
0644,
|
||||||
|
); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return runCmd("go", "generate", cCtx.Path("top")+"/...")
|
return runCmd("go", "generate", cCtx.Path("top")+"/...")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func V2Diff(cCtx *cli.Context) error {
|
||||||
|
os.Chdir(cCtx.Path("top"))
|
||||||
|
|
||||||
|
err := runCmd(
|
||||||
|
"diff",
|
||||||
|
"--ignore-all-space",
|
||||||
|
"--minimal",
|
||||||
|
"--color="+func() string {
|
||||||
|
if cCtx.Bool("color") {
|
||||||
|
return "always"
|
||||||
|
}
|
||||||
|
return "auto"
|
||||||
|
}(),
|
||||||
|
"--unified",
|
||||||
|
"--label=a/godoc",
|
||||||
|
filepath.Join("testdata", "godoc-v2.x.txt"),
|
||||||
|
"--label=b/godoc",
|
||||||
|
"godoc-current.txt",
|
||||||
|
)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("# %v ---> Hey! <---\n", badNewsEmoji)
|
||||||
|
fmt.Println(strings.TrimSpace(v2diffWarning))
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func V2Approve(cCtx *cli.Context) error {
|
||||||
|
top := cCtx.Path("top")
|
||||||
|
|
||||||
|
return runCmd(
|
||||||
|
"cp",
|
||||||
|
"-v",
|
||||||
|
filepath.Join(top, "godoc-current.txt"),
|
||||||
|
filepath.Join(top, "testdata", "godoc-v2.x.txt"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
func getSize(sourcePath string, builtPath string, tags string) (size int64, err error) {
|
func getSize(sourcePath string, builtPath string, tags string) (size int64, err error) {
|
||||||
// build example binary
|
// build example binary
|
||||||
err = runCmd("go", "build", "-tags", tags, "-o", builtPath, "-ldflags", "-s -w", sourcePath)
|
err = runCmd("go", "build", "-tags", tags, "-o", builtPath, "-ldflags", "-s -w", sourcePath)
|
||||||
|
2090
testdata/godoc-v2.x.txt
vendored
Normal file
2090
testdata/godoc-v2.x.txt
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user