Azure / Azure/azure-functions-core-tools
Better Monorepo Support for Python Function Apps
- Dominant language
- C#
- Stars
- 1.5k
- Forks
- 498
- Avg merge
- 4d 20h
- Merged PRs (30d)
- 14
Description
### Description
When deploying Python Azure Function Apps from a monorepo with shared internal packages, the current deployment process requires physically copying the code from the monorepo directory into the functionapp directory - I haven't found any other process that works.
Have just spent the afternoon trying to build a wheel from one directory and porting it into the other without luck:
1. Shell Environment Variable** ❌
```bash
export PIP_FIND_LINKS=".python_packages/wheels"
func azure functionapp publish ...
```
**Result**: Variable not passed to Azure remote build environment
2. App Setting with Relative Path** ❌
```bash
az functionapp config appsettings set ... --settings "PIP_FIND_LINKS=.python_packages/wheels"
```
**Result**:
```
WARNING: Location '.python_packages/wheels' is ignored: it is either a non-existing path or lacks a specific scheme.
```
3. App Setting with Absolute Path + file:// Scheme** ❌
```bash
az functionapp config appsettings set ... --settings "PIP_FIND_LINKS=file:///tmp/zipdeploy/extracted/.python_packages/wheels"
```
**Result**:
```
WARNING: Location 'file:///tmp/zipdeploy/extracted/.python_packages/wheels' is ignored: it is neither a file nor a directory.
```
## Any of the below would work for us
### Option 1: Support Relative Paths in Remote Build (Simplest)
Allow `requirements.txt` to contain relative paths that work during remote Oryx build, just like they do locally.
**Example:**
```
# requirements.txt
../../../shared/connect_to_database
fastapi==0.115.8
```
**Implementation suggestion:**
- Before running `pip install -r requirements.txt`, resolve relative paths and install them first
- Or: Copy referenced local packages into the build context before pip install
### Option 2: Support PEP 660 Editable Installs
Support modern Python packaging standards for local dependencies.
**Example:**
```
# requirements.txt
-e ../../../shared/connect_to_database
fastapi==0.115.8
```
**Current behavior:** Fails during remote build
**Desired behavior:** Recognize `-e` paths, copy source into build context, install as editable
### Option 3: Support `pyproject.toml` Workspace Dependencies
Recognize and support workspace-style dependencies in `pyproject.toml` (similar to Poetry workspaces, PDM, or npm workspaces).
**Example:**
```toml
# pyproject.toml in function app directory
[project]
dependencies = [
"fastapi==0.115.8",
"connect-to-database @ file://../../../shared/connect_to_database",
]
```
**Implementation suggestion:**
- Parse `pyproject.toml` during remote build
- Resolve `file://` paths relative to the project root
- Include referenced packages in the deployment bundle
### Option 4: Explicit Monorepo Configuration
Add a configuration option to specify monorepo layout and shared package locations.
**Example:**
```json
// .funcappconfig or similar
{
"monorepo": {
"root": "../../..",
"sharedPackages": [
"shared/connect_to_database"
]
}
}
```
Then allow normal package references in `requirements.txt`:
```
connect-to-database>=1.0.0
fastapi==0.115.8
```
## Real-World Use Case
**Repository structure:**
```
platform/
├── azure/
│ ├── global/
│ │ └── python/
│ │ └── connect_to_database/ # Shared package
│ │ ├── setup.py
│ │ └── connect_to_database/
│ └── project1/
│ └── functionapps/
│ └── funcapp1/
│ ├── requirements.txt
│ └── function_app.py
│ └── funcapp2/
│ ├── requirements.txt
│ └── function_app.py
│ └── project2/
│ └── functionapps/
│ └── funcapp3/ # Function app
│ ├── requirements.txt
│ └── function_app.py
```
**What should work but doesn't:**
```python
# requirements.txt in pubapi/
../../../global/python/connect_to_database
```
This works perfectly with `pip install -r requirements.txt` locally, but fails in Azure remote build.
## Impact
This affects **any organization using monorepos** with Azure Functions, which is increasingly common for:
- Microservices architectures with shared libraries
- Multi-tenant applications with shared utilities
- Data engineering platforms (our use case) with shared database/auth code
- Enterprise applications with shared business logic
## Comparison with Other Platforms
- **AWS Lambda (with SAM/CDK)**: Supports specifying local package paths in build configuration
- **Google Cloud Functions**: Can include local packages via build configuration
- **Vercel/Netlify**: Built-in monorepo support with workspace detection
- **Azure Static Web Apps**: Supports app-specific configuration in monorepos
Azure Functions should match or exceed these capabilities.
## Environment
- **Azure Functions Core Tools**: 4.0.5907
- **Python Version**: 3.12
- **Operating System**: Linux (GitHub Actions runners, local Ubuntu)
- **Deployment Method**: `func azure functionapp publish` with remote build
- **Build System**: Oryx 0.2.20251022.1
## Workaround Documentation
If this feature can't be implemented soon, please at least **document the official recommended approach** for monorepos. Currently, the documentation doesn't address this scenario at all.
Suggested documentation locations:
- https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference-python
- https://learn.microsoft.com/en-us/azure/azure-functions/functions-how-to-use-azure-function-app-settings
---
**Would you accept a PR for this feature?** Our team would be happy to contribute if you can provide guidance on the preferred approach.
Contributor guide
Research direction
Start at the `func azure functionapp publish` remote-build path and trace how `requirements.txt`, `pyproject.toml`, and local package paths are handled. First resolve which of the four proposed approaches is preferred; done should mean a documented or implemented monorepo workflow succeeds during remote Oryx builds without copying shared packages into the function app.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- azure, csharp, python
- Domain
- build-system, cli, cloud
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100