Repository navigation
Expand file tree
/
Copy patharstack-studio-linux-appimage.yml
More file actions
192 lines (180 loc) · 8.17 KB
/
Copy patharstack-studio-linux-appimage.yml
File metadata and controls
192 lines (180 loc) · 8.17 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
name: ARStack Studio Linux AppImage
on:
pull_request:
paths:
- 'apps/arstack_studio/**'
- '.github/workflows/arstack-studio-linux-appimage.yml'
- 'scripts/install-linux.sh'
workflow_dispatch:
inputs:
release_tag:
description: 'Existing GitHub release tag to build, test and attach Linux AppImage; blank = build artifact only'
required: false
type: string
permissions:
contents: read
jobs:
appimage:
name: Build and test Linux x86_64 package
runs-on: ubuntu-22.04
timeout-minutes: 55
permissions:
contents: read
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event_name == 'workflow_dispatch' && inputs.release_tag != '' && inputs.release_tag || github.sha }}
fetch-depth: 0
- name: Confirm release identity before packaging
if: ${{ inputs.release_tag != '' }}
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ inputs.release_tag }}
run: |
set -euo pipefail
test "$(git rev-parse HEAD)" = "$(git rev-parse "$TAG^{commit}")"
git fetch --no-tags origin main
git merge-base --is-ancestor "$TAG^{commit}" origin/main || {
echo "Release source is not integrated into main; refusing Linux package" >&2
exit 1
}
gh release view "$TAG" --json isDraft,isPrerelease -q 'select(.isDraft==false and .isPrerelease==false)' > release-check.json
test -s release-check.json
- name: Install Linux native dependencies
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends cmake ninja-build build-essential \
libgl1-mesa-dev libxkbcommon-x11-0 libxcb-cursor0 libxcb-xinerama0 \
libxcb-xkb1 libxcb-randr0 libxcb-image0 libxcb-keysyms1 libxcb-render-util0 \
libfuse2 unzip xvfb libdbus-1-3
- name: Install Qt 6
uses: jurplel/install-qt-action@v4
with:
version: '6.10.3'
arch: linux_gcc_64
modules: 'qtserialport'
cache: true
- name: Compile native Linux Studio and smoke test
run: |
set -euo pipefail
cmake -S apps/arstack_studio -B build-studio-linux -G Ninja \
-DCMAKE_BUILD_TYPE=Release -DARIEC61850_WARNINGS_AS_ERRORS=ON
cmake --build build-studio-linux --target arstack_studio --parallel 2
test -x build-studio-linux/arstack_studio
QT_QPA_PLATFORM=offscreen xvfb-run -a build-studio-linux/arstack_studio --check-reference-template
QT_QPA_PLATFORM=offscreen xvfb-run -a build-studio-linux/arstack_studio --check-p0-policy
- name: Stage Linux app and matched optional release firmware
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ inputs.release_tag }}
run: |
set -euo pipefail
mkdir -p AppDir/usr/bin AppDir/usr/share/icons/hicolor/512x512/apps
cp build-studio-linux/arstack_studio AppDir/usr/bin/ARStackStudio
cp assets/studio_icon/android-chrome-512x512.png AppDir/usr/share/icons/hicolor/512x512/apps/arstack-studio.png
cat > arstack-studio.desktop <<'DESKTOP'
[Desktop Entry]
Type=Application
Name=ARStack Studio
Exec=ARStackStudio
Icon=arstack-studio
Categories=Education;Science;Electronics;
Terminal=false
DESKTOP
cp LICENSE NOTICE COPYRIGHT.md THIRD_PARTY_NOTICES.md AppDir/usr/bin/
if [ -n "$TAG" ]; then
mkdir -p release-firmware AppDir/usr/bin/firmware AppDir/usr/bin/tools
gh release download "$TAG" --dir release-firmware --pattern 'firmware-manifest.json' --pattern '*.bin'
python3 - <<'PY'
import hashlib,json,pathlib,shutil
root=pathlib.Path('release-firmware')
manifest=json.loads((root/'firmware-manifest.json').read_text())
binfiles=list(root.glob('*.bin'))
assert len(binfiles)==1 and manifest['chip']=='esp32p4', 'Release firmware ambiguity'
src=binfiles[0]
assert hashlib.sha256(src.read_bytes()).hexdigest()==manifest['sha256'], 'Firmware hash mismatch'
output=pathlib.Path('AppDir/usr/bin/firmware')
shutil.copy2(src,output/manifest['image'])
shutil.copy2(root/'firmware-manifest.json',output/'firmware-manifest.json')
(output/'SHA256SUMS.txt').write_text(f"{manifest['sha256']} {manifest['image']}\n")
PY
curl -fLsS https://github.com/esp-rs/espflash/releases/download/v4.5.0/espflash-x86_64-unknown-linux-gnu.zip -o espflash.zip
echo 'dcd7fd822f247df18966935bbb10c7cb4b700c87172349633e9e323ee2542717 espflash.zip' | sha256sum -c -
unzip -j espflash.zip 'espflash' -d AppDir/usr/bin/tools
chmod +x AppDir/usr/bin/tools/espflash
fi
- name: Bundle Qt and create single-file AppImage
uses: miurahr/install-linuxdeploy-action@v1.8.0
id: linuxdeploy
with:
plugins: qt appimage
- name: Generate AppImage and release checksum
env:
QML_SOURCES_PATHS: ${{ github.workspace }}/apps/arstack_studio/qml
VERSION: ${{ inputs.release_tag || 'preview' }}
run: |
set -euo pipefail
export QMAKE="$(command -v qmake6 || command -v qmake)"
${{ steps.linuxdeploy.outputs.linuxdeploy }} \
--appdir AppDir \
--executable AppDir/usr/bin/ARStackStudio \
--desktop-file arstack-studio.desktop \
--icon-file AppDir/usr/share/icons/hicolor/512x512/apps/arstack-studio.png \
--plugin qt --output appimage
shopt -s nullglob
images=( ./*.AppImage )
test "${#images[@]}" -eq 1
mv "${images[0]}" ARStack-Studio-linux-x86_64.AppImage
chmod +x ARStack-Studio-linux-x86_64.AppImage
APPIMAGE_EXTRACT_AND_RUN=1 QT_QPA_PLATFORM=offscreen \
xvfb-run -a ./ARStack-Studio-linux-x86_64.AppImage --check-reference-template
APPIMAGE_EXTRACT_AND_RUN=1 QT_QPA_PLATFORM=offscreen \
xvfb-run -a ./ARStack-Studio-linux-x86_64.AppImage --check-p0-policy
if [ -n "${{ inputs.release_tag }}" ]; then
APPIMAGE_EXTRACT_AND_RUN=1 QT_QPA_PLATFORM=offscreen \
xvfb-run -a ./ARStack-Studio-linux-x86_64.AppImage --check-firmware-contract
fi
sha256sum ARStack-Studio-linux-x86_64.AppImage > ARStack-Studio-linux-x86_64.sha256
- name: Upload reviewed Linux artifacts
uses: actions/upload-artifact@v4
with:
name: arstack-studio-linux-x86_64
path: |
ARStack-Studio-linux-x86_64.AppImage
ARStack-Studio-linux-x86_64.sha256
if-no-files-found: error
retention-days: 14
attach-verified-release:
name: Attach tested Linux package to exact release tag
needs: appimage
if: ${{ github.event_name == 'workflow_dispatch' && inputs.release_tag != '' }}
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
ref: ${{ inputs.release_tag }}
fetch-depth: 0
- name: Download Linux build that passed the AppImage checks
uses: actions/download-artifact@v4
with:
name: arstack-studio-linux-x86_64
- name: Verify tag and release before publishing
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ inputs.release_tag }}
run: |
set -euo pipefail
test "$(git rev-parse HEAD)" = "$(git rev-parse "$TAG^{commit}")"
git fetch --no-tags origin main
git merge-base --is-ancestor "$TAG^{commit}" origin/main || {
echo "Release source is not integrated into main; refusing Linux package" >&2
exit 1
}
gh release view "$TAG" --json isDraft,isPrerelease -q 'select(.isDraft==false and .isPrerelease==false)' > release-check.json
test -s release-check.json
sha256sum -c ARStack-Studio-linux-x86_64.sha256
gh release upload "$TAG" \
ARStack-Studio-linux-x86_64.AppImage \
ARStack-Studio-linux-x86_64.sha256