Skip to content

Add a build-and-test workflow - #470

Merged
Ryanmello07 merged 2 commits into
mainfrom
ci/build-and-test
Aug 22, 2026
Merged

Add a build-and-test workflow#470
Ryanmello07 merged 2 commits into
mainfrom
ci/build-and-test

Conversation

@Ryanmello07

@Ryanmello07 Ryanmello07 commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

This repo has no .github directory today, so nothing is built or tested on push. This adds a first CI: build and test only, no release, no signing, no secrets.

Verified green on a real runner, first attemptrun 32550013491. Details at the bottom.

What it runs

Two jobs on ubuntu-latest, because they fail for completely different reasons.

sdk-aar — the Go half. Builds URnetworkSdk.aar with gomobile. This is not optional scaffolding: the app has no source of its own for the SDK. app/app/build.gradle's only dependency on it is

implementation fileTree(dir: "${bringyourHomeDir}/sdk/build/android", include: ['*.aar', '*.jar'])

nothing is published to download, and over a hundred files import com.bringyour.sdk — including the main sources the unit tests compile against. Without the .aar that fileTree resolves empty and nothing in the app compiles at all.

The job checks out urnetwork/sdk beside connect, glog and goidenticons (the replace ../ directives in sdk/go.mod and sdk/build/go.mod require exactly those directory names), carries the same conditional RenderPngV2 shim as urnetwork/windows, installs the pinned NDK, and runs make init_tools build_android.

gradle — the Kotlin half. Downloads that .aar and runs, from app/:

./gradlew --no-daemon \
  :app:testGithubDebugUnitTest \
  :app:assembleGithubDebug \
  :app:compileGithubReleaseKotlin \
  :app:compilePlayReleaseKotlin \
  :app:compileSolana_dappReleaseKotlin \
  :app:compileEthos_dappReleaseKotlin

testGithubDebugUnitTest is the real suite — 19 test classes under app/app/src/test/java/com/bringyour/network on junit 4.13.2, 177 tests, which ran green. It is worth saying that the release pipeline never runs these: build/all/run.sh only does clean assemblePlayRelease bundlePlayRelease assembleSolana_dappRelease assembleEthos_dappRelease. This closes a real gap, not a formality.

assembleGithubDebug proves the app still packages. The other three flavors get compile*ReleaseKotlin rather than an assemble (see below) — which is not a token check either, since each flavor adds its own java srcDir (src/ungoogle, src/google, src/solana_dapp, src/ethos_dapp) and this is the only thing that compiles those sources at all.

Triggers: push and pull_request on main, plus workflow_dispatch. permissions: contents: read. Concurrency group per ref with cancel-in-progress, and timeout-minutes on both jobs.

What it deliberately does not do

  • No release, no signing. Every release signingConfig resolves ${WARP_HOME}/release/android/signing/app.jks, which is not in this repo and is a genuine secret. So no assemble*Release / bundle*Release. compile*ReleaseKotlin never schedules a packaging or validateSigning task, which is why the release variants can still be compile-checked without one. build.sh already uses that same idiom for the flavor it cannot assemble locally.
  • No instrumented tests. app/app/src/androidTest, driven by test-main.sh, needs an emulator and a live account fixture from vault/main/test-acceptance.yml.
  • No localizations sync. build.sh regenerates res/values*/strings.xml from the sibling store first. The generated files are committed, so CI does not need the store — but it therefore will not catch key drift the way the release pipeline does.

The workflow references no secrets.* at all. The only signing input is the standard ~/.android/debug.keystore, generated in-job from the published android/androiddebugkey constants (validateSigningGithubDebug ran and passed).

Verified run

Run 32550013491, both jobs success on the first attempt.

sdk-aar 3m 24s — the gomobile bind itself was 2m 28s
gradle 7m 02s — BUILD SUCCESSFUL in 6m 33s, 131 actionable tasks, 131 executed
total wall clock ~10.5 min
  • .aar is real: 39,425,248 bytes, with all three JNI slices present — jni/arm64-v8a/libgojni.so, jni/armeabi-v7a/libgojni.so, jni/x86_64/libgojni.so — plus a 547 KB sources jar.
  • Unit tests: 177 tests, 0 failures, 0 ignored, 1.383s. The HTML report is uploaded as the unit-test-report artifact on every run, pass or fail.
  • All four flavors' kapt*ReleaseKotlin + compile*ReleaseKotlin executed, so Hilt annotation processing is covered per flavor.
  • stripGithubDebugDebugSymbols and packageGithubDebug executed, so the NDK and packaging paths are genuinely exercised.

This came in far under the hour I had budgeted, mostly because the pinned NDK 29.0.14206865 is already on the runner image (the install step took 9 seconds) and the bind is faster than expected. Job timeouts are set to 45 and 40 minutes — roughly 6x headroom, bounding a stalled fetch to minutes rather than GitHub's 6h default, the same reasoning urnetwork/linux's build.yml documents.

