Skip to content

Commit 4ed718d

Browse files
authored
feature nuget
updated actions for Nuget package
2 parents 796bae9 + 3e68ba2 commit 4ed718d

File tree

2 files changed

+307
-0
lines changed

2 files changed

+307
-0
lines changed
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
name: Build and Publish Template Package
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
version:
7+
description: 'Package version (e.g., 1.0.0)'
8+
required: true
9+
default: '1.0.0'
10+
author:
11+
description: 'Template author'
12+
required: true
13+
default: 'Nitin Singh'
14+
description:
15+
description: 'Template description'
16+
required: true
17+
default: 'Full-stack Clean Architecture template with .NET 9 API and Angular 19'
18+
19+
jobs:
20+
build-and-publish:
21+
runs-on: windows-latest
22+
23+
env:
24+
TEMPLATE_VERSION: ${{ github.event.inputs.version }}
25+
TEMPLATE_AUTHOR: ${{ github.event.inputs.author }}
26+
TEMPLATE_DESCRIPTION: ${{ github.event.inputs.description }}
27+
NUGET_AUTH_TOKEN: ${{ secrets.NUGET_API_KEY }}
28+
29+
steps:
30+
- name: Checkout repository
31+
uses: actions/checkout@v3
32+
with:
33+
fetch-depth: 0
34+
35+
- name: Setup .NET
36+
uses: actions/setup-dotnet@v3
37+
with:
38+
dotnet-version: '9.0.x'
39+
40+
- name: Setup NuGet
41+
uses: NuGet/setup-nuget@v1
42+
with:
43+
nuget-version: '6.x'
44+
45+
- name: Display version
46+
run: echo "Building template version ${{ env.TEMPLATE_VERSION }}"
47+
48+
- name: Create output directories
49+
run: |
50+
mkdir template-output
51+
mkdir nupkg
52+
53+
- name: Run template preparation script
54+
shell: pwsh
55+
run: |
56+
./CreateTemplate.ps1 -SourceDirectory . -TemplateNamespace Contact -OutputDirectory ./template-output
57+
58+
- name: Create .nuspec file
59+
shell: pwsh
60+
run: |
61+
$nuspecContent = @"
62+
<?xml version="1.0" encoding="utf-8"?>
63+
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
64+
<metadata>
65+
<id>CleanArchitecture.FullStack.Template</id>
66+
<version>${{ env.TEMPLATE_VERSION }}</version>
67+
<title>Clean Architecture Full-Stack Template</title>
68+
<authors>${{ env.TEMPLATE_AUTHOR }}</authors>
69+
<description>${{ env.TEMPLATE_DESCRIPTION }}</description>
70+
<tags>dotnet-new template cleanarchitecture angular fullstack docker postgresql</tags>
71+
<packageTypes>
72+
<packageType name="Template" />
73+
</packageTypes>
74+
<repository type="git" url="https://github.com/nitin27may/clean-architecture-docker-dotnet-angular" />
75+
<license type="expression">MIT</license>
76+
<projectUrl>https://github.com/nitin27may/clean-architecture-docker-dotnet-angular</projectUrl>
77+
<requireLicenseAcceptance>false</requireLicenseAcceptance>
78+
<copyright>Copyright © ${{ env.TEMPLATE_AUTHOR }} $((Get-Date).Year)</copyright>
79+
<summary>A full-stack template using Clean Architecture principles with .NET 9 API backend and Angular 19 frontend, containerized with Docker.</summary>
80+
</metadata>
81+
</package>
82+
"@
83+
84+
Set-Content -Path "./template-output/CleanArchitecture.FullStack.Template.nuspec" -Value $nuspecContent
85+
86+
- name: Update template.json metadata
87+
shell: pwsh
88+
run: |
89+
$templateJsonPath = "./template-output/.template.config/template.json"
90+
$templateJson = Get-Content -Path $templateJsonPath -Raw | ConvertFrom-Json
91+
92+
$templateJson.author = "${{ env.TEMPLATE_AUTHOR }}"
93+
$templateJson | ConvertTo-Json -Depth 10 | Set-Content -Path $templateJsonPath
94+
95+
- name: Pack template
96+
run: |
97+
nuget pack ./template-output/CleanArchitecture.FullStack.Template.nuspec -OutputDirectory ./nupkg
98+
99+
- name: Test template package
100+
run: |
101+
dotnet new install ./nupkg/CleanArchitecture.FullStack.Template.${{ env.TEMPLATE_VERSION }}.nupkg
102+
mkdir test-project
103+
cd test-project
104+
dotnet new cleanarch-fullstack --Organization TestCompany
105+
106+
- name: Upload package artifact
107+
uses: actions/upload-artifact@v3
108+
with:
109+
name: nuget-package
110+
path: ./nupkg/*.nupkg
111+
112+
- name: Push to NuGet
113+
run: |
114+
dotnet nuget push ./nupkg/CleanArchitecture.FullStack.Template.${{ env.TEMPLATE_VERSION }}.nupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json

CreateTemplate.ps1

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
<#
2+
.SYNOPSIS
3+
Prepares a Clean Architecture solution as a template.
4+
5+
.DESCRIPTION
6+
This script prepares the Clean Architecture solution as a template by
7+
tokenizing namespace references and setting up the structure for packaging.
8+
It does NOT create the actual NuGet package - this is handled separately.
9+
10+
.PARAMETER SourceDirectory
11+
The directory containing the source code to templatize. Default is the current directory.
12+
13+
.PARAMETER TemplateNamespace
14+
The current namespace prefix used in the solution that will be tokenized. Default is "Contact".
15+
16+
.PARAMETER OutputDirectory
17+
The directory where the prepared template will be created. Default is ".\template-output".
18+
#>
19+
20+
param(
21+
[string]$SourceDirectory = ".",
22+
[string]$TemplateNamespace = "Contact",
23+
[string]$OutputDirectory = ".\template-output"
24+
)
25+
26+
# Create a timestamp for logging purposes
27+
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
28+
Write-Host "[$timestamp] Template preparation process started"
29+
30+
# Ensure output directory exists and is empty
31+
if (Test-Path $OutputDirectory) {
32+
Write-Host "[$timestamp] Cleaning existing output directory..."
33+
Remove-Item -Path "$OutputDirectory\*" -Recurse -Force -ErrorAction SilentlyContinue
34+
} else {
35+
Write-Host "[$timestamp] Creating output directory..."
36+
New-Item -Path $OutputDirectory -ItemType Directory | Out-Null
37+
}
38+
39+
# Create template structure directories
40+
$templateConfigDir = Join-Path $OutputDirectory ".template.config"
41+
New-Item -Path $templateConfigDir -ItemType Directory -Force | Out-Null
42+
43+
# Copy all solution files to the output directory
44+
Write-Host "[$timestamp] Copying solution files..."
45+
$excludedItems = @(
46+
"bin", "obj", "node_modules", ".vs", ".vscode", "dist", ".git",
47+
".angular", "package-lock.json", "yarn.lock", ".env",
48+
"appsettings.Development.json", "CreateTemplate.ps1", "nupkg"
49+
)
50+
51+
# Get all directories in the source directory except excluded ones
52+
Get-ChildItem -Path $SourceDirectory -Directory |
53+
Where-Object { $excludedItems -notcontains $_.Name } |
54+
ForEach-Object {
55+
Copy-Item -Path $_.FullName -Destination $OutputDirectory -Recurse -Force
56+
}
57+
58+
# Get all files in the source directory except excluded ones or hidden files
59+
Get-ChildItem -Path $SourceDirectory -File |
60+
Where-Object {
61+
-not $_.Name.StartsWith('.') -and
62+
$_.Name -ne "CreateTemplate.ps1" -and
63+
$_.Extension -ne ".nupkg"
64+
} |
65+
ForEach-Object {
66+
Copy-Item -Path $_.FullName -Destination $OutputDirectory -Force
67+
}
68+
69+
# Clean up binary files from the output directory
70+
Write-Host "[$timestamp] Cleaning up binary and temporary files..."
71+
Get-ChildItem -Path $OutputDirectory -Include @("bin", "obj", "node_modules", ".vs", ".vscode", "dist", ".git", ".angular", ".github") -Recurse -Directory |
72+
ForEach-Object {
73+
Write-Host "Removing $($_.FullName)"
74+
Remove-Item -Path $_.FullName -Recurse -Force -ErrorAction SilentlyContinue
75+
}
76+
77+
# Find and replace namespace references in C# files
78+
Write-Host "[$timestamp] Tokenizing namespace references..."
79+
$filesToProcess = Get-ChildItem -Path $OutputDirectory -Include @("*.cs", "*.csproj", "*.sln") -Recurse -File
80+
81+
foreach ($file in $filesToProcess) {
82+
Write-Host "Processing $($file.FullName)"
83+
$content = Get-Content -Path $file.FullName -Raw
84+
85+
# Replace namespace references
86+
if ($file.Extension -eq ".cs") {
87+
$content = $content -replace "namespace\s+$TemplateNamespace\.", "namespace ${TemplateNamespace}."
88+
$content = $content -replace "using\s+$TemplateNamespace\.", "using ${TemplateNamespace}."
89+
}
90+
elseif ($file.Extension -eq ".csproj") {
91+
$content = $content -replace "<RootNamespace>$TemplateNamespace\.", "<RootNamespace>${TemplateNamespace}."
92+
$content = $content -replace "<AssemblyName>$TemplateNamespace\.", "<AssemblyName>${TemplateNamespace}."
93+
}
94+
elseif ($file.Name -eq "*.sln") {
95+
$content = $content -replace "$TemplateNamespace\.", "${TemplateNamespace}."
96+
}
97+
98+
# Write the modified content back to the file
99+
Set-Content -Path $file.FullName -Value $content -NoNewline
100+
}
101+
102+
# Create template.json configuration file
103+
Write-Host "[$timestamp] Creating template configuration..."
104+
$templateJson = @{
105+
'$schema' = "http://json.schemastore.org/template"
106+
author = "Template Author" # This will be overridden in the GitHub Action
107+
classifications = @("Web", "API", "Angular", "Clean Architecture", "Full-Stack")
108+
identity = "CleanArchitecture.FullStack.Template"
109+
name = "Clean Architecture Full-Stack Solution"
110+
shortName = "cleanarch-fullstack"
111+
tags = @{
112+
language = "C#"
113+
type = "project"
114+
}
115+
sourceName = $TemplateNamespace
116+
preferNameDirectory = $true
117+
symbols = @{
118+
Framework = @{
119+
type = "parameter"
120+
description = "The target framework for the project."
121+
datatype = "choice"
122+
choices = @(
123+
@{
124+
choice = "net9.0"
125+
description = ".NET 9.0"
126+
}
127+
)
128+
defaultValue = "net9.0"
129+
}
130+
Organization = @{
131+
type = "parameter"
132+
datatype = "string"
133+
description = "Organization name to use in the project"
134+
defaultValue = "YourCompany"
135+
replaces = $TemplateNamespace
136+
}
137+
SkipRestore = @{
138+
type = "parameter"
139+
datatype = "bool"
140+
description = "If specified, skips the automatic restore of the project on create."
141+
defaultValue = $false
142+
}
143+
IncludeAngular = @{
144+
type = "parameter"
145+
datatype = "bool"
146+
description = "If specified, includes the Angular frontend project."
147+
defaultValue = $true
148+
}
149+
}
150+
sources = @(
151+
@{
152+
source = "backend/"
153+
target = "backend/"
154+
}
155+
@{
156+
source = "frontend/"
157+
target = "frontend/"
158+
condition = "IncludeAngular"
159+
}
160+
@{
161+
source = "docker-compose.yml"
162+
target = "docker-compose.yml"
163+
}
164+
@{
165+
source = ".env-example"
166+
target = ".env-example"
167+
}
168+
@{
169+
source = "README.md"
170+
target = "README.md"
171+
}
172+
)
173+
postActions = @(
174+
@{
175+
condition = "(!SkipRestore)"
176+
description = "Restore NuGet packages required by this project."
177+
manualInstructions = @(
178+
@{
179+
text = "Run 'dotnet restore' in the backend directory"
180+
}
181+
)
182+
actionId = "210D431B-A78B-4D2F-B762-4ED3E3EA9025"
183+
continueOnError = $true
184+
}
185+
)
186+
}
187+
188+
# Convert the template configuration to JSON
189+
$templateJsonContent = $templateJson | ConvertTo-Json -Depth 10
190+
Set-Content -Path (Join-Path $templateConfigDir "template.json") -Value $templateJsonContent
191+
192+
Write-Host "[$timestamp] Template preparation completed successfully."
193+
Write-Host "Template output directory: $OutputDirectory"

0 commit comments

Comments
 (0)