-
Notifications
You must be signed in to change notification settings - Fork 0
186 lines (169 loc) · 7.74 KB
/
Copy pathbuild-linux.yml
File metadata and controls
186 lines (169 loc) · 7.74 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
name: Build (Linux)
# Manual trigger for Linux desktop builds (.AppImage + .deb).
# Linux-specific config is in src-tauri/tauri.linux.conf.json (auto-loaded by
# Tauri): bundle.targets = [deb, appimage] + the linux externalBin/resources.
#
# Always uploads the bundles as downloadable workflow artifacts so you can test
# a build without touching a release.
#
# `ref` is what to BUILD from (default main, so the build includes the latest
# fixes). `release_tag` is which published Release to ATTACH the bundles to —
# these are decoupled on purpose: a release tag (e.g. v1.13.4) may predate a
# build fix that only landed on main, so we build from main but upload to the
# tag. The bundle version comes from tauri.conf.json, so keep that in sync with
# the release_tag (the upload step warns on a mismatch).
on:
workflow_dispatch:
inputs:
ref:
description: 'Branch or tag to BUILD from (default: main)'
required: false
default: 'main'
release_tag:
description: 'Release tag to ATTACH bundles to, e.g. v1.13.4 (blank = artifacts only)'
required: false
default: ''
jobs:
build-linux:
runs-on: ubuntu-22.04
permissions:
contents: write
steps:
- name: Validate inputs
if: ${{ inputs.release_tag != '' }}
run: |
tag="${{ github.event.inputs.release_tag }}"
if [[ ! "$tag" =~ ^v[0-9]+\.[0-9]+ ]]; then
echo "release_tag must be a version tag (e.g. v1.13.4), got: '$tag'" && exit 1
fi
- name: Checkout
uses: actions/checkout@v5
with:
ref: ${{ github.event.inputs.ref }}
# Tauri v2 Linux build dependencies (webkit2gtk 4.1) + patchelf for the
# AppImage. Built on 22.04 (not latest) for the widest glibc compatibility
# of the resulting AppImage.
- name: Install Linux build dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
libwebkit2gtk-4.1-dev \
build-essential curl wget file \
libxdo-dev libssl-dev \
libayatana-appindicator3-dev \
librsvg2-dev patchelf libfuse2
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Setup Node
uses: actions/setup-node@v5
with:
node-version: 22
cache: pnpm
- name: Install Rust (stable, x86_64-unknown-linux-gnu)
uses: dtolnay/rust-toolchain@stable
with:
targets: x86_64-unknown-linux-gnu
# Required by src-tauri/build.rs, which bun-compiles the sidecar + MCP
# relay for the linux target during `cargo build`.
- name: Install Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build workspace core package
run: pnpm --filter @graphnosis-app/core build
- name: Build signed demo .gsk packs
env:
GSK_SIGNING_KEY_HEX: ${{ secrets.GSK_SIGNING_KEY_HEX }}
run: |
if [ -z "$GSK_SIGNING_KEY_HEX" ]; then
echo "ERROR: GSK_SIGNING_KEY_HEX secret is not set." && exit 1
fi
node scripts/build-gsk.mjs --sign
- name: Build sidecar
run: pnpm --filter @graphnosis-app/desktop-sidecar build
# linuxdeploy runs `ldd` on every ELF in the AppDir's usr/bin to bundle its
# shared libs, and treats an ldd failure as fatal ("Failed to run ldd:
# exited with code 1"). Our externalBin sidecars (graphnosis-sidecar,
# graphnosis-mcp-relay) are Bun --compile self-contained binaries: ldd
# can't trace them (it execs them in trace mode; they exit 1). They link
# only standard glibc, so they need NO dependency bundling. This shim makes
# ldd report "no deps" (exit 0) for binaries the real ldd can't trace,
# while passing normal binaries (the main app → GTK/WebKit) straight
# through. Prepended to PATH via GITHUB_PATH so linuxdeploy picks it up.
- name: Install ldd shim for self-contained sidecars
run: |
mkdir -p "$HOME/.local/bin-shim"
cat > "$HOME/.local/bin-shim/ldd" <<'SH'
#!/usr/bin/env bash
out=$(/usr/bin/ldd "$@" 2>&1); rc=$?
if [ $rc -ne 0 ]; then exit 0; fi
printf '%s\n' "$out"
SH
chmod +x "$HOME/.local/bin-shim/ldd"
echo "$HOME/.local/bin-shim" >> "$GITHUB_PATH"
# Tauri builds the .deb first (reliable), then the AppImage (linuxdeploy is
# flaky on FUSE-less CI). continue-on-error lets the job proceed with the
# .deb already on disk if the AppImage step dies; the Collect step below is
# the real gate (it fails if no .deb exists). --verbose surfaces
# linuxdeploy's stderr, which Tauri otherwise swallows behind "failed to
# run linuxdeploy".
- name: Build (Linux deb + AppImage)
continue-on-error: true
env:
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
APPIMAGE_EXTRACT_AND_RUN: 1
NO_STRIP: "true"
run: pnpm --filter @graphnosis-app/desktop tauri:build
# .deb is REQUIRED (its absence means the build genuinely failed). AppImage
# is OPTIONAL — uploaded if linuxdeploy succeeded, skipped with a warning
# otherwise, so a flaky AppImage never blocks shipping the .deb.
- name: Collect bundles under canonical names
id: find
run: |
SEMVER=$(node -p "require('./apps/desktop/src-tauri/tauri.conf.json').version")
BUNDLE="apps/desktop/src-tauri/target/release/bundle"
DEB=$(find "$BUNDLE" -name "*.deb" | head -1)
APPIMAGE=$(find "$BUNDLE" -name "*.AppImage" | head -1)
if [ -z "$DEB" ]; then
echo "ERROR: .deb not found under $BUNDLE — the build genuinely failed."
find "$BUNDLE" -maxdepth 2 -type f || true
exit 1
fi
# Canonical, predictable names so the /download/linux* routes resolve
# deterministically (Tauri lowercases the .deb package name otherwise).
mkdir -p dist-linux
cp "$DEB" "dist-linux/Graphnosis_${SEMVER}_amd64.deb"
echo "semver=$SEMVER" >> $GITHUB_OUTPUT
echo "deb=dist-linux/Graphnosis_${SEMVER}_amd64.deb" >> $GITHUB_OUTPUT
if [ -n "$APPIMAGE" ]; then
cp "$APPIMAGE" "dist-linux/Graphnosis_${SEMVER}_amd64.AppImage"
echo "appimage=dist-linux/Graphnosis_${SEMVER}_amd64.AppImage" >> $GITHUB_OUTPUT
echo "AppImage built ✓"
else
echo "appimage=" >> $GITHUB_OUTPUT
echo "::warning::AppImage NOT built (linuxdeploy failed) — uploading .deb only."
fi
- name: Upload bundle artifacts
uses: actions/upload-artifact@v4
with:
name: graphnosis-linux-bundles
path: dist-linux/*
retention-days: 14
- name: Attach bundles to GitHub release
if: ${{ inputs.release_tag != '' }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
TAG="${{ github.event.inputs.release_tag }}"
SEMVER="${{ steps.find.outputs.semver }}"
if [ "$TAG" != "v$SEMVER" ]; then
echo "WARNING: release_tag ($TAG) != built version (v$SEMVER)."
echo "Assets are named Graphnosis_${SEMVER}_amd64.* — the /download/linux route builds its URL from CURRENT_VERSION, so these must match the release the env var points at."
fi
FILES=( "${{ steps.find.outputs.deb }}#Graphnosis $TAG (Linux .deb)" )
if [ -n "${{ steps.find.outputs.appimage }}" ]; then
FILES+=( "${{ steps.find.outputs.appimage }}#Graphnosis $TAG (Linux AppImage)" )
fi
gh release upload "$TAG" "${FILES[@]}" --clobber