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

Correct module name for Go module support #712

Merged
merged 1 commit into from
Jan 14, 2019
Merged

Correct module name for Go module support #712

merged 1 commit into from
Jan 14, 2019

Conversation

SamWhited
Copy link
Contributor

@SamWhited SamWhited commented Oct 30, 2018

Go modules takes the advise that you should change the import path on all breaking changes to a package and formalizes it as the import compatibility rule.

As annoying as it is to update the major version in multiple places (tags, imports, the mod file), Go modules doesn't really work right unless you do. For example, right now if I add the following to my go.mod file:

require github.com/stripe/stripe-go v52.0.0

after I build it will be updated to something like the following because it doesn't think the version is correct:

require github.com/stripe/stripe-go v0.0.0-20181029204007-b91932a178f5

This change fixes the module name to include the v52 suffix and updates all imports so that an older version of the library doesn't get included in the v52 version.

There are other ways to manage this aside from bumping the module version, eg. copying the entire package into a v52/ tree, or maintaining an internal base package and only overriding new things in a vXX tree, branches, etc. but those all seemed like even more of a pain to me.

This is probably a pretty big decision, so this PR is more about getting discussion started about supporting Go modules more fully than anything else.

It should be noted that old supported Go versions have been updated in a point release to understand this so it shouldn't break anything on other releases to change the module name.

For more information on preparing a release see https://github.com/golang/go/wiki/Modules#releasing-modules-v2-or-higher

@SamWhited SamWhited changed the title Correct package name for Go modules Correct module name for Go module support Oct 30, 2018
@remi-stripe
Copy link
Contributor

@SamWhited Thanks a lot for starting the discussion on this and providing so much details! Just wanted to reply and flag that it would take a few days before we can investigate further but I did not want you to think we were ignoring this!

@brandur-stripe
Copy link
Contributor

Thanks for the effort here @SamWhited! I'm a little bummed that the upgrade solution is going to look so nasty for us. I guess we weren't part of the target demographic while the new system was being designed. Luckily, we have released scripts to help with this, but they're going to have to touch a lot of files which is going to make merge conflicts a lot more likely.

I believe the reason that your CI build is failing is that only Go 1.11 has built in support for Go modules (and it's succeeding). The others don't know how to read the go.mod, and therefore can't find the right paths (with major version included). To get them working, I think you'll have to pull down Vgo for those versions, and explicitly build with that.

I'd ideally prefer to wait at least one more Go version before bringing all this in so that Go modules are available without Vgo on both officially supported versions of Go.

@SamWhited
Copy link
Contributor Author

SamWhited commented Nov 7, 2018

I had thought a point release added it to the supported older releases, but maybe that's still on the table; I'll dig around for the CL tomorrow and double check.

EDIT: from https://golang.org/cl/109340:

Instead, this CL teaches the old (non-module-aware) go command
a tiny amount about modules and their import paths, to expand
the options for authors who want to publish compatible packages.
If an author has a v2 of a package, say my/thing/v2/sub/pkg,
in the my/thing repo's sub/pkg subdirectory (no v2 in the file system path),
then old go get continues to import that package as my/thing/sub/pkg.
But when go get is processing code in any module (code in a tree with
a go.mod file) and encounters a path like my/thing/v2/sub/pkg,
it will check to see if my/thing/go.mod says "module my/thing/v2".
If so, the go command will read the import my/thing/v2/sub/pkg
as if it said my/thing/sub/pkg, which is the correct "old" import path
for the package in question.

This CL will be back-ported to Go 1.10 and Go 1.9 as well.

CI appears to not have the point release, which I didn't notice before. So updating that should fix things. I pushed a change that I think will make travis use the latest point releases, so we'll see.

@SamWhited
Copy link
Contributor Author

That did it; CI is now green. The backported modules support was present in 1.9.7+ and 1.10.3+, so it's been out for a few versions.

@brandur-stripe
Copy link
Contributor

@SamWhited Ah, nice one. I noticed that you pulled go.sum back into the source tree — was that necessary to get things building? (As alluded in the .gitignore comment, it seems like it'd be nice to keep dependencies out given there are no non-test dependencies in the project.)

And regarding go.mod modifications: why golang.org/x/net and golang.org/x/text in particular? (And not the other test dependencies?)

@SamWhited
Copy link
Contributor Author

They are imported by the testing package which is actually a normal package with exported identifiers and could be imported by non-testing packages. It may not be likely that anything imports it, but since it exists every time you run, eg. go build ./... to make sure everything is still building the mod file will be updated and you'll end up with a diff, so it doesn't seem worth leaving them off. If there are dependencies in go.mod i can't see any reason not to keep the checksums (just in case). Having them is safer and not likely to break anything.

I could go either way; I just didn't see what benefit leaving the checksum file out had.

@brandur-stripe
Copy link
Contributor

brandur-stripe commented Nov 7, 2018

@SamWhited In that case, would you mind if we changed the go.mod back to exclude those dependencies again? I know that it's technically possible to import the testing/ package, but if you take a look in there it's all very much code that's specific to stripe-go's test suite and should not be used at all outside this project. IMO excluding the dependencies for the general case is beneficial because it keeps the project as lean as possible.

If you wouldn't mind, a couple more questions because you may know the answer off hand (and it'll save me some testing): do you know what the impact of this change will be for users on pre-1.11 versions of Go who don't have access to the new module system? I assume they'd have to upgrade to their latest point release in order to be able to use this package again?

Similarly, do you know what the impact would be for a project using an alternative package manager like dep? I suspect that majority of our users haven't made the Vgo migration yet, and I want to make sure not to break people too early.

(And thanks again for all the contributions here!)

@SamWhited
Copy link
Contributor Author

SamWhited commented Nov 7, 2018

I know that it's technically possible to import the testing/ package, but if you take a look in there it's all very much code that's specific to stripe-go's test suite and should not be used at all outside this project.

It should probably have a testing build flag then, or at least be internal (although in that case it would still be a dependency of the main project and contribute to the go.mod file).

IMO excluding the dependencies for the general case is beneficial because it keeps the project as lean as possible

Can you expand on what this means? To my knowledge having these dependencies in the go.mod file effectively just pins the version that the project will be built with (which is in some ways more important when running tests). It shouldn't change what's linked in to the final output. I'd actually generally suggest including test-only dependencies in go.mod too (though I'm not aware of what the Go team's advice is here; if anyone knows I'd love to see some discussion of this), but I couldn't run tests locally so I figured that could come later if the stripe developers wanted it.

EDIT: actually, running go mod tidy also adds testing dependencies which I hadn't noticed before; I'd say that makes it the official "what you're supposed to do" :)

do you know what the impact of this change will be for users on pre-1.11 versions of Go who don't have access to the new module system? I assume they'd have to upgrade to their latest point release in order to be able to use this package again?

That's my understanding as well; there are ways around that (eg. copying the package into a v52 directory and then asking them to update their imports), but they felt like a more invasive way to adopt modules to me.

Similarly, do you know what the impact would be for a project using an alternative package manager like dep?

I can't think why it would have any problems as long as they were using a version of Go with modules support or the limited compatibility for packages in the point releases.

If the tool itself was type checking the package as part of its dependency graph building process it might stumble over the versioned import statements if it hasn't updated to use go/packages, I suppose. Updates to tools that do this are being tracked in https://golang.org/issues/24661 (golang/go#24661) and I don't see any of the popular build tools in there.

@SamWhited
Copy link
Contributor Author

Ping; see previous comment.

@SamWhited
Copy link
Contributor Author

SamWhited commented Nov 27, 2018

Rebased for v54.

@SamWhited
Copy link
Contributor Author

Bumped for v55. Ping again on the question I asked in my last reply.

@brandur-stripe
Copy link
Contributor

Thanks Sam, and sorry about the non-responsiveness. I think this is the right way to go — I just need to update our internal release tooling to support the changes.

@SamWhited
Copy link
Contributor Author

Not to worry; thanks for your consideration of this PR. Let me know if there's anything else I can do to help.

@SamWhited
Copy link
Contributor Author

SamWhited commented Jan 10, 2019

If it's still not possible to merge this, would it be possible to remove the go.mod file since it's not being used anyways? this way support wouldn't be entirely broken and consumers of this library could at least use a properly versioned +incompatible import. Eg. without the broken go.mod file we'd be able to import v55.8.0+incompatible instead of v0.0.0-20190109212013-56973504bd2b and be able to tell at a glance what version we're on.

Thanks.

Copy link
Contributor

@brandur-stripe brandur-stripe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright, I finally added support for this to our release pipeline. One more ask below, but after that I think we can bring it in. Thanks for your patience!

stripe.go Outdated Show resolved Hide resolved
@brandur-stripe
Copy link
Contributor

Thanks for that fix up @SamWhited. Alright, bringing this in!

@brandur-stripe brandur-stripe merged commit 7d4acc2 into stripe:master Jan 14, 2019
@SamWhited SamWhited deleted the correct_import_version branch January 14, 2019 19:16
@jerbob92
Copy link

jerbob92 commented Jan 15, 2019

I appreciate you guys trying to keep up with changes in Go, but now this library is unusable for older Go versions. Perhaps add a notice for this in the readme?

@SamWhited
Copy link
Contributor Author

@jerbob92 basic, read-only, support for modules was backported to 1.10.3 (the earliest supported version of Go that's still receiving security updates), and to 1.9.7. If you're using anything older, I'd highly recommend that you think about upgrading to something that's still receiving stability and security patches.

@jerbob92
Copy link

@SamWhited
I was on 1.10.2 on the CI environment, changed it to 1.10.3 and it worked again. I'm just asking for a notice for anyone else that might run into this.

@mdestagnol
Copy link
Contributor

FYI it seems that this change breaks compatibility with dep. The error is: v55.9.0: "github.com/stripe/stripe-go" imports "github.com/stripe/stripe-go/v55/form", which contains malformed code: unknown error for "github.com/stripe/stripe-go/v55/form".
I run go 1.10.3.

@SamWhited
Copy link
Contributor Author

@mdestagnol in your files if you don't use the /v55 suffix dep should pick the right version (it's working for me anyways with a very simple example). If you want to use the version suffix you can probably manually modify the Gopkg.toml file and then everything should still build correctly.

@brandur-stripe
Copy link
Contributor

I just gave it a shot too with this simple program:

package main

import (
	"fmt"

	"github.com/stripe/stripe-go"
	"github.com/stripe/stripe-go/customer"
)

func main() {
	stripe.Key = "sk_test_..."

	c, err := customer.Get("cus_ELj9iKfDdhwLIR", nil)
	if err != nil {
		panic(err)
	}
	fmt.Printf("c = %+v\n", c)
}

And running dep init:

$ dep init
  Using ^55.8.0 as constraint for direct dep github.com/stripe/stripe-go
  Locking in v55.8.0 (5697350) for direct dep github.com/stripe/stripe-go
$ go run main.go
2019/01/15 15:53:49 Requesting GET api.stripe.com/v1/customers/cus_ELj9iKfDdhwLIR
c = &{AccountBalance:0 Created:1547596300 Currency:usd DefaultSource:<nil> Deleted:false Delinquent:false Description: Discount:<nil> Email: ID:cus_ELj9iKfDdhwLIR InvoicePrefix:29BD2EF Livemode:false Metadata:map[] Shipping:<nil> Sources:0xc0004220c0 Subscriptions:0xc0004221b0 TaxInfo:<nil> TaxInfoVerification:<nil>}

Remember that dep is just managing dependencies and placing them in vendor/. The Go toolchain itself knows to look in vendor/, and therefore should be able to resolve any version-prefixed paths in there the same way that any other program can.

@mdestagnol
Copy link
Contributor

mdestagnol commented Jan 16, 2019

@brandur-stripe : actually got the same result as you. But 55.8 is not the latest version including the /v55 changes. And I get the error I reported in the first place when I add the following constraint to the Gopkg.toml:

[[constraint]]
  name = "github.com/stripe/stripe-go"
  version = "55.9.0"

EDIT: I think what happens is that dep looks for the latest working version. It first tries the 55.9 but falls back to 55.8 since 55.9 doesn't work properly.

@SamWhited
Copy link
Contributor Author

I thought this had been merged, but it looks like it's not quite in dep yet: golang/dep#1963

@theckman
Copy link

theckman commented Jan 16, 2019

And unless something major happens it likely won't make it in that version of dep[1]. A full fork, instead of an ownership transfer, is likely our best way to address this, based on that issue, but it means we are going to need a large push to get the community on to our fork.

[1] golang/go#29639

@mdestagnol
Copy link
Contributor

Another option could be to have 2 branches of this repo: one with Module support, the other one with dep support. And we could define a deprecation date for the dep branch in a few months. That would let people the time to migrate once the support for Modules is stabilized in go1.12. What do you think @brandur-stripe ?

@SamWhited
Copy link
Contributor Author

SamWhited commented Jan 16, 2019

Oddly, this only appears to be choking on the /form package and nothing else, so maybe there's something wrong there. Adding the dependency like the following should fix things for now:

ignored = ["github.com/stripe/stripe-go/v55/form"]

[[constraint]]
  name = "github.com/stripe/stripe-go"
  version = "55.9.0"

EDIT: It appears to be this bug: golang/dep#351

A full fork, instead of an ownership transfer, is likely our best way to address this, based on that issue, but it means we are going to need a large push to get the community on to our fork.

I'm not sure where you get that from, the existing dep authors are still able to use the repo, new maintainers can be added, etc. so it doesn't really seem to matter where the repo lives, just that someone be interested in getting that patch over the finish line and getting it merged. By the end of that thread I was somewhat tired and may have skimmed over something important though.

@mdestagnol
Copy link
Contributor

Oddly, this only appears to be choking on the /form package and nothing else, so maybe there's something wrong there.

It's not only the form package. When I ignore the form package with the snippet of code you gave, I then get an error on another package:

v55.9.0: "github.com/stripe/stripe-go/client" imports "github.com/stripe/stripe-go/v55/product", which contains malformed code: no package exists at "github.com/stripe/stripe-go/v55/product"

