Search code examples
githubazure-functionsazure-python-sdk

Deployed Azure Python via github-actions does not find any package


When deployed via github-actions deploy.yaml

    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: 'Azure Login'
        uses: azure/login@v2
        with:
          client-id: ${{ env.ARM_CLIENT_ID }}
          subscription-id: ${{ env.ARM_SUBSCRIPTION_ID }}
          tenant-id: ${{ env.ARM_TENANT_ID }}
      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.9.20'
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt
      - name: 'Download Azure Function publishing profile'
        env:
          AZURE_SUBSCRIPTION_ID: ${{ env.ARM_SUBSCRIPTION_ID }}
          FUNCTION_APP_RESOURCE_GROUP: ${{ env.ARM_RESOURCE_GROUP_NAME }}
          FUNCTION_APP_NAME: fa-${{ env.APP_NAME }}
        run: |
          echo "FUNCTION_APP_PUB_PROFILE=$(az functionapp deployment list-publishing-profiles --subscription $AZURE_SUBSCRIPTION_ID --resource-group $FUNCTION_APP_RESOURCE_GROUP --name $FUNCTION_APP_NAME --xml)" >> $GITHUB_ENV
      - name: "Deploy function"
        uses: Azure/functions-action@v1
        with:
          app-name: fa-${{ env.APP_NAME }}
          publish-profile: ${{ env.FUNCTION_APP_PUB_PROFILE }}
          package: '.'
          

my python function function_app.py

import azure.functions as func
import logging

app = func.FunctionApp()

@app.timer_trigger(schedule="0 */1 * * * *", arg_name="myTimer", run_on_startup=True,
                   use_monitor=False)
def zsdbi(myTimer: func.TimerRequest) -> None:

    try:
        logging.info('36 Python timer trigger function executed.')
        import zsbiconfig
        import sftplib
        # import triggerfunc

        if myTimer.past_due:
            logging.info('The timer is past due!')

        config = zsbiconfig.MyConfig(azure=True)
        print('config.ftp_host:', config.ftp_host)
        print('config.ftp_username:', config.ftp_username)
        print('config.ftp_password:', config.ftp_password)

        # err = triggerfunc.triggerfunc(config)

    except Exception as e:
        logging.exception(e)

    return

does not find any package installed from requirements.txt

azure-functions
matplotlib
numpy
sftplib
pandas
python-dateutil
azure-identity
azure-keyvault-secrets
Office365-REST-Python-Client

The error message is :

2025-01-21T12:26:00Z   [Error]   No module named 'sftplib'
Traceback (most recent call last):
  File "/home/site/wwwroot/function_app.py", line 13, in zsdbi
    import sftplib
ModuleNotFoundError: No module named 'sftplib'

But the log of pip install ... performed on azure with the above deploy.yaml says :


Run python -m pip install --upgrade pip
  
Requirement already satisfied: pip in /home/runner/_work/_tool/Python/3.9.20/x64/lib/python3.9/site-packages (24.3.1)
Requirement already satisfied: azure-functions in /home/runner/_work/_tool/Python/3.9.20/x64/lib/python3.9/site-packages (from -r requirements.txt (line 5)) (1.21.3)
Requirement already satisfied: matplotlib in /home/runner/_work/_tool/Python/3.9.20/x64/lib/python3.9/site-packages (from -r requirements.txt (line 6)) (3.9.4)
Requirement already satisfied: numpy in /home/runner/_work/_tool/Python/3.9.20/x64/lib/python3.9/site-packages (from -r requirements.txt (line 7)) (2.0.2)
Requirement already satisfied: sftplib in /home/runner/_work/_tool/Python/3.9.20/x64/lib/python3.9/site-packages (from -r requirements.txt (line 8)) (0.0.2)

Note 1 When I install the dependencies in .python_packages/lib/site-packageswith :


      - name: Install dependencies
        run: |
          pushd './${{ env.AZURE_FUNCTIONAPP_PACKAGE_PATH }}'
          python -m pip install --upgrade pip
          pip install -r requirements.txt --target=".python_packages/lib/site-packages"

It works, but as all packages are now included in the zip file deployed to azure. The deploy takes n (minutes) longer which is somewhat annoying


Solution

  • You have to install packages in Virtual Environment.

    Add below steps in GitHub workflow(.yml file):

    1. Create and activate virtual environment
          - name: Create and start virtual environment
            run: |
              python -m venv venv
              source venv/bin/activate
    
    1. Install dependencies.
          - name: Install dependencies
            run: pip install -r requirements.txt
    

    Modify GitHub workflow as below:

    name: Build and deploy Python project to Azure Function App - functionAppName
    
    on:
      push:
        branches:
          - main
      workflow_dispatch:
    
    env:
      AZURE_FUNCTIONAPP_PACKAGE_PATH: '.' # set this to the path to your web app project, defaults to the repository root
      PYTHON_VERSION: '3.11' # set this to the python version to use (supports 3.6, 3.7, 3.8)
    
    jobs:
      build:
        runs-on: ubuntu-latest
        steps:
          - name: Checkout repository
            uses: actions/checkout@v4
    
          - name: Setup Python version
            uses: actions/setup-python@v1
            with:
              python-version: ${{ env.PYTHON_VERSION }}
    
          - name: Create and start virtual environment
            run: |
              python -m venv venv
              source venv/bin/activate
          - name: Install dependencies
            run: pip install -r requirements.txt
    
          - name: Zip artifact for deployment
            run: zip release.zip ./* -r
    
          - name: Upload artifact for deployment job
            uses: actions/upload-artifact@v3
            with:
              name: python-app
              path: |
                release.zip
                !venv/
      deploy:
        runs-on: ubuntu-latest
        needs: build
        environment:
          name: 'Production'
          url: ${{ steps.deploy-to-function.outputs.webapp-url }}
    
        steps:
          - name: Download artifact from build job
            uses: actions/download-artifact@v3
            with:
              name: python-app
    
          - name: Unzip artifact for deployment
            run: unzip release.zip
    
          - name: 'Deploy to Azure Functions'
            uses: Azure/functions-action@v1
            id: deploy-to-function
            with:
              app-name: 'functionappName'
              slot-name: 'Production'
              package: ${{ env.AZURE_FUNCTIONAPP_PACKAGE_PATH }}
              publish-profile: ${{ secrets.AZUREAPPSERVICE_PUBLISHPROFILE_5821AADXXX9CC06CD3FF7 }}
              scm-do-build-during-deployment: true
              enable-oryx-build: true
    

    Deployment Status in GitHub:

    enter image description here