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
34 changes: 16 additions & 18 deletions .github/scripts/publish-tag-release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,42 +13,40 @@ gh api "repos/$GITHUB_REPOSITORY/actions/artifacts/$ARTIFACT_ID" |
(.workflow_run.id | tostring) == $run and .workflow_run.head_sha == $source
' >/dev/null || fail 'artifact is not the exact immutable output of this source/run'
directory="${RELEASE_DIRECTORY:?}"
archive="vx-bridge-windows-amd64-$RELEASE_VERSION-$SOURCE_REVISION.zip"
installer="vx-bridge-installer-windows-amd64-$RELEASE_VERSION-$SOURCE_REVISION.zip"
msi="vx-bridge-windows-amd64-$RELEASE_VERSION-$SOURCE_REVISION.msi"
installer="vx-bridge-installer-windows-amd64-$RELEASE_VERSION.exe"
[[ -d "$directory" && ! -L "$directory" &&
"$(find "$directory" -mindepth 1 -maxdepth 1 | wc -l)" -eq 6 ]] ||
fail 'download must contain exactly app ZIP, installer ZIP, direct MSI and their checksums'
for file in "$archive" "$installer" "$msi"; do
"$(find "$directory" -mindepth 1 -maxdepth 1 | wc -l)" -eq 2 ]] ||
fail 'download must contain exactly the installer EXE and its checksum'
for file in "$installer"; do
[[ -f "$directory/$file" && ! -L "$directory/$file" &&
-f "$directory/$file.sha256" && ! -L "$directory/$file.sha256" ]] || fail 'unexpected asset/checksum file'
line="$(cat "$directory/$file.sha256")"
sum="${line%% *}"
[[ "$sum" =~ ^[0-9a-f]{64}$ && "$line" == "$sum $file" ]] || fail 'checksum must name only this exact asset'
[[ "$sum" =~ ^[0-9a-f]{64}$ && "$line" == "$sum $file" &&
"$(wc -c < "$directory/$file.sha256")" -eq $((64 + 2 + ${#file} + 1)) ]] ||
fail 'checksum must contain exactly one canonical line naming this asset'
(cd "$directory" && sha256sum --strict --check "$file.sha256")
done
REVISION="$SOURCE_REVISION" ARCHIVE="$directory/$archive" INSTALLER_ARCHIVE="$directory/$installer" make verify-installer
embedded="$(unzip -p "$directory/$installer" bridge.msi | sha256sum | cut -d' ' -f1)"
[[ "$embedded" == "$(sha256sum "$directory/$msi" | cut -d' ' -f1)" ]] ||
fail 'direct MSI differs from the installer bundle matching Setup/MSI'
REVISION="$SOURCE_REVISION" INSTALLER_ARCHIVE="$directory/$installer" make verify-installer

notes="${RUNNER_TEMP:?}/tag-release-notes.txt"
cat > "$notes" <<EOF
$RELEASE_VERSION - unsigned Windows application and installer. Source: $SOURCE_REVISION
Tag-ref object: $TAG_OID
Download the installer ZIP, extract it to one folder, and run setup.exe.
Keep its matching bridge.msi beside setup.exe; the direct MSI asset is not a standalone installer.
The separate application ZIP contains the six-file portable application distribution.
Installer metadata records the actual emitted PackageCode, full MSI hash and native owner identity.
Toolchain/license notices and checksums are included. No signing or automatic-update claim is made.
Download $installer and open it normally as the Windows user who will use the bridge, not as administrator.
This one EXE contains the matching native Setup, MSI and support files; no ZIP extraction or separate bridge download is needed.
Only the setup EXE and its .exe.sha256 checksum are uploaded. GitHub also supplies source archives.
Windows Installer still owns installation, repair, upgrades and uninstall. Normal application startup never invokes MSI.
Embedded metadata records the exact source, actual PackageCode, full MSI hash and native owner identity.
Toolchain/license notices and checksums are inside the EXE; /extract can save verified media to a new absolute folder for inspection or explicit recovery.
The installer and application are not Authenticode-signed. No automatic-update claim is made.
Publication does not qualify hardware, games, startup or lifecycle behavior on your machine.
Checksums detect corruption; they do not authenticate a publisher.
Build workflow: $GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID
EOF
# --verify-tag forbids the CLI's implicit missing-tag path. Draft creation
# fails on duplicate releases; no upload/clobber into an existing release.
gh release create "$RELEASE_VERSION" "$directory/$archive" "$directory/$archive.sha256" \
"$directory/$installer" "$directory/$installer.sha256" "$directory/$msi" "$directory/$msi.sha256" \
gh release create "$RELEASE_VERSION" "$directory/$installer" "$directory/$installer.sha256" \
--repo "$GITHUB_REPOSITORY" --verify-tag --target "$SOURCE_REVISION" --draft \
--prerelease=false --latest=false --title "$RELEASE_VERSION" --notes-file "$notes"
bash "$scripts/check-tag-release.sh" verify
Expand Down
6 changes: 3 additions & 3 deletions .github/scripts/setup-build-input.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ archiveName="vx-bridge-windows-amd64-$identity.zip"
archive="$application/$archiveName"
ARCHIVE="$archive" NATIVE_DIR="$native" OUT="$staging" make prepare-setup
mkdir "$bundle"
cp "$native/setup.exe" "$native/setup-actions.dll" "$native/native-inputs.txt" \
cp "$native/setup.exe" "$native/setup-actions.dll" "$native/bundle-stub.exe" "$native/native-inputs.txt" \
"$native/native-SHA256SUMS" "$archive" "$archive.sha256" "$bundle/"
cp "$staging/payload.wxs" "$bundle/linux-payload.wxs"
cp "$staging/setup-input.json" "$bundle/linux-setup-input.json"
Expand All @@ -47,10 +47,10 @@ while IFS= read -r line; do
count=$((count+1))
fi
done < "$native/native-inputs.txt"
[[ "$count" == 11 ]]
[[ "$count" == 13 ]]
(
cd "$bundle"
sha256sum setup.exe setup-actions.dll native-inputs.txt native-SHA256SUMS \
sha256sum setup.exe setup-actions.dll bundle-stub.exe native-inputs.txt native-SHA256SUMS \
"$archiveName" "$archiveName.sha256" \
linux-payload.wxs linux-setup-input.json compiler.txt packages.txt mingw-copyright.txt > INPUT-SHA256SUMS
)
Expand Down
5 changes: 3 additions & 2 deletions .github/scripts/setup-build-only.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ try {
Assert-ExactBuildSource
$identity=if ($env:RELEASE_VERSION -ceq 'development') { $env:REVISION } else { "$env:RELEASE_VERSION-$env:REVISION" }
$archiveName = "vx-bridge-windows-amd64-$identity.zip"
$hashed = @('setup.exe','setup-actions.dll','native-inputs.txt','native-SHA256SUMS',
$hashed = @('setup.exe','setup-actions.dll','bundle-stub.exe','native-inputs.txt','native-SHA256SUMS',
$archiveName,"$archiveName.sha256",'linux-payload.wxs','linux-setup-input.json',
'compiler.txt','packages.txt','mingw-copyright.txt')
$allowed = $hashed + @('INPUT-SHA256SUMS','provenance.json')
Expand Down Expand Up @@ -96,7 +96,7 @@ try {
$sourceHashes[$relative]=$true
}
}
if ($sourceHashes.Count -ne 11) { throw 'Native source/resource inventory differs.' }
if ($sourceHashes.Count -ne 13) { throw 'Native source/resource inventory differs.' }
$env:ARCHIVE=Join-Path $inputs $archiveName
$env:NATIVE_DIR=$inputs
$env:OUT=$staging
Expand Down Expand Up @@ -140,6 +140,7 @@ try {
$summary.msi_sha256=$msiHash
$env:AUTHORED_SETUP=$output
$env:MINGW_COPYRIGHT=Join-Path $inputs 'mingw-copyright.txt'
$env:BUNDLE_STUB=Join-Path $inputs 'bundle-stub.exe'
$env:OUT=Join-Path $env:RUNNER_TEMP 'release-artifacts'
Invoke-LoggedNativeTool -FilePath 'make' -LogPath $controlLog -Arguments @('-C',$source,'package-installer') | Out-Host
$summary.success=$true
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ jobs:
& 'C:\msys64\usr\bin\bash.exe' -lc 'pacman -S --needed --noconfirm make'
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
'C:\msys64\usr\bin' | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
- name: Author, inspect and package matching Setup/MSI without product execution
- name: Author, inspect and bundle matching Setup/MSI without product execution
env:
BUILD_INPUT_DIR: ${{ runner.temp }}/setup-build-input
EVIDENCE_DIR: ${{ runner.temp }}/setup-build-evidence
Expand Down Expand Up @@ -164,7 +164,7 @@ jobs:
artifact-ids: ${{ needs.installer.outputs.artifact-id }}
path: ${{ runner.temp }}/tag-release
digest-mismatch: error
- name: Publish only this run's verified application and matching installer assets
- name: Publish only this run's verified installer EXE and checksum
env:
GH_TOKEN: ${{ github.token }}
RELEASE_DIRECTORY: ${{ runner.temp }}/tag-release
Expand Down
16 changes: 8 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ override GOTOOLCHAIN := local
export GO GOFMT POWERSHELL CGO_ENABLED GOTOOLCHAIN REVISION RELEASE_VERSION OUT ARCHIVE NATIVE_DLL
export NATIVE_DIR SETUP_STAGING WIX_ARCHIVE TOOL_LOG SETUP_BUILD_PROFILE
export WORKFLOW_REVISION BUILD_INPUT_DIR EVIDENCE_DIR NATIVE_ARTIFACT_ID NATIVE_ARTIFACT_DIGEST
export AUTHORED_SETUP MINGW_COPYRIGHT INSTALLER_ARCHIVE LIFECYCLE_EVIDENCE
export AUTHORED_SETUP MINGW_COPYRIGHT BUNDLE_STUB INSTALLER_ARCHIVE LIFECYCLE_EVIDENCE

.PHONY: help help-installer help-qualification build package verify-package install-setup-toolchain build-setup-input build-setup-artifacts package-installer verify-installer build-setup-native prepare-setup build-setup-msi build-lifecycle-input author-lifecycle test-installer-lifecycle restore-lifecycle-policy test-native-tools test test-race vet fmt fmt-check check ci ci-windows benchmark lint-workflows check-commands release-resolve release-verify release-publish

Expand Down Expand Up @@ -46,11 +46,11 @@ help-installer:
@printf '%s\n' \
'Installer builds (static authoring/integrity only; no product execution):' \
' make install-setup-toolchain Explicit pinned MinGW provisioning on the approved Linux builder' \
' make build-setup-native Pinned C Setup/actions cross-build; REVISION/OUT' \
' make build-setup-native Pinned C Setup/actions/bundle stub cross-build; REVISION/OUT' \
' make prepare-setup Verify and stage application/native inputs; ARCHIVE/NATIVE_DIR/OUT' \
' make build-setup-msi Windows WiX authoring, tables/CAB inspection; SETUP_STAGING/WIX_ARCHIVE/TOOL_LOG/OUT' \
' make package-installer Matching Setup/MSI bundle and original app ZIP; AUTHORED_SETUP/ARCHIVE/MINGW_COPYRIGHT/OUT' \
' make verify-installer Check existing bundle against app ZIP; INSTALLER_ARCHIVE/ARCHIVE' \
' make package-installer Self-contained EXE + checksum; AUTHORED_SETUP/ARCHIVE/MINGW_COPYRIGHT/BUNDLE_STUB/OUT' \
' make verify-installer Check EXE, embedded media and app ZIP; INSTALLER_ARCHIVE' \
' make build-setup-input Shared exact-source Linux input job; source/run/version identity' \
' make build-setup-artifacts Shared Windows author/inspect/package job; exact input artifact identity' \
' make test-native-tools Fake-tool logging/exit regression; new external OUT' \
Expand Down Expand Up @@ -102,17 +102,17 @@ package-installer:
: "$${AUTHORED_SETUP:?Set AUTHORED_SETUP to the inspected Windows authoring output}"; \
: "$${ARCHIVE:?Set ARCHIVE to the exact verified application ZIP}"; \
: "$${MINGW_COPYRIGHT:?Set MINGW_COPYRIGHT to the pinned compiler copyright file}"; \
: "$${BUNDLE_STUB:?Set BUNDLE_STUB to the matching native bundle-stub.exe}"; \
: "$${OUT:?Set OUT to a new external release artifact directory}"; \
"$$GO" run -mod=readonly ./tools/msi/setup -revision "$${REVISION:-$$(git rev-parse HEAD)}" \
-version "$$RELEASE_VERSION" -archive "$$ARCHIVE" -installer "$$AUTHORED_SETUP" \
-copyright "$$MINGW_COPYRIGHT" -out "$$OUT"
-copyright "$$MINGW_COPYRIGHT" -bundle-stub "$$BUNDLE_STUB" -out "$$OUT"

verify-installer:
@set -euo pipefail; \
: "$${ARCHIVE:?Set ARCHIVE to the exact application ZIP}"; \
: "$${INSTALLER_ARCHIVE:?Set INSTALLER_ARCHIVE to the matching installer ZIP}"; \
: "$${INSTALLER_ARCHIVE:?Set INSTALLER_ARCHIVE to the self-contained installer EXE}"; \
"$$GO" run -mod=readonly ./tools/msi/setup -revision "$${REVISION:-$$(git rev-parse HEAD)}" \
-version "$$RELEASE_VERSION" -archive "$$ARCHIVE" -verify-installer "$$INSTALLER_ARCHIVE"
-version "$$RELEASE_VERSION" -verify-installer "$$INSTALLER_ARCHIVE"

build-setup-native:
@REVISION="$${REVISION:-$$(git rev-parse HEAD)}" bash installer/build-setup-native.sh
Expand Down
17 changes: 8 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,19 @@ VX receiver. VX Bridge does not supply a game or replace an existing license.
**[Open the latest release](https://github.com/devigned/vx-bridge/releases/latest)**
for release notes and downloads. Under **Assets** (expand it if needed), download
the file whose name starts with `vx-bridge-installer-windows-amd64-` and ends in
`.zip`. Do not choose the application-only ZIP, separate MSI, `.sha256` checksum
or **Source code** downloads.
`.exe`. The version is in the filename. The `.exe.sha256` file is a checksum;
**Source code** downloads are for developers, not installation. Older releases
without this EXE retain the files and instructions in their release notes.

1. In ProTee Labs, select **Game Options > Disconnect**. Close any existing
receiver through its own controls. Do not run two receivers or replace the
vendor's `GSPconnect.exe`.
2. Right-click the downloaded ZIP and select **Extract All**. Open the extracted
folder. Keep all extracted files together, including `setup.exe` and `bridge.msi`.
Do not run Setup from inside the ZIP or mix files from different builds.
3. Open `setup.exe` as the Windows user who will use the bridge, not as
administrator. Select **Install**. Do not double-click `bridge.msi`.
4. Leave **Auto-launch on Windows Startup** off unless the bridge should open
2. Open the downloaded installer EXE as the Windows user who will use the
bridge, not as administrator. Select **Install**. Everything Setup needs is
inside this one file; there is no ZIP to extract or separate MSI to download.
3. Leave **Auto-launch on Windows Startup** off unless the bridge should open
when you sign in. It is off on a fresh install.
5. Wait for Setup to report success. At **Start the bridge now?**, select
4. Wait for Setup to report success. At **Start the bridge now?**, select
**Start bridge** to open it once, or **Not now** to open **VX Bridge** from
Start later. Starting it once does not enable auto-launch.

Expand Down
10 changes: 7 additions & 3 deletions contributors.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,13 +104,17 @@ ARCHIVE="/absolute/path/to/artifacts/new-build/vx-bridge-windows-amd64-$revision

This creates and inspects a Windows x64 application ZIP without running either
executable. It is a development package, not an installer or a tested playing
release. It does not include the native Setup/MSI pair. The
release. It does not include the native Setup/MSI pair and is not uploaded separately
as a release asset. The
[build and package reference](docs/technical/COMMANDS.md#build-and-verify-a-package)
explains the two executable names, metadata and output rules.

Installer builds use a separate native/Windows toolchain and explicit commands
in the [installer manual](docs/technical/INSTALLER.md). An MSI alone is not the
user install route: the current package requires its matching `setup.exe`.
in the [installer manual](docs/technical/INSTALLER.md). The public installer
is one self-contained EXE containing the matching native Setup/MSI pair,
support files and notices. Only that EXE and its checksum are uploaded for
future releases; GitHub also supplies source archives. An extracted MSI alone
is not the user install route.

Don't copy a build over vendor files or onto a simulator just to see whether it
works. Real-equipment trials require separate owner approval, a reviewed artifact
Expand Down
24 changes: 14 additions & 10 deletions docs/FAQ.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@

## Where is the installer?

[Download the public v0.1.0 installer ZIP](https://github.com/devigned/vx-bridge/releases/download/v0.1.0/vx-bridge-installer-windows-amd64-v0.1.0-5401cf26d19238b04ba3dbb8ecfa60442616ca79.zip).
Select **Extract All**, keep all nine files together, and open `setup.exe` from
the extracted folder with matching `bridge.msi` beside it. Do not install the
bare MSI.

The application ZIP, source archives and **BUILD ONLY** artifacts are not the
installer. See [file types](INSTALL.md#choose-the-right-files) and
[Open the latest release](https://github.com/devigned/vx-bridge/releases/latest).
Download `vx-bridge-installer-windows-amd64-vX.Y.Z.exe` and open it normally,
not as administrator. It contains Setup, the matching MSI and support files.
The `.exe.sha256` file is a checksum, not a second installer.

Older releases, including [v0.1.0](releases/v0.1.0.md), retain their original
ZIP downloads and extraction instructions. Source archives and **BUILD ONLY**
artifacts are not the installer. See [file types](INSTALL.md#choose-the-right-files) and
[tested scope](#which-versions-and-features-have-been-checked).

## Windows blocks Setup
Expand Down Expand Up @@ -133,7 +134,8 @@ Don't launch an extra `GSPconnect.exe` to perform a control command.
Ordinary startup does not run Windows Installer or attempt automatic repair.
Open **VX Bridge Setup** from Start and choose **Repair / Reinstall**.
The bridge need not work first. If Setup cannot find its saved source, use the
original verified `setup.exe` with its matching `bridge.msi`.
original verified installer EXE for that build. Older ZIP releases need their
original matching extracted Setup/MSI pair.

**Repair does not always fix a failed upgrade.** It can restore files while
leaving more than one registered version, so Setup must still refuse to start
Expand All @@ -148,8 +150,10 @@ install fresh. Removing only one version is not completed recovery.

Normal removal uses **Windows Settings > Apps > Installed apps > VX Bridge >
Uninstall**. A damaged Windows Installer cache may require each recorded
version's verified original MSI with `REMOVE=ALL`. That explicit recovery route
is not a raw-MSI install instruction. Don't guess identities, delete installer
version's verified original MSI with `REMOVE=ALL`. A maintainer can use the
original EXE's `/extract` option to save that media without installing it.
That explicit recovery route is not a raw-MSI install instruction.
Don't guess identities, delete installer
records or manually purge folders to make the remaining copy appear healthy.
Remaining registrations or bridge-owned files are not successful recovery,
even if one command reported success.
Expand Down
Loading