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

Map label to PR according to nested path #119

Merged
merged 1 commit into from Sep 3, 2018
Merged

Map label to PR according to nested path #119

merged 1 commit into from Sep 3, 2018

Conversation

boaz0
Copy link
Member

@boaz0 boaz0 commented Aug 22, 2018

NOTE: this is an idea that I have to support this usecase. I would love to hear what you think.

Currently you can set labels according to one of the root directories (app, webpack, etc). In other words, you cannot label a PR according to a file in app/assets.

This commit adds this feature. For example in repos.yml:

theforeman/foreman:
  directory_labels:
    app/assets: ui
    app/controllers: backend
    webpack: ui

it will add ui label if there were changed files in ./app/assets/ or ./webpack/ and backend label if
a file was changed in ./app/controllers.

//cc : @ekohl @ohadlevy @tbrisker

@ekohl
Copy link
Member

ekohl commented Aug 22, 2018

I'm not a fan of the nested hash. How about just a simple hash where every key is a path?

theforeman/foreman:
  directory_labels:
    app/assets: ui
    app/controllers: backend
    webpack: ui

Then you can compare it with something like:

def is_subpath_of(matcher, path)
  matcher_parts = matcher.split('/')
  path_parts = path.split('/')
  return path_parts.length >= matcher_parts.length && !matcher_parts.zip(path_parts).any? { |first, second| first != second }
end

@tbrisker
Copy link
Member

Am I missing something here? why not just something like path.starts_with?(matcher)?

@ekohl
Copy link
Member

ekohl commented Aug 22, 2018

Am I missing something here? why not just something like path.starts_with?(matcher)?

Is that a function of the pathing library?

[22] pry(main)> 'app/assets2'.starts_with?('app/assets')
NoMethodError: undefined method `starts_with?' for "app/assets2":String
Did you mean?  start_with?
from (pry):32:in `__pry__'

Some tests that should pass:

refute is_subpath_of('app/assets', 'app')
assert is_subpath_of('app/assets', 'app/assets')
assert is_subpath_of('app/assets', 'app/assets/bla')
refute is_subpath_of('app/assets', 'app/assets2')
refute is_subpath_of('app/assets', 'assets/app')

@tbrisker
Copy link
Member

Sorry, i meant start_with? - that's a string function, https://ruby-doc.org/core-2.5.1/String.html#method-i-start_with-3F

@ekohl
Copy link
Member

ekohl commented Aug 22, 2018

That would fail with app/assets2 matching on app/assets

@boaz0
Copy link
Member Author

boaz0 commented Aug 23, 2018

We might go with @tbrisker idea if we do normalization (adding / if not giving in the end of matcher) before path.start_with?(matcher) unless I am missing an edge-case.

@ekohl thanks for your implementation, it does look way more elegant than mine. I will update the PR and add your tests.

Thanks.

@boaz0 boaz0 changed the title [PoC] Map label to PR according to nested path [WIP] Map label to PR according to nested path Aug 23, 2018
@tbrisker
Copy link
Member

@ekohl - Like @ripcurld suggests, that edge case could be easily solvable by adding a / at the end to make sure only the exact dir is matched. TBH, I'm not sure that edge case is one that exists in any of our code that we want these notifications for.

@boaz0 boaz0 changed the title [WIP] Map label to PR according to nested path Map label to PR according to nested path Aug 26, 2018
Copy link
Member

@ekohl ekohl left a comment

Choose a reason for hiding this comment

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

This feels like a very inefficient way. A more efficient way would be to copy the mapping. If you have found a hit, you can remove any entry from the mapping where the value is that label. Then you can continue until you've either processed all files or the mapping is empty. That was also present in the old code so perhaps it's not needed to optimize it now though.

@@ -179,9 +179,17 @@ def add_status(state, message, options = {})
@client.create_status(repo.full_name, options[:sha], state, context: 'prprocessor', description: message, target_url: options[:url])
end

def get_labels(filename, mapping)
mapping.select { |k, v| filename.start_with?(k) }.map { |k, v| v }
Copy link
Member

Choose a reason for hiding this comment

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

This should be filename == k || filename.start_with("#{k}/"). That way you can also match files. You can then remove the normalization code I think.

You can also use .values instead of the map.

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks @ekohl
Just one problem that I foresee - "directory_label" will be very confusing if we set there files names too. Maybe we should mention this in a document or rename it to "path_label"?

WDYT?

Copy link
Member

Choose a reason for hiding this comment

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

👍 for path_labels

@ekohl
Copy link
Member

ekohl commented Sep 3, 2018

Could you rebase this on current master and also update the theforeman/foreman which now also has directory_labels?

Side note: when force pushing to a PR, GH doesn't send a notification so they can easily go unnoticed. It can be good to place a comment that you updated it.

@@ -179,9 +179,17 @@ def add_status(state, message, options = {})
@client.create_status(repo.full_name, options[:sha], state, context: 'prprocessor', description: message, target_url: options[:url])
end

def set_directory_labels(mapping)
def get_labels(filename, mapping)
mapping.select { |k, v| filename == k || filename.start_with?((k+"/").squeeze) }.values
Copy link
Member

Choose a reason for hiding this comment

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

I didn't know squeeze but isn't this dangerous? Looks like it squeezes all duplicate characters but in a directory name you can have them for valid reasons (lookups would become lokups).

Copy link
Member Author

Choose a reason for hiding this comment

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

My bad. I thought squeeze removes characters from the end of the string.
What I wanted to do is to remove extra / in the key. For example, if someone adds "app/views/" to the map then it probably won't add "app/views/" label because the file "app/views/models/index.html" doesn't start with "app/views//".

Maybe using gsub can be replaced here?

@boaz0
Copy link
Member Author

boaz0 commented Sep 3, 2018

@ekohl rebased and updated - can you give feedback again? thanks 😃

@@ -20,7 +20,7 @@ theforeman/foreman:
redmine: foreman
redmine_required: true
link_to_redmine: true
directory_labels:
path_labels:
.+-stable: Stable branch
Copy link
Member

Choose a reason for hiding this comment

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

Looks like I messed this one up. This one should have been a branch_labels. I'll submit a separate PR to fix that.

github/pull_request.rb Outdated Show resolved Hide resolved
@boaz0
Copy link
Member Author

boaz0 commented Sep 3, 2018

//ping @ekohl your review again 🤞

.map{ |r| r.path_labels.keys }
.flatten
.select { |file_path| file_path.end_with?('/') }
assert_equal [], paths, "remove backslash from the following paths: #{paths.join(', ')}"
Copy link
Member

Choose a reason for hiding this comment

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

It's a slash (/), not a backslash (\). I'd also mention it's a trailing slash. Note backslash is also in the test name.

Currently you can set labels according to one of
the root directories (app, etc).
In other words, you cannot label a PR according to
a file in app/assets.

This commit adds this feature. For example in repos.yml:

theforeman/foreman:
  path_labels:
    app/assets: ui
    app/controllers: backend
    webpack: ui

it will add ui label if there were changed files in
./app/assets/ or ./webpack/ and backend label if
a file was changed in app/controllers

NOTE: "directory_labels" options is replaced by
      "path_labels".

Signed-off-by: Boaz Shuster <boaz.shuster.github@gmail.com>
@boaz0
Copy link
Member Author

boaz0 commented Sep 3, 2018

@ekohl done

@ekohl ekohl merged commit 2eb242f into theforeman:master Sep 3, 2018
@boaz0 boaz0 deleted the label_matcher branch September 3, 2018 15:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants