Skip to content

Commit

Permalink
Merge pull request #1 from panpuchkov/feature/pip-package
Browse files Browse the repository at this point in the history
Feature/pip package
  • Loading branch information
panpuchkov authored Dec 28, 2023
2 parents aea4a46 + 70933b6 commit 157b296
Show file tree
Hide file tree
Showing 16 changed files with 167 additions and 39 deletions.
50 changes: 42 additions & 8 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Docker Build & Push
name: Build & Push
permissions: write-all

on:
Expand Down Expand Up @@ -41,12 +41,15 @@ jobs:
pip install -U tox
pip install tox
tox
build:
runs-on: ubuntu-latest
needs: unittests
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0

- name: Docker Build
shell: bash
Expand All @@ -55,19 +58,50 @@ jobs:
docker build -t "${{ env.DOCKER_USERNAME }}/${{ env.IMAGE_NAME }}" .
- name: Log in to Docker Hub
if: github.ref == 'refs/heads/main'
uses: docker/login-action@v3
with:
username: ${{ env.DOCKER_USERNAME }}
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}

- name: Detect package version
shell: bash
run: |
set -x
PACKAGE_VERSION="$(git tag --contains)"
if [[ "${PACKAGE_VERSION}" == "" ]]; then
PACKAGE_VERSION="$(docker run --rm -v $(pwd):/app -w /app --user "$(id -u):$(id -g)" panpuchkov/pygitver --next-ver)-dev"
PACKAGE_VERSION=$(echo "${PACKAGE_VERSION}" | sed 's/^v*//' )
DOCKER_TAG_LATEST="${PACKAGE_VERSION}"
else
DOCKER_TAG_LATEST="latest"
fi
echo "PACKAGE_VERSION=$PACKAGE_VERSION" >> $GITHUB_ENV
echo "DOCKER_TAG_LATEST=$DOCKER_TAG_LATEST" >> $GITHUB_ENV
- name: Docker Push
shell: bash
run: |
set -x
DOCKER_TAG="$(git tag --contains)"
if [[ "${DOCKER_TAG}" == "" ]]; then
DOCKER_TAG="latest"
# Generate docker tags
IMAGE_NAME_WITH_TAG_VERSION="${{ env.DOCKER_USERNAME }}/${{ env.IMAGE_NAME }}:${PACKAGE_VERSION}"
IMAGE_NAME_WITH_TAG_LATEST="${{ env.DOCKER_USERNAME }}/${{ env.IMAGE_NAME }}:${DOCKER_TAG_LATEST}"
# Set docker tag
docker tag "${{ env.DOCKER_USERNAME }}/${{ env.IMAGE_NAME }}:latest" "${{ env.DOCKER_USERNAME }}/${{ env.IMAGE_NAME }}:${PACKAGE_VERSION}"
docker push "${IMAGE_NAME_WITH_TAG_VERSION}"
# Push latest if required
if [[ "${IMAGE_NAME_WITH_TAG_LATEST}" != "${IMAGE_NAME_WITH_TAG_LATEST}" ]]; then
docker push "${IMAGE_NAME_WITH_TAG_LATEST}"
fi
IMAGE_NAME_WITH_VERSION="${{ env.DOCKER_USERNAME }}/${{ env.IMAGE_NAME }}:${DOCKER_TAG}"
docker push "${IMAGE_NAME_WITH_VERSION}"
- name: Pip Build & Push
shell: bash
run: |
set -x
pip install -r requirements-build.txt
python -m build
sudo apt-get -y install twine
twine check dist/*
twine upload --skip-existing -u ${{ secrets.PYPI_USERNAME }} -p ${{ secrets.PYPI_PASSWORD }} dist/* --verbose
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@
.coverage
*/__pycache__/*
venv
dist
*.egg-info
27 changes: 19 additions & 8 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,25 +1,36 @@
################################################################
FROM python:3.12-alpine as build

# Make sure we use the virtualenv:
RUN python -m venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"

# Install pip requirements
COPY ./requirements.txt /pygitver/requirements.txt
RUN pip install --no-cache-dir -U pip \
&& pip install --no-cache-dir -r /pygitver/requirements.txt
WORKDIR /build-pkg

# Install pip requirements
COPY . /build-pkg

RUN apk add --no-cache git \
&& pip install --no-cache-dir -U pip \
&& pip install --no-cache-dir -r requirements.txt \
&& pip install --no-cache-dir -r requirements-build.txt \
&& rm -rf dist \
&& python -m build \
&& pip install $(ls /build-pkg/dist/pygitver-*.tar.gz) \
&& pip uninstall -r requirements-build.txt -y

################################################################
FROM python:3.12-alpine

ENV PYGITVER_TEMPLATE_CHANGELOG="/pygitver/templates/changelog.tmpl"
ENV PYGITVER_TEMPLATE_CHANGELOG_COMMON="/pygitver/templates/changelog-common.tmpl"
ENV PYGITVER_ROOT="/pygitver"

# Install dependencies
RUN apk add --no-cache git openssh \
&& ln -s /pygitver/pygitver /usr/local/bin/pygitver
RUN apk add --no-cache git openssh

# Copy application code and
COPY ./src /pygitver
COPY ./src/pygitver/templates /pygitver/templates
COPY ./scripts /pygitver/scripts
COPY --from=build /opt/venv /opt/venv

Expand All @@ -28,4 +39,4 @@ WORKDIR /app
# Make sure we use the virtualenv:
ENV PATH="/opt/venv/bin:$PATH"

ENTRYPOINT ["python", "/pygitver/pygitver.py"]
ENTRYPOINT ["pygitver"]
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,24 @@ Features:

# Examples

You may use it as a Python package or a Docker container.

## PIP Package

```shell
$ git tag -l
v0.0.1
v0.0.2
$ pygitver --curr-ver
v0.0.2
$ pygitver --next-ver
v0.0.3

```


## Docker Container

```shell
$ git tag -l
v0.0.1
Expand Down Expand Up @@ -235,3 +253,15 @@ or
```shell
coverage run -m pytest -- ./tests/test_git.py
```
#### Build pip package
Linux
```shell
python3 -m build
```
For `Debian` based OS:
```shell
DEB_PYTHON_INSTALL_LAYOUT=deb_system python3 -m build
```
38 changes: 38 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
[project]
name = "pygitver"
version = "0.1.0-dev"
authors = [
{ name="Yurii Puchkov", email="[email protected]" },
]
license = {text = "GNU General Public License v3 (GPLv3)"}
description = "Manages Git Tag versions and generates ChangeLog"
keywords = ["git tag", "version", "versions", "conventional commit", "semver", "changelog", "changelogs"]
readme = "README.md"
requires-python = ">=3.8"
classifiers = [
"Development Status :: 5 - Production/Stable",
"Environment :: Console",
"Natural Language :: English",
"Programming Language :: Python :: 3",
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
"Operating System :: OS Independent",
]
dependencies = [
"Jinja2==3.1.2"
]


[build-system]
requires = ["setuptools>=63", "wheel"]
build-backend = "setuptools.build_meta"


[project.scripts]
pygitver = "pygitver.pygitver:main"

[metadata]
url = "https://github.com/panpuchkov/pygitver"


[tool.setuptools.package-data]
pygitver = ["*.py", "*.tmpl"]
2 changes: 2 additions & 0 deletions requirements-build.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
build~=1.0
setuptools~=69.0
7 changes: 0 additions & 7 deletions src/pygitver

This file was deleted.

File renamed without changes.
13 changes: 9 additions & 4 deletions src/changelogs_mngr.py → src/pygitver/changelogs_mngr.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import os
import pathlib
import json
from git import Git, GitError
from pygitver.git import Git, GitError

from jinja2 import Environment, FileSystemLoader, TemplateNotFound

Expand Down Expand Up @@ -49,9 +50,13 @@ def read_files(self, path: str, file_ext: str = "json"):
self._changelogs["version"] = None
return self._changelogs

def changelog_generate(
self, template_name: str = "templates/changelog-common.tmpl"
) -> str:
def generate(self, template_name: str = "") -> str:
if not template_name:
script_directory = pathlib.Path(__file__).parent.resolve()
template_name = os.getenv(
"PYGITVER_TEMPLATE_CHANGELOG_COMMON",
f"{script_directory}/templates/changelog-common.tmpl",
)
try:
env = Environment(loader=FileSystemLoader(os.path.dirname(template_name)))
template = env.get_template(os.path.basename(template_name))
Expand Down
7 changes: 5 additions & 2 deletions src/git.py → src/pygitver/git.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import json
import os
import pathlib
import json
import re
import subprocess
from jinja2 import Environment, FileSystemLoader, TemplateNotFound
Expand Down Expand Up @@ -252,8 +253,10 @@ def changelog_generate(changelog_group: dict, template_name: str = "") -> str:
:return: string with formatted changelog
"""
if not template_name:
script_directory = pathlib.Path(__file__).parent.resolve()
template_name = os.getenv(
"PYGITVER_TEMPLATE_CHANGELOG", "templates/changelog.tmpl"
"PYGITVER_TEMPLATE_CHANGELOG",
f"{script_directory}/templates/changelog.tmpl",
)
try:
env = Environment(loader=FileSystemLoader(os.path.dirname(template_name)))
Expand Down
8 changes: 3 additions & 5 deletions src/pygitver.py → src/pygitver/pygitver.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import argparse

from git import Git, GitError
from changelogs_mngr import ChangelogsMngr, ChangelogsMngrError
from pygitver.git import Git, GitError
from pygitver.changelogs_mngr import ChangelogsMngr, ChangelogsMngrError
import json


Expand Down Expand Up @@ -116,9 +116,7 @@ def main():
output = join_changelogs.read_files(path=args.dir, file_ext="json")
if args.format == "text":
try:
print(
join_changelogs.changelog_generate(template_name=args.template)
)
print(join_changelogs.generate(template_name=args.template))
except ChangelogsMngrError as err:
print(err)
exit(1)
Expand Down
File renamed without changes.
File renamed without changes.
Empty file removed tests/__init__.py
Empty file.
18 changes: 15 additions & 3 deletions tests/test_changelogs_mngr.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import os
import json
import unittest
from src.changelogs_mngr import ChangelogsMngr, Git, ChangelogsMngrError
from unittest import mock
from pygitver.changelogs_mngr import ChangelogsMngr, ChangelogsMngrError
from pygitver.git import Git


class TestChangelogsMngr(unittest.TestCase):
Expand All @@ -14,10 +16,14 @@ def test_join_changelogs(self, monkeypatch):
expected = json.load(fp)
assert res == expected

@mock.patch.dict(os.environ, {"PYGITVER_TEMPLATE_CHANGELOG_COMMON": "src/pygitver/templates/changelog-common.tmpl"},
clear=True)
def test_join_changelogs_template(self):
join_changelogs = ChangelogsMngr("2.1.2")
join_changelogs.read_files("./tests/data/changelogs/", "json")
res = join_changelogs.changelog_generate(template_name="src/templates/changelog-common.tmpl")

res = join_changelogs.generate()

expected = "# Change Log\n\n" \
"## Version: 3.0.0\n\n\n\n\n\n" \
"## Services\n\n\n\n" \
Expand All @@ -40,6 +46,12 @@ def test_join_changelogs_template(self):
for pos, _ in enumerate(l_res):
self.assertEqual(l_expected[pos], l_res[pos])

res = join_changelogs.generate(template_name="src/pygitver/templates/changelog-common.tmpl")
l_res = res.split("\n")
l_expected = expected.split("\n")
for pos, _ in enumerate(l_res):
self.assertEqual(l_expected[pos], l_res[pos])

def test_init_changelog(self):
chl_mngr = ChangelogsMngr()
chl_mngr._changelogs = {"version": "0.0.0", "services": {"test": None}}
Expand All @@ -53,6 +65,6 @@ def test_changelog_generate(self):
chl_mngr = ChangelogsMngr()

with self.assertRaises(ChangelogsMngrError) as context:
chl_mngr.changelog_generate(template_name=template_name)
chl_mngr.generate(template_name=template_name)
self.assertEqual(f"ERROR: Template '{template_name}' was not found.",
str(context.exception))
4 changes: 2 additions & 2 deletions tests/test_git.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from src.git import Git
from pygitver.git import Git

GIT_LOG_OUTPUT_MOCK = "fix: test fix 1\n" \
"feat(api)!: new api\n" \
Expand Down Expand Up @@ -139,7 +139,7 @@ def test_changelog_generate(monkeypatch):
monkeypatch.setattr(Git, "changelog", value=lambda *args, **kwargs: GIT_LOG_OUTPUT_MOCK)
monkeypatch.setattr(Git, "git_version", value=lambda *args, **kwargs: "git version v1.0.0")
changelog = Git.changelog_generate(changelog_group=Git.changelog_group(),
template_name="src/templates/changelog.tmpl")
template_name="src/pygitver/templates/changelog.tmpl")
assert changelog == "##########\nChange Log\n##########\n\nVersion v1.0.0\n=============\n\n\n\n\n\n" \
"Features\n--------\n\n\n* New api\n\n\n\n\n\n" \
"Bug Fixes\n---------\n\n\n* Test fix 1\n\n* Test fix 2\n\n\n\n\n\n" \
Expand Down

0 comments on commit 157b296

Please sign in to comment.