Skip to content

Commit

Permalink
Removed LibraryExtractor system and use "runtimes" feature of nuget p…
Browse files Browse the repository at this point in the history
…ackages (#249)

* Removed LibraryExtractor system and use "runtimes" feature of nuget packages
* Added test suite for libplctag.NativeImport
* Adjusted documentation for libplctag.NativeImport to avoid 

---------

Signed-off-by: timyhac <[email protected]>
  • Loading branch information
timyhac authored Jul 16, 2024
1 parent 343d1b0 commit d52cd94
Show file tree
Hide file tree
Showing 48 changed files with 872 additions and 486 deletions.
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
name: Build and publish libplctag.NET nuget package
name: Release all

on: [workflow_dispatch]

jobs:
build:

runs-on: ubuntu-latest
runs-on: windows-latest

steps:
- uses: actions/checkout@v4
with:
lfs: true

- name: Publish all packages on version change
run: ./build.sh ReleaseAll --nuget-api-key ${{secrets.NUGET_API_KEY}}
run: .\build.cmd ReleaseAll --nuget-api-key ${{secrets.NUGET_API_KEY}}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: CI - Run all tests
name: Test libplctag

on: [push]

Expand All @@ -13,4 +13,4 @@ jobs:
lfs: true

- name: Build all and run tests
run: ./build.sh Test
run: ./build.sh TestLibplctag
16 changes: 16 additions & 0 deletions .github/workflows/test-libplctagNativeImport.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
name: Test libplctag.NativeImport

on: [workflow_dispatch,push]

jobs:
build:

runs-on: windows-latest

steps:
- uses: actions/checkout@v4
with:
lfs: true

- name: Build all and run tests
run: .\build.cmd TestLibplctagNativeImport
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Update libplctag core
name: Update core binaries

on:

Expand Down
12 changes: 4 additions & 8 deletions .nuke/build.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,8 @@
"PackLibplctag",
"PackLibplctagNativeImport",
"ReleaseAll",
"ReleaseLibplctag",
"ReleaseLibplctagNativeImport",
"Restore",
"Test",
"TestLibplctag",
"TestLibplctagNativeImport",
"UpdateCoreBinaries"
]
}
Expand All @@ -109,10 +107,8 @@
"PackLibplctag",
"PackLibplctagNativeImport",
"ReleaseAll",
"ReleaseLibplctag",
"ReleaseLibplctagNativeImport",
"Restore",
"Test",
"TestLibplctag",
"TestLibplctagNativeImport",
"UpdateCoreBinaries"
]
}
Expand Down
16 changes: 13 additions & 3 deletions DEVELOPERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,28 @@ GitHub Actions have been created to automate some common activities such as upda

These workflows delegate the actual automation logic to the [`_build`](../build) [NUKE](https://nuke.build/) project.

### How to release Nuget packages
## Testing libplctag.NativeImport

libplctag.NativeImport uses features of Nuget and MSBuild to distribute the libplctag core binaries.
What actually needs to be tested is that logic, which xUnit and other unit-testing frameworks are not well equipped to do.
The build project, however, is capable - and does this by creating orchestrating a package creation, and using it in the restore process for those test suites.

Different versions of .NET use packages differently (see [PackageReference vs packags.config](https://learn.microsoft.com/en-us/nuget/consume-packages/migrate-packages-config-to-package-reference)), so there are different test projects for each variation.


## How to release Nuget packages

1. Update the version number in the csproj files of the libplctag or libplctag.NativeImport projects.
2. Trigger the "Build and publish libplctag.NET nuget package" workflow.
4. Create a GitHub "Release" with details of the new release.

## How to update the core binaries libplctag.NativeImport
## How to update the libplctag core binaries

When a new version of libplctag core is released, the library binaries need to be updated in libplctag.NativeImport.
The build script can be used to copy these libraries in the project without error.

1. Trigger the "Update libplctag core" workflow.
2. Verify that the files have been correctly copied.
3. Make relevant modifications to libplctag.NativeImport such as modifying the method signatures (if required).
4. Finally, release the updated project as a new Nuget packages.
4. Release the updated project as a new Nuget package.
5. Finally, update the libplctag.NativeImport `<PackageReference>` version in the libplctag package, and release that.
184 changes: 125 additions & 59 deletions build/Build.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
using Nuke.Common.ProjectModel;
using Nuke.Common.Tools.DotNet;
using Nuke.Common.Tools.GitVersion;
using Nuke.Common.Tools.NuGet;
using Nuke.Common.Tools.VSTest;
using Nuke.Common.Utilities.Collections;
using Serilog;
using static Nuke.Common.IO.FileSystemTasks;
Expand All @@ -17,7 +19,7 @@

class Build : NukeBuild
{
public static int Main() => Execute<Build>(x => x.Test);
public static int Main() => Execute<Build>(x => x.TestLibplctag);

[Parameter("Configuration to build - Default is 'Debug' (local) or 'Release' (server)")]
readonly Configuration Configuration = IsLocalBuild ? Configuration.Debug : Configuration.Release;
Expand All @@ -29,51 +31,137 @@ class Build : NukeBuild

AbsolutePath SourceDirectory => RootDirectory / "src";
AbsolutePath ArtifactsDirectory => RootDirectory / "artifacts";
AbsolutePath PackageRestoreDirectory => SourceDirectory / "packages";
Project libplctag => Solution.GetProject("libplctag");
Project libplctag_NativeImport => Solution.GetProject("libplctag.NativeImport");


Target Clean => _ => _
.Before(Restore)
.Executes(() =>
{
DotNetClean();
SourceDirectory.GlobDirectories("**/bin", "**/obj").ForEach(dir => dir.DeleteDirectory());
ArtifactsDirectory.CreateOrCleanDirectory();
});

Target Restore => _ => _
.Executes(() =>
{
DotNetRestore(s => s
.SetProjectFile(Solution));
SourceDirectory.GlobDirectories("**/bin", "**/obj")
.Concat(ArtifactsDirectory)
.Concat(PackageRestoreDirectory)
.ForEach(dir =>
{
Log.Debug("Deleting {0}", dir);
dir.DeleteDirectory();
});
});

Target Compile => _ => _
.DependsOn(Restore)
.DependsOn(Clean)
.Executes(() =>
{
DotNetBuild(s => s
.SetProjectFile(Solution)
.SetProjectFile(libplctag)
.SetConfiguration(Configuration)
);

DotNetBuild(s => s
.SetProjectFile(libplctag_NativeImport)
.SetConfiguration(Configuration)
.EnableNoRestore()
);
});

Target Test => _ => _
Target TestLibplctag => _ => _
.DependsOn(Compile)
.Executes(() =>
{
DotNetTest(s => s
.SetProjectFile(Solution)
.SetConfiguration(Configuration)
.EnableNoRestore()
);
.SetProjectFile(libplctag)
.SetConfiguration(Configuration)
);
});


Target TestLibplctagNativeImport => _ => _
.DependsOn(PackLibplctagNativeImport)
.DependsOn(PackLibplctag)
.Executes(() =>
{
var testsNetCore = Solution.GetAllProjects("libplctag.NativeImport.Tests.NetCore.*");
var testsNetFramework = Solution.GetAllProjects("libplctag.NativeImport.Tests.NetFramework.*");

// This nuget.config file ensures that libplctag and libplctag.NativeImport are restored from the
// newly created and packed packages on disk, but still allows all other packages to be
// downloaded from the remote nuget feed.
var nuget_config_contents = $"""
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
<add key="buildArtifacts" value="{ArtifactsDirectory}" />
</packageSources>
<packageSourceMapping>
<packageSource key="nuget.org">
<package pattern="Microsoft.*" />
<package pattern="System.*" />
<package pattern="xunit*" />
<package pattern="coverlet*" />
<package pattern="runtime.*" />
<package pattern="newtonsoft.json" />
<package pattern="nuget.*" />
<package pattern="mstest.*" />
</packageSource>
<packageSource key="buildArtifacts">
<package pattern="libplctag" />
<package pattern="libplctag.NativeImport" />
</packageSource>
</packageSourceMapping>
</configuration>
""";

var nuget_config = Path.GetTempFileName() + ".nuget.config";
File.WriteAllText(nuget_config, nuget_config_contents);

foreach (var proj in testsNetFramework)
{
var outDir = proj.GetMSBuildProject(Configuration).GetPropertyValue("OutputPath");
var assembly = proj.Directory / outDir / proj.Name + ".dll";

NuGetTasks.NuGetRestore(s => s
.SetTargetPath(proj)
.SetPackagesDirectory(PackageRestoreDirectory)
.SetConfigFile(nuget_config)
);

DotNetMSBuild(s => s
.SetTargetPath(proj)
.SetConfiguration(Configuration)
.SetBinaryLog(assembly + ".binlog") // VIew with https://msbuildlog.com/
);

VSTestTasks.VSTest(assembly.ToString());
}

foreach (var proj in testsNetCore)
{
DotNetRestore(s => s
.SetProjectFile(proj)
.SetPackageDirectory(PackageRestoreDirectory)
.SetConfigFile(nuget_config)
);

DotNetBuild(s => s
.SetProjectFile(proj)
.SetConfiguration(Configuration)
.SetNoRestore(true)
);

DotNetTest(s => s
.SetProjectFile(proj)
.SetNoRestore(true)
);
}

File.Delete(nuget_config);
});


Target PackLibplctag => _ => _
.DependsOn(Test)
.Executes(() =>
{
DotNetPack(s => s
Expand All @@ -83,11 +171,10 @@ class Build : NukeBuild
.EnableNoRestore()
.SetOutputDirectory(ArtifactsDirectory)
);

});

Target PackLibplctagNativeImport => _ => _
.DependsOn(Test)
.DependsOn(Compile)
.Executes(() =>
{
DotNetPack(s => s
Expand All @@ -100,31 +187,9 @@ class Build : NukeBuild

});

Target ReleaseLibplctag => _ => _
.DependsOn(PackLibplctag)
.Requires(() => NugetApiUrl)
.Requires(() => NugetApiKey)
.Requires(() => Configuration.Equals(Configuration.Release))
.Executes(() =>
{
var version = libplctag.GetProperty("Version");
PushAndTag($"libplctag.{version}.nupkg", $"libplctag-v{version}");
});

Target ReleaseLibplctagNativeImport => _ => _
.DependsOn(PackLibplctagNativeImport)
.Requires(() => NugetApiUrl)
.Requires(() => NugetApiKey)
.Requires(() => Configuration.Equals(Configuration.Release))
.Executes(() =>
{
var version = libplctag_NativeImport.GetProperty("Version");
PushAndTag($"libplctag.NativeImport.{version}.nupkg", $"libplctag.NativeImport-v{version}");
});

Target ReleaseAll => _ => _
.DependsOn(PackLibplctag)
.DependsOn(PackLibplctagNativeImport)
.DependsOn(TestLibplctag)
.DependsOn(TestLibplctagNativeImport)
.Requires(() => NugetApiUrl)
.Requires(() => NugetApiKey)
.Requires(() => Configuration.Equals(Configuration.Release))
Expand All @@ -142,20 +207,20 @@ class Build : NukeBuild
.Executes(() =>
{

var runtimesFolder = RootDirectory / "src" / "libplctag.NativeImport" / "runtime";
var runtimesFolder = RootDirectory / "src" / "libplctag.NativeImport" / "runtimes";

(string zipFileName, string[] unzipPath, AbsolutePath destination)[] releases =
{
($"libplctag_{LibplctagCoreVersion}_macos_x64.zip", ["libplctag.dylib"], runtimesFolder/"osx_x64"/"libplctag.dylib" ),
($"libplctag_{LibplctagCoreVersion}_macos_aarch64.zip", ["libplctag.dylib"], runtimesFolder/"osx_ARM64"/"libplctag.dylib" ),
($"libplctag_{LibplctagCoreVersion}_ubuntu_x64.zip", ["libplctag.so"], runtimesFolder/"linux_x64"/"libplctag.so" ),
($"libplctag_{LibplctagCoreVersion}_ubuntu_x86.zip", ["libplctag.so"], runtimesFolder/"linux_x86"/"libplctag.so" ),
($"libplctag_{LibplctagCoreVersion}_linux_arm7l.zip", ["libplctag.so"], runtimesFolder/"linux_ARM"/"libplctag.so" ),
($"libplctag_{LibplctagCoreVersion}_linux_aarch64.zip", ["libplctag.so"], runtimesFolder/"linux_ARM64"/"libplctag.so" ),
($"libplctag_{LibplctagCoreVersion}_windows_x64.zip", ["Release", "plctag.dll"], runtimesFolder/"win_x64"/"plctag.dll" ),
($"libplctag_{LibplctagCoreVersion}_windows_x86.zip", ["Release", "plctag.dll"], runtimesFolder/"win_x86"/"plctag.dll" ),
($"libplctag_{LibplctagCoreVersion}_windows_Arm.zip", ["Release", "plctag.dll"], runtimesFolder/"win_ARM"/"plctag.dll" ),
($"libplctag_{LibplctagCoreVersion}_windows_Arm64.zip", ["Release", "plctag.dll"], runtimesFolder/"win_ARM64"/"plctag.dll" ),
($"libplctag_{LibplctagCoreVersion}_macos_x64.zip", ["libplctag.dylib"], runtimesFolder/"osx-x64"/"native"/"libplctag.dylib" ),
($"libplctag_{LibplctagCoreVersion}_macos_aarch64.zip", ["libplctag.dylib"], runtimesFolder/"osx-arm64"/"native"/"libplctag.dylib" ),
($"libplctag_{LibplctagCoreVersion}_ubuntu_x64.zip", ["libplctag.so"], runtimesFolder/"linux-x64"/"native"/"libplctag.so" ),
($"libplctag_{LibplctagCoreVersion}_ubuntu_x86.zip", ["libplctag.so"], runtimesFolder/"linux-x86"/"native"/"libplctag.so" ),
($"libplctag_{LibplctagCoreVersion}_linux_arm7l.zip", ["libplctag.so"], runtimesFolder/"linux-arm"/"native"/"libplctag.so" ),
($"libplctag_{LibplctagCoreVersion}_linux_aarch64.zip", ["libplctag.so"], runtimesFolder/"linux-arm64"/"native"/"libplctag.so" ),
($"libplctag_{LibplctagCoreVersion}_windows_x64.zip", ["Release", "plctag.dll"], runtimesFolder/"win-x64"/"native"/"plctag.dll" ),
($"libplctag_{LibplctagCoreVersion}_windows_x86.zip", ["Release", "plctag.dll"], runtimesFolder/"win-x86"/"native"/"plctag.dll" ),
($"libplctag_{LibplctagCoreVersion}_windows_Arm.zip", ["Release", "plctag.dll"], runtimesFolder/"win-arm"/"native"/"plctag.dll" ),
($"libplctag_{LibplctagCoreVersion}_windows_Arm64.zip", ["Release", "plctag.dll"], runtimesFolder/"win-arm64"/"native"/"plctag.dll" ),
};

var downloadFolder = RootDirectory / "downloads";
Expand Down Expand Up @@ -197,7 +262,8 @@ private void PushAndTag(string packageFilename, string tag)
.EnableSkipDuplicate()
);

if (output.Any(line => line.Text.Contains("Conflict", StringComparison.InvariantCultureIgnoreCase))) {
if (output.Any(line => line.Text.Contains("Conflict", StringComparison.InvariantCultureIgnoreCase)))
{
Log.Information("{0} already exists in package repository", packageFilename);
return;
}
Expand Down
5 changes: 5 additions & 0 deletions build/_build.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,9 @@
<PackageReference Include="Nuke.Common" Version="8.0.0" />
</ItemGroup>

<ItemGroup>
<PackageDownload Include="Microsoft.TestPlatform" Version="[17.10.0]" />
<PackageDownload Include="Nuget.CommandLine" Version="[6.10.1]" />
</ItemGroup>

</Project>
Loading

0 comments on commit d52cd94

Please sign in to comment.