Skip to content

Commit f3befad

Browse files
authored
Merge pull request #95 from Semiteq/feature/cpm-migration
Feature/cpm migration
2 parents 4369b21 + 6b58a88 commit f3befad

18 files changed

Lines changed: 875 additions & 430 deletions

.github/dependabot.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,11 @@ updates:
1010
- "*"
1111

1212
- package-ecosystem: "nuget"
13-
directory: "/NtoLib"
13+
# Repo-root scope: with Central Package Management enabled, all versions
14+
# live in Directory.Packages.props at the repo root. Pointing dependabot
15+
# at "/" lets it discover both NtoLib.csproj and Tests/Tests.csproj and
16+
# update the central versions file in a single PR per group.
17+
directory: "/"
1418
schedule:
1519
interval: "monthly"
1620
groups:

.github/instructions/csharp.instructions.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,15 @@ COM component via `netreg.exe`.
1313

1414
- **Framework:** .NET Framework 4.8, C# 10 (`LangVersion`), `Nullable` enabled
1515
- **Solution:** `NtoLib.sln` — two projects: `NtoLib` (main library) and `Tests` (xUnit)
16-
- **csproj style:** Old-style with explicit `<Compile Include>` entries (no wildcards)
17-
- **Build:** `dotnet build` → ILRepack merges NuGet DLLs into `NtoLib.dll` (vendor SDK DLLs
18-
in `Resources/` are excluded); `netreg.exe` registers the COM component for MasterSCADA
16+
- **csproj style:** SDK-style (`Microsoft.NET.Sdk`) with `EnableDefaultCompileItems=false`;
17+
every `.cs` file is listed explicitly as `<Compile Include>` (no wildcards). Packages
18+
are referenced via `<PackageReference>`; versions live centrally in
19+
`Directory.Packages.props` (Central Package Management).
20+
- **Build:** `dotnet build` produces an un-merged `NtoLib.dll` for unit tests. Merging
21+
is gated on `/p:RunILRepack=true` (because `[InternalsVisibleTo("Tests")]` would
22+
otherwise cause CS0433 ambiguity in the test project) and runs only via
23+
`Build/Package.ps1` / `Build/deploy.ps1` after the test step. `netreg.exe` registers
24+
the merged `NtoLib.dll` as a COM component for MasterSCADA.
1925

2026
---
2127

.github/workflows/ci.yml

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ on:
99
- "Tests/**"
1010
- "Resources/**"
1111
- "NtoLib.sln"
12+
- "Directory.Packages.props"
13+
- "nuget.config"
1214
- "global.json"
1315
- ".editorconfig"
1416
- "!**.md"
@@ -19,6 +21,8 @@ on:
1921
- "Tests/**"
2022
- "Resources/**"
2123
- "NtoLib.sln"
24+
- "Directory.Packages.props"
25+
- "nuget.config"
2226
- "global.json"
2327
- ".editorconfig"
2428
- "!**.md"
@@ -45,18 +49,8 @@ jobs:
4549
with:
4650
global-json-file: global.json
4751

48-
- name: setup NuGet
49-
uses: NuGet/setup-nuget@v2
50-
51-
# NtoLib.csproj uses packages.config with MSBuild <Import> of
52-
# ..\packages\Serilog.4.3.0\build\Serilog.targets — dotnet restore does
53-
# not populate packages/ for old-style projects, so nuget.exe restore
54-
# runs first. dotnet restore then covers the Tests project's
55-
# PackageReference graph.
5652
- name: restore
57-
run: |
58-
nuget restore NtoLib.sln
59-
dotnet restore NtoLib.sln
53+
run: dotnet restore NtoLib.sln
6054

6155
- name: build
6256
run: dotnet build NtoLib.sln -c Release --no-restore

AGENTS.md

Lines changed: 59 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,37 @@ via `netreg.exe`.
66

77
- **Framework:** .NET Framework 4.8, C# 10, Nullable enabled
88
- **Solution:** `NtoLib.sln` — two projects: `NtoLib` (main library) and `Tests` (xUnit)
9-
- **csproj style:** Old-style with explicit `<Compile Include>` entries (no wildcards)
9+
- **csproj style:** SDK-style (`<Project Sdk="Microsoft.NET.Sdk">`) with explicit
10+
`<Compile Include>` entries — default item globs are disabled
11+
(`EnableDefaultCompileItems=false`, `EnableDefaultEmbeddedResourceItems=false`,
12+
`EnableDefaultNoneItems=false`) so the "no wildcards" rule still holds.
13+
- **NuGet:** `PackageReference` only; versions centrally managed in
14+
`Directory.Packages.props` at the repo root (Central Package Management).
1015

1116
## Build
1217

1318
```powershell
14-
dotnet build NtoLib.sln
15-
Build/Package.ps1 # build + ILRepack merge + archive
16-
Build/Deploy.ps1 # build + merge + copy to target machine
19+
dotnet build NtoLib.sln # un-merged DLL (used by tests)
20+
dotnet build NtoLib.sln -p:RunILRepack=true # merged DLL (used for deployment)
21+
Build/Package.ps1 # build + test + ILRepack merge + archive
22+
Build/deploy.ps1 # build + merge + copy to target machine
1723
```
1824

25+
`Build/Package.ps1` orchestrates the pipeline: it runs the test suite against the
26+
un-merged DLL, then re-builds with `-p:RunILRepack=true` to produce the merged
27+
artifact, then archives.
28+
1929
ILRepack merges all NuGet DLLs into a single `NtoLib.dll`, excluding vendor SDK DLLs
20-
(`FB.dll`, `InSAT.*`, `MasterSCADA.*`). After build, `netreg.exe NtoLib.dll /showerror`
21-
registers the COM component for MasterSCADA.
30+
(`FB.dll`, `InSAT.*`, `MasterSCADA.*`). The merge step is implemented in
31+
`NtoLib/ILRepack.targets` (invoked through MSBuild via the
32+
`ILRepack.Lib.MSBuild.Task` package); the legacy `Build/tools/Merge.ps1` PowerShell
33+
wrapper has been removed. The target is gated on the `RunILRepack` MSBuild
34+
property so a plain `dotnet build` produces an un-merged DLL — this is intentional
35+
and required, because `NtoLib` carries `[InternalsVisibleTo("Tests")]` and merging
36+
internalised NuGet types into the assembly would collide with the Tests project's
37+
own `<PackageReference>`s on the same packages (CS0433 ambiguity on
38+
`FluentResults.Result<>`, `Microsoft.Extensions.*`, etc.). After the merged build,
39+
`netreg.exe NtoLib.dll /showerror` registers the COM component for MasterSCADA.
2240

2341
## Test
2442

@@ -46,7 +64,7 @@ Code Cleanup or `jb cleanupcode`.
4664
NtoLib/
4765
├── NtoLib/ main library (FB implementations)
4866
├── Tests/ xUnit + FluentAssertions + Moq
49-
├── Build/ PowerShell pipeline (Package.ps1, Deploy.ps1, tools/)
67+
├── Build/ PowerShell pipeline (Package.ps1, deploy.ps1, tools/)
5068
├── Docs/ documentation
5169
│ ├── architecture/ primer + NtoLib patterns (LLM-targeted, not user-facing)
5270
│ ├── known_issues/ platform-level bug classes with cause and workaround
@@ -72,14 +90,46 @@ for the reading order).
7290

7391
## csproj Conventions
7492

