Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cobra User Contract (Draft) #1232

Closed
jharshman opened this issue Sep 22, 2020 · 14 comments · Fixed by #1292
Closed

Cobra User Contract (Draft) #1232

jharshman opened this issue Sep 22, 2020 · 14 comments · Fixed by #1292
Assignees

Comments

@jharshman
Copy link
Collaborator

jharshman commented Sep 22, 2020

Below you will find a draft of expectations for the project. This has been put together and reviewed by maintainers.
We are now asking for community feedback.

Cobra User Contract

Versioning

Cobra will follow a steady release cadence. Users can expect a major release quarterly. Non breaking changes will also be released as minor versions quarterly. Patch bug releases are at the discretion of the maintainers. Users can expect security patch fixes to be released within the week of these becoming known. Releases will follow Semantic Versioning. Users tracking the Master branch should expect unpredictable breaking changes as the project continues to move forward. For stability, it is highly recommended to use a release.

Backward Compatibility

We will maintain two major releases in a moving window. The N-1 release will only receive bug fixes and security updates and will be dropped once N+1 is released.

Deprecation

Deprecation of Go versions or dependent packages will only occur in major releases. To reduce the change of this taking users by surprise, any large deprecation will be preceded by an announcement in the #cobra slack channel and an Issue on Github.

Communication

Cobra maintainers will use GitHub issues and the #cobra slack channel as the primary means of communication with the community. This is to foster open communication with all users and contributors.

Breaking Changes

Breaking changes are generally allowed in the master branch, as this is the branch used to develop the next release of Cobra.

There may be times, however, when master is closed for breaking changes. This is likely to happen as we near the release of a new version.

Breaking changes are not allowed in release branches, as these represent minor versions that have already been released. These version have consumers who expect the APIs, behaviors, etc, to remain stable during the lifetime of the patch stream for the minor release.

Examples of breaking changes include:

  • Removing or renaming exported constant, variable, type, or function.
  • Updating the version of critical libraries such as spf13/pflag, spf13/viper etc...
    • Some version updates may be acceptable for picking up bug fixes, but maintainers must exercise caution when reviewing.

There may, at times, need to be exceptions where breaking changes are allowed in release branches. These are at the discretion of the project's maintainers, and must be carefully considered before merging.

CI Testing

Maintainers will ensure the the Cobra test suite utilizes the current supported versions of Golang.

@marckhouzam
Copy link
Collaborator

Thank you @jharshman @jpmcb @wfernandes for putting forth this proposal!

I warmly welcome the well-defined schedule of releases (coincidentally, the helm project will also be moving to such a predictable schedule, to make it easier on users).

Users can expect a major release quarterly.

I love the quarterly release schedule. I'm a little surprised the releases will be major releases however. Are we even expecting breaking changes to be suggested so often? What release type will be done if all changes in a quarter are backwards-compatible?

Breaking changes are generally allowed in the master branch, as this is the branch used to develop the next minor release of Cobra.

I assume this should read "the branch used to develop the next major release of Cobra"?

Finally, with this new branching strategy, to which branch should PRs be submitted? Should they always target the master branch and then maintainers will ask for it to also be submitted to a release branche, if appropriate?

All the rest is 👍 for me!

Thanks again!

@umarcor
Copy link
Contributor

umarcor commented Sep 25, 2020

As Marc said, thanks a lot for moving forward with this proposal! The project really needs it!

Users can expect a major release quarterly. Non breaking changes will also be released as minor versions quarterly.

Releases will follow Semantic Versioning

I believe there is a wording issue here. Let me reword it:

Users can expect a tagged release of the latest major branch quarterly. Tagged releases including non breaking changes (almost exclusively) will also be published for other supported major branches quarterly. As explained in Backward Compatibility, a single other major branch will be supported.

That is, the decision about releases being major or minor cannot be stablished according to a regular time schedule, because that is incompatible with Semantic Versioning. The specific modifications that were added in a given period is what dictates what the next version should be (bugfix, minor or major).

It is possible to tag three consecutive releases of the latest major branch, without introducing a major bump. That would mean that contributors and maintainers coordinate for adding breaking changes during 1 quarter each year. Note, that this is just for illustration purposes.

For stability, it is highly recommended to use a published release.

I'd say "to use a tagged release" or just "to use a release". Per se, all releases are published.

Breaking changes are generally allowed in the master branch, as this is the branch used to develop the next minor release of Cobra.

Coherently, "as this is the major branch used to develop the next release of Cobra".

Deprecation of Go versions or dependent packages will only occur in major releases. To reduce the change of this taking users by surprise, any large deprecation will be preceded by an announcement in the #cobra slack channel and an Issue on Github.

Is there any starting plan for this? That is, which are the currently supported versions of Go?

According to #968:

  • Ubuntu and macOS: 1.11, 1.12, 1.13 and 1.14 pass. 1.10 fails.
  • Windows: 1.12, 1.13 and 1.14 pass. 1.10 and 1.11 fail.

Results are the same in Travis CI, but there Ubuntu is tested only.

Hence, it seems that 1.10 is deprecated de facto, and 1.11 is unsupported on Windows. Will support on Windows with Go 1.11 be fixed or shall we start with "Cobra 1.0.0 requires Go >=1.12"? Ref: https://endoflife.date/go

Cobra maintainers will use GitHub issues and the #cobra slack channel as the primary means of communication with the community. This is to foster open communication with all users and contributors.

Is it possible to have a separate chat channel which does not require handling credentials other than the ones used in GitHub?

Maintainers will run the Cobra test suite for the supported versions of Golang.

I will update #968 as soon as the list of supported versions of Golang is made explicit. That will allow maintainers not to worry about running the test suite themselves. Moreover, any contributor will have it done automatically.

@jpmcb
Copy link
Collaborator

jpmcb commented Oct 1, 2020

On releasing major versions every quarter, I believe the original intention behind this was to effectively deprecated versions of Go that Cobra supports. It may start as a slow march to deprecate go 1.10, 1.11 etc, but this way, we would at least give users an expected time frame for when they would need to update go in their cobra projects.

To @umarcor's point, I'm not sure if we would immediately deprecate versions of go <1.12 but instead, slowly roll out issues and announcements in quarterly releases that would constitute a breaking change. However, you bring up a good point that 1.10 and 1.11 are already basically broken.

Is it possible to have a separate chat channel which does not require handling credentials other than the ones used in GitHub?

Any suggestions? The cobra slack channel in the Go workspace is already fairly well populated and gets some good community traffic.

As far as branching strategies go, I'd imagine that we would cut new branches per release in this repository. But that may be an implementation detail we haven't ironed out yet. Any suggestions that have worked well for you @marckhouzam ?

@marckhouzam
Copy link
Collaborator

As far as branching strategies go, I'd imagine that we would cut new branches per release in this repository. But that may be an implementation detail we haven't ironed out yet. Any suggestions that have worked well for you @marckhouzam ?

I imagined something along what you hint at @jpmcb:

  • cutting a release branch, say 1.1 and releasing from there (this could allow for some soak time if needed)
  • continuing development on the master branch (I would advocate trying to avoid breaking changes as much as possible)
  • PRs would target the master branch, and if the submitter cares about the previous release, we would ask that they submit another PR to the release branch. If the PR is a bug that is not present on the master branch, then it should go straight to the release branch.
  • at the next cycle, cutting a new branch based on if the release contains breaking changes or not, so 1.2 or 2.0

I'm sure I'm skipping some details though.
What do you think?

@umarcor
Copy link
Contributor

umarcor commented Oct 3, 2020

On releasing major versions every quarter, I believe the original intention behind this was to effectively deprecated versions of Go that Cobra supports. It may start as a slow march to deprecate go 1.10, 1.11 etc, but this way, we would at least give users an expected time frame for when they would need to update go in their cobra projects.

I agree it might be good to deprecate a golang version every quarter, for a start. However, in the mid term, we should deprecate versions of go every two quarters, because that's go's release period. Note that we don't need to match go's supported versions, we can be 1 or 2 versions behind, as we do now.

To @umarcor's point, I'm not sure if we would immediately deprecate versions of go <1.12 but instead, slowly roll out issues and announcements in quarterly releases that would constitute a breaking change. However, you bring up a good point that 1.10 and 1.11 are already basically broken.

I think that 1.10 should be deprecated immediately. Regarding 1.11, should it be delayed some months, I believe fixing the windows jobs/builds would be a high priority.

Any suggestions? The cobra slack channel in the Go workspace is already fairly well populated and gets some good community traffic.

Gitter is the de facto standard. It has a nice integration with GitHub (users/permissions, refs, events, etc.). It is open source. It was bought by GitLab and a few days ago bought by Element, who is focusing on integration with Matrix.

