Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@ jobs:
- name: Test pinget-cli
run: cargo test -p pinget-cli --manifest-path rust/Cargo.toml

- name: Test pinget-publisher
run: cargo test -p pinget-publisher --manifest-path rust/Cargo.toml

- name: Check publisher documentation
run: cargo doc -p pinget-publisher --manifest-path rust/Cargo.toml --no-deps

- name: Build pinget-cli
run: cargo build -p pinget-cli --manifest-path rust/Cargo.toml

Expand Down Expand Up @@ -107,6 +113,27 @@ jobs:
- name: Run core tests
run: dotnet test dotnet/src/Devolutions.Pinget.Core.Tests/Devolutions.Pinget.Core.Tests.csproj -c Release --no-build

- name: Run publisher tests
run: dotnet test dotnet/src/Devolutions.Pinget.Publisher.Tests/Devolutions.Pinget.Publisher.Tests.csproj -c Release

- name: Run Rust and .NET publisher interoperability
shell: pwsh
run: |
cargo build --manifest-path rust/Cargo.toml -p pinget-cli --release
if ($LASTEXITCODE -ne 0) { throw 'Rust publisher CLI build failed.' }
$sdkRoot = Join-Path ${env:ProgramFiles(x86)} 'Windows Kits\10\bin'
$makeAppx = Get-ChildItem -LiteralPath $sdkRoot -Directory |
Sort-Object Name -Descending |
ForEach-Object { Join-Path $_.FullName 'x64\makeappx.exe' } |
Where-Object { Test-Path -LiteralPath $_ } |
Select-Object -First 1
if (-not $makeAppx) { throw 'Windows SDK MakeAppx was not found.' }
& .\tests\publisher\run-production-conformance.ps1 `
-RustCli .\rust\target\release\pinget.exe `
-DotnetAssembly .\dotnet\src\Devolutions.Pinget.Cli\bin\Release\net10.0\pinget.dll `
-MakeAppxPath $makeAppx
if ($LASTEXITCODE -ne 0) { throw 'Publisher interoperability checks failed.' }

- name: Build native COM DLLs
shell: pwsh
env:
Expand All @@ -124,8 +151,77 @@ jobs:
run: |
New-Item -Path artifacts/ci-nuget -ItemType Directory -Force | Out-Null
dotnet pack dotnet/src/Devolutions.Pinget.Core/Devolutions.Pinget.Core.csproj -c Release --no-build -o artifacts/ci-nuget
dotnet pack dotnet/src/Devolutions.Pinget.Publisher/Devolutions.Pinget.Publisher.csproj -c Release --no-build -o artifacts/ci-nuget
dotnet pack dotnet/src/Devolutions.Pinget.PowerShell.Engine/Devolutions.Pinget.PowerShell.Engine.csproj -c Release --no-build -o artifacts/ci-nuget

- name: Validate PowerShell module packaging
shell: pwsh
run: pwsh -NoLogo -NoProfile -File (Resolve-Path 'scripts/Build-PowerShellModule.ps1') -NoBuild -OutputRoot artifacts/ci-powershell -Clean

stock-winget-acceptance:
name: Signed stock WinGet acceptance (ephemeral runner)
runs-on: windows-latest
needs:
- dotnet
timeout-minutes: 45

steps:
- name: Checkout
uses: actions/checkout@v6

- name: Setup .NET
uses: actions/setup-dotnet@v5
with:
dotnet-version: 10.0.x

- name: Setup Rust
shell: pwsh
run: |
rustup toolchain install stable --profile minimal --target x86_64-pc-windows-msvc
rustup default stable

- name: Build disposable x64 publisher CLIs
shell: pwsh
run: |
pwsh -NoLogo -NoProfile -File (Resolve-Path 'scripts/Build-CliNativeNuGetPackages.ps1') `
-Package All `
-RustRuntimeIdentifiers 'win-x64' `
-DotNetRuntimeIdentifiers 'win-x64' `
-NoPack `
-Clean `
-StagingRoot artifacts/ci-stock-winget `
-OutputRoot artifacts/ci-stock-winget-packages
if ($LASTEXITCODE -ne 0) { throw 'Building the disposable x64 publisher CLIs failed.' }

- name: Run signed stock WinGet acceptance with runner-local credentials
shell: pwsh
run: |
$sdkRoot = Join-Path ${env:ProgramFiles(x86)} 'Windows Kits\10\bin'
$sdkTools = Get-ChildItem -LiteralPath $sdkRoot -Directory |
Sort-Object Name -Descending |
ForEach-Object {
[pscustomobject]@{
MakeAppx = Join-Path $_.FullName 'x64\makeappx.exe'
SignTool = Join-Path $_.FullName 'x64\signtool.exe'
}
} |
Where-Object {
(Test-Path -LiteralPath $_.MakeAppx) -and
(Test-Path -LiteralPath $_.SignTool)
} |
Select-Object -First 1
if (-not $sdkTools) { throw 'Windows SDK MakeAppx and SignTool were not found.' }

pwsh -NoLogo -NoProfile -File (Resolve-Path 'tests/publisher/run-ephemeral-host-publisher-gate.ps1') `
-RustCliPath (Resolve-Path 'artifacts/ci-stock-winget/rust/win-x64/pinget.exe') `
-DotnetCliPath (Resolve-Path 'artifacts/ci-stock-winget/dotnet-nativeaot/win-x64/pinget.exe') `
-MakeAppxPath $sdkTools.MakeAppx `
-SignToolPath $sdkTools.SignTool
if ($LASTEXITCODE -ne 0) { throw 'Signed stock WinGet acceptance failed.' }

- name: Remove disposable build outputs
if: always()
shell: pwsh
run: |
Remove-Item -LiteralPath 'artifacts/ci-stock-winget' -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item -LiteralPath 'artifacts/ci-stock-winget-packages' -Recurse -Force -ErrorAction SilentlyContinue
4 changes: 2 additions & 2 deletions .github/workflows/cli-packages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ jobs:
os: windows-latest
rust-target: aarch64-pc-windows-msvc
- rid: osx-x64
os: macos-14
os: macos-15
rust-target: x86_64-apple-darwin
- rid: osx-arm64
os: macos-14
os: macos-15
rust-target: aarch64-apple-darwin

steps:
Expand Down
17 changes: 12 additions & 5 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -120,18 +120,20 @@ jobs:
if ([string]::IsNullOrWhiteSpace($Version)) {
$coreVersion = Select-String -Path 'rust/crates/pinget-core/Cargo.toml' -Pattern '^version = "([^"]+)"$' | Select-Object -First 1
$cliVersion = Select-String -Path 'rust/crates/pinget-cli/Cargo.toml' -Pattern '^version = "([^"]+)"$' | Select-Object -First 1
$publisherVersion = Select-String -Path 'rust/crates/pinget-publisher/Cargo.toml' -Pattern '^version = "([^"]+)"$' | Select-Object -First 1
$dotnetVersion = Select-String -Path 'dotnet/src/Devolutions.Pinget.Cli/Program.cs' -Pattern '^const string Version = "([^"]+)";$' | Select-Object -First 1

if (($null -eq $coreVersion) -or ($null -eq $cliVersion) -or ($null -eq $dotnetVersion)) {
if (($null -eq $coreVersion) -or ($null -eq $cliVersion) -or ($null -eq $publisherVersion) -or ($null -eq $dotnetVersion)) {
throw 'Unable to detect version from source files'
}

$coreVersionValue = $coreVersion.Matches[0].Groups[1].Value
$cliVersionValue = $cliVersion.Matches[0].Groups[1].Value
$publisherVersionValue = $publisherVersion.Matches[0].Groups[1].Value
$dotnetVersionValue = $dotnetVersion.Matches[0].Groups[1].Value

if (($coreVersionValue -ne $cliVersionValue) -or ($coreVersionValue -ne $dotnetVersionValue)) {
throw "Version mismatch detected: pinget-core=$coreVersionValue pinget-cli=$cliVersionValue dotnet=$dotnetVersionValue"
if (($coreVersionValue -ne $cliVersionValue) -or ($coreVersionValue -ne $publisherVersionValue) -or ($coreVersionValue -ne $dotnetVersionValue)) {
throw "Version mismatch detected: pinget-core=$coreVersionValue pinget-cli=$cliVersionValue pinget-publisher=$publisherVersionValue dotnet=$dotnetVersionValue"
}

$Version = $coreVersionValue
Expand Down Expand Up @@ -188,12 +190,12 @@ jobs:
archive_name: pinget-windows-arm64.zip
binary_name: pinget.exe
- name: macos-x64
os: macos-14
os: macos-15
target: x86_64-apple-darwin
archive_name: pinget-macos-x64.zip
binary_name: pinget
- name: macos-arm64
os: macos-14
os: macos-15
target: aarch64-apple-darwin
archive_name: pinget-macos-arm64.zip
binary_name: pinget
Expand Down Expand Up @@ -374,6 +376,9 @@ jobs:
- name: Run core tests
run: dotnet test dotnet/src/Devolutions.Pinget.Core.Tests/Devolutions.Pinget.Core.Tests.csproj -c Release --no-build

- name: Run publisher tests
run: dotnet test dotnet/src/Devolutions.Pinget.Publisher.Tests/Devolutions.Pinget.Publisher.Tests.csproj -c Release

- name: Build native COM DLLs
shell: pwsh
env:
Expand Down Expand Up @@ -443,6 +448,7 @@ jobs:

$BinaryRoots = @(
'dotnet/src/Devolutions.Pinget.Core/bin/Release',
'dotnet/src/Devolutions.Pinget.Publisher/bin/Release',
'dotnet/src/Devolutions.Pinget.PowerShell.Engine/bin/Release',
'dotnet/src/Devolutions.Pinget.PowerShell.Cmdlets/bin/Release',
'rust/target/x86_64-pc-windows-msvc/release',
Expand Down Expand Up @@ -477,6 +483,7 @@ jobs:
New-Item -Path dist/nuget -ItemType Directory -Force | Out-Null
$packArgs = @('-c', 'Release', '--no-build', '-p:ContinuousIntegrationBuild=true', "-p:Version=$env:PACKAGE_VERSION", '-p:IncludeSymbols=true', '-p:SymbolPackageFormat=snupkg', '-o', 'dist/nuget')
dotnet pack dotnet/src/Devolutions.Pinget.Core/Devolutions.Pinget.Core.csproj @packArgs
dotnet pack dotnet/src/Devolutions.Pinget.Publisher/Devolutions.Pinget.Publisher.csproj @packArgs
dotnet pack dotnet/src/Devolutions.Pinget.PowerShell.Engine/Devolutions.Pinget.PowerShell.Engine.csproj @packArgs

- name: Package PowerShell module
Expand Down
53 changes: 53 additions & 0 deletions .github/workflows/repository-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
name: Repository source build

on:
workflow_dispatch:
inputs:
manifests:
description: Repository-relative directory containing WinGet manifests
required: true
type: string

permissions:
contents: read

jobs:
build:
name: Build an unsigned source snapshot
runs-on: windows-latest
steps:
- name: Checkout
uses: actions/checkout@v6

- name: Setup Rust
shell: pwsh
run: |
rustup toolchain install stable --profile minimal
rustup default stable

- name: Build publisher CLI
run: cargo build --manifest-path rust/Cargo.toml --package pinget-cli --release

- name: Build and verify snapshot
shell: pwsh
env:
MANIFEST_INPUT: ${{ inputs.manifests }}
run: |
$ErrorActionPreference = 'Stop'
$inputRoot = [System.IO.Path]::GetFullPath((Join-Path $env:GITHUB_WORKSPACE $env:MANIFEST_INPUT))
$checkoutPrefix = [System.IO.Path]::TrimEndingDirectorySeparator($env:GITHUB_WORKSPACE) + [System.IO.Path]::DirectorySeparatorChar
if (-not $inputRoot.StartsWith($checkoutPrefix, [System.StringComparison]::OrdinalIgnoreCase)) {
throw 'Manifest directory must be inside the checkout.'
}
$stateRoot = Join-Path $env:RUNNER_TEMP 'publisher-state'
& .\rust\target\release\pinget.exe repository build --input $inputRoot --state $stateRoot
if ($LASTEXITCODE -ne 0) { throw 'Source build failed.' }
& .\rust\target\release\pinget.exe repository verify --state $stateRoot
if ($LASTEXITCODE -ne 0) { throw 'Snapshot verification failed.' }

- name: Upload source snapshot
uses: actions/upload-artifact@v7
with:
name: unsigned-source-snapshot
path: ${{ runner.temp }}/publisher-state/builds
if-no-files-found: error
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ Structured manifest output is also supported:
- `show --output json|yaml`
- `search --manifests --output json|yaml`

For authoring a static Windows package source, see
[Publishing a static WinGet source](docs/repository-publishing.md). The
`repository` commands are separate from client-side `source` management.

The C# implementation also ships the **`Devolutions.Pinget.Client` PowerShell 7 module** that mirrors the upstream `Microsoft.WinGet.Client` cmdlet family with renamed `Pinget` nouns, backed by `Devolutions.Pinget.Core`.

## Pinget CLI
Expand Down
Loading
Loading