Skip to content

Commit

Permalink
Added Build project and github actions file for the build
Browse files Browse the repository at this point in the history
  • Loading branch information
ProgrammerAL committed Apr 30, 2024
1 parent 22ae4d0 commit 3833678
Show file tree
Hide file tree
Showing 7 changed files with 342 additions and 0 deletions.
48 changes: 48 additions & 0 deletions .github/workflows/build-and-deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: Build and Deploy

on:
push:
branches: [main]
workflow_dispatch:
workflow_call:

jobs:
build-and-publish:
runs-on: ubuntu-latest
env:
CONFIGURATION: Release
DOTNET_VERSION: 8.0.x
SITE_PROJECT_NAME: SvgHelpers
SRC_DIRECTORY_PATH: ${{ github.workspace }}/src/
BUILD_ARTIFACTS_PATH: ${{ github.workspace }}/build_artifacts
PULUMI_PROJECT_DIRECTORY: ${{ github.workspace }}/infra/pulumi-infra-deploy
PULUMI_PROJECT_FILE_PATH: ${{ github.workspace }}/infra/pulumi-infra-deploy/pulumi-infra-deploy.csproj
DYNAMIC_CONTENT_UPDATER_OUTPUT_PATH: ${{ github.workspace }}/static_content_output
PULUMI_STACK_NAME: prod
PULUMI_ACCESS_TOKEN: ${{ secrets.PULUMI_ACCESS_TOKEN }}

steps:
- uses: actions/checkout@v2
- name: Setup .NET
uses: actions/setup-dotnet@v1
with:
dotnet-version: ${{ env.DOTNET_VERSION }}
- name: Setup Node
uses: actions/setup-node@v3
with:
node-version: 18.3.0
- name: Install Cloudflare Wrangler
run: npm install --location=global wrangler
- name: Install Pulumi
uses: pulumi/setup-pulumi@v2

- name: Dotnet Restore - Pulumi Project
run: dotnet restore ${{ env.PULUMI_PROJECT_FILE_PATH }}

- name: Cake - Build
run: dotnet run --project build/build/Build.csproj -- --configuration=${{ env.CONFIGURATION }} --srcDirectoryPath=${{ env.SRC_DIRECTORY_PATH }} --BuildArtifactsPath=${{ env.BUILD_ARTIFACTS_PATH }}

# - name: Cake - Deploy
# run: dotnet run --project ${{ github.workspace }}/deploy/deploy/Deploy.csproj -- --configuration=${{ env.CONFIGURATION }} --PulumiStackName=${{ env.PULUMI_STACK_NAME }} --WorkspacePath=${{ github.workspace }} --BuildArtifactsPath=${{ env.BUILD_ARTIFACTS_PATH }}


2 changes: 2 additions & 0 deletions build/build.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
dotnet run --project build/Build.csproj -- $args
exit $LASTEXITCODE;
1 change: 1 addition & 0 deletions build/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
dotnet run --project ./build/Build.csproj -- "$@"
52 changes: 52 additions & 0 deletions build/build/ApplicationBuildConfigs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using Cake.Common;
using Cake.Core;

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

