Skip to content

Commit

Permalink
Merge pull request #135 from OpenTrafficCam/feature/1894-create-relea…
Browse files Browse the repository at this point in the history
…se-workflow-similar-to-otvision

Feature/1894-create-release-workflow-similar-to-otvision
  • Loading branch information
briemla authored Apr 12, 2023
2 parents 68ef2fc + 0ee4619 commit 8b928eb
Show file tree
Hide file tree
Showing 5 changed files with 232 additions and 0 deletions.
40 changes: 40 additions & 0 deletions .github/workflows/create-distribution.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
# This workflow will install Python dependencies, run tests

name: Create release

on:
workflow_run:
workflows: ["Run CI/CD"]
types: ["completed"]
branches: ["main"]

jobs:
create_distributions:
runs-on: ${{ matrix.os }}
if: ${{ github.event.workflow_run.conclusion == 'success' }}
strategy:
fail-fast: True
max-parallel: 1
matrix:
os: [ubuntu-latest]
python-version: ["3.10"]

steps:
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Create distributions
run: python build.py
- name: Release
uses: softprops/action-gh-release@v1
with:
body: |
This is the latest release and is not production ready.
Use at your own risk.
name: latest
draft: True
prerelease: True
files: dist/*.zip
2 changes: 2 additions & 0 deletions .shellcheckrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Necessary to allow execution of source venv/bin/activate
external-sources=true
170 changes: 170 additions & 0 deletions build.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
import os
import shutil
import zipfile
from dataclasses import dataclass
from pathlib import Path
from zipfile import ZipFile


def collect_files(
base_path: Path,
file_extension: str = ".py",
) -> list[Path]:
"""Collect all files in the file tree.
Args:
base_path (Path): base path to start searching files
file_extension (str, optional): only files with this extension will be
collected. Defaults to ".py".
Returns:
list[Path]: list of collected files.
"""
paths: list[Path] = []
for folder_name, subfolders, file_names in os.walk(base_path):
for file_name in file_names:
if file_name.endswith(file_extension):
file_path = Path(folder_name, file_name)
paths.append(file_path)
return paths


def zip_output_folder(input_folder: Path, zip_file: Path) -> None:
"""Zip a whole directory into a zip file. The directory structure (subdirectories)
will remain in the zip file.
Args:
input_folder (Path): folder to zip
zip_file (Path): zipped folder as file
"""
with ZipFile(zip_file, "w", zipfile.ZIP_DEFLATED) as output:
for root, dirs, files in os.walk(input_folder):
for file in files:
file_path = Path(root, file)
base_path = Path(input_folder, ".")
output_path = file_path.relative_to(base_path)
output.write(file_path, output_path)


def clean_directory(directory: Path) -> None:
"""Clean the given directory.
Args:
directory (Path): directory to clean.
"""
if directory.exists():
shutil.rmtree(directory)
directory.mkdir(exist_ok=True)


@dataclass(frozen=True)
class Configuration:
"""Configuration for deployment. It contains all files required on the given
platform (suffix)
"""

_otanalytics_path: Path
_files: list[Path]
_additional_files: list[Path]
_suffix: str

def create_zip(
self, file_name: str, output_directory: Path, temp_directory: Path
) -> None:
"""Create a zip file with the given name in the given output directory.
Store temporal artifacts in the temp_folder.
Args:
file_name (str): name of the zip file.
output_directory (Path): directory to store the zip file in.
temp_directory (Path): directory for temporal artifacts.
"""
clean_directory(build_path)
zip_file = Path(output_directory, f"{file_name}-{self._suffix}.zip")
self._copy_to_output_directory(temp_directory)
zip_output_folder(temp_directory, zip_file)
clean_directory(build_path)

def _copy_to_output_directory(self, output_directory: Path) -> None:
files = collect_files(base_path=self._otanalytics_path, file_extension=".py")
self._copy_files(files, output_directory=output_directory)

self._copy_files(self._files, output_directory=output_directory)
self._copy_files(self._additional_files, output_directory=output_directory)

def _copy_files(self, files: list[Path], output_directory: Path) -> None:
"""Copies all files into the output directory. The directory structure will
remain.
Args:
files (list[Path]): files to copy.
output_directory (Path): directory to copy the files to.
"""
for file in files:
output_file = Path(output_directory, file)
output_file.parent.mkdir(parents=True, exist_ok=True)
shutil.copy(file, output_file)

def _read_requirements(self, requirements_file: Path) -> str:
"""Read content of existing requirements file.
Args:
requirements_file (Path): path to requirements.txt
Returns:
str: content of requirements.txt
"""
with open(requirements_file, "r") as requirements:
return requirements.read()


build_path = Path("build")
distribution_path = Path("dist")
output_file_name = "otanalytics"

otanalytics_path = Path("OTAnalytics")

base_files = [
Path("LICENSE"),
Path("README.md"),
Path("requirements.txt"),
]

windows_files = [
Path("install.cmd"),
Path("start_gui.cmd"),
]

unix_files = [
Path("install.sh"),
Path("start_gui.sh"),
]

configurations: list[Configuration] = [
Configuration(
_otanalytics_path=otanalytics_path,
_files=base_files,
_additional_files=windows_files,
_suffix="win",
),
Configuration(
_otanalytics_path=otanalytics_path,
_files=base_files,
_additional_files=unix_files,
_suffix="linux",
),
Configuration(
_otanalytics_path=otanalytics_path,
_files=base_files,
_additional_files=unix_files,
_suffix="macOS",
),
]

clean_directory(distribution_path)
for configuration in configurations:
configuration.create_zip(
output_file_name,
output_directory=distribution_path,
temp_directory=build_path,
)
12 changes: 12 additions & 0 deletions start_gui.cmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
echo Install OTAnalytics.
@echo off
FOR /F "tokens=* USEBACKQ" %%F IN (`python --version`) DO SET PYTHON_VERSION=%%F

echo %PYTHON_VERSION%
if "x%PYTHON_VERSION:3.10=%"=="x%PYTHON_VERSION%" (
echo "Python Version 3.10 is not installed in environment." & cmd /K & exit
)

call venv\Scripts\activate
python -m OTAnalytics
deactivate
8 changes: 8 additions & 0 deletions start_gui.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/bin/bash
echo "Start OTAnalytics."

WORKING_DIR=$(pwd)

source "$WORKING_DIR"/venv/bin/activate
python3.10 -m OTAnalytics
deactivate

0 comments on commit 8b928eb

Please sign in to comment.