Raw New Markdown
Generating updated version of doc...
Rendered New Markdown
Generating updated version of doc...
---
title: Deploy to Azure Functions by using GitHub Actions
description: Set up continuous deployment for your Azure Functions app by using GitHub Actions with OpenID Connect (OIDC) authentication.
ms.topic: how-to
ms.date: 08/28/2026
ms.custom: devx-track-csharp, github-actions-azure
zone_pivot_groups: github-actions-deployment-options
---
# Deploy to Azure Functions by using GitHub Actions
You can use a [GitHub Actions workflow](https://docs.github.com/actions/learn-github-actions/introduction-to-github-actions#the-components-of-github-actions) to automatically build and deploy your function code to Azure by using the [`Azure/functions-action`](https://github.com/Azure/functions-action).
To deploy by using GitHub Actions, complete these three key steps:
1. [Create a user-assigned managed identity](#create-a-managed-identity-for-github-actions-deployment) in Azure with a federated credential that trusts your GitHub repository, and assign it the Website Contributor role on your function app.
1. Add the identity's client ID, tenant ID, and subscription ID as [repository secrets](https://docs.github.com/actions/security-guides/using-secrets-in-github-actions) in GitHub.
1. 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.
::: zone pivot="method-portal"
When you [use the Azure portal](./functions-how-to-github-actions.md?pivots=method-portal) to enable GitHub Actions, Functions automatically performs these tasks, both in your Azure subscription and in your GitHub repository.
::: zone-end
## 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:
```yml
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](/entra/workload-id/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](https://azure.microsoft.com/pricing/purchase-options/azure-account?cid=msft_learn).
+ A GitHub account. If you don't have one, sign up for [free](https://github.com/join).
+ 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](https://docs.github.com/actions/about-github-actions/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/container-registry/container-registry-get-started-azure-cli).
::: zone pivot="method-manual,method-template"
+ [Azure CLI](/cli/azure/install-azure-cli), when developing locally. You can also use the Azure CLI in Azure Cloud Shell.
::: zone-end
::: zone pivot="method-manual,method-template"
## 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](/cli/azure/identity#az-identity-create) command to create a user-assigned managed identity:
```azurecli
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.
1. From the output, note the `clientId` and `tenantId` values. Also get your subscription ID:
```azurecli
az account show --query "{subId: id}" -o table
```
You need these three values later when you [add credentials to GitHub](#add-credentials-to-github).
1. Use the [az role assignment create](/cli/azure/role/assignment#az-role-assignment-create) command to assign the [`Website Contributor`](/azure/role-based-access-control/built-in-roles/web-and-mobile#website-contributor) role to the managed identity, scoped to your function app:
```azurecli
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.
1. Use the [az identity federated-credential create](/cli/azure/identity/federated-credential#az-identity-federated-credential-create) command to create a federated credential that trusts tokens from your GitHub repository:
```azurecli
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.
1. (Optional) If you're deploying a container from Azure Container Registry, also assign the `acrpull` role to the managed identity:
```azurecli
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](#create-a-managed-identity-for-github-actions-deployment).
1. In [GitHub](https://github.com/), go to your repository.
1. Go to **Settings** > **Secrets and variables** > **Actions**.
1. On the **Secrets** tab, select **New repository secret**.
1. 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](https://github.com/marketplace/actions/docker-login#usage).
::: zone-end
::: zone pivot="method-manual"
## 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.
### [Windows](#tab/windows)
Deployments to Windows use `runs-on: windows-latest`. Containerized deployments require Linux.
### [Linux](#tab/linux)
Deployments to Linux use `runs-on: ubuntu-latest`. Use Linux for containerized deployments.
---
1. 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:
### [.NET](#tab/dotnet/windows)
:::code language="yml" source="~/azure-actions-workflow-samples/FunctionApp/oidc-auth-samples/windows-dotnet-functionapp-on-azure-oidc.yml" range="1-2,24-90":::
### [.NET](#tab/dotnet/linux)
:::code language="yml" source="~/azure-actions-workflow-samples/FunctionApp/oidc-auth-samples/linux-dotnet-functionapp-on-azure-oidc.yml" range="1-2,24-90":::
### [Java](#tab/java/windows)
:::code language="yml" source="~/azure-actions-workflow-samples/FunctionApp/oidc-auth-samples/windows-java-functionapp-on-azure-oidc.yml" range="1-2,22-90":::
### [Java](#tab/java/linux)
:::code language="yml" source="~/azure-actions-workflow-samples/FunctionApp/oidc-auth-samples/linux-java-functionapp-on-azure-oidc.yml" range="1-2,22-90":::
### [JavaScript](#tab/javascript/windows)
:::code language="yml" source="~/azure-actions-workflow-samples/FunctionApp/oidc-auth-samples/windows-node-functionapp-on-azure-oidc.yml" range="1-2,22-95":::
### [JavaScript](#tab/javascript/linux)
:::code language="yml" source="~/azure-actions-workflow-samples/FunctionApp/oidc-auth-samples/linux-node-functionapp-on-azure-oidc.yml" range="1-2,22-95":::
### [Python](#tab/python/windows)
Python functions aren't supported on Windows. Choose Linux instead.
### [Python](#tab/python/linux)
:::code language="yml" source="~/azure-actions-workflow-samples/FunctionApp/oidc-auth-samples/python-functionapp-on-azure-oidc.yml" range="1-2,22-88":::
### [PowerShell](#tab/powershell/windows)
:::code language="yml" source="~/azure-actions-workflow-samples/FunctionApp/oidc-auth-samples/powershell-functionapp-on-azure-oidc.yml" range="1-2,22-57":::
### [PowerShell](#tab/powershell/linux)
PowerShell functions aren't supported on Linux. Choose Windows instead.
### [Container](#tab/container/windows)
Container deployments aren't supported on Windows. Choose Linux instead.
### [Container](#tab/container/linux)
:::code language="yml" source="~/azure-actions-workflow-samples/FunctionApp/linux-container-functionapp-on-azure.yml" range="1-2,9-57":::
> [!IMPORTANT]
> For new container-based function app deployments, use the native Azure Container Apps hosting model. See [Deploy to Azure Container Apps with GitHub Actions](/azure/container-apps/github-actions). The `Azure/functions-container-action` shown here deploys container images to existing function app resources in Azure.
Before you use this YAML file, complete the following steps:
+ Update the values of `REGISTRY`, `NAMESPACE`, `IMAGE`, and `TAG` based on your container registry.
+ Update the container repository credentials in the `docker/login-action` action.
---
1. In the template, update the `env:` variables for your project. Every template requires `AZURE_FUNCTIONAPP_NAME`. The other variables depend on your language:
### [.NET](#tab/dotnet)
| 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) |
### [Java](#tab/java)
| Variable | Required | Description |
| ---- | :-: | ---- |
| `AZURE_FUNCTIONAPP_NAME` | Yes | Your function app name in Azure. Must match `functionAppName` in pom.xml. |
| `JAVA_VERSION` | Yes | The Java version of your project (for example, `21`) |
| `POM_XML_DIRECTORY` | No | Path to the directory containing pom.xml. Default: `.` (repository root) |
### [JavaScript](#tab/javascript)
| Variable | Required | Description |
| ---- | :-: | ---- |
| `AZURE_FUNCTIONAPP_NAME` | Yes | Your function app name in Azure |
| `NODE_VERSION` | Yes | The Node.js version of your project (for example, `22`) |
| `AZURE_FUNCTIONAPP_PROJECT_PATH` | No | Path to your project folder. Default: `.` (repository root) |
### [Python](#tab/python)
| Variable | Required | Description |
| ---- | :-: | ---- |
| `AZURE_FUNCTIONAPP_NAME` | Yes | Your function app name in Azure |
| `PYTHON_VERSION` | Yes | The Python version of your project (for example, `3.13.x`) |
| `AZURE_FUNCTIONAPP_PROJECT_PATH` | No | Path to your project folder. Default: `.` (repository root) |
### [PowerShell](#tab/powershell)
| Variable | Required | Description |
| ---- | :-: | ---- |
| `AZURE_FUNCTIONAPP_NAME` | Yes | Your function app name in Azure |
| `AZURE_FUNCTIONAPP_PROJECT_PATH` | No | Path to your project folder. Default: `.` (repository root) |
### [Container](#tab/container)
| Variable | Required | Description |
| ---- | :-: | ---- |
| `AZURE_FUNCTIONAPP_NAME` | Yes | Your function app name in Azure |
| `REGISTRY` | Yes | Your container registry login server (for example, `contoso.azurecr.io`) |
| `NAMESPACE` | Yes | The namespace/repository in your registry |
| `IMAGE` | Yes | The container image name |
| `TAG` | Yes | The image tag (for example, `${{ github.sha }}`) |
---
1. 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](#add-credentials-to-github).
1. Add this new YAML file in the `/.github/workflows/` path in your repository.
::: zone-end
::: zone pivot="method-portal"
## 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](/azure/role-based-access-control/built-in-roles/web-and-mobile#website-contributor) 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.
1. Enable **Continuous Deployment** if you want each code update to trigger a code push to Azure portal.
1. Under **GitHub settings**, select **Authorize** to connect your GitHub account. Sign in with the GitHub account that has write access to your repository.
1. Enter your GitHub organization, repository, and branch.
1. Optionally, select **Preview file** to view how the workflow file looks before it gets generated and added to your repository.
1. Complete configuring your function app. Your GitHub repository now includes a new workflow file in `/.github/workflows/`.
### For an existing function app
[!INCLUDE [functions-deploy-github-actions](../../includes/functions-deploy-github-actions.md)]
::: zone-end
::: zone pivot="method-template"
## 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](https://github.com/), go to your repository.
1. Select **Actions** and **New workflow**.
1. Search for *functions*.
:::image type="content" source="media/functions-how-to-github-actions/github-actions-functions-templates.png" alt-text="Screenshot of search for GitHub Actions functions templates. ":::
1. In the displayed functions app workflows authored by Microsoft Azure, find the one that matches your code language and select **Configure**.
1. 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.
1. 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:
```yml
- 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:
```yml
permissions:
id-token: write
contents: read
```
1. Verify that the new workflow file is saved with an appropriate name in `/.github/workflows/` and select **Commit changes**.
::: zone-end
## 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 request a remote build when you deploy to an app in the Flex Consumption plan. The remote build always uses Oryx. 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](functions-deployment-technologies.md#remote-build). Set to `true` to have Kudu build your project during deployment. Default: `false`. For more information, see [`SCM_DO_BUILD_DURING_DEPLOYMENT`](./functions-app-settings.md#scm_do_build_during_deployment). |
| **enable-oryx-build** | Allow Kudu to resolve project dependencies by using [Oryx](https://github.com/Microsoft/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](functions-deployment-slots.md) 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](./flex-consumption-plan.md) | [Package deployment] |
| [Elastic Premium](./functions-premium-plan.md) | [ZIP deployment] |
| [Dedicated (App Service)](./dedicated-plan.md) | [ZIP deployment] |
| [Consumption](./consumption-plan.md) | Windows: [ZIP deployment]<br/>Linux: [external package URL](./functions-deployment-technologies.md#external-package-url)<sup>*</sup> |
\* 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](consumption-plan.md).
For more information, see [Deployment technologies in Azure Functions](functions-deployment-technologies.md).
## Next steps
- [Recover from a bad Flex Consumption plan deployment](functions-rollback-deployments.md)
- [Learn more about Azure and GitHub integration](/azure/developer/github/)
[Azure portal]: https://portal.azure.com
[ZIP deployment]: functions-deployment-technologies.md#zip-deployment
[Package deployment]: functions-deployment-technologies.md#flex-consumption-package-deployment
[`Azure/functions-action`]: https://github.com/Azure/functions-action