As far as branching strategies go, I'd imagine that we would cut new branches per release in this repository. But that may be an implementation detail we haven't ironed out yet. Any suggestions that have worked well for you @marckhouzam ?

I think it's not necessary to cut new branches, until a bugfix is applied to that release. Apart from that, I agree with @marckhouzam's description.

@marckhouzam
Copy link
Collaborator

On releasing major versions every quarter, I believe the original intention behind this was to effectively deprecated versions of Go that Cobra supports.

I think we should make an explicit difference between removing Go version support and allowing changes that break backwards-compatibility.

For example, helm regularly moves to newer Go versions, and therefore would not worry about a new version of Cobra changing its Go support. However, if the new version of Cobra also changes its API in a non-backwards-compatible way, then this would impact helm pretty much every time.

May I suggest allowing to drop Go versions quarterly, but only allowing API breaking changes much less often?

@jpmcb
Copy link
Collaborator

jpmcb commented Oct 6, 2020

I agree with you Marc, I can't imagine the Cobra API changing (and breaking) much. It's relatively very stable and I don't anticipate things changing with it. I'd imagine we'd change the wording to be more specific around go version deprecation.

I don't think it's a explicit "we will break Cobra's interface every quarter" but rather, "we anticipate deprecating versions of Go quarterly / bi-quarterly with the cadence of Golang itself"

I think the next steps for this would be to open a PR and get further community feedback. Stay tuned for that!

@marckhouzam
Copy link
Collaborator

Are the maintainers still considering going ahead with this user contract? Just curious, and hopeful 😄

@github-actions
Copy link

This issue is being marked as stale due to a long period of inactivity

@umarcor
Copy link
Contributor

umarcor commented Feb 10, 2021

@anthonyfok, with regard to v1.1.2 tagged a few hours ago, please see: https://github.com/spf13/cobra/blob/master/CONDUCT.md

Non breaking changes will be released as minor versions quarterly.

Deprecation of Go versions or dependent packages will only occur in major releases. To reduce the change of this taking users by surprise, any large deprecation will be preceded by an announcement in the #cobra slack channel and an Issue on Github.

v1.1.2 is not semver compliant because several breaking changes were introduced since v1.1.1.

@anthonyfok
Copy link
Collaborator

anthonyfok commented Feb 10, 2021

v1.1.2 is not semver compliant because several breaking changes were introduced since v1.1.1.

I believe that there is only one potential breaking change, and that is the artificial requirement bump to >= go1.14. Cobra @master builds perfectly fine with go1.12.

I will be releasing v1.1.3 in its own release-branch.cobra1.1 branch to fix my oversight with the v1.1.2 release. My apologies.

Edit: Done! v1.1.3 is released.

anthonyfok added a commit that referenced this issue Feb 10, 2021
…ility

Resolves "v1.1.2 is not semver compliant" due to deprecation of Go version

See #1232 (comment)

This reverts commit 1d71ff0.
@umarcor
Copy link
Contributor

umarcor commented Feb 10, 2021

AFAIAA until >=1.14 was committed, there was no explicit set of supported versions. Hence, it would theoretically go back to 1.11, 1.10... I believe that setting >=1.14 was primarily for making a first official statement about it, which is coherent with the contract.

