release v1.0.6 #38
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
| # Builds the double-click TinyPlay desktop apps for Windows and macOS (both | |
| # Apple Silicon and Intel), with mpv bundled, and attaches them to a GitHub | |
| # Release when you push a v* tag. | |
| # | |
| # Windows → TinyPlay-Setup-x64.exe (install / upgrade in place) | |
| # macOS → TinyPlay-macos-arm64.dmg (Apple Silicon) | |
| # TinyPlay-macos-intel.dmg (Intel) | |
| # signed+notarized, drag TinyPlay.app to | |
| # Applications. Before the signing | |
| # secrets exist each falls back to an | |
| # unsigned TinyPlay-macos-<arch>.zip so | |
| # the build still runs. | |
| # | |
| # macOS is Developer ID signed + notarized + stapled when the signing secrets | |
| # are present, so users are not blocked by Gatekeeper ("unidentified developer"). | |
| # The signing job only runs on tag pushes / manual dispatch — never on pull | |
| # requests — so the certificate secrets are never exposed to untrusted forks. | |
| # Windows artifacts are UNSIGNED for now (no Windows code-signing certificate); | |
| # users may still see a SmartScreen "unknown publisher" prompt. | |
| # | |
| # The Intel macOS leg cross-builds from the arm64 runner: the Go core and | |
| # Swift shell cross-compile natively, but bundling a real x86_64 mpv binary | |
| # needs an x86_64 Homebrew prefix, which this job installs under Rosetta | |
| # (adds a few minutes of extra job time versus the native arm64 leg). | |
| name: release | |
| on: | |
| push: | |
| tags: ["v*"] | |
| workflow_dispatch: | |
| permissions: | |
| contents: write | |
| jobs: | |
| windows: | |
| runs-on: windows-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-go@v5 | |
| with: | |
| go-version: "1.22" | |
| - name: Download & bundle mpv | |
| shell: bash | |
| # Also stages vulkan-1.dll (mpv imports it and Windows does not ship it) | |
| # and fails the job if any bundled binary still has an unmet dependency. | |
| run: bash ./windows/bundle-mpv.sh dist/mpv | |
| - name: Embed exe icon | |
| shell: bash | |
| run: | | |
| go install github.com/akavel/rsrc@latest | |
| "$(go env GOPATH)/bin/rsrc" -ico assets/icon.ico -manifest cmd/tvremote/app.manifest -o cmd/tvremote/rsrc_windows.syso | |
| - name: Build exe | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| if [[ "$GITHUB_REF" == refs/tags/* ]]; then VER="${GITHUB_REF_NAME#v}"; else VER="0.0.0-dev"; fi | |
| go build -ldflags "-H windowsgui -X main.version=$VER" -o dist/TinyPlay.exe ./cmd/tvremote | |
| - name: Bundle third-party notices | |
| shell: bash | |
| run: cp THIRD_PARTY_NOTICES.md dist/THIRD_PARTY_NOTICES.md | |
| - name: Build Windows installer | |
| shell: pwsh | |
| run: | | |
| $compiler = "${env:ProgramFiles(x86)}\Inno Setup 6\ISCC.exe" | |
| if (-not (Test-Path $compiler)) { | |
| choco install innosetup --yes --no-progress | |
| } | |
| if (-not (Test-Path $compiler)) { | |
| throw "Inno Setup compiler was not installed" | |
| } | |
| if ("${{ github.ref }}" -like "refs/tags/*") { | |
| $version = "${{ github.ref_name }}".TrimStart('v') | |
| } else { | |
| $version = "0.0.0-dev" | |
| } | |
| & $compiler "/DMyAppVersion=$version" "windows\TinyPlay.iss" | |
| if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: TinyPlay-windows-setup | |
| path: dist/TinyPlay-Setup-x64.exe | |
| - name: Attach to release | |
| if: startsWith(github.ref, 'refs/tags/') | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| files: dist/TinyPlay-Setup-x64.exe | |
| macos: | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - arch: arm64 | |
| goarch: arm64 | |
| label: arm64 | |
| - arch: x86_64 | |
| goarch: amd64 | |
| label: intel | |
| runs-on: macos-14 # Apple Silicon; the intel leg cross-builds (see notes above) | |
| env: | |
| # 'true' only when the signing secrets exist; gates the sign step so the | |
| # build still succeeds (unsigned) before you've added them. | |
| HAS_SIGNING: ${{ secrets.MACOS_CERTIFICATE != '' && secrets.SIGN_IDENTITY != '' }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-go@v5 | |
| with: | |
| go-version: "1.22" | |
| - name: Build Go core (${{ matrix.goarch }}) | |
| # Pin the deployment target, do not turn cgo off. On the native arm64 | |
| # leg cgo is on, the external linker runs, and it stamps | |
| # LC_BUILD_VERSION minos with the runner's SDK (14.0 on macos-14) - | |
| # dyld then refuses to start the core on macOS 12/13, which is | |
| # invisible here and fatal there. Pinning gives minos 12.0 against the | |
| # newer SDK and changes nothing else; CGO_ENABLED=0 would also fix the | |
| # floor but would silently swap darwin's cgo DNS resolver for the pure | |
| # Go one on every Apple Silicon install, which is a behaviour change | |
| # for users who are not affected by the bug. The x86_64 leg | |
| # cross-compiles with cgo off already, where these vars are inert. | |
| run: MACOSX_DEPLOYMENT_TARGET=12.0 CGO_CFLAGS=-mmacosx-version-min=12.0 CGO_LDFLAGS=-mmacosx-version-min=12.0 GOOS=darwin GOARCH=${{ matrix.goarch }} go build -o build/tvremote-core-darwin-${{ matrix.goarch }} ./cmd/tvremote | |
| - name: Verify the core's deployment target | |
| # The bug this pin fixes shipped because nothing checked: v1.0.5 | |
| # advertised macOS 12 in LSMinimumSystemVersion and shipped a core | |
| # stamped minos 14.0. LSMinimumSystemVersion is a claim; LC_BUILD_VERSION | |
| # is the fact dyld enforces. Fail the build rather than ship that again. | |
| run: | | |
| set -euo pipefail | |
| bin="build/tvremote-core-darwin-${{ matrix.goarch }}" | |
| minos=$(otool -l "$bin" | awk '/LC_BUILD_VERSION/{f=1} f && $1=="minos"{print $2; exit}') | |
| echo "core minos: ${minos:-<none>}" | |
| case "$minos" in | |
| 10.*|11.*|12.0) ;; | |
| *) echo "core requires macOS $minos but TinyPlay advertises 12.0" >&2; exit 1 ;; | |
| esac | |
| - name: Install packaging tools (dylibbundler, create-dmg) | |
| run: brew install dylibbundler create-dmg | |
| - name: Install x86_64 Homebrew under Rosetta (intel leg only) | |
| if: matrix.arch == 'x86_64' | |
| run: | | |
| set -euo pipefail | |
| softwareupdate --install-rosetta --agree-to-license | |
| if [ ! -x /usr/local/bin/brew ]; then | |
| NONINTERACTIVE=1 arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" | |
| fi | |
| # GitHub's runner image ships a pre-existing python.org install under | |
| # /Library/Frameworks/Python.framework with matching /usr/local/bin | |
| # symlinks (idle3, pip3, ...). --overwrite only applies to the | |
| # formula named on the command line, not transitive build | |
| # dependencies, so when brewing mpv pulls in python@3.x (only to | |
| # build man pages) as a dependency, `brew link` on THAT dependency | |
| # still aborts on those pre-existing symlinks even with --overwrite | |
| # here. mpv itself finishes installing regardless, so tolerate the | |
| # failure and verify mpv is actually present instead of treating any | |
| # non-zero exit as fatal. | |
| arch -x86_64 /usr/local/bin/brew install --overwrite mpv || true | |
| if ! arch -x86_64 /usr/local/bin/brew list mpv >/dev/null 2>&1; then | |
| echo "mpv did not install successfully" >&2 | |
| exit 1 | |
| fi | |
| - name: Download & bundle mpv (self-contained via dylibbundler) | |
| run: | | |
| set -euo pipefail | |
| if [ "${{ matrix.arch }}" = "x86_64" ]; then | |
| real_mpv=$(readlink -f /usr/local/bin/mpv) | |
| else | |
| brew install mpv | |
| real_mpv=$(readlink -f "$(brew --prefix)/bin/mpv") | |
| fi | |
| mkdir -p mpvstage/bin/libs | |
| cp "$real_mpv" mpvstage/bin/mpv | |
| chmod u+w mpvstage/bin/mpv | |
| # Copy every non-system dylib next to the binary and rewrite load paths | |
| # so the bundle runs on a machine without Homebrew. -cd/-of/-od keep it | |
| # non-interactive (it otherwise prompts to create/overwrite and aborts). | |
| dylibbundler -cd -of -od -b -x mpvstage/bin/mpv -d mpvstage/bin/libs -p @executable_path/libs/ | |
| - name: Build .app | |
| run: | | |
| set -euo pipefail | |
| if [[ "$GITHUB_REF" == refs/tags/* ]]; then VER="${GITHUB_REF_NAME#v}"; else VER="0.0.0-dev"; fi | |
| ARCH="${{ matrix.arch }}" VERSION="$VER" MPV_DIR="$PWD/mpvstage" REQUIRE_BUNDLED_MPV=1 ./macos/build-app.sh | |
| # Import the Developer ID cert into a keychain that persists for the whole | |
| # job, so both the app-signing and DMG-signing steps below can use it. | |
| - name: Import signing certificate | |
| if: ${{ env.HAS_SIGNING == 'true' }} | |
| env: | |
| MACOS_CERTIFICATE: ${{ secrets.MACOS_CERTIFICATE }} | |
| MACOS_CERTIFICATE_PWD: ${{ secrets.MACOS_CERTIFICATE_PWD }} | |
| run: ./macos/import-cert.sh | |
| - name: Sign & notarize app | |
| if: ${{ env.HAS_SIGNING == 'true' }} | |
| env: | |
| SIGN_IDENTITY: ${{ secrets.SIGN_IDENTITY }} | |
| AC_API_KEY: ${{ secrets.AC_API_KEY }} | |
| AC_KEY_ID: ${{ secrets.AC_KEY_ID }} | |
| AC_ISSUER_ID: ${{ secrets.AC_ISSUER_ID }} | |
| run: ./macos/sign-notarize.sh "$PWD/build/TinyPlay.app" | |
| - name: Package signed DMG | |
| if: ${{ env.HAS_SIGNING == 'true' }} | |
| env: | |
| SIGN_IDENTITY: ${{ secrets.SIGN_IDENTITY }} | |
| AC_API_KEY: ${{ secrets.AC_API_KEY }} | |
| AC_KEY_ID: ${{ secrets.AC_KEY_ID }} | |
| AC_ISSUER_ID: ${{ secrets.AC_ISSUER_ID }} | |
| run: ./macos/make-dmg.sh "$PWD/build/TinyPlay.app" "$PWD/TinyPlay-macos-${{ matrix.label }}.dmg" | |
| - name: Package unsigned zip (fallback before secrets exist) | |
| if: ${{ env.HAS_SIGNING != 'true' }} | |
| run: | | |
| cd build | |
| ditto -c -k --keepParent "TinyPlay.app" "../TinyPlay-macos-${{ matrix.label }}.zip" | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: TinyPlay-macos-${{ matrix.label }} | |
| path: | | |
| TinyPlay-macos-${{ matrix.label }}.dmg | |
| TinyPlay-macos-${{ matrix.label }}.zip | |
| if-no-files-found: warn | |
| - name: Attach to release | |
| if: startsWith(github.ref, 'refs/tags/') | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| files: | | |
| TinyPlay-macos-${{ matrix.label }}.dmg | |
| TinyPlay-macos-${{ matrix.label }}.zip |