From d9bee53a003983496641698075abe954fe72f191 Mon Sep 17 00:00:00 2001 From: Martin Fencl Date: Wed, 13 Jul 2022 18:43:52 +0200 Subject: [PATCH] init --- .idea/.gitignore | 8 + .idea/inspectionProfiles/Project_Default.xml | 47 +++++ .../inspectionProfiles/profiles_settings.xml | 6 + .idea/misc.xml | 4 + .idea/modules.xml | 8 + .idea/skeleton-small_project.iml | 8 + .idea/vcs.xml | 6 + CHANGELOG.md | 0 MANIFEST.in | 1 + Makefile | 46 +++++ README.md | 16 ++ incoming_changes/.keep | 0 pyproject.toml | 6 + requirements.txt | 4 + scripts/__init__.py | 0 scripts/create_change_file.sh | 16 ++ scripts/release.py | 174 ++++++++++++++++++ scripts/start_pre_release_build.py | 47 +++++ setup.cfg | 20 ++ src/.keep | 0 tests/.keep | 0 tests/test_placeholder.py | 2 + 22 files changed, 419 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 .idea/inspectionProfiles/profiles_settings.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/skeleton-small_project.iml create mode 100644 .idea/vcs.xml create mode 100644 CHANGELOG.md create mode 100644 MANIFEST.in create mode 100644 Makefile create mode 100644 README.md create mode 100644 incoming_changes/.keep create mode 100644 pyproject.toml create mode 100644 requirements.txt create mode 100644 scripts/__init__.py create mode 100755 scripts/create_change_file.sh create mode 100755 scripts/release.py create mode 100755 scripts/start_pre_release_build.py create mode 100644 setup.cfg create mode 100644 src/.keep create mode 100644 tests/.keep create mode 100644 tests/test_placeholder.py diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..c0d2207 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,47 @@ + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..d56657a --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..56bf304 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/skeleton-small_project.iml b/.idea/skeleton-small_project.iml new file mode 100644 index 0000000..d0876a7 --- /dev/null +++ b/.idea/skeleton-small_project.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..e69de29 diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..74282fc --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1 @@ +include VERSION.txt diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..4abab48 --- /dev/null +++ b/Makefile @@ -0,0 +1,46 @@ +.PHONY: build build-pkg change_file clean dev mrproper namespace pep8 rebuild run static-checks test + +build: build-pkg + +build-pkg: + python3 -m pip install --upgrade build + python3 -m build + +change_file: + /bin/bash scripts/create_change_file.sh + +clean: + rm -fv **/*.pyc + rm -fv **/*.pyo + rm -rfv .pytest_cache + rm -rfv .coverage + rm -rfv dist + rm -rfv src/*.egg-info + rm -rfv __pycache__ + rm -rfv **/__pycache__ + +dev: + skaffold dev + +hosts: + echo "`minikube ip` CHANGEME.local" + +mrproper: clean + rm -f VERSION.txt + +namespace: + kubectl config set-context --current --namespace=CHANGEME-desktop-dev + +pep8: + flake8 src/ tests/ + +rebuild: + skaffold build -p rebuild + +run: + skaffold run --tail + +static-checks: pep8 + +test: + PYTHONPATH=src/ pytest -vv --cov-report term-missing --cov=src diff --git a/README.md b/README.md new file mode 100644 index 0000000..838ef4d --- /dev/null +++ b/README.md @@ -0,0 +1,16 @@ +# skeleton-small_project + +Template for "small" project + +* Export it and import as your new project. +* Change `small_project` to your project name. + +Make sure `CISCRIPT_API_TOKEN` is available in CI/CD variables. + +If a python package is not needed, you can get rid of: +* `MANIFEST.in` +* `pyproject.toml` +* `setup.cfg` +* `Makefile`: `build-pkg` + +Fill your project name in `CHANGEME` placeholder in `Makefile`. diff --git a/incoming_changes/.keep b/incoming_changes/.keep new file mode 100644 index 0000000..e69de29 diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..374b58c --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,6 @@ +[build-system] +requires = [ + "setuptools>=42", + "wheel" +] +build-backend = "setuptools.build_meta" diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..7be3987 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +# tests +flake8 +pytest +pytest-cov diff --git a/scripts/__init__.py b/scripts/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/scripts/create_change_file.sh b/scripts/create_change_file.sh new file mode 100755 index 0000000..9b3f76f --- /dev/null +++ b/scripts/create_change_file.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +BRANCH=`git rev-parse --abbrev-ref HEAD` +if [ "x${BRANCH}" != "x" ] && [ "${BRANCH}" != "HEAD" ] +then + FILE="incoming_changes/${BRANCH}.md" + if [ -e $FILE ] + then + echo "file '${FILE}' already exists" + else + touch "${FILE}" + echo "file '${FILE}' created" + fi +else + echo "branch name '${BRANCH}' is not valid" +fi diff --git a/scripts/release.py b/scripts/release.py new file mode 100755 index 0000000..111a326 --- /dev/null +++ b/scripts/release.py @@ -0,0 +1,174 @@ +#!/usr/bin/env python3 + +import datetime +import glob +import os +import re +import sys + +import requests +import semver + + +def release(): + major_version = 4 + + gitlab_project_id = os.environ["CI_PROJECT_ID"] + api_token = os.environ["CISCRIPT_API_TOKEN"] + minor_version = os.environ["MINOR_VERSION"] + if minor_version == "minor": + minor_version = None + else: + try: + minor_version = int(minor_version) + except ValueError: + sys.exit(f"minor version must be number but is '{minor_version}'") + patch_version = os.environ["PATCH_VERSION"] + if patch_version == "patch": + patch_version = None + else: + try: + patch_version = int(patch_version) + except ValueError: + sys.exit(f"patch version must be number but is '{patch_version}'") + + branch = os.environ["CI_COMMIT_BRANCH"] + print(f"branch '{branch}'") + if branch == "master": + if minor_version is None: + sys.exit("minor version must be set") + if patch_version is None: + patch_version = 0 + future_version = f"{major_version}.{minor_version}.{patch_version}" + response = requests.get( + ( + f"https://gitlab.princip.cz/" + f"api/v4/projects/{gitlab_project_id}/repository/tags" + ), + headers={"PRIVATE-TOKEN": api_token}, + params={"search": "^v"}, + ) + for tag_dict in response.json(): + tag_name = tag_dict["name"] + if (re.match(r"^v\d+\.\d+\.\d+$", tag_name) + and semver.compare(future_version, tag_name[1:]) < 1): + sys.exit( + f"existing version '{tag_name[1:]}' " + f"is greater than or equal to future version " + f"'{future_version}'" + ) + elif match := re.match(r"^stable-(\d+)\.(\d+)$", branch): + if patch_version is None: + sys.exit("patch version must be set") + major_version = int(match.group(1)) + branch_minor_version = int(match.group(2)) + if minor_version is None: + minor_version = branch_minor_version + elif minor_version != branch_minor_version: + sys.exit( + f"minor version on branch '{branch}' " + f"must be '{branch_minor_version}' or blank (default)" + ) + future_version = f"{major_version}.{minor_version}.{patch_version}" + response = requests.get( + ( + f"https://gitlab.princip.cz/" + f"api/v4/projects/{gitlab_project_id}/repository/tags" + ), + headers={"PRIVATE-TOKEN": api_token}, + params={"search": f"^v{major_version}.{minor_version}"}, + ) + for tag_dict in response.json(): + tag_name = tag_dict["name"] + if semver.compare(future_version, tag_name[1:]) < 1: + sys.exit( + f"existing version '{tag_name[1:]}' " + f"is greater than or equal to future version " + f"'{future_version}'" + ) + else: + sys.exit(f"release on branch '{branch}' is forbidden") + print(f"future version '{future_version}'") + future_tag_name = f"v{future_version}" + print(f"future tag name '{future_tag_name}'") + + response = requests.get( + ( + f"https://gitlab.princip.cz/" + f"api/v4/projects/{gitlab_project_id}/repository/tags" + f"/{future_tag_name}" + ), + headers={"PRIVATE-TOKEN": api_token}, + ) + if response.status_code != 404: + sys.exit(f"tag '{future_tag_name}' already exists") + + commit_message = f"update files for {future_version}" + payload_dict = { + "branch": branch, "commit_message": commit_message, "actions": []} + today_date = datetime.datetime.today().strftime("%Y-%m-%d") + release_description = f"## {future_version} ({today_date})\n" + change_file_fps = glob.glob(os.path.join("incoming_changes", "*.md")) + if not change_file_fps: + sys.exit("no change file") + for change_file_fp in change_file_fps: + change_file_fn = os.path.basename(change_file_fp) + match = re.match(r"^(\d+)-\S+.md$", change_file_fn) + if match: + issue_no = match.group(1) + else: + issue_no = None + with open(change_file_fp, "r") as change_file: + for line in change_file: + line = line.strip() + if issue_no: + line += f" #{issue_no}" + release_description += f"{line}\n" + payload_dict["actions"].append( + {"action": "delete", "file_path": change_file_fp}) + with open("CHANGELOG.md", "r+") as changelog_file: + content = changelog_file.read() + new_changelog_content = f"{release_description}\n\n{content}" + payload_dict["actions"].append({ + "action": "update", + "file_path": "CHANGELOG.md", + "content": new_changelog_content, + }) + print("CHANGELOG.md updated") + + response = requests.post( + ( + f"https://gitlab.princip.cz/" + f"api/v4/projects/{gitlab_project_id}/repository/commits" + ), + headers={"PRIVATE-TOKEN": api_token}, + json=payload_dict, + ) + if response.status_code == 201: + print(f"commit '{commit_message}' created") + else: + sys.exit( + f"error creating commit '{commit_message}', " + f"status code '{response.status_code}', json '{response.json()}'" + ) + + response = requests.post( + ( + f"https://gitlab.princip.cz/" + f"api/v4/projects/{gitlab_project_id}/repository/tags" + ), + headers={"PRIVATE-TOKEN": api_token}, + params={"tag_name": future_tag_name, "ref": branch}, + ) + if response.status_code == 201: + print(f"tag '{future_tag_name}' created") + else: + sys.exit( + f"error creating tag '{future_tag_name}', " + f"status code '{response.status_code}', " + f"json '{response.json()}'" + ) + + +if __name__ == "__main__": + release() diff --git a/scripts/start_pre_release_build.py b/scripts/start_pre_release_build.py new file mode 100755 index 0000000..fbe47bf --- /dev/null +++ b/scripts/start_pre_release_build.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 + +import os +import sys + +import requests +import semver + + +def start_pre_release_build(): + gitlab_project_id = os.environ["CI_PROJECT_ID"] + api_token = os.environ["CISCRIPT_API_TOKEN"] + branch = os.environ["CI_COMMIT_BRANCH"] + print(f"branch '{branch}'") + major_version = minor_version = 0 + patch_version = int(os.environ["CI_PIPELINE_ID"]) + commit_short_sha = os.environ["CI_COMMIT_SHORT_SHA"] + future_version = str( + semver.VersionInfo( + major=major_version, + minor=minor_version, + patch=patch_version, + prerelease="beta", + build=commit_short_sha, + ) + ) + future_tag_name = f"v{future_version}" + print(f"future tag name '{future_tag_name}'") + response = requests.post( + ( + f"https://gitlab.princip.cz/" + f"api/v4/projects/{gitlab_project_id}/repository/tags" + ), + headers={"PRIVATE-TOKEN": api_token}, + params={"tag_name": future_tag_name, "ref": branch}, + ) + if response.status_code == 201: + print(f"tag '{future_tag_name}' created") + else: + sys.exit( + f"error creating tag '{future_tag_name}', " + f"status code '{response.status_code}', json '{response.json()}'" + ) + + +if __name__ == "__main__": + start_pre_release_build() diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..275ee6d --- /dev/null +++ b/setup.cfg @@ -0,0 +1,20 @@ +[metadata] +name = small_project +version = file: VERSION.txt +author = Princip a. s. +author_email = lab-sw@eurowag.com +description = TBD +long_description = file: README.md +long_description_content_type = text/markdown +url = https://gitlab.princip.cz/lab/sw/small_project +classifiers = + Programming Language :: Python :: 3 + +[options] +package_dir = + = src +packages = find: +python_requires = >=3.9 + +[options.packages.find] +where = src diff --git a/src/.keep b/src/.keep new file mode 100644 index 0000000..e69de29 diff --git a/tests/.keep b/tests/.keep new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_placeholder.py b/tests/test_placeholder.py new file mode 100644 index 0000000..ead2122 --- /dev/null +++ b/tests/test_placeholder.py @@ -0,0 +1,2 @@ +def test_placeholder(): + "Replace me with the real deal..."