Skip to content

Commit a6c019f

Browse files
eriedclaude
andcommitted
CI: rolling pre-release for multi-wheel-support
Cherry-pick the branch-apk workflow from external-gps so every push to this branch produces a fresh debug APK at the rolling `branch-multi-wheel-support` GitHub release. Add a BRANCH.md describing what's in the build and what testers should poke at, since the workflow pastes that content into the release body. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent b9ec4c0 commit a6c019f

2 files changed

Lines changed: 191 additions & 0 deletions

File tree

.github/workflows/branch-apk.yml

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
name: Branch APK
2+
3+
# On every push to a non-main branch, build a debug APK and replace the
4+
# rolling pre-release tagged `branch-<name>` with the freshly built artifact.
5+
# Testers always get the latest commit by visiting the same release URL.
6+
#
7+
# Pull-request runs build the APK as a workflow artifact (downloadable from
8+
# the Actions tab for ~90 days) but do not touch the release list, so PRs
9+
# from forks can't push tags.
10+
11+
on:
12+
push:
13+
branches-ignore:
14+
- main
15+
tags-ignore:
16+
- "**"
17+
pull_request:
18+
branches:
19+
- "**"
20+
workflow_dispatch:
21+
22+
permissions:
23+
contents: write
24+
25+
jobs:
26+
build:
27+
runs-on: ubuntu-latest
28+
29+
steps:
30+
- name: Checkout
31+
uses: actions/checkout@v4
32+
with:
33+
fetch-depth: 0 # full history so we can produce a "since main" log
34+
35+
- name: Set up JDK 17
36+
uses: actions/setup-java@v4
37+
with:
38+
distribution: temurin
39+
java-version: "17"
40+
41+
- name: Set up Gradle
42+
uses: gradle/actions/setup-gradle@v3
43+
44+
- name: Make gradlew executable
45+
run: chmod +x ./gradlew
46+
47+
- name: Build debug APK
48+
run: ./gradlew :app:assembleDebug --no-daemon --stacktrace
49+
env:
50+
GRADLE_OPTS: -Xmx4g -Dorg.gradle.jvmargs=-Xmx4g
51+
52+
- name: Compute build metadata
53+
id: meta
54+
if: github.event_name != 'pull_request'
55+
run: |
56+
BRANCH="${GITHUB_REF##*/}"
57+
SHORT_SHA="$(git rev-parse --short HEAD)"
58+
TAG="branch-${BRANCH}"
59+
APK_NAME="EUC-Planet-${BRANCH}-${SHORT_SHA}.apk"
60+
61+
# Pull the per-branch description if BRANCH.md exists, otherwise
62+
# fall back to a generic notice. This becomes the release body header.
63+
if [ -f BRANCH.md ]; then
64+
cp BRANCH.md /tmp/branch-notes.md
65+
else
66+
cat > /tmp/branch-notes.md <<EOF
67+
# ${BRANCH}
68+
69+
No \`BRANCH.md\` found at repo root. Add one to describe what this
70+
branch is for and who should test it.
71+
EOF
72+
fi
73+
74+
# Recent commits since branching from main, capped to keep the
75+
# release body readable on big branches.
76+
git log --pretty=format:'- %h %s' main..HEAD | head -50 > /tmp/commit-log.md || true
77+
78+
{
79+
echo "**Pre-release from branch \`${BRANCH}\`** — automatic build at \`${SHORT_SHA}\`."
80+
echo
81+
echo "This is a CI-built debug APK. It can't update an existing Play Store install in place — uninstall the Play version first to install this build."
82+
echo
83+
cat /tmp/branch-notes.md
84+
echo
85+
echo "## Recent commits"
86+
echo
87+
cat /tmp/commit-log.md
88+
} > /tmp/release-body.md
89+
90+
echo "branch=${BRANCH}" >> "$GITHUB_OUTPUT"
91+
echo "short_sha=${SHORT_SHA}" >> "$GITHUB_OUTPUT"
92+
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
93+
echo "apk_name=${APK_NAME}" >> "$GITHUB_OUTPUT"
94+
95+
- name: Rename APK for release
96+
if: github.event_name != 'pull_request'
97+
run: |
98+
cp app/build/outputs/apk/debug/app-debug.apk \
99+
"/tmp/${{ steps.meta.outputs.apk_name }}"
100+
101+
- name: Upload APK as workflow artifact
102+
uses: actions/upload-artifact@v4
103+
with:
104+
name: app-debug-${{ github.run_id }}
105+
path: app/build/outputs/apk/debug/app-debug.apk
106+
retention-days: 90
107+
108+
- name: Strip prior APKs from rolling release
109+
if: github.event_name != 'pull_request'
110+
env:
111+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
112+
run: |
113+
# action-gh-release attaches new files but doesn't remove the previous
114+
# commit's APK; without this step the rolling pre-release accumulates
115+
# one APK per push. Delete every existing .apk on the tag before the
116+
# next step uploads the freshly built one. Tolerate the tag not
117+
# existing yet (first run on a brand-new branch).
118+
tag="${{ steps.meta.outputs.tag }}"
119+
if gh release view "$tag" >/dev/null 2>&1; then
120+
gh release view "$tag" --json assets \
121+
--jq '.assets[] | select(.name | endswith(".apk")) | .name' \
122+
| while read -r asset; do
123+
[ -n "$asset" ] && gh release delete-asset "$tag" "$asset" --yes || true
124+
done
125+
fi
126+
127+
- name: Replace rolling pre-release with new APK
128+
if: github.event_name != 'pull_request'
129+
uses: softprops/action-gh-release@v2
130+
with:
131+
tag_name: ${{ steps.meta.outputs.tag }}
132+
name: ${{ steps.meta.outputs.tag }} (${{ steps.meta.outputs.short_sha }})
133+
body_path: /tmp/release-body.md
134+
prerelease: true
135+
# Replace the existing tag/release on every push so testers can
136+
# always find the latest at the same URL.
137+
make_latest: "false"
138+
files: /tmp/${{ steps.meta.outputs.apk_name }}

BRANCH.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# multi-wheel-support
2+
3+
## What this branch adds
4+
5+
Foundation work for supporting wheels beyond the V14. The protocol layer
6+
splits into per-family adapters and the dashboard learns to surface its
7+
state for any of them. Concretely shipped here:
8+
9+
- **InMotion V2 model registry** covering V11 / V11Y / V12 HS / HT / Pro /
10+
V12S / V13 / V13 Pro / V14 50GB / V14 50S / V9 / P6. The wheel reports
11+
its model ID on connect and the registry maps it to the right command
12+
variant (horn opcode, max-speed packet shape, etc.).
13+
- **Wheel simulator** in the connect screen. Two virtual wheels (V14 and
14+
P6) feed canned BLE responses through the real adapter pipeline, so the
15+
whole UI works without hardware. Useful for translation, layout, and
16+
capability-gating work.
17+
- **Experimental banner** on the dashboard for any wheel that isn't a
18+
verified V14. Tapping it opens a prefilled GitHub Issue (`Wheel report`
19+
template) with the connected wheel and firmware already filled in.
20+
- **Wheel report template** at `.github/ISSUE_TEMPLATE/wheel_report.yml`
21+
with structured fields for wheel model, firmware, status, what works,
22+
details, and phone OS.
23+
24+
## Who should test this
25+
26+
- **V14 owners**: confirm that nothing changed for you. The banner stays
27+
hidden, the dashboard reads the same values, horn / light / lock /
28+
safety mode still work.
29+
- **Owners of any other InMotion wheel** (V11, V12, V13, V9, P6): try
30+
connecting. Telemetry decoding outside the V14 family is unverified,
31+
so expect wrong values. If anything works or fails, tap the orange
32+
banner to fire off a wheel report.
33+
- **No-wheel testers**: in the connect screen, scroll past the BLE list to
34+
the "Simulate a wheel" section. Tap V14 or P6 to drive the dashboard
35+
with synthetic telemetry.
36+
37+
## Known limits
38+
39+
- **P6 telemetry on real hardware is not parsed yet.** The simulator
40+
pretends the P6 speaks V14-shape framing so the dashboard renders, but
41+
on a real P6 the wheel uses a different binary layout and most fields
42+
will read zero. Fix is pending a labeled BLE capture from a real P6
43+
owner, see `docs/BLE_CAPTURE_GUIDE.md`.
44+
- **KingSong, Veteran, Begode/Gotway, InMotion V1 family (V8 / V10)**:
45+
their adapters aren't built yet, so connecting won't work. They appear
46+
in the wheel-report dropdown for users to manually pick if they want
47+
to file feedback.
48+
49+
## Feedback
50+
51+
Tap the orange banner on the dashboard for a prefilled GitHub issue, or
52+
open one manually at
53+
https://github.com/eried/eucplanet/issues/new?template=wheel_report.yml

0 commit comments

Comments
 (0)