feat(platform): better contract state transitions #942
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 Swift SDK and Example (no warnings) | |
| on: | |
| pull_request: | |
| paths: | |
| - 'packages/swift-sdk/**' | |
| - 'packages/rs-*/**' | |
| - '.github/workflows/swift-sdk-build.yml' | |
| push: | |
| branches: [ main, master ] | |
| paths: | |
| - 'packages/swift-sdk/**' | |
| - 'packages/rs-*/**' | |
| - '.github/workflows/swift-sdk-build.yml' | |
| jobs: | |
| swift-sdk-build: | |
| name: Swift SDK and Example build (warnings as errors) | |
| runs-on: [self-hosted, macOS, ARM64] | |
| timeout-minutes: 90 | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Show Xcode and Swift versions (use default on self-hosted runner) | |
| run: | | |
| xcodebuild -version | |
| swift --version | |
| # Rust + Cargo cache to speed up FFI build | |
| - name: Set up Rust toolchain (stable) | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Cache cargo registry | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| key: cargo-registry-${{ hashFiles('**/Cargo.lock') }} | |
| - name: Add iOS Rust targets | |
| run: | | |
| rustup target add aarch64-apple-ios aarch64-apple-ios-sim | |
| - name: Install cbindgen (for header generation) | |
| run: | | |
| brew install cbindgen || true | |
| - name: Restore cached Protobuf (protoc) | |
| id: cache-protoc | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ${{ env.HOME }}/.local/protoc-32.0/bin | |
| ${{ env.HOME }}/.local/protoc-32.0/include | |
| key: protoc/32.0/${{ runner.os }}/universal | |
| - name: Install Protobuf (protoc) if cache miss | |
| if: steps.cache-protoc.outputs.cache-hit != 'true' | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| set -euxo pipefail | |
| VERSION=32.0 | |
| OS=osx-universal_binary | |
| PROTOC_DIR="$HOME/.local/protoc-${VERSION}" | |
| mkdir -p "$PROTOC_DIR" | |
| curl -fsSL -H "Authorization: token ${GITHUB_TOKEN}" \ | |
| -o /tmp/protoc.zip \ | |
| "https://github.com/protocolbuffers/protobuf/releases/download/v${VERSION}/protoc-${VERSION}-${OS}.zip" | |
| unzip -o /tmp/protoc.zip -d "$PROTOC_DIR" | |
| - name: Save cached Protobuf (protoc) | |
| if: steps.cache-protoc.outputs.cache-hit != 'true' | |
| uses: actions/cache/save@v4 | |
| with: | |
| path: | | |
| ${{ env.HOME }}/.local/protoc-32.0/bin | |
| ${{ env.HOME }}/.local/protoc-32.0/include | |
| key: protoc/32.0/${{ runner.os }}/universal | |
| - name: Verify protoc and export env | |
| run: | | |
| set -euxo pipefail | |
| echo "$HOME/.local/protoc-32.0/bin" >> $GITHUB_PATH | |
| echo "PROTOC=$HOME/.local/protoc-32.0/bin/protoc" >> "$GITHUB_ENV" | |
| "$HOME/.local/protoc-32.0/bin/protoc" --version | |
| - name: Determine rust-dashcore revision (from rs-dpp) | |
| id: dashcore_rev | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| # Use the same rust-dashcore revision/tag as rs-dpp | |
| # Try to find tag first (preferred format) | |
| REV=$(grep -E '^[[:space:]]*dashcore[[:space:]]*=[[:space:]]*\{.*tag[[:space:]]*=' packages/rs-dpp/Cargo.toml \ | |
| | sed -E 's/.*tag[[:space:]]*=[[:space:]]*"([^"]+)".*/\1/' \ | |
| | head -n1 || true) | |
| # If no tag found, try rev format | |
| if [ -z "${REV:-}" ]; then | |
| REV=$(grep -E '^[[:space:]]*dashcore[[:space:]]*=[[:space:]]*\{.*rev[[:space:]]*=' packages/rs-dpp/Cargo.toml \ | |
| | sed -E 's/.*rev[[:space:]]*=[[:space:]]*"([^"]+)".*/\1/' \ | |
| | head -n1 || true) | |
| fi | |
| if [ -z "${REV:-}" ]; then | |
| echo "Failed to determine rust-dashcore revision or tag from Cargo.toml" >&2 | |
| exit 1 | |
| fi | |
| echo "rev=$REV" >> "$GITHUB_OUTPUT" | |
| - name: Checkout rust-dashcore at required revision | |
| shell: bash | |
| run: | | |
| set -euxo pipefail | |
| BASE_DIR="$(dirname "$GITHUB_WORKSPACE")" | |
| cd "$BASE_DIR" | |
| if [ -d rust-dashcore/.git ]; then | |
| echo "Updating existing rust-dashcore checkout" | |
| cd rust-dashcore | |
| git fetch --all --tags --prune | |
| else | |
| git clone --filter=blob:none https://github.com/dashpay/rust-dashcore.git rust-dashcore | |
| cd rust-dashcore | |
| fi | |
| git reset --hard # clean any local changes from previous runs, possibly with another branch | |
| git checkout "${{ steps.dashcore_rev.outputs.rev }}" | |
| - name: Determine rust-dashcore toolchain channel | |
| id: dashcore_toolchain | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| FILE="$(dirname "$GITHUB_WORKSPACE")/rust-dashcore/rust-toolchain.toml" | |
| if [ -f "$FILE" ]; then | |
| CHANNEL=$(grep -E '^[[:space:]]*channel[[:space:]]*=' "$FILE" | sed -E 's/.*"([^"]+)".*/\1/' | head -n1 || true) | |
| fi | |
| CHANNEL=${CHANNEL:-stable} | |
| echo "channel=$CHANNEL" >> "$GITHUB_OUTPUT" | |
| echo "RUST_DASHCORE_TOOLCHAIN=$CHANNEL" >> "$GITHUB_ENV" | |
| - name: Ensure rust-dashcore toolchain has iOS targets | |
| shell: bash | |
| run: | | |
| set -euxo pipefail | |
| RUST_DASHCORE_DIR="$(dirname "$GITHUB_WORKSPACE")/rust-dashcore" | |
| cd "$RUST_DASHCORE_DIR" | |
| TOOLCHAIN="${{ steps.dashcore_toolchain.outputs.channel }}" | |
| rustup toolchain install "$TOOLCHAIN" --profile minimal --no-self-update | |
| rustup target add --toolchain "$TOOLCHAIN" aarch64-apple-ios aarch64-apple-ios-sim x86_64-apple-ios | |
| - name: Build DashSDKFFI.xcframework and install into Swift package | |
| run: | | |
| bash packages/swift-sdk/build_ios.sh | |
| - name: Zip XCFramework and compute checksum | |
| run: | | |
| cd packages/swift-sdk | |
| ditto -c -k --sequesterRsrc --keepParent DashSDKFFI.xcframework DashSDKFFI.xcframework.zip | |
| swift package compute-checksum DashSDKFFI.xcframework.zip > xc_checksum.txt | |
| - name: Upload DashSDKFFI artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: DashSDKFFI.xcframework | |
| path: | | |
| packages/swift-sdk/DashSDKFFI.xcframework | |
| packages/swift-sdk/DashSDKFFI.xcframework.zip | |
| packages/swift-sdk/xc_checksum.txt | |
| retention-days: 14 | |
| - name: Comment/update PR with artifact link and usage guide (skip if unchanged) | |
| if: github.event_name == 'pull_request' | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const runUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`; | |
| const fs = require('fs'); | |
| const marker = '<!-- DASHSDKFFI_ARTIFACT_COMMENT -->'; | |
| let checksum = ''; | |
| try { checksum = fs.readFileSync('packages/swift-sdk/xc_checksum.txt', 'utf8').trim(); } catch (e) {} | |
| // Find existing marker comment on this PR | |
| const issue_number = context.payload.pull_request.number; | |
| const comments = await github.paginate(github.rest.issues.listComments, { | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number, | |
| per_page: 100 | |
| }); | |
| const existing = comments.find(c => (c.body || '').includes(marker)); | |
| // Extract old checksum if present | |
| const extractChecksum = (text) => { | |
| if (!text) return ''; | |
| const m = text.match(/checksum:\s*"?([a-f0-9]{64})"?/i); | |
| return m ? m[1] : ''; | |
| }; | |
| const oldChecksum = existing ? extractChecksum(existing.body) : ''; | |
| if (oldChecksum && checksum && oldChecksum === checksum) { | |
| core.info(`Checksum unchanged (${checksum}); skipping PR comment update.`); | |
| return; | |
| } | |
| const body = `${marker}\n` + | |
| `✅ DashSDKFFI.xcframework built for this PR.\n\n` + | |
| `- Workflow run: ${runUrl}\n` + | |
| `- Artifacts: DashSDKFFI.xcframework (folder), DashSDKFFI.xcframework.zip, xc_checksum.txt\n\n` + | |
| `SwiftPM (host the zip at a stable URL, then use):\n` + | |
| '```swift\n' + | |
| '.binaryTarget(\n' + | |
| ' name: "DashSDKFFI",\n' + | |
| ' url: "https://your.cdn.example/DashSDKFFI.xcframework.zip",\n' + | |
| ` checksum: "${checksum || '<paste checksum>'}"\n` + | |
| ')\n' + | |
| '```\n\n' + | |
| `Xcode manual integration:\n` + | |
| `- Download 'DashSDKFFI.xcframework' artifact from the run link above.\n` + | |
| `- Drag it into your app target (Frameworks, Libraries & Embedded Content) and set Embed & Sign.\n` + | |
| `- If using the Swift wrapper package, point its binaryTarget to the xcframework location or add the package and place the xcframework at the expected path.\n`; | |
| if (existing) { | |
| await github.rest.issues.updateComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| comment_id: existing.id, | |
| body | |
| }); | |
| } else { | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number, | |
| body | |
| }); | |
| } | |
| - name: Build SwiftDashSDK package (warnings as errors) | |
| working-directory: packages/swift-sdk | |
| env: | |
| OTHER_SWIFT_FLAGS: -warnings-as-errors | |
| SWIFT_TREAT_WARNINGS_AS_ERRORS: YES | |
| SWIFT_SUPPRESS_WARNINGS: NO | |
| run: | | |
| xcodebuild \ | |
| -project SwiftExampleApp/SwiftExampleApp.xcodeproj \ | |
| -scheme SwiftDashSDK \ | |
| -destination 'generic/platform=iOS Simulator' \ | |
| -configuration Debug \ | |
| ARCHS=arm64 \ | |
| ONLY_ACTIVE_ARCH=YES \ | |
| OTHER_SWIFT_FLAGS="$OTHER_SWIFT_FLAGS" \ | |
| SWIFT_TREAT_WARNINGS_AS_ERRORS=$SWIFT_TREAT_WARNINGS_AS_ERRORS \ | |
| SWIFT_SUPPRESS_WARNINGS=$SWIFT_SUPPRESS_WARNINGS \ | |
| build | |
| - name: Resolve ExampleApp dependencies | |
| working-directory: packages/swift-sdk | |
| run: | | |
| xcodebuild -project SwiftExampleApp/SwiftExampleApp.xcodeproj -resolvePackageDependencies | |
| - name: Build SwiftExampleApp (warnings as errors) | |
| working-directory: packages/swift-sdk | |
| env: | |
| # Treat Swift warnings as errors during xcodebuild | |
| OTHER_SWIFT_FLAGS: -warnings-as-errors | |
| SWIFT_TREAT_WARNINGS_AS_ERRORS: YES | |
| SWIFT_SUPPRESS_WARNINGS: NO | |
| run: | | |
| xcodebuild \ | |
| -project SwiftExampleApp/SwiftExampleApp.xcodeproj \ | |
| -scheme SwiftExampleApp \ | |
| -sdk iphonesimulator \ | |
| -destination 'generic/platform=iOS Simulator' \ | |
| -configuration Debug \ | |
| ARCHS=arm64 \ | |
| ONLY_ACTIVE_ARCH=YES \ | |
| OTHER_SWIFT_FLAGS="$OTHER_SWIFT_FLAGS" \ | |
| SWIFT_TREAT_WARNINGS_AS_ERRORS=$SWIFT_TREAT_WARNINGS_AS_ERRORS \ | |
| SWIFT_SUPPRESS_WARNINGS=$SWIFT_SUPPRESS_WARNINGS \ | |
| build |