Skip to content

Commit 094e1ee

Browse files
committed
feat!: restructure as proper Python package with tests
BREAKING CHANGE: Complete rewrite with new architecture - Restructured as installable Python package (pyproject.toml) - Modular design: config, encoder, sync, utils, watcher modules - YAML-based configuration with multiple output support - Added comprehensive test suite with pytest - Watchdog-based file system monitoring - Periodic sync check every 5 minutes for missing outputs - Safety guard allows initial bulk encoding when outputs are empty - Enhanced verify_sync tool with metadata checking - Added GitHub Actions for tests and releases - Docker image: drumsergio/audio-transcoder:0.1.0 Features: - Multiple output formats: ALAC, AAC, MP3, FLAC, Opus, WAV - Configurable bitrates for lossy codecs - Cover art preservation with automatic retry - MP3 source files copied directly to MP3 output - Atomic file writes (temp file + rename) - Unicode normalization for cross-platform compatibility
1 parent e792d46 commit 094e1ee

24 files changed

Lines changed: 3172 additions & 963 deletions

‎.github/workflows/release.yml‎

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*.*.*'
7+
8+
env:
9+
REGISTRY: docker.io
10+
IMAGE_NAME: drumsergio/audio-transcoder
11+
12+
jobs:
13+
test:
14+
runs-on: ubuntu-latest
15+
steps:
16+
- uses: actions/checkout@v4
17+
18+
- name: Set up Python
19+
uses: actions/setup-python@v5
20+
with:
21+
python-version: '3.13'
22+
cache: 'pip'
23+
24+
- name: Install dependencies
25+
run: |
26+
python -m pip install --upgrade pip
27+
pip install -e ".[dev]"
28+
29+
- name: Run tests
30+
run: pytest
31+
32+
build-and-push:
33+
needs: test
34+
runs-on: ubuntu-latest
35+
permissions:
36+
contents: write
37+
packages: write
38+
39+
steps:
40+
- uses: actions/checkout@v4
41+
42+
- name: Extract version from tag
43+
id: version
44+
run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
45+
46+
- name: Set up QEMU
47+
uses: docker/setup-qemu-action@v3
48+
49+
- name: Set up Docker Buildx
50+
uses: docker/setup-buildx-action@v3
51+
52+
- name: Log into Docker Hub
53+
uses: docker/login-action@v3
54+
with:
55+
username: ${{ secrets.DOCKERHUB_USERNAME }}
56+
password: ${{ secrets.DOCKERHUB_TOKEN }}
57+
58+
- name: Extract Docker metadata
59+
id: meta
60+
uses: docker/metadata-action@v5
61+
with:
62+
images: ${{ env.IMAGE_NAME }}
63+
tags: |
64+
type=semver,pattern={{version}}
65+
type=semver,pattern={{major}}.{{minor}}
66+
type=semver,pattern={{major}}
67+
type=raw,value=latest,enable={{is_default_branch}}
68+
69+
- name: Build and push Docker image
70+
uses: docker/build-push-action@v6
71+
with:
72+
context: .
73+
push: true
74+
platforms: linux/amd64,linux/arm64
75+
tags: ${{ steps.meta.outputs.tags }}
76+
labels: ${{ steps.meta.outputs.labels }}
77+
cache-from: type=gha
78+
cache-to: type=gha,mode=max
79+
80+
- name: Create GitHub Release
81+
uses: softprops/action-gh-release@v2
82+
with:
83+
generate_release_notes: true
84+
body: |
85+
## Docker Image
86+
87+
```bash
88+
docker pull ${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}
89+
```
90+
91+
## What's Changed
92+
93+
See the automatically generated release notes below.
94+
env:
95+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

‎.github/workflows/tests.yml‎

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
name: Tests
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
test:
11+
runs-on: ubuntu-latest
12+
strategy:
13+
matrix:
14+
python-version: ['3.11', '3.12', '3.13']
15+
16+
steps:
17+
- uses: actions/checkout@v4
18+
19+
- name: Set up Python ${{ matrix.python-version }}
20+
uses: actions/setup-python@v5
21+
with:
22+
python-version: ${{ matrix.python-version }}
23+
cache: 'pip'
24+
25+
- name: Install dependencies
26+
run: |
27+
python -m pip install --upgrade pip
28+
pip install -e ".[dev]"
29+
30+
- name: Run tests with coverage
31+
run: |
32+
pytest --cov --cov-report=xml --cov-report=term-missing
33+
34+
- name: Upload coverage to Codecov
35+
if: matrix.python-version == '3.13'
36+
uses: codecov/codecov-action@v4
37+
with:
38+
token: ${{ secrets.CODECOV_TOKEN }}
39+
files: ./coverage.xml
40+
fail_ci_if_error: false
41+
42+
lint:
43+
runs-on: ubuntu-latest
44+
steps:
45+
- uses: actions/checkout@v4
46+
47+
- name: Set up Python
48+
uses: actions/setup-python@v5
49+
with:
50+
python-version: '3.13'
51+
cache: 'pip'
52+
53+
- name: Install package
54+
run: |
55+
python -m pip install --upgrade pip
56+
pip install -e .
57+
58+
- name: Check imports
59+
run: |
60+
python -c "from audio_transcode_watcher.main import main"
61+
python -c "from audio_transcode_watcher.config import Config, load_config"

‎.gitignore‎

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Python
2+
__pycache__/
3+
*.py[cod]
4+
*$py.class
5+
*.so
6+
.Python
7+
build/
8+
develop-eggs/
9+
dist/
10+
downloads/
11+
eggs/
12+
.eggs/
13+
lib/
14+
lib64/
15+
parts/
16+
sdist/
17+
var/
18+
wheels/
19+
*.egg-info/
20+
.installed.cfg
21+
*.egg
22+
23+
# Virtual environments
24+
.venv/
25+
venv/
26+
ENV/
27+
28+
# Testing
29+
.coverage
30+
.pytest_cache/
31+
htmlcov/
32+
.tox/
33+
.nox/
34+
35+
# IDEs
36+
.idea/
37+
.vscode/
38+
*.swp
39+
*.swo
40+
41+
# OS
42+
.DS_Store
43+
Thumbs.db
44+
45+
# Local config (not the example)
46+
config.yaml
47+
!config.example.yaml

‎Dockerfile‎

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,22 @@
11
FROM python:3.13-slim
22

3-
# FFmpeg for transcoding
3+
# Install FFmpeg for transcoding
44
RUN apt-get update && apt-get install -y --no-install-recommends ffmpeg \
55
&& rm -rf /var/lib/apt/lists/*
66

7-
# Python deps
8-
COPY requirements.txt /tmp/
9-
RUN pip install --no-cache-dir -r /tmp/requirements.txt
10-
11-
# App
12-
COPY music_sync.py /app/music_sync.py
13-
COPY verify_sync.py /app/verify_sync.py
7+
# Set working directory
148
WORKDIR /app
9+
10+
# Copy package files
11+
COPY pyproject.toml README.md ./
12+
COPY src/ ./src/
13+
COPY tools/ ./tools/
14+
15+
# Install the package
16+
RUN pip install --no-cache-dir .
17+
18+
# Environment
1519
ENV PYTHONUNBUFFERED=1
16-
ENTRYPOINT ["python", "music_sync.py"]
20+
21+
# Default command
22+
ENTRYPOINT ["python", "-m", "audio_transcode_watcher.main"]

0 commit comments

Comments
 (0)