For a maintainer to decide

  1. Pin the sibling refs, or track their default branches? Shipped as tracking main/master, matching sdk's and windows' workflows. That means an unrelated push to sdk, connect, glog or goidenticons can turn every open PR here red at once. server's workflow has the same tradeoff written up in a comment; if it proves noisy, pin ref: per sibling and bump deliberately.
  2. Trigger scope. push is limited to main per the sdk/connect convention, so pushes to topic branches only get CI once a PR is open. server's workflow deliberately triggers on every branch instead — that is the precedent to copy if you want branch coverage.
  3. assembleGithubDebug — keep? It is the only proof the app packages, and splits { abi } with universalApk true means it emits three APKs. At 7 minutes for the whole gradle job it is comfortably affordable, so I kept it; it is the first thing to drop if that ever changes.

Two toolchain notes that will look odd in review

  • Go is pinned via go-version-file: sdk/build/go.mod (1.26.5), not go-version: stable like sdk/connect/linux use. stable is 1.27 now, and sdk/build/Makefile says so in the build_android recipe itself: "gomobile/gobind must be built with go <= 1.26 — the go 1.27 runtime fatals when this GODEBUG is set", GODEBUG=gotypesalias=0 being exactly what that recipe exports. GOTOOLCHAIN: local is set so a stray go directive cannot silently self-upgrade past the pin.
  • make init_tools, not make init. init ends with go clean -cache && go clean -modcache, which would discard everything setup-go had just restored, and it go gets x/mobile/bind — already a pinned indirect require in build/go.mod at the same GOMOBILE_VERSION. init_tools is the split the Makefile documents and the one build/all/android/setup.sh and :app:buildSdkAcceptance rely on.

Also: app/local.properties is written before any gradle invocation. versionName/versionCode are read from it at configuration time, and without it the build shells out to warp/warpctl/build/<os>/<arch>/warpctl — which does not exist on a runner — and dies before any task starts, with an IOException that names nothing about the cause. The file is git-ignored and the two values only name the archive.

Claude and others added 2 commits August 21, 2026 20:48
This repo had no CI at all. Every push and pull request against main now
builds the app and runs its JVM unit tests.

Two jobs, because they fail for different reasons.

sdk-aar builds URnetworkSdk.aar with gomobile. It is not optional: the app
has no source of its own for the SDK -- app/app/build.gradle's only
dependency on it is a fileTree over ${bringyourHomeDir}/sdk/build/android,
nothing is published to download, and over a hundred files import
com.bringyour.sdk -- so without the .aar nothing compiles, including the
main sources the unit tests pull in. It checks out sdk beside connect, glog
and goidenticons (the `replace ../` directives in sdk/go.mod and
sdk/build/go.mod require exactly those directory names), carries the same
conditional goidenticons RenderPngV2 shim as urnetwork/windows, installs the
pinned NDK, and runs `make init_tools build_android` -- init_tools rather
than init because init ends in `go clean -cache && go clean -modcache`,
which would discard everything setup-go had just restored. Go is pinned via
go-version-file: sdk/build/go.mod (1.26.5) rather than the house-usual
`stable`: stable is 1.27, and sdk/build/Makefile states that gomobile must be
built with go <= 1.26 or the runtime fatals on the GODEBUG its own recipe
exports.

gradle consumes that .aar and runs :app:testGithubDebugUnitTest -- 19 test
classes under app/app/src/test that the release pipeline never executes --
plus :app:assembleGithubDebug to prove the app still packages, plus
compile*ReleaseKotlin for all four flavors, which is the only thing that
compiles each flavor's own java srcDir. It writes app/local.properties
first, because versionName/versionCode are read from it at CONFIGURATION
time and otherwise the build shells out to a warpctl that does not exist on
a runner and dies before any task starts.

Build and test only. No release: assemble*Release resolves a keystore under
${WARP_HOME}/release that is not in this repo, and the instrumented suite
needs an emulator and a live account fixture from the vault. Neither is
attempted and no secret is referenced.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MAXFxG1EK4jTxQ1iW73BUr
The first run finished in 3m24s (sdk-aar) and 7m02s (gradle), so 90/60 was
far looser than needed. 45/40 keeps roughly a 6x margin while bounding a
stalled fetch to minutes instead of GitHub's 6h default -- the same reasoning
urnetwork/linux's build.yml documents on its jobs.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MAXFxG1EK4jTxQ1iW73BUr
@Ryanmello07
Ryanmello07 marked this pull request as ready for review August 22, 2026 05:16
@Ryanmello07
Ryanmello07 merged commit a2a911d into main Aug 22, 2026
2 checks passed
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