name: Build (reusable) on: workflow_call: env: FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true jobs: build-linux: runs-on: ubuntu-latest steps: - name: Setup repo uses: actions/checkout@v4 with: fetch-depth: 0 fetch-tags: true - name: Setup Node.js uses: actions/setup-node@v4 with: node-version-file: ".nvmrc" - name: Setup Rust (linux musl + windows-gnu + freebsd targets) uses: dtolnay/rust-toolchain@stable with: targets: x86_64-unknown-linux-musl,aarch64-unknown-linux-musl,armv7-unknown-linux-musleabihf,x86_64-pc-windows-gnu,x86_64-unknown-freebsd - uses: Swatinem/rust-cache@v2 with: key: linux-cross # GHA scopes cache *writes* to the creating ref, so entries written by # a tag run are never readable again — they only evict main's under the # 10 GB repo cap. Tag runs still restore from the default branch. save-if: ${{ github.ref == 'refs/heads/main' }} - name: Install cross-toolchains run: | sudo apt-get update # apt-only C cross-compilers; Rust supplies the static musl libc itself. # clang/lld/llvm are for the FreeBSD cross-build (no apt freebsd gcc). # (linker/CC wiring lives in .cargo/config.toml) sudo apt-get install -y musl-tools gcc-aarch64-linux-gnu \ gcc-arm-linux-gnueabihf gcc-mingw-w64-x86-64 \ clang lld llvm - name: Install npm dependencies run: npm ci - name: Build linux/windows binaries (compile once → raw + zips) run: make build-linux-ci - name: Build FreeBSD server + sb CLI run: | sudo mkdir -p /opt/freebsd-sysroot # Link against the OLDEST release still on the mirror, not the newest. # FreeBSD's libc uses symbol versioning (FBSD_1.x) that is only # backward compatible: a binary linked against 15.1 records a # FBSD_1.9 dependency and then refuses to start on 15.0 or 14.x # ("version FBSD_1.9 required by silverbullet not found"), while one # linked against 14.3 (max FBSD_1.8) runs on everything newer too. # The mirror only carries supported releases, so "oldest available" # tracks the support window on its own and never 404s on a pinned # version that got pruned. VER=$(curl -fsSL https://download.freebsd.org/releases/amd64/ \ | grep -oE '[0-9]+\.[0-9]+-RELEASE' | sort -V | uniq | head -1) echo "Oldest supported FreeBSD release (sysroot): $VER" curl -fsSL "https://download.freebsd.org/releases/amd64/$VER/base.txz" \ | sudo tar -xJf - -C /opt/freebsd-sysroot ./lib ./usr/lib ./usr/include make build-server-releases-freebsd make build-cli-releases-freebsd - name: Upload release zips (linux/windows/freebsd) uses: actions/upload-artifact@v4 with: name: release-zips-linux path: | silverbullet-server-*.zip sb-*.zip if-no-files-found: error - name: Upload raw docker binaries uses: actions/upload-artifact@v4 with: name: docker-binaries path: | silverbullet-amd64 silverbullet-arm64 silverbullet-arm if-no-files-found: error build-macos: runs-on: macos-latest steps: - name: Setup repo uses: actions/checkout@v4 with: fetch-depth: 0 fetch-tags: true - name: Setup Node.js uses: actions/setup-node@v4 with: node-version-file: ".nvmrc" - name: Setup Rust uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@v2 with: key: macos save-if: ${{ github.ref == 'refs/heads/main' }} - name: Install npm dependencies run: npm ci # The case-insensitive filesystem checks should run on macOS (case insensitive file system) - name: Test (macOS-only filesystem behavior) run: cargo test -p silverbullet-server-common --all-features - name: Build server + CLI release archives (darwin x2) run: | make build-server-releases-macos make build-cli-releases-rust-macos - name: Import certificate into keychain env: APPLE_CERTIFICATE_P12_BASE64: ${{ secrets.APPLE_CERTIFICATE_P12_BASE64 }} APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} run: | echo "$APPLE_CERTIFICATE_P12_BASE64" | base64 --decode > certificate.p12 KEYCHAIN_PATH="$RUNNER_TEMP/signing.keychain-db" KEYCHAIN_PASSWORD="$(openssl rand -hex 20)" security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH" security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" security import certificate.p12 \ -P "$APPLE_CERTIFICATE_PASSWORD" \ -A \ -t cert \ -f pkcs12 \ -k "$KEYCHAIN_PATH" security list-keychain -d user -s "$KEYCHAIN_PATH" security set-key-partition-list -S apple-tool:,apple:,codesign: \ -s -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" rm certificate.p12 - name: Sign and notarize macOS binaries env: APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }} APPLE_API_KEY_ISSUER_ID: ${{ secrets.APPLE_API_KEY_ISSUER_ID }} APPLE_API_KEY_P8_BASE64: ${{ secrets.APPLE_API_KEY_P8_BASE64 }} run: | mkdir -p "$HOME/private_keys" echo "$APPLE_API_KEY_P8_BASE64" | base64 --decode \ > "$HOME/private_keys/AuthKey_${APPLE_API_KEY_ID}.p8" IDENTITY="Developer ID Application: Zef Hemel ($APPLE_TEAM_ID)" # Both the server and the `sb` CLI darwin archives. for zip_file in *-darwin-*.zip; do echo "=== Processing $zip_file ===" zip_file="$(pwd)/$zip_file" WORK_DIR=$(mktemp -d) unzip -o "$zip_file" -d "$WORK_DIR" BINARY=$(ls "$WORK_DIR") codesign --force --options runtime \ --sign "$IDENTITY" \ --timestamp \ "$WORK_DIR/$BINARY" codesign --verify --verbose "$WORK_DIR/$BINARY" NOTARIZE_ZIP="$WORK_DIR/notarize.zip" ditto -c -k --keepParent "$WORK_DIR/$BINARY" "$NOTARIZE_ZIP" xcrun notarytool submit "$NOTARIZE_ZIP" \ --key "$HOME/private_keys/AuthKey_${APPLE_API_KEY_ID}.p8" \ --key-id "$APPLE_API_KEY_ID" \ --issuer "$APPLE_API_KEY_ISSUER_ID" \ --wait --timeout 10m rm "$zip_file" (cd "$WORK_DIR" && zip "$zip_file" "$BINARY") rm -rf "$WORK_DIR" done rm -rf "$HOME/private_keys" - name: Clean up keychain if: always() run: | security delete-keychain "$RUNNER_TEMP/signing.keychain-db" 2>/dev/null || true - name: Upload macOS release zips uses: actions/upload-artifact@v4 with: name: release-zips-macos path: | silverbullet-server-darwin-*.zip sb-darwin-*.zip if-no-files-found: error