release: v0.9.8 #14
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-windows.zip (TinyPlay.exe + mpv/, unzip & double-click) | |
| # 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 | |
| run: | | |
| set -euo pipefail | |
| api=$(curl -sL https://api.github.com/repos/zhongfly/mpv-winbuild/releases/latest) | |
| # Pick the plain x86_64 build (not the -v3- or -dev- variants). | |
| url=$(echo "$api" | grep -oE 'https://[^"]*mpv-x86_64-2[0-9]+[^"]*\.7z' | head -1) | |
| echo "mpv archive: $url" | |
| curl -L -o mpv.7z "$url" | |
| 7z x mpv.7z -ompv_extract | |
| mpv_exe=$(find mpv_extract -name mpv.exe | head -1) | |
| mpv_dir=$(dirname "$mpv_exe") | |
| mkdir -p dist/mpv | |
| cp "$mpv_exe" dist/mpv/ | |
| # These builds are mostly static, but copy any sibling DLLs just in case. | |
| cp "$mpv_dir"/*.dll dist/mpv/ 2>/dev/null || true | |
| - name: Embed exe icon | |
| shell: bash | |
| run: | | |
| go install github.com/akavel/rsrc@latest | |
| "$(go env GOPATH)/bin/rsrc" -ico assets/icon.ico -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: Package zip | |
| shell: bash | |
| run: | | |
| cd dist | |
| 7z a ../TinyPlay-windows.zip ./* | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: TinyPlay-windows | |
| path: TinyPlay-windows.zip | |
| - name: Attach to release | |
| if: startsWith(github.ref, 'refs/tags/') | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| files: TinyPlay-windows.zip | |
| 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 }}) | |
| run: GOOS=darwin GOARCH=${{ matrix.goarch }} go build -o build/tvremote-core-darwin-${{ matrix.goarch }} ./cmd/tvremote | |
| - 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 |