ui: single-click tray restores window; '-' button minimizes to taskba… #237
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build Tor for Windows | |
| on: | |
| push: | |
| branches: [main, master, remove-xray] | |
| tags: ['v*'] | |
| workflow_dispatch: | |
| inputs: | |
| tag: | |
| description: 'Release tag (e.g. v1.0.0). Leave empty for a build-only run.' | |
| required: false | |
| default: '' | |
| beta: | |
| description: 'Publish this release as a beta (pre-release) instead of latest' | |
| required: false | |
| type: boolean | |
| default: false | |
| permissions: | |
| contents: read | |
| jobs: | |
| transports: | |
| name: pluggable-transports (Windows x86_64) | |
| runs-on: ubuntu-latest | |
| steps: | |
| # Actions are pinned to commit SHAs (version in comment) for | |
| # reproducible, supply-chain-safe builds. To bump: verify the new tag, | |
| # then swap SHA + comment together. | |
| - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 (node24) | |
| with: | |
| go-version: "1.24" | |
| # This repo has no go.sum; the built-in module cache would just warn | |
| # and skip. The whole job runs in under a minute anyway. | |
| cache: false | |
| - name: Build pluggable transports | |
| run: | | |
| set -e | |
| mkdir -p out | |
| GOPATH_BIN="$(go env GOPATH)/bin/windows_amd64" | |
| echo "=== obfs4 ===" | |
| GOOS=windows GOARCH=amd64 \ | |
| go install gitlab.com/yawning/obfs4.git/obfs4proxy@v0.0.0-20231012084234-c3e2d44b1033 | |
| cp "$GOPATH_BIN/obfs4proxy.exe" out/obfs4proxy.exe | |
| echo "=== snowflake client ===" | |
| GOOS=windows GOARCH=amd64 \ | |
| go install gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/v2/client@v2.14.1 | |
| cp "$GOPATH_BIN/client.exe" out/snowflake-client.exe | |
| echo "=== webtunnel client ===" | |
| GOOS=windows GOARCH=amd64 \ | |
| go install gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/webtunnel/main/client@v0.0.6 | |
| cp "$GOPATH_BIN/client.exe" out/webtunnel.exe | |
| ls -la out/ | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 (node24) | |
| with: | |
| name: transports-win64 | |
| path: out/ | |
| tor-win64: | |
| name: torjet-win64 (single release artifact) | |
| runs-on: windows-latest | |
| needs: [transports] | |
| steps: | |
| # On workflow_dispatch with a tag input, check out EXACTLY that tag so | |
| # the published binary always matches its tagged source. | |
| - uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0 (node24) | |
| with: | |
| ref: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.tag || github.ref }} | |
| fetch-depth: 0 | |
| - name: Verify requested tag was checked out | |
| if: github.event_name == 'workflow_dispatch' && github.event.inputs.tag != '' | |
| shell: bash | |
| env: | |
| INPUT_TAG: ${{ github.event.inputs.tag }} | |
| run: | | |
| case "$INPUT_TAG" in | |
| v[0-9][0-9A-Za-z._-]*) ;; | |
| *) echo "::error::refusing unsafe tag '$INPUT_TAG'"; exit 1;; | |
| esac | |
| ACTUAL="$(git describe --tags --exact-match 2>/dev/null || true)" | |
| if [ "$ACTUAL" != "$INPUT_TAG" ]; then | |
| echo "::error::tag '$INPUT_TAG' not found (HEAD is '$ACTUAL'). Create/push the tag first." | |
| exit 1 | |
| fi | |
| echo "Building exactly $ACTUAL" | |
| # Package versions are pinned (pkg=ver-rel) against the CURRENT MSYS2 | |
| # sync databases (verify with: tar -xOf <pkg>.db.tar <pkg-dir>/desc | | |
| # grep -A1 %VERSION%). update:true is REQUIRED: without a fresh | |
| # `pacman -Sy` the preinstalled image's stale database cannot see the | |
| # pinned versions and every target resolves as "target not found". | |
| # Bump pins together whenever you want a newer toolchain; if pacman | |
| # ever reports "target not found", re-check the .db and adjust. | |
| - uses: msys2/setup-msys2@66cd2cce69caa17b53920067426061ca1de3a884 # v2.32.0 (node24) | |
| with: | |
| msystem: MINGW64 | |
| update: true | |
| cache: false | |
| install: >- | |
| mingw-w64-x86_64-gcc=16.2.0-3 | |
| mingw-w64-x86_64-binutils=2.47-3 | |
| make=4.4.1-3 | |
| mingw-w64-x86_64-pkgconf=1~3.0.5-1 | |
| mingw-w64-x86_64-libevent=2.1.12-14 | |
| mingw-w64-x86_64-openssl | |
| mingw-w64-x86_64-zlib=1.3.2-2 | |
| mingw-w64-x86_64-zstd=1.5.7-2 | |
| mingw-w64-x86_64-gettext-runtime=1.0-1 | |
| mingw-w64-x86_64-gettext-tools=1.0-1 | |
| perl=5.42.3-1 | |
| - name: Configure | |
| shell: msys2 {0} | |
| run: | | |
| cd "$GITHUB_WORKSPACE/tor-src" | |
| chmod +x configure | |
| ./configure --host=x86_64-w64-mingw32 \ | |
| --disable-asciidoc --disable-man --disable-html-docs | |
| - name: Upload configure log (on failure) | |
| if: failure() && hashFiles('tor-src/config.log') != '' | |
| uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 (node24) | |
| with: | |
| name: config-log | |
| path: tor-src/config.log | |
| - name: Build | |
| shell: msys2 {0} | |
| run: | | |
| cd "$GITHUB_WORKSPACE/tor-src" | |
| # No autotools are installed (the workflow never regenerates), so | |
| # stop make's maintainer-mode rules from trying: restamp generated | |
| # files strictly NEWER than their inputs (sources -> aclocal.m4 -> | |
| # configure/config.h.in/Makefile.in). | |
| find . -name '*.m4' -o -name 'Makefile.am' | xargs touch | |
| sleep 1 | |
| touch aclocal.m4 | |
| sleep 1 | |
| touch configure | |
| find . -name '*.h.in' | xargs touch | |
| find . -name 'Makefile.in' | xargs touch | |
| make -j$(nproc) 2>&1 | tee build-win.log | |
| exit ${PIPESTATUS[0]} | |
| - name: Smoke test | |
| shell: msys2 {0} | |
| run: | | |
| cd "$GITHUB_WORKSPACE/tor-src" | |
| ./src/app/tor.exe --version | |
| - name: Stage tor + runtime DLLs + geoip | |
| shell: msys2 {0} | |
| run: | | |
| cd "$GITHUB_WORKSPACE/tor-src" | |
| mkdir -p ../dist/data/bridges | |
| cp src/app/tor.exe ../dist/data/ | |
| # Copy every DLL that tor.exe (and the DLLs it loads) imports from the | |
| # MSYS2 runtime dir, transitively, so the bundle is self-contained on | |
| # machines without MSYS2 installed. tor.exe imports libzstd.dll and | |
| # the libevent DLLs import libwinpthread-1.dll; both used to be | |
| # omitted, so clean devices failed with "libzstd.dll was not found". | |
| BIN="$MINGW_PREFIX/bin" | |
| NEED="src/app/tor.exe" | |
| added=1 | |
| while [ "$added" = "1" ]; do | |
| added=0 | |
| for f in $NEED; do | |
| for d in $(objdump -p "$f" | awk '/DLL Name:/{print $3}'); do | |
| if [ -f "$BIN/$d" ] && [ ! -f "../dist/data/$d" ]; then | |
| cp "$BIN/$d" ../dist/data/ | |
| NEED="$NEED ../dist/data/$d" | |
| added=1 | |
| fi | |
| done | |
| done | |
| done | |
| cp src/config/geoip src/config/geoip6 ../dist/data/ | |
| ls ../dist/data/ | |
| - name: Download transports | |
| uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 (node24) | |
| with: | |
| name: transports-win64 | |
| path: transports/ | |
| - name: Merge transports into dist/data | |
| shell: pwsh | |
| run: | | |
| Copy-Item "transports\*.exe" -Destination "dist\data\" -Force | |
| Get-ChildItem "dist" -Recurse -File | Select-Object FullName, Length | |
| - name: Copy config template, bridges, README | |
| shell: pwsh | |
| run: | | |
| Copy-Item "configs\torrc.jet" "dist\data\torrc.template" -Force | |
| Copy-Item "bridges\*.txt" "dist\data\bridges\" -Force | |
| Copy-Item "README.md" "dist\data\README.md" -Force | |
| - name: Compile TorJet.exe | |
| shell: pwsh | |
| env: | |
| INPUT_TAG: ${{ github.event.inputs.tag }} | |
| run: | | |
| $ver = $env:INPUT_TAG | |
| if (-not $ver) { $ver = "${{ github.ref_name }}" } | |
| if ($ver -notmatch '^v?\d') { $ver = "" } | |
| & "scripts\build-start-tor.ps1" -OutFile "dist\TorJet.exe" -Version $ver | |
| - name: Upload single release artifact | |
| uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 (node24) | |
| with: | |
| name: torjet-win64 | |
| path: dist/ | |
| - name: Upload build log | |
| if: always() | |
| uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 (node24) | |
| with: | |
| name: build-log-win | |
| path: tor-src/build-win.log | |
| release: | |
| name: Publish GitHub Release | |
| runs-on: ubuntu-latest | |
| needs: [tor-win64] | |
| if: | | |
| (github.event_name == 'workflow_dispatch' && github.event.inputs.tag != '') || | |
| startsWith(github.ref, 'refs/tags/') | |
| permissions: | |
| contents: write | |
| env: | |
| BETA: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.beta || 'false' }} | |
| steps: | |
| - name: Validate and resolve tag | |
| id: tag | |
| shell: bash | |
| env: | |
| INPUT_TAG: ${{ github.event.inputs.tag }} | |
| run: | | |
| if [ -n "$INPUT_TAG" ]; then | |
| TAG="$INPUT_TAG" | |
| else | |
| TAG="${GITHUB_REF#refs/tags/}" | |
| fi | |
| case "$TAG" in | |
| v[0-9][0-9A-Za-z._-]*) ;; | |
| *) echo "::error::refusing unsafe release tag '$TAG'"; exit 1;; | |
| esac | |
| echo "TAG=$TAG" >> "$GITHUB_OUTPUT" | |
| echo "Publishing release tag: $TAG" | |
| # Full history so the release notes can list commits since the previous tag. | |
| - uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0 (node24) | |
| with: | |
| ref: ${{ steps.tag.outputs.TAG }} | |
| fetch-depth: 0 | |
| - name: Build release notes | |
| shell: bash | |
| env: | |
| TAG: ${{ steps.tag.outputs.TAG }} | |
| run: | | |
| PREV="$(git tag --sort=-creatordate | grep -vx "$TAG" | head -n 1 || true)" | |
| SHA="$(git rev-parse --short=9 HEAD)" | |
| { | |
| echo "TorJet $TAG — portable Windows Tor client tuned for maximum throughput." | |
| echo "" | |
| if [ "$BETA" = "true" ]; then | |
| echo "> **BETA (pre-release) build.**" | |
| echo "" | |
| fi | |
| echo "**Download:** \`torjet-win64-$TAG.zip\` — unzip anywhere and double-click \`TorJet.exe\`." | |
| echo "" | |
| echo "Built in CI from official tor 0.4.9.11 sources plus obfs4, webtunnel" | |
| echo "and snowflake." | |
| echo "" | |
| echo "| Endpoint | Address |" | |
| echo "|---|---|" | |
| echo "| SOCKS5 | 127.0.0.1:9050 |" | |
| echo "| HTTP CONNECT tunnel | 127.0.0.1:8118 |" | |
| echo "| DNS | 127.0.0.1:53530 |" | |
| echo "" | |
| echo "- Commit: \`$SHA\`" | |
| if [ -n "$PREV" ]; then | |
| echo "- Compare: https://github.com/${{ github.repository }}/compare/$PREV...$TAG" | |
| fi | |
| echo "" | |
| if [ -n "$PREV" ]; then | |
| echo "## Changes since $PREV" | |
| else | |
| echo "## Recent changes" | |
| fi | |
| echo "" | |
| if [ -n "$PREV" ]; then | |
| git log --oneline --no-decorate "$PREV..$TAG" | sed 's/^/- /' | |
| else | |
| git log --oneline --no-decorate -n 15 | sed 's/^/- /' | |
| fi | |
| } > "$GITHUB_WORKSPACE/release-notes.md" | |
| echo "--- release-notes.md ---" | |
| cat "$GITHUB_WORKSPACE/release-notes.md" | |
| - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 (node24) | |
| with: | |
| name: torjet-win64 | |
| path: release | |
| - name: Package portable folder into zip | |
| shell: bash | |
| env: | |
| TAG: ${{ steps.tag.outputs.TAG }} | |
| run: | | |
| cd release | |
| zip -r "../torjet-win64-$TAG.zip" TorJet.exe data | |
| ls -la ../ | |
| - name: Publish release | |
| shell: bash | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| TAG: ${{ steps.tag.outputs.TAG }} | |
| run: | | |
| ZIP="torjet-win64-$TAG.zip" | |
| NOTES="$GITHUB_WORKSPACE/release-notes.md" | |
| if [ "$BETA" = "true" ]; then | |
| PRERELEASE="--prerelease" | |
| echo "Publishing as BETA (pre-release)" | |
| else | |
| PRERELEASE="" | |
| echo "Publishing as full release (latest)" | |
| fi | |
| if gh release view "$TAG" --repo "${{ github.repository }}" >/dev/null 2>&1; then | |
| gh release upload "$TAG" "$ZIP" --repo "${{ github.repository }}" --clobber | |
| if [ "$BETA" = "true" ]; then | |
| gh release edit "$TAG" --repo "${{ github.repository }}" \ | |
| --notes-file "$NOTES" --prerelease | |
| else | |
| gh release edit "$TAG" --repo "${{ github.repository }}" \ | |
| --notes-file "$NOTES" --prerelease=false | |
| fi | |
| else | |
| gh release create "$TAG" "$ZIP" \ | |
| --repo "${{ github.repository }}" \ | |
| --title "TorJet $TAG" \ | |
| --notes-file "$NOTES" \ | |
| $PRERELEASE | |
| fi |