public record WebsitePaths(
string ProjectName,
string PathToSln,
string ProjectFolder,
string CsprojFile,
string OutDir,
string ZipOutDir,
string ZipOutFilePath,
string UnitTestDirectory,
string UnitTestProj,
string CoverletOutDir,
string CustomJsModulesDir)
{
public static WebsitePaths LoadFromContext(ICakeContext context, string buildConfiguration, string srcDirectory, string buildArtifactsPath)
{
var projectName = "SvgHelpers";
srcDirectory += $"/{projectName}";
var pathToSln = srcDirectory + $"/{projectName}.sln";
var functionProjectDir = srcDirectory + $"/{projectName}";
var functionCsprojFile = functionProjectDir + $"/{projectName}.csproj";
var outDir = functionProjectDir + $"/bin/{buildConfiguration}/cake-build-output";
var zipOutDir = buildArtifactsPath;
var zipOutFilePath = zipOutDir + $"/svg-helpers-site.zip";
var unitTestDirectory = srcDirectory + $"/UnitTests";
var unitTestProj = unitTestDirectory + $"/UnitTests.csproj";
var coverletOutDir = unitTestDirectory + $"/coverlet-coverage-results/";
var customJsModulesDir = srcDirectory + $"/CustomNpmModules/";

return new WebsitePaths(
projectName,
pathToSln,
functionProjectDir,
functionCsprojFile,
outDir,
zipOutDir,
zipOutFilePath,
unitTestDirectory,
unitTestProj,
coverletOutDir,
customJsModulesDir);
}
}
15 changes: 15 additions & 0 deletions build/build/Build.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<LangVersion>preview</LangVersion>
<RunWorkingDirectory>$(MSBuildProjectDirectory)</RunWorkingDirectory>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Cake.Frosting" Version="4.0.0" />
<PackageReference Include="Cake.GitHub" Version="0.1.0" />
<PackageReference Include="Cake.Npm" Version="4.0.0" />
</ItemGroup>
</Project>
25 changes: 25 additions & 0 deletions build/build/Build.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31912.275
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Build", "Build.csproj", "{0C92FB17-0701-445C-8DA8-4065442B48C5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{0C92FB17-0701-445C-8DA8-4065442B48C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0C92FB17-0701-445C-8DA8-4065442B48C5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0C92FB17-0701-445C-8DA8-4065442B48C5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0C92FB17-0701-445C-8DA8-4065442B48C5}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {4B8CCF56-5733-4E25-A930-E35CF2132F0F}
EndGlobalSection
EndGlobal
199 changes: 199 additions & 0 deletions build/build/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
using System;
using System.Threading.Tasks;
using Cake.Core;
using Cake.Core.Diagnostics;
using Cake.Frosting;
using Cake.Common;
using Cake.Common.IO;
using System.IO;
using System.IO.Compression;
using Cake.Common.Tools.DotNet;
using Cake.Common.Tools.DotNet.Restore;
using Cake.Npm;
using Cake.Npm.RunScript;
using System.Threading;
using System.Linq;
using Cake.Common.Tools.DotNet.Build;
using Cake.Common.Tools.DotNet.Test;
using Cake.Common.Tools.DotNet.Publish;
using NuGet.Packaging;
using System.Collections.Generic;

public static class Program
{
public static int Main(string[] args)
{
return new CakeHost()
.UseContext<BuildContext>()
.Run(args);
}
}

public class BuildContext : FrostingContext
{
public string Target { get; }
public string BuildConfiguration { get; }
public string SrcDirectoryPath { get; }
public string BuildArtifactsPath { get; }
public WebsitePaths WebClientPaths { get; }

public BuildContext(ICakeContext context)
: base(context)
{
Target = context.Argument("target", "Default");
BuildConfiguration = context.Argument<string>("configuration");
SrcDirectoryPath = context.Argument<string>("srcDirectoryPath");
BuildArtifactsPath = context.Argument<string>("BuildArtifactsPath");

WebClientPaths = WebsitePaths.LoadFromContext(context, BuildConfiguration, SrcDirectoryPath, BuildArtifactsPath);
}
}

[TaskName(nameof(OutputParametersTask))]
public sealed class OutputParametersTask : FrostingTask<BuildContext>
{
public override void Run(BuildContext context)
{
context.Log.Information($"INFO: Current Working Directory: {context.Environment.WorkingDirectory}");

context.Log.Information($"INFO: {nameof(context.BuildConfiguration)}: {context.BuildConfiguration}");
context.Log.Information($"INFO: {nameof(context.SrcDirectoryPath)}: {context.SrcDirectoryPath}");
}
}

[IsDependentOn(typeof(OutputParametersTask))]
[TaskName(nameof(CleanTask))]
public sealed class CleanTask : FrostingTask<BuildContext>
{
public override void Run(BuildContext context)
{
context.CleanDirectory(context.WebClientPaths.OutDir);
}
}

[IsDependentOn(typeof(CleanTask))]
[TaskName(nameof(BuildTask))]
public sealed class BuildTask : FrostingTask<BuildContext>
{
public override void Run(BuildContext context)
{
//Tasks to build custom NPM packages for public web app
var buildCustomJsModulesWebAppFuncs = Directory
.EnumerateDirectories(context.WebClientPaths.CustomJsModulesDir, "*", SearchOption.TopDirectoryOnly)
.Select(x => new Action(() => PublishCustomJsModule(context, x)));

//.NET Build tasks
var buildDotnetAppFuncs = new[]
{
() => BuildDotnetApp(context, context.WebClientPaths.PathToSln),
};

var buildFuncs = buildDotnetAppFuncs.Concat(buildCustomJsModulesWebAppFuncs).ToArray();

var runner = Parallel.ForEach(buildFuncs, func => func());
while (!runner.IsCompleted)
{
Thread.Sleep(100);
}
}

private void BuildDotnetApp(BuildContext context, string pathToSln)
{
context.DotNetRestore(pathToSln);

context.DotNetBuild(pathToSln, new DotNetBuildSettings
{
NoRestore = true,
Configuration = context.BuildConfiguration
});
}

private void PublishCustomJsModule(BuildContext context, string workingDirectory)
{
var settings = new NpmRunScriptSettings
{
WorkingDirectory = workingDirectory,
ScriptName = "publish"
};

NpmRunScriptAliases.NpmRunScript(context, settings);
}
}

[IsDependentOn(typeof(BuildTask))]
[TaskName(nameof(RunUnitTestsTask))]
public sealed class RunUnitTestsTask : FrostingTask<BuildContext>
{
public override void Run(BuildContext context)
{
var testSettings = new DotNetTestSettings()
{
Configuration = context.BuildConfiguration,
NoBuild = true,
ArgumentCustomization = (args) => args.Append("/p:CollectCoverage=true /p:CoverletOutputFormat=cobertura --logger trx")
};

var runTestsFuncs = new[]
{
() => context.DotNetTest(context.WebClientPaths.UnitTestProj, testSettings),
};

var runner = Parallel.ForEach(runTestsFuncs, func => func());
while (!runner.IsCompleted)
{
Thread.Sleep(100);
}
}
}

[IsDependentOn(typeof(RunUnitTestsTask))]
[TaskName(nameof(PublishApplicationsTask))]
public sealed class PublishApplicationsTask : FrostingTask<BuildContext>
{
public override void Run(BuildContext context)
{
var buildFuncs = new List<Action>
{
() => PublishWebClient(context),
};

var runner = Parallel.ForEach(buildFuncs, func => func());
while (!runner.IsCompleted)
{
Thread.Sleep(100);
}
}

private void PublishWebClient(BuildContext context)
{
var settings = new DotNetPublishSettings()
{
NoRestore = true,
NoBuild = true,
Configuration = context.BuildConfiguration,
OutputDirectory = context.WebClientPaths.OutDir,
};

context.DotNetPublish(context.WebClientPaths.CsprojFile, settings);

//Now that the code is published, create the compressed folder
if (!Directory.Exists(context.WebClientPaths.ZipOutDir))
{
_ = Directory.CreateDirectory(context.WebClientPaths.ZipOutDir);
}

if (File.Exists(context.WebClientPaths.ZipOutFilePath))
{
File.Delete(context.WebClientPaths.ZipOutFilePath);
}

ZipFile.CreateFromDirectory(context.WebClientPaths.OutDir, context.WebClientPaths.ZipOutFilePath);
context.Log.Information($"Output client web app zip file to: {context.WebClientPaths.ZipOutFilePath}");
}
}

[IsDependentOn(typeof(PublishApplicationsTask))]
[TaskName("Default")]
public class DefaultTask : FrostingTask
{
}

0 comments on commit 3833678

Please sign in to comment.