Skip to content

Commit

Permalink
Merge pull request #1896 from python-gitlab/jlvillal/ci_lint
Browse files Browse the repository at this point in the history
feat: add Project CI Lint support
  • Loading branch information
nejch committed Jul 5, 2022
2 parents 88a1535 + b213dd3 commit d15fea0
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 0 deletions.
43 changes: 43 additions & 0 deletions docs/gl_objects/projects.rst
Expand Up @@ -819,6 +819,49 @@ Get total fetches in last 30 days of a project::

total_fetches = project.additionalstatistics.get().fetches['total']

Project CI Lint
=============================

Reference
---------

* v4 API:

+ :class:`gitlab.v4.objects.ProjectCiLint`
+ :class:`gitlab.v4.objects.ProjectCiLintManager`
+ :attr:`gitlab.v4.objects.Project.ci_lint`

* GitLab API: https://docs.gitlab.com/ee/api/lint.html

Examples
---------

Validate a project's CI configuration::

lint_result = project.ci_lint.get()
assert lint_result.valid is True # Test that the .gitlab-ci.yml is valid
print(lint_result.merged_yaml) # Print the merged YAML file

Validate a CI YAML configuration with a namespace::

gitlab_ci_yml = """.api_test:
rules:
- if: $CI_PIPELINE_SOURCE=="merge_request_event"
changes:
- src/api/*
deploy:
extends:
- .api_test
rules:
- when: manual
allow_failure: true
script:
- echo "hello world"
"""
lint_result = project.ci_lint.create({"content": gitlab_ci_yml})
assert lint_result.valid is True # Test that the .gitlab-ci.yml is valid
print(lint_result.merged_yaml) # Print the merged YAML file

Project storage
=============================

Expand Down
23 changes: 23 additions & 0 deletions gitlab/v4/objects/projects.py
@@ -1,3 +1,8 @@
"""
GitLab API:
https://docs.gitlab.com/ee/api/projects.html
https://docs.gitlab.com/ee/api/lint.html
"""
from typing import (
Any,
Callable,
Expand Down Expand Up @@ -97,6 +102,8 @@
"ProjectRemoteMirrorManager",
"ProjectStorage",
"ProjectStorageManager",
"ProjectCiLint",
"ProjectCiLintManager",
]


Expand Down Expand Up @@ -158,6 +165,7 @@ class Project(RefreshMixin, SaveMixin, ObjectDeleteMixin, RepositoryMixin, RESTO
badges: ProjectBadgeManager
boards: ProjectBoardManager
branches: ProjectBranchManager
ci_lint: "ProjectCiLintManager"
clusters: ProjectClusterManager
commits: ProjectCommitManager
customattributes: ProjectCustomAttributeManager
Expand Down Expand Up @@ -1055,3 +1063,18 @@ class ProjectStorageManager(GetWithoutIdMixin, RESTManager):

def get(self, **kwargs: Any) -> ProjectStorage:
return cast(ProjectStorage, super().get(**kwargs))


class ProjectCiLint(RESTObject):
pass


class ProjectCiLintManager(GetWithoutIdMixin, CreateMixin, RESTManager):
"""GitLab API: https://docs.gitlab.com/ee/api/lint.html"""

_path = "/projects/{project_id}/ci/lint"
_obj_cls = ProjectCiLint
_from_parent_attrs = {"project_id": "id"}

def get(self, **kwargs: Any) -> ProjectCiLint:
return cast(ProjectCiLint, super().get(**kwargs))
46 changes: 46 additions & 0 deletions tests/unit/objects/test_projects.py
Expand Up @@ -82,6 +82,12 @@
"status": "created",
"source": "trigger",
}
ci_lint_get_content = {
"valid": True,
"merged_yaml": "---\n:test_job:\n :script: echo 1\n",
"errors": [],
"warnings": [],
}


@pytest.fixture
Expand Down Expand Up @@ -541,6 +547,32 @@ def resp_artifact():
yield rsps


@pytest.fixture
def resp_get_ci_lint():
with responses.RequestsMock() as rsps:
rsps.add(
method=responses.GET,
url="http://localhost/api/v4/projects/1/ci/lint",
json=ci_lint_get_content,
content_type="application/json",
status=200,
)
yield rsps


@pytest.fixture
def resp_create_ci_lint():
with responses.RequestsMock() as rsps:
rsps.add(
method=responses.POST,
url="http://localhost/api/v4/projects/1/ci/lint",
json=ci_lint_get_content,
content_type="application/json",
status=200,
)
yield rsps


def test_get_project(gl, resp_get_project):
data = gl.projects.get(1)
assert isinstance(data, Project)
Expand Down Expand Up @@ -756,3 +788,17 @@ def test_project_pull_mirror(project, resp_start_pull_mirroring_project):
def test_project_snapshot(project, resp_snapshot_project):
tar_file = project.snapshot()
assert isinstance(tar_file, bytes)


def test_project_ci_lint_get(project, resp_get_ci_lint):
lint_result = project.ci_lint.get()
assert lint_result.valid is True


def test_project_ci_lint_create(project, resp_create_ci_lint):
gitlab_ci_yml = """---
:test_job:
:script: echo 1
"""
lint_result = project.ci_lint.create({"content": gitlab_ci_yml})
assert lint_result.valid is True

0 comments on commit d15fea0

Please sign in to comment.