Commit 67a8149b authored by Simon Chabot's avatar Simon Chabot
Browse files

feat: add a command to includes in gitlab-ci.py

parent 033049ebacf7
Pipeline #65397 failed with stage
in 1 minute and 3 seconds
import yaml
from jinja2 import Environment
from cube_doctor import Command
jinja2_env = Environment(trim_blocks=True, lstrip_blocks=True)
GITLAB_CI_BASE_INCLUDES = """\
include:
- project: "open-source/gitlab-templates"
ref: "branch/default"
file:
- "templates/no-duplicate-pipelines.yml"
- "templates/release-on-heptapod.yml"
- "templates/publish-pypi.yml"
"""
GITLAB_CI_NEEDED_STAGES = """\
stages:
- tests
- release
- publish
"""
class AddIncludesInGitlabCI(Command):
BRANCH_NAME = "topic/default/includes-gitlab-ci"
TARGETS = ("cubes",)
commit_message = "ci(gitlab-ci): use templates from a common repository"
base_query = "?project lgg:has_gitlab_ci true ."
def pre_check(self, root_files):
if ".gitlab-ci.yml" not in root_files:
return "continue"
def modify_code(self, cube, repo, root_files, branches, other_args):
gitlab_ci_content = repo.read_file(".gitlab-ci.yml")
gitlab_ci_yaml = yaml.safe_load(gitlab_ci_content)
needed_stages = yaml.safe_load(GITLAB_CI_NEEDED_STAGES)["stages"]
if "include" in gitlab_ci_yaml:
return
result_lines = []
gitlab_ci_includes_has_been_added = False
update_stages = False
includes_at_the_beginning_of_the_file = not (
"default" in gitlab_ci_yaml or "image" in gitlab_ci_yaml
)
for line in gitlab_ci_content.split("\n"):
if not includes_at_the_beginning_of_the_file:
result_lines.append(line)
if (
not line.strip() and not gitlab_ci_includes_has_been_added
) or includes_at_the_beginning_of_the_file:
result_lines.append(GITLAB_CI_BASE_INCLUDES)
if "stages" not in gitlab_ci_yaml:
result_lines.append(GITLAB_CI_NEEDED_STAGES)
elif not set(gitlab_ci_yaml["stages"]).issuperset(set(needed_stages)):
update_stages = True
if includes_at_the_beginning_of_the_file:
result_lines.append(line)
gitlab_ci_includes_has_been_added = True
includes_at_the_beginning_of_the_file = False
result = "\n".join(result_lines)
if update_stages:
in_stage = False
stages_to_add = set(needed_stages) - set(gitlab_ci_yaml["stages"])
result_lines = []
for line in result.split("\n"):
if line.strip() == "stages:":
in_stage = True
result_lines.append(line)
continue
if in_stage and not line.strip():
for i in stages_to_add:
result_lines.append(f" - {i}")
result_lines.append(line)
in_stage = False
continue
result_lines.append(line)
result = "\n".join(result_lines)
repo.write_file(".gitlab-ci.yml", result)
yield {"branch_name": self.BRANCH_NAME, "commit_message": self.commit_message}
py3:
stage: tests
command:
- tox -e py3
default:
image: python
py3:
stage: tests
command:
- tox -e py3
stages:
- tests
- release
py3:
stage: tests
command:
- tox -e py3
default:
image: python
stages:
- tests
- release
- publish
py3:
stage: tests
command:
- tox -e py3
image: python
py3:
stage: tests
command:
- tox -e py3
stages:
- tests
- release
- publish
py3:
stage: tests
command:
- tox -e py3
default:
image: python
stages:
- tests
- release
- publish
py3:
stage: tests
command:
- tox -e py3
include:
- project: "open-source/gitlab-templates"
ref: "branch/default"
file:
- "templates/no-duplicate-pipelines.yml"
- "templates/release-on-heptapod.yml"
- "templates/publish-pypi.yml"
stages:
- tests
- release
- publish
py3:
stage: tests
command:
- tox -e py3
default:
image: python
include:
- project: "open-source/gitlab-templates"
ref: "branch/default"
file:
- "templates/no-duplicate-pipelines.yml"
- "templates/release-on-heptapod.yml"
- "templates/publish-pypi.yml"
stages:
- tests
- release
- publish
py3:
stage: tests
command:
- tox -e py3
include:
- project: "open-source/gitlab-templates"
ref: "branch/default"
file:
- "templates/no-duplicate-pipelines.yml"
- "templates/release-on-heptapod.yml"
- "templates/publish-pypi.yml"
stages:
- tests
- release
- publish
py3:
stage: tests
command:
- tox -e py3
default:
image: python
include:
- project: "open-source/gitlab-templates"
ref: "branch/default"
file:
- "templates/no-duplicate-pipelines.yml"
- "templates/release-on-heptapod.yml"
- "templates/publish-pypi.yml"
stages:
- tests
- release
- publish
py3:
stage: tests
command:
- tox -e py3
image: python
include:
- project: "open-source/gitlab-templates"
ref: "branch/default"
file:
- "templates/no-duplicate-pipelines.yml"
- "templates/release-on-heptapod.yml"
- "templates/publish-pypi.yml"
stages:
- tests
- release
- publish
py3:
stage: tests
command:
- tox -e py3
include:
- project: "open-source/gitlab-templates"
ref: "branch/default"
file:
- "templates/no-duplicate-pipelines.yml"
- "templates/release-on-heptapod.yml"
- "templates/publish-pypi.yml"
stages:
- tests
- release
- publish
py3:
stage: tests
command:
- tox -e py3
default:
image: python
include:
- project: "open-source/gitlab-templates"
ref: "branch/default"
file:
- "templates/no-duplicate-pipelines.yml"
- "templates/release-on-heptapod.yml"
- "templates/publish-pypi.yml"
stages:
- tests
- release
- publish
py3:
stage: tests
command:
- tox -e py3
import unittest
from cube_doctor.transforms.add_includes_in_gitlab_ci import AddIncludesInGitlabCI
from . import BaseCommandTC, TEST_DATA
class TransformAddIncludesInGitlabCITC(BaseCommandTC):
def test_add_includes_in_gitlab_ci(self):
data_input = TEST_DATA / "add_includes_in_gitlab_ci" / "in"
data_output = TEST_DATA / "add_includes_in_gitlab_ci" / "out"
self.base_execution(AddIncludesInGitlabCI(), data_input, data_output)
def test_add_includes_in_gitlab_ci_idempotent(self):
data_output = TEST_DATA / "add_includes_in_gitlab_ci" / "out"
self.base_execution(AddIncludesInGitlabCI(), data_output, data_output)
def test_add_includes_in_gitlab_ci_default(self):
data_input = TEST_DATA / "add_includes_in_gitlab_ci" / "in_default"
data_output = TEST_DATA / "add_includes_in_gitlab_ci" / "out_default"
self.base_execution(AddIncludesInGitlabCI(), data_input, data_output)
def test_add_includes_in_gitlab_ci_default_idempotent(self):
data_output = TEST_DATA / "add_includes_in_gitlab_ci" / "out_default"
self.base_execution(AddIncludesInGitlabCI(), data_output, data_output)
def test_add_includes_in_gitlab_ci_image(self):
data_input = TEST_DATA / "add_includes_in_gitlab_ci" / "in_image"
data_output = TEST_DATA / "add_includes_in_gitlab_ci" / "out_image"
self.base_execution(AddIncludesInGitlabCI(), data_input, data_output)
def test_add_includes_in_gitlab_ci_image_idempotent(self):
data_output = TEST_DATA / "add_includes_in_gitlab_ci" / "out_image"
self.base_execution(AddIncludesInGitlabCI(), data_output, data_output)
def test_add_includes_in_gitlab_ci_same_stages(self):
data_input = TEST_DATA / "add_includes_in_gitlab_ci" / "in_same_stages"
data_output = TEST_DATA / "add_includes_in_gitlab_ci" / "out_same_stages"
self.base_execution(AddIncludesInGitlabCI(), data_input, data_output)
def test_add_includes_in_gitlab_ci_same_stages_idempotent(self):
data_output = TEST_DATA / "add_includes_in_gitlab_ci" / "out_same_stages"
self.base_execution(AddIncludesInGitlabCI(), data_output, data_output)
def test_add_includes_in_gitlab_ci_same_stages_with_default(self):
data_input = (
TEST_DATA / "add_includes_in_gitlab_ci" / "in_same_stages_with_default"
)
data_output = (
TEST_DATA / "add_includes_in_gitlab_ci" / "out_same_stages_with_default"
)
self.base_execution(AddIncludesInGitlabCI(), data_input, data_output)
def test_add_includes_in_gitlab_ci_same_stages_with_default_idempotent(self):
data_output = (
TEST_DATA / "add_includes_in_gitlab_ci" / "out_same_stages_with_default"
)
self.base_execution(AddIncludesInGitlabCI(), data_output, data_output)
def test_add_includes_in_gitlab_ci_different_stages(self):
data_input = TEST_DATA / "add_includes_in_gitlab_ci" / "in_different_stages"
data_output = TEST_DATA / "add_includes_in_gitlab_ci" / "out_different_stages"
self.base_execution(AddIncludesInGitlabCI(), data_input, data_output)
def test_add_includes_in_gitlab_ci_different_stages_idempotent(self):
data_output = TEST_DATA / "add_includes_in_gitlab_ci" / "out_different_stages"
self.base_execution(AddIncludesInGitlabCI(), data_output, data_output)
def test_add_includes_in_gitlab_ci_different_stages_with_default(self):
data_input = (
TEST_DATA / "add_includes_in_gitlab_ci" / "in_different_stages_with_default"
)
data_output = (
TEST_DATA
/ "add_includes_in_gitlab_ci"
/ "out_different_stages_with_default"
)
self.base_execution(AddIncludesInGitlabCI(), data_input, data_output)
def test_add_includes_in_gitlab_ci_different_stages_with_default_idempotent(self):
data_output = (
TEST_DATA
/ "add_includes_in_gitlab_ci"
/ "out_different_stages_with_default"
)
self.base_execution(AddIncludesInGitlabCI(), data_output, data_output)
if __name__ == "__main__":
unittest.main()
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment