Use Azure Spring Apps CI/CD with GitHub Actions

Note

The Basic, Standard, and Enterprise plans will be deprecated starting from mid-March, 2025, with a 3 year retirement period. We recommend transitioning to Azure Container Apps. For more information, see the Azure Spring Apps retirement announcement.

The Standard consumption and dedicated plan will be deprecated starting September 30, 2024, with a complete shutdown after six months. We recommend transitioning to Azure Container Apps.

This article shows you how to build up a CI/CD workflow for Azure Spring Apps with GitHub Actions.

GitHub Actions support an automated software development lifecycle workflow. With GitHub Actions for Azure Spring Apps you can create workflows in your repository to build, test, package, release, and deploy to Azure.

Prerequisites

This example requires the Azure CLI.

Set up GitHub repository and authenticate

You need an Azure service principal credential to authorize Azure login action. To get an Azure credential, execute the following commands on your local machine:

az cloud set -n AzureChinaCloud
az login
az ad sp create-for-rbac \
    --role contributor \
    --scopes /subscriptions/<SUBSCRIPTION_ID> \
    --json-auth

To access to a specific resource group, you can reduce the scope:

az ad sp create-for-rbac \
    --role contributor \
    --scopes /subscriptions/<SUBSCRIPTION_ID>/resourceGroups/<RESOURCE_GROUP> \
    --json-auth

The command should output a JSON object:

{
    "clientId": "<GUID>",
    "clientSecret": "<GUID>",
    "subscriptionId": "<GUID>",
    "tenantId": "<GUID>",
    ...
}

This example uses the PiggyMetrics sample on GitHub. Fork the sample, uncheck Copy the Azure branch only, open the GitHub repository page, and select the Settings tab. Open Secrets menu, and select Add a new secret:

Screenshot of the GitHub Actions secrets and variables page with the New repository secret button highlighted.

Set the secret name to AZURE_CREDENTIALS and its value to the JSON string that you found under the heading Set up your GitHub repository and authenticate.

Screenshot of the GitHub Actions secrets / New secret page.

You can also get the Azure login credential from Key Vault in GitHub Actions as explained in Authenticate Azure Spring with Key Vault in GitHub Actions.

Provision service instance

To provision your Azure Spring Apps service instance, run the following commands using the Azure CLI.

az extension add --name spring
az group create --location chinanorth2 --name <resource group name>
az spring create -n <service instance name> -g <resource group name>
az spring config-server git set -n <service instance name> --uri https://github.com/xxx/piggymetrics --label config

End-to-end sample workflows

The following examples demonstrate common usage scenarios.

Deploying

The following sections show you various options for deploying your app.

To production

Azure Spring Apps supports deploying to deployments with built artifacts (for example, JAR or .NET Core ZIP) or source code archive.

The following example deploys to the default production deployment in Azure Spring Apps using JAR file built by Maven. This example is the only possible deployment scenario when using the Basic SKU:

Note

The package search pattern should only return exactly one package. If the build task produces multiple JAR packages such as sources.jar and javadoc.jar, you need to refine the search pattern so that it only matches the application binary artifact.

name: AzureSpringApps
on: push
env:
  ASC_PACKAGE_PATH: ${{ github.workspace }}
  AZURE_SUBSCRIPTION: <azure subscription name>

jobs:
  deploy_to_production:
    runs-on: ubuntu-latest
    name: deploy to production with artifact
    steps:
      - name: Checkout GitHub Action
        uses: actions/checkout@v2

      - name: Set up Java 11
        uses: actions/setup-java@v3
        with:
          distribution: 'temurin'
          java-version: '11'

      - name: maven build, clean
        run: |
          mvn clean package

      - name: Login via Azure CLI
        uses: azure/login@v1
        with:
          creds: ${{ secrets.AZURE_CREDENTIALS }}

      - name: deploy to production with artifact
        uses: azure/spring-apps-deploy@v1
        with:
          azure-subscription: ${{ env.AZURE_SUBSCRIPTION }}
          action: Deploy
          service-name: <service instance name>
          app-name: <app name>
          use-staging-deployment: false
          package: ${{ env.ASC_PACKAGE_PATH }}/**/*.jar

The following example deploys to the default production deployment in Azure Spring Apps using source code.

name: AzureSpringApps
on: push
env:
  ASC_PACKAGE_PATH: ${{ github.workspace }}
  AZURE_SUBSCRIPTION: <azure subscription name>

jobs:
  deploy_to_production:
    runs-on: ubuntu-latest
    name: deploy to production with source code
    steps:
      - name: Checkout GitHub Action
        uses: actions/checkout@v2

      - name: Login via Azure CLI
        uses: azure/login@v1
        with:
          creds: ${{ secrets.AZURE_CREDENTIALS }}

      - name: deploy to production step with source code
        uses: azure/spring-apps-deploy@v1
        with:
          azure-subscription: ${{ env.AZURE_SUBSCRIPTION }}
          action: deploy
          service-name: <service instance name>
          app-name: <app name>
          use-staging-deployment: false
          package: ${{ env.ASC_PACKAGE_PATH }}