@SamWhited
Copy link
Contributor Author

It's not only the form package. When I ignore the form package with the snippet of code you gave, I then get an error on another package:

That's odd, I can't reproduce that. Either way, you just want /stripe-go so you can probably just ignore all /v55 packages:

ignored = ["github.com/stripe/stripe-go/v55*"]

@mdestagnol
Copy link
Contributor

That's odd, I can't reproduce that. Either way, you just want /stripe-go so you can probably just ignore all /v55 packages

This doesn't work either. I get tons of errors like this when I run unit tests:

# cannot use "/vendor/github.com/stripe/stripe-go".Backends literal (type *"/vendor/github.com/stripe/stripe-go".Backends) as type *"github.com/stripe/stripe-go".Backends in argument to api.Init

@SamWhited
Copy link
Contributor Author

SamWhited commented Jan 16, 2019

This doesn't work either. I get tons of errors like this when I run unit tests:

What version of Go and dep are you using? And what exists in your vendor/ directory? stripe-go or stripe-go/v55?

Alternatively, do you have a minimal working example that can reproduce this problem? It's working fine for me, but maybe there's a version mismatch in the tooling we're using, or your real project is importing stripe differently from my dummy test project.

@mdestagnol
Copy link
Contributor

I upgraded to go version go1.11.4 darwin/amd64 yesterday. I was previously using 1.10.3. And I'm using dep: version : v0.5.0 build date : 2018-07-26. I have a stripe-go folder in vendors. I don't have a minimal project example unfortunately.

@SamWhited
Copy link
Contributor Author

I'm sorry, I still can't reproduce the problem with that version of dep and that version of Go (using a package in the GOPATH with GO111MODULE left unset and the ignore line I mentioned above).

Can you also confirm that you're imports don't include the /v55 suffix? Without a minimal working example it may be hard to file a bug report or help you figure out what's going on. Maybe you could pull out all the packages you import from stripe and throw them in a simple program that just creates a struct from each one or something and see if that has the same behavior?

@mdestagnol
Copy link
Contributor

mdestagnol commented Jan 16, 2019

@SamWhited : when I update stripe-go to 55.9 using the ignore statement you provided in Gopkg.toml (ignored = ["github.com/stripe/stripe-go/v55*"]), I can see that all the stripe-go packages are gone in the Gopkg.lock :

[[projects]]
  digest = "1:7fb4c6ed92335b91dca9788b287e61d8dec344008358acd2567bd6dc5a3aea4d"
  name = "github.com/stripe/stripe-go"
  packages = [
    ".",
    "client",
    "webhook",
  ]
  pruneopts = "UT"
  revision = "fc4981293b86246f2c617ac49e7d8e7fc52bc1ee"
  version = "v55.9.0"

For comparison, here is what I have in the Gopkg.lock when dep use 55.8:

[[projects]]
  digest = "1:07c4bf6a62e8aae1ab32effe35f5b545f4c0f4c33441052bf6c736a32054461b"
  name = "github.com/stripe/stripe-go"
  packages = [
    ".",
    "account",
    "applepaydomain",
    "balance",
    "bankaccount",
    "bitcoinreceiver",
    "bitcointransaction",
    "card",
    "charge",
    "client",
    "countryspec",
    "coupon",
    "customer",
    "discount",
    "dispute",
    "ephemeralkey",
    "event",
    "exchangerate",
    "fee",
    "feerefund",
    "file",
    "filelink",
    "form",
    "invoice",
    "invoiceitem",
    "issuerfraudrecord",
    "issuing/authorization",
    "issuing/card",
    "issuing/cardholder",
    "issuing/dispute",
    "issuing/transaction",
    "loginlink",
    "order",
    "orderreturn",
    "paymentintent",
    "paymentsource",
    "payout",
    "plan",
    "product",
    "radar/valuelist",
    "radar/valuelistitem",
    "recipient",
    "refund",
    "reporting/reportrun",
    "reporting/reporttype",
    "reversal",
    "sigma/scheduledqueryrun",
    "sku",
    "source",
    "sourcetransaction",
    "sub",
    "subitem",
    "terminal/connectiontoken",
    "terminal/location",
    "terminal/reader",
    "token",
    "topup",
    "transfer",
    "usagerecord",
    "webhook",
    "webhookendpoint",
  ]
  pruneopts = "UT"
  revision = "56973504bd2b8a4072b3e0d11fbbda5ced6f521d"
  version = "v55.8.0"

Pretty sure that's why we get all these errors when forcing the upgrade, and the reason why dep doesn't update to 55.9 in the first place.

@brandur-stripe
Copy link
Contributor

@SamWhited Hey! So my own little experiments with Dep confirm what @mdestagnol is saying in that although certain operations work, we run into trouble during others. It seems like we need to see golang/dep#1962 fixed over there before it'll be possible to have a package like ours that can support both Dep and Go modules cleanly.

Sam B. (Dep's maintainer) works with me, and I talked to him about this — he wants to see module support into Dep, but is experiencing some fairly severe time constraints right now. I think it'll land at some point, but probably not in the short term.

Given that usage of Dep is still so widespread, I think our best course of action right now is to revert module support in stripe-go to turn it back into a "dumb package" such that projects under the Go module system can still pull it in, but it won't be a first class citizen of the ecosystem. Hopefully within the next few months we can see some movement on that Dep issue, and then give it a little time to roll out more broadly. Once some grace time has elapsed, we revert the revert and bring your patch back in. I'll put a note in the README containing this context with links.

Sorry about all the run around on this — I really wanted to see good Go module support here, but it doesn't seem that it's currently possible to support the two biggest packaging systems in Go well simultaneously. Does that sound okay to you?

@SamWhited
Copy link
Contributor Author

I certainly wish you wouldn't, because we've already moved off of dep, but I understand your decision. Please consider removing the go.mod file entirely though instead of just reverting to the broken one with the incorrect module path; then we'll be able to use a +incompatible import at least.

I had forgotten Sam B. works with you; we've met a few times, at various Go events, the contributors summits, etc. Give him my regards and thank him for all his work on dep for me.

@mdestagnol
Copy link
Contributor

Sorry we couldn't find a better way, probably the right thing to do for now. And hopefully go1.12 create some momentum in the community to move toward Modules when released next month.

@SamWhited
Copy link
Contributor Author

SamWhited commented Jan 16, 2019

@brandur-stripe out of curiosity, what did the problem end up being? I still can't reproduce it. Is it just stripping out the subpackages? Is this something that could be fixed by turning off pruning for the package?

@brandur-stripe
Copy link
Contributor

I certainly wish you wouldn't, because we've already moved off of dep, but I understand your decision.

@SamWhited Yeah, I wish I wouldn't too :) But unfortunately it seems to be the best compromise at the moment.

Please consider removing the go.mod file entirely though instead of just reverting to the broken one with the incorrect module path; then we'll be able to use a +incompatible import at least.

Yep, forgot to mention it, but I saw your comment from before and I think that's the right way to go. Just strip modules out completely.

I had forgotten Sam B. works with you; we've met a few times, at various Go events, the contributors summits, etc. Give him my regards and thank him for all his work on dep for me.

Will do!

out of curiosity, what did the problem end up being? I still can't reproduce it. Is it just stripping out the subpackages? Is this something that could be fixed by turning off pruning for the package?

So I don't understand Dep well enough to be able to say exactly what's going on here, but I started out with a minimal main.go in an empty project directory:

package main

import (
	"fmt"

	"github.com/stripe/stripe-go"
	"github.com/stripe/stripe-go/customer"
)

func main() {
	stripe.Key = "sk_test_..."

	c, err := customer.Get("cus_ELj9iKfDdhwLIR", nil)
	if err != nil {
		panic(err)
	}
	fmt.Printf("c = %+v\n", c)
}

Then ran dep init, which works fine, except that it locks itself to the wrong version (as mentioned above) at 55.8.0.

Changing my Gopkg.toml manually and running dep ensure -update results in the error also mentioned above:

$ dep ensure -update
dep: WARNING: invalid key "ignored" in "constraint"
Solving failure: No versions of github.com/stripe/stripe-go met constraints:
        v55.9.0: "github.com/stripe/stripe-go" imports "github.com/stripe/stripe-go/v55/form", which contains malformed code: unknown error for "github.com/stripe/stripe-go/v55/form", if you get this error see https://github.com/golang/dep/issues/351
        v55.8.0: Could not introduce github.com/stripe/[email protected], as it is not allowed by constraint ^55.9.0 from project github.com/brandur/stripe-go-modules-dep.

Adding ignored = ["github.com/stripe/stripe-go/v55*"] to my Gopkg.toml like you suggested and repeating does work for me, but then when I run my program, something seriously weird is happening:

$ go run main.go
2019/01/16 13:04:47 Requesting GET api.stripe.com/v1/customers/cus_ELj9iKfDdhwLIR
2019/01/16 13:04:47 Error encountered from Stripe: {"status":401,"message":"You did not provide an API key, though you did set your Authorization header to \"Bearer\". Using Bearer auth, your Authorization header should look something like 'Authorization: Bearer YOUR_SECRET_KEY'. See https://stripe.com/docs/api#authentication for details, or we can help at https://support.stripe.com/.","type":"invalid_request_error"}
panic: {"status":401,"message":"You did not provide an API key, though you did set your Authorization header to \"Bearer\". Using Bearer auth, your Authorization header should look something like 'Authorization: Bearer YOUR_SECRET_KEY'. See https://stripe.com/docs/api#authentication for details, or we can help at https://support.stripe.com/.","type":"invalid_request_error"}

If I remove vendor and Gopkg.*, the program runs perfectly fine. I don't know what's happening, but I suspect that setting stripe.Key is happening in some package that's incompatible from the one that I'm using for customer API calls.

Happy to help look into what's going on there, but in general: I think there's enough evidence of subtle incompatibilities here that I believe that @mdestagnol is running into hard-to-reason about problems that are probably related to this change. Even if we could get past those, there's a little too much manual Gopkg.toml finagling required to get Dep working again for my comfort.

Sorry we couldn't find a better way, probably the right thing to do for now. And hopefully go1.12 create some momentum in the community to move toward Modules when released next month.

@mdestagnol Yeah, I don't think this will be out of master for too long. 1.12 should see some major marching forward with modules and there's going to be a lot of demand for compatibility. I'm sure we'll start seeing some good paths forward then.

@SamWhited
Copy link
Contributor Author

SamWhited commented Jan 16, 2019

If I remove vendor and Gopkg.*, the program runs perfectly fine. I don't know what's happening, but I suspect that setting stripe.Key is happening in some package that's incompatible from the one that I'm using for customer API calls.

Ahh yes, that would make sense. Go still thinks that stripe and stripe/v55 are two separate packages, so you end up with multiple distinct types called "Key" and possibly multiple versions of the stripe package (v55 and whatever version came right before a go.mod file was added).

Replacing the constraint with an override, and using /v55 imports throughout your program would probably fix that.

ignored = ["github.com/stripe/stripe-go/v55*"]

[[override]]
  name = "github.com/stripe/stripe-go"
  version = "55.9.0"

[prune]
  go-tests = true
  unused-packages = true

  [[prune.project]]
    name = "github.com/stripe/stripe-go"
    unused-packages = false

@brandur-stripe
Copy link
Contributor

brandur-stripe commented Jan 16, 2019

Replacing the constraint with an override, and using /v55 imports throughout your program would probably fix that.

You certainly have a better mental model of what Dep is up to than I do :)

I gave this a shot, and dep ensure -update worked, but I had trouble from there. Using import paths with v55 gave me this error message:

$ go run main.go
main.go:6:2: cannot find package "github.com/stripe/stripe-go/v55" in any of:
        /Users/brandur/Documents/go/src/github.com/brandur/stripe-go-modules-dep/vendor/github.com/stripe/stripe-go/v55 (vendor tree)

And using them without gave me the same problem of incompatible packages:

$ go run main.go
2019/01/16 13:25:36 Requesting GET api.stripe.com/v1/customers/cus_ELj9iKfDdhwLIR
2019/01/16 13:25:36 Error encountered from Stripe: {"status":401,"message":"You did not provide an API key, though you did set your Authorization header to \"Bearer\". Using Bearer auth, your Authorization header should look something like 'Authorization: Bearer YOUR_SECRET_KEY'. See https://stripe.com/docs/api#authentication for details, or we can help at https://support.stripe.com/.","type":"invalid_request_error"}
panic: {"status":401,"message":"You did not provide an API key, though you did set your Authorization header to \"Bearer\". Using Bearer auth, your Authorization header should look something like 'Authorization: Bearer YOUR_SECRET_KEY'. See https://stripe.com/docs/api#authentication for details, or we can help at https://support.stripe.com/.","type":"invalid_request_error"}

I believe there's probably a way of getting this working, but even so, I think the onus in new Dep configuration to get back onto something that works is a little too high.

@SamWhited
Copy link
Contributor Author

SamWhited commented Jan 16, 2019

You certainly have a better model of Dep is up to than I do :)

Not really; I've fought with trying to get it to handle odd dependencies at several past jobs, but it's always been mostly trial and error (but thanks).

I gave this a shot, and dep ensure -update worked, but I had trouble from there. Using import paths with v55 gave me this error message:

Odd, I thought that was working for me too. I'm not sure what weird thing is different about my setup, but I suppose it makes sense that Dep wouldn't understand how to download the /v55 version.

But I agree, figuring out how to configure dep even assuming we could get it working is probably too much to ask of people who are already using it.

brandur-stripe pushed a commit that referenced this pull request Jan 16, 2019
Reverts:
#712

(And an earlier PR that added a `go.mod` file in the first place.)

Unfortunately, there are still some fairly bad incompatibilities between
Go modules and Dep for users still on the latter. For now, we're going
to revert Go module support because there doesn't seem to be any easy
way (i.e., anything that's not maintaining a fork) of doing a good job
of both. Projects can still use the Go module system, but will have to
pull this package in as a pre-module incompatible one.

We are hoping to eventually see basic module awareness merged into Dep:

golang/dep#1963

If/when that gets done, we'll revert this revert after a small grace
period, and hopefully be back to a place where both packaging systems
are well supported.

I'll also modify the README to clarify the current situation in another
follow up PR.
@brandur brandur mentioned this pull request Jan 16, 2019
brandur-stripe pushed a commit that referenced this pull request Jan 16, 2019
Reverts:
#712

(And an earlier PR that added a `go.mod` file in the first place.)

Unfortunately, there are still some fairly bad incompatibilities between
Go modules and Dep for users still on the latter. For now, we're going
to revert Go module support because there doesn't seem to be any easy
way (i.e., anything that's not maintaining a fork) of doing a good job
of both. Projects can still use the Go module system, but will have to
pull this package in as a pre-module incompatible one.

We are hoping to eventually see basic module awareness merged into Dep:

golang/dep#1963

If/when that gets done, we'll revert this revert after a small grace
period, and hopefully be back to a place where both packaging systems
are well supported.

I'll also modify the README to clarify the current situation in another
follow up PR.
@brandur-stripe
Copy link
Contributor

@mdestagnol Dep should be working once again with version 55.10.0.

@mdestagnol
Copy link
Contributor

Awesome, thx @brandur-stripe, quickly checked and dep did update to 55.10!

By the way really appreciate how responsive you've been on this issue, merging pull requests, etc.; it really feels like a premium developer experience! Thx a lot

@brandur-stripe
Copy link
Contributor

@mdestagnol Excellent! And no worries at all — thanks for sticking through it.

brandur-stripe pushed a commit that referenced this pull request Apr 10, 2020
Similar to the original implementation for Go Modules in #712, here we
add a `go.mod` and `go.sum`, then proceed to use Go Modules style
import paths everywhere that include the current major revision.

Unfortunately, this may still cause trouble for Dep users who are trying
to upgrade stripe-go, but the project's now had two years to help its
users with basic Go Module awareness, and has chosen not to do so. It's
received no commits of any kind since August 2019, and therefore would
be considered unmaintained by most definitions. Elsewhere, Go Modules
now seem to be the only and obvious way forward, so we're likely to see
more and more users on them.

`scripts/check_api_clients/main.go` is also updated to be smarter about
breaking down package paths which may now include the major.

[1] golang/dep#1963
@brandur brandur mentioned this pull request Apr 10, 2020
remi-stripe pushed a commit that referenced this pull request Apr 16, 2020
Similar to the original implementation for Go Modules in #712, here we
add a `go.mod` and `go.sum`, then proceed to use Go Modules style
import paths everywhere that include the current major revision.

Unfortunately, this may still cause trouble for Dep users who are trying
to upgrade stripe-go, but the project's now had two years to help its
users with basic Go Module awareness, and has chosen not to do so. It's
received no commits of any kind since August 2019, and therefore would
be considered unmaintained by most definitions. Elsewhere, Go Modules
now seem to be the only and obvious way forward, so we're likely to see
more and more users on them.

`scripts/check_api_clients/main.go` is also updated to be smarter about
breaking down package paths which may now include the major.

[1] golang/dep#1963
remi-stripe pushed a commit that referenced this pull request Apr 16, 2020
Similar to the original implementation for Go Modules in #712, here we
add a `go.mod` and `go.sum`, then proceed to use Go Modules style
import paths everywhere that include the current major revision.

Unfortunately, this may still cause trouble for Dep users who are trying
to upgrade stripe-go, but the project's now had two years to help its
users with basic Go Module awareness, and has chosen not to do so. It's
received no commits of any kind since August 2019, and therefore would
be considered unmaintained by most definitions. Elsewhere, Go Modules
now seem to be the only and obvious way forward, so we're likely to see
more and more users on them.

`scripts/check_api_clients/main.go` is also updated to be smarter about
breaking down package paths which may now include the major.

[1] golang/dep#1963
brandur-stripe added a commit that referenced this pull request Apr 17, 2020
* Make API response accessible on returned API structs (#1054)

* Make API response accessible on returned API structs

Makes an API response struct containing niceties like the raw response
body, status, and request ID accessible via API resource structs
returned from client functions. For example:

    customer, err := customer.New(params)
    fmt.Printf("request ID = %s\n", customer.LastResponse.RequestID)

This is a feature that already exists in other language API libraries
and which is requested occasionally here, usually for various situations
involving more complex usage or desire for better observability.

-- Implementation

We introduce a few new types to make this work:

* `APIResponse`: Represents a response from the Stripe API and includes
  things like request ID, status, and headers. I elected to create my
  own object instead of reusing `http.Response` because it gives us a
  little more flexibility, and hides many of myriad of fields exposed by
  the `http` version, which will hopefully give us a little more API
  stability/forward compatibility.

* `APIResource`: A struct that contains `LastResponse` and is meant to
  represent any type that can we returned from a Stripe API endpoint. A
  coupon is an `APIResource` and so is a list object. This struct is
  embedded in response structs where appropriate across the whole API
  surface area (e.g. `Coupon`, `ListMeta`, etc.).

* `LastResponseGetter`: A very basic interface to an object that looks
  like an `APIResource`. This isn't strictly necessary, but gives us
  slightly more flexibility around the API and makes backward
  compatibility a little bit better for non-standard use cases (see the
  section on that below).

`stripe.Do` and other backend calls all start taking objects which are
`LastResponseGetter` instead of `interface{}`. This provides us with some
type safety around forgetting to include an embedded `APIResource` on
structs that should have it by making the compiler balk.

As `stripe.Do` finishes running a request, it generates an `APIResponse`
object and sets it onto the API resource type it's deserializing and
returning (e.g. a `Coupon`).

Errors also embed `APIResource` and similarly get access to the same set
of fields as response resources, although in their case some of the
fields provided in `APIResponse` are duplicates of what they had
already (see "Caveats" below).

-- Backwards compatibility

This is a minor breaking change in that backend implementations methods
like `Do` now take `LastResponseGetter` instead of `interface{}`, which
is more strict.

The good news though is that:

* Very few users should be using any of these even if they're
  technically public. The resource-specific clients packages tend to do
  all the work.

* Users who are broken should have a very easy time updating code.
  Mostly this will just involve adding `APIResource` to structs that were
  being passed in.

-- Naming

* `APIResponse`: Went with this instead of `StripeResponse` as we see in
  some other libraries because the linter will complain that it
  "stutters" when used outside of the package (meaning, uses the same
  word twice in a row), i.e. `stripe.StripeResponse`. `APIResponse`
  sorts nicely with `APIResource` though, so I think it's okay.

* `LastResponse`: Copied the "last" convention from other API libraries
  like stripe-python.

* `LastResponseGetter`: Given an "-er" name per Go convention around
  small interfaces that are basically one liners -- e.g. `Reader`,
  `Writer, `Formatter`, `CloseNotifier`, etc. I can see the argument
  that this maybe should just be `APIResourceInterface` or something
  like that in case we start adding new things, but I figure at that
  point we can either rename it, or create a parent interface that
  encapsulates it:

    ``` go
    type APIResourceInterface interface {
        LastResponseGetter
    }
    ```

-- Caveats

* We only set the last response for top-level returned objects. For
  example, an `InvoiceItem` is an API resource, but if it's returned
  under an `Invoice`, only `Invoice` has a non-nil `LastResponse`. The
  same applies for all resources under list objects. I figure that doing
  it this way is more performant and makes a little bit more intuitive
  sense. Users should be able to work around it if they need to.

* There is some duplication between `LastResponse` and some other fields
  that already existed on `stripe.Error` because the latter was already
  exposing some of this information, e.g. `RequestID`. I figure this is
  okay: it's nice that `stripe.Error` is a `LastResponseGetter` for
  consistency with other API resources. The duplication is a little
  unfortunate, but not that big of a deal.

* Rename `LastResponseGetter` to `LastResponseSetter` and remove a function

* Update stripe.go

Co-Authored-By: Olivier Bellone <[email protected]>

* Move `APIResource` onto individual list structs instead of having it in `ListMeta`

Co-authored-by: Brandur <[email protected]>
Co-authored-by: Olivier Bellone <[email protected]>

* Remove all beta features from Issuing APIs

* Multiple breaking API changes

* `PaymentIntent` is now expandable on `Charge`
* `Percentage` was removed as a filter when listing `TaxRate`
* Removed `RenewalInterval` on `SubscriptionSchedule`
* Removed `Country` and `RoutingNumber` from `ChargePaymentMethodDetailsAcssDebit`

* Start using Go Modules

Similar to the original implementation for Go Modules in #712, here we
add a `go.mod` and `go.sum`, then proceed to use Go Modules style
import paths everywhere that include the current major revision.

Unfortunately, this may still cause trouble for Dep users who are trying
to upgrade stripe-go, but the project's now had two years to help its
users with basic Go Module awareness, and has chosen not to do so. It's
received no commits of any kind since August 2019, and therefore would
be considered unmaintained by most definitions. Elsewhere, Go Modules
now seem to be the only and obvious way forward, so we're likely to see
more and more users on them.

`scripts/check_api_clients/main.go` is also updated to be smarter about
breaking down package paths which may now include the major.

[1] golang/dep#1963

* Change v71 back to v70

Move back down to current major version so that we can test that our
release script will bump it to v71 properly when the time comes.

Co-authored-by: Brandur <[email protected]>
Co-authored-by: Olivier Bellone <[email protected]>
Co-authored-by: Remi Jannel <[email protected]>
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 this pull request may close these issues.

6 participants