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

deploy: add a "deploy" command #5599

Closed
wants to merge 3 commits into from
Closed

Conversation

vangent
Copy link
Contributor

@vangent vangent commented Jan 10, 2019

The "deploy" command uses Go Cloud's blob package to deploy to multiple Cloud providers. Currently GCS, S3, and Azure are supported.

A new "deployments" section is added to the site config file; multiple deployment targets can be configured and selected using --target flag.

Deployment consists of walking the public/ site, walking the remote target, and computing a diff. New local files are marked to be uploaded, files at the target that no longer exist locally are marked to be deleted, and local files that have changed (either in size or MD5 hash) are marked to be uploaded.

The command prompts for confirmation before applying changes. The prompt can be disabled via --skipConfirmation. Alternatively, --dryRun will show proposed changes without making them.

Similar to s3deploy, a new "routes" section in the site config file can control metadata for the upload, including headers like Cache-Control and Content-Type, as well as whether the content should be gzipped.

@CLAassistant
Copy link

CLAassistant commented Jan 10, 2019

CLA assistant check
All committers have signed the CLA.

@vangent
Copy link
Contributor Author

vangent commented Jan 16, 2019

Hi Bjorn, ping?

I have a follow-on PR that adds support for ordering the uploads (similar to bep/s3deploy#37).

I can add another one to support the "ignore subfolders" feature request (bep/s3deploy#33).

I would also like to add CloudFront support in a separate PR.

@bep
Copy link
Member

bep commented Jan 16, 2019

@vangent I'm in the Canary Island doing mostly nothing this week. It's called a vacation. I will get back to this next week.

@vangent
Copy link
Contributor Author

vangent commented Jan 16, 2019

OK no worries! Just wanted to check in. Have a relaxing vacation!

Copy link
Member

@bep bep left a comment

Choose a reason for hiding this comment

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

I have added a set of comments of things that I think needs to be adjusted. We probably need to go a round 2) with this, but that will have to wait until I get home from sunny Spain.

commands/deploy.go Outdated Show resolved Hide resolved
commands/deploy.go Outdated Show resolved Hide resolved
deploy/deploy.go Outdated Show resolved Hide resolved
deploy/deploy.go Outdated Show resolved Hide resolved
deploy/deploy.go Outdated Show resolved Hide resolved
docs/config.toml Outdated Show resolved Hide resolved
deploy/deploy.go Outdated Show resolved Hide resolved
deploy/deploy.go Outdated Show resolved Hide resolved
jww.FEEDBACK.Println("Success!")

// TODO: Add support for CloudFront invalidation similar to s3deploy,
// and possibly similar functionality for other providers.
Copy link
Member

Choose a reason for hiding this comment

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

Is this not a feature in gocloud?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not currently, no; CDN APIs are very low on the list of APIs we have demand for. That may change.

IIUC, CloudFront can cache content from any provider.

I'd like to add CloudFront specifically, but in a separate PR if that's OK. We can see if there's demand for other CDNs; if there's a lot, then we can consider adding an abstraction to Go Cloud for it.

deploy/deploy.go Show resolved Hide resolved
deploy/deploy.go Show resolved Hide resolved
deploy/deploy.go Outdated

// route represents configuration to be applied to files whose paths match
// a specified pattern.
type route struct {
Copy link
Member

Choose a reason for hiding this comment

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

We also need a way to set the ACL. In s3deploy this is a boolean flag (public or private, default private).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is not supported by Go Cloud yet (google/go-cloud#1108).

It's a bit tricky because this functionality (setting the ACL per blob rather than per bucket/container) is not available in Azure at all.

Is it OK to not include this for now? I would guess that most people would have their site in a single bucket/container and can set the ACL there, no?

@bep
Copy link
Member

bep commented Jan 21, 2019

@vangent thanks, your updates look great. I was going to suggest that we pull his in and hide the hugo deploy command until we got something "feature complete and working" (it would still work, but you would have to know about it.

But then I started looking at the dependency changeset (i.e. the go.mod diff) ... And that was much bigger than I expected and includes many dependencies that do not look relevant (github.com/gopherjs/gopherjs, github.com/streadway/amqp, github.com/go-sql-driver/mysql, github.com/coreos/go-systemd etc.?) and also many dependencies I have not heard of. Some of these may be test dependencies (the go.mod file shows both), but I assume not all of them.

There are several issues with this which may be blocking:

  1. We are part of the Debian and Ubuntu build system, so adding a dependency is more work than just adding an import statement. @anthonyfok may give some insight on that.
  2. Also, I try as best as I can to vet dependencies and vet updates to dependencies. My time is limited.

I'm not saying we should not any new dependencies, but to me, it looks like the dependency handling in gocloud.dev/blob/* should be rethought (make features optional, maybe) so we don't need to "pull in the world" to upload a file.

/cc @spf13

@anthonyfok
Copy link
Member

Hi @bep,

Thank you for Cc'ing me.

@vangent thanks, your updates look great. I was going to suggest that we pull his in and hide the hugo deploy command until we got something "feature complete and working" (it would still work, but you would have to know about it.

Very cool!

But then I started looking at the dependency changeset (i.e. the go.mod diff) ... And that was much bigger than I expected and includes many dependencies that do not look relevant (github.com/gopherjs/gopherjs, github.com/streadway/amqp, github.com/go-sql-driver/mysql, github.com/coreos/go-systemd etc.?) and also many dependencies I have not heard of. Some of these may be test dependencies (the go.mod file shows both), but I assume not all of them.

There are several issues with this which may be blocking:

  1. We are part of the Debian and Ubuntu build system, so adding a dependency is more work than just adding an import statement. @anthonyfok may give some insight on that.

I am happy to report that many of the new dependencies, including the indirect ones, especially the four that you mentioned, are already in Debian. I would say we may need to make about a handful new packages, and that we on the Debian Go Team are used to doing that.

Also, other Debian Go Team members had a similar discussion with other software, and they had taught me to work smarter, as in we can put these new dependencies in the vendor/ directory as part of the Hugo source package. I actually did that between July and September 2018 for github.com/wellington/go-libsass and github.com/bep/go-tocss until they got accepted by the Debian FTP masters (My fault for missing some of the copyright information, contributing to that delay) so that we could have Hugo 0.43 to 0.47.1 in Debian without being blocked by new dependencies. (But then Debian's golang-1.11 hit a snag and that I couldn't solve myself...)

So, yes, no need to worry about the Debian and Ubuntu side of things. I am more than happy to use the same tricks again as before to keep the Debian package up-to-date.

  1. Also, I try as best as I can to vet dependencies and vet updates to dependencies. My time is limited.

Cool, thanks!

Cheers,
Anthony

@bep
Copy link
Member

bep commented Jan 22, 2019

@anthonyfok thanks for that input. It does address some of the concerns, but the gocloud still needs a dependency "overhaul" before we can pull this into master, I'm afraid. @vangent is that a project you somehow have access to and do you understand my concerns?

@vangent
Copy link
Contributor Author

vangent commented Jan 22, 2019

that a project you somehow have access to and do you understand my concerns

Yes, that's a project I have access to and I understand your concerns. Some of this may be due to Go modules being a bit confusing about dependencies -- for example, I reverted my changeds to go.mod and go.sum and then ran a build, and the set of changes is much smaller now. In particular, things that are listed in go.sum are not necessarily actually new dependencies; go sometimes downloads .mod files that aren't actually used in the binary.

I think that go list -deps is a more accurate way of viewing actual dependencies.

I did go list --deps | sort on master and on this branch, here are the actual diffs:

2a3,9
> cloud.google.com/go/compute/metadata
> cloud.google.com/go/iam
> cloud.google.com/go/internal
> cloud.google.com/go/internal/optional
> cloud.google.com/go/internal/trace
> cloud.google.com/go/internal/version
> cloud.google.com/go/storage
32a40
> database/sql/driver
75a84,119
> github.com/aws/aws-sdk-go/aws
> github.com/aws/aws-sdk-go/aws/awserr
> github.com/aws/aws-sdk-go/aws/awsutil
> github.com/aws/aws-sdk-go/aws/client
> github.com/aws/aws-sdk-go/aws/client/metadata
> github.com/aws/aws-sdk-go/aws/corehandlers
> github.com/aws/aws-sdk-go/aws/credentials
> github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds
> github.com/aws/aws-sdk-go/aws/credentials/endpointcreds
> github.com/aws/aws-sdk-go/aws/credentials/stscreds
> github.com/aws/aws-sdk-go/aws/csm
> github.com/aws/aws-sdk-go/aws/defaults
> github.com/aws/aws-sdk-go/aws/ec2metadata
> github.com/aws/aws-sdk-go/aws/endpoints
> github.com/aws/aws-sdk-go/aws/request
> github.com/aws/aws-sdk-go/aws/session
> github.com/aws/aws-sdk-go/aws/signer/v4
> github.com/aws/aws-sdk-go/internal/s3err
> github.com/aws/aws-sdk-go/internal/sdkio
> github.com/aws/aws-sdk-go/internal/sdkrand
> github.com/aws/aws-sdk-go/internal/sdkuri
> github.com/aws/aws-sdk-go/internal/shareddefaults
> github.com/aws/aws-sdk-go/private/protocol
> github.com/aws/aws-sdk-go/private/protocol/eventstream
> github.com/aws/aws-sdk-go/private/protocol/eventstream/eventstreamapi
> github.com/aws/aws-sdk-go/private/protocol/query
> github.com/aws/aws-sdk-go/private/protocol/query/queryutil
> github.com/aws/aws-sdk-go/private/protocol/rest
> github.com/aws/aws-sdk-go/private/protocol/restxml
> github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil
> github.com/aws/aws-sdk-go/service/s3
> github.com/aws/aws-sdk-go/service/s3/s3iface
> github.com/aws/aws-sdk-go/service/s3/s3manager
> github.com/aws/aws-sdk-go/service/sts
> github.com/Azure/azure-pipeline-go/pipeline
> github.com/Azure/azure-storage-blob-go/azblob
86a131
> github.com/dustin/go-humanize
119a165
> github.com/gohugoio/hugo/deploy
184a231,240
> github.com/go-ini/ini
> github.com/golang/protobuf/proto
> github.com/golang/protobuf/protoc-gen-go/descriptor
> github.com/golang/protobuf/ptypes
> github.com/golang/protobuf/ptypes/any
> github.com/golang/protobuf/ptypes/duration
> github.com/golang/protobuf/ptypes/timestamp
> github.com/googleapis/gax-go
> github.com/google/uuid
> github.com/google/wire
199a256
> github.com/jmespath/go-jmespath
247a305,312
> gocloud.dev/blob
> gocloud.dev/blob/azureblob
> gocloud.dev/blob/driver
> gocloud.dev/blob/fileblob
> gocloud.dev/blob/gcsblob
> gocloud.dev/blob/s3blob
> gocloud.dev/gcp
> gocloud.dev/internal/useragent
264a330
> golang.org/x/net/context/ctxhttp
265a332
> golang.org/x/net/http2
266a334
> golang.org/x/net/http2/hpack
267a336
> golang.org/x/net/http/httpguts
270a340,346
> golang.org/x/net/internal/timeseries
> golang.org/x/net/trace
> golang.org/x/oauth2
> golang.org/x/oauth2/google
> golang.org/x/oauth2/internal
> golang.org/x/oauth2/jws
> golang.org/x/oauth2/jwt
281a358,410
> google.golang.org/api/gensupport
> google.golang.org/api/googleapi
> google.golang.org/api/googleapi/internal/uritemplates
> google.golang.org/api/googleapi/transport
> google.golang.org/api/internal
> google.golang.org/api/iterator
> google.golang.org/api/option
> google.golang.org/api/storage/v1
> google.golang.org/api/transport/http
> google.golang.org/api/transport/http/internal/propagation
> google.golang.org/genproto/googleapis/api/annotations
> google.golang.org/genproto/googleapis/iam/v1
> google.golang.org/genproto/googleapis/rpc/code
> google.golang.org/genproto/googleapis/rpc/status
> google.golang.org/grpc
> google.golang.org/grpc/balancer
> google.golang.org/grpc/balancer/base
> google.golang.org/grpc/balancer/roundrobin
> google.golang.org/grpc/codes
> google.golang.org/grpc/connectivity
> google.golang.org/grpc/credentials
> google.golang.org/grpc/encoding
> google.golang.org/grpc/encoding/proto
> google.golang.org/grpc/grpclog
> google.golang.org/grpc/internal
> google.golang.org/grpc/internal/backoff
> google.golang.org/grpc/internal/channelz
> google.golang.org/grpc/internal/envconfig
> google.golang.org/grpc/internal/grpcrand
> google.golang.org/grpc/internal/transport
> google.golang.org/grpc/keepalive
> google.golang.org/grpc/metadata
> google.golang.org/grpc/naming
> google.golang.org/grpc/peer
> google.golang.org/grpc/resolver
> google.golang.org/grpc/resolver/dns
> google.golang.org/grpc/resolver/passthrough
> google.golang.org/grpc/stats
> google.golang.org/grpc/status
> google.golang.org/grpc/tap
> go.opencensus.io
> go.opencensus.io/internal
> go.opencensus.io/internal/tagencoding
> go.opencensus.io/plugin/ochttp
> go.opencensus.io/plugin/ochttp/propagation/b3
> go.opencensus.io/stats
> go.opencensus.io/stats/internal
> go.opencensus.io/stats/view
> go.opencensus.io/tag
> go.opencensus.io/trace
> go.opencensus.io/trace/internal
> go.opencensus.io/trace/propagation
> go.opencensus.io/trace/tracestate
310a440
> log/syslog
320a451
> net/http/httputil
326a458
> os/user
336a469
> runtime/pprof

That is still a long list, but it's not too surprising at least to me given the new dependencies on Azure, AWS, and GCP. I don't think there's any way around those if deploy is going to support deploying to those Cloud providers.

@vangent
Copy link
Contributor Author

vangent commented Jan 30, 2019

@bep does my response seem reasonable?

@bep
Copy link
Member

bep commented Jan 31, 2019

go sometimes downloads .mod files that aren't actually used in the binary.

I assume that is test dependencies, which will not end up in the end binary -- but certainly in a binary (the test binary).

@bep does my response seem reasonable?

The response is reasonable. But I have to consider the conclusion. The thing is, this discussion started right about at the same time as Russ Cox, a coworker of yours, posted this article about this subject. I took that as a sign that I should stop and think really hard about this. Which I'm doing. I will get back to you early next week.

@vangent
Copy link
Contributor Author

vangent commented Jan 31, 2019

I assume that is test dependencies

Not necessarily. Currently our repo has a single main .mod file which includes all of the portable APIs, of which blob is only one. That's why the coreos and mysql dependencies are in there -- they have nothing to do with blob but are used in another one of our APIs, runtimevar. But I don't believe they will end up in the binary (or even test binary) unless they are actually used (explicitly via import, or implicitly as a dependency of an import).

I think that go list -deps is a more accurate way of viewing actual dependencies, not the .mod file.

@bep
Copy link
Member

bep commented Feb 12, 2019

Quick note that this is not forgotten. I'm thinking about pulling it in and add a "feature flag" of some sort (build tag), so people can use it if they want and we can enable it by default once it is done-done. But I have to wrap my head around it, because once it is in it is hard to take back.

@vangent
Copy link
Contributor Author

vangent commented Mar 20, 2019

Hi @bep, any update on your "feature flag" idea?

@bep
Copy link
Member

bep commented Apr 24, 2019

No, and sorry about the delay.

@bep
Copy link
Member

bep commented Apr 24, 2019

@vangent here's what we're going to do:

  • Once the dust on Hugo 0.55 settles (I have one more patch release to do in the next few days, and it is simpler to do that from master without any cherry-picking), I will merge this PR.
  • We can hide the "deploy" command (there is a boolean flag on the command) which means that if you know about it, you can use it.
  • I will give you commit access to master so you can do whatever you like to get this into shape, or you can open PRs if you want to discuss/have me look at it.

@vangent
Copy link
Contributor Author

vangent commented Apr 24, 2019

SGTM. After this PR, I think all that's needed is updates to the documentation, which I'm happy to try but would like your review on.

I have a another follow-on to support "ordering" of uploads (I think s3deploy has this).

@bep
Copy link
Member

bep commented Apr 25, 2019

Can you squash the commits and rebase against master?

After this PR, I think all that's needed is updates to the documentation, which I'm happy to try but would like your review on.

Does this PR implement CDN cache invalidation? If not, that is, in my head, a must have.

@vangent
Copy link
Contributor Author

vangent commented Apr 25, 2019

Squash/rebase done.

No, it doesn't include CDN invalidation.

@vangent
Copy link
Contributor Author

vangent commented Apr 25, 2019

There are 12 open TODOs in the PR, please review them and let me know which ones can be deleted, which ones need more investigation, and which ones should definitely be done in follow-on PRs before considered this feature complete (e.g, like the CDN invalidation). Thanks!

@vangent
Copy link
Contributor Author

vangent commented May 1, 2019

I have a PR ready after this one to add CDN invalidate for CloudFront. It just invalidates /* for now.

@vangent
Copy link
Contributor Author

vangent commented May 1, 2019

I think the main thing that needs to happen before this can be submitted is that the change to docs/config.toml needs to be reverted, and instead this feature needs to have some documentation added about how to use it. @bep can you suggest where that documentation should go? Or can it be added separately?

@bep
Copy link
Member

bep commented May 3, 2019

@vangent yes, don't worry about the config.toml. That does not go "live" until we do a release and push it to the hugoDocs repo (and even then it would not hurt anyone).

I have triggered a new build, seems to be some "build exeeding limit" timeout issues. Could this be a Go Modules issue? I.e. that cloning all the dependencies is taking too long? If so, we should probably look into the newly announced modules proxy server.

I will merge once I understand the above. I see the TODOs, and I will create separate issues of some of those so we can add them later (e.g. the most important that I would need to use this (and when I need it, I'll assume others also would), quickly noting here:

  • Deployment to subfolders of a bucket, esp. see this commit: bep/s3deploy@56b818b
  • Some kind of cache invalidation for CDN

@bep
Copy link
Member

bep commented May 3, 2019

I'm doing some build testing experimentation of this in

#5925

@vangent
Copy link
Contributor Author

vangent commented May 3, 2019

don't worry about the config.toml

OK. I reverted the changes to that file since they were just an example and included (for example) my bucket names.

@vangent
Copy link
Contributor Author

vangent commented May 3, 2019

Could this be a Go Modules issue

It's possible that downloading the additional modules pushed it over some timeout edge. I have seen the checks pass on this PR before though.

Enabling the modules proxy sounds like a good idea regardless.

@vangent
Copy link
Contributor Author

vangent commented May 3, 2019

I will create separate issues of some of those so we can add them later

SGTM. Please go ahead and assign the issues to me. I already have PRs ready for:

  • Cache invalidate for CloudFront (although it's simpler than way you had in s3; we can discuss).
  • Support for ordering.

I will start working on the "subfolders of a bucket" TODO as well.

Thanks bep!

@bep
Copy link
Member

bep commented May 3, 2019

I merged this in #5925

@bep bep closed this May 3, 2019
@vangent vangent deleted the deploy branch May 3, 2019 16:07
@github-actions
Copy link

This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jan 29, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants