Skip to content

ci: unified CI and release workflows with reusable build pipelines#723

Open
cdecker wants to merge 3 commits into
mainfrom
2026w21-ci-release-workflows
Open

ci: unified CI and release workflows with reusable build pipelines#723
cdecker wants to merge 3 commits into
mainfrom
2026w21-ci-release-workflows

Conversation

@cdecker
Copy link
Copy Markdown
Collaborator

@cdecker cdecker commented May 21, 2026

Summary

Replaces the per-language standalone CI workflows and the per-crate tag-triggered release workflow with a unified architecture built on reusable build workflows.

Architecture

graph TD
    subgraph "Reusable Build Workflows"
        BR[build-rust.yml]
        BK[build-kotlin.yml]
        BN[build-napi.yml]
        BP[build-python.yml]
        BS[build-swift.yml]
    end

    subgraph "Orchestrators"
        CI[ci.yml]
        REL[release.yml]
    end

    CI --> BR
    CI --> BK
    CI --> BN
    CI --> BP

    REL --> BS
    REL --> BK
    REL --> BN
    REL --> BP
Loading

Changes

Deleted (replaced by ci.yml):

  • kotlin.yml, python.yml, typescript.yml, rust-unit.yml, check-formatting.yml

New reusable build workflows (workflow_call only):

  • build-rust.yml — workspace build + test
  • build-swift.yml — iOS XCFramework + Swift sources
  • build-kotlin.yml — Android NDK + KMP bindings
  • build-napi.yml — Node.js native bindings (5 targets)
  • build-python.yml — Python wheels (6 targets + sdist)

New ci.yml — CI orchestrator for PRs/pushes. Calls the build workflows and runs N-API integration tests + Python install smoke test + formatting check.

Replaced release.yml — Release orchestrator (manual dispatch):

  • Validates version numbers match Cargo.toml + changelog entries exist
  • Publishes Rust crates in topological order (gl-client -> gl-sdk -> gl-sdk-cli) with crates.io index polling between steps
  • Builds all bindings in parallel via reusable workflows
  • Publishes to npm, PyPI, Swift SPM, creates GitHub Releases + tags
  • Uses trusted publishing (OIDC) for crates.io — no API token needed
  • Dry-run mode: runs cargo publish --dry-run, npm publish --dry-run, builds all bindings, but skips real publishing/tagging

Other:

  • Added license and repository to gl-sdk-cli/Cargo.toml (required for crates.io)

Testing

After merge, run the Release Orchestrator with dry_run=true to validate everything end-to-end without publishing.

cdecker and others added 2 commits May 21, 2026 18:29
Replace the per-language standalone CI workflows (kotlin.yml, python.yml,
typescript.yml, rust-unit.yml, check-formatting.yml) with a single ci.yml
orchestrator that delegates to reusable build-*.yml workflows.

Replace the per-crate tag-triggered release.yml with a unified Release
Orchestrator that:
- Validates version numbers and changelogs
- Publishes Rust crates in topological order (gl-client -> gl-sdk ->
  gl-sdk-cli) with crates.io index polling between steps
- Builds all bindings in parallel (Swift, Kotlin, N-API, Python)
- Publishes to npm, PyPI, Swift SPM, and creates GitHub Releases
- Uses trusted publishing (OIDC) for crates.io -- no API token needed
- Supports dry-run mode with cargo publish --dry-run and npm --dry-run

New reusable build workflows:
- build-rust.yml: workspace build + test
- build-swift.yml: iOS XCFramework + Swift sources
- build-kotlin.yml: Android NDK + KMP bindings
- build-napi.yml: Node.js native bindings (5 targets)
- build-python.yml: Python wheels (6 targets + sdist)

Also adds license and repository metadata to gl-sdk-cli Cargo.toml
(required for crates.io publishing).
Iterate on the CI orchestrator and reusable build workflows to reliably
test against prebuilt artifacts without rebuilding from source.

Key changes:

Workflow infrastructure:
- Add build-test-binaries.yml for gl-plugin and gl-signerproxy artifacts
- Install cfssl from prebuilt release binaries instead of Go toolchain
- Modernize all third-party actions to 2026 versions (v6/v7/v8)
- Add protoc repo-token to avoid GitHub API rate limiting
- Fix macOS builds: native hosts (macos-13/macos-14) for architecture match
- Fix Windows: set Python architecture for x86 builds
- Fix Linux: chown maturin Docker output to restore user permissions
- Per-architecture rust-cache namespaces to avoid target collisions

Python wheel testing (python-test job):
- Install gl-testing with --no-deps to avoid uv workspace source
  resolution rebuilding gl-client from source via maturin
- Install remaining deps explicitly, excluding workspace packages
- Use uv run --no-sync to prevent workspace re-resolution
- Use uv venv --clear (clnvm creates a .venv first)
- Add bitcoind, cfssl, lightningd (clnvm) for integration test fixtures
- Set CARGO_TARGET_DIR so gl-testing finds downloaded test binaries

N-API testing (napi-test job):
- Use absolute workspace paths for pip install (working-directory offset)
- Install gl-sdk wheel alongside gl-client
- Spawn gltestserver with uv run --no-sync (not uv run --package)
- Download prebuilt test binaries instead of compiling Rust locally
- Set CARGO_TARGET_DIR for gl-testing binary discovery

gl-sdk wheel packaging:
- Force-include glsdk/glsdk.py in hatchling build hook (gitignored by
  default, so the UniFFI Python bindings were missing from the wheel)
- Retag wheel from py3-none-any to correct platform tag since it
  contains native libglsdk.so/.dylib/.dll

Also includes cargo fmt and Cargo.toml dependency consolidation from
the parent branch.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@cdecker cdecker force-pushed the 2026w21-ci-release-workflows branch from b0b2e4a to 573370c Compare May 21, 2026 22:21
The nobody_id and root_id test fixtures set GL_NOBODY_CRT,
GL_NOBODY_KEY, and GL_CA_CRT env vars but never cleaned them up on
teardown. When later tests called Credentials.load(b""), the Rust
Device::default() found the stale env vars pointing to deleted temp
files, load_file_or_default failed, and .expect() panicked. With
panic=abort in the release profile, UniFFI's catch_unwind couldn't
intercept it, killing the process with SIGABRT (exit 134).

Three fixes:
- Remove panic=abort from [profile.release] so UniFFI can catch panics
- Fall back to compiled-in defaults when env var file reads fail
- Clean up cert env vars in fixture teardown

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant