-
Notifications
You must be signed in to change notification settings - Fork 181
Automated dependency update binary #336
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
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about auth for istio-ca ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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!
toolbox/deps_update/dependency.go
Outdated
package main | ||
|
||
/* | ||
Assumes Dependency Hoisting in all bazel dependency files. Example: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/Hoisting/Hosting
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
or githubclient
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think either parameterize this function by a context or use context.Background() -- not TODO
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: s/run/runs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
haha I took this code from istio/istio. I blame Seb on this.
toolbox/deps_update/util.go
Outdated
// 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
toolbox/deps_update/util.go
Outdated
} | ||
|
||
// 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
toolbox/deps_update/main.go
Outdated
|
||
var ( | ||
repo = flag.String("repo", "", "Update dependencies of only this repository") | ||
githubClnt *githubClient |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
doesn't seem like this should be a global package level variable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to have an error return if the function never returns an error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe you can use "git commit -am "
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Careful using panic, you may still want to update other repos even the first one hit an error
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
return nil | ||
} | ||
|
||
func main() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose it is a periodic job, then why not use goroutine and wake up every midnight
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We want this to work also for release branches, so you should make the branch as a flag.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment here. Use the branch as a flag.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe dynamically update the flags based which deps needs to be updated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment here. Make the branch a flag.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't you want to look only those that have the prefix ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just create one hub for all of them. It is the same we use for testing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Needs 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: