Release #36
Workflow file for this run
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: Release | |
| # First-release pipeline (M1): Rust crates → crates.io, Node → npm, | |
| # Python → PyPI (trusted publishing), Go .a artifacts + C ABI artifacts → | |
| # GitHub Release. Swift / Kotlin / Flutter land in later milestones. | |
| on: | |
| push: | |
| tags: ['v*'] | |
| workflow_dispatch: | |
| inputs: | |
| rust: | |
| description: 'Publish Rust crates to crates.io' | |
| type: boolean | |
| default: true | |
| node: | |
| description: 'Build + publish Node binding to npm' | |
| type: boolean | |
| default: false | |
| python: | |
| description: 'Publish Python wheels to PyPI' | |
| type: boolean | |
| default: false | |
| jvm: | |
| description: 'Publish Java + Kotlin to Maven Central' | |
| type: boolean | |
| default: false | |
| flutter: | |
| description: 'Publish Flutter plugin to pub.dev (embeds mobile FFI libs)' | |
| type: boolean | |
| default: false | |
| artifacts: | |
| description: 'Build Go .a + C ABI libs and create GitHub Release' | |
| type: boolean | |
| default: false | |
| permissions: | |
| contents: write | |
| id-token: write # npm provenance + PyPI trusted publishing | |
| env: | |
| CARGO_TERM_COLOR: always | |
| jobs: | |
| # ── Rust core → crates.io (dependency order) ───────────────────────────── | |
| rust-publish: | |
| name: Publish crates to crates.io | |
| runs-on: ubuntu-latest | |
| environment: release | |
| if: github.event_name == 'push' || github.event.inputs.rust == 'true' | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| # Idempotent publish: skips a crate whose version already exists on | |
| # crates.io, so re-running the workflow after a partial failure is safe. | |
| # The version is read from the workspace Cargo.toml so this never goes | |
| # stale across releases. | |
| - name: Publish aimux-stream | |
| run: | | |
| VERSION=$(grep -m1 '^version = ' Cargo.toml | sed 's/version = "\(.*\)"/\1/') | |
| if curl -sf -A "aimux-ci" "https://crates.io/api/v1/crates/aimux-stream/${VERSION}" > /dev/null 2>&1; then | |
| echo "aimux-stream@${VERSION} already published, skipping" | |
| else | |
| cargo publish -p aimux-stream | |
| fi | |
| env: | |
| CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} | |
| - name: Publish aimux-core | |
| run: | | |
| sleep 30 | |
| VERSION=$(grep -m1 '^version = ' Cargo.toml | sed 's/version = "\(.*\)"/\1/') | |
| if curl -sf -A "aimux-ci" "https://crates.io/api/v1/crates/aimux-core/${VERSION}" > /dev/null 2>&1; then | |
| echo "aimux-core@${VERSION} already published, skipping" | |
| else | |
| cargo publish -p aimux-core | |
| fi | |
| env: | |
| CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} | |
| - name: Publish aimux-provider-utils | |
| run: | | |
| sleep 30 | |
| VERSION=$(grep -m1 '^version = ' Cargo.toml | sed 's/version = "\(.*\)"/\1/') | |
| if curl -sf -A "aimux-ci" "https://crates.io/api/v1/crates/aimux-provider-utils/${VERSION}" > /dev/null 2>&1; then | |
| echo "aimux-provider-utils@${VERSION} already published, skipping" | |
| else | |
| cargo publish -p aimux-provider-utils | |
| fi | |
| env: | |
| CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} | |
| - name: Publish aimux-providers | |
| run: | | |
| sleep 30 | |
| VERSION=$(grep -m1 '^version = ' Cargo.toml | sed 's/version = "\(.*\)"/\1/') | |
| if curl -sf -A "aimux-ci" "https://crates.io/api/v1/crates/aimux-providers/${VERSION}" > /dev/null 2>&1; then | |
| echo "aimux-providers@${VERSION} already published, skipping" | |
| else | |
| cargo publish -p aimux-providers | |
| fi | |
| env: | |
| CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} | |
| - name: Publish aimux-ffi | |
| run: | | |
| sleep 30 | |
| VERSION=$(grep -m1 '^version = ' Cargo.toml | sed 's/version = "\(.*\)"/\1/') | |
| if curl -sf -A "aimux-ci" "https://crates.io/api/v1/crates/aimux-ffi/${VERSION}" > /dev/null 2>&1; then | |
| echo "aimux-ffi@${VERSION} already published, skipping" | |
| else | |
| cargo publish -p aimux-ffi | |
| fi | |
| env: | |
| CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} | |
| # ── Node binding: build per-platform .node, then publish to npm ────────── | |
| node-build: | |
| name: Node build (${{ matrix.settings.target }}) | |
| runs-on: ${{ matrix.settings.host }} | |
| env: | |
| MACOSX_DEPLOYMENT_TARGET: '10.13' | |
| if: github.event_name == 'push' || github.event.inputs.node == 'true' | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| settings: | |
| - host: windows-latest | |
| target: x86_64-pc-windows-msvc | |
| binary: aimux.win32-x64-msvc.node | |
| - host: windows-latest | |
| target: aarch64-pc-windows-msvc | |
| binary: aimux.win32-arm64-msvc.node | |
| - host: macos-15-intel | |
| target: x86_64-apple-darwin | |
| binary: aimux.darwin-x64.node | |
| - host: macos-latest | |
| target: aarch64-apple-darwin | |
| binary: aimux.darwin-arm64.node | |
| - host: ubuntu-latest | |
| target: x86_64-unknown-linux-gnu | |
| binary: aimux.linux-x64-gnu.node | |
| - host: ubuntu-latest | |
| target: aarch64-unknown-linux-gnu | |
| binary: aimux.linux-arm64-gnu.node | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| with: | |
| targets: ${{ matrix.settings.target }} | |
| - uses: Swatinem/rust-cache@v2 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 24 | |
| - name: Install dependencies | |
| working-directory: bindings/node | |
| run: npm ci | |
| - name: Build Linux (glibc 2.17 baseline) | |
| if: contains(matrix.settings.target, 'unknown-linux-gnu') | |
| working-directory: bindings/node | |
| shell: bash | |
| env: | |
| TARGET_CC: clang | |
| TARGET_CXX: clang++ | |
| run: npx napi build --platform --release --target ${{ matrix.settings.target }} --use-napi-cross | |
| - name: Build | |
| if: ${{ !contains(matrix.settings.target, 'unknown-linux-gnu') }} | |
| working-directory: bindings/node | |
| shell: bash | |
| run: npx napi build --platform --release --target ${{ matrix.settings.target }} | |
| - name: Verify artifact | |
| working-directory: bindings/node | |
| shell: bash | |
| run: test -f '${{ matrix.settings.binary }}' | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: node-${{ matrix.settings.target }} | |
| path: bindings/node/*.node | |
| node-publish: | |
| name: Publish Node to npm | |
| needs: node-build | |
| runs-on: ubuntu-latest | |
| environment: release | |
| if: github.event_name == 'push' || github.event.inputs.node == 'true' | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 24 | |
| registry-url: https://registry.npmjs.org | |
| - name: Install dependencies | |
| working-directory: bindings/node | |
| run: npm ci | |
| - name: Build napi index.js + d.ts (regenerate from current lib.rs) | |
| # index.js / index.d.ts are napi build artifacts; the committed | |
| # copies may be stale (e.g. initLogging added in RFC-0014 but not | |
| # re-exported in the committed index.js). Rebuild on the host to | |
| # regenerate them before tsc + prepublish. | |
| working-directory: bindings/node | |
| run: npm run build | |
| - name: Create platform packages | |
| working-directory: bindings/node | |
| run: npx napi create-npm-dirs | |
| - name: Download platform binaries | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: bindings/node/artifacts | |
| pattern: node-* | |
| - name: Collect and verify platform packages | |
| working-directory: bindings/node | |
| shell: bash | |
| run: | | |
| npx napi artifacts --output-dir artifacts --npm-dir npm | |
| expected=( | |
| npm/win32-x64-msvc/aimux.win32-x64-msvc.node | |
| npm/win32-arm64-msvc/aimux.win32-arm64-msvc.node | |
| npm/darwin-x64/aimux.darwin-x64.node | |
| npm/darwin-arm64/aimux.darwin-arm64.node | |
| npm/linux-x64-gnu/aimux.linux-x64-gnu.node | |
| npm/linux-arm64-gnu/aimux.linux-arm64-gnu.node | |
| ) | |
| for binary in "${expected[@]}"; do | |
| test -f "$binary" || { echo "Missing $binary" >&2; exit 1; } | |
| done | |
| test "$(find npm -type f -name 'aimux.*.node' | wc -l | tr -d ' ')" = 6 | |
| - name: Publish | |
| working-directory: bindings/node | |
| run: npm publish --provenance --access public | |
| env: | |
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | |
| NPM_CONFIG_PROVENANCE: "true" | |
| NPM_CONFIG_ACCESS: public | |
| # ── Python binding: build + publish platform wheels (OIDC trusted) ─────── | |
| python-release: | |
| name: Publish Python (${{ matrix.os }}) | |
| runs-on: ${{ matrix.os }} | |
| if: github.event_name == 'push' || github.event.inputs.python == 'true' | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest, macos-latest, windows-latest] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| - uses: Swatinem/rust-cache@v2 | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.11" | |
| - name: Build and publish wheel | |
| uses: PyO3/maturin-action@v1 | |
| with: | |
| command: publish | |
| args: --no-sdist | |
| working-directory: bindings/python | |
| # ── Go binding: build libaimux_ffi.a per platform, ship on GitHub Release | |
| # (users download the archive for their platform via `go generate`). | |
| # NOTE: Windows uses the gnu target — Go's cgo links with mingw gcc, | |
| # which cannot consume MSVC-format .a archives. ───────────────────────── | |
| go-build: | |
| name: Go binding (${{ matrix.settings.target }}) | |
| runs-on: ${{ matrix.settings.host }} | |
| if: github.event_name == 'push' || github.event.inputs.artifacts == 'true' | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| settings: | |
| - host: ubuntu-latest | |
| target: x86_64-unknown-linux-gnu | |
| - host: macos-15-intel | |
| target: x86_64-apple-darwin | |
| - host: macos-latest | |
| target: aarch64-apple-darwin | |
| - host: windows-latest | |
| target: x86_64-pc-windows-gnu | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| with: | |
| targets: ${{ matrix.settings.target }} | |
| - uses: Swatinem/rust-cache@v2 | |
| # macos-13 runners do not preinstall Go (ubuntu/windows do) — pin it | |
| # explicitly so every host has the same toolchain. | |
| - uses: actions/setup-go@v5 | |
| with: | |
| go-version: "1.24.x" | |
| - name: Build static archive | |
| run: cargo build -p aimux-ffi --release --target ${{ matrix.settings.target }} | |
| - name: Test Go binding | |
| working-directory: bindings/go | |
| shell: bash | |
| run: | | |
| export CGO_LDFLAGS="-L${{ github.workspace }}/target/${{ matrix.settings.target }}/release" | |
| go vet ./... | |
| go test ./... | |
| - name: Stage archive with platform name | |
| shell: bash | |
| run: | | |
| mkdir -p staging | |
| cp target/${{ matrix.settings.target }}/release/libaimux_ffi.a staging/libaimux_ffi-${{ matrix.settings.target }}.a | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: libaimux_ffi-${{ matrix.settings.target }}.a | |
| path: staging/libaimux_ffi-${{ matrix.settings.target }}.a | |
| console-build-test: | |
| name: CONSOLE-TEST (${{ matrix.settings.target }}) | |
| runs-on: ${{ matrix.settings.host }} | |
| if: github.event_name == 'push' || github.event.inputs.artifacts == 'true' | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - host: ubuntu-latest | |
| target: x86_64-unknown-linux-gnu | |
| suffix: linux-x64 | |
| - host: macos-latest | |
| target: aarch64-apple-darwin | |
| suffix: macos-arm64 | |
| - host: windows-latest | |
| target: x86_64-pc-windows-msvc | |
| suffix: windows-x64.exe | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| with: | |
| targets: ${{ matrix.settings.target }} | |
| - uses: Swatinem/rust-cache@v2 | |
| # macos-13 runners do not preinstall Go (ubuntu/windows do) — pin it | |
| # explicitly so every host has the same toolchain. | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 22 | |
| - name: Build frontend | |
| working-directory: tools/aimux-web/web | |
| run: | | |
| npm ci | |
| npm run build | |
| - name: Build console (embedded frontend) | |
| run: cargo build --release --target ${{ matrix.settings.target }} -p aimux-web --features embed-frontend | |
| - name: Build CLI tools | |
| run: cargo build --release --target ${{ matrix.settings.target }} -p aimux-cli -p aimux-replay | |
| - name: Test Go binding | |
| working-directory: bindings/go | |
| shell: bash | |
| run: | | |
| export CGO_LDFLAGS="-L${{ github.workspace }}/target/${{ matrix.settings.target }}/release" | |
| go vet ./... | |
| go test ./... | |
| - name: Stage binaries with platform suffix | |
| shell: bash | |
| run: | | |
| mkdir -p staging | |
| EXT=""; [ "$RUNNER_OS" = "Windows" ] && EXT=".exe" | |
| cp "target/${{ matrix.settings.target }}/release/aimux-web$EXT" "staging/aimux-web-${{ matrix.settings.suffix }}" | |
| for tool in aimux-cli aimux-replay; do | |
| if [ -f "target/${{ matrix.settings.target }}/release/$tool$EXT" ]; then | |
| cp "target/${{ matrix.settings.target }}/release/$tool$EXT" "staging/$tool-${{ matrix.settings.suffix }}" | |
| fi | |
| done | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: aimux-web-test-${{ matrix.settings.target }} | |
| path: staging/* | |
| # ── C ABI shared libraries (C/C++ + reference for other bindings) ──────── | |
| ffi-build: | |
| name: aimux-ffi (${{ matrix.target }}) | |
| runs-on: ${{ matrix.host }} | |
| if: github.event_name == 'push' || github.event.inputs.artifacts == 'true' | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - host: ubuntu-latest | |
| target: x86_64-unknown-linux-gnu | |
| artifact: libaimux_ffi-linux-x64.so | |
| - host: macos-latest | |
| target: aarch64-apple-darwin | |
| artifact: libaimux_ffi-macos-arm64.dylib | |
| - host: windows-latest | |
| target: x86_64-pc-windows-msvc | |
| artifact: aimux_ffi-windows-x64.dll | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| with: | |
| targets: ${{ matrix.target }} | |
| - uses: Swatinem/rust-cache@v2 | |
| - name: Build cdylib | |
| run: cargo build -p aimux-ffi --release --target ${{ matrix.target }} | |
| - name: Stage library with platform name | |
| shell: bash | |
| run: | | |
| mkdir -p staging | |
| case "${{ matrix.target }}" in | |
| *linux*) cp target/${{ matrix.target }}/release/libaimux_ffi.so staging/${{ matrix.artifact }} ;; | |
| *darwin*) cp target/${{ matrix.target }}/release/libaimux_ffi.dylib staging/${{ matrix.artifact }} ;; | |
| *windows*) cp target/${{ matrix.target }}/release/aimux_ffi.dll staging/${{ matrix.artifact }} ;; | |
| esac | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ matrix.artifact }} | |
| path: staging/${{ matrix.artifact }} | |
| # ── aimux-web console + CLI: self-contained binaries with the embedded | |
| # frontend, shipped on the GitHub Release so users download one file and | |
| # run it (no cargo / npm step). The CLI tools ride along on the same | |
| # matrix — they share the heavy provider dependency tree. ─────────────── | |
| console-build: | |
| name: aimux-web (${{ matrix.settings.target }}) | |
| runs-on: ${{ matrix.settings.host }} | |
| if: github.event_name == 'push' || github.event.inputs.artifacts == 'true' | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - host: ubuntu-latest | |
| target: x86_64-unknown-linux-gnu | |
| suffix: -linux-x64 | |
| - host: macos-latest | |
| target: aarch64-apple-darwin | |
| suffix: -macos-arm64 | |
| - host: windows-latest | |
| target: x86_64-pc-windows-msvc | |
| suffix: -windows-x64.exe | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| with: | |
| targets: ${{ matrix.settings.target }} | |
| - uses: Swatinem/rust-cache@v2 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 22 | |
| - name: Build frontend | |
| working-directory: tools/aimux-web/web | |
| run: | | |
| npm ci | |
| npm run build | |
| - name: Build console (embedded frontend) | |
| run: cargo build --release --target ${{ matrix.settings.target }} -p aimux-web --features embed-frontend | |
| - name: Build CLI tools | |
| run: cargo build --release --target ${{ matrix.settings.target }} -p aimux-cli -p aimux-replay | |
| - name: Stage binaries with platform suffix | |
| shell: bash | |
| run: | | |
| mkdir -p staging | |
| EXT=""; [ "$RUNNER_OS" = "Windows" ] && EXT=".exe" | |
| cp "target/${{ matrix.settings.target }}/release/aimux-web$EXT" "staging/aimux-web${{ matrix.settings.suffix }}" | |
| for tool in aimux-cli aimux-replay; do | |
| if [ -f "target/${{ matrix.settings.target }}/release/$tool$EXT" ]; then | |
| cp "target/${{ matrix.settings.target }}/release/$tool$EXT" "staging/$tool${{ matrix.settings.suffix }}" | |
| fi | |
| done | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: aimux-web-${{ matrix.settings.target }} | |
| path: staging/* | |
| # ── Flutter mobile artifacts: Android .so per ABI + iOS .xcframework ────── | |
| # Built at release time and embedded into the Flutter plugin package by the | |
| # flutter-publish job, so the pub.dev artifact ships with its native core. | |
| flutter-ffi-mobile: | |
| name: Flutter mobile FFI (${{ matrix.platform }}) | |
| runs-on: ${{ matrix.host }} | |
| # Built for both the GitHub Release (manual integration) and the | |
| # pub.dev plugin package (flutter input). | |
| if: github.event_name == 'push' || github.event.inputs.artifacts == 'true' || github.event.inputs.flutter == 'true' | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - platform: android | |
| host: ubuntu-latest | |
| targets: aarch64-linux-android armv7-linux-androideabi x86_64-linux-android | |
| - platform: ios | |
| host: macos-latest | |
| targets: aarch64-apple-ios aarch64-apple-ios-sim | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| with: | |
| targets: ${{ matrix.targets }} | |
| - uses: Swatinem/rust-cache@v2 | |
| - name: Build Android .so (cargo-ndk) | |
| if: matrix.platform == 'android' | |
| run: | | |
| cargo install cargo-ndk | |
| rustup target add aarch64-linux-android armv7-linux-androideabi x86_64-linux-android | |
| cargo ndk -t arm64-v8a -t armeabi-v7a -t x86_64 -o staging/android \ | |
| build -p aimux-ffi --release | |
| for abi in arm64-v8a armeabi-v7a x86_64; do | |
| test -f "staging/android/$abi/libaimux_ffi.so" || { echo "Missing $abi" >&2; exit 1; } | |
| done | |
| - name: Build iOS xcframework | |
| if: matrix.platform == 'ios' | |
| run: | | |
| mkdir -p staging | |
| bash scripts/build-ios-xcframework.sh staging/aimux_ffi.xcframework | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: flutter-${{ matrix.platform }} | |
| path: staging/ | |
| # ── JVM bindings: publish aimux-java + aimux-kotlin to Maven Central ────── | |
| jvm-publish: | |
| name: Publish Java+Kotlin to Maven Central | |
| runs-on: ubuntu-latest | |
| environment: release | |
| if: github.event_name == 'push' || github.event.inputs.jvm == 'true' | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-java@v4 | |
| with: | |
| distribution: temurin | |
| java-version: "17" | |
| - uses: gradle/actions/setup-gradle@v4 | |
| - name: Publish aimux-java | |
| working-directory: bindings/java | |
| run: gradle publish | |
| env: | |
| ORG_GRADLE_PROJECT_ossrhUsername: ${{ secrets.OSSRH_USERNAME }} | |
| ORG_GRADLE_PROJECT_ossrhPassword: ${{ secrets.OSSRH_PASSWORD }} | |
| ORG_GRADLE_PROJECT_signingKey: ${{ secrets.SIGNING_KEY }} | |
| ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.SIGNING_PASSWORD }} | |
| - name: Publish aimux-kotlin | |
| working-directory: bindings/kotlin | |
| run: gradle publish | |
| env: | |
| ORG_GRADLE_PROJECT_ossrhUsername: ${{ secrets.OSSRH_USERNAME }} | |
| ORG_GRADLE_PROJECT_ossrhPassword: ${{ secrets.OSSRH_PASSWORD }} | |
| ORG_GRADLE_PROJECT_signingKey: ${{ secrets.SIGNING_KEY }} | |
| ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.SIGNING_PASSWORD }} | |
| - name: Submit deployments to Central Portal | |
| # The OSSRH Staging API compatibility service only stages uploads; | |
| # this POST (same IP, same runner) moves them into the Portal for | |
| # the ai.arcships namespace. | |
| env: | |
| OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }} | |
| OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }} | |
| run: | | |
| curl -sS -u "$OSSRH_USERNAME:$OSSRH_PASSWORD" \ | |
| -X POST "https://ossrh-staging-api.central.sonatype.com/manual/upload/defaultRepository/ai.arcships" \ | |
| -w '\nHTTP %{http_code}\n' | |
| # 201/202 = accepted; the deployment then appears in the Portal | |
| # (central.sonatype.com/publishing) for release. | |
| # ── Flutter plugin: embed mobile FFI libs, test, publish to pub.dev ─────── | |
| # Publisher: arcships.ai (pub.dev). The native core (Android .so per ABI + | |
| # iOS xcframework) is built by flutter-ffi-mobile and embedded into the | |
| # package so consumers get a working plugin from `flutter pub add aimux`. | |
| flutter-publish: | |
| name: Publish Flutter to pub.dev | |
| needs: flutter-ffi-mobile | |
| runs-on: ubuntu-latest | |
| environment: release | |
| if: github.event_name == 'push' || github.event.inputs.flutter == 'true' | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| - uses: Swatinem/rust-cache@v2 | |
| - uses: subosito/flutter-action@v2 | |
| with: | |
| channel: stable | |
| - name: Download mobile FFI artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: mobile-artifacts | |
| pattern: flutter-* | |
| merge-multiple: true | |
| - name: Embed Android .so per ABI | |
| run: | | |
| for abi in arm64-v8a armeabi-v7a x86_64; do | |
| test -f "mobile-artifacts/android/$abi/libaimux_ffi.so" || { echo "Missing $abi" >&2; exit 1; } | |
| cp "mobile-artifacts/android/$abi/libaimux_ffi.so" \ | |
| "bindings/flutter/android/src/main/jniLibs/$abi/libaimux_ffi.so" | |
| done | |
| - name: Embed iOS xcframework | |
| run: | | |
| # flutter-ffi-mobile (ios) uploads staging/ contents, so the | |
| # artifact lands at the root (no ios/ prefix). | |
| test -f mobile-artifacts/aimux_ffi.xcframework/Info.plist | |
| cp -r mobile-artifacts/aimux_ffi.xcframework bindings/flutter/ios/ | |
| - name: Build host FFI library (for tests) | |
| run: cargo build -p aimux-ffi --release | |
| - name: Test | |
| working-directory: bindings/flutter | |
| env: | |
| LD_LIBRARY_PATH: ${{ github.workspace }}/target/release | |
| run: flutter test | |
| - name: Analyze | |
| working-directory: bindings/flutter | |
| run: flutter analyze | |
| - name: Publish to pub.dev | |
| working-directory: bindings/flutter | |
| env: | |
| # OAuth credentials from `dart pub login` (pub-credentials.json), | |
| # stored as a single JSON secret. | |
| PUB_DEV_TOKEN: ${{ secrets.PUB_DEV_TOKEN }} | |
| run: | | |
| mkdir -p "$HOME/.config/dart" | |
| printf '%s' "$PUB_DEV_TOKEN" > "$HOME/.config/dart/pub-credentials.json" | |
| flutter pub publish --force | |
| # ── GitHub Release: aggregate all binary artifacts (C ABI libs + Go .a) ── | |
| github-release: | |
| name: Create GitHub Release | |
| needs: [go-build, ffi-build, console-build, flutter-ffi-mobile] | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'push' || github.event.inputs.artifacts == 'true' | |
| steps: | |
| - uses: actions/checkout@v4 | |
| # workflow_dispatch runs have no tag ref; resolve it from Cargo.toml so | |
| # softprops/action-gh-release can target the right tag either way. | |
| - name: Resolve version | |
| id: version | |
| run: | | |
| VERSION=$(grep -m1 '^version = ' Cargo.toml | sed 's/version = "\(.*\)"/\1/') | |
| echo "tag=v${VERSION}" >> "$GITHUB_OUTPUT" | |
| - name: Download all artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: release-assets | |
| merge-multiple: true | |
| - name: List assets | |
| run: ls -la release-assets/ | |
| - name: Create release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ steps.version.outputs.tag }} | |
| files: release-assets/** | |
| generate_release_notes: true |