GitLab CI/CD部署Azure Functions无生效,但VSCode扩展部署正常的问题求助
GitLab CI/CD部署Azure Functions无生效,但VSCode扩展部署正常的问题求助
我用Python 3.9开发了一批Azure Functions,现在在GitLab仓库配置CI/CD时碰到了棘手的问题——这个仓库托管在Azure VM上,不确定这点是否相关。这些函数需要连接Azure PostgreSQL数据库,相关代码我会在后面贴出。
我的.gitlab-ci.yml配置了三个阶段的任务:前两个构建并部署React应用到Azure静态Web应用的流程完全正常,但第三个部署Functions的任务就出问题了:GitLab流水线显示执行成功,但Azure Function App的概览页面里完全看不到部署后的函数,而且任务日志里也没有任何报错信息。
但我用VSCode的Azure Functions Core Tools扩展直接部署时,一切都正常:函数会出现在概览页,能正常连接数据库并工作,本地运行测试也没有任何问题。
下面是涉及到的各部分代码,隐私相关的URL等信息已做脱敏处理:
.gitlab-ci.yml
stages: - build-react - deploy-react - deploy-functions # Build the React app build-react: stage: build-react image: registry.gitlab.com/static-web-apps/azure-static-web-apps-deploy script: - cd app-frontend - npm install - VITE_FUNCTIONS_BASE_URL=azurewebsites-url npx vite build artifacts: paths: - app-frontend/dist only: - main # Deploy the React app to Azure Static Web Apps deploy-react: stage: deploy-react image: registry.gitlab.com/static-web-apps/azure-static-web-apps-deploy script: - cd app-frontend - npm install -g @azure/static-web-apps-cli - swa deploy --env production --deployment-token token --output-location ./dist only: - main deploy-functions: stage: deploy-functions image: mcr.microsoft.com/azure-functions/python:3.0 # Azure Functions image script: - set -e - cd azure_functions # Navigate to the folder containing your Azure Function app - zip -r ../my-functions.zip . # Create a zip file of only the contents of the azure_functions folder - cd .. # Navigate back to the root directory - echo "Zipped successfully" - apt-get update && apt-get install -y ca-certificates curl apt-transport-https lsb-release gnupg - curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash - echo "Deploying to Azure..." - az login --service-principal -u $AZURE_CLIENT_ID -p $AZURE_CLIENT_SECRET --tenant $AZURE_TENANT_ID - az functionapp deployment source config-zip --resource-group $AZURE_RESOURCE_GROUP --name $AZURE_FUNCTIONAPP_NAME --src ./my-functions.zip only: - main
requirements.txt
azure-functions psycopg2-binary
function_app.py
import json import azure.functions as func import logging from datetime import datetime import psycopg2 import os # Database connection details DB_HOST = os.getenv("DB_HOST") DB_NAME = os.getenv("DB_NAME") DB_USER = os.getenv("DB_USER") DB_PASSWORD = os.getenv("DB_PASSWORD") DB_PORT = os.getenv("DB_PORT") app = func.FunctionApp(http_auth_level=func.AuthLevel.ANONYMOUS) @app.route(route="desks", methods=["GET"], auth_level=func.AuthLevel.ANONYMOUS) def getDesks(req: func.HttpRequest) -> func.HttpResponse: # Connect to database and fetch reservations for the given date try: connection = psycopg2.connect( host=DB_HOST, port=DB_PORT, database=DB_NAME, user=DB_USER, password=DB_PASSWORD, ) cursor = connection.cursor() # Query to get all desks query = """ SELECT d.id FROM desks d; """ cursor.execute(query) desks = cursor.fetchall() # Prepare the response data if desks: response_data = [{"id": desk[0]} for desk in desks] return func.HttpResponse( body=json.dumps(response_data), status_code=200, mimetype="application/json", ) else: return func.HttpResponse("No desks found", status_code=200) except Exception as e: logging.error(f"Error fetching desks: {str(e)}") return func.HttpResponse( "An error occurred while processing the request.", status_code=500 ) finally: if cursor: cursor.close() if connection: connection.close() @app.route(route="reservations", methods=["GET"], auth_level=func.AuthLevel.ANONYMOUS) def getReservationsForDate(req: func.HttpRequest) -> func.HttpResponse: # Get the date from the query parameter (expected format: YYYY-MM-DD) reservation_date = req.params.get("date") if not reservation_date: return func.HttpResponse( "Please provide a 'date' query parameter (YYYY-MM-DD).", status_code=400 ) try: # Convert string date to a date object for validation reservation_date = datetime.strptime(reservation_date, "%Y-%m-%d").date() except ValueError: return func.HttpResponse( "Invalid date format. Please provide a valid date in YYYY-MM-DD format.", status_code=400, ) # Connect to database and fetch reservations for the given date try: connection = psycopg2.connect( host=DB_HOST, port=DB_PORT, database=DB_NAME, user=DB_USER, password=DB_PASSWORD, ) cursor = connection.cursor() # Query to get all reservations for the provided date query = """ SELECT r.id, r.desk_id, r.reserved_by, r.reservation_date FROM reservations r WHERE r.reservation_date = %s; """ cursor.execute(query, (reservation_date,)) reservations = cursor.fetchall() # Prepare the response data if reservations: response_data = [ { "id": res[0], "desk_id": res[1], "reserved_by": res[2], "reservation_date": res[3].strftime("%Y-%m-%d"), } for res in reservations ] return func.HttpResponse( body=json.dumps(response_data), status_code=200, mimetype="application/json", ) else: return func.HttpResponse(body=json.dumps([]), status_code=200) except Exception as e: logging.error(f"Error fetching reservations: {str(e)}") return func.HttpResponse( "An error occurred while processing the request.", status_code=500 ) finally: if cursor: cursor.close() if connection: connection.close() @app.route( route="reservation-dates", methods=["GET"], auth_level=func.AuthLevel.ANONYMOUS ) def getDatesWithReservationForEmail(req: func.HttpRequest) -> func.HttpResponse: email = req.params.get("email") if not email: return func.HttpResponse( "Please provide an 'email' query parameter.", status_code=400 ) todays_date = datetime.today().date() # Connect to database and fetch dates in which the email provided has reservations try: connection = psycopg2.connect( host=DB_HOST, port=DB_PORT, database=DB_NAME, user=DB_USER, password=DB_PASSWORD, ) cursor = connection.cursor() # Query to get all reservations for the provided date query = """ SELECT r.reservation_date FROM reservations r WHERE r.reserved_by = %s AND r.reservation_date >= %s; """ cursor.execute(query, (email, todays_date)) reservation_dates = cursor.fetchall() # Prepare the response data if reservation_dates: response_data = [res[0].strftime("%Y-%m-%d") for res in reservation_dates] return func.HttpResponse( body=json.dumps(response_data), status_code=200, mimetype="application/json", ) else: return func.HttpResponse(body=json.dumps([]), status_code=200) except Exception as e: logging.error(f"Error fetching reservation dates for email {email}: {str(e)}") return func.HttpResponse( "An error occurred while processing the request.", status_code=500 ) finally: if cursor: cursor.close() if connection: connection.close() @app.route(route="reservations", methods=["POST"], auth_level=func.AuthLevel.ANONYMOUS) def reserveDesks(req: func.HttpRequest) -> func.HttpResponse: # Parse the JSON body request_body = req.get_json() if not request_body: return func.HttpResponse("Invalid or missing JSON body.", status_code=400) # Extract `userEmail` employee_email = request_body.get("employee") # Extract `reservations` reservations = request_body.get("reservations", []) # Validate presence of required fields if not employee_email or not reservations: return func.HttpResponse( "Missing 'employee' or 'reservations' in the JSON body.", status_code=400, ) # Database connection try: connection = psycopg2.connect( host=DB_HOST, port=DB_PORT, database=DB_NAME, user=DB_USER, password=DB_PASSWORD, ) # 原代码此处截断,保留现有内容 except Exception as e: logging.error(f"Error processing reservation: {str(e)}") return func.HttpResponse( "An error occurred while processing your reservation.", status_code=500 ) finally: if connection: connection.close()
备注:内容来源于stack exchange,提问作者110110010011
相关产品推荐
相关产品推荐

