Skip to content
Merged
  •  
  •  
  •  
54 changes: 54 additions & 0 deletions .github/workflows/generate-types-autopr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
name: Weekly Type Generation and Auto PR

on:
schedule:
- cron: '0 3 * * 1' # Every Monday at 03:00 UTC
workflow_dispatch:

permissions:
contents: write # Needed for PR creation and branch pushes

jobs:
generate-and-pr:
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Setup .NET 9
uses: actions/setup-dotnet@v4
with:
dotnet-version: '9.0.x'

- name: Restore dependencies
run: dotnet restore

- name: Run generator
run: dotnet run --project Generator/System.Management.Generator.csproj

- name: Check for changes
id: git-check
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
git add Types/**/*.g.cs || true
if git diff --cached --quiet; then
echo "no_changes=true" >> $GITHUB_OUTPUT
else
echo "no_changes=false" >> $GITHUB_OUTPUT
fi

- name: Create Pull Request
if: steps.git-check.outputs.no_changes == 'false'
uses: peter-evans/create-pull-request@v6
with:
commit-message: "chore(types): update generated types"
branch: "auto/generated-types-update"
title: "chore(types): update generated types"
body: |
Automated update of generated types from learn.microsoft.com.
This PR was created by a scheduled GitHub Action.
delete-branch: true
5 changes: 1 addition & 4 deletions .github/workflows/nuget-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@ name: Build and Publish NuGet Packages
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]

jobs:
build:
build-and-publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand All @@ -30,7 +28,6 @@ jobs:
run: dotnet pack Linq/System.Management.Linq.csproj --configuration Release --output ./nupkgs

- name: Publish to NuGet
if: github.event_name == 'push'
run: |
set -e
for pkg in ./nupkgs/*.nupkg; do
Expand Down
22 changes: 22 additions & 0 deletions .github/workflows/pr-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Build (PR)

on:
pull_request:
branches: [ master ]

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '9.0.x'

- name: Restore dependencies
run: dotnet restore

- name: Build
run: dotnet build --configuration Release --no-restore
70 changes: 70 additions & 0 deletions .github/workflows/pr-generator.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
name: PR Type Generation

on:
pull_request:
paths:
- 'Generator/*.*'
- 'Types/**/*.g.cs'
- '.github/workflows/pr-generator.yml'

jobs:
generate-and-commit:
runs-on: ubuntu-latest

permissions:
contents: write # Needed to allow push with GITHUB_TOKEN

steps:
- name: Checkout PR branch
uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.head_ref }}

- name: Check last commit author
id: last-commit
run: |
AUTHOR=$(git log -1 --pretty=format:'%an')
echo "author=$AUTHOR" >> $GITHUB_OUTPUT

- name: Setup .NET 9
if: steps.last-commit.outputs.author != 'github-actions[bot]'
uses: actions/setup-dotnet@v4
with:
dotnet-version: '9.0.x'

- name: Restore dependencies
if: steps.last-commit.outputs.author != 'github-actions[bot]'
run: dotnet restore

- name: Run generator
if: steps.last-commit.outputs.author != 'github-actions[bot]'
run: dotnet run --project Generator/System.Management.Generator.csproj

- name: Check for changes
if: steps.last-commit.outputs.author != 'github-actions[bot]'
id: git-check
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
git add Types/**/*.g.cs || true
if git diff --cached --quiet; then
echo "no_changes=true" >> $GITHUB_OUTPUT
else
echo "no_changes=false" >> $GITHUB_OUTPUT
fi

- name: Set up authentication for push
if: steps.last-commit.outputs.author != 'github-actions[bot]' && steps.git-check.outputs.no_changes == 'false'
run: |
git remote set-url origin https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Commit and push changes to PR branch
if: steps.last-commit.outputs.author != 'github-actions[bot]' && steps.git-check.outputs.no_changes == 'false'
run: |
git commit -m "chore(types): update generated types (PR auto-update)"
git push
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ bld/
[Ll]og/
[Ll]ogs/

#Allow Win32 generated files to be committed
!Types/Win32/
!Types/Win32/**

# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
Expand Down
24 changes: 16 additions & 8 deletions Generator/CodeGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,27 @@ namespace System.Management.Generator;
public class CodeGenerator
{
private static readonly HashSet<string> _excludedFolders = new(StringComparer.OrdinalIgnoreCase) { "bin", "obj" };
public const string DefaultTargetDirectory = "..\\..\\..\\..\\Types\\";

private static DirectoryInfo FindTypesDirectory()
{
var dir = new DirectoryInfo(Environment.CurrentDirectory);
while (dir != null)
{
var typesDir = new DirectoryInfo(Path.Combine(dir.FullName, "Types"));
if (typesDir.Exists)
return typesDir;
dir = dir.Parent;
}
throw new DirectoryNotFoundException("Could not find 'Types' directory in any parent directory.");
}

private readonly Dictionary<string, ClassDefinition> _classDefinitions;
private readonly DirectoryInfo _targetDirectory;

public CodeGenerator(IEnumerable<ClassDefinition> classDefinitions, string targetDirectory = DefaultTargetDirectory)
public CodeGenerator(IEnumerable<ClassDefinition> classDefinitions)
{
_classDefinitions = classDefinitions.ToDictionary(t => t.ClassName, t => t, StringComparer.InvariantCultureIgnoreCase);
_targetDirectory = new DirectoryInfo(targetDirectory);

if (!_targetDirectory.Exists)
{
_targetDirectory.Create();
}
_targetDirectory = FindTypesDirectory();
}

public void GenerateCode()
Expand Down
60 changes: 36 additions & 24 deletions Generator/DefinitionLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,23 @@ internal partial class DefinitionLoader(IEnumerable<string> classNames)

private string? CheckClass(string? className)
{
if (className == null)
{
return null;
}

if ("Win32_LogicalElement".Equals(className))
{
return CheckClass("CIM_LogicalElement");
}
if (className != null && !_classDefinitions.ContainsKey(className))

if (!_classDefinitions.ContainsKey(className))
{
if (className.IndexOf('_') == -1)
{
return CheckClass($"__{className}");
}

_classDefinitions.Add(className, default);
Console.WriteLine($"Met new class {className}.");
}
Expand Down Expand Up @@ -359,30 +370,31 @@ private static string TrimHTML(string source)
/// <param name="classUri">Specifies the list of drives to schedule for Autochk at the next reboot. The string syntax consists of the drive letter followed by a colon for the logical disk, for example: "C:"</param>
/// <param name="methodBlock"></param>
/// <returns>Returns a value of 0 (zero) if successful, and some other value if any other error occurs. Values are listed in the following list.</returns>
private static async Task<List<MethodDefinition>> ParseMethods(Uri classUri, string methodBlock)
private static Task<List<MethodDefinition>> ParseMethods(Uri classUri, string methodBlock)
{
List<MethodDefinition> result = [];
var tBodyIndex = methodBlock.IndexOf("<tbody");
foreach (Match methodRow in TableRowRegex.Matches(methodBlock[tBodyIndex..]))
{
List<string> cells = [..TableCellRegex.Matches(methodRow.Groups[1].Value).Select(c => c.Groups[1].Value)];
if (cells.Count != 2)
{
ErrorReporter.Report($"Found unexpected number({cells.Count}) of cells in method Row.");
}

var nameCell = cells[0];
var linkMatch = LinkRegex.Match(nameCell);
if (!linkMatch.Success)
{
continue;
}

var name = TrimHTML(nameCell);
var description = TrimHTML(cells[1]);
var methodPageContent = await GetPageContentsAsync(new Uri(classUri, linkMatch.Groups[1].Value));
}

return result;
// TODO: Implement method parsing logic
//var tBodyIndex = methodBlock.IndexOf("<tbody");
//foreach (Match methodRow in TableRowRegex.Matches(methodBlock[tBodyIndex..]))
//{
// List<string> cells = [..TableCellRegex.Matches(methodRow.Groups[1].Value).Select(c => c.Groups[1].Value)];
// if (cells.Count != 2)
// {
// ErrorReporter.Report($"Found unexpected number({cells.Count}) of cells in method Row.");
// }

// var nameCell = cells[0];
// var linkMatch = LinkRegex.Match(nameCell);
// if (!linkMatch.Success)
// {
// continue;
// }

// var name = TrimHTML(nameCell);
// var description = TrimHTML(cells[1]);
// var methodPageContent = await GetPageContentsAsync(new Uri(classUri, linkMatch.Groups[1].Value));
//}

return Task.FromResult(result);
}
}
8 changes: 3 additions & 5 deletions Types/Base/_ACE.g.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
/**************************************************************
* *
* WARNING: This file is autogenerated by *
* System.Management.Generator. *
* Any changes made to this file will be overwritten. *
* WARNING: This file is autogenerated by *
* System.Management.Generator. *
* Any changes made to this file will be overwritten. *
* *
**************************************************************/
namespace System.Management.Types.Base;

#nullable enable
public partial record class _ACE(ManagementObject ManagementObject) : _SecurityRelatedClass(ManagementObject)
{
/// <summary>
Expand All @@ -19,4 +18,3 @@ public partial record class _ACE(ManagementObject ManagementObject) : _SecurityR
/// </summary>
public _Trustee? Trustee => (_Trustee)ManagementObject[nameof(Trustee)];
}
#nullable disable
16 changes: 16 additions & 0 deletions Types/Base/_AbsoluteTimerInstruction.g.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**************************************************************
* *
* WARNING: This file is autogenerated by *
* System.Management.Generator. *
* Any changes made to this file will be overwritten. *
* *
**************************************************************/
namespace System.Management.Types.Base;

public partial record class _AbsoluteTimerInstruction(ManagementObject ManagementObject) : _TimerInstruction(ManagementObject)
{
/// <summary>
/// Fixed-length string in DMTF format that specifies when the timer fires.
/// </summary>
public DateTimeOffset? EventDateTime => ManagementObject.GetDateTimePropertyValue(nameof(EventDateTime));
}
20 changes: 20 additions & 0 deletions Types/Base/_AggregateEvent.g.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**************************************************************
* *
* WARNING: This file is autogenerated by *
* System.Management.Generator. *
* Any changes made to this file will be overwritten. *
* *
**************************************************************/
namespace System.Management.Types.Base;

public partial record class _AggregateEvent(ManagementObject ManagementObject) : _IndicationRelated(ManagementObject)
{
/// <summary>
/// Number of events combined to produce this single summary event.
/// </summary>
public uint? NumberOfEvents => (uint?)ManagementObject[nameof(NumberOfEvents)];
/// <summary>
/// Copy of one of the events delivered within the aggregation interval. For example, if a consumer has registered for registry key change events from the Registry Event provider, Representative would hold an instance of the RegistryKeyChangeEvent class.
/// </summary>
public object? Representative => (object)ManagementObject[nameof(Representative)];
}
Loading