• 
      

    Add support for Gerrit as a hosting service

    Review Request #8938 — Created May 11, 2017 and submitted

    Information

    Review Board
    release-2.5.x
    f04d061...

    Reviewers

    This patch adds support for Gerrit as a hosting service when the Gerrit
    server has the gerrit-reviewboard plugin installed (see: /r/8919/ et
    al.). The Gerrit API does not provide sufficient information (e.g., it
    cannot retrieve files by blob ID, cannot list commits, and cannot
    retrieve diffs for arbitrary commits not related to changes), so we rely
    on the plugin for this. This hosting service will check for the plugin's
    presence via the Gerrit API and will not allow repositories without it
    installed.

    • Tested post-commit review request creation.
    • Tested rbt post with a Gerrit-backed repository.
    • Ran unit tests.

    Description From Last Updated

    F401 'reviewboard.scmtools.errors.SCMError' imported but unused

    reviewbot reviewbot

    F401 'hashlib' imported but unused

    reviewbot reviewbot

    F401 'hmac' imported but unused

    reviewbot reviewbot

    F401 'json' imported but unused

    reviewbot reviewbot

    F401 'hashlib.md5' imported but unused

    reviewbot reviewbot

    F401 'textwrap.dedent' imported but unused

    reviewbot reviewbot

    F401 'django.core.exceptions.ObjectDoesNotExist' imported but unused

    reviewbot reviewbot

    F401 'django.utils.six' imported but unused

    reviewbot reviewbot

    F401 'django.utils.six.moves.cStringIO as StringIO' imported but unused

    reviewbot reviewbot

    F401 'django.utils.six.moves.urllib.error.HTTPError' imported but unused

    reviewbot reviewbot

    F401 'django.utils.six.moves.urllib.parse.urlparse' imported but unused

    reviewbot reviewbot

    F401 'djblets.testing.decorators.add_fixtures' imported but unused

    reviewbot reviewbot

    F401 'reviewboard.hostingsvcs.gerrit.Gerrit' imported but unused

    reviewbot reviewbot

    F401 'reviewboard.hostingsvcs.models.HostingServiceAccount' imported but unused

    reviewbot reviewbot

    E303 too many blank lines (2)

    reviewbot reviewbot

    E128 continuation line under-indented for visual indent

    reviewbot reviewbot

    E128 continuation line under-indented for visual indent

    reviewbot reviewbot

    E128 continuation line under-indented for visual indent

    reviewbot reviewbot

    E501 line too long (84 > 79 characters)

    reviewbot reviewbot

    E126 continuation line over-indented for hanging indent

    reviewbot reviewbot

    "subclasses"

    chipx86 chipx86

    I think you meant "hosting account"?

    chipx86 chipx86

    t comes after s.

    david david

    Wrap in parens instead of using the continuation character.

    david david

    The Meta class should come last in the form.

    chipx86 chipx86

    The &gt; can be inside the <tt>. In other words, one <tt> should be fine.

    chipx86 chipx86

    Here too.

    chipx86 chipx86

    Missing : after :py:meth.

    chipx86 chipx86

    "hostingsvcs"

    chipx86 chipx86

    "project form?"

    chipx86 chipx86

    Seems like this should maybe be "Gerrit URL"?

    chipx86 chipx86

    This is missing help text.

    chipx86 chipx86

    This should be "Project name". It's also missing help text.

    chipx86 chipx86

    Wrap this error in _()?

    david david

    The error should be less terse. Maybe "This is not a valid port. Ports must be in the range of …

    chipx86 chipx86

    Might read better as "The only required part is the FQDN ...

    chipx86 chipx86

    typo: ot

    david david

    Looks like this could be one line?

    chipx86 chipx86

    This can be one statement.

    chipx86 chipx86

    What happens if this changes in the future? Think we should code defensively here. If the data doesn't include this, …

    chipx86 chipx86

    We only use this in one error message that's only called when configuring a repository, so let's do that there …

    chipx86 chipx86

    Probably belongs up with form.

    chipx86 chipx86

    This is the default.

    chipx86 chipx86

    You don't have to provide this argument. It will be captured by kwargs.

    chipx86 chipx86

    No need to provide this either.

    chipx86 chipx86

    Missing , optional.

    chipx86 chipx86

    Missing , optional.

    chipx86 chipx86

    Needs the full class path.

    chipx86 chipx86

    e should be passed in as another arg, since the logger functions do their own format operation.

    david david

    Ideally we should flesh this out. "Unable to authenticate with Gerrit. The username or password might be invalid." It's best …

    chipx86 chipx86

    Missing docs.

    chipx86 chipx86

    We should be using encrypt_password and decrypt_password for any credentials being stored.

    chipx86 chipx86

    Typo: "reviewbaord" -> "reviewboard"

    chipx86 chipx86

    This can only be done if we're shipping this with 3.0. We still support Python 2.6 for Review Board 2.5.

    chipx86 chipx86

    I'd suggest following GitHub's model and defining an api_get that does the common stuff (passing credentials and only returning the …

    chipx86 chipx86

    I am left in suspense.

    chipx86 chipx86

    Historically, this function comes before the rest of the overriden functions (this, then authorize, then the rest).

    chipx86 chipx86

    Typo: "reviewbaord" -> "reviewboard"

    chipx86 chipx86

    You can do: parts = [ ... ] + rest_parts

    chipx86 chipx86

    Better formatted as: url = ('%s/' % urljoin(...)) I believe that will fit on two lines. Maybe three, if you …

    chipx86 chipx86

    Should be one statement.

    chipx86 chipx86

    Can you add two blank lines between these?

    david david

    Undo this change.

    david david

    Undo this change.

    david david

    Undo this change.

    david david

    Undo this change. The .closest is part of the whole selector process. The .setVisible is the thing we're calling on …

    chipx86 chipx86

    Can you add two blank lines between these?

    david david

    E999 SyntaxError: invalid syntax

    reviewbot reviewbot

    E501 line too long (80 > 79 characters)

    reviewbot reviewbot

    E303 too many blank lines (2)

    reviewbot reviewbot

    E303 too many blank lines (2)

    reviewbot reviewbot

    W391 blank line at end of file

    reviewbot reviewbot

    This should go after all the django.utils.six imports

    david david

    Use parens instead of \

    david david

    Trailing comma isn't necessary since these are just args. ) can be on this line too.

    david david

    Should be marked for translation.

    david david

    Should be marked for translation.

    david david

    Should end in a period to match the others.

    david david

    Instead of implementing a custom clean method you should be able to just pass in min_value and max_value to the …

    david david

    Other implementations call this arg hosting_service

    david david

    typo: ot

    david david

    Comma after "Otherwise"

    david david

    The string included in the comment here doesn't match the code.

    david david

    The implementation of _parse_plugin_version could raise exceptions if we get something unexpected from the server. Can we try/catch and convert …

    david david

    Blank line after this.

    david david

    Add two blank lines after this.

    david david

    Undo this change. Maybe wrap the whole thing in parens too?

    david david

    Undo this change.

    david david

    Undo this change.

    david david

    Undo this change.

    david david

    Undo this change.

    david david

    Add two blank lines before this.

    david david

    F401 'django.core.exceptions.ValidationError' imported but unused

    reviewbot reviewbot

    E203 whitespace before ':'

    reviewbot reviewbot

    E231 missing whitespace after ':'

    reviewbot reviewbot

    E701 multiple statements on one line (colon)

    reviewbot reviewbot

    E999 SyntaxError: invalid syntax

    reviewbot reviewbot

    We should probably assert that gerrit_url is not None here.

    david david

    Leftover debug output?

    david david

    Leftover debug output?

    david david

    I think this would be more readable if we split it up a bit: url = urljoin(repository.extra_data['gerrit_url'], '/'.join(parts)) if query: …

    david david

    Why this change?

    david david

    Blank line after this.

    david david

    So in python 3, json.dumps requires that all the keys and values be str. I think instead of having a …

    david david

    Same here.

    david david

    And here.

    david david

    And here.

    david david

    And here.

    david david

    Blank line after this.

    david david

    And here.

    david david

    E131 continuation line unaligned for hanging indent

    reviewbot reviewbot

    Because we know the format, this would be a lot more readable as: 'required': '%d.%d.%d' % self.REQUIRED_PLUGIN_VERSION,

    david david

    Please pass in e as an arg to logging.error instead of pre-formatting it.

    david david

    This should fit on one line.

    david david

    This can just use + instead of extend

    david david

    F401 'django.utils.six' imported but unused

    reviewbot reviewbot

    Swap these.

    chipx86 chipx86

    Should be in alphabetical order.

    chipx86 chipx86

    I know the base implementation doesn't do anything, but it might in the future. Let's call the parent method here.

    chipx86 chipx86

    "to the"

    chipx86 chipx86

    We should specify the URL here (first argument in *args), since we otherwise don't have enough information to figure out …

    chipx86 chipx86

    Can we have a module-level logger?

    chipx86 chipx86

    "Source code"

    chipx86 chipx86

    Mind linking to the URL here?

    chipx86 chipx86

    No need for the backtick when using a reference without a space in the name.

    chipx86 chipx86

    "Gerrit"

    chipx86 chipx86

    The ] shouldn't be here.

    chipx86 chipx86

    We should link to the URL for the repository in this message. We can then provide instructions in that repository's …

    chipx86 chipx86

    This can fit on one line.

    chipx86 chipx86

    We should specify the repository ID here, since we otherwise don't have enough information to debug problems.

    chipx86 chipx86

    Keyword arguments should ideally be used in localized text when there's more than one variable being injected. Helps with translations …

    chipx86 chipx86

    The dictionary should be expanded.

    chipx86 chipx86

    Same here.

    chipx86 chipx86

    We should specify the URL here, since we otherwise don't have enough information to debug problems.

    chipx86 chipx86

    Missing gettext.

    chipx86 chipx86

    Missing gettext.

    chipx86 chipx86

    The dictionary should be expanded.

    chipx86 chipx86

    Same here.

    chipx86 chipx86

    Parens around the equality check.

    chipx86 chipx86

    Missing gettext.

    chipx86 chipx86

    Missing gettext.

    chipx86 chipx86

    Same here.

    chipx86 chipx86

    Same here.

    chipx86 chipx86

    gettext

    chipx86 chipx86

    Can we catch an exception here and handle it gracefully, in case something goes wonky with the response?

    chipx86 chipx86

    Same here.

    chipx86 chipx86

    We should specify the repository ID here, since we otherwise don't have enough information to debug problems.

    chipx86 chipx86

    We should ideally use keywords for the format string here.

    chipx86 chipx86

    Same here.

    chipx86 chipx86

    Can you place arguments starting right after Commit(? These aren't long enough to require wrapping.

    chipx86 chipx86

    Same here.

    chipx86 chipx86

    Should use +=. It's faster. Or just + on the previous line.

    chipx86 chipx86

    Alphabetical order.

    chipx86 chipx86

    Alphabetical order.

    chipx86 chipx86

    Private methods go last.

    chipx86 chipx86

    You can start after Repository(

    chipx86 chipx86

    This shouldn't be necessary on Gerrit. Same with other calls in this file.

    chipx86 chipx86

    The parens aren't necessary in JavaScript.

    chipx86 chipx86

    E501 line too long (82 > 79 characters)

    reviewbot reviewbot

    E501 line too long (92 > 79 characters)

    reviewbot reviewbot

    E501 line too long (81 > 79 characters)

    reviewbot reviewbot

    E127 continuation line over-indented for visual indent

    reviewbot reviewbot

    W391 blank line at end of file

    reviewbot reviewbot

    E501 line too long (92 > 79 characters)

    reviewbot reviewbot

    E501 line too long (92 > 79 characters)

    reviewbot reviewbot

    E501 line too long (92 > 79 characters)

    reviewbot reviewbot

    I just realized this isn't going to work. e.read() makes no sense for a b64decode. The error isn't really descriptive …

    chipx86 chipx86

    This needs to be unfolded as well.

    chipx86 chipx86
    Checks run (1 failed, 1 succeeded)
    flake8 failed.
    JSHint passed.

    flake8

    brennie
    Review request changed
    Change Summary:

    Unit tests.

    Summary:
    WIP: Gerrit Support
    Add support for Gerrit as a hosting service
    Description:
    ~  

    WIP

      ~

    This patch adds support for Gerrit as a hosting service when the Gerrit

      + server has the gerrit-reviewboard plugin installed (see: /r/8919/ et
      + al.). The Gerrit API does not provide sufficient information (e.g., it
      + cannot retrieve files by blob ID, cannot list commits, and cannot
      + retrieve diffs for arbitrary commits not related to changes), so we rely
      + on the plugin for this. This hosting service will check for the plugin's
      + presence via the Gerrit API and will not allow repositories without it
      + installed.

    Testing Done:
      +
    • Tested post-commit review request creation.
      +
    • Tested rbt post with a Gerrit-backed repository.
      +
    • Ran unit tests.

    Checks run (1 failed, 1 succeeded)

    flake8 failed.
    JSHint passed.

    flake8

    brennie
    brennie
    david
    1. 
        
    2. reviewboard/hostingsvcs/gerrit.py (Diff revision 3)
       
       
       
       
       
       
       
       
       
       
      Show all issues

      t comes after s.

    3. reviewboard/hostingsvcs/gerrit.py (Diff revision 3)
       
       
       
      Show all issues

      Wrap in parens instead of using the continuation character.

      1. I discovered pycharm auto imports while doing the java stuff but it doesnt do it so pretty.

    4. reviewboard/hostingsvcs/gerrit.py (Diff revision 3)
       
       
      Show all issues

      Wrap this error in _()?

    5. reviewboard/hostingsvcs/gerrit.py (Diff revision 3)
       
       
      Show all issues

      typo: ot

    6. reviewboard/hostingsvcs/gerrit.py (Diff revision 3)
       
       
       
       
       
      Show all issues

      e should be passed in as another arg, since the logger functions do their own format operation.

    7. Show all issues

      Can you add two blank lines between these?

    8. Show all issues

      Undo this change.

    9. Show all issues

      Undo this change.

    10. Show all issues

      Undo this change.

    11. Show all issues

      Can you add two blank lines between these?

    12. 
        
    chipx86
    1. 
        
    2. reviewboard/hostingsvcs/forms.py (Diff revision 3)
       
       
      Show all issues

      "subclasses"

    3. reviewboard/hostingsvcs/forms.py (Diff revision 3)
       
       
      Show all issues

      I think you meant "hosting account"?

    4. reviewboard/hostingsvcs/gerrit.py (Diff revision 3)
       
       
      Show all issues

      The Meta class should come last in the form.

    5. reviewboard/hostingsvcs/gerrit.py (Diff revision 3)
       
       
      Show all issues

      The &gt; can be inside the <tt>. In other words, one <tt> should be fine.

    6. reviewboard/hostingsvcs/gerrit.py (Diff revision 3)
       
       
      Show all issues

      Here too.

    7. reviewboard/hostingsvcs/gerrit.py (Diff revision 3)
       
       
      Show all issues

      Missing : after :py:meth.

    8. reviewboard/hostingsvcs/gerrit.py (Diff revision 3)
       
       
      Show all issues

      "hostingsvcs"

    9. reviewboard/hostingsvcs/gerrit.py (Diff revision 3)
       
       
      Show all issues

      "project form?"

    10. reviewboard/hostingsvcs/gerrit.py (Diff revision 3)
       
       
      Show all issues

      Seems like this should maybe be "Gerrit URL"?

    11. reviewboard/hostingsvcs/gerrit.py (Diff revision 3)
       
       
      Show all issues

      This is missing help text.

    12. reviewboard/hostingsvcs/gerrit.py (Diff revision 3)
       
       
      Show all issues

      This should be "Project name".

      It's also missing help text.

    13. reviewboard/hostingsvcs/gerrit.py (Diff revision 3)
       
       
      Show all issues

      The error should be less terse. Maybe "This is not a valid port. Ports must be in the range of 0-65535."

    14. reviewboard/hostingsvcs/gerrit.py (Diff revision 3)
       
       
      Show all issues

      Might read better as "The only required part is the FQDN ...

    15. reviewboard/hostingsvcs/gerrit.py (Diff revision 3)
       
       
       
      Show all issues

      Looks like this could be one line?

    16. reviewboard/hostingsvcs/gerrit.py (Diff revision 3)
       
       
       
      Show all issues

      This can be one statement.

    17. reviewboard/hostingsvcs/gerrit.py (Diff revision 3)
       
       
      Show all issues

      What happens if this changes in the future? Think we should code defensively here. If the data doesn't include this, log it and return the data as-is. Might also want to make the \n optional, as that seems like an easy thing that can change.

    18. reviewboard/hostingsvcs/gerrit.py (Diff revision 3)
       
       
       
      Show all issues

      We only use this in one error message that's only called when configuring a repository, so let's do that there instead.

    19. reviewboard/hostingsvcs/gerrit.py (Diff revision 3)
       
       
      Show all issues

      Probably belongs up with form.

    20. reviewboard/hostingsvcs/gerrit.py (Diff revision 3)
       
       
      Show all issues

      This is the default.

    21. reviewboard/hostingsvcs/gerrit.py (Diff revision 3)
       
       
       
      Show all issues

      You don't have to provide this argument. It will be captured by kwargs.

    22. reviewboard/hostingsvcs/gerrit.py (Diff revision 3)
       
       
       
      Show all issues

      No need to provide this either.

    23. reviewboard/hostingsvcs/gerrit.py (Diff revision 3)
       
       
      Show all issues

      Missing , optional.

    24. reviewboard/hostingsvcs/gerrit.py (Diff revision 3)
       
       
      Show all issues

      Missing , optional.

    25. reviewboard/hostingsvcs/gerrit.py (Diff revision 3)
       
       
      Show all issues

      Needs the full class path.

    26. reviewboard/hostingsvcs/gerrit.py (Diff revision 3)
       
       
      Show all issues

      Ideally we should flesh this out. "Unable to authenticate with Gerrit. The username or password might be invalid."

      It's best to avoid overly terse errors that look like they came from Posix libraries.

    27. reviewboard/hostingsvcs/gerrit.py (Diff revision 3)
       
       
      Show all issues

      Missing docs.

    28. reviewboard/hostingsvcs/gerrit.py (Diff revision 3)
       
       
      Show all issues

      We should be using encrypt_password and decrypt_password for any credentials being stored.

    29. reviewboard/hostingsvcs/gerrit.py (Diff revision 3)
       
       
      Show all issues

      Typo: "reviewbaord" -> "reviewboard"

    30. reviewboard/hostingsvcs/gerrit.py (Diff revision 3)
       
       
       
       
       
       
      Show all issues

      I'd suggest following GitHub's model and defining an api_get that does the common stuff (passing credentials and only returning the data).

    31. reviewboard/hostingsvcs/gerrit.py (Diff revision 3)
       
       
      Show all issues

      I am left in suspense.

    32. reviewboard/hostingsvcs/gerrit.py (Diff revision 3)
       
       
      Show all issues

      Historically, this function comes before the rest of the overriden functions (this, then authorize, then the rest).

    33. reviewboard/hostingsvcs/gerrit.py (Diff revision 3)
       
       
      Show all issues

      Typo: "reviewbaord" -> "reviewboard"

    34. reviewboard/hostingsvcs/gerrit.py (Diff revision 3)
       
       
       
      Show all issues

      You can do:

      parts = [
          ...
      ] + rest_parts
      
    35. reviewboard/hostingsvcs/gerrit.py (Diff revision 3)
       
       
       
       
       
      Show all issues

      Better formatted as:

      url = ('%s/'
             % urljoin(...))
      

      I believe that will fit on two lines. Maybe three, if you need to put '/'.join(parts) on the next line.

    36. reviewboard/hostingsvcs/tests/test_gerrit.py (Diff revision 3)
       
       
       
       
      Show all issues

      Should be one statement.

    37. Show all issues

      Undo this change. The .closest is part of the whole selector process. The .setVisible is the thing we're calling on the resulting elements.

      1. This is in contravention to basically the rest of our JS style.

      2. I think this would be the best:

        $twoFactorAuthRows = $authForm
            .find('[data-required-for-2fa]')
            .closest('.form-row')
                .setVisible(hostingInfo.needs_two_factor_auth_code);
        
    38. 
        
    chipx86
    1. 
        
    2. reviewboard/hostingsvcs/gerrit.py (Diff revision 3)
       
       
       
       
       
       
      Show all issues

      This can only be done if we're shipping this with 3.0. We still support Python 2.6 for Review Board 2.5.

    3. 
        
    brennie
    Review request changed
    Change Summary:

    Addressed Christian's feedback. Need to doublecheck everything still works.

    Checks run (1 failed, 1 succeeded)

    flake8 failed.
    JSHint passed.

    flake8

    brennie
    david
    1. 
        
    2. reviewboard/hostingsvcs/gerrit.py (Diff revision 5)
       
       
      Show all issues

      This should go after all the django.utils.six imports

    3. reviewboard/hostingsvcs/gerrit.py (Diff revision 5)
       
       
       
      Show all issues

      Use parens instead of \

    4. reviewboard/hostingsvcs/gerrit.py (Diff revision 5)
       
       
      Show all issues

      Trailing comma isn't necessary since these are just args. ) can be on this line too.

    5. reviewboard/hostingsvcs/gerrit.py (Diff revision 5)
       
       
       
      Show all issues

      Should be marked for translation.

    6. reviewboard/hostingsvcs/gerrit.py (Diff revision 5)
       
       
       
      Show all issues

      Should be marked for translation.

    7. reviewboard/hostingsvcs/gerrit.py (Diff revision 5)
       
       
      Show all issues

      Should end in a period to match the others.

    8. reviewboard/hostingsvcs/gerrit.py (Diff revision 5)
       
       
      Show all issues

      Instead of implementing a custom clean method you should be able to just pass in min_value and max_value to the forms.IntegerField constructor.

    9. reviewboard/hostingsvcs/gerrit.py (Diff revision 5)
       
       
      Show all issues

      Other implementations call this arg hosting_service

    10. reviewboard/hostingsvcs/gerrit.py (Diff revision 5)
       
       
      Show all issues

      typo: ot

    11. reviewboard/hostingsvcs/gerrit.py (Diff revision 5)
       
       
      Show all issues

      Comma after "Otherwise"

    12. reviewboard/hostingsvcs/gerrit.py (Diff revision 5)
       
       
      Show all issues

      The string included in the comment here doesn't match the code.

    13. reviewboard/hostingsvcs/gerrit.py (Diff revision 5)
       
       

      Does this need a try/catch?

    14. reviewboard/hostingsvcs/gerrit.py (Diff revision 5)
       
       
       
      Show all issues

      The implementation of _parse_plugin_version could raise exceptions if we get something unexpected from the server. Can we try/catch and convert to a RepositoryError?

    15. reviewboard/hostingsvcs/gerrit.py (Diff revision 5)
       
       

      Does this need a try/catch?

    16. reviewboard/hostingsvcs/gerrit.py (Diff revision 5)
       
       
      Show all issues

      Blank line after this.

    17. reviewboard/hostingsvcs/gerrit.py (Diff revision 5)
       
       

      Does this need a try/catch?

    18. Show all issues

      Add two blank lines after this.

    19. Show all issues

      Undo this change. Maybe wrap the whole thing in parens too?

    20. reviewboard/static/rb/js/admin/repositoryform.js (Diff revision 5)
       
       
       
       
      Show all issues

      Undo this change.

    21. Show all issues

      Undo this change.

    22. Show all issues

      Undo this change.

    23. Show all issues

      Undo this change.

    24. Show all issues

      Add two blank lines before this.

    25. 
        
    brennie
    Review request changed
    Change Summary:

    Addressed David's feedback

    Commit:
    132ec30a34ede4c145c351ae1bb63c42eeafd408
    94bd97fdcb38df77c798472722c37a0e661f712a

    Checks run (1 failed, 1 succeeded)

    flake8 failed.
    JSHint passed.

    flake8

    brennie
    brennie
    david
    1. 
        
    2. reviewboard/hostingsvcs/gerrit.py (Diff revision 8)
       
       
      Show all issues

      We should probably assert that gerrit_url is not None here.

    3. reviewboard/hostingsvcs/gerrit.py (Diff revision 8)
       
       
      Show all issues

      Leftover debug output?

    4. reviewboard/hostingsvcs/gerrit.py (Diff revision 8)
       
       
      Show all issues

      Leftover debug output?

    5. reviewboard/hostingsvcs/gerrit.py (Diff revision 8)
       
       
       
      Show all issues

      I think this would be more readable if we split it up a bit:

      url = urljoin(repository.extra_data['gerrit_url'],
                    '/'.join(parts))
      
      if query:
          url = '%s/?%s' % (url, urlencode(query))
      else:
          url = '%s/' % url
      
    6. reviewboard/hostingsvcs/github.py (Diff revision 8)
       
       
      Show all issues

      Why this change?

    7. 
        
    brennie
    david
    1. 
        
    2. reviewboard/hostingsvcs/gerrit.py (Diff revision 9)
       
       
      Show all issues

      Blank line after this.

    3. Show all issues

      So in python 3, json.dumps requires that all the keys and values be str. I think instead of having a bunch of bytestrings in here, we should have them all be unicode, but then do json.dumps(...).encode('utf-8')

    4. Show all issues

      Same here.

    5. Show all issues

      And here.

    6. Show all issues

      And here.

    7. Show all issues

      And here.

    8. Show all issues

      Blank line after this.

    9. Show all issues

      And here.

    10. 
        
    brennie
    Review request changed
    Change Summary:

    Addressed David's feedback.

    Commit:
    639c85ab2d5a1df87bfe49e9aa0814c90c1618d3
    2049fb6d13a537310bd7fba1dc37c32d24bfba50

    Checks run (1 failed, 1 succeeded)

    flake8 failed.
    JSHint passed.

    flake8

    brennie
    david
    1. 
        
    2. reviewboard/hostingsvcs/gerrit.py (Diff revision 11)
       
       
       
       
      Show all issues

      Because we know the format, this would be a lot more readable as:

      'required': '%d.%d.%d' % self.REQUIRED_PLUGIN_VERSION,
      
    3. reviewboard/hostingsvcs/gerrit.py (Diff revision 11)
       
       
      Show all issues

      Please pass in e as an arg to logging.error instead of pre-formatting it.

    4. reviewboard/hostingsvcs/gerrit.py (Diff revision 11)
       
       
       
      Show all issues

      This should fit on one line.

    5. reviewboard/hostingsvcs/gerrit.py (Diff revision 11)
       
       
       
      Show all issues

      This can just use + instead of extend

      1. Not if its a tuple.

      2. >>> (1, 2, 3) + (4, 5)
        (1, 2, 3, 4, 5)
        
      3. Oh, I see, you're appending a tuple to a list. Nevermind then.

    6. 
        
    brennie
    Review request changed
    Change Summary:

    Addressed David's feedback.

    Commit:
    281ec69a84c890149fe2c5f6562f5a9ce7cbc3d5
    d7ca381374c4239518f524add0f7bfa44f9d2a80

    Checks run (1 failed, 1 succeeded)

    flake8 failed.
    JSHint passed.

    flake8

    brennie
    david
    1. Looks good. Please re-run manual and automated tests before pushing.

    2. 
        
    chipx86
    1. This looks like more feedback than it is. Primarily some small docs/error message stuff repeated for different instances.

    2. reviewboard/hostingsvcs/gerrit.py (Diff revision 13)
       
       
       
      Show all issues

      Swap these.

    3. reviewboard/hostingsvcs/gerrit.py (Diff revision 13)
       
       
       
       
       
      Show all issues

      Should be in alphabetical order.

    4. reviewboard/hostingsvcs/gerrit.py (Diff revision 13)
       
       
       
       
       
       
       
       
      Show all issues

      I know the base implementation doesn't do anything, but it might in the future. Let's call the parent method here.

    5. reviewboard/hostingsvcs/gerrit.py (Diff revision 13)
       
       
      Show all issues

      "to the"

    6. reviewboard/hostingsvcs/gerrit.py (Diff revision 13)
       
       
       
       
      Show all issues

      We should specify the URL here (first argument in *args), since we otherwise don't have enough information to figure out what went wrong.

    7. reviewboard/hostingsvcs/gerrit.py (Diff revision 13)
       
       
      Show all issues

      Can we have a module-level logger?

      1. I thought we couldn't use module-level loggers for some reason?

    8. reviewboard/hostingsvcs/gerrit.py (Diff revision 13)
       
       
      Show all issues

      "Source code"

    9. reviewboard/hostingsvcs/gerrit.py (Diff revision 13)
       
       
      Show all issues

      Mind linking to the URL here?

    10. reviewboard/hostingsvcs/gerrit.py (Diff revision 13)
       
       
      Show all issues

      "Gerrit"

    11. reviewboard/hostingsvcs/gerrit.py (Diff revision 13)
       
       
      Show all issues

      The ] shouldn't be here.

    12. reviewboard/hostingsvcs/gerrit.py (Diff revision 13)
       
       
       
      Show all issues

      We should link to the URL for the repository in this message. We can then provide instructions in that repository's README for installation instructions.

    13. reviewboard/hostingsvcs/gerrit.py (Diff revision 13)
       
       
       
       
       
      Show all issues

      We should specify the repository ID here, since we otherwise don't have enough information to debug problems.

      1. We don't have a repository ID here, unless I am mistaken.

      2. You're right, we don't. We can include the Gerrit URL in this case.

    14. reviewboard/hostingsvcs/gerrit.py (Diff revision 13)
       
       
       
       
      Show all issues

      Keyword arguments should ideally be used in localized text when there's more than one variable being injected. Helps with translations when the order ends up changing.

    15. reviewboard/hostingsvcs/gerrit.py (Diff revision 13)
       
       
       
       
      Show all issues

      We should specify the URL here, since we otherwise don't have enough information to debug problems.

    16. reviewboard/hostingsvcs/gerrit.py (Diff revision 13)
       
       
      Show all issues

      Missing gettext.

    17. reviewboard/hostingsvcs/gerrit.py (Diff revision 13)
       
       
       
       
       
       
      Show all issues

      Missing gettext.

    18. reviewboard/hostingsvcs/gerrit.py (Diff revision 13)
       
       
      Show all issues

      Parens around the equality check.

    19. reviewboard/hostingsvcs/gerrit.py (Diff revision 13)
       
       
       
      Show all issues

      Missing gettext.

    20. reviewboard/hostingsvcs/gerrit.py (Diff revision 13)
       
       
       
      Show all issues

      Missing gettext.

    21. reviewboard/hostingsvcs/gerrit.py (Diff revision 13)
       
       
       
      Show all issues

      gettext

    22. reviewboard/hostingsvcs/gerrit.py (Diff revision 13)
       
       
      Show all issues

      Can we catch an exception here and handle it gracefully, in case something goes wonky with the response?

    23. reviewboard/hostingsvcs/gerrit.py (Diff revision 13)
       
       
       
      Show all issues

      We should specify the repository ID here, since we otherwise don't have enough information to debug problems.

    24. reviewboard/hostingsvcs/gerrit.py (Diff revision 13)
       
       
       
       
      Show all issues

      We should ideally use keywords for the format string here.

    25. reviewboard/hostingsvcs/gerrit.py (Diff revision 13)
       
       
       
       
       
       
       
       
      Show all issues

      Can you place arguments starting right after Commit(? These aren't long enough to require wrapping.

    26. reviewboard/hostingsvcs/gerrit.py (Diff revision 13)
       
       
      Show all issues

      Should use +=. It's faster. Or just + on the previous line.

      1. Can't if rest_parts is a tuple, like I mentioned in a previous review.

    27. reviewboard/hostingsvcs/tests/test_gerrit.py (Diff revision 13)
       
       
       
      Show all issues

      Alphabetical order.

    28. reviewboard/hostingsvcs/tests/test_gerrit.py (Diff revision 13)
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
      Show all issues

      Private methods go last.

    29. reviewboard/hostingsvcs/tests/test_gerrit.py (Diff revision 13)
       
       
       
       
       
      Show all issues

      You can start after Repository(

    30. Show all issues

      This shouldn't be necessary on Gerrit.

      Same with other calls in this file.

    31. Show all issues

      The parens aren't necessary in JavaScript.

    32. 
        
    brennie
    Review request changed
    Commit:
    1f0aa4dfbc6c40684fe348a89596a65d9eeb6ab2
    31bdb1f97a0c065362f617be8515ea3982d75e03

    Checks run (1 failed, 1 succeeded)

    flake8 failed.
    JSHint passed.

    flake8

    brennie
    Review request changed
    Commit:
    31bdb1f97a0c065362f617be8515ea3982d75e03
    6fad3546f04264c9f312cb0fc60a1f831b578ea0

    Checks run (1 failed, 1 succeeded)

    flake8 failed.
    JSHint passed.

    flake8

    brennie
    Review request changed
    Commit:
    6fad3546f04264c9f312cb0fc60a1f831b578ea0
    ad10029713c4314896eb8ca1f46b3a1170e0fbca

    Checks run (1 failed, 1 succeeded)

    flake8 failed.
    JSHint passed.

    flake8

    chipx86
    1. 
        
    2. reviewboard/hostingsvcs/gerrit.py (Diff revisions 13 - 16)
       
       
      Show all issues

      No need for the backtick when using a reference without a space in the name.

    3. reviewboard/hostingsvcs/gerrit.py (Diff revisions 13 - 16)
       
       
       
      Show all issues

      This can fit on one line.

    4. reviewboard/hostingsvcs/gerrit.py (Diff revisions 13 - 16)
       
       
      Show all issues

      The dictionary should be expanded.

    5. reviewboard/hostingsvcs/gerrit.py (Diff revisions 13 - 16)
       
       
      Show all issues

      Same here.

    6. reviewboard/hostingsvcs/gerrit.py (Diff revisions 13 - 16)
       
       
      Show all issues

      The dictionary should be expanded.

    7. reviewboard/hostingsvcs/gerrit.py (Diff revisions 13 - 16)
       
       
      Show all issues

      Same here.

    8. reviewboard/hostingsvcs/gerrit.py (Diff revisions 13 - 16)
       
       
      Show all issues

      Same here.

    9. reviewboard/hostingsvcs/gerrit.py (Diff revisions 13 - 16)
       
       
      Show all issues

      Same here.

    10. reviewboard/hostingsvcs/gerrit.py (Diff revisions 13 - 16)
       
       
      Show all issues

      Same here.

    11. reviewboard/hostingsvcs/gerrit.py (Diff revisions 13 - 16)
       
       
      Show all issues

      Same here.

    12. reviewboard/hostingsvcs/gerrit.py (Diff revisions 13 - 16)
       
       
      Show all issues

      Same here.

    13. reviewboard/hostingsvcs/tests/test_gerrit.py (Diff revisions 13 - 16)
       
       
       
       
       
      Show all issues

      Alphabetical order.

    14. 
        
    brennie
    Review request changed
    Commit:
    ad10029713c4314896eb8ca1f46b3a1170e0fbca
    4404c4ee7df5a5ca36c3a62058727dcef72fbaf7

    Checks run (1 failed, 1 succeeded)

    flake8 failed.
    JSHint passed.

    flake8

    brennie
    chipx86
    1. 
        
    2. reviewboard/hostingsvcs/gerrit.py (Diff revision 18)
       
       
       
       
       
       
       
       
       
       
       
       
      Show all issues

      I just realized this isn't going to work. e.read() makes no sense for a b64decode. The error isn't really descriptive of the problem, either. Can you fix this up and add a unit test for it?

    3. reviewboard/hostingsvcs/gerrit.py (Diff revision 18)
       
       
      Show all issues

      This needs to be unfolded as well.

    4. 
        
    brennie
    brennie
    chipx86
    1. Ship It!
    2. 
        
    brennie
    Review request changed
    Status:
    Completed
    Change Summary:
    Pushed to release-2.5.x (308de19)