Update README with a GIF for the Expo CloudSync example #434
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, test and release sqlite-sync | |
| on: | |
| push: | |
| workflow_dispatch: | |
| permissions: | |
| contents: write | |
| pages: write | |
| id-token: write | |
| jobs: | |
| build: | |
| runs-on: ${{ matrix.os }} | |
| container: ${{ matrix.container && matrix.container || '' }} | |
| name: ${{ matrix.name }}${{ matrix.arch && format('-{0}', matrix.arch) || '' }} build${{ matrix.arch != 'arm64-v8a' && matrix.name != 'ios-sim' && matrix.name != 'ios' && matrix.name != 'wasm' && matrix.name != 'apple-xcframework' && ' + test' || ''}} | |
| timeout-minutes: 20 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - os: ubuntu-22.04 | |
| arch: x86_64 | |
| name: linux | |
| - os: ubuntu-22.04-arm | |
| arch: arm64 | |
| name: linux | |
| - os: ubuntu-22.04 | |
| arch: x86_64 | |
| name: linux-musl | |
| container: alpine:latest | |
| - os: ubuntu-22.04-arm | |
| arch: arm64 | |
| name: linux-musl | |
| - os: macos-15 | |
| name: macos | |
| make: COVERAGE=ON | |
| - os: windows-2022 | |
| arch: x86_64 | |
| name: windows | |
| - os: ubuntu-22.04 | |
| arch: arm64-v8a | |
| name: android | |
| make: PLATFORM=android ARCH=arm64-v8a | |
| - os: ubuntu-22.04 | |
| arch: x86_64 | |
| name: android | |
| make: PLATFORM=android ARCH=x86_64 | |
| sqlite-amalgamation-zip: https://sqlite.org/2025/sqlite-amalgamation-3490100.zip | |
| - os: macos-15 | |
| name: ios | |
| make: PLATFORM=ios | |
| - os: macos-15 | |
| name: ios-sim | |
| make: PLATFORM=ios-sim | |
| - os: ubuntu-22.04 | |
| name: wasm | |
| make: PLATFORM=wasm | |
| - os: macos-15 | |
| name: apple-xcframework | |
| make: xcframework | |
| defaults: | |
| run: | |
| shell: ${{ matrix.container && 'sh' || 'bash' }} | |
| env: | |
| CONNECTION_STRING: ${{ secrets.CONNECTION_STRING }} | |
| APIKEY: ${{ secrets.APIKEY }} | |
| WEBLITE: ${{ secrets.WEBLITE }} | |
| steps: | |
| - uses: actions/[email protected] | |
| - uses: msys2/[email protected] | |
| if: matrix.name == 'windows' | |
| with: | |
| msystem: mingw64 | |
| install: mingw-w64-x86_64-cc make | |
| - name: windows install dependencies | |
| if: matrix.name == 'windows' | |
| run: choco install sqlite -y | |
| - name: macos install dependencies | |
| if: matrix.name == 'macos' | |
| run: brew link sqlite --force && brew install lcov | |
| - name: linux-musl x86_64 install dependencies | |
| if: matrix.name == 'linux-musl' && matrix.arch == 'x86_64' | |
| run: apk update && apk add --no-cache gcc make curl sqlite openssl-dev musl-dev linux-headers | |
| - name: linux-musl arm64 setup container | |
| if: matrix.name == 'linux-musl' && matrix.arch == 'arm64' | |
| run: | | |
| docker run -d --name alpine \ | |
| --platform linux/arm64 \ | |
| -v ${{ github.workspace }}:/workspace \ | |
| -w /workspace \ | |
| -e CONNECTION_STRING="${{ env.CONNECTION_STRING }}" \ | |
| -e APIKEY="${{ env.APIKEY }}" \ | |
| -e WEBLITE="${{ env.WEBLITE }}" \ | |
| alpine:latest \ | |
| tail -f /dev/null | |
| docker exec alpine sh -c "apk update && apk add --no-cache gcc make curl sqlite openssl-dev musl-dev linux-headers" | |
| - name: windows build curl | |
| if: matrix.name == 'windows' | |
| run: make curl/windows/libcurl.a | |
| shell: msys2 {0} | |
| - name: wasm install wabt | |
| if: matrix.name == 'wasm' | |
| run: sudo apt install wabt | |
| - name: build sqlite-sync | |
| run: ${{ matrix.name == 'linux-musl' && matrix.arch == 'arm64' && 'docker exec alpine' || '' }} make extension ${{ matrix.make && matrix.make || ''}} | |
| - name: create keychain for codesign | |
| if: matrix.os == 'macos-15' | |
| run: | | |
| echo "${{ secrets.APPLE_CERTIFICATE }}" | base64 --decode > certificate.p12 | |
| security create-keychain -p "${{ secrets.KEYCHAIN_PASSWORD }}" build.keychain | |
| security default-keychain -s build.keychain | |
| security unlock-keychain -p "${{ secrets.KEYCHAIN_PASSWORD }}" build.keychain | |
| security import certificate.p12 -k build.keychain -P "${{ secrets.CERTIFICATE_PASSWORD }}" -T /usr/bin/codesign | |
| security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "${{ secrets.KEYCHAIN_PASSWORD }}" build.keychain | |
| - name: codesign dylib | |
| if: matrix.os == 'macos-15' && matrix.name != 'apple-xcframework' | |
| run: codesign --sign "${{ secrets.APPLE_TEAM_ID }}" --timestamp --options runtime dist/cloudsync.dylib | |
| - name: codesign and notarize xcframework | |
| if: matrix.name == 'apple-xcframework' | |
| run: | | |
| find dist/CloudSync.xcframework -name "*.framework" -exec echo "Signing: {}" \; -exec codesign --sign "${{ secrets.APPLE_TEAM_ID }}" --timestamp --options runtime {} \; # Sign each individual framework FIRST | |
| codesign --sign "${{ secrets.APPLE_TEAM_ID }}" --timestamp --options runtime dist/CloudSync.xcframework # Then sign the xcframework wrapper | |
| ditto -c -k --keepParent dist/CloudSync.xcframework dist/CloudSync.xcframework.zip | |
| xcrun notarytool submit dist/CloudSync.xcframework.zip --apple-id "${{ secrets.APPLE_ID }}" --password "${{ secrets.APPLE_PASSWORD }}" --team-id "${{ secrets.APPLE_TEAM_ID }}" --wait | |
| rm dist/CloudSync.xcframework.zip | |
| - name: cleanup keychain for codesign | |
| if: matrix.os == 'macos-15' | |
| run: | | |
| rm certificate.p12 | |
| security delete-keychain build.keychain | |
| - name: android setup test environment | |
| if: matrix.name == 'android' && matrix.arch != 'arm64-v8a' | |
| run: | | |
| echo "::group::enable kvm group perms" | |
| echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules | |
| sudo udevadm control --reload-rules | |
| sudo udevadm trigger --name-match=kvm | |
| echo "::endgroup::" | |
| echo "::group::download and build sqlite3 without SQLITE_OMIT_LOAD_EXTENSION" | |
| curl -O ${{ matrix.sqlite-amalgamation-zip }} | |
| unzip sqlite-amalgamation-*.zip | |
| export ${{ matrix.make }} | |
| $ANDROID_NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/${{ matrix.arch }}-linux-android26-clang sqlite-amalgamation-*/shell.c sqlite-amalgamation-*/sqlite3.c -o sqlite3 -ldl | |
| # remove unused folders to save up space | |
| rm -rf sqlite-amalgamation-*.zip sqlite-amalgamation-* openssl | |
| echo "::endgroup::" | |
| echo "::group::prepare the test script" | |
| make test PLATFORM=$PLATFORM ARCH=$ARCH || echo "It should fail. Running remaining commands in the emulator" | |
| cat > commands.sh << EOF | |
| mv -f /data/local/tmp/sqlite3 /system/xbin | |
| cd /data/local/tmp | |
| export CONNECTION_STRING="$CONNECTION_STRING" | |
| export APIKEY="$APIKEY" | |
| export WEBLITE="$WEBLITE" | |
| $(make test PLATFORM=$PLATFORM ARCH=$ARCH -n) | |
| EOF | |
| echo "::endgroup::" | |
| - name: android test sqlite-sync | |
| if: matrix.name == 'android' && matrix.arch != 'arm64-v8a' | |
| uses: reactivecircus/[email protected] | |
| with: | |
| api-level: 26 | |
| arch: ${{ matrix.arch }} | |
| script: | | |
| adb root | |
| adb remount | |
| adb push ${{ github.workspace }}/. /data/local/tmp/ | |
| adb shell "sh /data/local/tmp/commands.sh" | |
| - name: test sqlite-sync | |
| if: contains(matrix.name, 'linux') || matrix.name == 'windows' || matrix.name == 'macos' | |
| run: ${{ matrix.name == 'linux-musl' && matrix.arch == 'arm64' && 'docker exec alpine' || '' }} make test ${{ matrix.make && matrix.make || ''}} | |
| - uses: actions/[email protected] | |
| if: matrix.name == 'macos' | |
| with: | |
| path: coverage | |
| - uses: actions/[email protected] | |
| if: always() | |
| with: | |
| name: cloudsync-${{ matrix.name }}${{ matrix.arch && format('-{0}', matrix.arch) || '' }} | |
| path: dist/${{ matrix.name == 'wasm' && 'sqlite-wasm.zip' || matrix.name == 'apple-xcframework' && 'CloudSync.*' || 'cloudsync.*'}} | |
| if-no-files-found: error | |
| release: | |
| runs-on: ubuntu-22.04 | |
| name: release | |
| needs: build | |
| if: github.ref == 'refs/heads/main' | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| steps: | |
| - uses: actions/[email protected] | |
| - uses: actions/[email protected] | |
| with: | |
| path: artifacts | |
| - name: setup GitHub Pages | |
| uses: actions/configure-pages@v5 | |
| - name: deploy coverage to GitHub Pages | |
| uses: actions/[email protected] | |
| - name: release tag version from cloudsync.h | |
| id: tag | |
| run: | | |
| VERSION=$(make version) | |
| if [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then | |
| LATEST=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" https://api.github.com/repos/${{ github.repository }}/releases/latest | jq -r '.name') | |
| if [[ "$VERSION" != "$LATEST" || "$GITHUB_EVENT_NAME" == "workflow_dispatch" ]]; then | |
| echo "version=$VERSION" >> $GITHUB_OUTPUT | |
| else | |
| echo "::warning file=src/cloudsync.h::To release a new version, please update the CLOUDSYNC_VERSION in src/cloudsync.h to be different than the latest $LATEST" | |
| fi | |
| exit 0 | |
| fi | |
| echo "❌ CLOUDSYNC_VERSION not found in cloudsync.h" | |
| exit 1 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20.x' | |
| registry-url: 'https://registry.npmjs.org' | |
| - name: zip artifacts | |
| run: | | |
| for folder in "artifacts"/*; do | |
| if [ -d "$folder" ]; then | |
| name=$(basename "$folder") | |
| if [[ "$name" != "github-pages" && "$name" != "cloudsync-wasm" ]]; then | |
| (cd "$folder" && zip -rq "../../${name}-${{ steps.tag.outputs.version }}.zip" .) | |
| tar -czf "${name}-${{ steps.tag.outputs.version }}.tar.gz" -C "$folder" . | |
| fi | |
| fi | |
| done | |
| cp artifacts/cloudsync-wasm/sqlite-wasm.zip "sqlite-$(make sqlite_version)-sync-${{ steps.tag.outputs.version }}-wasm.zip" | |
| - name: wasm publish to npmjs | |
| if: steps.tag.outputs.version != '' | |
| run: | | |
| TAG=$(git ls-remote --tags https://github.com/sqlite/sqlite-wasm.git | \ | |
| awk -v ver=$(make sqlite_version) -F'/' '$NF ~ ver"-build[0-9]+$" {print $NF}' | \ | |
| sort -V | \ | |
| tail -n1) | |
| git clone --branch "$TAG" --depth 1 https://github.com/sqlite/sqlite-wasm.git sqlite-wasm | |
| rm -rf sqlite-wasm/sqlite-wasm/* | |
| unzip artifacts/cloudsync-wasm/sqlite-wasm.zip -d sqlite-wasm/tmp | |
| mv sqlite-wasm/tmp/sqlite-wasm-*/jswasm sqlite-wasm/sqlite-wasm | |
| cd sqlite-wasm && npm i && npm run fix && npm run publint && npm run check-types && cd .. | |
| PKG=sqlite-wasm/package.json | |
| TMP=sqlite-wasm/package.tmp.json | |
| DESC="SQLite Wasm compiled with the automatically initialized sqlite-sync extension. Conveniently packaged as an ES Module for effortless integration." | |
| jq \ | |
| --arg name "@sqliteai/sqlite-sync-wasm" \ | |
| --arg version "$(make sqlite_version)-sync-$(make version)" \ | |
| --arg desc "$DESC" \ | |
| --argjson keywords '["sync","offsync","cloudsync","sqliteai"]' \ | |
| --arg repo_url "git+https://github.com/sqliteai/sqlite-sync.git" \ | |
| --arg author "Gioele Cantoni ([email protected])" \ | |
| --arg bugs_url "https://github.com/sqliteai/sqlite-sync/issues" \ | |
| --arg homepage "https://github.com/sqliteai/sqlite-sync#readme" \ | |
| ' | |
| .name = $name | |
| | .version = $version | |
| | .description = $desc | |
| | .keywords += $keywords | |
| | del(.bin) | |
| | .scripts |= with_entries(select( | |
| .key != "build" | |
| and .key != "start" | |
| and .key != "start:node" | |
| and .key != "prepublishOnly" | |
| and .key != "deploy" | |
| )) | |
| | .repository.url = $repo_url | |
| | .author = $author | |
| | .bugs.url = $bugs_url | |
| | .homepage = $homepage | |
| | del(.devDependencies.decompress) | |
| | del(.devDependencies["http-server"]) | |
| | del(.devDependencies.shx) | |
| ' "$PKG" > "$TMP" && mv "$TMP" "$PKG" | |
| sed 's/@sqlite\.org\/sqlite-wasm/@sqliteai\/sqlite-sync-wasm/g' sqlite-wasm/README.md > sqlite-wasm/README.tmp | |
| echo -e "# sqlite-sync WASM $(make version)\nThis README and the TypeScript types are from the [official SQLite wasm repository](https://github.com/sqlite/sqlite-wasm)\n\n$(cat sqlite-wasm/README.tmp)" > sqlite-wasm/README.md | |
| rm -rf sqlite-wasm/tmp sqlite-wasm/bin sqlite-wasm/demo sqlite-wasm/README.tmp sqlite-wasm/package-lock.json | |
| cd sqlite-wasm && npm publish --access public | |
| #add --provenance to npm publish when the repo will be public | |
| env: | |
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | |
| - uses: softprops/[email protected] | |
| if: steps.tag.outputs.version != '' | |
| with: | |
| generate_release_notes: true | |
| tag_name: ${{ steps.tag.outputs.version }} | |
| files: | | |
| cloudsync-*-${{ steps.tag.outputs.version }}.zip | |
| cloudsync-*-${{ steps.tag.outputs.version }}.tar.gz | |
| CloudSync-*-${{ steps.tag.outputs.version }}.zip | |
| CloudSync-*-${{ steps.tag.outputs.version }}.tar.gz | |
| sqlite-*-sync-${{ steps.tag.outputs.version }}-wasm.zip | |
| make_latest: true |