# yaml-language-server: $schema=https://aka.ms/m365-agents-toolkits/v1.11/yaml.schema.json
# Visit https://aka.ms/teamsfx-v5.0-guide for details on this file
# Visit https://aka.ms/teamsfx-actions for details on actions
version: v1.11

environmentFolderPath: ./env

provision:
  # Creates an app
  - uses: teamsApp/create
    with:
      # app name
      name: {{appName}}${{APP_NAME_SUFFIX}}
    # Write the information of created resources into environment file for
    # the specified environment variable(s).
    writeToEnvironmentFile:
      teamsAppId: TEAMS_APP_ID

  - uses: arm/deploy # Deploy given ARM templates parallelly.
    with:
      # AZURE_SUBSCRIPTION_ID is a built-in environment variable,
      # if its value is empty, toolkit will prompt you to select a subscription.
      # Referencing other environment variables with empty values
      # will skip the subscription selection prompt.
      subscriptionId: ${{AZURE_SUBSCRIPTION_ID}}
      # AZURE_RESOURCE_GROUP_NAME is a built-in environment variable,
      # if its value is empty, toolkit will prompt you to select or create one
      # resource group.
      # Referencing other environment variables with empty values
      # will skip the resource group selection prompt.
      resourceGroupName: ${{AZURE_RESOURCE_GROUP_NAME}}
      templates:
        - path: ./infra/azure.bicep # Relative path to this file
          # Placeholders will be replaced with corresponding environment
          # variable before ARM deployment.
          parameters: ./infra/azure.parameters.json
          # Required when deploying ARM template
          deploymentName: Create-resources
      # Microsoft 365 Agents Toolkit will download this bicep CLI version from github for you,
      # will use bicep CLI in PATH if you remove this config.
      bicepCliVersion: v0.9.1
  
  # Grant the bot managed identity access to your Foundry Project.
  # This avoids manual IAM steps when launching the deployed bot in Teams.
  - uses: script
    name: grant Foundry access (Azure AI User)
    with:
      timeout: 600000
      run: |
        $ErrorActionPreference = "Stop"

        if (-not $env:FOUNDRY_PROJECT_ENDPOINT) { throw "FOUNDRY_PROJECT_ENDPOINT is not set." }
        if (-not $env:BOT_ID) { throw "BOT_ID (managed identity client id) is not set." }
        if (-not $env:AZURE_SUBSCRIPTION_ID) { throw "AZURE_SUBSCRIPTION_ID is not set." }

        $projectEndpoint = $env:FOUNDRY_PROJECT_ENDPOINT.TrimEnd("/")
        $uri = [Uri]$projectEndpoint
        $resourceName = $uri.Host.Split(".")[0]
        $projectName = ($projectEndpoint -split "/api/projects/")[1]
        if (-not $projectName) { throw "Unable to parse project name from FOUNDRY_PROJECT_ENDPOINT." }

        Write-Host "Foundry resource: $resourceName"
        Write-Host "Foundry project: $projectName"

        $resourceTypes = @(
          "Microsoft.MachineLearningServices/workspaces",
          "Microsoft.AIResource/aiResources",
          "Microsoft.CognitiveServices/accounts"
        )

        $resourceId = $null
        $resourceTypeUsed = $null
        foreach ($type in $resourceTypes) {
          $candidateId = az resource list --subscription $env:AZURE_SUBSCRIPTION_ID --name $resourceName --resource-type $type --query "[0].id" -o tsv
          if ($candidateId) {
            $resourceId = $candidateId
            $resourceTypeUsed = $type
            break
          }
        }

        if (-not $resourceId) { throw "Unable to find Azure AI resource '$resourceName' in subscription $($env:AZURE_SUBSCRIPTION_ID)." }

        $projectScope = $null
        if ($resourceTypeUsed) {
          $projectType = "$resourceTypeUsed/projects"
          $projectId = az resource list --subscription $env:AZURE_SUBSCRIPTION_ID --name $projectName --resource-type $projectType --query "[0].id" -o tsv
          if ($projectId) {
            $projectScope = $projectId
          }
        }

        $scope = if ($projectScope) { $projectScope } else { $resourceId }
        Write-Host "Assigning role at scope: $scope"

        $clientId = $env:BOT_ID
        $spObjectId = az ad sp show --id $clientId --query id -o tsv 2>$null
        if (-not $spObjectId) { $spObjectId = $clientId }

        $scopeCandidates = @()
        if ($projectScope) { $scopeCandidates += $projectScope }
        if ($resourceId) { $scopeCandidates += $resourceId }

        $existing = $null
        foreach ($s in $scopeCandidates | Select-Object -Unique) {
          $candidate = az role assignment list --assignee $spObjectId --scope $s --query "[?roleDefinitionName=='Azure AI User'][0].id" -o tsv
          if ($candidate) { $existing = $candidate; break }
        }

        if ($existing) {
          Write-Host "Role assignment already exists: $existing"
          exit 0
        }

        az role assignment create --assignee $spObjectId --role "Azure AI User" --scope $scope

  # Build app package with latest env value
  - uses: teamsApp/zipAppPackage
    with:
      # Path to manifest template
      manifestPath: ./appPackage/manifest.json
      outputZipPath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip
      outputFolder: ./appPackage/build

  # Validate app package using validation rules
  - uses: teamsApp/validateAppPackage
    with:
      # Relative path to this file. This is the path for built zip file.
      appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip

  # Apply the app manifest to an existing app in Developer Portal.
  # Will use the app id in manifest file to determine which app to update.
  - uses: teamsApp/update
    with:
      # Relative path to this file. This is the path for built zip file.
      appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip

  - uses: teamsApp/extendToM365
    with:
      # Relative path to the build app package.
      appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip
    # Write the information of created resources into environment file for
    # the specified environment variable(s).
    writeToEnvironmentFile:
      titleId: M365_TITLE_ID
      appId: M365_APP_ID

