ulint
A linter for Umbrel apps written in Python.
Features
- YAML Validation: validation of
umbrel-app.ymlandumbrel-app-store.ymlfiles - Docker Compose Validation: validation of Docker Compose files with security checks
- Directory Structure Validation: validation of proper app directory structure
- Security Checks: validation of potential security vulnerabilities
Installation
Installation via uv
# using uv tool
uv tool install ulint
# using uvx
uvx ulint --help
# using pipx
pipx install ulint
# using pip
pip install ulint
Build from Source
This project uses uv as the package manager. Make sure you have uv installed, then:
# Clone the repository
git clone http://github.com/Mr-Sunglasses/ulint
cd ulint
# Install dependencies
uv sync
# Install the package in development mode
uv pip install -e .
Usage
Command Line Interface
# Lint all apps in a directory
ulint lint /path/to/app-store
# Lint a specific app
umbrel-linter lint /path/to/app-store --app my-app
# Lint with specific options
umbrel-linter lint /path/to/app-store \
--log-level error \
--strict \
--skip-architectures \
--format json
Available Commands
lint: Main linting commandversion: Show version informationconfig: Show configuration information
Command Options
--app, -a: Specific app ID to lint--log-level, -l: Log level (error, warning, info)--strict, -s: Treat warnings as errors--skip-architectures: Skip checking Docker image architectures--new-submission: This is a new app submission--pr-url: Pull request URL for new submissions--store-type: App store type (official, community)--format, -f: Output format (rich, json, plain)--verbose, -v: Verbose output
Programmatic Usage
from umbrel_linter import UmbrelLinter
from umbrel_linter.core.models import LinterConfig, LintingContext
from pathlib import Path
# Create linter with configuration
config = LinterConfig(
check_image_architectures=True,
log_level="warning",
strict_mode=False
)
linter = UmbrelLinter(config)
# Lint a specific app
result = linter.lint_app(Path("/path/to/app-store"), "my-app")
# Check results
if result.has_errors():
print(f"Found {result.total_errors} errors")
for error in result.errors:
print(f"{error.severity}: {error.title} - {error.message}")
Configuration
The linter can be configured through the LinterConfig class:
from umbrel_linter.core.models import LinterConfig, Severity
config = LinterConfig(
check_image_architectures=True, # Check Docker image architectures
log_level=Severity.WARNING, # Minimum log level
strict_mode=False, # Treat warnings as errors
ignore_patterns=["*.tmp"] # File patterns to ignore
)
Error Types
The linter identifies various types of issues:
YAML Validation Errors
- Invalid YAML syntax
- Missing required fields
- Invalid field types
- Schema validation failures
Docker Compose Validation Errors
- Invalid image names and tags
- Security vulnerabilities (Docker socket mounting, root user)
- Invalid volume mounts
- Missing required files/directories
- Invalid port mappings
- Incorrect app proxy configuration
Directory Structure Errors
- Empty directories without
.gitkeepfiles - Missing required files
Security Warnings
- Docker socket mounting
- Root user usage
- Host network mode
- Insecure volume mounts
Development
Setting up Development Environment
# Install development dependencies
uv sync --dev
# Run tests
uv run pytest
# Run linting
uv run ruff check .
uv run black .
# Run type checking
uv run mypy .
Running Tests
# Run all tests
uv run pytest
# Run with coverage
uv run pytest --cov=umbrel_linter
# Run specific test file
uv run pytest tests/test_models.py
Code Quality
The project uses several tools for code quality:
- Black: Code formatting
- Ruff: Fast Python linter
- MyPy: Static type checking
- Pytest: Testing framework
Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests for new functionality
- Ensure all tests pass
- Submit a pull request
License
This project is licensed under the MIT License - see the LICENSE file for details.
Metadata
Release files for umbrel-linter 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| umbrel_linter-0.1.0.tar.gz | 93.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| umbrel_linter-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 127.5 kB
Release files / umbrel_linter-0.1.0.tar.gz
| Download URL | umbrel_linter-0.1.0.tar.gz |
|---|---|
| Size | 93.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1fbd5a5a80c4ad27871e27a5fffc68181f18f7ad1596f32d39f0fdb5ecce0d90
|
|
BLAKE2b-256 checksum How to use checksums |
d96145f4e84f5c8a7340fe76e8d1ce540ecc8e7c5f55d2c65296e4af0d9d4e7d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.5
|
Release files / umbrel_linter-0.1.0-py3-none-any.whl
| Download URL | umbrel_linter-0.1.0-py3-none-any.whl |
|---|---|
| Size | 34.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
aba94d98e6c4da0dda6e64c0ea953c5174f1e27bfb2761ba5c2d291c3a414b5a
|
|
BLAKE2b-256 checksum How to use checksums |
0b57efea80e97e1cf3aced3cfeaaf387e77d54de7b63181bc5d117a764f98c7f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.5
|