77# - Linux: Uses Ubuntu runner with cross-compilation
88# - macOS: Uses macOS runner with cross-compilation
99# - Windows: Uses Ubuntu runner with Docker cross-compilation (same as desktop build)
10+
1011on :
11- workflow_call :
12- inputs :
13- version :
14- required : false
15- default : " "
16- type : string
17- ref :
18- type : string
19- required : false
20- default : " "
12+ push :
13+ branches :
14+ - build-termux-xcap
15+ # on:
16+ # workflow_call:
17+ # inputs:
18+ # version:
19+ # required: false
20+ # default: ""
21+ # type: string
22+ # ref:
23+ # type: string
24+ # required: false
25+ # default: ""
2126
2227name : " Reusable workflow to build CLI"
2328
2429jobs :
2530 build-cli :
2631 name : Build CLI
2732 runs-on : ${{ matrix.build-on }}
33+ container : ${{ matrix.is-termux && format('termux/termux-docker:{0}', matrix.architecture) || '' }}
34+ volumes : ${{ matrix.is-termux && fromJSON('["/tmp/node20:/__e/node20"]') || '[]' }}
2835 strategy :
2936 fail-fast : false
3037 matrix :
3138 include :
3239 # Linux builds
33- - os : ubuntu-latest
34- architecture : x86_64
35- target-suffix : unknown-linux-gnu
36- build-on : ubuntu-latest
37- use-cross : true
38- - os : ubuntu-latest
39- architecture : aarch64
40- target-suffix : unknown-linux-gnu
41- build-on : ubuntu-latest
42- use-cross : true
43- # macOS builds
44- - os : macos-latest
45- architecture : x86_64
46- target-suffix : apple-darwin
47- build-on : macos-latest
48- use-cross : true
49- - os : macos-latest
40+ # - os: ubuntu-latest
41+ # architecture: x86_64
42+ # target-suffix: unknown-linux-gnu
43+ # build-on: ubuntu-latest
44+ # use-cross: true
45+ # - os: ubuntu-latest
46+ # architecture: aarch64
47+ # target-suffix: unknown-linux-gnu
48+ # build-on: ubuntu-latest
49+ # use-cross: true
50+ # # macOS builds
51+ # - os: macos-latest
52+ # architecture: x86_64
53+ # target-suffix: apple-darwin
54+ # build-on: macos-latest
55+ # use-cross: true
56+ # - os: macos-latest
57+ # architecture: aarch64
58+ # target-suffix: apple-darwin
59+ # build-on: macos-latest
60+ # use-cross: true
61+ # # Windows builds (only x86_64 supported)
62+ # - os: windows
63+ # architecture: x86_64
64+ # target-suffix: pc-windows-gnu
65+ # build-on: ubuntu-latest
66+ # use-cross: false
67+ # use-docker: true
68+ # Termux build (only aarch64 supported)
69+ - os : termux
5070 architecture : aarch64
51- target-suffix : apple-darwin
52- build-on : macos-latest
53- use-cross : true
54- # Windows builds (only x86_64 supported)
55- - os : windows
56- architecture : x86_64
57- target-suffix : pc-windows-gnu
58- build-on : ubuntu-latest
59- use-cross : false
60- use-docker : true
71+ target-suffix : aarch64-linux-android
72+ build-on : ubuntu-24.04-arm
73+ is-termux : true
6174
6275 steps :
6376 - name : Checkout code
6679 ref : ${{ inputs.ref }}
6780 fetch-depth : 0
6881
82+ - name : Set Termux Environment Variables
83+ if : matrix.is-termux
84+ run : |
85+ echo "TERMUX_MAIN_PACKAGE_FORMAT=debian" >> $GITHUB_ENV
86+ echo "ANDROID_ROOT=/system" >> $GITHUB_ENV
87+ echo "ANDROID_DATA=/data" >> $GITHUB_ENV
88+ echo "PREFIX=/data/data/com.termux/files/usr" >> $GITHUB_ENV
89+ echo "HOME=/data/data/com.termux/files/home" >> $GITHUB_ENV
90+ echo "PATH=/data/data/com.termux/files/usr/bin" >> $GITHUB_ENV
91+ echo "TMPDIR=/data/data/com.termux/files/usr/tmp" >> $GITHUB_ENV
92+ echo "LANG=en_US.UTF-8" >> $GITHUB_ENV
93+ echo "TZ=UTC" >> $GITHUB_ENV
94+
95+ - name : Termux - set pkg command to use the packages-cf.termux.dev mirror
96+ if : matrix.is-termux
97+ run : ln -sf ${PREFIX}/etc/termux/mirrors/default ${PREFIX}/etc/termux/chosen_mirrors
98+
99+ - name : Termux: upgrade all packages to prepare for installing nodejs
100+ if : matrix.is-termux
101+ run : /entrypoint.sh bash -c "yes | pkg upgrade -y"
102+
103+ - name : Termux: fix executable bit for all binaries in $PREFIX/bin for all users
104+ if : matrix.is-termux
105+ run : chmod -R o+x ${PREFIX}/bin
106+
107+ - name : Termux: install bionic-libc nodejs to force compatibility with actions/checkout and actions/upload-artifact
108+ if : matrix.is-termux
109+ run : |
110+ /entrypoint.sh pkg install -y nodejs-lts
111+ ln -sf ${PREFIX}/bin /__e/node20/bin
112+
113+ - name : Termux: fix permissions of repository after actions/checkout, which ran as root user, while entrypoint.sh activates system user (1000)
114+ if : matrix.is-termux
115+ run : chown -R 1000:1000 .
116+
117+ - name : Termux: setup rust and protobuf
118+ if : matrix.is-termux
119+ run : |
120+ /entrypoint.sh pkg install -y rust
121+ /entrypoint.sh pkg install -y protobuf
122+ /entrypoint.sh pkg install -y tar gzip zip
123+
69124 - name : Update version in Cargo.toml
70125 if : ${{ inputs.version != '' }}
71126 run : |
@@ -145,7 +200,7 @@ jobs:
145200 set -e
146201 echo '=== Setting up Rust environment with caching ==='
147202 export CARGO_HOME=/usr/local/cargo
148- export PATH=/usr/local/cargo/bin:\ $PATH
203+ export PATH=/usr/local/cargo/bin:$PATH
149204
150205 # Check if Windows target is already installed in cache
151206 if rustup target list --installed | grep -q x86_64-pc-windows-gnu; then
@@ -173,7 +228,7 @@ jobs:
173228 echo 'jobs = 4' >> .cargo/config.toml
174229 echo '' >> .cargo/config.toml
175230 echo '[target.x86_64-pc-windows-gnu]' >> .cargo/config.toml
176- echo 'linker = \ "x86_64-w64-mingw32-gcc\ "' >> .cargo/config.toml
231+ echo 'linker = "x86_64-w64-mingw32-gcc"' >> .cargo/config.toml
177232 echo '' >> .cargo/config.toml
178233 echo '[net]' >> .cargo/config.toml
179234 echo 'git-fetch-with-cli = true' >> .cargo/config.toml
@@ -182,16 +237,16 @@ jobs:
182237 echo '[profile.release]' >> .cargo/config.toml
183238 echo 'codegen-units = 1' >> .cargo/config.toml
184239 echo 'lto = false' >> .cargo/config.toml
185- echo 'panic = \ "abort\ "' >> .cargo/config.toml
240+ echo 'panic = "abort"' >> .cargo/config.toml
186241 echo 'debug = false' >> .cargo/config.toml
187242 echo 'opt-level = 2' >> .cargo/config.toml
188243 echo '' >> .cargo/config.toml
189244 echo '[registries.crates-io]' >> .cargo/config.toml
190- echo 'protocol = \ "sparse\ "' >> .cargo/config.toml
245+ echo 'protocol = "sparse"' >> .cargo/config.toml
191246
192247 echo '=== Building with cached dependencies ==='
193248 # Check if we have cached build artifacts
194- if [ -d target/x86_64-pc-windows-gnu/release/deps ] && [ \"\ $(ls -A target/x86_64-pc-windows-gnu/release/deps)\ " ]; then
249+ if [ -d target/x86_64-pc-windows-gnu/release/deps ] && [ " $(ls -A target/x86_64-pc-windows-gnu/release/deps)" ]; then
195250 echo '✅ Found cached build artifacts, performing incremental build...'
196251 CARGO_INCREMENTAL=1
197252 else
@@ -200,16 +255,16 @@ jobs:
200255 fi
201256
202257 echo '🔨 Building Windows CLI executable...'
203- CARGO_INCREMENTAL=\ $CARGO_INCREMENTAL \
258+ CARGO_INCREMENTAL=$CARGO_INCREMENTAL \
204259 CARGO_NET_RETRY=3 \
205260 CARGO_HTTP_TIMEOUT=60 \
206261 RUST_BACKTRACE=1 \
207262 cargo build --release --target x86_64-pc-windows-gnu -p goose-cli --jobs 4
208263
209264 echo '=== Copying Windows runtime DLLs ==='
210- GCC_DIR=\ $(ls -d /usr/lib/gcc/x86_64-w64-mingw32/*/ | head -n 1)
211- cp \"\ $GCC_DIR/libstdc++-6.dll\ " target/x86_64-pc-windows-gnu/release/
212- cp \"\ $GCC_DIR/libgcc_s_seh-1.dll\ " target/x86_64-pc-windows-gnu/release/
265+ GCC_DIR=$(ls -d /usr/lib/gcc/x86_64-w64-mingw32/*/ | head -n 1)
266+ cp " $GCC_DIR/libstdc++-6.dll" target/x86_64-pc-windows-gnu/release/
267+ cp " $GCC_DIR/libgcc_s_seh-1.dll" target/x86_64-pc-windows-gnu/release/
213268 cp /usr/x86_64-w64-mingw32/lib/libwinpthread-1.dll target/x86_64-pc-windows-gnu/release/
214269
215270 echo '✅ Build completed successfully!'
@@ -229,6 +284,26 @@ jobs:
229284 echo "✅ Windows runtime DLLs:"
230285 ls -la ./target/x86_64-pc-windows-gnu/release/*.dll
231286
287+ - name : Build CLI (Termux)
288+ if : matrix.is-termux
289+ run : |
290+ #/entrypoint.sh cargo build --release
291+ #
292+ export TARGET=.
293+
294+ # Create a directory for the package contents
295+ mkdir -p "target/${TARGET}/release/goose-package"
296+ touch "target/${TARGET}/release/goose"
297+
298+ # Copy binaries
299+ cp "target/${TARGET}/release/goose" "target/${TARGET}/release/goose-package/"
300+ cp "target/${TARGET}/release/goosed" "target/${TARGET}/release/goose-package/"
301+
302+ # Create the tar archive with all binaries
303+ cd "target/${TARGET}/release"
304+ tar -cjf "goose-${{ matrix.architecture }}-termux.tar.bz2" -C goose-package .
305+ echo "ARTIFACT=target/${TARGET}/release/goose-${{ matrix.architecture }}-termux.tar.bz2" >> $GITHUB_ENV
306+
232307 - name : Build temporal-service for target platform using build.sh script (Linux/macOS)
233308 if : matrix.use-cross
234309 run : |
@@ -402,8 +477,15 @@ jobs:
402477 zip -r "goose-${TARGET}.zip" goose-package/
403478 echo "ARTIFACT=target/${TARGET}/release/goose-${TARGET}.zip" >> $GITHUB_ENV
404479
480+ - name : Package CLI (Termux)
481+ if : matrix.is-termux
482+ run : |
483+ cd target/release
484+ zip -r goose-${{ inputs.version }}-${{ matrix.architecture }}-termux.zip goose goosed mcp-server generate_schema
485+ echo "ARTIFACT=target/release/goose-${{ inputs.version }}-${{ matrix.architecture }}-termux.zip" >> $GITHUB_ENV
486+
405487 - name : Upload CLI artifact
406488 uses : actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # pin@v4
407489 with :
408- name : goose-${{ matrix.architecture }}-${{ matrix.target-suffix }}
490+ name : ${{ matrix.is-termux && format(' goose-{0}-{1}-termux', inputs.version, matrix.architecture) || format('goose-{0}-{1}', matrix.architecture, matrix. target-suffix) }}
409491 path : ${{ env.ARTIFACT }}
0 commit comments