Automated dependency update binary#336
Conversation
|
/assign @sebastienvas |
|
The base of this code change was migrated from PR#493 on istio/istio Additionally, we assume each repo now hosts a file where its dependency info is recorded (see PR #89 on istio/mixerclient). Hence, the dependency update script now accesses dependency info from such file. |
toolbox/deps_update/main.go
Outdated
| if err != nil { | ||
| return err | ||
| } | ||
| mixerSHA, err := githubClnt.getHeadCommitSHA("mixer", "stable") |
There was a problem hiding this comment.
What about auth for istio-ca ?
nlandolfi
left a comment
There was a problem hiding this comment.
nice!
most of my comments are a function of
- trying to get away from package level variables
- trying to be idiomatic
- trying to fail the program early if one of assumptions isn't met (like loading token immediately)
just suggestions!
| package main | ||
|
|
||
| /* | ||
| Assumes Dependency Hoisting in all bazel dependency files. Example: |
There was a problem hiding this comment.
I actually do want to say hoisting here. It means pulling the commit SHA up and out of the bazel rules, defining is as constant string, and referencing it in the bazel rule.
| @@ -0,0 +1,111 @@ | |||
| // Copyright 2017 Istio Authors | |||
There was a problem hiding this comment.
I think it might be a go thing to name files snake case github_client.go
but not a big deal i don't think.
There was a problem hiding this comment.
I actually see a mix of camel case and snake case in our repos for go files and got confused too. But I guess I will leave it like this unless people have a strong opinion
toolbox/deps_update/githubClient.go
Outdated
| Body: &body, | ||
| } | ||
| log.Printf("Creating a PR with Title: \"%s\" for repo %s", title, repo) | ||
| pr, _, err := g.client.PullRequests.Create(context.TODO(), *owner, repo, &req) |
There was a problem hiding this comment.
i think either parameterize this function by a context or use context.Background() -- not TODO
toolbox/deps_update/util.go
Outdated
| return hex.EncodeToString(hash[:]) | ||
| } | ||
|
|
||
| // Shell run command on shell and get back output and error if get one |
There was a problem hiding this comment.
haha I took this code from istio/istio. I blame Seb on this.
| // GetMD5Hash generates an MD5 digest of the given string | ||
| func GetMD5Hash(text string) string { | ||
| hash := md5.Sum([]byte(text)) | ||
| return hex.EncodeToString(hash[:]) |
There was a problem hiding this comment.
is the [:] making a copy of the hash bytes and do we need to make a copy since you don't do anything with hash?
There was a problem hiding this comment.
possibly can delete, you only use helper once, and might be able to be replaced with
hex.EncodeToString(md5.Sum([]byte(text)))
maybe
There was a problem hiding this comment.
The [:] operator creates a slice (type []byte) from an array (type [16]byte). (See full explanation here) It is necessary to make such conversion here since md5.Sum() returns [16]byte but hex.EncodeToString wants []byte.
I think this function is generically useful to not just this particular feature/script but also the rest of test-infra so putting it under util is in my opinion a good idea.
| } | ||
|
|
||
| // Shell run command on shell and get back output and error if get one | ||
| func Shell(format string, args ...interface{}) (string, error) { |
There was a problem hiding this comment.
my suggestion here is maybe don't bother with writing a helper unless you need the extra logging
rather than doing the fmt.Sprintf with the formatting you can just use the underlying signature and pass in the executable and list of args right? seems funky that you always create the string only to split it again...
like exec.Command("./some/script.sh", []string{"-p", "flag", "-d", fmt.Sprintf("%d", integerSomething)}).CombinedOutput() seems nearly equivalent
|
|
||
| var ( | ||
| repo = flag.String("repo", "", "Update dependencies of only this repository") | ||
| githubClnt *githubClient |
There was a problem hiding this comment.
doesn't seem like this should be a global package level variable
There was a problem hiding this comment.
It is declared on a global scope so that other functions in main.go could easily access githubClient functions. The intention is not providing package level visibility. Any way we could do better?
There was a problem hiding this comment.
shoot just saw this -- gotcha, the other option is to pass it down as arguments to functions.
toolbox/deps_update/main.go
Outdated
| // Update the commit SHA reference in a given line from dependency file | ||
| // to the latest stable version | ||
| // returns the updated line | ||
| func replaceCommit(line string, dep dependency) (string, error) { |
There was a problem hiding this comment.
this should probably either take as argument a pointer to a client or have a client reciever
i.e., replaceCommit(gc *githubClient, line string, dep dependency) or func (gc *githubClient) replaceCommit(line string, dep dependency)
There was a problem hiding this comment.
Any reason why such indirection is necessary?
toolbox/deps_update/main.go
Outdated
| } | ||
|
|
||
| // Get the list of dependencies of a repo | ||
| // Assumes repo has been cloned to local |
There was a problem hiding this comment.
cloned to local? or cloned locally? does this program assume that we are in root directory of the repo?
There was a problem hiding this comment.
The assumption has been removed
toolbox/deps_update/main.go
Outdated
|
|
||
| // Generates an MD5 digest of the version set of the repo dependencies | ||
| // useful in avoiding making duplicate branches of the same code change | ||
| func fingerPrint(deps []dependency) (string, error) { |
There was a problem hiding this comment.
i think also should either take a github client or be a method with a gc receiver.
|
ohhhhh gotcha -- SGTM
…On Fri, Jul 28, 2017 at 5:56 PM Charles Xu ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In toolbox/deps_update/dependency.go
<#336 (comment)>:
> +// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+/*
+ Assumes Dependency Hoisting in all bazel dependency files. Example:
I actually do want to say hoisting here. It means pulling the commit SHA
up and out of the bazel rules, defining is as constant string, and
referencing it in the bazel rule.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#336 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/ACBRUVxgdZ8NGN8BDtyKqsSqoN_nFeXLks5sSoNEgaJpZM4Okose>
.
|
|
ya seb pointed out to me that mixer does camel case
…On Fri, Jul 28, 2017 at 6:00 PM Charles Xu ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In toolbox/deps_update/githubClient.go
<#336 (comment)>:
> @@ -0,0 +1,111 @@
+// Copyright 2017 Istio Authors
I actually see a mix of camel case and snake case in our repos for go
files and got confused too. But I guess I will leave it like this unless
people have a strong opinion
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#336 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/ACBRUexz6UpVk0216FgorHJNfWmbSPvvks5sSoQpgaJpZM4Okose>
.
|
|
PTAL Comments above have been addressed. Specifically, failed PRs are now closed in subsequent runs, istio-ca is taken care of, code style has improved, and duplicate code with github_helper has been refactored. An example PR created by this script is here. This update script has to work with |
toolbox/deps_update/main.go
Outdated
| // Returns the updated line | ||
| func replaceCommit(line string, dep dependency) (string, error) { | ||
| idx := strings.Index(line, "\"") | ||
| return line[:idx] + "\"" + dep.LastStableSHA + "\",", nil |
There was a problem hiding this comment.
No need to have an error return if the function never returns an error.
There was a problem hiding this comment.
You are absolutely right. There has been a refactor and I forgot to take the error out.
toolbox/deps_update/main.go
Outdated
| caHub := "docker.io/istio" | ||
| istioctlURL := fmt.Sprintf( | ||
| "https://storage.googleapis.com/istio-artifacts/pilot/%s/artifacts/istioctl", pilotSHA) | ||
| hub := "gcr.io/istio-testing" |
There was a problem hiding this comment.
Please make something like docker hub, gcs storage configurable from flags or read from somewhere, try not hardcoded.
There was a problem hiding this comment.
I agree. It is now read from istio.VERSION directly.
toolbox/deps_update/main.go
Outdated
| caHub := "docker.io/istio" | ||
| istioctlURL := fmt.Sprintf( | ||
| "https://storage.googleapis.com/istio-artifacts/pilot/%s/artifacts/istioctl", pilotSHA) | ||
| hub := "gcr.io/istio-testing" |
There was a problem hiding this comment.
Try not to hardcoded something like docker hubs and gcs storage, make it configurable and read it from flags or somewhere else.
toolbox/deps_update/main.go
Outdated
| // Returns the updated line | ||
| func replaceCommit(line string, dep dependency) (string, error) { | ||
| idx := strings.Index(line, "\"") | ||
| return line[:idx] + "\"" + dep.LastStableSHA + "\",", nil |
There was a problem hiding this comment.
If no error is going to be returned, then remove error from return values.
toolbox/deps_update/main.go
Outdated
| if _, err := util.Shell("git add *"); err != nil { | ||
| return err | ||
| } | ||
| if _, err := util.Shell("git commit -m Update_Dependencies"); err != nil { |
There was a problem hiding this comment.
Maybe you can use "git commit -am "
toolbox/deps_update/main.go
Outdated
| } | ||
| for _, r := range repos { | ||
| if err := updateDependenciesOf(r); err != nil { | ||
| log.Panicf("Failed to udpate dependency: %v\n", err) |
There was a problem hiding this comment.
Careful using panic, you may still want to update other repos even the first one hit an error
| return nil | ||
| } | ||
|
|
||
| func main() { |
There was a problem hiding this comment.
I suppose it is a periodic job, then why not use goroutine and wake up every midnight
There was a problem hiding this comment.
I thought the intention is to set up the cron jobs thru jenkins/prow and this binary does not care when it is invoked (ordering of repo) or how it is triggered (cron versus PR). I was trying to leave for room for the future if we want to update istio project by building from leaves.
|
PTAL |
|
you should use pretty print on the json file. That being said, this looks promising |
toolbox/deps_update/main.go
Outdated
| // useful in avoiding making duplicate branches of the same code change | ||
| // Also updates dependency objects deserialized from istio.deps | ||
| func fingerPrintAndUpdateDepSHA(repo string, deps *[]dependency) (string, error) { | ||
| digest, err := githubClnt.getHeadCommitSHA(repo, "master") |
There was a problem hiding this comment.
We want this to work also for release branches, so you should make the branch as a flag.
toolbox/deps_update/githubClient.go
Outdated
| func (g githubClient) closeFailedPullRequests(repo string) error { | ||
| log.Printf("Search for failed auto PRs to update dependencies in repo %s", repo) | ||
| options := github.PullRequestListOptions{ | ||
| Base: "master", |
There was a problem hiding this comment.
Same comment here. Use the branch as a flag.
toolbox/deps_update/main.go
Outdated
| // Assumes at the root of istio directory | ||
| // Runs the updateVersion.sh script | ||
| func updateIstioDeps() error { | ||
| pilotSHA, err := githubClnt.getHeadCommitSHA("pilot", "stable") |
There was a problem hiding this comment.
Do you have to hard code this? Can you look at the istio.deps files and generate this from the json files?
There was a problem hiding this comment.
There has to be some hadcoding in order to use install/updateVersion.sh because each dependency is passed in with different flag and hub. Such flags and hubs are only applicable to istio/istio so they should not be put into the json file. I did refactor this such that SHAs are read from deps array (read from json file) but I still have to specify the name such as "pilot" and "mixer" to properly use the flags. Let me know if you have smarter ways to do this.
toolbox/deps_update/main.go
Outdated
| istioctlURL := fmt.Sprintf( | ||
| "https://storage.googleapis.com/istio-artifacts/pilot/%s/artifacts/istioctl", pilotSHA) | ||
| hub := "gcr.io/istio-testing" | ||
| cmd := fmt.Sprintf("./install/updateVersion.sh -p %s,%s -x %s,%s -i %s -c %s,%s", |
There was a problem hiding this comment.
Maybe dynamically update the flags based which deps needs to be updated.
There was a problem hiding this comment.
It is hard since there is also correspondence between dependency and hub, and istioctlURL does not have a hub. The updateVersion.sh is just a bit ad hoc so I think what I have here is actually the most concise
toolbox/deps_update/githubClient.go
Outdated
| } | ||
| title := prTitlePrefix + repo | ||
| body := "This PR will be merged automatically once checks are successful." | ||
| base := "master" |
There was a problem hiding this comment.
Same comment here. Make the branch a flag.
toolbox/deps_update/githubClient.go
Outdated
| } | ||
| var multiErr error | ||
| for _, pr := range prs { | ||
| if strings.Contains(*pr.Title, prTitlePrefix) { |
There was a problem hiding this comment.
Don't you want to look only those that have the prefix ?
|
PTAL Minor dispute over the map thing but I agree with everything else. An Example PR created by the script is here https://github.com/chxchx/istio/pull/11/files |
|
The PR that you pointed is still using gcr.io/istio-io in some of those update. |
sebastienvas
left a comment
There was a problem hiding this comment.
I can t see your comments. Let s do an hour of pair programming tomorrow so that I can understand where you are going
toolbox/deps_update/main.go
Outdated
| owner = flag.String("owner", "istio", "Github Owner or org") | ||
| tokenFile = flag.String("token_file", "", "File containing Github API Access Token") | ||
| baseBranch = flag.String("base_branch", "master", "Branch from which the deps update commit is based") | ||
| caHub = flag.String("ca_hub", "", "Optional. Where new CA image is hosted") |
There was a problem hiding this comment.
Just create one hub for all of them. It is the same we use for testing.
There was a problem hiding this comment.
Are you sure? Because on istio master, the three hubs in istio.VERSION are all different. Unless you are saying they all resolve to the same host but maybe having the option of updaing only one of the hubs and not others could be useful.
|
You are absolutely right. I forgot to rebase from istio/istio. Please take a look on this https://github.com/chxchx/istio/pull/12/files Also, this PR now contingent on the correction I just made at istio/istio#534 so please also take a look on that. |
61d2707 to
7acfe42
Compare
755da31 to
81bf23c
Compare
|
PTAL I hope I understand what @sebastienvas wants for the hub flag. Example PR created by this script can be found here https://github.com/chxchx/istio/pull/14/files |
|
/lgtm |
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: chxchx, sebastienvas, yutongz The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these OWNERS Files:
You can indicate your approval by writing |
|
/test all [submit-queue is verifying that this PR is safe to merge] |
|
Automatic merge from submit-queue |
Automatic merge from submit-queue Automated dependency update binary **Release note**: ```release-note NONE ```
Release note: