Thank you for your interest in contributing!
This project is currently maintained by a solo developer, but contributions, suggestions, and improvements are welcome.
- 🧑🤝🧑 Contributors vs Maintainers
- 🧱 Development Workflow
- 🪪 License & Attribution
- 📜 Code of Conduct
- 📋 TODO List
- 🌍 Contact & Discussions
Contributors
Anyone can be a contributor by:
- Submitting bug reports or feature requests via GitHub Issues (use the issue templates: Bug Report and Feature Request)
- Proposing code changes through Pull Requests (the PR template will guide you through the process)
- Improving documentation
- Participating in discussions
- Testing and providing feedback
Maintainers
The maintainer(s) are responsible for:
- Reviewing and merging Pull Requests
- Managing releases and versioning
- Ensuring code quality and project direction
- Responding to critical issues
- Maintaining the project's infrastructure
- Creating and managing hotfix branches for urgent production fixes
- Creating and managing release branches for preparing releases
- Moving "Unreleased" changelog entries to versioned sections during releases
- Managing repository automation (stale issues/PRs, auto-labeling, auto-assignment, etc.)
Important: Even maintainers must go through Pull Requests. No direct commits to main or develop are allowed - all changes, including those from maintainers, must be submitted via Pull Requests and go through the standard review process.
Note: Contributors can submit fixes for critical issues via feature branches. Maintainers may promote these to hotfix branches when urgent production fixes are needed.
Repository automation policies (maintainer-only):
- Publishing workflows (
.github/workflows/*.yml) - handles sensitive secrets and can publish Docker images - Stale issues/PRs workflow - affects repository management policies
- Auto-assignment workflows - affects review process
- Auto-labeler workflow (
.github/workflows/labeler.yml) - automatically labels PRs based on changed files - Other automation workflows that affect repository management
Auto-labeling configuration (contributors can suggest changes via PRs):
- Auto-labeling configuration (
.github/labeler.yml) - contributors can suggest updates when adding new features/components - Example: If adding a new API endpoint, contributor can suggest adding label rules for that component
- Maintainers review and approve label configuration changes
Why most automation is maintainer-only:
- These workflows implement repository policies and management decisions
- Changes can affect how issues/PRs are handled, categorized, and maintained
- They require understanding of project management strategy
What contributors can do:
- Suggest changes to auto-labeling configuration (
.github/labeler.yml) via PRs, especially when adding new features/components - Suggest improvements or report issues with automation via GitHub Issues
- Add/remove labels on their own issues and PRs (type labels like
bug,enhancement, priority labels, etc.) - Discuss automation behavior in discussions or issues
What contributors cannot do:
- Modify automation workflows (stale, auto-assignment, etc.) - these are policy decisions
- Create or delete repository labels (maintainer-only) - repository labels are the label definitions (like
bug,enhancement,api,track) that exist in the repository's label list - Modify labels on issues/PRs they didn't create (unless they have write access)
Currently, this project has a solo maintainer, but the role may expand as the project grows.
We follow a strict Git Flow model:
Workflow steps: Fork & Clone → Environment Setup → Branching → Developing → Testing → Committing → Pull Request Process (including Pre-PR Checklist) → Releasing (For Maintainers)
For contributors:
-
Fork the repository on GitHub
-
Clone your fork:
git clone https://github.com/YOUR-USERNAME/the-music-tree-api.git cd the-music-tree-api
For maintainers:
Clone the main repository directly:
git clone https://github.com/BehindTheMusicTree/the-music-tree-api.git
cd the-music-tree-api- Python 3.14
- Docker and Docker Compose - Required for running the PostgreSQL database and Audio Fingerprinter containers
-
Clone the repository:
git clone https://github.com/BehindTheMusicTree/the-music-tree-api.git cd the-music-tree-api -
Set up environment variables:
Create a copy of the file
env/dev/.env.dev.templateasenv/.envand set the required values. See the Environment Variables section below for details on all required variables.Note: Environment variables are required for filesystem setup and running containers in the following steps.
-
Install system dependencies:
# Ubuntu/Linux sudo bash scripts/install-dependencies.sh # macOS # Install dependencies via Homebrew or use the Linux script as reference
This installs required system tools:
flac,ffmpeg,libchromaprint-tools,jq,postgresql-client -
Create and activate a virtual environment:
python -m venv .venv source .venv/bin/activate # (Linux/macOS) .venv\Scripts\activate # (Windows)
-
Install Python dependencies:
pip install -r requirements.txt
-
Set up filesystem:
bash scripts/setup-filesystem.sh
This creates necessary directories for:
- Static files
- Django logs
- Gunicorn logs (if app is exposed)
- Media files and libraries
- Temporary uploaded files
-
Run database and Audio Fingerprinter containers:
bash scripts/run-db-and-afp-containers.sh
This starts the required Docker containers:
- PostgreSQL database container
- Audio Fingerprinter (AFP) container
Note: Make sure Docker is running before running this script.
You need to set up several environment variables for development, build, and run.
Environment Variable Handling:
The application uses strict environment variable validation:
- Required variables: Must be set or the application will fail to start with a clear error message
- No fallbacks: Required environment variables do not have default values - they must be explicitly set
- Path validation: Path variables (like
MEDIA_DIR) are validated to ensure the directories exist - Type validation: Boolean and integer variables are validated for correct types
- Application data: Application data files (like reference data, fixtures) are stored relative to the codebase (
BASE_DIR) and do not require environment variables
Development:
Create a copy of the file env/dev/.env.dev.template as env/.env and set the values.
Build: The docker build requires the following environment variables:
APP_NAMEAPP_VERSIONTMP_UPLOADED_FILES_EXTERNALMEDIA_DIR_EXTERNALLIBRARIES_DIR_NAMESTATIC_FILES_EXTERNALSTATIC_FILES_INTERNALDJANGO_LOG_DIR_EXTERNALDJANGO_LOG_GENERAL_FILENAMEDJANGO_LOG_INFO_FILENAMEDJANGO_LOG_REQUESTS_FILENAMEDJANGO_LOG_REQUESTS_DEBUG_FILENAMEDJANGO_LOG_EXCEPTIONS_FILENAMEDJANGO_LOG_DJANGO_FILENAMEDJANGO_LOG_APP_FILENAMEGUNICORN_LOG_DIRGUNICORN_LOG_ERROR_FILENAMEGUNICORN_LOG_ACCESS_FILENAME
Running the container: Running the container requires the following environment variables:
DJANGO_SECRET_KEYACOUSTID_API_KEYCSRF_TRUSTED_ORIGINSALLOWED_HOSTSDB_CONTAINER_NAMEDB_PORT=5432DB_BODZIFY_API_DB_NAMEDB_BODZIFY_API_USERNAMEDB_BODZIFY_API_USER_PASSWORDAFP_CONTAINER_NAME(AFP meaning Audio FingerPrinter)AFP_PORTAFP_POST_ENDPOINT
Note: Application data files (like the reference genre tree) are stored in the data/ directory relative to the project root and are deployed with the codebase. They do not require environment variable configuration.
The Bodzify API requires a PostgreSQL database to function. The database runs in a Docker container, which is started by the run-db-and-afp-containers.sh script. This ensures a consistent development environment across all contributors.
For audio fingerprinting, the Bodzify API requires an app called Audio Fingerprinter. You can find the Audio Fingerprinter app on GitHub at the following link: Audio Fingerprinter
We follow strict Git Flow with the following branch structure:
- The production-ready, stable branch
- All tests must pass before merging
- Releases are tagged from
main - No direct commits allowed - All changes must go through Pull Requests, including changes from maintainers
- Only receives merges from
release/*andhotfix/*branches - Branch protection enforced - GitHub Actions automatically blocks PRs to
mainthat don't come fromhotfix/*orrelease/*branches (see.github/workflows/branch-protection.yml)
-- The integration branch for ongoing development
-- All feature and chore branches merge into develop
developis merged intomainvia release branches- No direct commits allowed - All changes must go through Pull Requests
-- Only receives merges from
feature/*,chore/*, anddependabot/*branches - Branch protection enforced - GitHub Actions automatically blocks PRs to
developthat don't come fromfeature/*,chore/*, ordependabot/*branches (see.github/workflows/branch-protection.yml)
- PRs to
mainmust come fromhotfix/*orrelease/*branches only. This ensures production fixes are traceable and carefully released. - PRs to
developmust come fromfeature/*,chore/*, ordependabot/*branches only. PRs from other branch types (e.g.,fix/*,refactor/*, etc.) will be blocked by the branch protection workflow. - Branch protection is enforced by the
branch-protection.ymlGitHub Actions workflow located at.github/workflows/branch-protection.yml.
-
Create one for each new feature or bug fix
-
Branch from
develop -
Include issue numbers when applicable:
feature/123-add-ogg-support -
Examples:
git checkout develop git pull origin develop git checkout -b feature/improve-genre-classification git checkout -b feature/123-add-ogg-support # With issue number git checkout -b feature/456-fix-id3v1-encoding # With issue number
-
Merge into
developvia Pull Request when complete and tested
-
For maintenance, infrastructure, and configuration work
-
Branch from
develop -
Include issue numbers when applicable:
chore/234-update-dependencies -
Examples: repository setup, CI/CD changes, dependency updates, documentation infrastructure
-
Examples:
git checkout develop git pull origin develop git checkout -b chore/github-setup git checkout -b chore/update-dependencies git checkout -b chore/234-update-dependencies # With issue number -
Merge into
developvia Pull Request when complete
-
Created from
developwhen preparing a new release -
Used for final testing, bug fixes, and version bumping
-
Examples:
git checkout develop git pull origin develop git checkout -b release/v0.2.1
-
Only bug fixes and release-related changes go into release branches
-
When ready, merge into both
main(for production) anddevelop(to keep develop up to date) -
Tag the release on
mainafter merging
-
For urgent bug fixes on production versions
-
Branch from
main -
Include issue numbers when applicable:
hotfix/789-critical-bug -
Examples:
git checkout main git pull origin main git checkout -b hotfix/critical-metadata-bug git checkout -b hotfix/789-critical-security-patch # With issue number -
Contributors can submit fixes via feature branches that maintainers may promote to hotfixes if needed
-
When complete, merge into both
main(for immediate production fix) anddevelop(to keep develop up to date)
-
For maintenance, infrastructure, and configuration work
-
Branch from
develop -
Include issue numbers when applicable:
chore/234-update-dependencies -
Examples: repository setup, CI/CD changes, dependency updates, documentation infrastructure
-
Examples:
git checkout develop git pull origin develop git checkout -b chore/github-setup git checkout -b chore/update-dependencies git checkout -b chore/234-update-dependencies # With issue number -
Merge into
developvia Pull Request when complete
- For automated dependency updates created by Dependabot
- Typically generated/managed by GitHub and follow a naming convention like
dependabot/<ecosystem>/<package>-<version>(e.g.,dependabot/pip/requests-2.28.0) - Branch from
develop - Dependabot opens Pull Requests that should target
developfor dependency bumps and security updates - Merge into
developvia Pull Request when complete; treat them likechore/*changes or dependency maintenance
See DEVELOPMENT.md for comprehensive coding standards and best practices.
We use pytest for all automated testing with Django.
# Run all tests
pytest
# Run tests for a specific module
pytest api/test/view/track/
# Run tests with coverage
pytest --cov=app --cov-report=html --cov-report=term-missing
# Run tests with verbose output
pytest -v
# Run a specific test file
pytest api/test/view/track/test_specific.pyTest Structure:
- Tests are located in
api/test/ - Follow the naming convention:
test_{scenario}_then_{expected_result} - Use
assertinstead ofassertEqual - Each test should focus on a single scenario
CI Testing:
- CI runs tests with fail-fast flag (
-x) - stops on first failure for faster feedback - Test results are published to GitHub Actions UI
- Tests run automatically on pushes to
main,develop,release/*,hotfix/*branches and pull requests
We follow a structured commit format inspired by Conventional Commits.
IMPORTANT: Always activate the project's virtual environment (.venv) before committing if you're using pre-commit hooks.
Quick reference:
- Format:
<type>(<scope>): <summary> - Activate virtual environment:
source .venv/bin/activate(Linux/macOS) or.venv\Scripts\activate(Windows)
Commit Types:
feat- New featurefix- Bug fixrefactor- Code restructuringdocs- Documentation updatechore- Maintenance / infrastructuretest- Adding or updating testsstyle- Formatting / lint-only changesci- CI/CD pipeline changes
Examples:
feat(track): add audio fingerprint supportfix(genre): handle duplicate genre namesdocs: update API documentationtest(track): add test for track uploadchore: update dependencies
Commit Message Guidelines:
- Use imperative mood ("Add…", "Fix…", "Update…")
- Keep summary under ~70 characters
- Include issue/ticket IDs when applicable (e.g.,
fix(#482): handle null values) - Be descriptive but concise
Before submitting a Pull Request, ensure the following checks are completed:
1. Code Quality
- ✅ Follow code style standards in DEVELOPMENT.md
- ✅ Code follows Django best practices
- ✅ Type hints are used where appropriate
- ✅ No debug statements or commented-out code
2. Tests
- ✅ All tests pass:
pytest - ✅ New features have corresponding tests
- ✅ Bug fixes include regression tests
- ✅ Tests follow the naming convention:
test_{scenario}_then_{expected_result} - ✅ Each test focuses on a single scenario
3. Documentation
- ✅ Update docstrings for new functions/classes (only when needed)
- ✅ Update README or other documentation if adding new features or changing behavior
- ✅ Add/update type hints where appropriate
- ✅ Update
CHANGELOG.mdwith your changes in the[Unreleased]section ⚠️ Update CONTRIBUTING.md only in exceptional cases
4. Git Hygiene
- ✅ Commit messages follow the commit message convention
- ✅ Branch is up to date with target branch (
developfor features,mainfor hotfixes) - ✅ No accidental commits (large files, secrets, personal configs)
- ✅ Branch follows naming convention (
feature/,chore/,hotfix/,release/)
5. Branch Target
- ✅ Feature branches target
developbranch (NOTmain- GitHub will block PRs tomainfrom feature branches) - ✅ Hotfix branches target
mainbranch - ✅ Release branches target both
mainanddevelop(maintainers only) - ✅ Chore branches target
developbranch (NOTmain)
Important: GitHub Actions automatically enforces that PRs to main can only come from hotfix/* or release/* branches. If you try to create a PR from a feature/* or chore/* branch to main, the CI will fail.
All Contributor Checks Plus:
1. Code Review
- ✅ Code follows project conventions and style
- ✅ Logic is sound and well-structured
- ✅ Error handling is appropriate
- ✅ Performance considerations addressed (if applicable)
- ✅ Django best practices are followed
2. Testing Verification
- ✅ CI tests pass on all platforms and Python versions
- ✅ Test coverage is adequate
- ✅ Edge cases are handled
- ✅ Integration with existing features works correctly
3. Documentation Review
- ✅ API changes are documented
- ✅ Breaking changes are clearly marked and documented
- ✅ Examples and usage are updated if needed
- ✅ Update CONTRIBUTING.md if changing development workflow
4. Compatibility Verification
- ✅ Breaking changes have proper versioning plan (major version bump)
- ✅ Backward compatibility maintained (unless intentional breaking change)
- ✅ Migration path documented for breaking changes
- ✅ Dependencies are up to date and compatible
5. Final Checks
- ✅ PR description is clear and complete
- ✅ All review comments are addressed
- ✅ No unresolved discussions
- ✅ Ready for release (if applicable)
- ✅ Branch targets correct base branch (
developfor features,mainfor hotfixes)
Before opening a Pull Request, ensure you have completed the Pre-PR Checklist above.
Pull Request titles must follow the same format as commit messages for consistency:
Format:
<type>(<optional-scope>): <short imperative description>
Allowed Types:
feat— new featurefix— bug fixrefactor— code restructuringdocs— documentation updatechore— maintenance / infrastructure (dependency updates, tooling setup, repository configuration)perf— performance improvementstyle— formatting / lint-only changesci— CI/CD pipeline changes (GitHub Actions workflows, CI configuration)test— adding or updating tests
Rules:
- Use imperative mood ("Add…", "Fix…", "Update…")
- Keep it under ~70 characters
- Include issue/ticket IDs when applicable (e.g.,
fix(#482): handle null values) - Avoid "WIP" in titles — use draft PRs instead
- Use lowercase for type and scope (e.g.,
feat(track):, notFeat(Track):)
Note on Branch Prefixes vs PR Title Types:
Branch prefixes (feature/, chore/, hotfix/, release/) are for branch organization and differ from PR title types:
- Branch
feature/add-flac-support→ PR title:feat: add flac support(usefeat, notfeature) - Branch
chore/update-dependencies→ PR title:chore: update dependencies(usechore) - Branch
hotfix/critical-bug→ PR title:fix: critical bug(usefix, nothotfix) - Branch
release/v0.2.1→ PR title:chore: prepare release v0.2.1(usechore)
Note on GitHub's Auto-Suggested Titles:
GitHub automatically generates PR titles based on branch names. GitHub's auto-suggested titles do not follow our convention, so you must rewrite them to match the standard format:
-
❌ GitHub suggestion:
Feature/add album artist tag support(from branchfeature/add-album-artist-tag-support) -
✅ Correct format:
feat(track): add album artist tag support -
❌ GitHub suggestion:
Chore/format code with ruff(from branchchore/format-code-with-ruff) -
✅ Correct format:
style: format code with ruff
Examples:
feat(track): add audio fingerprint supportfix(genre): correctly parse genre hierarchydocs: update contributing guidechore: update dependenciestest(track): add test for track uploadfix(#482): handle null search valuesstyle: format code with blackci: update GitHub Actions workflow
When opening a Pull Request, a template will be automatically provided. Ensure your PR description includes:
- ✅ Clear description of changes
- ✅ Reference related issues (e.g., "Fixes #123")
- ✅ Note any breaking changes
- ✅ Include testing instructions if applicable
- ✅ Specify the target branch (
developfor features,mainfor hotfixes)
Note: The PR template (.github/pull_request_template.md) will guide you through the process and ensure all necessary information is included.
If your PR includes breaking changes:
- ✅ Breaking changes are clearly documented in the PR description
- ✅ Migration path is provided (if applicable)
- ✅ Breaking changes include proper versioning notes (for maintainers to handle)
When you open a Pull Request, several automations will run automatically:
- Auto-labeling: Labels are automatically added based on files changed in your PR:
- Component labels: Automatically applied based on which parts of the codebase you've modified (e.g.,
track,artist,album,genre,tag,playlist,play,user,spotify,musicbrainz,audio-fingerprinting,filtering,middleware,serializer,model,view,exception,utils) - Type labels: Automatically applied based on file types (e.g.,
test,documentation,ci,dependencies,docker,scripts,migration,settings,admin,fixtures,logging,management,validator) - The labeler configuration is defined in
.github/labeler.ymland runs via the.github/workflows/labeler.ymlworkflow - Multiple labels can be applied to a single PR if it touches multiple areas
- Component labels: Automatically applied based on which parts of the codebase you've modified (e.g.,
- Manual labels: You should still add type labels (
bug,enhancement,feature) and priority labels manually, as these can't be determined from file paths - Auto-assignment: For contributor PRs (not maintainer PRs), reviewers are automatically assigned
- CI/CD checks: Automated tests run on your PR
- Welcome message: First-time contributors receive a welcome message with helpful links
These automations help streamline the review process and ensure consistency across the project.
Note: If you add a new feature or component, you can suggest updates to .github/labeler.yml via a PR to ensure future changes to that component are automatically labeled correctly.
The project uses focused, reusable GitHub Actions workflows for CI/CD:
Test Workflow (.github/workflows/test.yml):
- Runs automatically on pushes to
mainanddevelopbranches - Runs automatically on pull requests targeting
mainordevelop - Can be triggered manually via
workflow_dispatch - Executes the full test suite with pytest
- Publishes test results to GitHub Actions UI
Publish Workflow (.github/workflows/publish.yml):
- Runs automatically when version tags are pushed (e.g.,
v0.2.1) - Can be triggered manually via
workflow_dispatch - Orchestrates the release process:
- Collects and commits static files
- Builds and pushes Docker image to Docker Hub
- Deploys to the test server
Other Workflows:
build.yml- Builds and pushes Docker images (reusable)deploy.yml- Handles server deployment (reusable)static-files.yml- Collects and commits static files (reusable)branch-protection.yml- Enforces Git Flow branching ruleslabeler.yml- Automatically labels PRs based on changed files
Workflow Philosophy:
- Separation of concerns: Tests run on every change, publishing only on releases
- Reusability: Individual workflows can be called independently or as part of a pipeline
- Maintainability: Each workflow has a single, focused responsibility
- Flexibility: All workflows support manual triggering for debugging and testing
Releases are created from the main branch using strict Git Flow.
Quick release process:
-
Ensure
developis ready for release - All features for the release should be merged intodevelopgit checkout develop git pull origin develop
-
Create a release branch from
developgit checkout -b release/v0.2.1 git push origin release/v0.2.1
-
On the release branch, prepare the release:
-
Review and finalize
CHANGELOG.md:- Review changes in the
[Unreleased]section - Move content from
[Unreleased]section to new version entry with date (e.g.,## [v0.2.1] - 2025-01-15) - Review and consolidate entries if needed
- Leave the
[Unreleased]section empty (or with a placeholder) for future PRs
- Review changes in the
-
Make any final bug fixes or adjustments on the release branch
-
Ensure all tests pass:
pytest
-
-
Merge release branch into
maingit checkout main git pull origin main git merge --no-ff release/v0.2.1 git push origin main
-
Tag the release on
maingit tag v0.2.1 git push origin v0.2.1
Important: The tag version must match the version in
CHANGELOG.md(with thevprefix). -
Merge release branch back into
develop(to keep develop up to date)git checkout develop git pull origin develop git merge --no-ff release/v0.2.1 git push origin develop
-
Delete the release branch (locally and remotely)
git branch -d release/v0.2.1 git push origin --delete release/v0.2.1
-
CI/CD will automatically:
When you push the version tag (step 5), the
publish.ymlworkflow will automatically:- Collect and commit static files
- Build and push Docker image to Docker Hub
- Deploy to the test server
See the GitHub Actions Workflows section above for details on the workflow structure.
Hotfix Release Process:
For urgent production fixes:
-
Create hotfix branch from
main:git checkout main git pull origin main git checkout -b hotfix/critical-bug-fix
-
Make the fix and update
CHANGELOG.mdin the[Unreleased]section -
Merge hotfix into
main:git checkout main git merge --no-ff hotfix/critical-bug-fix git tag v0.2.2 # Increment patch version git push origin main --tags -
Merge hotfix into
develop:git checkout develop git merge --no-ff hotfix/critical-bug-fix git push origin develop
-
Delete the hotfix branch
All contributions are made under the project's Apache License 2.0.
You retain authorship of your code; the project retains redistribution rights under the same license. See the LICENSE file for details.
This project adheres to a Code of Conduct to ensure a welcoming and inclusive environment for all contributors. Please read and follow our Code of Conduct when participating in this project.
Our Code of Conduct is based on the Contributor Covenant, version 2.1. It outlines our expectations for behavior, unacceptable behavior, and how to report violations.
This project maintains a TODO list that tracks future work, improvements, and testing tasks. The TODO list is organized by priority and category:
- Features - New functionality and enhancements
- Testing & Quality - Test coverage, quality improvements, and validation
- Infrastructure - CI/CD, deployment, monitoring, and technical improvements
- Documentation - Documentation improvements and guides
Important Notes:
- Maintainers are responsible - Project maintainers are responsible for maintaining and updating the TODO list
- Contributors should NOT modify it - Contributors should not edit the TODO list directly
- Suggest tasks via issues - If you'd like to suggest a new task or work on an existing one, please open a GitHub issue first for discussion
- Updated during releases - Maintainers align and update the TODO list when releasing new versions based on project priorities, completed work, and community feedback
You can open:
- Issues → bug reports or new ideas
- Use the Bug Report template for reporting bugs
- Use the Feature Request template for suggesting new features
- Discussions → suggestions, architecture, or music-related topics
Let's make this API grow together 🌱