The following example deploys to the default production deployment in Azure Spring Apps with an existing container image.

name: AzureSpringApps
on: push
env:
  ASC_PACKAGE_PATH: ${{ github.workspace }}
  AZURE_SUBSCRIPTION: <azure subscription name>

jobs:
  deploy_to_production:
    runs-on: ubuntu-latest
    name: deploy to production with source code
    steps:
      - name: Checkout GitHub Action
        uses: actions/checkout@v2

      - name: Login via Azure CLI
        uses: azure/login@v1
        with:
          creds: ${{ secrets.AZURE_CREDENTIALS }}

      - name: Deploy Custom Image
        uses: Azure/spring-apps-deploy@v1
        with:
          azure-subscription: ${{ env.AZURE_SUBSCRIPTION }}
          action: deploy
          service-name: <service instance name>
          app-name: <app name>
          deployment-name: <deployment name>
          container-registry: <your container image registry>
          registry-username: ${{ env.REGISTRY_USERNAME }}
          registry-password: ${{ secrets.REGISTRY_PASSWORD }}
          container-image: <your image tag>

During deployment, you can achieve more functionality by using more arguments. For more information, see the Arguments section of GitHub Action for deploying to Azure Spring Apps.

Blue-green

The following examples deploy to an existing staging deployment. This deployment doesn't receive production traffic until it's set as a production deployment. You can set use-staging-deployment true to find the staging deployment automatically or just allocate specific deployment-name. We only focus on the spring-apps-deploy action and leave out the preparatory jobs in the rest of the article.

# environment preparation configurations omitted
    steps:
      - name: blue green deploy step use-staging-deployment
        uses: azure/spring-apps-deploy@v1
        with:
          azure-subscription: ${{ env.AZURE_SUBSCRIPTION }}
          action: deploy
          service-name: <service instance name>
          app-name: <app name>
          use-staging-deployment: true
          package: ${{ env.ASC_PACKAGE_PATH }}/**/*.jar
# environment preparation configurations omitted
    steps:
      - name: blue green deploy step with deployment-name
        uses: azure/spring-apps-deploy@v1
        with:
          azure-subscription: ${{ env.AZURE_SUBSCRIPTION }}
          action: deploy
          service-name: <service instance name>
          app-name: <app name>
          deployment-name: staging
          package: ${{ env.ASC_PACKAGE_PATH }}/**/*.jar

For more information on blue-green deployments, including an alternative approach, see Blue-green deployment strategies.

Setting production deployment

The following example sets the current staging deployment as production, effectively swapping which deployment receives production traffic.

# environment preparation configurations omitted
    steps:
      - name: set production deployment step
        uses: azure/spring-apps-deploy@v1
        with:
          azure-subscription: ${{ env.AZURE_SUBSCRIPTION }}
          action: set-production
          service-name: <service instance name>
          app-name: <app name>
          use-staging-deployment: true

Deleting a staging deployment

The Delete Staging Deployment action allows you to delete the deployment not receiving production traffic. This deletion frees up resources used by that deployment and makes room for a new staging deployment:

# environment preparation configurations omitted
    steps:
      - name: Delete staging deployment step
        uses: azure/spring-apps-deploy@v1
        with:
          azure-subscription: ${{ env.AZURE_SUBSCRIPTION }}
          action: delete-staging-deployment
          service-name: <service instance name>
          app-name: <app name>

Deploy with Maven Plugin

Another option is to use the Maven Plugin for deploying the Jar and updating App settings. The command mvn azure-spring-apps:deploy is idempotent and automatically creates Apps if needed. You don't need to create corresponding apps in advance.

name: AzureSpringApps
on: push

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:

    - uses: actions/checkout@main

    - name: Set up Java 11
      uses: actions/setup-java@v3
      with:
        distribution: 'temurin'
        java-version: '11'

    - name: maven build, clean
      run: |
        mvn clean package -DskipTests

    # Maven plugin can cosume this authentication method automatically
    - name: Azure Login
      uses: azure/login@v1
      with:
        creds: ${{ secrets.AZURE_CREDENTIALS }}

    # Maven deploy, make sure you have correct configurations in your pom.xml
    - name: deploy to Azure Spring Apps using Maven
      run: |
        mvn azure-spring-apps:deploy

Run the workflow

GitHub Actions should be enabled automatically after you push .github/workflow/main.yml to GitHub. The action is triggered when you push a new commit. If you create this file in the browser, your action should have already run.

To verify that the action has been enabled, select the Actions tab on the GitHub repository page:

Screenshot of the GitHub Actions tab showing the All workflows section.

If your action runs in error, for example, if you haven't set the Azure credential, you can rerun checks after fixing the error. On the GitHub repository page, select Actions, select the specific workflow task, and then select the Rerun checks button to rerun checks:

Screenshot of the GitHub Actions tab with the Re-run checks button highlighted.

Next steps