使用 GitHub Actions 部署到 Azure Functions

你可以使用 GitHub Actions 工作流,借助 Azure/functions-action 自动构建并将你的函数代码部署到 Azure。

要通过 GitHub Actions 部署,请完成以下三个关键步骤:

  1. 在 Azure 中创建一个用户分配的托管标识,为其配置一个信任你的 GitHub 存储库的联合凭据,并在你的函数应用上为其分配“网站参与者”角色。
  2. 在 GitHub 中添加身份的客户端 ID、租户 ID 和订阅 ID 作为仓库秘密
  3. 在你的仓库中添加一个工作流 YAML 文件,使用 azure/login 并通过 OpenID Connect(OIDC)进行身份验证,然后调用 Azure/functions-action 进行部署。

当你使用 Azure 门户启用 GitHub Actions 时,Functions 会自动执行这些任务,既在 Azure 订阅中,也在 GitHub 仓库中。

为Azure Functions创建工作流配置

你维护一个 YAML 文件(.yml),定义了仓库路径中的 /.github/workflows/ 工作流程配置。 此定义包含构成工作流的操作和参数,它们特定于函数的开发语言。

请使用文章顶部的选择器选择一种创建工作流程文件的方法:

方法 最适用于 OIDC 支持
工作流程模板 完全控制:复制OIDC准备好的模板并进行自定义 需要配置
Azure 门户 最简单的设置:门户可以帮你创建身份、凭证和工作流程文件 已为您配置
GitHub 市场 GitHub-first:从GitHub内置的市场模板开始 需要配置和模板修改

身份验证概述

GitHub Actions必须通过Azure认证才能部署你的代码。 本文使用OpenID Connect(OIDC),这是推荐的认证方法。 OIDC使用联邦凭证在你的GitHub仓库与Microsoft Entra中用户分配的托管身份之间建立信任关系。 GitHub 中没有存储任何秘密。

OIDC认证示例

以下内联示例展示了所有工作流模板中使用的核心OIDC认证和部署模式:

permissions:
  id-token: write
  contents: read

steps:
  - name: 'Login via OIDC'
    uses: azure/login@v3
    with:
      client-id: ${{ secrets.AZURE_CLIENT_ID }}
      tenant-id: ${{ secrets.AZURE_TENANT_ID }}
      subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

  - name: 'Deploy to Azure Functions'
    uses: Azure/functions-action@v1
    with:
      app-name: ${{ env.AZURE_FUNCTIONAPP_NAME }}
      package: ${{ env.AZURE_FUNCTIONAPP_PACKAGE_PATH }}

GitHub Actions OIDC 认证注意事项

  • OIDC 使用 工作负载身份联合 ,仅支持用户分配的托管身份。
  • 当你在 Azure 门户启用基于 GitHub Actions 的部署时,默认使用 OIDC 认证。
  • 在OIDC中,托管身份的客户端ID、租户ID和订阅ID都作为GitHub仓库的秘密存储。
  • 使用Azure基于角色的访问控制(Azure RBAC),仅限制访问部署所需的Azure资源。

先决条件

  • 具有活动订阅的 Azure 帐户。 创建帐户

  • 一个 GitHub 帐户。 如果没有该帐户,请注册免费版

  • Project GitHub仓库中的源代码。

  • 对 GitHub Actions 工作流程的基本了解。 如果你是 GitHub Actions 的新手,请参见《理解 GitHub Actions》。

  • 一个托管在Azure上的工作函数应用(仅代码或基于容器)。

  • (仅限容器部署)一个现有的容器注册表,比如 Azure 容器注册表

  • Azure CLI(进行本地开发时需要)。 还可以在Azure Cloud Shell中使用Azure CLI。

为 GitHub Actions 部署创建一个托管身份

OpenID Connect(OIDC)是 GitHub Actions 部署到 Azure Functions 的推荐认证方法。 使用 OIDC,你在 Azure 中配置用户分配的托管身份,并与你的 GitHub 仓库建立信任关系。 该工作流程可以直接通过 Azure 认证,而无需将凭证存储为秘密。

  1. 使用 az identity create 命令创建用户分配的托管标识:

    az identity create --name myGitHubDeployIdentity --resource-group <RESOURCE_GROUP> \
    --query "{clientId: clientId, tenantId: tenantId}" -o table
    

    <RESOURCE_GROUP> 替换为资源组的名称。

  2. 注意输出中的 clientIdtenantId 的值。 另外,获取你的订阅ID:

    az account show --query "{subId: id}" -o table
    

    你以后在GitHub添加凭证时需要这三个值。

  3. 使用 az role assignment create 命令,将 Website Contributor 角色分配给托管标识,并将作用域限定为你的函数应用:

    IDENTITY_PRINCIPAL=$(az identity show --name myGitHubDeployIdentity --resource-group <RESOURCE_GROUP> --query 'principalId' -o tsv)
    FUNCTION_APP_ID=$(az functionapp show --name <APP_NAME> --resource-group <RESOURCE_GROUP> --query 'id' -o tsv)
    az role assignment create --assignee $IDENTITY_PRINCIPAL --role "Website Contributor" --scope $FUNCTION_APP_ID
    

    分别将 <APP_NAME><RESOURCE_GROUP> 替换为你的应用名称和资源组名称。

  4. 使用 az identity federated-credential create 命令创建一个联合凭证,信任来自 GitHub 仓库的令牌:

    az identity federated-credential create \
        --identity-name myGitHubDeployIdentity \
        --resource-group <RESOURCE_GROUP> \
        --name github-deploy-credential \
        --issuer https://token.actions.githubusercontent.com \
        --subject repo:<GITHUB_ORG>/<REPO_NAME>:ref:refs/heads/<BRANCH_NAME> \
        --audiences api://AzureADTokenExchange
    

    <RESOURCE_GROUP><GITHUB_ORG><REPO_NAME><BRANCH_NAME> 替换为自定义值。 主题必须与触发你工作流程的分支相匹配。

  5. (可选)如果要从 Azure 容器注册表 部署容器,还需要将 acrpull 角色分配给托管标识:

    IDENTITY_PRINCIPAL=$(az identity show --name myGitHubDeployIdentity --resource-group <RESOURCE_GROUP> --query 'principalId' -o tsv)
    az role assignment create --assignee $IDENTITY_PRINCIPAL --role acrpull \
        --scope /subscriptions/<SUBSCRIPTION_ID>/resourceGroups/<RESOURCE_GROUP>/providers/Microsoft.ContainerRegistry/registries/<REGISTRY_NAME>
    

    <SUBSCRIPTION_ID><RESOURCE_GROUP><REGISTRY_NAME> 替换为你自己的值。

将凭据添加到GitHub

使用你 创建托管身份时复制的值。

  1. GitHub 中,转到存储库。

  2. 前往 设置>秘密与变量>操作

  3. 机密选项卡中,选择新建仓库机密

  4. 创建以下每个秘密:

    Name 价值
    AZURE_CLIENT_ID 托管标识的clientId
    AZURE_TENANT_ID 托管标识的tenantId
    AZURE_SUBSCRIPTION_ID 包含你功能应用的订阅ID

对于从私有注册表部署容器的情况,你还需要注册表专用的机密信息。 更多信息请参见 Docker 登录操作

通过模板创建工作流

手动创建工作流配置的最佳方式是通过官方支持的模板。

  1. 选择“Windows”或“Linux”,确保获取适用于正确操作系统的模板。

    部署到 Windows 时使用 runs-on: windows-latest。 容器化部署需要Linux。

  2. 使用Azure Functions动作仓库中针对特定语言的OIDC工作流模板。 将完整文件内容复制到你仓库中一个新命名 .github/workflows/deploy-function-app.yml 的文件中:

name: Build and deploy .NET project to Azure Function App using OIDC

on:
  push:
    branches: [ main ]
  workflow_dispatch:

env:
  AZURE_FUNCTIONAPP_NAME: 'APP_NAME'         # Set this to your function app name on Azure 
  AZURE_FUNCTIONAPP_PROJECT_PATH: '.'        # Set this to the path to your function app project, defaults to the repository root. The deploy action will package the contents of this path.
  DOTNET_VERSION: '10.0.x'                   # Set this to the .NET version of your project
  BUILD_ARTIFACT_NAME: 'released-package'    # Set this according to your team's naming convention

jobs:
  build:
    runs-on: windows-latest # Assumes your target function app is Windows-based
    permissions:
      id-token: write  # Required for OIDC
      contents: read   # Required for actions/checkout
    defaults:
      run:
        shell: bash
        working-directory: ${{ env.AZURE_FUNCTIONAPP_PROJECT_PATH }}
    steps:
      - name: 'Checkout repository'
        uses: actions/checkout@v6

      - name: 'Set up .NET version: ${{ env.DOTNET_VERSION }}'
        uses: actions/setup-dotnet@v5
        with:
          dotnet-version: ${{ env.DOTNET_VERSION }}

      # Perform additional steps such as running tests, if needed

      - name: 'Build and prepare .NET project for deployment'
        run: dotnet publish --configuration Release --output ./output

      - name: Upload artifact for the deployment job
        uses: actions/upload-artifact@v7
        with:
          name: ${{ env.BUILD_ARTIFACT_NAME }}
          path: ${{ env.AZURE_FUNCTIONAPP_PROJECT_PATH }}/output
          include-hidden-files: true  # Required for .NET projects

  deploy:
    runs-on: windows-latest # Assumes your target function app is Windows-based
    needs: build
    permissions:
      id-token: write  # Required for OIDC
    steps:
      - name: 'Download artifact from build job'
        uses: actions/download-artifact@v8
        with:
          name: ${{ env.BUILD_ARTIFACT_NAME }}
          path: '${{ env.AZURE_FUNCTIONAPP_PROJECT_PATH }}/downloaded-artifact'

      - name: 'Log in to Azure with AZ CLI'
        uses: azure/login@v3
        with:
          client-id: ${{ vars.AZURE_CLIENT_ID }}
          tenant-id: ${{ vars.AZURE_TENANT_ID }}
          subscription-id: ${{ vars.AZURE_SUBSCRIPTION_ID }}

      - name: 'Run the Azure Functions action'
        uses: Azure/functions-action@v1
        id: deploy-to-function-app
        with:
          app-name: ${{ env.AZURE_FUNCTIONAPP_NAME }}
          package: '${{ env.AZURE_FUNCTIONAPP_PROJECT_PATH }}/downloaded-artifact'	
  1. 在模板里更新 env: 项目变量。 每个模板都需要 AZURE_FUNCTIONAPP_NAME。 其他变量取决于你的语言:

    Variable Required Description
    AZURE_FUNCTIONAPP_NAME 是的 Azure中的函数应用名称
    DOTNET_VERSION 是的 你项目的 .NET 版本(例如,10.0.x
    AZURE_FUNCTIONAPP_PROJECT_PATH 你的项目文件夹路径。 默认:.(仓库根目录)
  2. OIDC 模板已包含带有 OIDC 身份验证的 azure/login 步骤。 验证 secrets.AZURE_CLIENT_IDsecrets.AZURE_TENANT_IDsecrets.AZURE_SUBSCRIPTION_ID 引用是否与你创建的 仓库密钥 匹配。

  3. 将此新 YAML 文件添加到存储库的 /.github/workflows/ 路径中。

在门户中创建工作流配置

当你用门户启用 GitHub Actions 时,Functions 会自动完成所有设置。 你不需要手动创建管理身份、配置凭证或编写工作流文件。 功能会帮你完成以下任务:

在您的Azure 订阅中:

  • 创建一个用户分配的托管标识,并在你的函数应用上为其分配 Website Contributor 角色。
  • 在托管身份中添加一个联合凭证,用于 GitHub OIDC 认证。

在您的GitHub仓库中:

  • 将客户端ID、订阅ID和租户ID值添加为GitHub Actions秘密。
  • 基于你的应用栈创建一个工作流文件并提交给 .github/workflows

创建函数应用期间

在 Azure 门户中创建函数时,可以通过“部署”选项卡快速开始使用 GitHub Actions。 若要在创建新的函数应用时添加 GitHub Actions 工作流,请执行以下操作:

  1. Azure 门户中,选择“创建函数应用”流中的“部署”。

  2. 如果你希望每个代码更新都触发到 Azure 门户的代码推送,请启用持续部署

  3. GitHub 设置中,选择授权以连接您的 GitHub 账户。 用拥有写入权限的 GitHub 账户登录你的仓库。

  4. 输入你的 GitHub 组织、存储库和分支。

  5. 可选地,选择 预览文件 ,查看工作流文件生成并添加到仓库前的样子。

  6. 完成函数应用的配置。 你的 GitHub 存储库现在包含 /.github/workflows/ 中的新工作流文件。

对于现有函数应用

要将 GitHub Actions 工作流添加到现有函数应用:

  1. Azure 门户中导航到函数应用并选择 Deployment Center

  2. 对于 Source 请选择 GitHub。 如果未看到默认消息 Building with GitHub Actions,请选择 Change provider选择 GitHub Actions 并选择 OK

  3. 如果尚未授权GitHub访问,请选择 Authorize。 提供GitHub凭据,然后选择 Sign in。 若要授权其他GitHub帐户,请选择 Change Account 并使用其他帐户登录。

  4. 选择 GitHub 组织仓库分支。 若要使用GitHub Actions进行部署,必须对此存储库具有写入访问权限。

  5. Authentication 设置中,选择是使用 GitHub Actions 用户分配的标识还是使用 Basic authentication 凭据进行身份验证。 对于基本身份验证,将使用当前凭据。

  6. 选择预览文件以查看将添加到GitHub 存储库中的工作流文件。

  7. 选择“保存”,将工作流文件添加到存储库。

创建工作流配置文件

可以直接从 GitHub 存储库通过 Azure Functions 模板创建 GitHub Actions 工作流配置文件。

  1. GitHub 中,转到存储库。

  2. 选择“操作”和“新建工作流”。

  3. 搜索函数

    搜索 GitHub Actions 函数模板的屏幕截图。

  4. 在显示的由 Azure 创作的函数应用工作流中,找到与代码语言匹配的工作流,然后选择“配置”。

  5. 在新创建的 YAML 文件中,将 env.AZURE_FUNCTIONAPP_NAME 参数更新为 Azure 中函数应用资源的名称。 你可能还需要更新设定应用所用语言版本的参数,比如DOTNET_VERSIONC#或PYTHON_VERSIONPython应用。

  6. 默认模板可能使用发布配置文件认证,而不是推荐的OIDC。 要切换到 OIDC 并与门户行为保持一致,请做出以下更改:

    • Azure/functions-action 中移除 publish-profilescm-do-build-during-deploymentenable-oryx-build 参数。

    • 如果存在,请从作业中移除该 environment 设置,因为联邦凭证主题必须与分支触发器匹配。

    • Azure/functions-action步骤前添加一个azure/login步骤:

      - name: 'Login via OIDC'
        uses: azure/login@v3
        with:
          client-id: ${{ secrets.AZURE_CLIENT_ID }}
          tenant-id: ${{ secrets.AZURE_TENANT_ID }}
          subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
      
      - name: 'Run Azure Functions Action'
        uses: Azure/functions-action@v1
        with:
          app-name: ${{ env.AZURE_FUNCTIONAPP_NAME }}
          package: ${{ env.AZURE_FUNCTIONAPP_PACKAGE_PATH }}
      
    • 为作业添加以下权限:

      permissions:
        id-token: write
        contents: read
      
  7. 确认新工作流文件保存时有合适的名称 /.github/workflows/ ,然后选择 提交更改

Azure Functions 操作

Azure Functions 操作 (Azure/functions-action) 定义你的代码如何发布到 Azure 中现有的函数应用或应用中的特定槽。

参数

下表描述了支持的 Azure/functions-action输入参数:

参数 Description
app-name (必修)你在 Azure 中函数应用的名称。
package (必填)要发布的项目的路径。 默认值:.(仓库中的所有文件)。
远程构建 将其设置为 true 可在部署到 Flex Consumption 应用时启用 Kudu 的生成操作。 Oryx 构建始终会执行;不要同时设置 scm-do-build-during-deploymentenable-oryx-build。 默认值:false
SCM-DO-部署期间构建 允许Kudu站点执行部署前操作,如 远程构建。 设置为 true 让Kudu在部署时构建你的项目。 默认值:false。 有关详细信息,请参阅 SCM_DO_BUILD_DURING_DEPLOYMENT
enable-oryx-build 允许Kudu通过使用 Oryx解决项目依赖。 将此项和 scm-do-build-during-deployment 都设置为 true,以使用 Oryx 而非工作流。 默认值:false。 仅限 Linux。
slot-name 要部署到的部署槽位。 默认:生产槽位。
publish-profile 包含你的发布配置文件的 GitHub 机密的名称。 使用推荐的OIDC认证时不需要。
sku 在 Flex Consumption 计划中使用 publish-profile 进行身份验证时,将其设置为 flexconsumption。 对于OIDC认证或其他托管计划来说,这就不需要了。
respect-pom-xml (仅限 Java)将其设置为 true,以从 pom.xml 中获取部署工件。 当 true 时,将 package 设置为 .。 默认值:false
respect-funcignore 设置为 true 以尊重你的 .funcignore 文件并排除列出的路径。 默认值:false

下表显示了每个托管计划支持的参数:

参数 Flex 消耗 弹性高级版 专属 消耗
app-name Required Required Required Required
package Required Required Required Required
远程构建 Optional
SCM-DO-部署期间构建 Optional Optional Optional
启用 Oryx 构建 可选(Linux) 可选(Linux) 可选(Linux)
slot-name 不支持 Optional Optional Optional
publish-profile 不推荐 不推荐 不推荐 不推荐
sku 仅发布个人资料
respect-pom-xml 可选(Java) 可选(Java) 可选(Java) 可选(Java)
respect-funcignore Optional Optional Optional Optional

部署方法

使用GitHub Actions时,部署方式取决于你的托管计划:

托管计划 部署方法
弹性高级版 将 Zip 部署到消耗应用
弹性高级版 Zip 部署
专用(应用服务) Zip 部署
消费 Windows: Zip 部署
Linux: 外部包 URL*

* 在 Linux 上以消耗计划运行应用的功能已计划停用。 有关详细信息,请参阅 Azure Functions 按需计划托管

有关详细信息,请参阅 Azure Functions 中的部署技术

后续步骤