Skip to content

Commit

Permalink
Add GitHub Actions workflow (#11)
Browse files Browse the repository at this point in the history
  • Loading branch information
justinyoo authored Nov 27, 2023
1 parent 696da6b commit 0284e05
Show file tree
Hide file tree
Showing 21 changed files with 664 additions and 51 deletions.
130 changes: 130 additions & 0 deletions .github/workflows/azure-dev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
on:
workflow_dispatch:
push:
branches:
- main
- 'feature/*'
pull_request:
branches:
- main

# https://learn.microsoft.com/en-us/azure/developer/github/connect-from-azure?tabs=azure-portal%2Clinux#set-up-azure-login-with-openid-connect-authentication
permissions:
id-token: write
contents: read

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Login to Azure
if: (github.event_name == 'push' && github.ref == 'refs/heads/main') || github.event_name == 'workflow_dispatch'
uses: azure/login@v1
with:
tenant-id: ${{ vars.AZURE_TENANT_ID }}
subscription-id: ${{ vars.AZURE_SUBSCRIPTION_ID }}
client-id: ${{ vars.AZURE_CLIENT_ID }}

# - name: Install Azure Developer CLI
# if: (github.event_name == 'push' && github.ref == 'refs/heads/main') || github.event_name == 'workflow_dispatch'
# uses: Azure/[email protected]

- name: Install Azure Developer CLI (nightly build)
if: (github.event_name == 'push' && github.ref == 'refs/heads/main') || github.event_name == 'workflow_dispatch'
shell: pwsh
run: |
Invoke-RestMethod 'https://aka.ms/install-azd.ps1' -OutFile ./install-azd.ps1
./install-azd.ps1 -Version daily
- name: Login to Azure Developer CLI
if: (github.event_name == 'push' && github.ref == 'refs/heads/main') || github.event_name == 'workflow_dispatch'
shell: pwsh
run: |
azd auth login `
--tenant-id "${{ vars.AZURE_TENANT_ID }}" `
--client-id "${{ vars.AZURE_CLIENT_ID }}" `
--federated-credential-provider "${{ vars.AZD_PIPELINE_PROVIDER }}"
- name: Setup environment
if: (github.event_name == 'push' && github.ref == 'refs/heads/main') || github.event_name == 'workflow_dispatch'
shell: pwsh
run: |
# Create config.json under .azure
New-Item -Type Directory .azure
$config = @{ version = 1; defaultEnvironment = "${{ vars.AZURE_ENV_NAME }}" }
$config | ConvertTo-Json -Depth 100 | Out-File -Path ./.azure/config.json -Force
# Create config.json under .azure/${{ vars.AZURE_ENV_NAME }}
New-Item -Type Directory .azure/${{ vars.AZURE_ENV_NAME }}
$config = @{ services = @{ app = @{ config = @{ exposedServices = @( "webapp" ) } } } }
$config | ConvertTo-Json -Depth 100 | Out-File -Path ./.azure/${{ vars.AZURE_ENV_NAME }}/config.json -Force
# Create .env under .azure/${{ vars.AZURE_ENV_NAME }}
$dotenv = @()
$dotenv += "AZD_PIPELINE_PROVIDER=`"${{ vars.AZD_PIPELINE_PROVIDER }}`""
$dotenv += "AZURE_CONTAINER_APPS_ENVIRONMENT_DEFAULT_DOMAIN=`"${{ vars.AZURE_CONTAINER_APPS_ENVIRONMENT_DEFAULT_DOMAIN }}`""
$dotenv += "AZURE_CONTAINER_APPS_ENVIRONMENT_ID=`"${{ vars.AZURE_CONTAINER_APPS_ENVIRONMENT_ID }}`""
$dotenv += "AZURE_CONTAINER_REGISTRY_ENDPOINT=`"${{ vars.AZURE_CONTAINER_REGISTRY_ENDPOINT }}`""
$dotenv += "AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID=`"${{ vars.AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID }}`""
$dotenv += "AZURE_ENV_NAME=`"${{ vars.AZURE_ENV_NAME }}`""
$dotenv += "AZURE_LOCATION=`"${{ vars.AZURE_LOCATION }}`""
$dotenv += "AZURE_PIPELINE_CLIENT_ID=`"${{ vars.AZURE_PIPELINE_CLIENT_ID }}`""
$dotenv += "AZURE_SUBSCRIPTION_ID=`"${{ vars.AZURE_SUBSCRIPTION_ID }}`""
$dotenv += "MANAGED_IDENTITY_CLIENT_ID=`"${{ vars.MANAGED_IDENTITY_CLIENT_ID }}`""
$dotenv += "SERVICE_BINDING_QUEUE_ENDPOINT=`"${{ vars.SERVICE_BINDING_QUEUE_ENDPOINT }}`""
$dotenv += "SERVICE_BINDING_TABLE_ENDPOINT=`"${{ vars.SERVICE_BINDING_TABLE_ENDPOINT }}`""
$dotenv | Out-File -Path ./.azure/${{ vars.AZURE_ENV_NAME }}/.env -Force
- name: Update appsettings.json
if: (github.event_name == 'push' && github.ref == 'refs/heads/main') || github.event_name == 'workflow_dispatch'
shell: pwsh
run: |
$resourceName = az resource list -g rg-${{ vars.AZURE_ENV_NAME }} --query "[?type=='Microsoft.CognitiveServices/accounts'].name" -o tsv
$endpoint = az cognitiveservices account show -g rg-${{ vars.AZURE_ENV_NAME }} -n $resourceName --query "properties.endpoint" -o tsv
$apiKey = az cognitiveservices account keys list -g rg-${{ vars.AZURE_ENV_NAME }} -n $resourceName --query "key1" -o tsv
$deploymentId = az cognitiveservices account deployment list -g rg-${{ vars.AZURE_ENV_NAME }} -n $resourceName --query "[].name" -o tsv
$openAI = @{ Endpoint = $endpoint; ApiKey = $apiKey; DeploymentId = $deploymentId; }
# Copy-Item -Path ./AspireYouTubeSummariser.AppHost/appsettings.Development.sample.json `
# -Destination ./AspireYouTubeSummariser.AppHost/appsettings.Development.json -Force
$appsettings = Get-Content -Path ./AspireYouTubeSummariser.AppHost/appsettings.json | ConvertFrom-Json
$appsettings.OpenAI = $openAI
$appsettings | ConvertTo-Json -Depth 100 | Out-File -Path ./AspireYouTubeSummariser.AppHost/appsettings.json -Force
- name: Setup .NET SDK
uses: actions/setup-dotnet@v3
with:
dotnet-version: 8.x

- name: Install Aspire workload
shell: pwsh
run: |
dotnet workload update
dotnet workload install aspire
- name: Restore NuGet packages
shell: bash
run: |
dotnet restore
- name: Build solution
shell: bash
run: |
dotnet build
- name: Test solution
shell: bash
run: |
dotnet test
- name: Deploy to Azure Container Apps
if: (github.event_name == 'push' && github.ref == 'refs/heads/main') || github.event_name == 'workflow_dispatch'
shell: pwsh
run: |
azd deploy
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -486,3 +486,7 @@ $RECYCLE.BIN/
appsettings.Development.json
**/bundle.js
**/bundle.js.*.txt
.azure

*.bak
*.org
10 changes: 0 additions & 10 deletions AspireYouTubeSummariser.ApiApp/appsettings.Development.sample.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,5 @@
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},

// "ConnectionStrings": {
// "table": "{{AZURE_STORAGE_CONNECTION_STRING}}"
// },

"OpenAI": {
"Endpoint": "{{AOAI_ENDPOINT_URL}}",
"ApiKey": "{{AOAI_API_KEY}}",
"DeploymentId": "{{AOAI_DEPLOYMENT_ID}}"
}
}
10 changes: 0 additions & 10 deletions AspireYouTubeSummariser.ApiApp/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,6 @@
}
},

// "ConnectionStrings": {
// "table": "{{AZURE_STORAGE_CONNECTION_STRING}}"
// },

"OpenAI": {
"Endpoint": "{{AOAI_ENDPOINT_URL}}",
"ApiKey": "{{AOAI_API_KEY}}",
"DeploymentId": "{{AOAI_DEPLOYMENT_ID}}"
},

"Prompt": {
"System": "You are the expert of summarising long contents. You are going to summarise the following YouTube video transcript in a given language code.",
"MaxTokens": 3000,
Expand Down
12 changes: 12 additions & 0 deletions AspireYouTubeSummariser.AppHost/Program.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
using AspireYouTubeSummariser.Shared.Configurations;

using Microsoft.Extensions.Configuration;

var builder = DistributedApplication.CreateBuilder(args);

var cache = builder.AddRedisContainer("cache");
var storage = builder.AddAzureStorage("storage");
var queue = storage.AddQueues("queue");
var table = storage.AddTables("table");

var openAISettings = builder.Configuration.GetSection(OpenAISettings.Name).Get<OpenAISettings>();

var apiapp = builder.AddProject<Projects.AspireYouTubeSummariser_ApiApp>("apiapp")
.WithEnvironment("OpenAI__Endpoint", openAISettings.Endpoint)
.WithEnvironment("OpenAI__ApiKey", openAISettings.ApiKey)
.WithEnvironment("OpenAI__DeploymentId", openAISettings.DeploymentId)
.WithReference(table);

builder.AddProject<Projects.AspireYouTubeSummariser_WebApp>("webapp")
Expand All @@ -14,6 +23,9 @@
.WithReference(apiapp);

builder.AddProject<Projects.AspireYouTubeSummariser_Worker>("worker")
.WithEnvironment("OpenAI__Endpoint", openAISettings.Endpoint)
.WithEnvironment("OpenAI__ApiKey", openAISettings.ApiKey)
.WithEnvironment("OpenAI__DeploymentId", openAISettings.DeploymentId)
.WithReference(queue)
.WithReference(table);

Expand Down
15 changes: 13 additions & 2 deletions AspireYouTubeSummariser.AppHost/Properties/launchSettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,22 @@
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "http://localhost:15218",
"applicationUrl": "http://localhost:15000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"DOTNET_ENVIRONMENT": "Development",
"DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:16101"
"DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:16000"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "http://localhost:15001",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"DOTNET_ENVIRONMENT": "Development",
"DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:16001"
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@
},

