แก้ไข

Deploy to Azure Functions by using GitHub Actions

You can use a GitHub Actions workflow to automatically build and deploy your function code to Azure by using the Azure/functions-action.

To deploy by using GitHub Actions, complete these three key steps:

  1. Create a user-assigned managed identity in Azure with a federated credential that trusts your GitHub repository, and assign it the Website Contributor role on your function app.
  2. Add the identity's client ID, tenant ID, and subscription ID as repository secrets in GitHub.
  3. Add a workflow YAML file to your repository that uses azure/login with OpenID Connect (OIDC) to authenticate, then calls Azure/functions-action to deploy.

When you use the Azure portal to enable GitHub Actions, Functions automatically performs these tasks, both in your Azure subscription and in your GitHub repository.

Create a workflow configuration for Azure Functions

You maintain a YAML file (.yml) that defines the workflow configuration in the /.github/workflows/ path in your repository. This definition contains the actions and parameters that make up the workflow, which is specific to the development language of your functions.

Choose a method for creating your workflow file using the selector at the top of the article:

Method Best for OIDC support
Workflow template Full control: copy an OIDC-ready template and customize it Requires configuration
Azure portal Easiest setup: portal can create the identity, credentials, and workflow file for you Configured for you
GitHub marketplace GitHub-first: start from GitHub's built-in marketplace templates Requires configuration and template modification

Authentication overview

GitHub Actions must authenticate with Azure to deploy your code. This article uses OpenID Connect (OIDC), which is the recommended authentication method. OIDC uses federated credentials to create a trust relationship between your GitHub repository and a user-assigned managed identity in Microsoft Entra. No secrets are stored in GitHub.

OIDC authentication example

The following inline example shows the core OIDC authentication and deployment pattern used in all workflow templates:

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 authentication considerations

  • OIDC uses workload identity federation and only supports user-assigned managed identities.
  • When you enable a GitHub Actions-based deployment in the Azure portal, OIDC authentication is used by default.
  • With OIDC, the managed identity's client ID, tenant ID, and subscription ID are stored as GitHub repository secrets.
  • Use Azure role-based access control (Azure RBAC) to limit access only to the Azure resources required for your deployment.

Prerequisites

  • An Azure account with an active subscription. Create an account for free.

  • A GitHub account. If you don't have one, sign up for free.

  • Project source code in a GitHub repository.

  • A basic understanding of GitHub Actions workflows. If you're new to GitHub Actions, see Understanding GitHub Actions.

  • A working function app hosted on Azure (code-only or container-based).

  • (Container deployments only) An existing container registry, such as Azure Container Registry.

  • Azure CLI, when developing locally. You can also use the Azure CLI in Azure Cloud Shell.

Create a managed identity for GitHub Actions deployment

OpenID Connect (OIDC) is the recommended authentication method for GitHub Actions deployments to Azure Functions. With OIDC, you configure a user-assigned managed identity in Azure and create a trust relationship with your GitHub repository. The workflow can then authenticate with Azure without storing credentials as secrets.

  1. Use the az identity create command to create a user-assigned managed identity:

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

    Replace <RESOURCE_GROUP> with the name of your resource group.

  2. From the output, note the clientId and tenantId values. Also get your subscription ID:

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

    You need these three values later when you add credentials to GitHub.

  3. Use the az role assignment create command to assign the Website Contributor role to the managed identity, scoped to your function app:

    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
    

    Replace <APP_NAME> and <RESOURCE_GROUP> with the names of your app and resource group, respectively.

  4. Use the az identity federated-credential create command to create a federated credential that trusts tokens from your GitHub repository:

    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
    

    Replace <RESOURCE_GROUP>, <GITHUB_ORG>, <REPO_NAME>, and <BRANCH_NAME> with your values. The subject must match the branch that triggers your workflow.

  5. (Optional) If you're deploying a container from Azure Container Registry, also assign the acrpull role to the managed identity:

    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>
    

    Replace <SUBSCRIPTION_ID>, <RESOURCE_GROUP>, and <REGISTRY_NAME> with your values.

Add credentials to GitHub