Even though cobra might work with 1.12 or 1.13, IMHO we should discourage usage of unmaintained software (https://endoflife.date/go).

No need to apologise. This was a recent addition to the repo and oversights can happen.

@anthonyfok
Copy link
Collaborator

anthonyfok commented Feb 10, 2021

AFAIAA until >=1.14 was committed, there was no explicit set of supported versions. Hence, it would theoretically go back to 1.11, 1.10...

I thought so too until I actually went and tested it. go1.12 is indeed the minimum requirement because of the use of io.StringWriter. Cobra v1.1.3 fails to build with go1.11 with the following errors:

./bash_completions.go:22:24: undefined: io.StringWriter
./bash_completions.go:383:26: undefined: io.StringWriter
./bash_completions.go:423:24: undefined: io.StringWriter
./bash_completions.go:435:27: undefined: io.StringWriter
./bash_completions.go:473:25: undefined: io.StringWriter
./bash_completions.go:484:20: undefined: io.StringWriter
./bash_completions.go:499:38: undefined: io.StringWriter
./bash_completions.go:525:21: undefined: io.StringWriter
./bash_completions.go:562:28: undefined: io.StringWriter
./bash_completions.go:587:29: undefined: io.StringWriter
./bash_completions.go:587:29: too many errors

I believe that setting >=1.14 was primarily for making a first official statement about it, which is coherent with the contract.

Yes, exactly, and that is actually something I'm a bit uncomfortable with. The go directive in go.mod should be set for technical reasons, and not artificially bumped merely to make an official statement to be coherent with a User Contract.

It is perfectly fine to bump the Go version requirement for Travis CI, for GitHub workflows, and to document in README.md (for example) that the community will not support end users using Go << 1.14. However, IMHO, go.mod should not be modified for this reason, because:

  1. Other Go projects do not make such "official statement" with a "User Contract".
  2. Google don't artificially inflate go version in their go.mod either, see for example:
    a. https://github.com/golang/crypto/blob/master/go.mod
    b. https://github.com/golang/net/blob/master/go.mod
    c. https://github.com/golang/sys/blob/master/go.mod
  3. go is smart enough to modify the go directive in go.mod as technically necessary.
  4. There are users using older OSes, or for whatever other reasons, somehow need to stay with an older version of Go, even though that is highly discouraged.

Thankfully, go itself isn't strict about the version specified in the go directive of go.mod, as documented in https://golang.org/doc/go1.12#modules:

The go directive in a go.mod file now indicates the version of the language used by the files within that module. It will be set to the current release (go 1.12) if no existing version is present. If the go directive for a module specifies a version newer than the toolchain in use, the go command will attempt to build the packages regardless, and will note the mismatch only if that build fails.

So merely setting go 1.14 in go.mod does not actually break compatibility at all as go itself is very lenient on it. (Oh, does that mean I didn't need to release v1.1.3? Darn it...) But yes, I see that there are already confusions with helm project, so it is worth clearing the confusion with a v1.1.3 release.

Even though cobra might work with 1.12 or 1.13, IMHO we should discourage usage of unmaintained software (https://endoflife.date/go).

Very true, but that is what user documentation is for, not in go.mod, because there are these two goals we should strive for simultaneously:

  1. discourage usage of unmaintained software
  2. maintain maximum backward compatibility with legacy software when possible

@umarcor
Copy link
Contributor

umarcor commented Feb 11, 2021

AFAIAA until >=1.14 was committed, there was no explicit set of supported versions. Hence, it would theoretically go back to 1.11, 1.10...

I thought so too until I actually went and tested it. go1.12 is indeed the minimum requirement because of the use of io.StringWriter. Cobra v1.1.3 fails to build with go1.11 with the following errors:

I'm pretty aware of that, because I'm the one responsible for those breaking changes. I've been almost two years waiting for maintainers to decide when to drop <=1.11 so that we could enable golangci-lint and address rotting of the codebase (#1044). There are other similar enhancements that should land in master soon (#853 #1337).

Those contributions were kept on hold for so long because there was no official voice to decide when should golang versions be deprecated by cobra. Therefore, I'm so glad about having a criteria for releasing and deprecation now.

It is perfectly fine to bump the Go version requirement for Travis CI, for GitHub workflows, and to document in README.md (for example) that the community will not support end users using Go << 1.14. However, IMHO, go.mod should not be modified for this reason, because:

I think this is a fair point. Honestly, I would be good with cobra supporting >=1.12, instead of >=1.14. I think it is undesirable, but I don't have any objection as long as it does not block enhancing/improving the codebase.

  1. There are users using older OSes, or for whatever other reasons, somehow need to stay with an older version of Go, even though that is highly discouraged.

For 1.12 or 1.13, I might agree. For older versions, those users have greater problems than cobra. They can just pick v1 and stick with that. If they want to use bleeding-edge software, they need to understand that sticking with too old OSes is problematic. We might argue that 2.5y is not too long. Yet, Google did already decide that for us. It is.

Even though cobra might work with 1.12 or 1.13, IMHO we should discourage usage of unmaintained software (endoflife.date/go).

Very true, but that is what user documentation is for, not in go.mod, because there are these two goals we should strive for simultaneously:

  1. discourage usage of unmaintained software
  2. maintain maximum backward compatibility with legacy software when possible

Just for clarification, I gotcha and I do agree with you: we can set 1.12 in go.mod and use the CI/documentation for communicating that <1.14 is unsupported/untested by cobra.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants