From 79aa2ddd6c200b653d43340e560f836826c198f6 Mon Sep 17 00:00:00 2001 From: Russell Ballestrini Date: Sun, 2 Mar 2025 08:36:51 -0500 Subject: [PATCH 1/2] pypi release prep! modified: .gitlab-ci.yml modified: Makefile modified: README.rst modified: setup.py --- .gitlab-ci.yml | 35 ++++++++---- Makefile | 149 ++++++++++++++++++++++++++++++++++++++++--------- README.rst | 53 +++++++++++------- setup.py | 84 +++++++++++++++++----------- 4 files changed, 231 insertions(+), 90 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index fb9e267..a2a3d2b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -2,10 +2,13 @@ stages: - test - build - deploy + - pypi-twine test: stage: test tags: ["build"] + except: + - tags script: make test artifacts: paths: @@ -15,22 +18,24 @@ test: build: stage: build tags: ["build"] + except: + - tags script: - mv env.vanilla env - - make prod - # copy static assets to env/static & create a tarball of the static files. + - make install-from-source-prod + # Copy static assets to env/static and create a tarball of the static files. - cp -pr make_post_sell/static env/static - cp -pr env/static static - tar -zcf static.tar.gz static - # move the virtualenv with virtualenv-clone into desired location. + # Clone the virtualenv with virtualenv-clone into the desired location. - virtualenv-clone env /opt/make_post_sell/env - # make tarball of virtualenv. + # Create a tarball of the virtualenv. - tar -zcf env.tar.gz -C /opt/make_post_sell . - # create sha512 of env.tar.gz + # Create SHA512 hash of env.tar.gz. - sha512sum env.tar.gz >> env.tar.gz.hash - # create commit-hash.txt to track this build's git commit hash. + # Create commit-hash.txt to track this build's git commit hash. - echo $CI_COMMIT_SHA >> commit-hash.txt - # clean up directory outside of gitlab-runner filesystem. + # Clean up the directory outside of the gitlab-runner filesystem. - rm -rf /opt/make_post_sell/env artifacts: paths: @@ -44,9 +49,19 @@ deploy: stage: deploy needs: [build] rules: - - if: '$CI_COMMIT_BRANCH == "develop"' - when: on_success - - if: '$CI_COMMIT_BRANCH == "master"' + - if: '$CI_COMMIT_BRANCH == "develop" || $CI_COMMIT_BRANCH == "master" || $CI_COMMIT_BRANCH == "main"' when: on_success trigger: include: .gitlab-ci.deploy.yml + +pypi-twine: + stage: pypi-twine + tags: + - build + only: + - tags + script: + - pip install --upgrade pip + - pip install twine + - python3 setup.py sdist bdist_wheel + - twine upload dist/* diff --git a/Makefile b/Makefile index bba312e..6d6e435 100644 --- a/Makefile +++ b/Makefile @@ -1,31 +1,128 @@ -env: - python3 -m venv env - . env/bin/activate - env/bin/pip install --upgrade pip - env/bin/pip install --upgrade -r requirements.py3.txt +# Makefile for operating the make_post_sell server using either PyPI packages or source -dev: env - env/bin/pip install --upgrade -r requirements-dev.txt - env/bin/pip install --upgrade -r requirements-test.txt - env/bin/pip install --editable . - cp -rp env env.vanilla +# Variables (using the current working directory) +VENV_DIR = $(shell pwd)/env +DATA_DIR = $(shell pwd)/data +CONFIG_FILE = development.ini +# Using the provided configuration URL. +CONFIG_URL = https://git.unturf.com/engineering/make-post-sell/make_post_sell/-/raw/master/development.ini -prod: env - env/bin/pip install --upgrade -r requirements-prod.txt - env/bin/pip install . - cp -rp env env.vanilla +PYTHON = $(VENV_DIR)/bin/python +PIP = $(VENV_DIR)/bin/pip +PSERVE = $(VENV_DIR)/bin/pserve +ALEMBIC = $(VENV_DIR)/bin/alembic +MPS_INIT = $(VENV_DIR)/bin/initialize_make_post_sell_db -init_db: env - env/bin/initialize_make_post_sell_db ${config} +# Default target: install from PyPI and then start the server. +all: install-from-pypi serve +# ----------------------------------------------------------------------------- +# Environment Setup Targets +# ----------------------------------------------------------------------------- + +# Create virtual environment if not present. +$(VENV_DIR)/bin/activate: + @echo "Creating virtual environment in $(VENV_DIR)..." + python3 -m venv $(VENV_DIR) + +venv: $(VENV_DIR)/bin/activate + +# Create data directory and download configuration file if missing. +$(DATA_DIR)/$(CONFIG_FILE): + @echo "Creating data directory in $(DATA_DIR) and downloading configuration file..." + mkdir -p $(DATA_DIR) + cd $(DATA_DIR) && wget -O $(CONFIG_FILE) $(CONFIG_URL) + +config: $(DATA_DIR)/$(CONFIG_FILE) + +# ----------------------------------------------------------------------------- +# Package Installation Targets for PyPI Installation +# ----------------------------------------------------------------------------- + +# Install the make_post_sell core package from PyPI. +install-core: venv + @echo "Installing make_post_sell core package from PyPI..." + $(PIP) install make_post_sell + +# Install development extras from PyPI. +install-dev: venv + @echo "Installing make_post_sell development extras from PyPI..." + $(PIP) install make_post_sell[dev] + +# Combined PyPI installation target. +install: install-core install-dev + +# ----------------------------------------------------------------------------- +# Package Installation Targets for Source Installation +# ----------------------------------------------------------------------------- + +# Install from source (editable mode) for development and testing. +install-source-dev-and-test: venv + @echo "Installing make_post_sell from source (editable mode) for development..." + $(PIP) install --editable . + $(PIP) install --upgrade -r requirements-dev.txt + $(PIP) install --upgrade -r requirements-test.txt + cp -rp $(VENV_DIR) $(VENV_DIR).vanilla + +# Install from source for production (non‑editable). +install-source-prod: venv + @echo "Installing make_post_sell from source for production (non‑editable)..." + $(PIP) install . + $(PIP) install --upgrade -r requirements-prod.txt + cp -rp $(VENV_DIR) $(VENV_DIR).vanilla + +# ----------------------------------------------------------------------------- +# Database Initialization and Server Targets +# ----------------------------------------------------------------------------- + +# Initialize the database using the configuration file. +init-db: venv config + @echo "Initializing the make_post_sell database..." + $(MPS_INIT) $(DATA_DIR)/$(CONFIG_FILE) + $(ALEMBIC) -c $(DATA_DIR)/$(CONFIG_FILE) stamp head + +# Start the development server with auto-reload. +serve: venv config + @echo "Starting the make_post_sell development server..." + $(PSERVE) $(DATA_DIR)/$(CONFIG_FILE) --reload + +# ----------------------------------------------------------------------------- +# Combined Setup Targets +# ----------------------------------------------------------------------------- + +# Install and set up using PyPI packages. +install-from-pypi: venv config install init-db + +# Install and set up from source (editable mode) for development and testing. +install-from-source: venv config install-source-dev-and-test init-db + +# Install and set up from source for production (non‑editable). +install-from-source-prod: venv config install-source-prod init-db + +# ----------------------------------------------------------------------------- +# Additional Targets +# ----------------------------------------------------------------------------- + +# Print instructions for activating the virtual environment. +activate: + @echo "To activate the virtual environment, run:" + @echo " source $(VENV_DIR)/bin/activate" + +# Run the test suite. +test: install-source-dev-and-test + @echo "Running tests..." + $(VENV_DIR)/bin/py.test + +# Start a simple HTTP server (if needed for static files). +http: venv + @echo "Starting simple HTTP server on port 8000..." + $(PYTHON) -m http.server 8000 + +# ----------------------------------------------------------------------------- +# Cleanup Target +# ----------------------------------------------------------------------------- + +# Remove the virtual environment directories. clean: - rm -rf env - rm -rf env.vanilla - -test: dev - #env/bin/py.test --lf - env/bin/py.test - -serve: dev - # In the first shell, run a copy of make_post_sell using: - env/bin/pserve development.ini --reload + @echo "Cleaning up: removing $(VENV_DIR) and $(VENV_DIR).vanilla..." + rm -rf $(VENV_DIR) $(VENV_DIR).vanilla diff --git a/README.rst b/README.rst index ce75847..eb2aaf7 100644 --- a/README.rst +++ b/README.rst @@ -3,32 +3,51 @@ Make Post Sell The `Make Post Sell `_ monolith platform service. +You can use the SaaS or self-host! -Getting Started ---------------- +Our `blog acts as our user guide `_ & also uses ``make_post_sell``! -Clone this repo and change your working directory to the checkout. -Create a Python virtual environment and install project dependencies: +Quick Start: Operating a Server with PyPI or Source Code +========================================================== -.. code-block:: bash +Before you start, navigate to the directory where you want to install ``make_post_sell`` database & files. - make dev +This Makefile-based workflow lets you choose between installing ``make_post_sell`` from PyPI packages or directly from the source code (editable mode). Both flows create a virtual environment in ``./env`` and store configuration and SQLite data in the persistent ``./data`` directory. -Load schema and default data into the database using a script, -we currently use sqlite3 as a development and test database: +1. **Install make_post_sell** -.. code-block:: bash + - **PyPI Installation:** + Download the Makefile and run:: + + wget "https://git.unturf.com/engineering/make-post-sell/make_post_sell/-/raw/master/Makefile" + make install-from-pypi - make init_db config=development.ini + - **Source Installation (Editable Mode):** + Clone the repository and run:: + + git clone ssh://git@git.unturf.com:2222/engineering/make-post-sell/make_post_sell.git + make install-from-source -Run a web application server with the project loaded: + - **Production Installation (Non‑Editable):** + For production use (non‑editable even from source), run:: + + git clone ssh://git@git.unturf.com:2222/engineering/make-post-sell/make_post_sell.git + make install-from-source-prod -.. code-block:: bash +2. **Activate the Virtual Environment** - make serve + Before running any commands, activate the virtual environment:: + + source env/bin/activate -In a web browser navagate to http://127.0.0.1:6501/ and you should see the app. +3. **Start the Development Server** + + With the virtual environment active, start the server:: + + make serve + + Then browse to [http://127.0.0.1:6501/](http://127.0.0.1:6501/) to view the app. Running Tests @@ -45,11 +64,6 @@ SQL Migrations =============== If your deployment is brand new, you don't need to run any migrations. -You should however run this to stamp the database as ready: - -.. code-block:: bash - - alembic -c development.ini stamp head Otherwise, it should be safe to run this at anytime to catch your database up: @@ -154,4 +168,3 @@ Licence ===================== All code contributed goes into the public domain. - diff --git a/setup.py b/setup.py index 113371c..9f4b303 100644 --- a/setup.py +++ b/setup.py @@ -1,54 +1,70 @@ import os - from setuptools import setup, find_packages -here = os.path.abspath(os.path.dirname(__file__)) -with open(os.path.join(here, "README.rst")) as f: - README = f.read() +def parse_requirements(filename): + """ + Read and parse a requirements file, ignoring comments and blank lines. + """ + req_path = os.path.join(os.path.dirname(__file__), filename) + with open(req_path, "r", encoding="utf-8") as f: + lines = f.read().splitlines() + return [line.strip() for line in lines if line.strip() and not line.startswith("#")] -tests_require = [ - "WebTest >= 1.3.1", # py3 compat - "pytest >= 3.7.4", - "pytest-cov", -] +# Determine the runtime requirements. +install_requires = parse_requirements("requirements.py3.txt") + +# Optional extras for development, production, and testing. +extras_require = { + "dev": parse_requirements("requirements-dev.txt"), + "prod": parse_requirements("requirements-prod.txt"), + "test": parse_requirements("requirements-test.txt"), +} + +# Read the long description from README.rst. +here = os.path.abspath(os.path.dirname(__file__)) +with open(os.path.join(here, "README.rst"), "r", encoding="utf-8") as f: + long_description = f.read() setup( name="make_post_sell", version="1.0.0", description="Make Post Sell", - long_description=README, - author="Russell Ballestrini", - author_email="russell@ballestrini.net", - url="https://www.makepostsell.com", - keywords="make post sell web pyramid pylons ecommerse digital downloads content marketing youtube alternative", - packages=find_packages(exclude="tests"), - package_data={ - "make_post_sell": ["scripts/alembic/*.py", "scripts/alembic/versions/*.py"] - }, - include_package_data=True, - zip_safe=False, - extras_require={ - "testing": tests_require, - }, - entry_points={ - "paste.app_factory": [ - "main = make_post_sell:main", - ], - "console_scripts": [ - "initialize_make_post_sell_db=make_post_sell.scripts.initialize_db:main", - ], - }, + long_description=long_description, classifiers=[ - "Programming Language :: Python :: 2.7", - "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "Programming Language :: Python", "Framework :: Pyramid", "Topic :: Internet :: WWW/HTTP", "Topic :: Internet :: WWW/HTTP :: WSGI :: Application", ], - + author="Russell Ballestrini", + author_email="russell@ballestrini.net", + url="https://www.makepostsell.com", + keywords="make post sell web pyramid pylons ecommerce digital downloads physical goods content marketing youtube alternative", + packages=find_packages(), + package_data={ + "make_post_sell": ["scripts/alembic/*.py", "scripts/alembic/versions/*.py"] + }, + include_package_data=True, + zip_safe=False, + install_requires=install_requires, + extras_require=extras_require, + entry_points={ + "paste.app_factory": ["main = make_post_sell:main"], + "console_scripts": [ + "initialize_make_post_sell_db = make_post_sell.scripts.initialize_db:main", + ], + }, ) + +# python setup.py sdist bdist_wheel +# twine upload dist/* -- 2.49.1 From 2c46bc1e11ef21304e7e98ecb13d2e165e4b9b18 Mon Sep 17 00:00:00 2001 From: Russell Ballestrini Date: Sun, 2 Mar 2025 08:51:57 -0500 Subject: [PATCH 2/2] modified: README.rst --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index eb2aaf7..aacbd63 100644 --- a/README.rst +++ b/README.rst @@ -47,7 +47,7 @@ This Makefile-based workflow lets you choose between installing ``make_post_sell make serve - Then browse to [http://127.0.0.1:6501/](http://127.0.0.1:6501/) to view the app. + Then browse to `http://127.0.0.1:6501/ `_ to view the app. Running Tests -- 2.49.1