Reputation: 1172
I'm trying to deploy a handful of Python functions into my consumption plan based Function App using Azure DevOps YAML pipeline.
Despite following all the advice found here: https://learn.microsoft.com/en-us/azure/azure-functions/recover-python-functions?tabs=manual%2Cbash&pivots=python-mode-configuration#enable-remote-build
I was still unable to: (a) See why the requirements.txt in the root of the project was being ignored and (b) Work out why, when I download my package from the URL provided at the APPLICATION_SETTINGS -> WEBSITE_RUN_FROM_PACKAGE variable there was in fact no .python_packages directory there at all.
This was despite setting SCM_DO_BUILD_DURING_DEPLOYMENT and ENABLE_ORYX_BUILD to True.
After hours of scrabbling around I eventually discovered a potential solution, which was to install the dependencies right there in the DevOps pipeline with:
steps:
- task: UsePythonVersion@0
displayName: "Use Python 3.10"
inputs:
versionSpec: 3.10
- bash: |
pip install --target="./.python_packages/lib/site-packages" -r ./requirements.txt
workingDirectory: $(workingDirectory)
displayName: "Install application dependencies"
Prior to then creating and publishing the archive, which is then consumed by the AzureFunctionApp@2 action to deploy it.
Is this the correct way to accomplish this? The Python Functions documentation seems to suggest that the requirements.txt should be processed during the build, but it absolutely is not.
Where I am stuck is in trying to understand what that step is actually doing. Am I correct in saying it is installing the dependencies into the Python instance on the DevOps Agent just for the purposes of the agents own .python_packages folder, post install, to be copied into the artifact which is then deployed? Is that the case?
Fundamentally, my question is: Isn't there a better way?
Thanks!
Upvotes: 3
Views: 5768
Reputation: 8157
Is this the correct way to accomplish this? The Python Functions documentation seems to suggest that the requirements.txt should be processed during the build, but it absolutely is not.
Yes, The requirements.txt packages needs to be installed in the DevOps agent and then the build artifact with the packages are deployed to the Function app for the Function Trigger to work. Even the Default Azure DevOps yaml code to Deploy the Python Function has separate pip install step to install packages. Refer below:-
I have used the Template below and selected my Function app and path set to - $(System.DefaultWorkingDirectory)
My Azure DevOps yaml script:-
trigger:
- master
variables:
azureSubscription: 'xxxxxxxxxx354dd'
# Function app name
functionAppName: 'siliconfunc76'
# Agent VM image name
vmImageName: 'ubuntu-latest'
# Working Directory
workingDirectory: '$(System.DefaultWorkingDirectory)'
stages:
- stage: Build
displayName: Build stage
jobs:
- job: Build
displayName: Build
pool:
vmImage: $(vmImageName)
steps:
- bash: |
if [ -f extensions.csproj ]
then
dotnet build extensions.csproj --runtime ubuntu.16.04-x64 --output ./bin
fi
workingDirectory: $(workingDirectory)
displayName: 'Build extensions'
- task: UsePythonVersion@0
displayName: 'Use Python 3.10'
inputs:
versionSpec: 3.10 # Functions V2 supports Python 3.6 as of today
- bash: |
pip install --target="./.python_packages/lib/site-packages" -r ./requirements.txt
workingDirectory: $(workingDirectory)
displayName: 'Install application dependencies'
- task: ArchiveFiles@2
displayName: 'Archive files'
inputs:
rootFolderOrFile: '$(workingDirectory)'
includeRootFolder: false
archiveType: zip
archiveFile: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
replaceExistingArchive: true
- publish: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
artifact: drop
- stage: Deploy
displayName: Deploy stage
dependsOn: Build
condition: succeeded()
jobs:
- deployment: Deploy
displayName: Deploy
environment: 'development'
pool:
vmImage: $(vmImageName)
strategy:
runOnce:
deploy:
steps:
- task: AzureFunctionApp@1
displayName: 'Azure functions app deploy'
inputs:
azureSubscription: '$(azureSubscription)'
appType: functionAppLinux
appName: $(functionAppName)
package: '$(Pipeline.Workspace)/drop/$(Build.BuildId).zip'
Output:-
All the package dependencies are installed in the Build step where Function is built on Azure DevOps agent like below:-
Those packages are Archived as an artifact like below:-
Then the Archived folder is published as an Artifact like below:-
In the next stage those Published artifact is Downloaded and Deployed in the Function App like below:-
Above method is the Ideal and efficient method for now to Deploy the Function app.
You can only build the Function app with the Build step and use Release pipeline to Deploy the Function App via Release Refer my SO thread answer1 for the same.
Alternatively you can Refer My YAML script from this SO thread answer2 where I have utilized
func azure functionapp publish functionappname --python
And installed the dependencies with pip install
in the same build step.
To Deploy FunctionV2 using Azure DevOps refer my SO thread answer3.
Upvotes: 7