You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 18:03:08