Skip to content

Commit 657e303

Browse files
Merge branch 'feature/6.1-dotnet-ai-foundation' into develop
2 parents a148bf2 + 02e0697 commit 657e303

33 files changed

Lines changed: 4746 additions & 108 deletions
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
name: Deploy Angular to Azure Static Web Apps
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
paths:
8+
- 'Clients/TalentManagement-Angular-Material/**'
9+
- '.github/workflows/deploy-angular.yml'
10+
workflow_dispatch:
11+
12+
permissions:
13+
id-token: write # Required for OIDC token request
14+
contents: read
15+
16+
env:
17+
ANGULAR_APP_DIR: 'Clients/TalentManagement-Angular-Material/talent-management'
18+
STATIC_WEB_APP_NAME: 'swa-talent-ui-dev'
19+
RESOURCE_GROUP: 'rg-talent-dev'
20+
21+
jobs:
22+
build-and-deploy:
23+
name: Build and Deploy Angular
24+
runs-on: ubuntu-latest
25+
26+
steps:
27+
- name: Checkout repository (with submodules)
28+
uses: actions/checkout@v4
29+
with:
30+
submodules: recursive
31+
32+
- name: Set up Node.js
33+
uses: actions/setup-node@v4
34+
with:
35+
node-version: '22.x'
36+
cache: 'npm'
37+
cache-dependency-path: '${{ env.ANGULAR_APP_DIR }}/package-lock.json'
38+
39+
- name: Install dependencies
40+
working-directory: ${{ env.ANGULAR_APP_DIR }}
41+
run: npm ci
42+
43+
- name: Inject production environment variables
44+
working-directory: ${{ env.ANGULAR_APP_DIR }}
45+
env:
46+
API_URL: ${{ secrets.API_APP_URL }}
47+
IDENTITY_SERVER_URL: ${{ secrets.IDENTITY_SERVER_URL }}
48+
run: |
49+
sed -i "s|https://your-production-api.com/api/v1|${API_URL}/api/v1|g" src/environments/environment.prod.ts
50+
sed -i "s|https://localhost:44310|${IDENTITY_SERVER_URL}|g" src/environments/environment.prod.ts
51+
52+
- name: Build Angular (production)
53+
working-directory: ${{ env.ANGULAR_APP_DIR }}
54+
run: npm run build -- --configuration production
55+
56+
- name: Log in to Azure
57+
uses: azure/login@v2
58+
with:
59+
client-id: ${{ secrets.AZURE_CLIENT_ID }}
60+
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
61+
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
62+
63+
- name: Get Static Web App deployment token
64+
id: swa-token
65+
run: |
66+
SWA_TOKEN=$(az staticwebapp secrets list \
67+
--name ${{ env.STATIC_WEB_APP_NAME }} \
68+
--resource-group ${{ env.RESOURCE_GROUP }} \
69+
--query properties.apiKey \
70+
--output tsv)
71+
echo "token=${SWA_TOKEN}" >> $GITHUB_OUTPUT
72+
73+
- name: Deploy to Azure Static Web Apps
74+
uses: Azure/static-web-apps-deploy@v1
75+
with:
76+
azure_static_web_apps_api_token: ${{ steps.swa-token.outputs.token }}
77+
action: upload
78+
app_location: 'Clients/TalentManagement-Angular-Material/talent-management'
79+
output_location: 'dist/talent-management/browser'
80+
skip_app_build: true

.github/workflows/deploy-api.yml

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
name: Deploy .NET API to Azure App Service
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
paths:
8+
- 'ApiResources/TalentManagement-API/**'
9+
- '.github/workflows/deploy-api.yml'
10+
workflow_dispatch:
11+
12+
permissions:
13+
id-token: write # Required for OIDC token request
14+
contents: read
15+
16+
env:
17+
DOTNET_VERSION: '10.x'
18+
PROJECT_PATH: 'ApiResources/TalentManagement-API/TalentManagementAPI.WebApi/TalentManagementAPI.WebApi.csproj'
19+
SOLUTION_PATH: 'ApiResources/TalentManagement-API/TalentManagementAPI.slnx'
20+
PUBLISH_DIR: '${{ github.workspace }}/publish/api'
21+
APP_SERVICE_NAME: 'app-talent-api-dev'
22+
RESOURCE_GROUP: 'rg-talent-dev'
23+
24+
jobs:
25+
build-and-deploy:
26+
name: Build, Test, and Deploy API
27+
runs-on: ubuntu-latest
28+
29+
steps:
30+
- name: Checkout repository (with submodules)
31+
uses: actions/checkout@v4
32+
with:
33+
submodules: recursive
34+
35+
- name: Set up .NET ${{ env.DOTNET_VERSION }}
36+
uses: actions/setup-dotnet@v4
37+
with:
38+
dotnet-version: ${{ env.DOTNET_VERSION }}
39+
40+
- name: Restore dependencies
41+
run: dotnet restore ${{ env.SOLUTION_PATH }}
42+
43+
- name: Build
44+
run: dotnet build ${{ env.SOLUTION_PATH }} --configuration Release --no-restore
45+
46+
- name: Run unit tests
47+
run: dotnet test ${{ env.SOLUTION_PATH }} --configuration Release --no-build --verbosity normal
48+
49+
- name: Publish
50+
run: |
51+
dotnet publish ${{ env.PROJECT_PATH }} \
52+
--configuration Release \
53+
--no-build \
54+
--output ${{ env.PUBLISH_DIR }}
55+
56+
- name: Log in to Azure
57+
uses: azure/login@v2
58+
with:
59+
client-id: ${{ secrets.AZURE_CLIENT_ID }}
60+
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
61+
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
62+
63+
- name: Configure App Service settings
64+
run: |
65+
az webapp config appsettings set \
66+
--resource-group ${{ env.RESOURCE_GROUP }} \
67+
--name ${{ env.APP_SERVICE_NAME }} \
68+
--settings \
69+
"ConnectionStrings__DefaultConnection=${{ secrets.API_DB_CONNECTION_STRING }}" \
70+
"Sts__ServerUrl=${{ secrets.IDENTITY_SERVER_URL }}" \
71+
"Sts__ValidIssuer=${{ secrets.IDENTITY_SERVER_URL }}" \
72+
"Sts__Audience=app.api.talentmanagement" \
73+
"JWTSettings__Key=${{ secrets.JWT_KEY }}" \
74+
"JWTSettings__Issuer=CoreIdentity" \
75+
"JWTSettings__Audience=CoreIdentityUser" \
76+
"JWTSettings__DurationInMinutes=60" \
77+
"FeatureManagement__AuthEnabled=true" \
78+
"ASPNETCORE_ENVIRONMENT=Production"
79+
80+
- name: Deploy to Azure App Service
81+
uses: azure/webapps-deploy@v3
82+
with:
83+
app-name: ${{ env.APP_SERVICE_NAME }}
84+
package: ${{ env.PUBLISH_DIR }}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
name: Deploy IdentityServer to Azure App Service
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
paths:
8+
- 'TokenService/Duende-IdentityServer/**'
9+
- '.github/workflows/deploy-identityserver.yml'
10+
workflow_dispatch:
11+
12+
permissions:
13+
id-token: write # Required for OIDC token request
14+
contents: read
15+
16+
env:
17+
DOTNET_VERSION: '8.x'
18+
STS_PROJECT_PATH: 'TokenService/Duende-IdentityServer/src/DuendeIdentityServer.STS.Identity/DuendeIdentityServer.STS.Identity.csproj'
19+
ADMIN_PROJECT_PATH: 'TokenService/Duende-IdentityServer/src/DuendeIdentityServer.Admin/DuendeIdentityServer.Admin.csproj'
20+
PUBLISH_DIR: '${{ github.workspace }}/publish/ids'
21+
APP_SERVICE_NAME: 'app-talent-ids-dev'
22+
RESOURCE_GROUP: 'rg-talent-dev'
23+
24+
jobs:
25+
build-and-deploy:
26+
name: Build, Test, and Deploy IdentityServer
27+
runs-on: ubuntu-latest
28+
29+
steps:
30+
- name: Checkout repository (with submodules)
31+
uses: actions/checkout@v4
32+
with:
33+
submodules: recursive
34+
35+
- name: Set up .NET ${{ env.DOTNET_VERSION }}
36+
uses: actions/setup-dotnet@v4
37+
with:
38+
dotnet-version: ${{ env.DOTNET_VERSION }}
39+
40+
- name: Restore dependencies
41+
run: dotnet restore ${{ env.STS_PROJECT_PATH }}
42+
43+
- name: Build
44+
run: dotnet build ${{ env.STS_PROJECT_PATH }} --configuration Release --no-restore
45+
46+
- name: Publish
47+
run: |
48+
dotnet publish ${{ env.STS_PROJECT_PATH }} \
49+
--configuration Release \
50+
--no-build \
51+
--output ${{ env.PUBLISH_DIR }}
52+
53+
- name: Log in to Azure
54+
uses: azure/login@v2
55+
with:
56+
client-id: ${{ secrets.AZURE_CLIENT_ID }}
57+
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
58+
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
59+
60+
- name: Configure App Service settings
61+
run: |
62+
az webapp config appsettings set \
63+
--resource-group ${{ env.RESOURCE_GROUP }} \
64+
--name ${{ env.APP_SERVICE_NAME }} \
65+
--settings \
66+
"ConnectionStrings__ConfigurationDbConnection=${{ secrets.IDS_DB_CONNECTION_STRING }}" \
67+
"ConnectionStrings__PersistedGrantDbConnection=${{ secrets.IDS_DB_CONNECTION_STRING }}" \
68+
"ConnectionStrings__IdentityDbConnection=${{ secrets.IDS_DB_CONNECTION_STRING }}" \
69+
"AdminConfiguration__IdentityServerBaseUrl=${{ secrets.IDENTITY_SERVER_URL }}" \
70+
"ASPNETCORE_ENVIRONMENT=Production"
71+
72+
- name: Deploy to Azure App Service
73+
uses: azure/webapps-deploy@v3
74+
with:
75+
app-name: ${{ env.APP_SERVICE_NAME }}
76+
package: ${{ env.PUBLISH_DIR }}

blogs/AI-ENHANCEMENT-SERIES-PLAN.md

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -132,29 +132,32 @@ git push --set-upstream origin feature/[N.N]-[slug]
132132

133133
- [x] Ollama running at `http://localhost:11434`
134134
- [x] `blogs/AI-ENHANCEMENT-SERIES-PLAN.md` created ✅
135-
- [ ] Create `blogs/series-6-ai-app-features/` folder
136-
- [ ] Create `blogs/series-7-developer-productivity-ai/` folder
137-
- [ ] Create `docs/images/ai/` folder for screenshots
138-
- [ ] Update `blogs/BLOG-SERIES-PLAN.md` with Series 6 & 7 entries
139-
- [ ] Update `blogs/SERIES-NAVIGATION-TOC.md` to include new series
135+
- [x] Create `blogs/series-6-ai-app-features/` folder
136+
- [x] Create `blogs/series-7-developer-productivity-ai/` folder
137+
- [x] Create `docs/images/ai/` folder for screenshots
138+
- [x] Update `blogs/BLOG-SERIES-PLAN.md` with Series 6 & 7 entries
139+
- [x] Update `blogs/SERIES-NAVIGATION-TOC.md` to include new series
140140

141141
### Phase 1: Series 6 — Backend Foundation
142142

143-
- [ ] **6.1 — .NET AI Foundation**
144-
- [ ] `git checkout -b feature/6.1-dotnet-ai-foundation` in ApiResources submodule
145-
- [ ] `git checkout -b feature/6.1-dotnet-ai-foundation` in parent repo
146-
- [ ] Write article draft (`6.1-dotnet-ai-foundation.md`)
147-
- [ ] Add to WebApi.csproj: `Microsoft.Extensions.AI`, `Microsoft.Extensions.AI.Ollama`
148-
- [ ] Add `"FeatureManagement": { "AiEnabled": false }` to `appsettings.json`
149-
- [ ] Add `aiEnabled: false` to `environment.ts`
150-
- [ ] Create `Application/Interfaces/IAiChatService.cs`
151-
- [ ] Create `Infrastructure.Shared/Services/OllamaAiService.cs`
152-
- [ ] Create `WebApi/Controllers/v1/AiController.cs` with `[FeatureGate("AiEnabled")]`
153-
- [ ] Screenshot: Swagger AI endpoint → `docs/images/ai/`
154-
- [ ] Commit + push submodule feature branch
155-
- [ ] Commit + push parent feature branch (blog + submodule ref)
156-
- [ ] Open PR: ApiResources `feature/6.1-dotnet-ai-foundation``develop`
157-
- [ ] Open PR: Parent `feature/6.1-dotnet-ai-foundation``develop`
143+
- [x] **6.1 — .NET AI Foundation**
144+
- [x] `git checkout -b feature/6.1-dotnet-ai-foundation` in ApiResources submodule ✅
145+
- [x] `git checkout -b feature/6.1-dotnet-ai-foundation` in parent repo ✅
146+
- [x] Write article draft (`6.1-dotnet-ai-foundation.md`) ✅
147+
- [x] Add to WebApi.csproj: `Microsoft.Extensions.AI.Ollama`
148+
- [x] Add to Infrastructure.Shared.csproj: `Microsoft.Extensions.AI`
149+
- [x] Add `"AiEnabled": false` to `FeatureManagement` in `appsettings.json`
150+
- [x] Add `"Ollama"` config block to `appsettings.json`
151+
- [x] Create `Application/Interfaces/IAiChatService.cs`
152+
- [x] Create `Infrastructure.Shared/Services/OllamaAiService.cs`
153+
- [x] Create `WebApi/Controllers/v1/AiController.cs` with `[FeatureGate("AiEnabled")]`
154+
- [x] Register `AddOllamaChatClient()` in `Program.cs`
155+
- [x] Register `IAiChatService``OllamaAiService` in `ServiceRegistration.cs`
156+
- [ ] Screenshot: Swagger AI endpoint → `docs/images/ai/` *(manual step)*
157+
- [x] Commit + push ApiResources `feature/6.1-dotnet-ai-foundation`
158+
- [x] Commit + push parent `feature/6.1-dotnet-ai-foundation`
159+
- [ ] Open PR: ApiResources `feature/6.1-dotnet-ai-foundation``develop`https://github.com/workcontrolgit/TalentManagement-API/pull/new/feature/6.1-dotnet-ai-foundation
160+
- [ ] Open PR: Parent `feature/6.1-dotnet-ai-foundation``develop`https://github.com/workcontrolgit/AngularNetTutorial/pull/new/feature/6.1-dotnet-ai-foundation
158161

159162
- [ ] **6.2 — HR AI Assistant (data-aware)**
160163
- [ ] `git checkout -b feature/6.2-dotnet-ai-hr-assistant` in ApiResources submodule

blogs/BLOG-SERIES-PLAN.md

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,56 @@
175175
- **File:** `blogs/series-5-devops-data/5.2-cicd-github-actions.md`
176176
- **Notes:** Draft complete. Ready for review.
177177

178+
### ☁️ Series 5 Azure Deployment Sub-Series
179+
180+
*Target audience: developers new to Azure with a Visual Studio Professional subscription ($50/month credit). Each article ships with real, runnable Bicep templates and GitHub Actions workflows.*
181+
182+
- [ ] **Article 5.3 — Azure Subscription Setup**
183+
- **Title:** Your First Azure Deployment: Setting Up a Visual Studio Subscription
184+
- **Subtitle:** Activate Your $50 Monthly Credit, Install the Azure CLI, and Understand What Fits in Your Budget
185+
- **File:** `blogs/series-5-devops-data/5.3-azure-subscription-setup.md`
186+
- **Branch:** `feature/5.3-5.8-azure-deployment-series`
187+
- **Notes:** Blog only — no code files. Setup guide for new Azure users.
188+
189+
- [ ] **Article 5.4 — Bicep Infrastructure**
190+
- **Title:** Infrastructure as Code: Provision All Azure Resources with One Bicep Command
191+
- **Subtitle:** From Empty Subscription to a Running App Service Plan, SQL Server, and Static Web App in Minutes
192+
- **File:** `blogs/series-5-devops-data/5.4-azure-bicep-infrastructure.md`
193+
- **Code:** `infra/main.bicep`, `infra/modules/*.bicep`, `infra/parameters/dev.bicepparam`
194+
- **Branch:** `feature/5.3-5.8-azure-deployment-series`
195+
- **Notes:** Writes real Bicep templates that can be run against an actual Azure subscription.
196+
197+
- [ ] **Article 5.5 — OIDC GitHub Actions Setup**
198+
- **Title:** Secure CI/CD: Connect GitHub Actions to Azure Without Storing Passwords
199+
- **Subtitle:** How Federated Identity Credentials Replace Long-Lived Secrets With Short-Lived OIDC Tokens
200+
- **File:** `blogs/series-5-devops-data/5.5-azure-oidc-github-actions.md`
201+
- **Code:** Walkthrough of `infra/scripts/setup-oidc.sh` (already written)
202+
- **Branch:** `feature/5.3-5.8-azure-deployment-series`
203+
- **Notes:** Explains the existing setup-oidc.sh script step by step; covers 4 GitHub Secrets.
204+
205+
- [ ] **Article 5.6 — Deploy .NET Apps**
206+
- **Title:** Deploy .NET API and IdentityServer to Azure App Service with GitHub Actions
207+
- **Subtitle:** Restore, Build, Test, Publish, and Deploy — Automatically on Every Push to Main
208+
- **File:** `blogs/series-5-devops-data/5.6-azure-deploy-dotnet-apps.md`
209+
- **Code:** `.github/workflows/deploy-api.yml`, `.github/workflows/deploy-identityserver.yml`
210+
- **Branch:** `feature/5.3-5.8-azure-deployment-series`
211+
- **Notes:** Covers deployment order (IdentityServer first), App Service config, EF Core migrations.
212+
213+
- [ ] **Article 5.7 — Deploy Angular**
214+
- **Title:** Deploy Angular to Azure Static Web Apps: Zero Cost, Global CDN, Auto PR Previews
215+
- **Subtitle:** Inject Environment URLs at Build Time and Let GitHub Actions Handle the Rest
216+
- **File:** `blogs/series-5-devops-data/5.7-azure-deploy-angular-swa.md`
217+
- **Code:** `.github/workflows/deploy-angular.yml`, `staticwebapp.config.json`
218+
- **Branch:** `feature/5.3-5.8-azure-deployment-series`
219+
- **Notes:** Covers environment URL injection at build time and SPA fallback routing config.
220+
221+
- [ ] **Article 5.8 — Post-Deployment Configuration and Validation**
222+
- **Title:** Connect the Stack: Post-Deployment Configuration and Validation
223+
- **Subtitle:** Wire Up IdentityServer Redirect URIs, CORS, and Validate the Full Login Flow on Azure
224+
- **File:** `blogs/series-5-devops-data/5.8-azure-post-deployment-config.md`
225+
- **Branch:** `feature/5.3-5.8-azure-deployment-series`
226+
- **Notes:** Blog only — configuration checklist, common failure patterns, end-to-end validation steps.
227+
178228
---
179229

180230
## 🤖 Series 6: AI App Features
@@ -257,10 +307,10 @@
257307

258308
## 📊 Publication Tracker
259309

260-
**Total articles planned:** 31
310+
**Total articles planned:** 37
261311
**Published:** 1
262312
**Draft ready:** 22
263-
**Not started:** 10 (Series 6 & 7)
313+
**Not started:** 16 (Series 5 Azure sub-series × 6, Series 6 × 6, Series 7 × 4)
264314

265315
---
266316

0 commit comments

Comments
 (0)