Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
DenisDiachkov authored Sep 3, 2024
0 parents commit dedfb6f
Show file tree
Hide file tree
Showing 13 changed files with 333 additions and 0 deletions.
61 changes: 61 additions & 0 deletions .github/workflows/build-analysis-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
name: Python application

on:
push:
branches:
- '**'
tags-ignore:
- '**'
pull_request:

jobs:
setup:
runs-on: self-hosted
steps:
- uses: actions/checkout@v3
- name: Set up Python 3.11
uses: actions/setup-python@v3
with:
python-version: "3.11"
- name: Install dependencies
env:
PIP_INDEX_EXTRA_URL_REMAINDER: ${{ secrets.PIP_INDEX_EXTRA_URL_REMAINDER }}
PIP_USERNAME: ${{ secrets.PIP_USERNAME }}
PIP_PASSWORD: ${{ secrets.PIP_PASSWORD }}
PIP_PROTOCOL: ${{ vars.PIP_PROTOCOL }}
run: |
python -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e .[test,analyze] \
--no-cache-dir \
--extra-index-url $PIP_PROTOCOL://$PIP_USERNAME:$PIP_PASSWORD@$PIP_INDEX_EXTRA_URL_REMAINDER \
--trusted-host $PIP_INDEX_EXTRA_URL_REMAINDER
analysis:
needs: setup
runs-on: self-hosted
steps:
- name: Set up Python 3.11
uses: actions/setup-python@v3
with:
python-version: "3.11"
- name: Lint (Pylint)
run: source .venv/bin/activate && pylint src
- name: Format check (Black)
run: source .venv/bin/activate && black --check src
- name: Format check (Isort)
run: source .venv/bin/activate && isort --check src
- name: Type check (Pyright)
run: source .venv/bin/activate && pyright src
- name: Security scan (Bandit)
run: source .venv/bin/activate && bandit -r src
unittests:
needs: analysis
runs-on: self-hosted
steps:
- name: Set up Python 3.11
uses: actions/setup-python@v3
with:
python-version: "3.11"
- name: Unittests (Pytest)
run: source .venv/bin/activate && pytest tests/unittests
62 changes: 62 additions & 0 deletions .github/workflows/build-pypi-docker.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
name: Tag creation

on:
push:
tags:
- 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
jobs:
pypi:
runs-on: self-hosted
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.x'
- name: Update VERSION file
run: echo "${{ github.ref_name }}" | cut -c 2- > VERSION
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e '.[build,publish]'
- name: Build and publish
env:
PIP_USERNAME: ${{ secrets.PIP_USERNAME }}
PIP_PASSWORD: ${{ secrets.PIP_PASSWORD }}
PIP_INDEX_EXTRA_URL_REMAINDER: ${{ secrets.PIP_INDEX_EXTRA_URL_REMAINDER }}
PIP_PROTOCOL: ${{ vars.PIP_PROTOCOL }}
run: |
python -m build
twine upload --verbose \
--repository-url $PIP_PROTOCOL://$PIP_INDEX_EXTRA_URL_REMAINDER \
-u $PIP_USERNAME -p $PIP_PASSWORD dist/*
docker:
needs: pypi
runs-on: self-hosted
steps:
- name: Save package name
run: echo $(ls dist | grep .tar.gz | cut -d '-' -f 1) > DOCKER_CONTAINER_NAME
- name: Build docker image
env:
DOCKER_HUB_URL: ${{ secrets.DOCKER_HUB_URL }}
PIP_INDEX_EXTRA_URL_REMAINDER: ${{ secrets.PIP_INDEX_EXTRA_URL_REMAINDER }}
PIP_INDEX_EXTRA_URL: ${{ vars.PIP_PROTOCOL }}://${{ secrets.PIP_USERNAME }}:${{ secrets.PIP_PASSWORD }}@${{ secrets.PIP_INDEX_EXTRA_URL_REMAINDER }}
run: |
echo $PIP_INDEX_EXTRA_URL > /FILE && \
docker build -t $DOCKER_HUB_URL/$(cat DOCKER_CONTAINER_NAME):$(cat VERSION) \
--secret id=PIP_INDEX_EXTRA_URL,env=PIP_INDEX_EXTRA_URL \
--progress=plain \
--no-cache \
--network=host \
--add-host $PIP_INDEX_EXTRA_URL_REMAINDER:$(dig +short $PIP_INDEX_EXTRA_URL_REMAINDER) \
.
- name: Push docker image and cleanup
env:
DOCKER_HUB_URL: ${{ secrets.DOCKER_HUB_URL }}
DOCKER_HUB_USERNAME: ${{ secrets.DOCKER_HUB_USERNAME }}
DOCKER_HUB_PASSWORD: ${{ secrets.DOCKER_HUB_PASSWORD }}
run: |
echo $DOCKER_HUB_PASSWORD | docker login $DOCKER_HUB_URL -u $DOCKER_HUB_USERNAME --password-stdin
docker push $DOCKER_HUB_URL/$(cat DOCKER_CONTAINER_NAME):$(cat VERSION)
docker rmi $DOCKER_HUB_URL/$(cat DOCKER_CONTAINER_NAME):$(cat VERSION)
16 changes: 16 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# general things to ignore
build/
dist/
*.egg-info/
*.egg
*.py[cod]
__pycache__/
*.so
*~

# due to using tox and pytest
.tox
.cache

# due to using vscode
.vscode/
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2024 AGISwarm

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
92 changes: 92 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# Python Template Project

This repository provides a Python project template optimized for development, testing, and CI/CD integration using Docker.

## Project Structure

- `src/AGISwarm/python_template/`: Main package.
- `__init__.py`: Package initialization.
- `__main__.py`: Main module logic.
- `py.typed`: Marker file for PEP 561 typing.
- `pyproject.toml`: Specifies build system requirements and project dependencies.
- `tests/`: Unit and functional tests.
- `.github/workflows/`:
- `build-analysis-test.yml`: CI for build and test.
- `build-pypi-docker.yml`: CI for Docker and PyPI deployment.
- `dockerfile`: Docker setup for Python.

## Features

- Automated tests with examples.
- CI/CD via GitHub Actions.
- Docker integration for deployment.

## Getting Started

### Installation

1. Import the template repository to your GitHub account.

2. Clone the repository:
```bash
git clone <repository-url>
```
3. Navigate to the project directory:
```bash
cd <repository-name>
```
4. Adapt the project to your needs:
1. Modify the project name in `pyproject.toml` and `src/AGISwarm/python_template/__init__.py` to match your project name.
2. Change namespace `AGISwarm` to your own namespace.
3. Add your code to `src/<namespace>/<project-name>/` folder.
4. Write your tests in `tests/` folder.
1. Unittests will be run automatically by GitHub Actions every time you push to the repository. Functional tests will be not.

5. Install dependencies:
```bash
pip install .
```

### CICD Setup

For testing and deployment in a CI/CD setup, refer to our [CICD project](https://github.com/AGISwarm/CICD).

### Usage

#### Command Line

```bash
python -m <namespace>.<project-name>
```

#### Docker

1. Build python package:
```bash
python -m build
```
2. Create PIP_INDEX_EXTRA_URL environment variable to be able to install dependencies from a self-hosted PyPI server.

Given URL is self-hosted PyPI server from [CICD](README.md#cicd-setup) setup.
Replace with your own if needed.
Or remove secret mounting in Dockerfile, if no need.
```bash
export PIP_INDEX_EXTRA_URL=http://pypi-server/
```
3. Build Docker image. Use this command for testing purposes only. If you use [CICD](README.md#cicd-setup) setup, it will build and push the image for you after creating a tag in your repository:
```bash
docker build -t <your tag name> --secret id=PIP_INDEX_EXTRA_URL,env=PIP_INDEX_EXTRA_URL .
```
4. Run Docker container:
```bash
docker run <your tag name>
```


## License

Distributed under the MIT License. See `LICENSE.txt` for details.

## Contact

Denis Diachkov - [email protected]
1 change: 1 addition & 0 deletions VERSION
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0.0.0
14 changes: 14 additions & 0 deletions dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
FROM python:3.11-slim


COPY dist /dist

RUN mkdir -p /root/pip
RUN --mount=type=secret,id=PIP_INDEX_EXTRA_URL,target=/PIP_INDEX_EXTRA_URL \
python -m pip install --upgrade pip && \
python -m pip install /dist/*.whl --no-cache-dir \
--extra-index-url $(cat /PIP_INDEX_EXTRA_URL) \
--trusted-host $(cat /PIP_INDEX_EXTRA_URL | awk -F/ '{print $3}' | awk -F@ '{print $2}')

RUN echo $(ls /dist/*.whl | sed 's/.*\///' | sed 's/-.*//') > /PACKAGE_NAME
ENTRYPOINT python -m $(cat /PACKAGE_NAME)
33 changes: 33 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"

[project]
name = "AGISwarm.python-template"
dynamic = ["version"]
description = "Python template project"
readme = "README.md"

requires-python = ">=3.11"
license = { file = "LICENSE.txt" }
keywords = ["sample", "setuptools", "development"]
classifiers = [
"Programming Language :: Python :: 3",
]
dependencies = ['numpy']
[project.optional-dependencies]
test = ['pytest']
analyze = ['pyright', 'pylint', 'bandit', 'black', 'isort']
build = ['setuptools', 'wheel', 'build']
publish = ['twine']


[tool.setuptools.dynamic]
version = { file = "VERSION" }


[tool.setuptools.packages.find]
where = ["src"]

[tool.setuptools.package-data]
python_template = ["py.typed"]
6 changes: 6 additions & 0 deletions src/AGISwarm/python_template/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
"""__init__.py
"""

from importlib.metadata import version

__version__ = version("AGISwarm.python_template")
12 changes: 12 additions & 0 deletions src/AGISwarm/python_template/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
"""Main.py"""

from . import __version__


def main():
"""Main function"""
print(__version__)


if __name__ == "__main__":
main()
Empty file.
8 changes: 8 additions & 0 deletions tests/functional_tests/test_functional_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
"""Example test file for pytest."""

import pytest


def test_example():
"""Example test function."""
assert 1 == 1
7 changes: 7 additions & 0 deletions tests/unittests/test_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
"""Example test file for pytest."""

import pytest


def test_example():
assert 1 == 1

0 comments on commit dedfb6f

Please sign in to comment.