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

proposal: cmd/go: import the latest version by default if no version specified #44169

Open
pelliu opened this issue Feb 8, 2021 · 13 comments
Open
Labels
Projects
Milestone

Comments

@pelliu
Copy link

@pelliu pelliu commented Feb 8, 2021

What version of Go are you using (go version)?

$ go 1.15

Does this issue reproduce with the latest release?

yes

What operating system and processor architecture are you using (go env)?

mac os , linux and windows

go env Output
GO111MODULE="on"
GOARCH="amd64"
GOBIN="/Users/XXX/go/bin"
GOCACHE="/Users/XXX/Library/Caches/go-build"
GOENV="/Users/XXX/Library/Application Support/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOINSECURE=""
GOMODCACHE="/Users/XXX/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/XXX/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/35/83b9r4213sj5pvm379c5cb0m0000gn/T/go-build349298857=/tmp/go-build -gno-record-gcc-switches -fno-common"

What did you do?

Hi, we are Oracle SDK team, currently we are developing new services and sometimes also need to update the existing service APIs, so making breaking changes are somehow unavoided, after we enabled Go Mod feature, we always need to add "import...../xxxxverson" in each go file, the problem is when users using our SDKs, once we do breaking change, they are also impacted, should update all their go files for import part, this is not very user friendly. I understand specifying the version should be necessary, however, it would be nice if don't specify the version,but by default just point to the latest version, otherwise, it is really painful for us to follow go version bump policy -

A semantic version has the form vMAJOR.MINOR.PATCH.

  • Increment the MAJOR version when you make a backwards incompatible change to the public API of your module. This should only be done when absolutely necessary.

  • Increment the MINOR version when you make a backwards compatible change to the API, like changing dependencies or adding a new function, method, struct field, or type.

  • Increment the PATCH version after making minor changes that don't affect your module's public API or dependencies, like fixing a bug.

https://github.com/oracle/oci-go-sdk/blob/master/analytics/analytics_client.go#L15

What did you expect to see?

