Commit a518bbf8 authored by Pierre Smeyers's avatar Pierre Smeyers
Browse files

initial

parents
Loading
Loading
Loading
Loading

.gitignore

0 → 100644
+142 −0
Original line number Diff line number Diff line
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
#  Usually these files are written by a python script from a template
#  before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
.python-version

# pipenv
#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
#   However, in case of collaboration, if having platform-specific dependencies or dependencies
#   having no cross-platform support, pipenv may install dependencies that don’t work, or not
#   install all needed dependencies.
#Pipfile.lock

# celery beat schedule file
celerybeat-schedule

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# Azure Functions artifacts
bin
obj
appsettings.json
local.settings.json

# Azurite artifacts
__blobstorage__
__queuestorage__
__azurite_db*__.json
.python_packages
.azure

.devcontainer/
.vscode/
reports/
.github/
body.json

README.md

0 → 100644
+20 −0
Original line number Diff line number Diff line
# to-be-continuous utils

Various to-be-continuous internal utility tools.

## template-to-component

This program helps migrating to-be-continuous legacy templates (include:project) to GitLab CI/CD components (include:component).

Usage:

```bash
# install dependencies
poetry install

# obtain help
poetry run t2c --help

# run tool
poetry run t2c path/to/tbc/template
```

poetry.lock

0 → 100644
+0 −0

File added.

Preview size limit exceeded, changes collapsed.

pyproject.toml

0 → 100644
+74 −0
Original line number Diff line number Diff line
[tool.poetry]
name = "tbc-utils"
version = "0.1.0"
description = "TBC internal utility tools"
authors = ["Pierre Smeyers <pierre.smeyers@gmail.com>"]
license = "LGPL"
readme = "README.md"
packages = [{include = "tbc", from = "src"}]

[tool.poetry.dependencies]
python = "^3.9"
pyyaml = "^6.0.1"

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

[tool.poetry.scripts]
t2c = "tbc.template-to-component:migrate"

[tool.poetry.group.dev.dependencies]
# new development dependencies can be added with 'poetry add -D yyy'
pytest = "^7.0.0"
pytest-cov = "^4.0.0"
pytest-env = "^0.8.0"
black = "^21.12b0"
mypy = "^1.0.0"
pylint = "^2.17.5"

[tool.pytest.ini_options]
# this project uses "pytest" for unit testing
# see: https://docs.pytest.org/en/6.2.x/customize.html#pyproject-toml
testpaths = [
    "tests",
]

[tool.black]
# this project uses "Black" as code formatter
# see: https://black.readthedocs.io/en/stable/usage_and_configuration/the_basics.html#usage
line-length = 88
target-version = ['py310']
include = '\.pyi?$'

[tool.mypy]
# this project uses "mypy" as a static type checker
# see: https://mypy.readthedocs.io/en/stable/config_file.html
python_version = 3.10
warn_return_any = true
warn_unused_configs = true
disallow_untyped_defs = true

[[tool.mypy.overrides]]
# loosen rules for tests
module = "tests.*"
warn_return_any = false
disallow_untyped_defs = false

[tool.pylint.messages_control]
max-line-length = 88
disable = [
  "missing-docstring",
#   "unused-argument",
#   "no-value-for-parameter",
#   "no-member",
#   "no-else-return",
#   "bad-whitespace",
#   "bad-continuation",
#   "line-too-long",
#   "fixme",
#   "protected-access",
   "too-few-public-methods",
#   "unspecified-encoding",
#   "redefined-outer-name"
]
+83 −0
Original line number Diff line number Diff line
import argparse
import json

import yaml


def _migrate_var(var: dict[str, any], var_prefix):
    #   "name": "DOCKER_BUILD_TOOL",
    #   "type": "enum",
    #   "values": ["kaniko", "buildah", "dind"],
    #   "description": "The build tool to use for building container image",
    #   "default": "kaniko", 
    #   advanced
    #   mandatory
    #   secret
        is_secret = var.get("secret", False)
        if is_secret:
            # skip secrets
            return
        is_mandatory = var.get("mandatory", False)
        var_name: str = var["name"]
        var_type: str = var.get("type", "text")
        var_default: str = var.get("default")
        input_name = (var_name[len(var_prefix):] if var_name.startswith(var_prefix) else var_name).lower()
        print(f"{input_name}:")
        print(f"  description: {var.get('description', 'n/a')}")
        print(f"  type: {var_type if var_type in ['number', 'boolean'] else 'string'}")
        if var_type == "enum":
            print(f"  options: {var.get('values', [])}")
        if not is_mandatory or var_default:
            # declare default
            if var_default:
                print(f"  default: '{var_default}'")
            elif var_type == "boolean":
                print("  default: false")
            else:
                print("  default: null")

def _migrate(tpl_desc, project_dir: str, var_prefix: str):
    print(f"migrate {tpl_desc['template_path']}")

    # with open(f"{project_dir}/{tpl_desc['template_path']}", "r") as tpl_file:
    #     tpl = yaml.load(tpl_file, yaml.UnsafeLoader)

    for var in tpl_desc.get("variables", []):
        _migrate_var(var, var_prefix)

    for feat in tpl_desc.get("features", []):
       if feat.get("enable_with"):
           _migrate_var({
               "name": feat.get("enable_with"),
               "description": f"Enable {feat['name']}",
               "type": "boolean",
           }, var_prefix)
       elif feat.get("disable_with"):
           _migrate_var({
               "name": feat.get("disable_with"),
               "description": f"Disable {feat['name']}",
               "type": "boolean",
           }, var_prefix)
       for var in feat.get("variables", []):
            _migrate_var(var, var_prefix)


def migrate():
    parser = argparse.ArgumentParser(
                    prog='template-to-component',
                    description='This tool migrates a legacy TBC template to a new GitLab CI/CD component')
    parser.add_argument('project_dir')
    parser.add_argument('--var-prefix')

    args = parser.parse_args()
    
    with open(f"{args.project_dir}/kicker.json", "r") as kicker_file:
        kicker = json.load(kicker_file)
    
    var_prefix = (args.var_prefix or kicker["name"].upper()) + "_"
    # print(f"kicker: {kicker}")
    _migrate(kicker, args.project_dir, var_prefix)
    
    for variant in kicker.get("variants"):
        _migrate(variant, args.project_dir, var_prefix)