"ConnectionStrings": {
"queue": "{{AZURE_STORAGE_CONNECTION_STRING}}",
"table": "{{AZURE_STORAGE_CONNECTION_STRING}}"
"queue": "https://{account_name}.table.core.windows.net/",
"table": "https://{account_name}.table.core.windows.net/"
},

"OpenAI": {
"Endpoint": "https://{account_name}.openai.azure.com/",
"ApiKey": "random.apikey.aoai",
"DeploymentId": "random.deploymentid.aoai"
}
}
10 changes: 8 additions & 2 deletions AspireYouTubeSummariser.AppHost/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@
},

"ConnectionStrings": {
"queue": "{{AZURE_STORAGE_CONNECTION_STRING}}",
"table": "{{AZURE_STORAGE_CONNECTION_STRING}}"
"queue": "https://{account_name}.table.core.windows.net/",
"table": "https://{account_name}.table.core.windows.net/"
},

"OpenAI": {
"Endpoint": "https://{account_name}.openai.azure.com/",
"ApiKey": "random.apikey.aoai",
"DeploymentId": "random.deploymentid.aoai"
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Library</OutputType>
Expand All @@ -11,6 +11,7 @@
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />

<PackageReference Include="Azure.Monitor.OpenTelemetry.AspNetCore" Version="1.0.0-beta.8" />
<PackageReference Include="Microsoft.Extensions.Http.Resilience" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.ServiceDiscovery" Version="8.0.0-preview.1.23557.2" />
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.7.0-alpha.1" />
Expand Down
3 changes: 3 additions & 0 deletions AspireYouTubeSummariser.ServiceDefaults/Extensions.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
using System.Net;

using Azure.Monitor.OpenTelemetry.AspNetCore;

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Http.Resilience;
using Microsoft.Extensions.Logging;

using OpenTelemetry.Logs;
using OpenTelemetry.Metrics;
using OpenTelemetry.Trace;
Expand Down
2 changes: 1 addition & 1 deletion AspireYouTubeSummariser.WebApp/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
builder.Services.AddHttpClient<IApiAppClient, ApiAppClient>(client =>
{
//client.BaseAddress = new Uri("http://localhost:5050");
client.BaseAddress = new Uri("http://apiapp");
client.BaseAddress = new Uri("https://apiapp");
});
builder.Services.AddScoped<IQueueServiceClientWrapper, QueueServiceClientWrapper>();

Expand Down
11 changes: 0 additions & 11 deletions AspireYouTubeSummariser.Worker/appsettings.Development.sample.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,5 @@
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},

// "ConnectionStrings": {
// "queue": "{{AZURE_STORAGE_CONNECTION_STRING}}",
// "table": "{{AZURE_STORAGE_CONNECTION_STRING}}"
// },

"OpenAI": {
"Endpoint": "{{AOAI_ENDPOINT_URL}}",
"ApiKey": "{{AOAI_API_KEY}}",
"DeploymentId": "{{AOAI_DEPLOYMENT_ID}}"
}
}
11 changes: 0 additions & 11 deletions AspireYouTubeSummariser.Worker/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,6 @@
}
},

// "ConnectionStrings": {
// "queue": "{{AZURE_STORAGE_CONNECTION_STRING}}",
// "table": "{{AZURE_STORAGE_CONNECTION_STRING}}"
// },

"OpenAI": {
"Endpoint": "{{AOAI_ENDPOINT_URL}}",
"ApiKey": "{{AOAI_API_KEY}}",
"DeploymentId": "{{AOAI_DEPLOYMENT_ID}}"
},

"Prompt": {
"System": "You are the expert of summarising long contents. You are going to summarise the following YouTube video transcript in a given language code.",
"MaxTokens": 3000,
Expand Down
43 changes: 42 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@ This provides sample Aspire-orchestrated apps that summarise a YouTube video tra

- [.NET 8 SDK](https://dotnet.microsoft.com/download/dotnet/8.0?WT.mc_id=dotnet-107070-juyoo)
- [Visual Studio 2022](https://visualstudio.microsoft.com?WT.mc_id=dotnet-107070-juyoo) 17.9 or later with the .NET Aspire workload installed
- [Docker Desktop](https://www.docker.com/products/docker-desktop)
- [Docker Desktop](https://docker.com/products/docker-desktop)
- [Azure Developer CLI](https://learn.microsoft.com/azure/developer/azure-developer-cli/overview?WT.mc_id=dotnet-107070-juyoo)
- [Azure CLI](https://learn.microsoft.com/cli/azure/what-is-azure-cli?WT.mc_id=dotnet-107070-juyoo)
- [GitHub CLI](https://cli.github.com/)
- [PowerShell](https://learn.microsoft.com/powershell/scripting/overview?WT.mc_id=dotnet-107070-juyoo)
- [Azure subscription](https://azure.microsoft.com/free?WT.mc_id=dotnet-107070-juyoo)
- [Azure OpenAI Service subscription](https://aka.ms/oaiapply)

Expand Down Expand Up @@ -100,6 +103,44 @@ This provides sample Aspire-orchestrated apps that summarise a YouTube video tra
dotnet run --project AspireYouTubeSummariser.AppHost
```

### Deploy to Azure

1. Checkout to the `main` branch

```bash
git switch main
dotnet restore && dotnet build
```

1. Rename `appsettings.Development.sample.json` in the `AppHost` project to `appsettings.Development.json`.

1. Add Azure OpenAI Service details &ndash; endpoint, API key and deployment ID &ndash; to the file. You can get these details from the [Azure Portal](https://portal.azure.com/?WT.mc_id=dotnet-107070-juyoo).

1. Add Azure Queue/Table Storage Account details &ndash; connection strings &ndash; to the file You can get these details from the [Azure Portal](https://portal.azure.com/?WT.mc_id=dotnet-107070-juyoo).

1. Run the following commands in order:

```bash
# Initialise azd
AZURE_ENV_NAME="aspire$RANDOM"
azd init -e $AZURE_ENV_NAME
# Provision resources to Azure
azd provision
# Provision GitHub Actions environment
azd pipeline config
pwsh Set-GitHubActionsVariables.ps1 -GitHubAlias <GitHubAlias>
# Provision rest of resources to Azure outside Aspire
pwsh Run-PostProvision.ps1 -GitHubAlias <GitHubAlias>
# Deploy apps to Azure
azd deploy
```

1. Push code changes to the GitHub repository to trigger a GitHub Actions workflow.

## Resources

- [.NET Aspire overview](https://learn.microsoft.com/dotnet/aspire/get-started/aspire-overview?WT.mc_id=dotnet-107070-juyoo)
Expand Down
8 changes: 8 additions & 0 deletions azure.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# yaml-language-server: $schema=https://raw.githubusercontent.com/Azure/azure-dev/main/schemas/v1.0/azure.yaml.json

name: aspire-youtube-summariser
services:
app:
language: dotnet
project: .\AspireYouTubeSummariser.AppHost\AspireYouTubeSummariser.AppHost.csproj
host: containerapp
Loading

0 comments on commit 0284e05

Please sign in to comment.