Skip to content

Project Push Rules get method returning NoneType #1192

Closed

Description

@L30Bola

Description of the problem, including code/CLI snippet

I have this function

def set_project_push_rules_configuration(gitlab, project_id, **kwargs):
    """
    On kwargs you pass arguments that are mutable using the Gitlab Project's Push Rules API
    Documentation on that: https://docs.gitlab.com/ee/api/projects.html#push-rules
    """

    defaults = {
        "prevent_secrets": True,
    }
    defaults.update(kwargs)
    project = gitlab.projects.get(project_id)
    project_push_rules = project.pushrules.get()
    project_push_rules = set_attrs(project_push_rules, defaults)
    try:
        project_push_rules.save()
    except GitlabUpdateError:
        exception(
            "Couldn't update "
            + project.name
            + "'s (ID: "
            + str(project_id)
            + ") Push Rules configurations!"
        )

The above function is available on a Flask App that receives all Gitlab System Hooks and is triggered when a repository is created (the project_create event), alongside some other functions:

 if request_json["event_name"] == "project_create" and request_json[
        "path_with_namespace"
    ].startswith("infrastructure/"):
        set_project_configuration(gl, request_json["project_id"])
        remove_project_approval_rules(gl, request_json["project_id"])
        set_project_merge_request_approvals_configuration(
            gl, request_json["project_id"]
        )
        create_basic_directory_structure(gl, request_json["project_id"])
        set_project_master_branch_protected(gl, request_json["project_id"])
        set_project_push_rules_configuration(gl, request_json["project_id"])

Expected Behavior

This project_push_rules = project.pushrules.get(), should return a <ProjectPushRules> object.

Actual Behavior

When I try on an already created repository, the above code works. But from the system hook project_create event, the line that gets the repository Push Rules (project_push_rules = project.pushrules.get()) return None, which then leads to AttributeError: 'NoneType' object has no attribute 'prevent_secrets'.

Specifications

  • python-gitlab version: 2.5.0
  • API version you are using (v3/v4): v4
  • Gitlab server version (or gitlab.com): 13.3.5-ee

The project Pipfile:

[[source]]
url = "https://pypi.python.org/simple"
verify_ssl = true
name = "pypi"

[requires]
python_version = "3.8"

[packages]
python-gitlab = "==2.5.0"
requests = "*"
Flask = "==1.1.2"
uwsgi = "==2.0.19.1"
Jinja2 = "==2.11.2"
PyYAML = "==5.3.1"

[dev-packages]
pylint = "*"
pytest = "*"
coverage = "*"
black = "==20.8b1"

Activity

  1. nejch commented on Sep 17, 2020

    @nejch
    Member

    I personally have no way of testing this as it's an EE feature, but the fact that it's returning None only on project creation makes me think the webhook is fired before GitLab has fully configured the project (an asynchronous task, probably).

    Can you try to give a generous sleep() before pushrules.get() and see if that helps? If that works, then you can find more graceful ways of handling it.

  2. L30Bola commented on Sep 25, 2020

    @L30Bola
    Author

    Hmm, sorry for the delay on giving an answer. So, I was wrong on this working on recently-created repositories. I tried creating one and waiting for it to be "workable". Even with the sleep and I still got the error, Push Rules is returning None on repository creation.

  3. nejch commented on Sep 25, 2020

    @nejch
    Member

    Ah ok. Heh, then it's probably this:

    server_data = self.gitlab.http_get(self.path, **kwargs)
    if server_data is None:
    return None
    return self._obj_cls(self, server_data)

    I guess the response from a plain request with curl/requests is empty as well, rather than a 404 response like with some other get endpoints (I can't try myself)?

    It'd be good then to check the rest of the codebase for similar scenarios to see if this is actually the desired behavior for GetWithoutIdMixin since some other people might be using it this way, and simply create the resource when it does not exist. e.g.

    project_push_rules = project.pushrules.get()
    if not project_push_rules:
        project.pushrules.create(data)
  4. L30Bola commented on Sep 25, 2020

    @L30Bola
    Author

    YAY! I changed the original function to this:

    def set_project_push_rules_configuration(gitlab, project_id, **kwargs):
        """
        On kwargs you pass arguments that are mutable using the Gitlab Project's Push Rules API
        Documentation on that: https://docs.gitlab.com/ee/api/projects.html#push-rules
    
        Double check your kwargs because arguments not supported by the API
        (let's say a typo, for example) are simply ignored
        """
    
        defaults = {
            "prevent_secrets": True,
        }
        defaults.update(kwargs)
        project = gitlab.projects.get(project_id)
        project_push_rules = project.pushrules.get()
        if project_push_rules is None:
            try:
                project.pushrules.create(defaults)
            except GitlabCreateError:
                exception(
                    "Couldn't create "
                    + project.name
                    + "'s (ID: "
                    + str(project_id)
                    + ") Push Rules configurations!"
                )
        else:
            project_push_rules = set_attrs(project_push_rules, defaults)
            try:
                project_push_rules.save()
            except GitlabUpdateError:
                exception(
                    "Couldn't update "
                    + project.name
                    + "'s (ID: "
                    + str(project_id)
                    + ") Push Rules configurations!"
                )

    And now it works! Thanks for the help.

  5. locked as resolved and limited conversation to collaborators on Nov 7, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions