-
Notifications
You must be signed in to change notification settings - Fork 13
Development Guide
- Python 3.11+
- Node.js 18+ and npm 9+
- Git
git clone https://github.com/AbhishekMandapmalvi/AutoApply.git
cd AutoApply
# Create and activate virtual environment
python -m venv venv
# Windows:
venv\Scripts\activate
# macOS/Linux:
source venv/bin/activate
# Install Python dependencies (including dev extras)
pip install -e ".[dev]"
# Install Playwright Chromium
playwright install chromium
# Install Electron dependencies
cd electron
npm install
cd ..# Option 1: Run via Electron (full desktop experience)
cd electron && npm start
# Option 2: Run Flask backend standalone (for API development)
python run.py
# Option 3: Run with development bypass (no auth required)
AUTOAPPLY_DEV=1 python run.py# Run all tests
pytest tests/ -x -q
# Run with coverage
pytest tests/ --cov=app --cov=bot --cov=core --cov=config --cov=db --cov=routes -x -q
# Run a specific test file
pytest tests/test_api.py -x -q
# Run a specific test
pytest tests/test_api.py::test_health_endpoint -x -q
# Run with verbose output
pytest tests/ -vThe test suite contains 542+ tests covering bot, core, config, db, and routes modules at approximately 97% coverage.
Windows note: Exit code 15 is a known gevent signal-handling quirk on Windows and does not indicate a test failure. Always check the actual pass/fail counts in the test output.
| File | Tests | Scope |
|---|---|---|
tests/test_settings.py |
17 | Pydantic config models, load/save |
tests/test_database.py |
22 | SQLite CRUD, WAL mode, migrations |
tests/test_state.py |
29 | App state management, thread safety |
tests/test_api.py |
56 | Flask route handlers, auth, validation |
tests/test_integration.py |
8 | End-to-end API workflows |
tests/test_ai_engine.py |
25 | LLM provider calls, fallback |
tests/test_resume_renderer.py |
11 | PDF generation |
tests/test_filter.py |
35 | Job scoring, ATS detection |
tests/test_bot_base.py |
14 | BaseApplier, human-like behavior |
tests/test_bot_loop.py |
44 | Bot main loop, state transitions |
tests/test_bot_helpers.py |
31 | Bot utility functions |
tests/test_search_engines.py |
43 | LinkedIn/Indeed searchers |
tests/test_browser_manager.py |
21 | Playwright context management |
tests/test_appliers_ats.py |
19 | Greenhouse, Lever appliers |
tests/test_appliers_coverage.py |
73 | Applier edge cases, coverage boost |
tests/test_appliers_workday_ashby.py |
69 | Workday, Ashby appliers |
tests/test_scheduler.py |
25 | Schedule logic, timezone handling |
tests/test_app_detail.py |
15 | Application detail view API |
tests/test_login_api.py |
22 | Login browser API |
tests/test_quick_wins.py |
29 | Rate limiter, security headers |
tests/test_rate_limiter.py |
12 | Token bucket algorithm |
The tests/conftest.py file provides shared fixtures:
-
_dev_mode_auth_bypass(autouse) -- SetsAUTOAPPLY_DEV=1to bypass API auth in all tests. -
app-- Creates a Flask test application viacreate_app(). -
client-- Flask test client. -
tmp_path-- Used for filesystem tests to avoid polluting real data directories. -
mock_db-- In-memory SQLite database for test isolation.
AutoApply uses Ruff for Python formatting and linting:
# Check for lint errors
ruff check .
# Auto-fix lint errors
ruff check . --fix
# Format code
ruff format .
# Check formatting without modifying
ruff format . --checkStatic type checking with mypy:
mypy app.py app_state.py run.py config/ core/ db/ bot/ routes/The project uses pre-commit with Ruff hooks configured in .pre-commit-config.yaml:
# Install pre-commit hooks
pre-commit install
# Run all hooks on all files (manual check)
pre-commit run --all-filesHooks run automatically on every git commit:
- ruff-format -- Ensures consistent code formatting.
- ruff -- Checks for lint errors with auto-fix.
The project uses GitHub Actions with 3 jobs that run on every push and pull request:
- Runs
ruff check .andruff format . --check. - Runs
mypyon all source modules.
- Sets up Python 3.11.
- Installs dependencies from
pyproject.toml. - Runs
pytest tests/ -x -q --tb=short. - Reports test results and coverage.
- Runs
pip-auditto check for known vulnerabilities in dependencies. - Checks for hardcoded secrets or sensitive patterns.
All three jobs must pass for a PR to be mergeable.
AutoApply/
├── app.py # create_app() factory, Flask app setup
├── app_state.py # Shared application state singleton
├── run.py # Entry point: starts Flask+SocketIO server
├── pyproject.toml # Python project metadata, dependencies
├── config/
│ └── settings.py # Pydantic v2 config models, load/save
├── core/
│ ├── ai_engine.py # Multi-provider LLM integration
│ ├── filter.py # Job scoring, ATS detection
│ ├── scheduler.py # Time-based bot scheduling
│ ├── resume_renderer.py # PDF resume generation
│ └── i18n.py # Backend internationalization
├── db/
│ └── database.py # SQLite database operations
├── bot/
│ ├── bot.py # Main bot loop
│ ├── browser.py # Playwright browser manager
│ ├── state.py # Bot state machine
│ ├── search/
│ │ ├── base.py # BaseSearcher ABC, RawJob
│ │ ├── linkedin.py # LinkedIn searcher
│ │ └── indeed.py # Indeed searcher
│ └── apply/
│ ├── base.py # BaseApplier ABC, ApplyResult
│ ├── linkedin.py # LinkedIn Easy Apply
│ ├── indeed.py # Indeed Quick Apply
│ ├── greenhouse.py # Greenhouse ATS
│ ├── lever.py # Lever ATS
│ ├── workday.py # Workday ATS
│ └── ashby.py # Ashby ATS
├── routes/
│ ├── bot.py # Bot blueprint
│ ├── applications.py # Applications blueprint
│ ├── config.py # Config blueprint
│ ├── profile.py # Profile blueprint
│ ├── analytics.py # Analytics blueprint
│ ├── login.py # Login blueprint
│ └── lifecycle.py # Lifecycle blueprint
├── templates/
│ └── index.html # SPA shell (Jinja2)
├── static/
│ ├── css/main.css # Application styles
│ ├── js/ # 17 ES modules
│ │ ├── app.js # Entry point
│ │ ├── api.js # API client
│ │ ├── i18n.js # Frontend i18n
│ │ ├── dashboard.js # Dashboard tab
│ │ ├── applications.js # Applications tab
│ │ ├── config.js # Settings tab
│ │ └── ... # Other modules
│ └── locales/
│ └── en.json # English translations
├── electron/
│ ├── main.js # Electron main process
│ ├── python-backend.js # Flask child process manager
│ ├── package.json # Electron dependencies
│ └── build/ # electron-builder config
├── tests/
│ ├── conftest.py # Shared fixtures
│ ├── test_api.py # Route tests
│ ├── test_bot_loop.py # Bot tests
│ └── ... # Other test files
└── .github/
└── workflows/ # CI pipeline definitions
-
Blueprints in
routes/: Each Blueprint handles one domain area. Shared state lives inapp_state.py, not in blueprint modules. -
create_app()factory: All app setup happens inapp.py :: create_app(). This pattern supports test isolation (each test gets a fresh app). -
Pydantic models: All configuration uses Pydantic v2 models in
config/settings.py. No raw dict access for config data. -
ABC pattern: Search engines extend
BaseSearcher; appliers extendBaseApplier. Both define the contract inbase.py.
-
Choose the blueprint in
routes/(or create a new one if the domain warrants it). -
Add the route:
@bp.route('/api/example', methods=['GET']) def get_example(): return jsonify({"data": "value"})
-
Add tests in the corresponding test file:
def test_get_example(client): resp = client.get('/api/example') assert resp.status_code == 200 assert resp.json['data'] == 'value'
-
Add i18n strings if the endpoint returns user-facing messages:
- Add key to
static/locales/en.json. - Use
t("key")fromcore/i18n.pyin the route.
- Add key to
-
Update the API reference documentation if the endpoint is public.
-
Create the applier in
bot/apply/:# bot/apply/myats.py from bot.apply.base import BaseApplier, ApplyResult class MyATSApplier(BaseApplier): async def apply(self, page, job, resume_path, cover_letter): # Fill form fields using self._human_type() # Click buttons with self._random_pause() # Return ApplyResult(success=True/False, message="...") pass
-
Register in APPLIERS dict (
bot/bot.py):from bot.apply.myats import MyATSApplier APPLIERS = { # ... existing entries "myats": MyATSApplier, }
-
Add URL fingerprint (
core/filter.py):ATS_FINGERPRINTS = { # ... existing entries "myats.example.com": "myats", }
-
Write tests in
tests/test_appliers_*.py:- Test form filling with mocked Playwright page.
- Test error handling (form not found, submission failure, captcha).
- Test human-like delay behavior.
-
Update documentation and the supported platforms table.
-
Branch from master:
git checkout master git pull git checkout -b feature/my-feature
-
Make changes, committing frequently with descriptive messages.
-
Run checks before pushing:
ruff check . ruff format . --check pytest tests/ -x -q
-
Push and open a PR:
git push -u origin feature/my-feature gh pr create --title "Add my feature" --body "Description..."
-
Required checks: All three CI jobs (lint, test, security) must pass.
-
Merge: Squash-merge to master once approved and all checks pass.
For contribution guidelines, code of conduct, and additional details, see CONTRIBUTING.md in the repository root.
AutoApply Wiki
User Guide
Technical
Build & Deploy
Project