75-
- `NtoLib.csproj` uses **explicit `<Compile Include>` entries** — no wildcards. Every new
76-
`.cs` file must be added manually.
93+
- `NtoLib.csproj` is **SDK-style** (`<Project Sdk="Microsoft.NET.Sdk">`) but uses
94+
**explicit `<Compile Include>` entries** — no wildcards. Default item globs are
95+
disabled via `EnableDefaultCompileItems=false`,
96+
`EnableDefaultEmbeddedResourceItems=false`, `EnableDefaultNoneItems=false`, and
97+
`GenerateAssemblyInfo=false`. Every new `.cs` file must be added manually.
7798
- FB XML pin configuration files must be included as **`<EmbeddedResource>`**, not `<Content>`:
7899
```xml
79100
<EmbeddedResource Include="MyFeature\MyFB.xml" />
80101
```
81102
- When adding a new FB with multiple source files, add all `<Compile Include>` and the
82103
`<EmbeddedResource>` entry in a single csproj edit to avoid partial builds.
104+
- `packages.config` is **gone** — the project uses `<PackageReference>` exclusively.
105+
106+
### Central Package Management
107+
108+
- NuGet package versions are centrally managed in `Directory.Packages.props` at the
109+
repo root (`ManagePackageVersionsCentrally=true`,
110+
`CentralPackageTransitivePinningEnabled=true`).
111+
- Add a new package by appending a `<PackageVersion Include="..." Version="..." />`
112+
entry to `Directory.Packages.props`, then reference it from the consuming csproj
113+
with `<PackageReference Include="..." />`**no `Version=` attribute on the
114+
`PackageReference`**. NuGet emits `NU1008` (hard error) if a `Version=` attribute
115+
is left in place under CPM, and `NU1010` if a referenced id has no
116+
`<PackageVersion>` entry.
117+
- Dependabot is configured against the repo root and bumps versions in
118+
`Directory.Packages.props` only; csproj files are not touched by version updates.
119+
120+
### ILRepack and `[InternalsVisibleTo("Tests")]`
121+
122+
- The merge target lives in `NtoLib/ILRepack.targets` and is wired in via the
123+
`ILRepack.Lib.MSBuild.Task` package's `$(ILRepackTargetsFile)` hook.
124+
- The target only runs when the `RunILRepack` MSBuild property is `true`. A plain
125+
`dotnet build` therefore produces an **un-merged** DLL — this is required for the
126+
Tests project to build, because merging internalises NuGet types that Tests also
127+
references directly.
128+
- `Build/Package.ps1` runs the test suite against the un-merged DLL first, then
129+
re-invokes `dotnet build NtoLib/NtoLib.csproj -c Release -p:RunILRepack=true` to
130+
produce the deployable merged artifact between the Test and Archive steps.
131+
- `Build/tools/Merge.ps1` no longer exists; do not re-introduce a PowerShell merge
132+
wrapper.
83133

84134
## Dependencies
85135

Build/Package.ps1

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,14 @@ if (-not (Test-Path $RepoRoot))
2222

2323
& (Join-Path $ToolsDir 'Build.ps1') -Configuration $Configuration -RepoRoot $RepoRoot
2424
& (Join-Path $ToolsDir 'Test.ps1') -Configuration $Configuration -RepoRoot $RepoRoot
25-
& (Join-Path $ToolsDir 'Merge.ps1') -Configuration $Configuration -RepoRoot $RepoRoot
25+
26+
# Bundle NuGet runtime dependencies into NtoLib.dll via the ILRepack.targets MSBuild target.
27+
# Gated by /p:RunILRepack=true so the preceding test build stays un-merged
28+
# (see NtoLib/ILRepack.targets header for the rationale).
29+
dotnet build (Join-Path $RepoRoot 'NtoLib\NtoLib.csproj') -c $Configuration -v minimal -p:RunILRepack=true --no-restore
30+
if ($LASTEXITCODE -ne 0)
31+
{
32+
throw "ILRepack merge step failed with exit code $LASTEXITCODE."
33+
}
34+
2635
& (Join-Path $ToolsDir 'Archive.ps1') -Configuration $Configuration -RepoRoot $RepoRoot

Build/deploy.ps1

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,14 @@ if ( [string]::IsNullOrWhiteSpace($ConfigurationDirectory))
3131
}
3232

3333
& (Join-Path $ToolsDir 'Build.ps1') -Configuration $Configuration -RepoRoot $RepoRoot
34-
& (Join-Path $ToolsDir 'Merge.ps1') -Configuration $Configuration -RepoRoot $RepoRoot
34+
35+
# Bundle NuGet runtime dependencies into NtoLib.dll via the ILRepack.targets MSBuild target.
36+
# Gated by /p:RunILRepack=true so the preceding solution build stays un-merged
37+
# (see NtoLib/ILRepack.targets header for the rationale).
38+
dotnet build (Join-Path $RepoRoot 'NtoLib\NtoLib.csproj') -c $Configuration -v minimal -p:RunILRepack=true --no-restore
39+
if ($LASTEXITCODE -ne 0)
40+
{
41+
throw "ILRepack merge step failed with exit code $LASTEXITCODE."
42+
}
43+
3544
& (Join-Path $ToolsDir 'Copy.ps1') -Configuration $Configuration -RepoRoot $RepoRoot -DestinationDirectory $DestinationDirectory -ConfigurationDirectory $ConfigurationDirectory

Build/readme.md

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -53,23 +53,18 @@ powershell -NoProfile -ExecutionPolicy Bypass -File .\Build\tools\Build.ps1
5353

5454
### 2) Слияние зависимостей (Merge)
5555

56-
Скрипт: `Build\tools\Merge.ps1`
57-
Назначение: объединение `NtoLib.dll` и большинства managed-зависимостей в один файл с помощью **ILRepack**.
56+
Слияние выполняется через MSBuild-таргет `NtoLib/ILRepack.targets`, использующий пакет **ILRepack.Lib.MSBuild.Task**. Отдельного скрипта `Merge.ps1` больше нет — таргет вызывается напрямую через `dotnet build` с флагом `-p:RunILRepack=true`.
5857

59-
Скрипт:
60-
- берёт все `*.dll` из `NtoLib\bin\<BUILD_CONFIGURATION>\`
61-
- объединяет их в `NtoLib.dll`
58+
Поведение таргета:
59+
- объединяет managed-зависимости из `NtoLib\bin\<BUILD_CONFIGURATION>\` в `NtoLib.dll`
6260
- **не включает** хостовые зависимости MasterSCADA (например `FB.dll`, `MasterSCADA.*`) и **не включает** `System.Resources.Extensions.dll`
63-
- использует `/lib:` для каталогов поиска зависимостей при анализе ссылок
61+
- активируется только при `RunILRepack=true`, чтобы юнит-тесты собирались с не-смерженной сборкой
6462

6563
Запуск:
6664
```powershell
67-
powershell -NoProfile -ExecutionPolicy Bypass -File .\Build\tools\Merge.ps1
65+
dotnet build .\NtoLib\NtoLib.csproj -c Release -p:RunILRepack=true
6866
```
6967

70-
Требование: установлен ILRepack в каталоге:
71-
- `NtoLib\packages\ILRepack.2.0.44\tools\ILRepack.exe`
72-
7368
### 3) Тесты (Test)
7469

7570
Скрипт: `Build\tools\Test.ps1`
@@ -158,9 +153,9 @@ powershell -NoProfile -ExecutionPolicy Bypass -File .\Build\Package.ps1
158153

159154
## Прямые команды dotnet (при необходимости)
160155

161-
Restore (packages.config):
156+
Restore (PackageReference + Central Package Management через `Directory.Packages.props` в корне репозитория):
162157
```powershell
163-
dotnet msbuild .\NtoLib.sln /t:Restore /p:RestorePackagesConfig=true
158+
dotnet restore .\NtoLib.sln
164159
```
165160

166161
Build:

0 commit comments

Comments
 (0)