deploy:
  # Run npm command
  - uses: cli/runNpmCommand
    name: install dependencies
    with:
      args: install

  - uses: cli/runNpmCommand
    name: build app
    with:
      args: run build --if-present

  # Deploy your application to Azure App Service using the zip deploy feature.
  # For additional details, refer to https://aka.ms/zip-deploy-to-app-services.
  - uses: azureAppService/zipDeploy
    with:
      # Deploy base folder
      artifactFolder: .
      # Ignore file location, leave blank will ignore nothing
      ignoreFile: .webappignore
      # The resource id of the cloud resource to be deployed to.
      # This key will be generated by arm/deploy action automatically.
      # You can replace it with your existing Azure Resource id
      # or add it to your environment variable file.
      resourceId: ${{AZURE_APP_SERVICE_RESOURCE_ID}}

publish:

  # Build app package with latest env value
  - uses: teamsApp/zipAppPackage
    with:
      # Path to manifest template
      manifestPath: ./appPackage/manifest.json
      outputZipPath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip
      outputFolder: ./appPackage/build

  # Validate app package using validation rules
  - uses: teamsApp/validateAppPackage
    with:
      # Relative path to this file. This is the path for built zip file.
      appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip

  # Apply the app manifest to an existing app in Developer Portal.
  # Will use the app id in manifest file to determine which app to update.
  - uses: teamsApp/update
    with:
      # Relative path to this file. This is the path for built zip file.
      appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip

  # Publish the app to Teams Admin Center (https://admin.teams.microsoft.com/policies/manage-apps)
  # for review and approval
  - uses: teamsApp/publishAppPackage
    with:
      appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip
    # Write the information of created resources into environment file for
    # the specified environment variable(s).
    writeToEnvironmentFile:
      publishedAppId: TEAMS_APP_PUBLISHED_APP_ID
