feat(native): package Windows sender evaluation build (#99)

This commit is contained in:
AAA authored and GitHub committed 2026-08-21 03:18:48 +08:00
1 parent 39dc7061b2
commit bd8a0d80b0
11 files changed
+299 -24

No files matched your search

@@ -0,0 +1,51 @@
name: Native sender package
on:
workflow_dispatch:
pull_request:
paths:
- "native/sender/**"
- "native/process-audio-helper/**"
- "scripts/package-native-sender.ps1"
- ".github/workflows/native-sender-package.yml"
push:
branches:
- main
paths:
- "native/sender/**"
- "native/process-audio-helper/**"
- "scripts/package-native-sender.ps1"
- ".github/workflows/native-sender-package.yml"
permissions:
contents: read
jobs:
package:
runs-on: windows-latest
steps:
- name: Check out repository
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v6
with:
go-version: 1.26.6
cache-dependency-path: native/sender/go.sum
- name: Build and verify package
shell: pwsh
run: |
./scripts/package-native-sender.ps1 `
-OutputDirectory (Join-Path $env:RUNNER_TEMP 'screener-native-package') `
-Revision '${{ github.sha }}'
- name: Upload evaluation artifact
uses: actions/upload-artifact@v7
with:
name: screener-native-windows-x64-${{ github.sha }}
path: |
${{ runner.temp }}/screener-native-package/*.zip
${{ runner.temp }}/screener-native-package/*.zip.sha256
if-no-files-found: error
retention-days: 7
compression-level: 0
@@ -178,9 +178,12 @@ failed stage while synchronously retaining a bounded final-negative snapshot:
candidates; a future selected-edge attempt requires its own generation-bound
gate after SFU/UDP rather than widening or blocking the direct-path canary.
Only after these stages pass may separate performance, quality, loss,
reconnect, browser, audio/A-V-sync, packaging, and license gates begin. Do not
expand the feature to make the diagnostic gate pass.
A commit-bound, short-lived evaluation artifact may package the current source
to run these stages without a development toolchain. That artifact is not an
acceptance or release claim. Only after these stages pass may separate
performance, quality, loss, reconnect, browser, audio/A-V-sync, formal release,
and license gates begin. Do not expand the feature to make the diagnostic gate
pass.
## Consequences
+9 -4
View File
@@ -2,8 +2,9 @@
Date: 2026-08-21
Status: Accepted. The browser hint and opt-in Native Windows P1 slice are
source-complete; Native remains unpackaged, default-off, and undeployed.
Status: Accepted. The browser hint, opt-in Native Windows P1 slice, and bounded
Windows x64 evaluation-package path are source-complete; Native remains
default-off, formally unreleased, and undeployed.
## Context
@@ -122,12 +123,16 @@ track and 495 inbound Opus packets while video decoded/rendered 296 frames.
privacy claim the platform cannot support.
- Strict per-window audio is a native Windows 11 feature, not a browser promise
or a silent system-audio fallback.
- The helper is packaged beside the sender in a commit-bound evaluation ZIP.
The ZIP carries internal and external SHA-256 manifests plus exact linked Go
dependency license files; it is neither an installer nor a release.
- Android `AudioPlaybackCapture` and packaged cross-platform UI remain later
candidates; they do not block this slice.
## Follow-Up TODO
- Package the helper beside the sender and keep explicit target selection
default-off.
- Download and run the short-lived Windows x64 evaluation artifact; keep
explicit target selection default-off. A formal release remains blocked on
the project license, signing, and its own acceptance boundary.
- Keep native WGC video, a second Viewer, SFU/TURN, endurance, and real-game
A/V sync as separate follow-ups.
+3 -3
View File
@@ -23,14 +23,14 @@ Last updated: 2026-08-21
- Use direct host P2P for one or two viewers, then the bounded controller for every room when `PEER_ASSISTED_MEDIA=true`. Room `1` is historical smoke, not a runtime gate; resource, quality, recovery, SFU/UDP, bounded-failure, and browser/mobile evidence remain separate.
- Browser relays resend remote `MediaStreamTrack` values and re-encode at each hop; WebRTC does not guarantee a shared encoder across peer connections, so measure the cost.
- Keep experiments bounded: the standard representation sequence is below; native RTP relay, encoded-object striping, and FEC remain separate.
- ADR-0006 remains no-go. Native H.264 opt-in loopback (Chrome 151, 1280x720) rendered 298/299 with zero fatal/encoder errors; VP8 remains default. Pion timing, hardware attribution, multi-viewer/endurance/public/packaged proof remain open.
- ADR-0006 remains no-go. VP8 is default; H.264 loopback rendered 298/299. Windows x64 evaluation packaging is source-complete; downloaded use, Pion timing, hardware, multi-viewer/endurance/public proof remain open.
- Mobile Web Host is unsupported; feature-detect and fail clearly. Mobile Viewer stays leaf-only. After Windows native, gate Android 14+; iOS waits for stable iOS 27 ScreenCaptureKit.
- ADR-0005 accepts direct/peer UDP, bounded SFU roots, then optional selected-edge TURN. Production now enables the one-shot selected-edge tuple after SFU; participant-wide TURN remains rejected and ordinary peer ICE stays STUN-only. No real TURN/SFU media canary has yet been run.
- The controller is process-enabled, not room-allowlisted: `PEER_ASSISTED_MEDIA=true` gives every normal room the same direct/peer -> SFU -> selected-edge path with per-room state. Room `1` is historical smoke. Preserve sticky P2P, mobile leaves and break-before-make; recovery gets one attempt per layer (ICE restart, same-parent rebuild, alternate peer, then SFU), never three identical retries.
- C+B quality reparenting is edge-local and cooldown-bound; no score, timer, or global parent penalty.
- Flagship media is UDP; HTTPS/WSS stays TLS/TCP; the old release remains rollback-only.
- Treat settings as ceilings and degradation as unclassified. Use correlated Host A+B/Viewer C and one-variable evidence; never force AV1, infer by UA, or create a composite score.
- Web capture cannot isolate process audio. ADR-0008 Windows 11 native audio is opt-in/source-only: opaque local selection, no system-mix fallback or exposed PID, and one shared Opus track; one direct Viewer received 495 packets. Packaging, game A/V sync, other routes, and Windows 10 remain open.
- Web cannot isolate process audio. ADR-0008 Win11 audio is opt-in/source-only with no system-mix fallback or exposed PID; one Viewer got 495 Opus packets. Evaluation packaging includes the helper, hashes, and linked licenses; release, game sync, other routes, and Win10 remain open.
- Viewer-local names and the opt-in Web participant roster remain control-plane-only. Web Host names are deployed in the current release and stay socket/localStorage-only; Native remains outside the capability boundary.
- Do not add scene detection, dynamic-FPS control, or forced AV1 without negotiation, encode, game, CPU/GPU, and sender evidence.
- ADR-0002 grant/public access, the v3 room-password migration, and Web Host display names are deployed. Names/presence remain session-only without account or roster tables.
@@ -53,7 +53,7 @@ Last updated: 2026-08-21
- Chrome 151 synthetic topology/quality runs kept fanout 2/1 and decoding; one relay close recovered in 5.32 seconds. Control evidence only.
- Room `1` publishes `HIGH+LOW` with Dynacast off and subscriber `HIGH` ceilings, and now has bounded local quality reparenting. Both remain unverified on real media; test zero-child leaves and calibrated C+B loss before broad rollout.
- C+B uses three hard-bad pairs, one-use samples and guarded intent/cooldown. Deployed admission rescue moves the oldest childless zero-capacity Host leaf below an unassigned one-slot relay in one revision; no score/timer/global rebalance. Deployment passed, but no real room triggered it.
- Web Host name/presence and the best-effort window-scoped audio request hint are deployed; both remain control-plane/capture hints and do not change the Native wire. Native H.264 opt-in source is present but no packaged native sender is in the release; VP8 remains the Web/production default. See `docs/research/native-h264-opt-in-path.md`.
- Web Host name/presence and window-audio hint are deployed without changing the Native wire. Native H.264 source and Windows x64 evaluation packaging are present, but no Native release/deployment exists; VP8 remains the Web/production default. See `docs/research/native-h264-opt-in-path.md`.
## Provisional Quality Targets
+36 -2
View File
@@ -477,6 +477,35 @@ static standard-path results and any future native reopen gate. This path still
requires measured per-representation traffic/resources and cannot bypass #28's
stock-GCC/RTX stop line.
## 2026-08-21 Evaluation Packaging Boundary
The current source now has one Windows x64 evaluation-package path. It reuses
the existing Go build and MSVC helper build, places the two executables beside
each other, embeds the exact Git revision, adds an internal `SHA256SUMS.txt`,
and publishes the ZIP with an adjacent SHA-256 file.
`screener-sender.exe --version` is the non-interactive package smoke. This does not add an installer,
Electron, auto-update, signing, a bundled server, codec matrix, or release.
The workflow uses the official `windows-latest` image, whose current manifest
includes VSWhere, the x64 Visual C++ tools, and Windows 11 SDK, and the official
immutable `actions/upload-artifact@v7` path with missing-file failure, zero
second-stage compression for the precompressed ZIP, and seven-day retention.
GitHub requires authentication to download the resulting artifact. The
workflow is path-filtered on pull requests and `main`, with manual dispatch for
an exact retained commit. Sources were checked 2026-08-21.
The linked-binary audit covers 23 modules: coder/websocket is ISC; the 16 Pion
modules are MIT; google/uuid, wlynxg/anet, and the four `golang.org/x` modules
are BSD-style. Every linked module exposes a recognized root license file. The
packager derives the list from `go list -deps`, copies those exact files plus
the Go toolchain license, and fails if a linked module has no license file. No
GPL/AGPL reference or proprietary Oopz code enters the package.
The project distribution license remains undecided. The Actions artifact is
therefore labeled evaluation-only and grants no project redistribution right;
GitHub Release publication remains blocked on the license decision. This
bounded trial artifact does not change ADR-0006's product No-Go status.
## Product Stop Line
The stock Pion GCC plus negotiated RFC 4588 RTX composition is
@@ -544,10 +573,15 @@ SFU/UDP fails and needs its own bounded transport gate.
- [Apple iOS ScreenCaptureKit sample](https://developer.apple.com/documentation/screencapturekit/capturing-screen-content-on-ios)
- [Apple required hardware encoder key](https://developer.apple.com/documentation/videotoolbox/kvtvideoencoderspecification_requirehardwareacceleratedvideoencoder)
- [Apple hardware encoder readback](https://developer.apple.com/documentation/videotoolbox/kvtcompressionpropertykey_usinghardwareacceleratedvideoencoder)
- [GitHub Actions artifact upload](https://github.com/actions/upload-artifact)
- [GitHub Windows 2025 runner image](https://github.com/actions/runner-images/blob/main/images/windows/Windows2025-Readme.md)
- [PowerShell `Compress-Archive`](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.archive/compress-archive)
- [Go license](https://go.dev/LICENSE)
The current Go candidate directly uses Pion (MIT) and coder/websocket (ISC).
Before distributing any sender executable, choose the project license and
generate and verify notices for those direct and all transitive dependencies.
The evaluation package generates and verifies notices for the Go runtime and
all linked direct/transitive dependencies. Choose the project license before a
formal release or redistribution grant.
libwebrtc/H.264 remains a separate future route requiring its own third-party
notice and patent/licensing review. No source code from these projects was
copied into Screener.
+9 -10
View File
@@ -15,10 +15,9 @@ active/running with `NRestarts=0`, and local/public health are 200.
Ordinary ICE remains STUN-only; `PEER_ASSISTED_MEDIA=true` enables the
bounded peer/SFU-UDP controller for every room (at most two roots), while the
selected-edge UDP tuple is configured with TTL 120. Room `1` is historical
smoke only. No real TURN/SFU media canary has run. Web Host names and the
best-effort window-scoped audio request hint are deployed; Native H.264 source is
available but no packaged native sender is deployed, and VP8 remains the Web
default.
smoke only. No real TURN/SFU media canary has run. Web Host names/audio hint are
deployed. Native H.264 and Windows x64 evaluation packaging are source-only;
there is no Native release/deployment, and Web defaults VP8.
## Execution Principle
@@ -42,7 +41,7 @@ Flagship; parallel; min run/smoke/rollback; benchmark later. Active UI/config/lo
- Host A+B and authenticated P2P Viewer C are sanitized, generation-bound, read-only, and fail closed for stale, ambiguous, or SFU-fed evidence; no raw media metadata is retained.
- The `a11a73d` built-in TURN canary is rejected: local allocation passed, but direct Host/Pion Viewer failed before forced relay. Full rollback restored STUN-only client ICE and zero allocations.
- Chrome 151 loopbacks decoded VP8 299 and H.264 opt-in 299/298 rendered at 1280x720 without fatal/encoder errors. Hardware attribution, Pion timing, multi-viewer/endurance/public/native proof remain open; production stays VP8.
- Native Win11 audio is source-only/default-off. Smoke isolated target 4018x; one Viewer got 495 Opus packets. Packaging, game sync, Win10, and other routes remain open.
- Native Win11 audio is source-only/default-off. Target isolation was 4018x; one Viewer got 495 Opus packets. Package build passes; download, game sync, Win10, and other routes are open.
- Access protocol/config/HTTP/storage/SQLite/signaling focused tests pass, including commit-first teardown and v1 rollback.
- Source adds selected Host ingress and peer last-mile for every enabled room; focused routing/config tests pass with Peer ICE STUN-only.
- Host names, the window-audio hint, all-room routing, and all-room Host selected ingress are active; the stale restart assertion is historical only.
@@ -54,7 +53,7 @@ Flagship; parallel; min run/smoke/rollback; benchmark later. Active UI/config/lo
- Android Chrome/iOS Safari Viewer leaves remain unverified and conservatively leaf-only. Mobile Web Host is unsupported; native senders are planned only.
- Silent partitions can wait 30 to 60 seconds for heartbeat detection before the default 5-second grace; this remains unverified.
- The former release reportedly sustained bandwidth-limited blur on a capable LAN; Host refresh recovered while Viewer refresh did not. The new deployment has not yet reproduced or cleared it.
- ADR-0006 has one Viewer proof; two-edge/FIFO, physical hardware, endurance, public, packaged-native, and browser-diversity proof remain open.
- ADR-0006 has one Viewer proof; two-edge/FIFO, hardware, endurance, public/downloaded-package, and browser-diversity proof remain open.
- Browser fanout is host two/viewer one; any accepted endpoint relay stays capped at two downstream edges.
- PR #49/#50 BWE is unverified/default-off: test zero-child leaves, then root impact. No local per-leaf UDP shaper; resume with Linux `tc` or public canary, never CDP. Web P2P/SVC shortcuts remain no-go.
- The corrected standby smoke is localhost/headless/video-only; public DNS/TLS reuse, transport, audio, shaping, load, mobile, endurance, and sub-25 ms overlap remain open.
@@ -71,10 +70,10 @@ SFU; it never runs three identical retries or abandons progressing P2P early.
Next gate exactly-two/Dynacast-off BWE on a zero-child SFU leaf, then root
evacuation. Native source accepts increasing capture timestamps shorter than
duration; VP8 and explicit H.264 Viewer decode/render are recorded. Hardware
preference is not physical proof. Next prove fresh Pion
outbound diagnostics before viewer 2/FIFO/hardware/endurance/deploy.
Package Native audio and test one real-game A/V pair later without displacing P0.
duration; VP8 and H.264 Viewer decode/render are recorded. Preference is not
proof. Package one-Viewer VP8/H.264/Opus first; WGC/MF hardware then
Viewer2/FIFO are functional slices. The 2s Pion sample is later diagnostic
cleanup. Test real-game A/V later without displacing P0.
Ordinary Peer ICE stays STUN-only; participant-wide TURN is removed. The
selected-edge tuple is configured in production, but Host ingress still needs one
forced-relay canary before any media-success claim. Retained performance/resource
+4 -2
View File
@@ -5,8 +5,10 @@ It enumerates visible top-level windows locally and captures only the explicitly
selected process plus its children through WASAPI application loopback. It has
no whole-system fallback and no network code.
Build it outside the repository, then place both executables in the same output
directory (or set `SCREENER_PROCESS_AUDIO_HELPER` for a development run):
The standard evaluation ZIP builds this helper beside the sender through
`scripts/package-native-sender.ps1`. For a helper-only development build, use
an output directory outside the repository (or set
`SCREENER_PROCESS_AUDIO_HELPER` for a development run):
```powershell
$out = Join-Path ([IO.Path]::GetTempPath()) 'screener-native-audio'
+41
View File
@@ -0,0 +1,41 @@
# Screener Native Sender for Windows x64
This evaluation package contains the current Native sender and the Windows 11
process-audio helper. It has no installer, updater, code signature, or bundled
server.
## Run
1. Keep `screener-sender.exe` and `screener-process-audio.exe` in the same
directory.
2. Run `screener-sender.exe`. It opens a loopback-only UI in the default
browser; current Chrome or Edge is required.
3. Enter the Screener server and Host admission password, choose VP8 (default)
or experimental H.264, then choose the screen or window to share.
4. Process audio is off by default. To enable it, select the exact target in
the audio list and select the same target in the browser picker.
5. Close the console window to stop the sender.
Process audio requires Windows 11 build 22000 or newer. It captures only the
selected process tree and never falls back to the system mix. H.264 requests
browser hardware preference but does not prove which physical encoder Chrome
or Edge selected. Viewers continue using the normal Web client.
Verify the downloaded ZIP against its adjacent `.sha256` file, then verify the
files inside it with `SHA256SUMS.txt`. The package is unsigned, so Windows may
show an unknown-publisher warning.
The project distribution license is not yet selected. This short-lived Actions
artifact is for evaluation and does not grant redistribution rights. Exact
third-party license texts for the linked Go runtime and modules are under
`licenses/`.
## Build
From a clean Git checkout on Windows with Go 1.26.6 and Visual Studio C++ Build
Tools installed:
```powershell
$output = Join-Path ([IO.Path]::GetTempPath()) "screener-native-package-$([Guid]::NewGuid())"
./scripts/package-native-sender.ps1 -OutputDirectory $output
```
+16
View File
@@ -12,7 +12,23 @@ import (
"github.com/TNTcraftHIM/Screener/native/sender/internal/app"
)
var buildRevision = "development"
func main() {
if len(os.Args) == 2 {
switch os.Args[1] {
case "--version":
fmt.Printf("Screener sender %s\n", buildRevision)
return
case "--help", "-h":
fmt.Println("Usage: screener-sender.exe [--version|--help]")
return
}
}
if len(os.Args) > 1 {
fmt.Fprintln(os.Stderr, "Usage: screener-sender.exe [--version|--help]")
os.Exit(2)
}
if err := run(); err != nil {
fmt.Fprintln(os.Stderr, "Screener sender stopped:", err)
os.Exit(1)
+122
View File
@@ -0,0 +1,122 @@
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[string]$OutputDirectory,
[string]$Revision
)
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
$scriptDirectory = Split-Path -Parent $MyInvocation.MyCommand.Path
$repositoryRoot = [IO.Path]::GetFullPath((Join-Path $scriptDirectory '..'))
$outputRoot = [IO.Path]::GetFullPath($OutputDirectory)
$repositoryPrefix = $repositoryRoot.TrimEnd([IO.Path]::DirectorySeparatorChar) + [IO.Path]::DirectorySeparatorChar
if ($outputRoot.Equals($repositoryRoot, [StringComparison]::OrdinalIgnoreCase) -or
$outputRoot.StartsWith($repositoryPrefix, [StringComparison]::OrdinalIgnoreCase)) {
throw 'OutputDirectory must be outside the repository.'
}
if (Test-Path -LiteralPath $outputRoot) {
throw 'OutputDirectory must not already exist.'
}
$headRevision = (& git -C $repositoryRoot rev-parse HEAD).Trim()
if ($LASTEXITCODE -ne 0) { throw 'Unable to resolve the Git revision.' }
if ([string]::IsNullOrWhiteSpace($Revision)) { $Revision = $headRevision }
$Revision = $Revision.Trim().ToLowerInvariant()
if ($Revision -notmatch '^[0-9a-f]{40}$' -or $Revision -ne $headRevision) {
throw 'Revision must be the full SHA-1 of the checked-out commit.'
}
$dirty = @(git -C $repositoryRoot status --porcelain)
if ($LASTEXITCODE -ne 0 -or $dirty.Count -ne 0) {
throw 'Native packages must be built from a clean Git checkout.'
}
$go = Get-Command go.exe -ErrorAction Stop
$senderDirectory = Join-Path $repositoryRoot 'native\sender'
$packageName = "screener-native-windows-x64-$($Revision.Substring(0, 12))"
$packageDirectory = Join-Path $outputRoot $packageName
$licenseDirectory = Join-Path $packageDirectory 'licenses'
$senderExecutable = Join-Path $packageDirectory 'screener-sender.exe'
$zipPath = Join-Path $outputRoot "$packageName.zip"
New-Item -ItemType Directory -Path $licenseDirectory -Force | Out-Null
$previousGoOS = $env:GOOS
$previousGoArch = $env:GOARCH
$previousCGO = $env:CGO_ENABLED
Push-Location $senderDirectory
try {
$env:GOOS = 'windows'
$env:GOARCH = 'amd64'
$env:CGO_ENABLED = '0'
$linkerFlags = "-X main.buildRevision=$Revision"
& $go.Source build -mod=readonly -trimpath -buildvcs=true -ldflags $linkerFlags -o $senderExecutable ./cmd/screener-sender
if ($LASTEXITCODE -ne 0) { throw 'Native sender build failed.' }
$moduleLines = @(& $go.Source list -deps -f '{{with .Module}}{{if not .Main}}{{.Path}}|{{.Version}}|{{.Dir}}{{end}}{{end}}' ./cmd/screener-sender |
Where-Object { -not [string]::IsNullOrWhiteSpace($_) } | Sort-Object -Unique)
if ($LASTEXITCODE -ne 0 -or $moduleLines.Count -eq 0) {
throw 'Unable to enumerate linked Go modules.'
}
$goVersion = (& $go.Source version).Trim()
$goRoot = (& $go.Source env GOROOT).Trim()
} finally {
Pop-Location
$env:GOOS = $previousGoOS
$env:GOARCH = $previousGoArch
$env:CGO_ENABLED = $previousCGO
}
& (Join-Path $repositoryRoot 'native\process-audio-helper\build.ps1') -OutputDirectory $packageDirectory | Out-Null
$helperObject = Join-Path $packageDirectory 'main.obj'
if (Test-Path -LiteralPath $helperObject) { Remove-Item -LiteralPath $helperObject -Force }
$moduleManifest = @()
foreach ($line in $moduleLines) {
$modulePath, $moduleVersion, $moduleDirectory = $line -split '\|', 3
if ([string]::IsNullOrWhiteSpace($moduleDirectory) -or -not (Test-Path -LiteralPath $moduleDirectory -PathType Container)) {
throw "Linked module source is unavailable: $modulePath@$moduleVersion"
}
$licenseFiles = @(Get-ChildItem -LiteralPath $moduleDirectory -File | Where-Object {
$_.Name -match '^(LICENSE|LICENCE|COPYING|NOTICE)(\.|$)'
})
if ($licenseFiles.Count -eq 0) { throw "Linked module has no recognized license file: $modulePath@$moduleVersion" }
$moduleLicenseDirectory = Join-Path $licenseDirectory (($modulePath + '@' + $moduleVersion) -replace '[^A-Za-z0-9._@+-]', '_')
New-Item -ItemType Directory -Path $moduleLicenseDirectory | Out-Null
$licenseFiles | Copy-Item -Destination $moduleLicenseDirectory
$moduleManifest += "$modulePath $moduleVersion"
}
$goLicense = Join-Path $goRoot 'LICENSE'
if (-not (Test-Path -LiteralPath $goLicense -PathType Leaf)) { throw 'Go toolchain license was not found.' }
$goLicenseDirectory = Join-Path $licenseDirectory 'go-toolchain'
New-Item -ItemType Directory -Path $goLicenseDirectory | Out-Null
Copy-Item -LiteralPath $goLicense -Destination (Join-Path $goLicenseDirectory 'LICENSE')
$moduleManifest | Set-Content -LiteralPath (Join-Path $licenseDirectory 'MODULES.txt') -Encoding ascii
Copy-Item -LiteralPath (Join-Path $senderDirectory 'README.md') -Destination (Join-Path $packageDirectory 'README.md')
@(
"revision=$Revision"
'platform=windows/amd64'
"toolchain=$goVersion"
) | Set-Content -LiteralPath (Join-Path $packageDirectory 'REVISION.txt') -Encoding ascii
$versionOutput = (& $senderExecutable --version).Trim()
if ($LASTEXITCODE -ne 0 -or $versionOutput -ne "Screener sender $Revision") {
throw 'Packaged sender revision smoke failed.'
}
$packagePrefix = $packageDirectory.TrimEnd([IO.Path]::DirectorySeparatorChar) + [IO.Path]::DirectorySeparatorChar
$checksums = Get-ChildItem -LiteralPath $packageDirectory -File -Recurse | Sort-Object FullName | ForEach-Object {
$relativePath = $_.FullName.Substring($packagePrefix.Length).Replace('\', '/')
"$((Get-FileHash -LiteralPath $_.FullName -Algorithm SHA256).Hash.ToLowerInvariant()) $relativePath"
}
$checksums | Set-Content -LiteralPath (Join-Path $packageDirectory 'SHA256SUMS.txt') -Encoding ascii
Compress-Archive -LiteralPath $packageDirectory -DestinationPath $zipPath -CompressionLevel Optimal
$zipHash = (Get-FileHash -LiteralPath $zipPath -Algorithm SHA256).Hash.ToLowerInvariant()
"$zipHash $([IO.Path]::GetFileName($zipPath))" |
Set-Content -LiteralPath "$zipPath.sha256" -Encoding ascii
Write-Output $zipPath
Write-Output "$zipPath.sha256"
+2
View File
@@ -14,6 +14,7 @@ tsconfig.json
.githooks/pre-commit
.github/pull_request_template.md
.github/workflows/repository-hygiene.yml
.github/workflows/native-sender-package.yml
docs/README.md
docs/project-memory.md
docs/status.md
@@ -27,6 +28,7 @@ docs/research/webrtc-p2p-screen-sharing.md
scripts/required-project-paths.txt
scripts/check-project-state.sh
scripts/check-project-state.ps1
scripts/package-native-sender.ps1
scripts/install-hooks.sh
scripts/install-hooks.ps1
deploy/coturn/turnserver.conf.example