Skip to content

Commit e91339c

Browse files
Merge branch 'release/1.13.0'
2 parents 3a2e1da + 057fc26 commit e91339c

23 files changed

+799
-81
lines changed

.github/workflows/build-and-test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
runs-on: windows-latest # Required for some (WPF) projects
1717

1818
steps:
19-
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
19+
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
2020
id: checkout
2121
with:
2222
fetch-depth: 0

.github/workflows/dependabot-auto-merge.yml

Lines changed: 0 additions & 33 deletions
This file was deleted.

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,3 +158,7 @@ data/dsl/*.java
158158
# Nodejs / NPM
159159
node_modules
160160
package-lock.json
161+
162+
# Azure / .NET Aspire
163+
.azure
164+
infra/

deployment/cake/aspire-tasks.cake

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
#l "aspire-variables.cake"
2+
3+
using System.Xml.Linq;
4+
5+
//-------------------------------------------------------------
6+
7+
public class AspireProcessor : ProcessorBase
8+
{
9+
public AspireProcessor(BuildContext buildContext)
10+
: base(buildContext)
11+
{
12+
13+
}
14+
15+
public override bool HasItems()
16+
{
17+
return BuildContext.Aspire.Items.Count > 0;
18+
}
19+
20+
public override async Task PrepareAsync()
21+
{
22+
if (!HasItems())
23+
{
24+
return;
25+
}
26+
27+
// Nothing needed
28+
}
29+
30+
public override async Task UpdateInfoAsync()
31+
{
32+
if (!HasItems())
33+
{
34+
return;
35+
}
36+
37+
// Nothing needed
38+
}
39+
40+
public override async Task BuildAsync()
41+
{
42+
if (!HasItems())
43+
{
44+
return;
45+
}
46+
47+
// Nothing needed
48+
}
49+
50+
public override async Task PackageAsync()
51+
{
52+
if (!HasItems())
53+
{
54+
return;
55+
}
56+
57+
var aspireContext = BuildContext.Aspire;
58+
59+
if (aspireContext.Items.Count > 1)
60+
{
61+
throw new InvalidOperationException("Multiple Aspire projects found. Please ensure only one Aspire project is defined in the solution.");
62+
}
63+
64+
var environmentName = GetEnvironmentName(aspireContext);
65+
66+
foreach (var aspireProject in aspireContext.Items)
67+
{
68+
if (BuildContext.General.SkipComponentsThatAreNotDeployable &&
69+
!ShouldPackageProject(BuildContext, aspireProject))
70+
{
71+
CakeContext.Information("Aspire project '{0}' should not be packaged", aspireProject);
72+
continue;
73+
}
74+
75+
BuildContext.CakeContext.LogSeparator("Packaging Aspire project '{0}'", aspireProject);
76+
77+
BuildContext.CakeContext.Information("Setting environment variables");
78+
79+
var environmentVariables = new Dictionary<string, string>
80+
{
81+
{ "AZURE_PRINCIPAL_ID", aspireContext.AzurePrincipalId },
82+
{ "AZURE_PRINCIPAL_TYPE", aspireContext.AzurePrincipalType },
83+
{ "AZURE_LOCATION", aspireContext.AzureLocation },
84+
{ "AZURE_RESOURCE_GROUP", $"rg-{aspireContext.AzureResourceGroup}-{aspireContext.EnvironmentName}" },
85+
{ "AZURE_SUBSCRIPTION_ID", aspireContext.AzureSubscriptionId },
86+
{ "AZURE_ENV_NAME", aspireContext.EnvironmentName },
87+
};
88+
89+
foreach (var environmentVariable in environmentVariables)
90+
{
91+
RunAzd($"env set {environmentVariable.Key}=\"{environmentVariable.Value}\" -e {environmentName} --no-prompt");
92+
}
93+
94+
BuildContext.CakeContext.Information("Generating infrastructure context");
95+
96+
RunAzd($"infra gen -e {environmentName} --force");
97+
98+
BuildContext.CakeContext.LogSeparator();
99+
}
100+
}
101+
102+
public override async Task DeployAsync()
103+
{
104+
if (!HasItems())
105+
{
106+
return;
107+
}
108+
109+
var aspireContext = BuildContext.Aspire;
110+
111+
if (aspireContext.Items.Count > 1)
112+
{
113+
throw new InvalidOperationException("Multiple Aspire projects found. Please ensure only one Aspire project is defined in the solution.");
114+
}
115+
116+
var environmentName = GetEnvironmentName(aspireContext);
117+
118+
foreach (var aspireProject in aspireContext.Items)
119+
{
120+
if (!ShouldDeployProject(BuildContext, aspireProject))
121+
{
122+
CakeContext.Information("Aspire project '{0}' should not be deployed", aspireProject);
123+
continue;
124+
}
125+
126+
BuildContext.CakeContext.LogSeparator("Deploying Aspire project '{0}'", aspireProject);
127+
128+
try
129+
{
130+
BuildContext.CakeContext.Information("Logging in to Azure");
131+
132+
RunAzd($"auth login --tenant-id {aspireContext.AzureTenantId} --client-id {aspireContext.AzureClientId} --client-secret {aspireContext.AzureClientSecret}");
133+
134+
// Note: got weird errors when running provision and deploy manually, so using up instead
135+
136+
BuildContext.CakeContext.Information("Deploying to Azure");
137+
138+
RunAzd($"up -e {environmentName}");
139+
140+
//BuildContext.CakeContext.Information("Provisioning infrastructure for Aspire project '{0}'", aspireProject);
141+
142+
//RunAzd($"provision -e {environmentName}");
143+
144+
//BuildContext.CakeContext.Information("Deploying Aspire project '{0}'", aspireProject);
145+
146+
// Note: this could technically be improved in the future by using
147+
// azd deploy 'componentname'
148+
149+
//RunAzd($"deploy --all -e {environmentName}");
150+
151+
await BuildContext.Notifications.NotifyAsync(aspireProject, string.Format("Deployed to Azure"), TargetType.AspireProject);
152+
}
153+
finally
154+
{
155+
BuildContext.CakeContext.Information("Logging out of Azure");
156+
157+
RunAzd($"auth logout");
158+
}
159+
160+
BuildContext.CakeContext.LogSeparator();
161+
}
162+
}
163+
164+
public override async Task FinalizeAsync()
165+
{
166+
// Nothing needed
167+
}
168+
169+
private string GetEnvironmentName(AspireContext aspireContext)
170+
{
171+
// Because resource group names are set: "rg-{environmentName}" by Aspire, we automatically add
172+
// an extra name to the environment
173+
174+
var environmentName = $"{aspireContext.AzureResourceGroup}-{aspireContext.EnvironmentName}";
175+
176+
return environmentName;
177+
}
178+
179+
private void RunAzd(string arguments)
180+
{
181+
if (BuildContext.CakeContext.StartProcess("azd", new ProcessSettings
182+
{
183+
Arguments = arguments
184+
}) != 0)
185+
{
186+
throw new CakeException("Azd failed failed. Please check the logs for more details.");
187+
}
188+
}
189+
}
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
#l "buildserver.cake"
2+
3+
//-------------------------------------------------------------
4+
5+
public class AspireContext : BuildContextWithItemsBase
6+
{
7+
public AspireContext(IBuildContext parentBuildContext)
8+
: base(parentBuildContext)
9+
{
10+
}
11+
12+
public string EnvironmentName { get; set; }
13+
14+
public string AzurePrincipalId { get; set; }
15+
16+
public string AzurePrincipalType { get; set; }
17+
18+
public string AzureLocation { get; set; }
19+
20+
public string AzureResourceGroup { get; set; }
21+
22+
public string AzureSubscriptionId { get; set; }
23+
24+
public string AzureTenantId { get; set; }
25+
26+
public string AzureClientId { get; set; }
27+
28+
public string AzureClientSecret { get; set; }
29+
30+
protected override void ValidateContext()
31+
{
32+
if (Items.Count == 0)
33+
{
34+
return;
35+
}
36+
37+
if (Items.Count > 1)
38+
{
39+
throw new InvalidOperationException("Multiple Aspire projects found. Please ensure only one Aspire project is defined in the solution.");
40+
}
41+
42+
if (string.IsNullOrWhiteSpace(EnvironmentName))
43+
{
44+
throw new InvalidOperationException("Environment name is not set. Please set the 'AspireEnvironment' variable.");
45+
}
46+
47+
if (string.IsNullOrWhiteSpace(AzurePrincipalId))
48+
{
49+
throw new InvalidOperationException("Azure principal ID is not set. Please set the 'AzurePrincipalId' variable.");
50+
}
51+
52+
if (string.IsNullOrWhiteSpace(AzureLocation))
53+
{
54+
throw new InvalidOperationException("Azure location is not set. Please set the 'AzureLocation' variable.");
55+
}
56+
57+
if (string.IsNullOrWhiteSpace(AzureResourceGroup))
58+
{
59+
throw new InvalidOperationException("Azure resource group is not set. Please set the 'AzureResourceGroup' variable.");
60+
}
61+
62+
if (string.IsNullOrWhiteSpace(AzureSubscriptionId))
63+
{
64+
throw new InvalidOperationException("Azure subscription ID is not set. Please set the 'AzureSubscriptionId' variable.");
65+
}
66+
67+
if (string.IsNullOrWhiteSpace(AzureTenantId))
68+
{
69+
throw new InvalidOperationException("Azure tenant ID is not set. Please set the 'AzureTenantId' variable.");
70+
}
71+
72+
if (string.IsNullOrWhiteSpace(AzureClientId))
73+
{
74+
throw new InvalidOperationException("Azure client ID is not set. Please set the 'AzureClientId' variable.");
75+
}
76+
77+
if (string.IsNullOrWhiteSpace(AzureClientSecret))
78+
{
79+
throw new InvalidOperationException("Azure client secret is not set. Please set the 'AzureClientSecret' variable.");
80+
}
81+
}
82+
83+
protected override void LogStateInfoForContext()
84+
{
85+
CakeContext.Information($"Found '{Items.Count}' Aspire projects");
86+
}
87+
}
88+
89+
//-------------------------------------------------------------
90+
91+
private AspireContext InitializeAspireContext(BuildContext buildContext, IBuildContext parentBuildContext)
92+
{
93+
var data = new AspireContext(parentBuildContext)
94+
{
95+
Items = AspireProjects ?? new List<string>(),
96+
EnvironmentName = buildContext.BuildServer.GetVariable("AspireEnvironment", "prod", showValue: true),
97+
AzurePrincipalId = buildContext.BuildServer.GetVariable("AspireAzurePrincipalId", showValue: true),
98+
AzurePrincipalType = buildContext.BuildServer.GetVariable("AspireAzurePrincipalType", "ManagedIdentity", showValue: true),
99+
AzureLocation = buildContext.BuildServer.GetVariable("AspireAzureLocation", showValue: true),
100+
AzureResourceGroup = buildContext.BuildServer.GetVariable("AspireAzureResourceGroup", showValue: true),
101+
AzureSubscriptionId = buildContext.BuildServer.GetVariable("AspireAzureSubscriptionId", showValue: true),
102+
AzureTenantId = buildContext.BuildServer.GetVariable("AspireAzureTenantId", showValue: true),
103+
AzureClientId = buildContext.BuildServer.GetVariable("AspireAzureClientId", showValue: true),
104+
AzureClientSecret = buildContext.BuildServer.GetVariable("AspireAzureClientSecret", showValue: false)
105+
};
106+
107+
return data;
108+
}
109+
110+
//-------------------------------------------------------------
111+
112+
List<string> _aspireProjects;
113+
114+
public List<string> AspireProjects
115+
{
116+
get
117+
{
118+
if (_aspireProjects is null)
119+
{
120+
_aspireProjects = new List<string>();
121+
}
122+
123+
return _aspireProjects;
124+
}
125+
}

0 commit comments

Comments
 (0)