mirror of https://github.com/Fody/Costura.git

6 changed files with 329 additions and 3 deletions
-
4.gitignore
-
189deployment/cake/aspire-tasks.cake
-
125deployment/cake/aspire-variables.cake
-
2deployment/cake/lib-generic.cake
-
6deployment/cake/lib-msbuild.cake
-
6deployment/cake/tasks.cake
@ -0,0 +1,189 @@ |
|||
#l "aspire-variables.cake" |
|||
|
|||
using System.Xml.Linq; |
|||
|
|||
//------------------------------------------------------------- |
|||
|
|||
public class AspireProcessor : ProcessorBase |
|||
{ |
|||
public AspireProcessor(BuildContext buildContext) |
|||
: base(buildContext) |
|||
{ |
|||
|
|||
} |
|||
|
|||
public override bool HasItems() |
|||
{ |
|||
return BuildContext.Aspire.Items.Count > 0; |
|||
} |
|||
|
|||
public override async Task PrepareAsync() |
|||
{ |
|||
if (!HasItems()) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
// Nothing needed |
|||
} |
|||
|
|||
public override async Task UpdateInfoAsync() |
|||
{ |
|||
if (!HasItems()) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
// Nothing needed |
|||
} |
|||
|
|||
public override async Task BuildAsync() |
|||
{ |
|||
if (!HasItems()) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
// Nothing needed |
|||
} |
|||
|
|||
public override async Task PackageAsync() |
|||
{ |
|||
if (!HasItems()) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
var aspireContext = BuildContext.Aspire; |
|||
|
|||
if (aspireContext.Items.Count > 1) |
|||
{ |
|||
throw new InvalidOperationException("Multiple Aspire projects found. Please ensure only one Aspire project is defined in the solution."); |
|||
} |
|||
|
|||
var environmentName = GetEnvironmentName(aspireContext); |
|||
|
|||
foreach (var aspireProject in aspireContext.Items) |
|||
{ |
|||
if (BuildContext.General.SkipComponentsThatAreNotDeployable && |
|||
!ShouldPackageProject(BuildContext, aspireProject)) |
|||
{ |
|||
CakeContext.Information("Aspire project '{0}' should not be packaged", aspireProject); |
|||
continue; |
|||
} |
|||
|
|||
BuildContext.CakeContext.LogSeparator("Packaging Aspire project '{0}'", aspireProject); |
|||
|
|||
BuildContext.CakeContext.Information("Setting environment variables"); |
|||
|
|||
var environmentVariables = new Dictionary<string, string> |
|||
{ |
|||
{ "AZURE_PRINCIPAL_ID", aspireContext.AzurePrincipalId }, |
|||
{ "AZURE_PRINCIPAL_TYPE", aspireContext.AzurePrincipalType }, |
|||
{ "AZURE_LOCATION", aspireContext.AzureLocation }, |
|||
{ "AZURE_RESOURCE_GROUP", $"rg-{aspireContext.AzureResourceGroup}-{aspireContext.EnvironmentName}" }, |
|||
{ "AZURE_SUBSCRIPTION_ID", aspireContext.AzureSubscriptionId }, |
|||
{ "AZURE_ENV_NAME", aspireContext.EnvironmentName }, |
|||
}; |
|||
|
|||
foreach (var environmentVariable in environmentVariables) |
|||
{ |
|||
RunAzd($"env set {environmentVariable.Key}=\"{environmentVariable.Value}\" -e {environmentName} --no-prompt"); |
|||
} |
|||
|
|||
BuildContext.CakeContext.Information("Generating infrastructure context"); |
|||
|
|||
RunAzd($"infra gen -e {environmentName} --force"); |
|||
|
|||
BuildContext.CakeContext.LogSeparator(); |
|||
} |
|||
} |
|||
|
|||
public override async Task DeployAsync() |
|||
{ |
|||
if (!HasItems()) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
var aspireContext = BuildContext.Aspire; |
|||
|
|||
if (aspireContext.Items.Count > 1) |
|||
{ |
|||
throw new InvalidOperationException("Multiple Aspire projects found. Please ensure only one Aspire project is defined in the solution."); |
|||
} |
|||
|
|||
var environmentName = GetEnvironmentName(aspireContext); |
|||
|
|||
foreach (var aspireProject in aspireContext.Items) |
|||
{ |
|||
if (!ShouldDeployProject(BuildContext, aspireProject)) |
|||
{ |
|||
CakeContext.Information("Aspire project '{0}' should not be deployed", aspireProject); |
|||
continue; |
|||
} |
|||
|
|||
BuildContext.CakeContext.LogSeparator("Deploying Aspire project '{0}'", aspireProject); |
|||
|
|||
try |
|||
{ |
|||
BuildContext.CakeContext.Information("Logging in to Azure"); |
|||
|
|||
RunAzd($"auth login --tenant-id {aspireContext.AzureTenantId} --client-id {aspireContext.AzureClientId} --client-secret {aspireContext.AzureClientSecret}"); |
|||
|
|||
// Note: got weird errors when running provision and deploy manually, so using up instead |
|||
|
|||
BuildContext.CakeContext.Information("Deploying to Azure"); |
|||
|
|||
RunAzd($"up -e {environmentName}"); |
|||
|
|||
//BuildContext.CakeContext.Information("Provisioning infrastructure for Aspire project '{0}'", aspireProject); |
|||
|
|||
//RunAzd($"provision -e {environmentName}"); |
|||
|
|||
//BuildContext.CakeContext.Information("Deploying Aspire project '{0}'", aspireProject); |
|||
|
|||
// Note: this could technically be improved in the future by using |
|||
// azd deploy 'componentname' |
|||
|
|||
//RunAzd($"deploy --all -e {environmentName}"); |
|||
|
|||
await BuildContext.Notifications.NotifyAsync(aspireProject, string.Format("Deployed to Azure"), TargetType.AspireProject); |
|||
} |
|||
finally |
|||
{ |
|||
BuildContext.CakeContext.Information("Logging out of Azure"); |
|||
|
|||
RunAzd($"auth logout"); |
|||
} |
|||
|
|||
BuildContext.CakeContext.LogSeparator(); |
|||
} |
|||
} |
|||
|
|||
public override async Task FinalizeAsync() |
|||
{ |
|||
// Nothing needed |
|||
} |
|||
|
|||
private string GetEnvironmentName(AspireContext aspireContext) |
|||
{ |
|||
// Because resource group names are set: "rg-{environmentName}" by Aspire, we automatically add |
|||
// an extra name to the environment |
|||
|
|||
var environmentName = $"{aspireContext.AzureResourceGroup}-{aspireContext.EnvironmentName}"; |
|||
|
|||
return environmentName; |
|||
} |
|||
|
|||
private void RunAzd(string arguments) |
|||
{ |
|||
if (BuildContext.CakeContext.StartProcess("azd", new ProcessSettings |
|||
{ |
|||
Arguments = arguments |
|||
}) != 0) |
|||
{ |
|||
throw new CakeException("Azd failed failed. Please check the logs for more details."); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,125 @@ |
|||
#l "buildserver.cake" |
|||
|
|||
//------------------------------------------------------------- |
|||
|
|||
public class AspireContext : BuildContextWithItemsBase |
|||
{ |
|||
public AspireContext(IBuildContext parentBuildContext) |
|||
: base(parentBuildContext) |
|||
{ |
|||
} |
|||
|
|||
public string EnvironmentName { get; set; } |
|||
|
|||
public string AzurePrincipalId { get; set; } |
|||
|
|||
public string AzurePrincipalType { get; set; } |
|||
|
|||
public string AzureLocation { get; set; } |
|||
|
|||
public string AzureResourceGroup { get; set; } |
|||
|
|||
public string AzureSubscriptionId { get; set; } |
|||
|
|||
public string AzureTenantId { get; set; } |
|||
|
|||
public string AzureClientId { get; set; } |
|||
|
|||
public string AzureClientSecret { get; set; } |
|||
|
|||
protected override void ValidateContext() |
|||
{ |
|||
if (Items.Count == 0) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
if (Items.Count > 1) |
|||
{ |
|||
throw new InvalidOperationException("Multiple Aspire projects found. Please ensure only one Aspire project is defined in the solution."); |
|||
} |
|||
|
|||
if (string.IsNullOrWhiteSpace(EnvironmentName)) |
|||
{ |
|||
throw new InvalidOperationException("Environment name is not set. Please set the 'AspireEnvironment' variable."); |
|||
} |
|||
|
|||
if (string.IsNullOrWhiteSpace(AzurePrincipalId)) |
|||
{ |
|||
throw new InvalidOperationException("Azure principal ID is not set. Please set the 'AzurePrincipalId' variable."); |
|||
} |
|||
|
|||
if (string.IsNullOrWhiteSpace(AzureLocation)) |
|||
{ |
|||
throw new InvalidOperationException("Azure location is not set. Please set the 'AzureLocation' variable."); |
|||
} |
|||
|
|||
if (string.IsNullOrWhiteSpace(AzureResourceGroup)) |
|||
{ |
|||
throw new InvalidOperationException("Azure resource group is not set. Please set the 'AzureResourceGroup' variable."); |
|||
} |
|||
|
|||
if (string.IsNullOrWhiteSpace(AzureSubscriptionId)) |
|||
{ |
|||
throw new InvalidOperationException("Azure subscription ID is not set. Please set the 'AzureSubscriptionId' variable."); |
|||
} |
|||
|
|||
if (string.IsNullOrWhiteSpace(AzureTenantId)) |
|||
{ |
|||
throw new InvalidOperationException("Azure tenant ID is not set. Please set the 'AzureTenantId' variable."); |
|||
} |
|||
|
|||
if (string.IsNullOrWhiteSpace(AzureClientId)) |
|||
{ |
|||
throw new InvalidOperationException("Azure client ID is not set. Please set the 'AzureClientId' variable."); |
|||
} |
|||
|
|||
if (string.IsNullOrWhiteSpace(AzureClientSecret)) |
|||
{ |
|||
throw new InvalidOperationException("Azure client secret is not set. Please set the 'AzureClientSecret' variable."); |
|||
} |
|||
} |
|||
|
|||
protected override void LogStateInfoForContext() |
|||
{ |
|||
CakeContext.Information($"Found '{Items.Count}' Aspire projects"); |
|||
} |
|||
} |
|||
|
|||
//------------------------------------------------------------- |
|||
|
|||
private AspireContext InitializeAspireContext(BuildContext buildContext, IBuildContext parentBuildContext) |
|||
{ |
|||
var data = new AspireContext(parentBuildContext) |
|||
{ |
|||
Items = AspireProjects ?? new List<string>(), |
|||
EnvironmentName = buildContext.BuildServer.GetVariable("AspireEnvironment", "prod", showValue: true), |
|||
AzurePrincipalId = buildContext.BuildServer.GetVariable("AspireAzurePrincipalId", showValue: true), |
|||
AzurePrincipalType = buildContext.BuildServer.GetVariable("AspireAzurePrincipalType", "ManagedIdentity", showValue: true), |
|||
AzureLocation = buildContext.BuildServer.GetVariable("AspireAzureLocation", showValue: true), |
|||
AzureResourceGroup = buildContext.BuildServer.GetVariable("AspireAzureResourceGroup", showValue: true), |
|||
AzureSubscriptionId = buildContext.BuildServer.GetVariable("AspireAzureSubscriptionId", showValue: true), |
|||
AzureTenantId = buildContext.BuildServer.GetVariable("AspireAzureTenantId", showValue: true), |
|||
AzureClientId = buildContext.BuildServer.GetVariable("AspireAzureClientId", showValue: true), |
|||
AzureClientSecret = buildContext.BuildServer.GetVariable("AspireAzureClientSecret", showValue: false) |
|||
}; |
|||
|
|||
return data; |
|||
} |
|||
|
|||
//------------------------------------------------------------- |
|||
|
|||
List<string> _aspireProjects; |
|||
|
|||
public List<string> AspireProjects |
|||
{ |
|||
get |
|||
{ |
|||
if (_aspireProjects is null) |
|||
{ |
|||
_aspireProjects = new List<string>(); |
|||
} |
|||
|
|||
return _aspireProjects; |
|||
} |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue