ci: migrate from setuptools to PEP517 hatchling to build
This commit is contained in:
parent
b32de905a4
commit
42d4a62679
@ -1,6 +1,6 @@
|
|||||||
ARG RUNTIME_VERSION="3.8"
|
ARG RUNTIME_VERSION="3.9"
|
||||||
ARG DISTRO_VERSION="3.15"
|
ARG DISTRO_VERSION="3.16"
|
||||||
ARG PULUMI_VERSION="3.35.0"
|
ARG PULUMI_VERSION="3.35.1"
|
||||||
|
|
||||||
FROM python:${RUNTIME_VERSION}-alpine${DISTRO_VERSION} AS builder
|
FROM python:${RUNTIME_VERSION}-alpine${DISTRO_VERSION} AS builder
|
||||||
ARG PULUMI_VERSION
|
ARG PULUMI_VERSION
|
||||||
|
7
Makefile
7
Makefile
@ -14,10 +14,7 @@ endif
|
|||||||
|
|
||||||
.PHONY: pytest build test_upload upload all dev_setup pybuild
|
.PHONY: pytest build test_upload upload all dev_setup pybuild
|
||||||
|
|
||||||
all: pybuild pytest
|
all: pytest pybuild
|
||||||
|
|
||||||
dev_setup:
|
|
||||||
pip install -U -r dev-requirements.txt --user
|
|
||||||
|
|
||||||
pytest:
|
pytest:
|
||||||
flake8 cloudbender tests
|
flake8 cloudbender tests
|
||||||
@ -27,7 +24,7 @@ clean:
|
|||||||
rm -rf .cache build .coverage .eggs cloudbender.egg-info .pytest_cache dist
|
rm -rf .cache build .coverage .eggs cloudbender.egg-info .pytest_cache dist
|
||||||
|
|
||||||
pybuild:
|
pybuild:
|
||||||
python setup.py bdist_wheel --universal
|
hatchling build
|
||||||
|
|
||||||
test_upload: $(PACKAGE_FILE)
|
test_upload: $(PACKAGE_FILE)
|
||||||
twine upload --repository-url https://test.pypi.org/legacy/ dist/cloudbender-*.whl
|
twine upload --repository-url https://test.pypi.org/legacy/ dist/cloudbender-*.whl
|
||||||
|
@ -7,18 +7,15 @@ import yaml
|
|||||||
import copy
|
import copy
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
import zlib
|
||||||
|
|
||||||
import jinja2
|
import jinja2
|
||||||
|
import python_minifier
|
||||||
import markupsafe
|
import markupsafe
|
||||||
|
|
||||||
from jinja2.filters import make_attrgetter
|
from jinja2.filters import make_attrgetter
|
||||||
from jinja2.runtime import Undefined
|
from jinja2.runtime import Undefined
|
||||||
|
|
||||||
import pyminifier.token_utils
|
|
||||||
import pyminifier.minification
|
|
||||||
import pyminifier.compression
|
|
||||||
import pyminifier.obfuscate
|
|
||||||
import types
|
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@ -129,40 +126,41 @@ def sub(value="", pattern="", replace="", ignorecase=False):
|
|||||||
return re.sub(pattern, replace, value, flags=flags)
|
return re.sub(pattern, replace, value, flags=flags)
|
||||||
|
|
||||||
|
|
||||||
def pyminify(source, obfuscate=False, minify=True):
|
def pyminify(source):
|
||||||
# pyminifier options
|
minified = python_minifier.awslambda(source, filename=None, entrypoint=None)
|
||||||
options = types.SimpleNamespace(
|
gz_source = gz_pack(minified)
|
||||||
tabs=False,
|
|
||||||
replacement_length=1,
|
|
||||||
use_nonlatin=0,
|
|
||||||
obfuscate=0,
|
|
||||||
obf_variables=1,
|
|
||||||
obf_classes=0,
|
|
||||||
obf_functions=0,
|
|
||||||
obf_import_methods=0,
|
|
||||||
obf_builtins=0,
|
|
||||||
)
|
|
||||||
|
|
||||||
tokens = pyminifier.token_utils.listified_tokenizer(source)
|
|
||||||
|
|
||||||
if minify:
|
|
||||||
source = pyminifier.minification.minify(tokens, options)
|
|
||||||
tokens = pyminifier.token_utils.listified_tokenizer(source)
|
|
||||||
|
|
||||||
if obfuscate:
|
|
||||||
name_generator = pyminifier.obfuscate.obfuscation_machine(use_unicode=False)
|
|
||||||
pyminifier.obfuscate.obfuscate(
|
|
||||||
"__main__", tokens, options, name_generator=name_generator
|
|
||||||
)
|
|
||||||
# source = pyminifier.obfuscate.apply_obfuscation(source)
|
|
||||||
|
|
||||||
source = pyminifier.token_utils.untokenize(tokens)
|
|
||||||
# logger.info(source)
|
|
||||||
minified_source = pyminifier.compression.gz_pack(source)
|
|
||||||
logger.info(
|
logger.info(
|
||||||
"Compressed python code from {} to {}".format(len(source), len(minified_source))
|
"Compressed python code from {} to {}".format(len(source), len(gz_source))
|
||||||
)
|
)
|
||||||
return minified_source
|
return gz_source
|
||||||
|
|
||||||
|
|
||||||
|
# From pyminifier
|
||||||
|
def gz_pack(source):
|
||||||
|
"""
|
||||||
|
Returns 'source' as a gzip-compressed, self-extracting python script.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
This method uses up more space than the zip_pack method but it has the
|
||||||
|
advantage in that the resulting .py file can still be imported into a
|
||||||
|
python program.
|
||||||
|
"""
|
||||||
|
out = ""
|
||||||
|
# Preserve shebangs (don't care about encodings for this)
|
||||||
|
first_line = source.split("\n")[0]
|
||||||
|
if re.compile('^#!.*$').match(first_line):
|
||||||
|
if first_line.rstrip().endswith("python"):
|
||||||
|
first_line = first_line.rstrip()
|
||||||
|
first_line += "3"
|
||||||
|
out = first_line + "\n"
|
||||||
|
compressed_source = zlib.compress(source.encode("utf-8"))
|
||||||
|
out += "import zlib, base64\n"
|
||||||
|
out += "exec(zlib.decompress(base64.b64decode('"
|
||||||
|
out += base64.b64encode(compressed_source).decode("utf-8")
|
||||||
|
out += "')))\n"
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
def inline_yaml(block):
|
def inline_yaml(block):
|
||||||
|
@ -7,7 +7,7 @@ import time
|
|||||||
import pathlib
|
import pathlib
|
||||||
import pprint
|
import pprint
|
||||||
import pulumi
|
import pulumi
|
||||||
import pkg_resources
|
import importlib.resources as pkg_resources
|
||||||
|
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from dateutil.tz import tzutc
|
from dateutil.tz import tzutc
|
||||||
@ -518,12 +518,8 @@ class Stack(object):
|
|||||||
|
|
||||||
if self.outputs:
|
if self.outputs:
|
||||||
if self.store_outputs:
|
if self.store_outputs:
|
||||||
try:
|
filename = self.stackname + ".yaml"
|
||||||
filename = self.cfn_data["Metadata"]["CustomOutputs"]["Name"]
|
my_template = pkg_resources.read_text(templates, "outputs.yaml")
|
||||||
my_template = self.cfn_data["Metadata"]["CustomOutputs"]["Template"]
|
|
||||||
except (TypeError, KeyError):
|
|
||||||
filename = self.stackname + ".yaml"
|
|
||||||
my_template = pkg_resources.read_text(templates, "outputs.yaml")
|
|
||||||
|
|
||||||
output_file = os.path.join(
|
output_file = os.path.join(
|
||||||
self.ctx["outputs_path"], self.rel_path, filename
|
self.ctx["outputs_path"], self.rel_path, filename
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
boto3
|
|
||||||
Jinja2
|
|
||||||
click
|
|
||||||
pyminifier
|
|
||||||
cfn-lint>=0.34
|
|
||||||
pulumi
|
|
||||||
pulumi-aws
|
|
||||||
pulumi-aws-native
|
|
45
pyproject.toml
Normal file
45
pyproject.toml
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
[build-system]
|
||||||
|
requires = ["hatchling", "hatch-vcs"]
|
||||||
|
build-backend = "hatchling.build"
|
||||||
|
|
||||||
|
[project]
|
||||||
|
name = "cloudbender"
|
||||||
|
dynamic = ["version"]
|
||||||
|
authors = [
|
||||||
|
{ name="Stefan Reimer", email="stefan@zero-downtime.net" },
|
||||||
|
]
|
||||||
|
description = "Toolset to render and manage AWS Cloudformation"
|
||||||
|
readme = "README.md"
|
||||||
|
license = { file="LICENSE.md" }
|
||||||
|
requires-python = ">=3.7"
|
||||||
|
dependencies = [
|
||||||
|
"boto3",
|
||||||
|
"mock",
|
||||||
|
"Jinja2>=3.0.0",
|
||||||
|
"click",
|
||||||
|
"cfn-lint>=0.34",
|
||||||
|
"python-minifier",
|
||||||
|
"pulumi>=3.35.0",
|
||||||
|
"pulumi-aws>5.0.0",
|
||||||
|
"pulumi-aws-native",
|
||||||
|
"pulumi-policy",
|
||||||
|
]
|
||||||
|
classifiers = [
|
||||||
|
"Development Status :: 4 - Beta",
|
||||||
|
"Environment :: Console",
|
||||||
|
"Operating System :: POSIX",
|
||||||
|
"Programming Language :: Python",
|
||||||
|
"License :: OSI Approved :: GNU Affero General Public License v3",
|
||||||
|
]
|
||||||
|
|
||||||
|
[project.urls]
|
||||||
|
"Homepage" = "https://git.zero-downtime.net/ZeroDownTime/CloudBender"
|
||||||
|
|
||||||
|
[project.scripts]
|
||||||
|
cloudbender = "cloudbender.cli:cli"
|
||||||
|
|
||||||
|
[tool.hatch.version]
|
||||||
|
source = "vcs"
|
||||||
|
|
||||||
|
[tool.isort]
|
||||||
|
profile = "black"
|
@ -2,13 +2,12 @@ boto3
|
|||||||
mock
|
mock
|
||||||
Jinja2>=3.0.0
|
Jinja2>=3.0.0
|
||||||
click
|
click
|
||||||
pyminifier
|
python-minifier
|
||||||
cfn-lint>=0.34
|
cfn-lint>=0.34
|
||||||
pulumi>=3.35.0
|
pulumi>=3.35.0
|
||||||
pulumi-aws>5.0.0
|
pulumi-aws>5.0.0
|
||||||
pulumi-aws-native
|
pulumi-aws-native
|
||||||
pulumi-policy
|
pulumi-policy
|
||||||
# apprise
|
|
||||||
|
|
||||||
# flake8
|
# flake8
|
||||||
# pytest
|
# pytest
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
[metadata]
|
|
||||||
description_file = README.md
|
|
||||||
|
|
||||||
[bdist_wheel]
|
|
||||||
universal=1
|
|
62
setup.py
62
setup.py
@ -1,62 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
import io
|
|
||||||
import os
|
|
||||||
import re
|
|
||||||
from setuptools import setup
|
|
||||||
from setuptools import find_packages
|
|
||||||
from setuptools.command.test import test as TestCommand
|
|
||||||
|
|
||||||
class PyTest(TestCommand):
|
|
||||||
"""TestCommand subclass to use pytest with setup.py test."""
|
|
||||||
|
|
||||||
def finalize_options(self):
|
|
||||||
"""Find our package name and test options to fill out test_args."""
|
|
||||||
|
|
||||||
TestCommand.finalize_options(self)
|
|
||||||
self.test_args = ['-rx', '--cov', 'cloudbender',
|
|
||||||
'--cov-report', 'term-missing']
|
|
||||||
self.test_suite = True
|
|
||||||
|
|
||||||
def run_tests(self):
|
|
||||||
"""Taken from http://pytest.org/latest/goodpractises.html."""
|
|
||||||
|
|
||||||
# have to import here, outside the eggs aren't loaded
|
|
||||||
import pytest
|
|
||||||
errno = pytest.main(self.test_args)
|
|
||||||
raise SystemExit(errno)
|
|
||||||
|
|
||||||
|
|
||||||
if os.path.isfile("README.md"):
|
|
||||||
with io.open("README.md", encoding="utf-8") as opendescr:
|
|
||||||
long_description = opendescr.read()
|
|
||||||
else:
|
|
||||||
long_description = __doc__
|
|
||||||
|
|
||||||
setup(
|
|
||||||
name='cloudbender',
|
|
||||||
setuptools_git_versioning={
|
|
||||||
"enabled": True,
|
|
||||||
"dev_template": "{tag}-{ccount}",
|
|
||||||
},
|
|
||||||
setup_requires=["setuptools-git-versioning"],
|
|
||||||
description='Toolset to render and manage AWS Cloudformation',
|
|
||||||
python_requires='>=3.8',
|
|
||||||
long_description=long_description,
|
|
||||||
long_description_content_type="text/markdown",
|
|
||||||
author='Stefan Reimer',
|
|
||||||
author_email='stefan@zero-downtime.net',
|
|
||||||
url='https://git.zero-downtime.net/ZeroDownTime/CloudBender',
|
|
||||||
packages=find_packages(),
|
|
||||||
package_data={ 'cloudbender': ['templates/*.md', 'templates/*.yaml'], },
|
|
||||||
include_package_data=True,
|
|
||||||
entry_points={'console_scripts': [ "cloudbender = cloudbender.cli:cli" ]},
|
|
||||||
install_requires=['boto3', 'Jinja2>=3.0.0', 'click', 'cfn-lint>=0.34', 'pyminifier', 'pulumi', 'pulumi-aws'], #'apprise'
|
|
||||||
tests_require=["pytest-cov", "moto", "mock", 'pytest'],
|
|
||||||
cmdclass={"test": PyTest},
|
|
||||||
classifiers=[
|
|
||||||
"Development Status :: 4 - Beta",
|
|
||||||
"Environment :: Console",
|
|
||||||
"Operating System :: POSIX",
|
|
||||||
"Programming Language :: Python",
|
|
||||||
"License :: OSI Approved :: GNU Affero General Public License v3"
|
|
||||||
])
|
|
Loading…
Reference in New Issue
Block a user