feat(native): package Windows sender evaluation build (#99)
This commit is contained in:
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
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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
|
||||
```
|
||||
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
@@ -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
|
||||
Reference in new issue
Block a user