Skip to content

Commit 0910dfd

Browse files
committed
Refactor template into ChengYuan modular core
1 parent 1bdd01a commit 0910dfd

145 files changed

Lines changed: 5964 additions & 485 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -626,7 +626,7 @@ jobs:
626626
run: |
627627
set -euo pipefail
628628
TAG="${{ needs.resolve-version.outputs.tag }}"
629-
RELEASE_NAME="dotnet.CI.template $TAG"
629+
RELEASE_NAME="ChengYuan $TAG"
630630
631631
shopt -s nullglob
632632
RELEASE_ASSETS=()

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ Thank you for your interest in contributing to this project!
1111

1212
```bash
1313
git clone <repo-url>
14-
cd dotnet.CI.template
14+
cd <repo-folder>
1515
dotnet restore
1616
dotnet build
1717
dotnet test

ChengYuan.slnx

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<Solution>
2+
<Folder Name="/src/Framework/">
3+
<Project Path="src/Framework/ChengYuan.Core/ChengYuan.Core/ChengYuan.Core.csproj" />
4+
<Project Path="src/Framework/ChengYuan.Core/ChengYuan.Core.Runtime/ChengYuan.Core.Runtime.csproj" />
5+
<Project Path="src/Framework/ChengYuan.Core/ChengYuan.Core.Json/ChengYuan.Core.Json.csproj" />
6+
<Project Path="src/Framework/ChengYuan.Core/ChengYuan.Core.Validation/ChengYuan.Core.Validation.csproj" />
7+
<Project Path="src/Framework/ChengYuan.Core/ChengYuan.Core.Localization/ChengYuan.Core.Localization.csproj" />
8+
<Project Path="src/Framework/ChengYuan.Core/ChengYuan.Core.Data/ChengYuan.Core.Data.csproj" />
9+
<Project Path="src/Framework/ChengYuan.Core/ChengYuan.Core.EntityFrameworkCore/ChengYuan.Core.EntityFrameworkCore.csproj" />
10+
<Project Path="src/Framework/ChengYuan.Hosting/ChengYuan.Hosting.csproj" />
11+
<Project Path="src/Framework/ChengYuan.Domain/ChengYuan.Domain.Abstractions/ChengYuan.Domain.Abstractions.csproj" />
12+
<Project Path="src/Framework/ChengYuan.Domain/ChengYuan.Domain.Runtime/ChengYuan.Domain.Runtime.csproj" />
13+
<Project Path="src/Framework/ChengYuan.Domain/ChengYuan.Domain.EntityFrameworkCore/ChengYuan.Domain.EntityFrameworkCore.csproj" />
14+
<Project Path="src/Framework/ChengYuan.Caching/ChengYuan.Caching.Abstractions/ChengYuan.Caching.Abstractions.csproj" />
15+
<Project Path="src/Framework/ChengYuan.Caching/ChengYuan.Caching.Runtime/ChengYuan.Caching.Runtime.csproj" />
16+
<Project Path="src/Framework/ChengYuan.Caching/ChengYuan.Caching.Memory/ChengYuan.Caching.Memory.csproj" />
17+
<Project Path="src/Framework/ChengYuan.Outbox/ChengYuan.Outbox.Abstractions/ChengYuan.Outbox.Abstractions.csproj" />
18+
<Project Path="src/Framework/ChengYuan.Outbox/ChengYuan.Outbox.Runtime/ChengYuan.Outbox.Runtime.csproj" />
19+
<Project Path="src/Framework/ChengYuan.Outbox/ChengYuan.Outbox.Persistence/ChengYuan.Outbox.Persistence.csproj" />
20+
<Project Path="src/Framework/ChengYuan.Outbox/ChengYuan.Outbox.Worker/ChengYuan.Outbox.Worker.csproj" />
21+
<Project Path="src/Framework/ChengYuan.ExecutionContext/ChengYuan.ExecutionContext.Abstractions/ChengYuan.ExecutionContext.Abstractions.csproj" />
22+
<Project Path="src/Framework/ChengYuan.ExecutionContext/ChengYuan.ExecutionContext.Runtime/ChengYuan.ExecutionContext.Runtime.csproj" />
23+
<Project Path="src/Framework/ChengYuan.MultiTenancy/ChengYuan.MultiTenancy.Abstractions/ChengYuan.MultiTenancy.Abstractions.csproj" />
24+
<Project Path="src/Framework/ChengYuan.MultiTenancy/ChengYuan.MultiTenancy.Runtime/ChengYuan.MultiTenancy.Runtime.csproj" />
25+
</Folder>
26+
<Folder Name="/src/Applications/" />
27+
<Folder Name="/src/Hosts/">
28+
<Project Path="src/Hosts/ChengYuan.WebHost/ChengYuan.WebHost.csproj" />
29+
<Project Path="src/Hosts/ChengYuan.CliHost/ChengYuan.CliHost.csproj" />
30+
</Folder>
31+
<Folder Name="/tests/">
32+
<Project Path="tests/ChengYuan.ArchitectureTests/ChengYuan.ArchitectureTests.csproj" />
33+
<Project Path="tests/ChengYuan.FrameworkKernel.Tests/ChengYuan.FrameworkKernel.Tests.csproj" />
34+
</Folder>
35+
<Project Path="build/_build.csproj" />
36+
</Solution>

Directory.Packages.props

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@
66
<ItemGroup>
77
<!-- Build tooling -->
88
<PackageVersion Include="Nuke.Common" Version="10.1.0" />
9+
<!-- Runtime dependencies -->
10+
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="10.0.0" />
11+
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="10.0.0" />
12+
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.0" />
13+
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="10.0.0" />
14+
<PackageVersion Include="Microsoft.EntityFrameworkCore.InMemory" Version="10.0.0" />
915
<!-- Analyzers -->
1016
<PackageVersion Include="Microsoft.CodeAnalysis.PublicApiAnalyzers" Version="5.0.0-1.25277.114" />
1117
<!-- Testing -->

Dotnet.CI.Template.slnx

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,19 @@
11
<Solution>
2-
<Folder Name="/src/">
3-
<Project Path="src/Dotnet.CI.Template.Sample/Dotnet.CI.Template.Sample.csproj" />
2+
<Folder Name="/src/Framework/">
3+
<Project Path="src/Framework/ChengYuan.Hosting/ChengYuan.Hosting.csproj" />
4+
<Project Path="src/Framework/ChengYuan.ExecutionContext/ChengYuan.ExecutionContext.Abstractions/ChengYuan.ExecutionContext.Abstractions.csproj" />
5+
<Project Path="src/Framework/ChengYuan.ExecutionContext/ChengYuan.ExecutionContext.Runtime/ChengYuan.ExecutionContext.Runtime.csproj" />
6+
<Project Path="src/Framework/ChengYuan.MultiTenancy/ChengYuan.MultiTenancy.Abstractions/ChengYuan.MultiTenancy.Abstractions.csproj" />
7+
<Project Path="src/Framework/ChengYuan.MultiTenancy/ChengYuan.MultiTenancy.Runtime/ChengYuan.MultiTenancy.Runtime.csproj" />
8+
</Folder>
9+
<Folder Name="/src/Applications/" />
10+
<Folder Name="/src/Hosts/">
11+
<Project Path="src/Hosts/ChengYuan.WebHost/ChengYuan.WebHost.csproj" />
12+
<Project Path="src/Hosts/ChengYuan.CliHost/ChengYuan.CliHost.csproj" />
413
</Folder>
514
<Folder Name="/tests/">
6-
<Project Path="tests/Dotnet.CI.Template.Sample.Tests/Dotnet.CI.Template.Sample.Tests.csproj" />
15+
<Project Path="tests/ChengYuan.ArchitectureTests/ChengYuan.ArchitectureTests.csproj" />
16+
<Project Path="tests/ChengYuan.FrameworkKernel.Tests/ChengYuan.FrameworkKernel.Tests.csproj" />
717
</Folder>
818
<Project Path="build/_build.csproj" />
919
</Solution>

README.md

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Dotnet.CI.Template
1+
# ChengYuan
22

33
[![CI and Release](https://github.com/AGIBuild/dotnet.CI.template/actions/workflows/ci.yml/badge.svg)](https://github.com/AGIBuild/dotnet.CI.template/actions/workflows/ci.yml)
44
[![CodeQL](https://github.com/AGIBuild/dotnet.CI.template/actions/workflows/codeql.yml/badge.svg)](https://github.com/AGIBuild/dotnet.CI.template/actions/workflows/codeql.yml)
@@ -14,7 +14,7 @@ This repository is a **productized starter** that gives you:
1414

1515
CI/CD is here, but it is not the protagonist; your product is.
1616

17-
![Dotnet.CI.Template Home](.github/assets/readme/docs-home-hero.png)
17+
![ChengYuan Home](.github/assets/readme/docs-home-hero.png)
1818

1919
## Why This Repo Exists
2020

@@ -24,7 +24,7 @@ Most new projects lose momentum in the first week to repetitive setup:
2424
- standardizing versioning
2525
- bolting on documentation later
2626

27-
`Dotnet.CI.Template` removes that tax. You start with a working product baseline and focus on business features from day one.
27+
`ChengYuan` removes that tax. You start with a working product baseline and focus on business features from day one.
2828

2929
## Product Capabilities
3030

@@ -49,7 +49,7 @@ Most new projects lose momentum in the first week to repetitive setup:
4949

5050
## What Makes It Better Than Starting Empty
5151

52-
| Comparison | Blank Repo | Dotnet.CI.Template |
52+
| Comparison | Blank Repo | ChengYuan |
5353
|---|---|---|
5454
| First successful release | days of setup | built-in path |
5555
| Build orchestration | mixed shell + YAML | NUKE targets |
@@ -77,17 +77,25 @@ Product Code (src/) + Tests (tests/)
7777
## Quick Start
7878

7979
1. Create your repository from this template:
80-
[Use this template](https://github.com/AGIBuild/dotnet.CI.template/generate)
81-
2. Run the init wizard to rename everything:
80+
[Use this template](https://github.com/AGIBuild/dotnet.CI.template/generate)
81+
2. Restore, build, and validate the current skeleton:
8282

8383
```bash
84-
./init.sh # interactive (Linux/macOS)
85-
./init.ps1 # interactive (Windows)
84+
dotnet restore ChengYuan.slnx
85+
dotnet build ChengYuan.slnx
86+
dotnet test --solution ChengYuan.slnx
8687
```
8788

88-
3. Configure `release` environment in GitHub (`Settings` -> `Environments`)
89-
4. Add `NUGET_API_KEY` secret (if `ENABLE_NUGET` is `true`)
90-
5. Review [Feature Switches](#feature-switches), then push to `main`
89+
3. Run one of the thin hosts to verify composition:
90+
91+
```bash
92+
dotnet run --project src/Hosts/ChengYuan.WebHost
93+
dotnet run --project src/Hosts/ChengYuan.CliHost
94+
```
95+
96+
4. Configure `release` environment in GitHub (`Settings` -> `Environments`)
97+
5. Add `NUGET_API_KEY` secret (if `ENABLE_NUGET` is `true`)
98+
6. Review [Feature Switches](#feature-switches), then push to `main`
9199

92100
## Feature Switches
93101

build/BuildTask.Parameters.cs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,20 @@ partial class BuildTask
1212
[Parameter("Version suffix for prerelease builds (e.g., ci.158)")]
1313
readonly string VersionSuffix = string.Empty;
1414

15+
[Parameter("Host to publish - supported values are 'web' and 'cli'")]
16+
new readonly string Host = string.Empty;
1517

1618
// Internal path conventions controlled by build tasks (not external parameters).
17-
readonly string BuildPath = "Dotnet.CI.Template.slnx";
18-
readonly string TestPath = "Dotnet.CI.Template.slnx";
19-
readonly string PackPath = "Dotnet.CI.Template.slnx";
20-
readonly string PublishPath = "src/Dotnet.CI.Template.Sample/Dotnet.CI.Template.Sample.csproj";
19+
readonly string BuildPath = "ChengYuan.slnx";
20+
readonly string TestPath = "ChengYuan.slnx";
21+
readonly string PackPath = "ChengYuan.slnx";
22+
string NormalizedHost => Host.Trim().ToLowerInvariant();
23+
string PublishPath => NormalizedHost switch
24+
{
25+
"web" => "src/Hosts/ChengYuan.WebHost/ChengYuan.WebHost.csproj",
26+
"cli" => "src/Hosts/ChengYuan.CliHost/ChengYuan.CliHost.csproj",
27+
_ => string.Empty
28+
};
2129

2230
// Publish inputs.
2331
[Parameter("Target runtime identifier used by Publish target")]

build/BuildTask.Targets.Init.cs

Lines changed: 3 additions & 192 deletions
Original file line numberDiff line numberDiff line change
@@ -1,202 +1,13 @@
11
using System;
2-
using System.Diagnostics;
3-
using System.IO;
4-
using System.Linq;
5-
using System.Text.RegularExpressions;
62
using Nuke.Common;
7-
using Nuke.Common.IO;
8-
using static Nuke.Common.Tools.DotNet.DotNetTasks;
93

104
partial class BuildTask
115
{
12-
const string OldSampleName = "Dotnet.CI.Template.Sample";
13-
const string OldSlnName = "Dotnet.CI.Template";
14-
15-
static readonly string[] ExcludedDirectories =
16-
[".git", "node_modules", "artifacts", "dist", "bin", "obj", ".vitepress"];
17-
186
Target Init => _ => _
19-
.Requires(() => !string.IsNullOrWhiteSpace(ProjectName))
20-
.Requires(() => Regex.IsMatch(ProjectName, @"^[A-Za-z][A-Za-z0-9.]*$"))
217
.Executes(() =>
228
{
23-
Console.WriteLine($"[1/7] Replacing file contents...");
24-
ReplaceFileContents();
25-
26-
Console.WriteLine($"[2/7] Updating author...");
27-
UpdateAuthor();
28-
29-
Console.WriteLine($"[3/7] Renaming directories...");
30-
RenameDirectories();
31-
32-
Console.WriteLine($"[4/7] Renaming files...");
33-
RenameFiles();
34-
35-
Console.WriteLine($"[5/7] Resetting version to 0.1.0...");
36-
ResetVersion();
37-
38-
Console.WriteLine($"[6/7] Refreshing lock files...");
39-
DotNet($"restore {ProjectName}.slnx --force-evaluate", workingDirectory: RootDirectory);
40-
41-
if (ResetGit)
42-
{
43-
Console.WriteLine("[7/7] Resetting git history...");
44-
ResetGitHistory();
45-
}
46-
else
47-
{
48-
Console.WriteLine("[7/7] Git history preserved.");
49-
}
50-
51-
DeleteInitScripts();
52-
53-
Console.WriteLine();
54-
Console.WriteLine($"Done! Your project '{ProjectName}' is ready.");
55-
Console.WriteLine();
56-
Console.WriteLine("Next steps:");
57-
Console.WriteLine(" 1. Update GitHub URL in docs/.vitepress/config.ts");
58-
Console.WriteLine(" 2. Run: dotnet build");
9+
throw new InvalidOperationException(
10+
"The legacy initialization flow is disabled while the ChengYuan template family implementation is in progress. " +
11+
"Rename the repository explicitly and extend the framework and application modules directly.");
5912
});
60-
61-
void ReplaceFileContents()
62-
{
63-
var files = RootDirectory
64-
.GlobFiles("**/*")
65-
.Where(f => !IsExcludedPath(f) && !IsInitScript(f) && IsTextFile(f));
66-
67-
foreach (var file in files)
68-
{
69-
var content = File.ReadAllText(file);
70-
if (!content.Contains(OldSampleName) && !content.Contains(OldSlnName))
71-
continue;
72-
73-
content = content.Replace(OldSampleName, ProjectName);
74-
content = content.Replace(OldSlnName, ProjectName);
75-
File.WriteAllText(file, content);
76-
}
77-
}
78-
79-
void UpdateAuthor()
80-
{
81-
if (string.IsNullOrWhiteSpace(Author))
82-
return;
83-
84-
var csprojFiles = RootDirectory
85-
.GlobFiles("src/**/*.csproj")
86-
.Where(f => !IsExcludedPath(f));
87-
88-
foreach (var csproj in csprojFiles)
89-
{
90-
var content = File.ReadAllText(csproj);
91-
if (!content.Contains("<Authors>"))
92-
continue;
93-
94-
content = Regex.Replace(content, @"<Authors>[^<]*</Authors>", $"<Authors>{Author}</Authors>");
95-
File.WriteAllText(csproj, content);
96-
}
97-
}
98-
99-
void RenameDirectories()
100-
{
101-
var dirs = Directory.GetDirectories(RootDirectory, $"*{OldSampleName}*", SearchOption.AllDirectories)
102-
.Where(d => !IsExcludedPath((AbsolutePath)d))
103-
.OrderByDescending(d => d.Length);
104-
105-
foreach (var dir in dirs)
106-
{
107-
var newName = Path.GetFileName(dir).Replace(OldSampleName, ProjectName);
108-
var newPath = Path.Combine(Path.GetDirectoryName(dir)!, newName);
109-
Console.WriteLine($" {dir} -> {newPath}");
110-
Directory.Move(dir, newPath);
111-
}
112-
}
113-
114-
void RenameFiles()
115-
{
116-
var files = Directory.GetFiles(RootDirectory, $"*{OldSampleName}*", SearchOption.AllDirectories)
117-
.Where(f => !IsExcludedPath((AbsolutePath)f));
118-
119-
foreach (var file in files)
120-
{
121-
var newName = Path.GetFileName(file).Replace(OldSampleName, ProjectName);
122-
var newPath = Path.Combine(Path.GetDirectoryName(file)!, newName);
123-
Console.WriteLine($" {file} -> {newPath}");
124-
File.Move(file, newPath);
125-
}
126-
127-
var slnFile = RootDirectory / $"{OldSlnName}.slnx";
128-
if (File.Exists(slnFile))
129-
{
130-
var newSlnFile = RootDirectory / $"{ProjectName}.slnx";
131-
File.Move(slnFile, newSlnFile);
132-
Console.WriteLine($" {slnFile} -> {newSlnFile}");
133-
}
134-
}
135-
136-
void ResetVersion()
137-
{
138-
var propsFile = DirectoryBuildPropsFile;
139-
if (!File.Exists(propsFile))
140-
return;
141-
142-
var content = File.ReadAllText(propsFile);
143-
content = Regex.Replace(content, @"<VersionPrefix>[^<]*</VersionPrefix>", "<VersionPrefix>0.1.0</VersionPrefix>");
144-
File.WriteAllText(propsFile, content);
145-
}
146-
147-
void ResetGitHistory()
148-
{
149-
var gitDir = RootDirectory / ".git";
150-
if (Directory.Exists(gitDir))
151-
Directory.Delete(gitDir, recursive: true);
152-
153-
RunGit("init");
154-
RunGit("add .");
155-
RunGit("commit -m \"Initial commit from dotnet.CI.template\"");
156-
}
157-
158-
void DeleteInitScripts()
159-
{
160-
File.Delete(RootDirectory / "init.sh");
161-
File.Delete(RootDirectory / "init.ps1");
162-
}
163-
164-
void RunGit(string arguments)
165-
{
166-
var psi = new ProcessStartInfo("git", arguments)
167-
{
168-
WorkingDirectory = RootDirectory,
169-
UseShellExecute = false
170-
};
171-
using var process = Process.Start(psi)
172-
?? throw new InvalidOperationException($"Failed to start: git {arguments}");
173-
process.WaitForExit();
174-
if (process.ExitCode != 0)
175-
throw new InvalidOperationException($"git {arguments} exited with code {process.ExitCode}");
176-
}
177-
178-
bool IsExcludedPath(AbsolutePath path)
179-
{
180-
var relative = RootDirectory.GetRelativePathTo(path).ToString();
181-
return ExcludedDirectories.Any(d =>
182-
relative.Contains($"{d}/", StringComparison.OrdinalIgnoreCase) ||
183-
relative.Contains($"{d}\\", StringComparison.OrdinalIgnoreCase) ||
184-
relative.StartsWith($"{d}/", StringComparison.OrdinalIgnoreCase) ||
185-
relative.StartsWith($"{d}\\", StringComparison.OrdinalIgnoreCase));
186-
}
187-
188-
static bool IsInitScript(AbsolutePath path)
189-
{
190-
var name = Path.GetFileName(path);
191-
return name is "init.sh" or "init.ps1";
192-
}
193-
194-
static bool IsTextFile(AbsolutePath path)
195-
{
196-
var extension = Path.GetExtension(path).ToLowerInvariant();
197-
return extension is ".cs" or ".csproj" or ".props" or ".targets" or ".slnx" or ".sln"
198-
or ".json" or ".yml" or ".yaml" or ".xml" or ".md" or ".txt" or ".sh" or ".ps1"
199-
or ".ts" or ".js" or ".css" or ".html" or ".editorconfig" or ".gitignore"
200-
or ".config" or ".mdc" or ".toml";
201-
}
20213
}

0 commit comments

Comments
 (0)