Repository navigation
217 lines (188 loc) · 9.31 KB
/
Copy pathrelease.yml
File metadata and controls
217 lines (188 loc) · 9.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
# Release pipeline: pushing a `v*` tag builds the SIGNED Android APK and
# publishes a GitHub Release with it attached.
#
# Linux ships .rpm and .deb, built in the distro containers they target.
#
# One universal Linux binary is not possible here and a bundle format does not
# rescue it: the app links webkit2gtk and gtk3, whose sonames move between
# distro releases, and the mirror pipeline loads GStreamer plugins from the
# system at runtime. So this is a matrix, one package per target distro, and
# the version each was built against is what it declares a dependency on.
#
# Not AppImage or Flatpak, deliberately. The app talks to BlueZ's Profile1,
# eavesdrops on the session bus for notifications, shells adb, pactl, nmcli and
# gsettings, and pushes a helper binary to the phone — a sandbox is the wrong
# shape for it, and an AppImage carrying webkit is both large and fragile.
#
# Required repo secrets (Settings → Secrets and variables → Actions):
# KEYSTORE_B64 — base64 of vortex-release.jks
# (`base64 -w0 ~/secure/vortex-release.jks`)
# KEYSTORE_PASSWORD — storePassword
# KEY_ALIAS — key alias (vortex)
# KEY_PASSWORD — keyPassword
name: Release
on:
push:
tags: ["v*"]
permissions:
contents: write
jobs:
linux-packages:
name: Linux package (${{ matrix.name }})
runs-on: ubuntu-latest
container: ${{ matrix.image }}
strategy:
fail-fast: false
matrix:
include:
- name: fedora-44
image: fedora:44
bundle: rpm
ext: rpm
- name: debian-13
image: debian:13
bundle: deb
ext: deb
steps:
# `git` first: actions/checkout falls back to a REST download without it,
# which loses the working tree layout the build expects.
- name: Bootstrap the container
run: |
if command -v dnf >/dev/null; then dnf -y install git which; \
else apt-get update && apt-get -y install git ca-certificates; fi
- uses: actions/checkout@v4
# The same script install_linux.sh uses, so CI and a user's machine
# install the same set. It detects the package manager itself and skips
# sudo when already root, which is the case in a container.
- name: Build and runtime dependencies
run: ./linux/packaging/install-deps.sh
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
with:
workspaces: linux/ui-tauri/src-tauri
- name: Frontend dependencies
working-directory: linux/ui-tauri
run: npm install --legacy-peer-deps
- name: Bundle
working-directory: linux/ui-tauri
run: npm run tauri build -- --bundles ${{ matrix.bundle }}
# Name the artifact after the distro it was built against: the whole
# point of the matrix is that these are NOT interchangeable.
- name: Name it after its target
run: |
src=$(find linux/ui-tauri/src-tauri/target/release/bundle \
-name "*.${{ matrix.ext }}" | head -1)
test -n "$src" || { echo "no ${{ matrix.ext }} produced"; exit 1; }
cp "$src" "vortex-${GITHUB_REF_NAME}-${{ matrix.name }}.${{ matrix.ext }}"
- uses: actions/upload-artifact@v4
with:
name: linux-${{ matrix.name }}
path: vortex-*.${{ matrix.ext }}
android-apk:
name: Signed APK + GitHub Release
runs-on: ubuntu-latest
needs: linux-packages
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: "21"
- uses: gradle/actions/setup-gradle@v4
- name: Materialize keystore from secrets
working-directory: android
env:
KEYSTORE_B64: ${{ secrets.KEYSTORE_B64 }}
KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
run: |
echo "$KEYSTORE_B64" | base64 -d > vortex-release.jks
cat > keystore.properties <<EOF
storeFile=$GITHUB_WORKSPACE/android/vortex-release.jks
storePassword=$KEYSTORE_PASSWORD
keyAlias=$KEY_ALIAS
keyPassword=$KEY_PASSWORD
EOF
- name: Tests
working-directory: android
run: ./gradlew test --no-daemon
- name: Build signed release APK
working-directory: android
run: ./gradlew assembleRelease --no-daemon
- name: Rename APK to versioned name
run: |
cp android/app/build/outputs/apk/release/app-release.apk \
"vortex-${GITHUB_REF_NAME}.apk"
- name: Shred keystore materialization
if: always()
working-directory: android
run: rm -f vortex-release.jks keystore.properties
# generate_release_notes is off on purpose: the public repo receives one
# squashed snapshot commit per publish, so GitHub's auto notes would list
# a single "release: snapshot …" line and nothing a tester could use.
# UPDATE THE `What's new` BLOCK when bumping the version — it is the only
# place the Releases page describes the release. (The changelog is
# private, so the workflow cannot read it from here.)
- name: Collect the Linux packages
uses: actions/download-artifact@v4
with:
pattern: linux-*
merge-multiple: true
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
files: |
vortex-*.apk
vortex-*.rpm
vortex-*.deb
generate_release_notes: false
body: |
## What's new in 1.0.0-beta.7
**The desktop now ships as a package.** `.rpm` for Fedora 44 and `.deb` for
Debian 13 are attached below — no clone, no Rust toolchain, no twenty-minute
compile. They are built in the distro they name and are not interchangeable:
the app links webkit2gtk and gtk3, whose versions move between releases. On
anything else, `install_linux.sh` still builds from source as before.
**A release of fixes, not features.** The project went through a full audit and
83 findings were closed. The ones you are most likely to have felt:
- **Earbuds handoff was failing about half the time.** Both devices allowed a
Bluetooth profile disconnect one second to complete; real earbuds routinely
need two or three, so a disconnect that was still in progress was reported as
a failure and the other device then tried to connect earbuds the first had not
released. Switches now go through on the first attempt.
- **The call pill sat on "Calling…" for the whole call** instead of becoming a
live timer.
- **Universal Control** is close to rewritten: it arms on KDE, it survives the
adb connection being re-established (it used to die with it, and the cursor
silently stopped crossing), wireless adb configures itself and closes its port
again when the feature is switched off. New: with a text field focused on the
phone, **Esc** dismisses the field instead of returning the cursor — two quick
presses always return, so the escape hatch cannot be taken away.
- **Do Not Disturb is shared.** Silence one device and the other goes quiet too.
- Phone-as-second-monitor works outside GNOME; notification action buttons work
on non-GNOME shells; mirrored notifications no longer fold into one row;
received files land in your real XDG download folder.
**If something breaks, the desktop app now writes
`~/.local/state/vortex/vortex.log`.** It used to launch with stderr discarded,
so a normal run left nothing to look at. That file plus `adb logcat` is what
makes a report actionable.
**The binary we push to your phone is verifiable.** Universal Control works by
pushing a 20 KB helper to `/data/local/tmp` and running it as the shell user.
It is committed in built form because the app embeds it at compile time, so
`android/inject/build.sh` rebuilds it — with NDK r26b, byte-for-byte identical:
```bash
OUT=/tmp/vi android/inject/build.sh
cmp /tmp/vi linux/ui-tauri/src-tauri/assets/vortex_inject && echo identical
```
### Honest warning
Universal Control has been run on exactly **one** pair so far — GNOME 50 with a
Redmi 9/9C. The fallback for phones that will not let adb open `/dev/uinput` has,
by definition, never run on one. If it misbehaves on yours, that is the point of
this beta: please open an issue with your distro, desktop and phone model.
---
**Android:** download `vortex-${{ github.ref_name }}.apk` and install it on the phone
(or use `android/install.sh` over adb — it auto-grants the Accessibility/Notification permissions).
It upgrades over beta.2 in place — same app, no re-pairing.
**Linux:** clone the repo and run `./install_linux.sh` — it installs deps, builds, and installs in one go.
Update both sides together.