Skip to content

Conversation

chxchx
Copy link
Contributor

@chxchx chxchx commented Jul 27, 2017

Release note:

NONE

@googlebot googlebot added the cla: yes Set by the Google CLA bot to indicate the author of a PR has signed the Google CLA. label Jul 27, 2017
@chxchx
Copy link
Contributor Author

chxchx commented Jul 27, 2017

/assign @sebastienvas

@chxchx
Copy link
Contributor Author

chxchx commented Jul 27, 2017

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.

@sebastienvas sebastienvas self-requested a review July 27, 2017 02:13
if err != nil {
return err
}
mixerSHA, err := githubClnt.getHeadCommitSHA("mixer", "stable")
Copy link
Contributor

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 ?

Copy link
Contributor

@nlandolfi nlandolfi left a 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

  1. trying to get away from package level variables
  2. trying to be idiomatic
  3. 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:
Copy link
Contributor

Choose a reason for hiding this comment

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

s/Hoisting/Hosting

Copy link
Contributor Author

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
Copy link
Contributor

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.

Copy link
Contributor

Choose a reason for hiding this comment

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

or githubclient

Copy link
Contributor Author

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

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)
Copy link
Contributor

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

return hex.EncodeToString(hash[:])
}

// Shell run command on shell and get back output and error if get one
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: s/run/runs

Copy link
Contributor Author

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.

// GetMD5Hash generates an MD5 digest of the given string
func GetMD5Hash(text string) string {
hash := md5.Sum([]byte(text))
return hex.EncodeToString(hash[:])
Copy link
Contributor

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?

Copy link
Contributor

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

Copy link
Contributor Author

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.

}

// Shell run command on shell and get back output and error if get one
func Shell(format string, args ...interface{}) (string, error) {
Copy link
Contributor

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


var (
repo = flag.String("repo", "", "Update dependencies of only this repository")
githubClnt *githubClient
Copy link
Contributor

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

Copy link
Contributor Author

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?

Copy link
Contributor

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.

// 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) {
Copy link
Contributor

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)

Copy link
Contributor Author

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?

}

// Get the list of dependencies of a repo
// Assumes repo has been cloned to local
Copy link
Contributor

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?

Copy link
Contributor Author

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


// 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) {
Copy link
Contributor

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.

@nlandolfi
Copy link
Contributor

nlandolfi commented Jul 29, 2017 via email

@nlandolfi
Copy link
Contributor

nlandolfi commented Jul 29, 2017 via email

@chxchx
Copy link
Contributor Author

chxchx commented Jul 30, 2017

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 istio.deps file at root, and please also take a look at istio/istio#510

// Returns the updated line
func replaceCommit(line string, dep dependency) (string, error) {
idx := strings.Index(line, "\"")
return line[:idx] + "\"" + dep.LastStableSHA + "\",", nil
Copy link
Contributor

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.

Copy link
Contributor Author

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.

caHub := "docker.io/istio"
istioctlURL := fmt.Sprintf(
"https://storage.googleapis.com/istio-artifacts/pilot/%s/artifacts/istioctl", pilotSHA)
hub := "gcr.io/istio-testing"
Copy link
Contributor

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.

Copy link
Contributor Author

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.

caHub := "docker.io/istio"
istioctlURL := fmt.Sprintf(
"https://storage.googleapis.com/istio-artifacts/pilot/%s/artifacts/istioctl", pilotSHA)
hub := "gcr.io/istio-testing"
Copy link
Contributor

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.

// Returns the updated line
func replaceCommit(line string, dep dependency) (string, error) {
idx := strings.Index(line, "\"")
return line[:idx] + "\"" + dep.LastStableSHA + "\",", nil
Copy link
Contributor

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.

if _, err := util.Shell("git add *"); err != nil {
return err
}
if _, err := util.Shell("git commit -m Update_Dependencies"); err != nil {
Copy link
Contributor

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 "

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

}
for _, r := range repos {
if err := updateDependenciesOf(r); err != nil {
log.Panicf("Failed to udpate dependency: %v\n", err)
Copy link
Contributor

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

Copy link
Contributor Author

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() {
Copy link
Contributor

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

Copy link
Contributor Author

@chxchx chxchx Jul 31, 2017

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.

@chxchx
Copy link
Contributor Author

chxchx commented Jul 31, 2017

PTAL
An example PR on istio/istio created by this script can be found here https://github.com/chxchx/istio/pull/9/files

@sebastienvas
Copy link
Contributor

sebastienvas commented Aug 1, 2017

you should use pretty print on the json file. That being said, this looks promising

// 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")
Copy link
Contributor

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

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",
Copy link
Contributor

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

// Assumes at the root of istio directory
// Runs the updateVersion.sh script
func updateIstioDeps() error {
pilotSHA, err := githubClnt.getHeadCommitSHA("pilot", "stable")
Copy link
Contributor

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?

Copy link
Contributor Author

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.

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",
Copy link
Contributor

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.

Copy link
Contributor Author

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

}
title := prTitlePrefix + repo
body := "This PR will be merged automatically once checks are successful."
base := "master"
Copy link
Contributor

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

}
var multiErr error
for _, pr := range prs {
if strings.Contains(*pr.Title, prTitlePrefix) {
Copy link
Contributor

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 ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@chxchx
Copy link
Contributor Author

chxchx commented Aug 3, 2017

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

@sebastienvas
Copy link
Contributor

The PR that you pointed is still using gcr.io/istio-io in some of those update.

Copy link
Contributor

@sebastienvas sebastienvas left a 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

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")
Copy link
Contributor

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.

Copy link
Contributor Author

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.

@chxchx
Copy link
Contributor Author

chxchx commented Aug 3, 2017

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.

@chxchx chxchx force-pushed the depsUpdate branch 2 times, most recently from 61d2707 to 7acfe42 Compare August 3, 2017 05:05
@chxchx chxchx force-pushed the depsUpdate branch 2 times, most recently from 755da31 to 81bf23c Compare August 7, 2017 19:54
@chxchx
Copy link
Contributor Author

chxchx commented Aug 7, 2017

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

@sebastienvas
Copy link
Contributor

/lgtm

@istio-merge-robot
Copy link

[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:
  • OWNERS [sebastienvas,yutongz]

You can indicate your approval by writing /approve in a comment
You can cancel your approval by writing /approve cancel in a comment

@istio-merge-robot
Copy link

/test all [submit-queue is verifying that this PR is safe to merge]

@istio-merge-robot
Copy link

Automatic merge from submit-queue

@istio-merge-robot istio-merge-robot merged commit 6ddc565 into istio:master Aug 10, 2017
@chxchx chxchx deleted the depsUpdate branch August 10, 2017 20:11
yutongz pushed a commit to yutongz/test-infra that referenced this pull request Aug 16, 2017
Automatic merge from submit-queue

Automated dependency update binary

**Release note**:

```release-note
NONE
```
soloio-bot pushed a commit to soloio-bot/test-infra that referenced this pull request Jun 22, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cla: yes Set by the Google CLA bot to indicate the author of a PR has signed the Google CLA.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants