8.0.30 #100
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/release | |
| on: | |
| push: | |
| branches: | |
| - main | |
| #on: workflow_dispatch | |
| jobs: | |
| create-release: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Check out Git repository | |
| uses: actions/checkout@v1 | |
| - name: Get package.json version | |
| id: get_version | |
| shell: bash | |
| run: | | |
| PACKAGE_VERSION=$(node -p "require('./package.json').version") | |
| echo "PACKAGE_VERSION=$PACKAGE_VERSION" >> $GITHUB_ENV | |
| - name: Create an empty release | |
| shell: bash | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| echo "Releasing version $PACKAGE_VERSION" | |
| gh release create "v$PACKAGE_VERSION" --draft \ | |
| --title "v$PACKAGE_VERSION" \ | |
| --notes-file RELEASE.md | |
| # --notes "Pinokio version $PACKAGE_VERSION." | |
| windows-unsigned: | |
| if: false | |
| needs: "create-release" | |
| runs-on: windows-2022 | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Check out Git repository | |
| uses: actions/checkout@v1 | |
| - name: Install Node.js, NPM and Yarn | |
| uses: actions/setup-node@v1 | |
| with: | |
| node-version: 22 | |
| - name: Build/release Electron app | |
| id: electron-builder | |
| uses: samuelmeuli/action-electron-builder@v1.6.0 | |
| with: | |
| github_token: ${{ secrets.github_token }} | |
| # If the commit is tagged with a version (e.g. "v1.0.0"), | |
| # release the app after building | |
| #release: ${{ startsWith(github.ref, 'refs/tags/v') }} | |
| release: true | |
| #args: --win --dir # Build win-unpacked only | |
| args: --win | |
| windows: | |
| # if: false | |
| needs: "create-release" | |
| runs-on: windows-2022 | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Check out Git repository | |
| uses: actions/checkout@v1 | |
| - name: Install Node.js, NPM and Yarn | |
| uses: actions/setup-node@v1 | |
| with: | |
| node-version: 22 | |
| - name: Build/release Electron app | |
| id: electron-builder | |
| uses: samuelmeuli/action-electron-builder@v1.6.0 | |
| with: | |
| github_token: ${{ secrets.github_token }} | |
| # If the commit is tagged with a version (e.g. "v1.0.0"), | |
| # release the app after building | |
| #release: ${{ startsWith(github.ref, 'refs/tags/v') }} | |
| #release: true | |
| release: false | |
| #args: --win --dir # Build win-unpacked only | |
| args: --win | |
| # - name: Check contents | |
| # run: | | |
| # dir dist-win32 \ | |
| # dir dist-win32\\win-unpacked | |
| # shell: cmd | |
| ### sign start | |
| - name: upload-unsigned-artifact | |
| id: upload-unsigned-artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| #path: dist-win32 | |
| #path: dist-win32/win-unpacked/Pinokio.exe | |
| path: dist-win32/Pinokio.exe | |
| retention-days: 1 | |
| - id: Sign | |
| if: ${{ runner.os == 'Windows' }} | |
| uses: signpath/github-action-submit-signing-request@v1.1 | |
| with: | |
| api-token: '${{ secrets.SIGNPATH_API_TOKEN }}' | |
| organization-id: 'd2da0df2-dc12-4516-8222-87178d5ebf3d' | |
| project-slug: 'pinokio' | |
| #signing-policy-slug: 'test-signing' | |
| signing-policy-slug: 'release-signing' | |
| github-artifact-id: '${{ steps.upload-unsigned-artifact.outputs.artifact-id }}' | |
| wait-for-completion: true | |
| output-artifact-directory: './signed-windows' | |
| parameters: | | |
| version: ${{ toJSON(github.ref_name) }} | |
| - name: Rebuild blockmap and latest.yml from signed installer | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| shopt -s nullglob | |
| files=(signed-windows/*.exe) | |
| if [[ ${#files[@]} -ne 1 ]]; then | |
| echo "Expected exactly one signed exe, found ${#files[@]}" >&2 | |
| exit 1 | |
| fi | |
| SIGNED_EXE="${files[0]}" | |
| EXE_BASENAME=$(basename "$SIGNED_EXE") | |
| VERSION=$(node -p "require('./package.json').version") | |
| OUT_DIR=dist-win32 | |
| mkdir -p "$OUT_DIR" | |
| # Use app-builder bundled with electron-builder to regenerate blockmap for the signed binary | |
| APP_BUILDER=$(node -p "require('app-builder-bin').appBuilderPath") | |
| "$APP_BUILDER" blockmap --input "$SIGNED_EXE" --output "$OUT_DIR/${EXE_BASENAME}.blockmap" | |
| EXE="$SIGNED_EXE" BLOCKMAP="$OUT_DIR/${EXE_BASENAME}.blockmap" VERSION="$VERSION" OUT_DIR="$OUT_DIR" node - <<'EOF' | |
| const fs = require('fs'); | |
| const crypto = require('crypto'); | |
| const path = require('path'); | |
| const exe = process.env.EXE; | |
| const blockmap = process.env.BLOCKMAP; | |
| const version = process.env.VERSION; | |
| const outDir = process.env.OUT_DIR; | |
| const exeStats = fs.statSync(exe); | |
| const blockmapStats = fs.statSync(blockmap); | |
| const sha512 = crypto.createHash('sha512').update(fs.readFileSync(exe)).digest('base64'); | |
| const lines = [ | |
| `version: ${version}`, | |
| `files:`, | |
| ` - url: ${path.basename(exe)}`, | |
| ` sha512: ${sha512}`, | |
| ` size: ${exeStats.size}`, | |
| ` blockMapSize: ${blockmapStats.size}`, | |
| `path: ${path.basename(exe)}`, | |
| `sha512: ${sha512}`, | |
| `releaseDate: "${new Date().toISOString()}"` | |
| ]; | |
| fs.writeFileSync(path.join(outDir, 'latest.yml'), lines.join('\n')); | |
| EOF | |
| # # Replace the unsigned exe with the signed exe | |
| # - name: Replace with signed exe | |
| # run: | | |
| # copy /Y ".\signed-windows\Pinokio.exe" ".\dist-win32\win-unpacked\Pinokio.exe" | |
| # shell: cmd | |
| ### sign end | |
| # # Build the final installer from the signed exe | |
| # - name: Build final installer | |
| # env: | |
| # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| ## CSC_IDENTITY_AUTO_DISCOVERY: "false" # disable any auto code-sign discovery | |
| ## DISABLE_CODE_SIGNING: "true" # electron-builder respects this to skip signing | |
| # run: | | |
| # #yarn run electron-builder --win --prepackaged dist-win32/win-unpacked --publish never | |
| # yarn run electron-builder --win --prepackaged dist-win32/win-unpacked --publish always | |
| - name: Get package.json version | |
| id: get_version | |
| shell: bash | |
| run: | | |
| PACKAGE_VERSION=$(node -p "require('./package.json').version") | |
| echo "PACKAGE_VERSION=$PACKAGE_VERSION" >> $GITHUB_ENV | |
| - name: Publish GitHub Release with gh | |
| shell: bash | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| echo "Releasing version $PACKAGE_VERSION" | |
| #gh release create "v$PACKAGE_VERSION" ./signed-windows/*.exe \ | |
| #gh release upload "v$PACKAGE_VERSION" ./dist-win32/*.exe .dist-win32/latest.yml ./dist-win32/*.exe.blockmap | |
| gh release upload "v$PACKAGE_VERSION" ./signed-windows/*.exe ./dist-win32/latest.yml ./dist-win32/*.exe.blockmap --clobber | |
| #gh release create "v$PACKAGE_VERSION" ./dist-win32/*.exe \ | |
| # --title "Release v$PACKAGE_VERSION" \ | |
| # --notes "Pinokio version $PACKAGE_VERSION." | |
| mac: | |
| # if: false | |
| needs: "create-release" | |
| runs-on: macos-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Check out Git repository | |
| uses: actions/checkout@v1 | |
| - name: Install Node.js, NPM and Yarn | |
| uses: actions/setup-node@v1 | |
| with: | |
| node-version: 22 | |
| # - name: Prepare for app notarization | |
| # if: startsWith(matrix.os, 'macos') | |
| # # Import Apple API key for app notarization on macOS | |
| # run: | | |
| # mkdir -p ~/private_keys/ | |
| # echo '${{ secrets.api_key }}' > ~/private_keys/AuthKey_${{ secrets.api_key_id }}.p8 | |
| - name: Build/release Electron app | |
| id: electron-builder | |
| uses: samuelmeuli/action-electron-builder@v1.6.0 | |
| with: | |
| # GitHub token, automatically provided to the action | |
| # (No need to define this secret in the repo settings) | |
| github_token: ${{ secrets.github_token }} | |
| # If the commit is tagged with a version (e.g. "v1.0.0"), | |
| # release the app after building | |
| #release: ${{ startsWith(github.ref, 'refs/tags/v') }} | |
| release: true | |
| mac_certs: ${{ secrets.mac_certs }} | |
| mac_certs_password: ${{ secrets.mac_certs_password }} | |
| env: | |
| # macOS notarization API key | |
| #API_KEY_ID: ${{ secrets.api_key_id }} | |
| #API_KEY_ISSUER_ID: ${{ secrets.api_key_issuer_id }} | |
| APPLE_ID: ${{ secrets.APPLE_ID }} | |
| APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }} | |
| APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} | |
| - name: Show notarization-error.log | |
| if: failure() | |
| run: cat dist-darwin/**/notarization-error.log || echo "No notarization-error.log found" | |
| linux: | |
| # if: false | |
| needs: "create-release" | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| arch: [x64, arm64] | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Check out Git repository | |
| uses: actions/checkout@v1 | |
| - name: Install Node.js, NPM and Yarn | |
| uses: actions/setup-node@v1 | |
| with: | |
| node-version: 22 | |
| - name: Install dependencies | |
| shell: bash | |
| run: | | |
| if [ -f package-lock.json ] || [ -f npm-shrinkwrap.json ]; then | |
| npm ci | |
| else | |
| npm install | |
| fi | |
| - name: Constrain Linux targets to matrix arch | |
| shell: bash | |
| env: | |
| TARGET_ARCH: ${{ matrix.arch }} | |
| run: | | |
| node - <<'EOF' | |
| const fs = require('fs'); | |
| const packagePath = './package.json'; | |
| const packageJson = JSON.parse(fs.readFileSync(packagePath, 'utf8')); | |
| const targetArch = process.env.TARGET_ARCH; | |
| if (!targetArch) { | |
| throw new Error('TARGET_ARCH is not set'); | |
| } | |
| const linux = packageJson.build && packageJson.build.linux; | |
| if (!linux || !Array.isArray(linux.target)) { | |
| throw new Error('build.linux.target is not configured as an array'); | |
| } | |
| linux.target = linux.target.map((entry) => { | |
| if (typeof entry === 'string') { | |
| return { target: entry, arch: [targetArch] }; | |
| } | |
| if (entry && typeof entry === 'object') { | |
| return { ...entry, arch: [targetArch] }; | |
| } | |
| return entry; | |
| }); | |
| fs.writeFileSync(packagePath, `${JSON.stringify(packageJson, null, 2)}\n`); | |
| EOF | |
| - name: Install ARM64 native packages | |
| if: matrix.arch == 'arm64' | |
| shell: bash | |
| run: | | |
| npm_config_os=linux \ | |
| npm_config_cpu=arm64 \ | |
| npm_config_libc=glibc \ | |
| npm_config_force=true \ | |
| npm install --no-save @parcel/watcher-linux-arm64-glibc@2.5.1 | |
| npm_config_os=linux \ | |
| npm_config_cpu=arm64 \ | |
| npm_config_libc=glibc \ | |
| npm_config_force=true \ | |
| npm install --no-save @koromix/koffi-linux-arm64@3.0.2 | |
| - name: Build/release Linux app | |
| shell: bash | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.github_token }} | |
| run: | | |
| ./node_modules/.bin/electron-builder install-app-deps --platform linux --arch ${{ matrix.arch }} | |
| ./node_modules/.bin/electron-builder --linux --${{ matrix.arch }} --publish never | |
| - name: Validate ARM64 Linux packaged natives | |
| if: matrix.arch == 'arm64' | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| shopt -s nullglob | |
| pick_file() { | |
| for candidate in "$@"; do | |
| if [ -f "$candidate" ]; then | |
| printf '%s\n' "$candidate" | |
| return 0 | |
| fi | |
| done | |
| return 1 | |
| } | |
| deb_files=(dist-linux/*arm64*.deb dist-linux/*aarch64*.deb) | |
| if [ ${#deb_files[@]} -eq 0 ]; then | |
| echo "No ARM64 .deb artifacts found in dist-linux" >&2 | |
| ls -la dist-linux || true | |
| exit 1 | |
| fi | |
| for deb in "${deb_files[@]}"; do | |
| echo "Validating $deb" | |
| workdir="$(mktemp -d)" | |
| dpkg-deb -x "$deb" "$workdir/root" | |
| if ! grep -R --binary-files=without-match -q '/opt/Pinokio/pinokio-bin' "$workdir/root"; then | |
| echo "Could not find /opt/Pinokio/pinokio-bin fallback in extracted package" >&2 | |
| exit 1 | |
| fi | |
| pty_node="$(pick_file \ | |
| "$workdir/root/opt/Pinokio/resources/app.asar.unpacked/node_modules/@homebridge/node-pty-prebuilt-multiarch/build/Release/pty.node" \ | |
| "$workdir/root/opt/Pinokio/resources/app.asar.unpacked/node_modules/pinokiod/node_modules/@homebridge/node-pty-prebuilt-multiarch/build/Release/pty.node" \ | |
| )" || { | |
| echo "Missing patched pty.node in ARM64 package" >&2 | |
| exit 1 | |
| } | |
| watcher_node="$(pick_file \ | |
| "$workdir/root/opt/Pinokio/resources/app.asar.unpacked/node_modules/@parcel/watcher/build/Release/watcher.node" \ | |
| "$workdir/root/opt/Pinokio/resources/app.asar.unpacked/node_modules/pinokiod/node_modules/@parcel/watcher/build/Release/watcher.node" \ | |
| )" || { | |
| echo "Missing patched watcher.node in ARM64 package" >&2 | |
| exit 1 | |
| } | |
| watcher_platform_node="$(pick_file \ | |
| "$workdir/root/opt/Pinokio/resources/app.asar.unpacked/node_modules/@parcel/watcher-linux-arm64-glibc/watcher.node" \ | |
| "$workdir/root/opt/Pinokio/resources/app.asar.unpacked/node_modules/pinokiod/node_modules/@parcel/watcher-linux-arm64-glibc/watcher.node" \ | |
| )" || { | |
| echo "Missing @parcel/watcher-linux-arm64-glibc payload in ARM64 package" >&2 | |
| exit 1 | |
| } | |
| file "$pty_node" | |
| file "$watcher_node" | |
| file "$watcher_platform_node" | |
| file "$pty_node" | grep -qi 'aarch64' || { | |
| echo "pty.node is not ARM64 in $deb" >&2 | |
| exit 1 | |
| } | |
| file "$watcher_node" | grep -qi 'aarch64' || { | |
| echo "watcher.node is not ARM64 in $deb" >&2 | |
| exit 1 | |
| } | |
| file "$watcher_platform_node" | grep -qi 'aarch64' || { | |
| echo "watcher-linux-arm64-glibc payload is not ARM64 in $deb" >&2 | |
| exit 1 | |
| } | |
| rm -rf "$workdir" | |
| done | |
| - name: Upload Linux release artifacts | |
| shell: bash | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| set -euo pipefail | |
| version="$(node -p "require('./package.json').version")" | |
| tag="v${version}" | |
| files=() | |
| while IFS= read -r -d '' file; do | |
| files+=("$file") | |
| done < <(find dist-linux -maxdepth 1 -type f \ | |
| \( -name '*.AppImage' -o -name '*.deb' -o -name '*.rpm' -o -name '*linux*.yml' -o -name 'latest*.yml' \) \ | |
| -print0) | |
| if [ "${#files[@]}" -eq 0 ]; then | |
| echo "No Linux artifacts found in dist-linux" >&2 | |
| ls -la dist-linux || true | |
| exit 1 | |
| fi | |
| gh release upload "$tag" "${files[@]}" --clobber |