Nightly Build #133
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: Nightly Build | |
| # Daily / on-demand builds, published as a rolling pre-release on GitHub. | |
| # | |
| # Difference vs release.yml: | |
| # - release.yml → triggered by `v*` semver tags, becomes the "Latest" stable release | |
| # - nightly.yml → continuous interim builds, marked prerelease, single rolling tag | |
| # | |
| # Trigger options: | |
| # - Manual: Actions tab → "Nightly Build" → Run workflow | |
| # - Push to main: every commit (disabled by default; uncomment the push block) | |
| # - Daily cron at 04:00 UTC | |
| on: | |
| workflow_dispatch: | |
| schedule: | |
| - cron: '0 4 * * *' | |
| # Uncomment to also build on every push to main: | |
| # push: | |
| # branches: [main] | |
| permissions: | |
| contents: write | |
| concurrency: | |
| group: nightly-build | |
| cancel-in-progress: true | |
| jobs: | |
| prepare-release: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| version: ${{ steps.version.outputs.version }} | |
| tag: ${{ steps.version.outputs.tag }} | |
| release_id: ${{ steps.recreate.outputs.release_id }} | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Compute nightly version + tag | |
| id: version | |
| shell: bash | |
| run: | | |
| BASE_VERSION=$(node -p "require('./open-pdf-studio/package.json').version") | |
| DATE=$(date -u +'%Y%m%d') | |
| SHORT_SHA=$(git rev-parse --short HEAD) | |
| VERSION="${BASE_VERSION}-nightly.${DATE}.${SHORT_SHA}" | |
| echo "version=${VERSION}" >> "$GITHUB_OUTPUT" | |
| echo "tag=nightly" >> "$GITHUB_OUTPUT" | |
| echo "Building nightly ${VERSION}" | |
| - name: Delete previous nightly release + tag (rolling) | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| gh release delete nightly --yes --cleanup-tag || true | |
| - name: Create fresh nightly release (prerelease, draft=false so artifacts upload visibly) | |
| id: recreate | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const version = "${{ steps.version.outputs.version }}"; | |
| const { data } = await github.rest.repos.createRelease({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| tag_name: "nightly", | |
| target_commitish: context.sha, | |
| name: `Nightly build ${version}`, | |
| body: [ | |
| "🌙 **Nightly / interim build** — not a stable release.", | |
| "", | |
| "Built from the latest `main` branch. May contain bugs or incomplete features.", | |
| "For stable, use the latest `v*` release.", | |
| "", | |
| `Source: \`${context.sha.substring(0,7)}\``, | |
| `Build version: \`${version}\`` | |
| ].join("\n"), | |
| draft: false, | |
| prerelease: true | |
| }); | |
| core.setOutput("release_id", data.id); | |
| return data.id; | |
| build-tauri: | |
| needs: prepare-release | |
| permissions: | |
| contents: write | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - platform: 'ubuntu-22.04' | |
| args: '' | |
| target: 'linux' | |
| - platform: 'macos-26' | |
| args: '--target universal-apple-darwin' | |
| target: 'macos' | |
| - platform: 'windows-latest' | |
| args: '' | |
| target: 'windows-system' | |
| - platform: 'windows-latest' | |
| args: '' | |
| target: 'windows-user' | |
| runs-on: ${{ matrix.platform }} | |
| env: | |
| TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} | |
| TAURI_SIGNING_PRIVATE_KEY_PASSWORD: 'tauri2026' | |
| # linuxdeploy/appimagetool need FUSE; extract-and-run avoids requiring a | |
| # FUSE mount on the CI runner (harmless on Windows/macOS — only the | |
| # AppImage tooling reads it). | |
| APPIMAGE_EXTRACT_AND_RUN: 1 | |
| defaults: | |
| run: | |
| working-directory: open-pdf-studio | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: 20 | |
| - name: Install Rust stable | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Install Rust targets (macOS universal) | |
| if: matrix.target == 'macos' | |
| run: rustup target add aarch64-apple-darwin x86_64-apple-darwin | |
| - name: Install dependencies (Ubuntu only) | |
| if: matrix.target == 'linux' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf | |
| - name: Install frontend dependencies | |
| run: npm ci | |
| # The PDFium worker pool runs as a Tauri sidecar (bundle.externalBin). | |
| # Tauri requires binaries/pdfium-worker-<target-triple> to exist at build | |
| # time on EVERY desktop platform, so build the workspace crate first and | |
| # drop it in with the right triple suffix. Without these steps build.rs / | |
| # tauri_build fails the validation — the cause of the failing nightlies. | |
| - name: Build pdfium-worker sidecar (Windows) | |
| if: contains(matrix.target, 'windows') | |
| shell: pwsh | |
| working-directory: . | |
| run: | | |
| cargo build --release -p pdfium-worker | |
| New-Item -ItemType Directory -Force open-pdf-studio/src-tauri/binaries | Out-Null | |
| Copy-Item target/release/pdfium-worker.exe open-pdf-studio/src-tauri/binaries/pdfium-worker-x86_64-pc-windows-msvc.exe -Force | |
| - name: Build pdfium-worker sidecar (Linux) | |
| if: matrix.target == 'linux' | |
| working-directory: . | |
| run: | | |
| cargo build --release -p pdfium-worker | |
| mkdir -p open-pdf-studio/src-tauri/binaries | |
| cp target/release/pdfium-worker open-pdf-studio/src-tauri/binaries/pdfium-worker-x86_64-unknown-linux-gnu | |
| - name: Build pdfium-worker sidecar (macOS universal) | |
| if: matrix.target == 'macos' | |
| working-directory: . | |
| run: | | |
| cargo build --release -p pdfium-worker --target aarch64-apple-darwin | |
| cargo build --release -p pdfium-worker --target x86_64-apple-darwin | |
| mkdir -p open-pdf-studio/src-tauri/binaries | |
| # tauri-build validates the sidecar PER ARCH during the per-target | |
| # cargo builds of a universal bundle, so all three names must exist. | |
| cp target/aarch64-apple-darwin/release/pdfium-worker open-pdf-studio/src-tauri/binaries/pdfium-worker-aarch64-apple-darwin | |
| cp target/x86_64-apple-darwin/release/pdfium-worker open-pdf-studio/src-tauri/binaries/pdfium-worker-x86_64-apple-darwin | |
| lipo -create -output open-pdf-studio/src-tauri/binaries/pdfium-worker-universal-apple-darwin \ | |
| target/aarch64-apple-darwin/release/pdfium-worker \ | |
| target/x86_64-apple-darwin/release/pdfium-worker | |
| - name: Set user install mode (Windows user installer) | |
| if: matrix.target == 'windows-user' | |
| shell: pwsh | |
| run: | | |
| $conf = Get-Content src-tauri/tauri.conf.json -Raw | ConvertFrom-Json | |
| $conf.bundle.windows.nsis.installMode = "currentUser" | |
| $conf | ConvertTo-Json -Depth 10 | Set-Content src-tauri/tauri.conf.json | |
| # Linux uses in-proc PDFium (the worker sidecar is Windows-only), so the | |
| # AppImage must bundle libpdfium.so — referenced by tauri.linux.conf.json. | |
| # Fetch the same pdfium release as the committed win-x64/pdfium.dll | |
| # (bblanchon chromium/7834) before bundling. | |
| - name: Fetch libpdfium.so (Linux) | |
| if: matrix.target == 'linux' | |
| run: | | |
| mkdir -p src-tauri/binaries/linux-x64 | |
| curl -L "https://github.com/bblanchon/pdfium-binaries/releases/download/chromium%2F7834/pdfium-linux-x64.tgz" -o /tmp/pdfium-linux.tgz | |
| tar xzf /tmp/pdfium-linux.tgz -C /tmp lib/libpdfium.so | |
| cp /tmp/lib/libpdfium.so src-tauri/binaries/linux-x64/libpdfium.so | |
| # macOS bundelt in-proc PDFium (naast de worker-sidecar): tauri.macos.conf.json | |
| # verwijst naar binaries/macos-universal/libpdfium.dylib. Universal | |
| # (arm64+x86_64) via bblanchon/pdfium-binaries (zelfde chromium-release als | |
| # Linux/Windows), met SHA-256-verificatie. | |
| - name: Prepare libpdfium.dylib (macOS) | |
| if: matrix.target == 'macos' | |
| run: npm run prepare:native-runtime | |
| # Onderteken de dylib vóór het bundelen — zie release.yml voor de | |
| # onderbouwing (notarisatie keurt een onondertekende resource-dylib af). | |
| - name: Sign libpdfium.dylib (macOS) | |
| if: matrix.target == 'macos' | |
| shell: bash | |
| env: | |
| APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} | |
| APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} | |
| APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }} | |
| run: | | |
| set -euo pipefail | |
| KEYCHAIN="$RUNNER_TEMP/dylib-sign.keychain-db" | |
| KEYCHAIN_PW="$(uuidgen)" | |
| printf '%s' "$APPLE_CERTIFICATE" | base64 --decode > "$RUNNER_TEMP/dylib-cert.p12" | |
| security create-keychain -p "$KEYCHAIN_PW" "$KEYCHAIN" | |
| security set-keychain-settings -lut 21600 "$KEYCHAIN" | |
| security unlock-keychain -p "$KEYCHAIN_PW" "$KEYCHAIN" | |
| security import "$RUNNER_TEMP/dylib-cert.p12" -P "$APPLE_CERTIFICATE_PASSWORD" \ | |
| -A -t cert -f pkcs12 -k "$KEYCHAIN" | |
| security set-key-partition-list -S "apple-tool:,apple:,codesign:" \ | |
| -k "$KEYCHAIN_PW" "$KEYCHAIN" > /dev/null | |
| security list-keychains -d user -s "$KEYCHAIN" login.keychain-db | |
| codesign --force --options runtime --timestamp \ | |
| --sign "$APPLE_SIGNING_IDENTITY" \ | |
| src-tauri/binaries/macos-universal/libpdfium.dylib | |
| codesign -dv --verbose=2 src-tauri/binaries/macos-universal/libpdfium.dylib | |
| rm -f "$RUNNER_TEMP/dylib-cert.p12" | |
| - name: Write App Store Connect API key (macOS) | |
| if: matrix.target == 'macos' | |
| shell: bash | |
| run: | | |
| printf '%s' "${{ secrets.APPLE_API_KEY_CONTENT }}" > "${{ runner.temp }}/apple-api-key.p8" | |
| - name: Build Tauri app | |
| if: matrix.target != 'windows-user' && matrix.target != 'macos' | |
| uses: tauri-apps/tauri-action@action-v0.6.1 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| with: | |
| projectPath: open-pdf-studio | |
| args: ${{ matrix.args }} | |
| releaseId: ${{ needs.prepare-release.outputs.release_id }} | |
| includeUpdaterJson: false | |
| # Compile once. Bundling is a separate phase so a temporary failure in | |
| # the external notarization service can be retried without rebuilding | |
| # both macOS architectures. | |
| - name: Build macOS app without bundles | |
| if: matrix.target == 'macos' | |
| run: npm run tauri -- build --target universal-apple-darwin --no-bundle | |
| - name: Upload macOS release assets | |
| if: matrix.target == 'macos' | |
| uses: tauri-apps/tauri-action@action-v0.6.1 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} | |
| APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} | |
| APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }} | |
| # Notarisatie via App Store Connect API-key: Apple-ID + app-specifiek | |
| # wachtwoord gaf een permanente HTTP 500 op de notary-API (bekend | |
| # probleem met die auth-methode); de API-key-route is de door Apple | |
| # aanbevolen en betrouwbare CI-methode. | |
| APPLE_API_ISSUER: ${{ secrets.APPLE_API_ISSUER }} | |
| APPLE_API_KEY: ${{ secrets.APPLE_API_KEY }} | |
| APPLE_API_KEY_PATH: ${{ runner.temp }}/apple-api-key.p8 | |
| APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} | |
| with: | |
| projectPath: open-pdf-studio | |
| tauriScript: node scripts/macos-notarization-retry.mjs | |
| args: --target universal-apple-darwin | |
| releaseId: ${{ needs.prepare-release.outputs.release_id }} | |
| includeUpdaterJson: false | |
| - name: Verify macOS signature and notarization | |
| if: matrix.target == 'macos' | |
| run: | | |
| APP_PATH="../target/universal-apple-darwin/release/bundle/macos/Open PDF Studio.app" | |
| DMG_PATH="$(find ../target/universal-apple-darwin/release/bundle/dmg -name '*.dmg' -print -quit)" | |
| test -n "$DMG_PATH" | |
| codesign --verify --deep --strict --verbose=2 "$APP_PATH" | |
| spctl --assess --type execute --verbose=4 "$APP_PATH" | |
| xcrun stapler validate "$APP_PATH" | |
| xcrun stapler validate "$DMG_PATH" | |
| bash scripts/macos-startup-smoke.sh "$APP_PATH" | |
| - name: Build Tauri app (Windows user installer) | |
| if: matrix.target == 'windows-user' | |
| uses: tauri-apps/tauri-action@action-v0.6.1 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| with: | |
| projectPath: open-pdf-studio | |
| args: ${{ matrix.args }} | |
| releaseId: ${{ needs.prepare-release.outputs.release_id }} | |
| includeUpdaterJson: false |