Use the values you copied when you created the managed identity.

  1. In GitHub, go to your repository.

  2. Go to Settings > Secrets and variables > Actions.

  3. On the Secrets tab, select New repository secret.

  4. Create each of the following secrets:

    Name Value
    AZURE_CLIENT_ID The clientId of the managed identity
    AZURE_TENANT_ID The tenantId of the managed identity
    AZURE_SUBSCRIPTION_ID The subscription ID that contains your function app

For container deployments from a private registry, you also need registry-specific secrets. For more information, see Docker Login Action.

Create the workflow from a template

The best way to manually create a workflow configuration is to start from the officially supported template.

  1. Choose either Windows or Linux to make sure that you get the template for the correct operating system.

    Deployments to Windows use runs-on: windows-latest. Containerized deployments require Linux.

  2. Use the language-specific OIDC workflow template from the Azure Functions actions repository. Copy the full file contents into a new file named .github/workflows/deploy-function-app.yml in your repository:

    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'
    
  3. In the template, update the env: variables for your project. Every template requires AZURE_FUNCTIONAPP_NAME. The other variables depend on your language:

    Variable Required Description
    AZURE_FUNCTIONAPP_NAME Yes Your function app name in Azure
    DOTNET_VERSION Yes The .NET version of your project (for example, 10.0.x)
    AZURE_FUNCTIONAPP_PROJECT_PATH No Path to your project folder. Default: . (repository root)
  4. The OIDC templates already include the azure/login step with OIDC authentication. Verify that the secrets.AZURE_CLIENT_ID, secrets.AZURE_TENANT_ID, and secrets.AZURE_SUBSCRIPTION_ID references match the repository secrets you created.

  5. Add this new YAML file in the /.github/workflows/ path in your repository.

Create the workflow configuration in the portal

When you use the portal to enable GitHub Actions, Functions handles all the setup automatically. You don't need to manually create a managed identity, configure credentials, or write a workflow file. Functions performs these tasks for you:

In your Azure subscription:

  • Creates a user-assigned managed identity and assigns it the Website Contributor role on your function app.
  • Adds a federated credential to the managed identity for GitHub OIDC authentication.

In your GitHub repository:

  • Adds the client ID, subscription ID, and tenant ID values as GitHub Actions secrets.
  • Creates a workflow file based on your application stack and commits it to .github/workflows.

During function app create

You can get started quickly with GitHub Actions through the Deployment tab when you create a function in Azure portal. To add a GitHub Actions workflow when you create a new function app:

  1. In the Azure portal, select Deployment in the Create Function App flow.

  2. Enable Continuous Deployment if you want each code update to trigger a code push to Azure portal.

  3. Under GitHub settings, select Authorize to connect your GitHub account. Sign in with the GitHub account that has write access to your repository.

  4. Enter your GitHub organization, repository, and branch.

  5. Optionally, select Preview file to view how the workflow file looks before it gets generated and added to your repository.

  6. Complete configuring your function app. Your GitHub repository now includes a new workflow file in /.github/workflows/.

For an existing function app

To add a GitHub Actions workflow to an existing function app:

  1. Go to your function app in the Azure portal and select Deployment > Deployment Center.

  2. Select Continuous Deployment (CI/CD). For Source, select GitHub. If you don't see the default message Building with GitHub Actions, select Change provider, choose GitHub Actions, and select OK.

  3. If you didn't already authorize GitHub access, select Authorize. Provide your GitHub credentials and select Sign in. To authorize a different GitHub account, select Change Account and sign in with another account.

  4. Select your GitHub Organization, Repository, and Branch. To deploy by using GitHub Actions, you must have write access to this repository.

  5. For Workflow option, select Add a workflow. This option creates a new workflow file in /.github/workflows/. To use an existing workflow, select Use available workflow and choose your workflow file.

  6. In Authentication settings, choose User-assigned identity to use OpenID Connect (OIDC), which is recommended because it doesn't require you to store secrets in GitHub. Select your subscription and the (New) suggested identity name. A new user-assigned managed identity is created and granted access to the Website Contributor role. If you use an existing identity, you must first grant it access to Website Contributor role.

    Important

    When you select Basic authentication, your publish profile, which contains shared secrets, is stored in GitHub Secrets. You must also enable SCM basic authentication, which makes your app less secure.

  7. Select Preview file to see the workflow file that gets added to your GitHub repository in .github/workflows/.

  8. Select Save to add the workflow file to your repository. Select the Logs tab to view the status of current and previous deployments.

Create the workflow configuration file

You can create the GitHub Actions workflow configuration file from the Azure Functions templates directly from your GitHub repository.

  1. In GitHub, go to your repository.

  2. Select Actions and New workflow.

  3. Search for functions.

    Screenshot of search for GitHub Actions functions templates.

  4. In the displayed functions app workflows authored by Microsoft Azure, find the one that matches your code language and select Configure.

  5. In the newly created YAML file, update the env.AZURE_FUNCTIONAPP_NAME parameter with the name of your function app resource in Azure. You might also need to update the parameter that sets the language version used by your app, such as DOTNET_VERSION for C# or PYTHON_VERSION for Python apps.

  6. The default templates might use publish profile authentication instead of the recommended OIDC. To switch to OIDC and align with portal behaviors, make the following changes:

    • Remove the publish-profile, scm-do-build-during-deployment, and enable-oryx-build parameters from Azure/functions-action.

    • Remove the environment setting from the job (if present), since the federated credential subject must match the branch trigger.

    • Add an azure/login step before the Azure/functions-action step:

      - 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 }}
      
    • Add the following permissions to the job:

      permissions:
        id-token: write
        contents: read
      
  7. Verify that the new workflow file is saved with an appropriate name in /.github/workflows/ and select Commit changes.

Azure Functions action

The Azure Functions action (Azure/functions-action) defines how your code is published to an existing function app in Azure, or to a specific slot in your app.

Parameters

The following table describes the input parameters supported by Azure/functions-action:

Parameter Description
app-name (Required) The name of your function app in Azure.
package (Required) The path to your project to publish. Default: . (all files in the repository).
remote-build Set to true to enable a build action from Kudu when deploying to a Flex Consumption app. Oryx build is always performed; don't also set scm-do-build-during-deployment or enable-oryx-build. Default: false.
scm-do-build-during-deployment Allow the Kudu site to perform pre-deployment operations such as remote builds. Set to true to have Kudu build your project during deployment. Default: false. For more information, see SCM_DO_BUILD_DURING_DEPLOYMENT.
enable-oryx-build Allow Kudu to resolve project dependencies by using Oryx. Set both this and scm-do-build-during-deployment to true to use Oryx instead of the workflow. Default: false. Linux only.
slot-name The deployment slot to deploy to. Default: production slot.
publish-profile The name of the GitHub secret that contains your publish profile. Not needed when using the recommended OIDC authentication.
sku Set to flexconsumption when authenticating with publish-profile on a Flex Consumption plan. Not needed with OIDC authentication or other hosting plans.
respect-pom-xml (Java only) Set to true to derive the deployment artifact from pom.xml. When true, set package to .. Default: false.
respect-funcignore Set to true to honor your .funcignore file and exclude listed paths. Default: false.

The following table shows which parameters are supported for each hosting plan:

Parameter Flex Consumption Elastic Premium Dedicated Consumption
app-name Required Required Required Required
package Required Required Required Required
remote-build Optional
scm-do-build-during-deployment Optional Optional Optional
enable-oryx-build Optional (Linux) Optional (Linux) Optional (Linux)
slot-name Not supported Optional Optional Optional
publish-profile Not recommended Not recommended Not recommended Not recommended
sku publish-profile only
respect-pom-xml Optional (Java) Optional (Java) Optional (Java) Optional (Java)
respect-funcignore Optional Optional Optional Optional

Deployment methods

When you use GitHub Actions, the deployment method depends on your hosting plan:

Hosting plan Deployment method
Flex Consumption One deploy
Elastic Premium Zip deploy
Dedicated (App Service) Zip deploy
Consumption Windows: Zip deploy
Linux: external package URL*

* The ability to run your apps on Linux in a Consumption plan is planned for retirement. For more information, see Azure Functions Consumption plan hosting.

For more information, see Deployment technologies in Azure Functions.

Next steps