Skip to content

Conversation

justaugustus
Copy link
Member

@justaugustus justaugustus commented Sep 3, 2019

Introducing krel (the Kubernetes Release toolbox), and the first draft of the branch fast-forward subcommand, ff!

Here's the directory structure:

cmd/
├── krel
│   ├── BUILD.bazel
│   ├── cmd
│   │   ├── BUILD.bazel
│   │   ├── ff.go
│   │   └── root.go
│   └── main.go

pkg/
├──  util
    ├── BUILD.bazel
    ├── common.go
    └── git.go

After mulling this over for a bit, I decided we should get at least two things out of this:

  • A set of common libraries to use for the tooling rewrite (pkg/util/common.go and pkg/util/git.go are the first of these)
  • Unified CLI tool (via cobra), to take advantage of global flags (like --cleanup and --nomock) and common patterns

This is still pretty rough, but it's at least in a good place to merge the structure in and iterate! :)

Signed-off-by: Stephen Augustus [email protected]

@k8s-ci-robot k8s-ci-robot added do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. do-not-merge/blocked-paths Indicates that a PR should not merge because it touches files in blocked paths. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. labels Sep 3, 2019
@k8s-ci-robot k8s-ci-robot added size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. approved Indicates a PR has been approved by an approver from all required OWNERS files. area/release-eng Issues or PRs related to the Release Engineering subproject sig/release Categorizes an issue or PR as relevant to SIG Release. labels Sep 3, 2019
@justaugustus
Copy link
Member Author

(...and yes, the finished product will have tests 😅 )

@justaugustus justaugustus force-pushed the bff branch 5 times, most recently from 0b14acd to ad43a85 Compare September 10, 2019 17:41
@idealhack idealhack removed the request for review from claurence September 29, 2019 15:38
Copy link
Member

@saschagrunert saschagrunert left a comment

Choose a reason for hiding this comment

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

Hey 👋, generally LGTM, but I have some comments. Regarding the many TODOs still left in the code I'd suggest to bring this in as soon as possible and then we can resolve them together. :)

.golangci.yml Outdated
@@ -0,0 +1,32 @@
linters-settings:
Copy link
Member

Choose a reason for hiding this comment

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

I would suggest in adding golangci-lint as build target / verification script somewhere inside the CI.

}
*/

func AskYesOrNo(question string) (string, error) {
Copy link
Member

Choose a reason for hiding this comment

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

I would return a bool here to make the usage more straight forward.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done!

@@ -0,0 +1,203 @@
/*
Copy link
Member

Choose a reason for hiding this comment

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

We may unify this file with the one from pkg/notes/git.go

Copy link
Contributor

Choose a reason for hiding this comment

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

Agreed here, git related things feel like they would be worthy of their own package

Copy link
Member Author

Choose a reason for hiding this comment

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

+1! That was exactly what I had in mind. :)

pkg/util/git.go Outdated

func GetMergeBase(masterRefShort, releaseRefShort string, repo *git.Repository) (string, error) {
masterRef := fmt.Sprintf("origin/%s", masterRefShort)
releaseRef := fmt.Sprintf("origin/%s", releaseRefShort)
Copy link
Member

Choose a reason for hiding this comment

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

The default remote origin may be a const value somewhere since it's used in many places.

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed!

pkg/util/git.go Outdated
}

if len(res) == 0 {
os.Exit(1)
Copy link
Member

Choose a reason for hiding this comment

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

I suggest exit'ing in the main path and return an error here instead.

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed!

Comment on lines 71 to 72
log.Println(err)
os.Exit(1)
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
log.Println(err)
os.Exit(1)
log.Fatal(err)

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed!

@justaugustus
Copy link
Member Author

@saschagrunert -- sounds like a plan! I'll work on this this week.

@k8s-ci-robot k8s-ci-robot removed the do-not-merge/blocked-paths Indicates that a PR should not merge because it touches files in blocked paths. label Oct 29, 2019
@justaugustus
Copy link
Member Author

/test pull-release-test

@justaugustus justaugustus changed the title [WIP] cmd/branchff: Initial commit of Go-based branchff tool cmd/krel/cmd/ff: Initial commit of Go-based branchff tool Oct 31, 2019
@k8s-ci-robot k8s-ci-robot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Oct 31, 2019
@justaugustus
Copy link
Member Author

/assign @saschagrunert @hasheddan
/milestone v1.17

Copy link
Contributor

@hasheddan hasheddan left a comment

Choose a reason for hiding this comment

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

This is awesome @justaugustus, thanks for leading this effort :) A few comments below. Not sure at what state we should deem this mergeable, but I am fine moving forward with something that isn't perfect given we intend to iterate on this more.

)

// Run wraps the exec.Cmd.Run() command and sets the standard output.
// TODO: Should this take an error code argument/return an error code?
Copy link
Contributor

Choose a reason for hiding this comment

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

This a great thing to point out and I definitely think Run() should be returning error here. Otherwise, any user of this package is unable to determine whether to exit or continue as they see fit based on the outcome of calling this function. While it doesn't make a huge difference for ff, it could prove difficult to work with if any other tool consumes it.

@@ -0,0 +1,203 @@
/*
Copy link
Contributor

Choose a reason for hiding this comment

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

Agreed here, git related things feel like they would be worthy of their own package

pkg/util/git.go Outdated
// We can then use every Remote functions to retrieve wanted information
refs, err := rem.List(&git.ListOptions{})
if err != nil {
log.Fatal(err)
Copy link
Contributor

Choose a reason for hiding this comment

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

Would be useful to return an informative error here.

Copy link
Member

Choose a reason for hiding this comment

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

Later: We could use something like wrapping errors with additional context to provide some sort of error stack.

*/

func Ask(question, expectedResponse string) (string, bool, error) {
retries := 3
Copy link
Contributor

Choose a reason for hiding this comment

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

How would you feel about making retries a parameter here?

}

log.Printf(
`Go look around in %s to make sure things look okay before pushing...
Copy link
Contributor

Choose a reason for hiding this comment

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

nitpick: it might be more readable to move this to a separate variable outside the main function execution

@@ -0,0 +1,32 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
Copy link
Member

Choose a reason for hiding this comment

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

I’m wondering if we need bazel at all if we stick to go modules and a recent version (>1.12).

Copy link
Member Author

Choose a reason for hiding this comment

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

@saschagrunert -- Though I grumble on occasion about bazel, we get the advantage of leveraging the verify tests from k/repo-infra.

Updating & verifying all things is now simple:

  • update: ./hack/update-all.sh
  • verify: ./hack/verify-all.sh

See here: #889, #890

Copy link
Contributor

Choose a reason for hiding this comment

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

It, being the verify, does not seem to work for me: #908

It might well be an issue on my side, could someone maybe check if that actually works for you?

dryRunFlag = "--dry-run"
}

re := regexp.MustCompile(util.BranchRE)
Copy link
Member

Choose a reason for hiding this comment

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

I would add this as a stand alone function to the utils and avoid making BranchRE public, like: util.IsReleaseBranch(string)

log.Fatalf("%s is not a release branch\n", branch)
}

branchExists, err := util.BranchExists(branch)
Copy link
Member

Choose a reason for hiding this comment

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

Can we return either a bool or an error here? Because the value of err is unhandled and it could be that we return nil below.

Copy link
Member Author

Choose a reason for hiding this comment

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

Still returning both, but the error is handled now.

defer cleanupTmpDir(baseDir)
}

workingDir := fmt.Sprintf("%s/%s", baseDir, branch)
Copy link
Member

Choose a reason for hiding this comment

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

I would stick to filepath.Join for path manipulations.


currentPath := fmt.Sprintf("%s", os.Getenv("PATH"))
etcdPath := fmt.Sprintf("%s/third_party/etcd:%s", gitRoot, currentPath)
os.Setenv("PATH", os.Getenv("PATH"))
Copy link
Member

Choose a reason for hiding this comment

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

We should set it to etcdPath here, right?

)

// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
Copy link
Member

Choose a reason for hiding this comment

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

This is more a question to which style we want to stick:

Do we want to avoid global variables and init functions by moving them into main?

Copy link
Member Author

Choose a reason for hiding this comment

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

@saschagrunert -- I think I like the layout for this iteration, but we can talk style more once this merges. :)

@justaugustus
Copy link
Member Author

@hasheddan @saschagrunert -- I've addressed all of your comments, so this should be good to approve/merge now!

Copy link
Contributor

@hasheddan hasheddan left a comment

Choose a reason for hiding this comment

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

Assuming we are good with deferring tests to a future iteration (which seems fine considering we don't plan to be using this in a production setting until the tool is more robust) then LGTM!

/lgtm /approve

@justaugustus
Copy link
Member Author

@hasheddan -- As a heads up, /lgtm and /approve need to be on separate lines as the first and only thing on the line, like so:

/lgtm
/approve

@k8s-ci-robot
Copy link
Contributor

@justaugustus: you cannot LGTM your own PR.

In response to this:

@hasheddan -- As a heads up, /lgtm and /approve need to be on separate lines as the first and only thing on the line, like so:

/lgtm
/approve

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@justaugustus
Copy link
Member Author

(haha, I knew it was going to say that.)
/honk

@k8s-ci-robot
Copy link
Contributor

@justaugustus:
goose image

In response to this:

(haha, I knew it was going to say that.)
/honk

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@hasheddan
Copy link
Contributor

/lgtm

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Oct 31, 2019
@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: hasheddan, justaugustus

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot merged commit 82366a4 into kubernetes:master Oct 31, 2019
Copy link
Contributor

@hoegaarden hoegaarden left a comment

Choose a reason for hiding this comment

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

While I really appreciate all the work and thoughts that are going into re-writing the tools in go, I am abit concerned about the general direction:

This seems to be generally go int o a direction of a monolithic tool for all the release things. I think it would be more useful to break the release tools apart. What do I mean by that:
In short: don't implement things & "wiring" that other tools can do for us, just implement our specifics. Specifically In the case of branchff: really only implement our fast forwarding and merging business, push and pull and other stuff should be done elsewhere.

Why?

  • We can leverage other tools (GCB) to wire the things together
  • It's easier to change / adapt / ... e.g. we can just run other steps before/after the thing (branchff in this case) and the thing (branchff in this case) doesn't need to know or change

Consider this:

# "monostep" / bakcbox-ish step
- name: gcr.io/k8s-release-tools/krel
  args: [ "branchff", "--some-arg" ]

vs.

# get a thing, maybe not even git.k8s.io/kubernetes but some downstream vendor's repo
- name: gcr.io/cloud-builders/git
  dir: src/k8s
  args: [ "pull", "$_K8S_RPEO", "--branch", "$_K8S_REPO" ]
# only do the FF, nothing else 
- name: gcr.io/k8s-release-tools/branchff
  dir: src.k8s
  args: [ "$_FF_BRANCH" ]
# push it upstream, wherever that is
- name:  gcr.io/cloud-builders/git
  dir:  src/k8s
  args: [ "push", "upstream", "$_FF_BRANCH" ]

Now I want to run some tests on the branchff'ed branch (e.g. run e2e on kind or whatnot). Ideally that would be just adding a new GCB task, and not changing any code in branchff/krel/...

   [....]
# only do the FF, nothing else 
- name: gcr.io/k8s-release-tools/branchff
  dir: src.k8s
  args: [ "$_FF_BRANCH" ]
# run some tests with the branchff'ed code
- name: gcr.io/k8s-release-tools/kind-e2e
  args: [ "--k8s-src", "src/k8s" ]
# push it upstream, wherever that is -- IFF the last step succeeded
- name:  gcr.io/cloud-builders/git
  dir:  src/k8s
  args: [ "push", "upstream", "$_FF_BRANCH" ]

To summarise:

  • I am not saying the idea of krel is bad, I am merely questioning the direction it seems to go a bit.
  • I am concerned we might be on a path were we pack too much responsibility & wiring into the tool, and not leveraging enough of the other tools we are using already anyway.
  • I'd rather have some small sharp tools with a defined interface between each other. In the case of GCB the interface between multiple steps are directories to be consumed and produced. That's an easy enough thing to
    • run/wire locally
    • extract, reshuffle, extend, run single, ... steps
    • move to another system somewhen (e.g. if we find we need tekton).

@@ -0,0 +1,32 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
Copy link
Contributor

Choose a reason for hiding this comment

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

It, being the verify, does not seem to work for me: #908

It might well be an issue on my side, could someone maybe check if that actually works for you?

@justaugustus
Copy link
Member Author

We're chatting in Slack (https://kubernetes.slack.com/archives/CJH2GBF7Y/p1572605765115500) w.r.t. @hoegaarden's review.
I'm going to drop notes later on the umbrella issue to talk more about what's in my head direction-wise.

@tpepper
Copy link

tpepper commented Nov 1, 2019

I think @hoegaarden 's concerns are valid. As new things are built there definitely should also be refactoring common things out of existing tools and instituting new splits in the tools and flow (as in the pull, branchff, push example). Those are more testable. It's totally conceivable one person wont see a pattern and other reviewers will, and ask for a refactor. We'll have to decide on a case by case basis if the refactor should happen before merge, be done by the original change proposer, or if it can follow and if somebody else can do it. The latter path will likely lead to more merge conflicts and rebase issues if folks aren't communicating.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. area/release-eng Issues or PRs related to the Release Engineering subproject cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. lgtm "Looks good to me", indicates that a PR is ready to be merged. sig/release Categorizes an issue or PR as relevant to SIG Release. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants