diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index dd0446a..33a1598 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -4,6 +4,19 @@ on: push: pull_request: workflow_dispatch: + inputs: + version: + description: Release version without the v prefix (for example, 0.1.0) + required: true + type: string + dry_run: + description: Build and validate release packages without creating a tag or release + required: false + default: false + type: boolean + +permissions: + contents: read jobs: package: @@ -19,13 +32,13 @@ jobs: rust_target: x86_64-pc-windows-msvc nuget_arch: amd64 vcvars_arch: x64 - artifact: windbg-tool-windows-x64 + artifact: windbg-tool-x64 can_run: true - label: windows-arm64 rust_target: aarch64-pc-windows-msvc nuget_arch: arm64 vcvars_arch: x64_arm64 - artifact: windbg-tool-windows-arm64 + artifact: windbg-tool-arm64 can_run: false env: @@ -170,3 +183,77 @@ jobs: name: ${{ matrix.artifact }} path: target\package\${{ matrix.artifact }}.zip if-no-files-found: error + + release: + name: Publish GitHub Release + needs: package + if: github.event_name == 'workflow_dispatch' + runs-on: windows-latest + timeout-minutes: 10 + permissions: + contents: write + env: + GH_TOKEN: ${{ github.token }} + VERSION: ${{ inputs.version }} + + steps: + - name: Download packages + uses: actions/download-artifact@v6 + with: + path: release-assets + pattern: windbg-tool-* + merge-multiple: true + + - name: Validate release inputs and assets + shell: pwsh + run: | + $ErrorActionPreference = 'Stop' + + if ($env:VERSION -notmatch '^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-[0-9A-Za-z][0-9A-Za-z.-]*)?(?:\+[0-9A-Za-z][0-9A-Za-z.-]*)?$') { + throw "Version must be a semantic version without the v prefix: $env:VERSION" + } + + $tag = "v$env:VERSION" + $assets = @( + 'windbg-tool-x64.zip', + 'windbg-tool-arm64.zip' + ) + foreach ($asset in $assets) { + $path = Join-Path $PWD "release-assets\$asset" + if (-not (Test-Path -Path $path -PathType Leaf)) { + throw "Release asset was not downloaded: $asset" + } + } + + $response = & gh api --include "repos/$env:GITHUB_REPOSITORY/git/ref/tags/$tag" 2>&1 + $exitCode = $LASTEXITCODE + if ($exitCode -eq 0) { + throw "Refusing to publish because tag $tag already exists." + } + + $responseText = $response -join [Environment]::NewLine + if ($responseText -notmatch '(?m)^HTTP/\S+ 404') { + throw "Could not determine whether tag $tag exists: $responseText" + } + + - name: Create release and upload packages + if: inputs.dry_run == false + shell: pwsh + run: | + $ErrorActionPreference = 'Stop' + + $tag = "v$env:VERSION" + $assets = @( + (Join-Path $PWD 'release-assets\windbg-tool-x64.zip'), + (Join-Path $PWD 'release-assets\windbg-tool-arm64.zip') + ) + & gh release create $tag $assets ` + --repo $env:GITHUB_REPOSITORY ` + --target $env:GITHUB_SHA ` + --title "windbg-tool $tag" ` + --generate-notes + + - name: Report dry run + if: inputs.dry_run + shell: pwsh + run: Write-Host "Dry run completed. Would create v$env:VERSION with the validated package ZIPs." diff --git a/README.md b/README.md index 16f5fc2..50bdad6 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,9 @@ The built executable is: target\debug\windbg-tool.exe ``` -Release ZIP artifacts are built by the Windows packaging workflow. The local equivalent uses `cargo xtask deps --arch `, `cargo xtask native-build --arch --static-crt`, a release build for the matching MSVC Rust target, and `cargo xtask package --profile release`. +Release ZIP artifacts are built by the Windows packaging workflow. Run **Windows packages** manually with an unprefixed semantic version such as `0.1.0` to publish the `v0.1.0` GitHub Release. Select **dry_run** to build and validate the packages without creating a tag or release. The release contains `windbg-tool-x64.zip` and `windbg-tool-arm64.zip`. + +The local equivalent uses `cargo xtask deps --arch `, `cargo xtask native-build --arch --static-crt`, a release build for the matching MSVC Rust target, and `cargo xtask package --profile release`. Both packages statically link the MSVC runtime and bundle their required TTD, DbgEng, symbol, and native-bridge DLLs. For deeper setup, test commands, runtime details, and workspace notes, see [the development guide](docs/development.md). diff --git a/docs/development.md b/docs/development.md index 852682d..36a2967 100644 --- a/docs/development.md +++ b/docs/development.md @@ -54,7 +54,7 @@ rustup target add x86_64-pc-windows-msvc cargo xtask deps --arch amd64 cargo xtask native-build --arch amd64 --static-crt cargo build -p windbg-tool --release --target x86_64-pc-windows-msvc -cargo xtask package --arch amd64 --target x86_64-pc-windows-msvc --profile release --out target\package\windbg-tool-windows-x64 +cargo xtask package --arch amd64 --target x86_64-pc-windows-msvc --profile release --out target\package\windbg-tool-x64 ``` Use `--arch arm64` with `--target aarch64-pc-windows-msvc` for the Windows ARM64 package. Architecture-specific dependency staging uses `target\runtime\\...`, while the legacy no-argument `cargo xtask deps`, `cargo xtask native-build`, and `cargo xtask package` commands keep using the existing host-architecture directories. @@ -63,6 +63,15 @@ Release packages statically link the MSVC C runtime into Rust code with `RUSTFLA Cross-compiling the ARM64 package from an x64 machine requires the Visual Studio ARM64 MSVC toolset and an `x64_arm64` developer environment for the native bridge and Rust crates that compile C/C++ code. +### Publishing a GitHub Release + +Run the **Windows packages** workflow with **Run workflow** and enter an unprefixed semantic version such as `0.1.0`. After both package matrix jobs complete, the workflow creates the `v0.1.0` tag at the commit selected for the dispatch and publishes a GitHub Release containing: + +- `windbg-tool-x64.zip` +- `windbg-tool-arm64.zip` + +Select **dry_run** to build both ZIPs, validate their contents, validate the version, and confirm that the tag is available without creating a tag or GitHub Release. The workflow rejects existing tags and invalid versions rather than replacing a release. Each ZIP contains the statically linked Rust executable and native bridge plus the required dynamic TTD Replay, DbgEng, and symbol runtime DLLs. + To smoke-test the packaged MCP server: ```powershell