import ( "context" "fmt" "github.com/oracle/oci-go-sdk/common" //it should work and point to github.com/oracle/oci-go-sdk/v35/common "github.com/oracle/oci-go-sdk/common/auth" "net/http" )

What did you see instead?

error reported, no version specified.

@D1CED
Copy link

@D1CED D1CED commented Feb 9, 2021

Maybe don't release a major version every week.

Alternative: Use version 0 which explicitly makes no guarantees on API stability.

@pelliu
Copy link
Author

@pelliu pelliu commented Feb 9, 2021

We tried to avoid doing breaking change, however, we have so many services adding new features, which is not easy to control breaking changes, but we also need to follow Go version bump rules, have to do major version bump for breaking changes. If we don't import version in our xxx.go files, the released packages can't be added to https://pkg.go.dev/github.com/oracle/oci-go-sdk?tab=versions, so it is really painful for users to use. I think not only us, but others also have the same problem, I checked some other cloud go sdk, they also have to add breaking changes, however, they did minor and patch version bump, did not follow Golang version bump rule, so I really hope Golang can resolve this, thanks!

@D1CED
Copy link

@D1CED D1CED commented Feb 9, 2021

Should this issue be considered a proposal? If so please do:

@gopherbot, please add labels Proposal,modules

Edit: Oops, gopherbot seem a little too eager

@pelliu
Copy link
Author

@pelliu pelliu commented Feb 9, 2021

@D1CED , thank you so much!

@D1CED
Copy link

@D1CED D1CED commented Feb 11, 2021

@ianlancetaylor can this issue be added to the proposal milestone and slot into the Incoming proposal project section.

This proposal should also be retitled to something like: proposal: import current version by default if no version specified
But I think this needs some more clarification by the author.

Any immediate thoughts?

Thanks.

@deltamualpha
Copy link

@deltamualpha deltamualpha commented Feb 11, 2021

Do you mean you want consumers of your library to be able to just automatically get the latest version at all times, or just that your library doesn't have to refer to itself using the /v{num} format inside its own packages?

@ianlancetaylor
Copy link
Contributor

@ianlancetaylor ianlancetaylor commented Feb 11, 2021

Since you ask, I'll make this a proposal, but I don't see how it could possibly work. In Go different packages must have different import paths. Permitting the same import path to mean different versions of a package can't work.

@ianlancetaylor ianlancetaylor changed the title Can we import the latest version by default if no version specified. proposal: cmd/go: import the latest version by default if no version specified Feb 11, 2021
@gopherbot gopherbot added this to the Proposal milestone Feb 11, 2021
@ianlancetaylor ianlancetaylor added this to Incoming in Proposals Feb 11, 2021
@ianlancetaylor
Copy link
Contributor

@ianlancetaylor ianlancetaylor commented Feb 11, 2021

@peterbourgon
Copy link
Member

@peterbourgon peterbourgon commented Feb 12, 2021

Related: #40323

@jayconrod
Copy link
Contributor

@jayconrod jayconrod commented Feb 12, 2021

This goes against a key design goal of modules: building with a reproducible set of dependency versions. If a module author releases a new major version with incompatible changes, their users shouldn't immediately be broken by those changes.

@bcmills
Copy link
Member

@bcmills bcmills commented Feb 12, 2021

we are developing new services and sometimes also need to update the existing service APIs, so making breaking changes are somehow unavoided

Can you give more detail about why breaking changes are unavoidable? This proposal seems to be aiming to undo an explicit design element of #24301, and revisiting that design means that we need evidence that was not already taken into account when the decision to accept that proposal was made.

Looking at the changelog in https://github.com/oracle/oci-go-sdk/blob/master/CHANGELOG.md, I see that the breaking changes seem to fall into a number of categories, many of which are addressed (directly or indirectly) in https://blog.golang.org/module-compatibility.

To take a few examples:

  • Header Parameter Etag in Operation ListAppCatalogListingResourceVersions response was removed from the Core service
  • Property VnicId in model Ipv6 was removed from from the Core service
  • Const GetObjectArchivalStateAvailable was removed from operation GetObject response from the Object Storage service

Why did these need to be removed, instead of deprecated?

  • Property IdcsAccessToken in model CreateBlockchainPlatformDetails changed from optional to required in the Blockchain Platform service

Why was it necessary to make that property required? If it was necessary in order to reduce user error (perhaps from users forgetting to set that property when appropriate), why was it done as a breaking change to an existing model rather than, say, deprecating the old model and introducing a new, corrected one?

  • Method GetLifecycleState()'s return type in the interface ConfigurationSourceProviderSummary was changed from ConfigurationSourceProviderSummary to ConfigurationSourceProviderLifecycleStateEnum

Why was the type of the existing method changed, rather than introducing a new method with a different name and return type and deprecating the existing method?


All of these changes look to me like very reasonable things to do in an evolving, unstable API — but an evolving, unstable API would be major version 0, not a “stable” major version. (See https://semver.org/#doesnt-this-discourage-rapid-development-and-fast-iteration and https://semver.org/#if-even-the-tiniest-backwards-incompatible-changes-to-the-public-api-require-a-major-version-bump-wont-i-end-up-at-version-4200-very-rapidly.)

For a Go package at a stable major version, the expectation is that the package author will make a significant effort to avoid unnecessary breaking changes — even if that means keeping around parts of the API that would otherwise be deprecated or redundant or providing shims to translate from an old way of doing things to a newer way.

@D1CED
Copy link

@D1CED D1CED commented Feb 12, 2021

A couple questions for clarification:

  1. Am I right in the assumption that an import would behave differently when it is used in a package of the current module versus an external module?
  2. How would that interact with importing a version v0 or v1 of the same module?
  3. How would that interact with releasing a newer version?

Examples:
Lets assume the latest major version of mymod is v5.

-- mymod/mypkg.go@v5 --
import "mymod/otherpkg" // this would resolve to "mymod/v5/otherpkg"

-- othermod/mypkg.go --
import "mymod/otherpkg" // this would resolve to "mymod/v1/otherpkg"
  1. Now we release a new major version of mymod (v6).
-- mymod/mypkg.go@v6 --
import "mymod/otherpkg" // resolves to "mymod/v6/otherpkg" as it is the latest

-- mymod/mypkg.go@v5 --
import "mymod/otherpkg" // applying 'latest' literally this resolves to "mymod/v6/otherpkg" which breaks this version
@peterbourgon
Copy link
Member

@peterbourgon peterbourgon commented Feb 13, 2021

All of these changes look to me like very reasonable things to do in an evolving, unstable API — but an evolving, unstable API would be major version 0, not a “stable” major version.

"Stable" and "unstable" are not well-defined terms; even the links to the SemVer FAQ make this clear. They are relative and context-dependent. It is entirely possible that a major version bump each week means a project in one domain is "stable", and that a major version bump every six months means a project in another domain is "unstable".

The definition you're using here is toward one end of the spectrum, but not every module consumer requires, or even benefits, from this stricter definition of stability. And because Go modules has a monopoly claim on package management, it is not free to assert these more specific definitions of subjective terms, without artificially limiting participation in the ecosystem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Proposals
Incoming
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
8 participants