Skip to content

ci: fix PowerShell invocation for sys extraction script #14

ci: fix PowerShell invocation for sys extraction script

ci: fix PowerShell invocation for sys extraction script #14

Workflow file for this run

name: Release Wintun Artifacts
on:
workflow_dispatch:
inputs:
tag:
description: "Release tag to publish (example: v0.14.1-dryark.1)"
required: true
type: string
push:
tags:
- "v*"
permissions:
contents: write
jobs:
release:
name: Build and publish release assets
runs-on: windows-2022
steps:
- uses: actions/checkout@v4
- name: Setup MSBuild
uses: microsoft/setup-msbuild@v2
- name: Resolve Windows SDK version
shell: pwsh
run: |
$sdkRoot = Join-Path ${env:ProgramFiles(x86)} "Windows Kits\10\Include"
$versions = Get-ChildItem -Path $sdkRoot -Directory |
Where-Object { $_.Name -match '^\d+\.\d+\.\d+\.\d+$' } |
Sort-Object Name -Descending
if (-not $versions) {
throw "No Windows 10 SDK versions found under $sdkRoot"
}
$preferred = $versions | Where-Object { $_.Name -notlike '10.0.26100.*' } | Select-Object -First 1
if (-not $preferred) {
$preferred = $versions | Select-Object -First 1
}
"WINTUN_SDK_VERSION=$($preferred.Name)" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
Write-Host "Using WindowsTargetPlatformVersion=$($preferred.Name)"
- name: Build Release DLL targets
shell: pwsh
run: msbuild wintun.proj /m /t:Dll /p:Configuration=Release /p:WindowsTargetPlatformVersion=$env:WINTUN_SDK_VERSION
- name: Resolve release tag
id: release_tag
shell: pwsh
run: |
if ("${{ github.event_name }}" -eq "workflow_dispatch") {
"value=${{ inputs.tag }}" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8
} else {
$tag = "${{ github.ref_name }}"
"value=$tag" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8
}
- name: Fetch matching wintun.net package
shell: pwsh
run: |
$tag = "${{ steps.release_tag.outputs.value }}"
if ($tag -notmatch '^v(?<ver>\d+\.\d+\.\d+)-dryark\.\d+$') {
throw "Tag '$tag' must match v<major>.<minor>.<patch>-dryark.<n>"
}
$upstreamVer = $Matches['ver']
$upstreamZipName = "wintun-$upstreamVer.zip"
$upstreamUrl = "https://www.wintun.net/builds/$upstreamZipName"
$upstreamDir = "out/upstream-wintun-$upstreamVer"
New-Item -ItemType Directory -Force -Path "out" | Out-Null
Write-Host "Fetching upstream package: $upstreamUrl"
Invoke-WebRequest -Uri $upstreamUrl -OutFile "out/$upstreamZipName"
Expand-Archive -Path "out/$upstreamZipName" -DestinationPath $upstreamDir -Force
- name: Extract and rename embedded SYS payloads
shell: pwsh
run: |
python -m pip install --disable-pip-version-check pefile
@'
from pathlib import Path
import pefile
out_dir = Path("out")
upstream_root = next(p for p in out_dir.iterdir() if p.is_dir() and p.name.startswith("upstream-wintun-"))
bin_dir = upstream_root / "wintun" / "bin"
targets = [
("amd64", "DRYWINTUN-AMD64.sys"),
("arm64", "DRYWINTUN-ARM64.sys"),
("x86", "DRYWINTUN-X86.sys"),
]
def extract_wintun_sys(dll_path: Path) -> bytes:
pe = pefile.PE(str(dll_path), fast_load=False)
if not hasattr(pe, "DIRECTORY_ENTRY_RESOURCE"):
raise RuntimeError(f"no resources in {dll_path}")
for type_entry in pe.DIRECTORY_ENTRY_RESOURCE.entries:
if type_entry.id != pefile.RESOURCE_TYPE["RT_RCDATA"]:
continue
for name_entry in type_entry.directory.entries:
name = str(name_entry.name) if name_entry.name is not None else ""
if name.upper() != "WINTUN.SYS":
continue
for lang_entry in name_entry.directory.entries:
data_entry = lang_entry.data.struct
blob = pe.get_memory_mapped_image()[
data_entry.OffsetToData : data_entry.OffsetToData + data_entry.Size
]
if blob[:2] == b"MZ":
return blob
raise RuntimeError(f"WINTUN.SYS not found in {dll_path}")
lines = []
for arch, out_name in targets:
dll_path = bin_dir / arch / "wintun.dll"
blob = extract_wintun_sys(dll_path)
out_path = out_dir / out_name
out_path.write_bytes(blob)
pe = pefile.PE(data=blob, fast_load=False)
sec = pe.OPTIONAL_HEADER.DATA_DIRECTORY[
pefile.DIRECTORY_ENTRY["IMAGE_DIRECTORY_ENTRY_SECURITY"]
]
signed = sec.Size > 0
lines.append(
f"{out_name}: source={dll_path.as_posix()} size={len(blob)} cert_table_size={sec.Size} signed={signed}"
)
(out_dir / "UPSTREAM_SYS_STATUS.txt").write_text("\\n".join(lines) + "\\n", encoding="utf-8")
'@ | Set-Content -Path extract_embedded_sys.py -Encoding utf8
python extract_embedded_sys.py
- name: Stage release assets
shell: pwsh
run: |
New-Item -ItemType Directory -Force -Path out | Out-Null
Copy-Item "Release/amd64/wintun.dll" "out/drywintun-amd64.dll"
Copy-Item "Release/arm64/wintun.dll" "out/drywintun-arm64.dll"
Copy-Item "Release/x86/wintun.dll" "out/drywintun-x86.dll"
- name: Generate SHA256SUMS
shell: pwsh
run: |
$items = @("drywintun-amd64.dll", "drywintun-arm64.dll", "drywintun-x86.dll")
$items += (Get-ChildItem -Path out -Filter "wintun-*.zip" | ForEach-Object { $_.Name })
$items += (Get-ChildItem -Path out -Filter "DRYWINTUN-*.sys" | ForEach-Object { $_.Name })
$items += (Get-ChildItem -Path out -Filter "UPSTREAM_SYS_STATUS.txt" | ForEach-Object { $_.Name })
Remove-Item -ErrorAction SilentlyContinue out/SHA256SUMS.txt
foreach ($item in $items) {
$hash = (Get-FileHash "out/$item" -Algorithm SHA256).Hash.ToLower()
"$hash $item" | Out-File -FilePath out/SHA256SUMS.txt -Append -Encoding ascii
}
- name: Publish GitHub release assets
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ steps.release_tag.outputs.value }}
files: |
out/drywintun-amd64.dll
out/drywintun-arm64.dll
out/drywintun-x86.dll
out/wintun-*.zip
out/DRYWINTUN-*.sys
out/UPSTREAM_SYS_STATUS.txt
out/SHA256SUMS.txt