-
Notifications
You must be signed in to change notification settings - Fork 208
397 lines (350 loc) · 18.2 KB
/
update_apps.yml
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
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
name: Update_Apps
# Controls when the workflow will run
on:
# run at 00:00 and 12:00 UTC every Day
schedule:
- cron: "0 0,12 * * *"
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
# this workflow contains 3 jobs that run sequentially: get-latest-app-versions, test-updated-apps, and create-pr
# get-latest-app-versions gets the latests app versions and modifies the working directory of the repository with those changes. then it uploads that working directory of the git repository as an artifact for use in later jobs
# test-updated-apps runs a matrix of testcases where all updated apps from the first job are tested for successful installation/uninstallation in the working directory of the git repoistory downloaded from the artifact
# create-pr then uses the output from get-latest-app-versions and test-updated-apps to finalize a PR where only apps that passed all testcases are updated and any that fail have a descriptive error written in the PR comment
jobs:
get-latest-app-versions:
name: Get Latest App Versions
# The type of runner that the job will run on
runs-on: ubuntu-latest
outputs:
UPDATED_APPS: ${{ steps.updated.outputs.UPDATED_APPS }}
FAILED_APPS: ${{ steps.failed.outputs.FAILED_APPS }}
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v3
# Runs a set of commands using the runners shell
- name: Run app update scripts
env:
GH_PERSONAL_ACCESS_TOKEN: ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }}
run: |
# print user info
echo $USER $USERNAME $(id) $(whoami)
#source pi-apps functions
#export all functions and variables
set -a
#make DIRECTORY equal to GITHUB_WORKSPACE, for subscripts and api functions
DIRECTORY=$GITHUB_WORKSPACE
source $GITHUB_WORKSPACE/api
#add special functions
get_release() {
curl -s --header "Authorization: token $GH_PERSONAL_ACCESS_TOKEN" "https://api.github.com/repos/$1/releases/latest" | jq -r '.tag_name' | sed s/^v//g
}
get_release_raw() {
curl -s --header "Authorization: token $GH_PERSONAL_ACCESS_TOKEN" "https://api.github.com/repos/$1/releases/latest" | jq -r '.tag_name'
}
get_prerelease() {
curl -s --header "Authorization: token $GH_PERSONAL_ACCESS_TOKEN" "https://api.github.com/repos/$1/releases" | jq -r 'map(select(.prerelease)) | first | .tag_name' | sed s/^v//g
}
get_prerelease_raw() {
curl -s --header "Authorization: token $GH_PERSONAL_ACCESS_TOKEN" "https://api.github.com/repos/$1/releases" | jq -r 'map(select(.prerelease)) | first | .tag_name'
}
function validate_url(){
if command wget --timeout=5 -q --spider "$1"; then
return 0
else
return 1
fi
}
#stop exporting functions
set +a
#make sure all update scripts are executable
chmod +x $GITHUB_WORKSPACE/.github/workflows/updates/*.sh
cd $GITHUB_WORKSPACE
apps=( .github/workflows/updates/*.sh )
for app_directory in "${apps[@]}"; do
echo
#make sure we are still in the main workspace (incase an update script left off elsewhere)
cd $GITHUB_WORKSPACE
export app_name="$(echo ${app_directory%.*} | sed 's:.*/::')"
echo "$app_name"
status "Checking $app_name for updates"
# move to app folder
cd "$GITHUB_WORKSPACE/apps/$app_name"
# run app update script
"$GITHUB_WORKSPACE/$app_directory"
done
cd
- name: Output updated apps
id: updated
run: |
if test -f /tmp/updated_apps; then
sort -u /tmp/updated_apps > /tmp/updated_apps_sorted
echo "UPDATED_APPS<<EOF" >> $GITHUB_OUTPUT
cat /tmp/updated_apps_sorted >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
fi
- name: Output failed apps
id: failed
run: |
if test -f /tmp/failed_apps; then
echo "FAILED_APPS<<EOF" >> $GITHUB_OUTPUT
cat /tmp/failed_apps | sed '0~1 a\\' >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
fi
- name: Tar GITHUB_WORKSPACE
run: |
cd ${{ runner.temp }}
tar -C $GITHUB_WORKSPACE -cvf GITHUB_WORKSPACE.tar .
- name: Upload GITHUB_WORKSPACE Artifact
uses: actions/upload-artifact@v3
with:
name: GITHUB_WORKSPACE
path: ${{ runner.temp }}/GITHUB_WORKSPACE.tar
test-updated-apps:
runs-on: ubuntu-latest
needs: get-latest-app-versions
strategy:
matrix:
include:
- os: bullseye
arch: armhf
image: https://downloads.raspberrypi.org/raspios_oldstable_armhf/images/raspios_oldstable_armhf-2023-12-06/2023-12-05-raspios-bullseye-armhf.img.xz
cache: yes
- os: bullseye
arch: arm64
image: https://downloads.raspberrypi.org/raspios_oldstable_arm64/images/raspios_oldstable_arm64-2023-12-06/2023-12-05-raspios-bullseye-arm64.img.xz
cache: yes
- os: bookworm
arch: armhf
image: https://downloads.raspberrypi.com/raspios_armhf/images/raspios_armhf-2024-03-15/2024-03-15-raspios-bookworm-armhf.img.xz
cache: yes
- os: bookworm
arch: arm64
image: https://downloads.raspberrypi.com/raspios_arm64/images/raspios_arm64-2024-03-15/2024-03-15-raspios-bookworm-arm64.img.xz
cache: yes
name: Testing on ${{ matrix.os }} - ${{ matrix.arch }}
outputs:
FAILED_UPDATE_APPS_bullseye_armhf: ${{ steps.failed.outputs.FAILED_UPDATE_APPS_bullseye_armhf || '' }}
FAILED_UPDATE_APPS_bullseye_arm64: ${{ steps.failed.outputs.FAILED_UPDATE_APPS_bullseye_arm64 || '' }}
FAILED_UPDATE_APPS_bookworm_armhf: ${{ steps.failed.outputs.FAILED_UPDATE_APPS_bookworm_armhf || '' }}
FAILED_UPDATE_APPS_bookworm_arm64: ${{ steps.failed.outputs.FAILED_UPDATE_APPS_bookworm_arm64 || '' }}
UPDATED_APPS_bullseye_armhf: ${{ steps.updated.outputs.UPDATED_APPS_bullseye_armhf || '' }}
UPDATED_APPS_bullseye_arm64: ${{ steps.updated.outputs.UPDATED_APPS_bullseye_arm64 || '' }}
UPDATED_APPS_bookworm_armhf: ${{ steps.updated.outputs.UPDATED_APPS_bookworm_armhf || '' }}
UPDATED_APPS_bookworm_arm64: ${{ steps.updated.outputs.UPDATED_APPS_bookworm_arm64 || '' }}
steps:
# restore GITHUB_WORKSPACE
- uses: actions/download-artifact@v3
with:
name: GITHUB_WORKSPACE
path: ${{ runner.temp }}
- name: Extract GITHUB_WORKSPACE
run: |
cd ${{ runner.temp }}
tar xf GITHUB_WORKSPACE.tar -C $GITHUB_WORKSPACE
cd $GITHUB_WORKSPACE
- name: Replace secret reference with contents
if: ${{ matrix.image == 'RPIOS_TRIXIE_URL' || matrix.image == 'RPIOS_TRIXIE_ARMHF_URL' }}
run: |
image_url=${{ secrets[matrix.image] }}
echo "::add-mask::$image_url"
echo "image_url=$image_url" >> "$GITHUB_ENV"
- name: Replace non-secret reference with contents
if: ${{ matrix.image != 'RPIOS_TRIXIE_URL' && matrix.image != 'RPIOS_TRIXIE_ARMHF_URL' }}
run: |
image_url=${{ matrix.image }}
echo "image_url=$image_url" >> "$GITHUB_ENV"
- name: Write UPDATED_APPS and FAILED_APPS from OUTPUT of get-latest-app-versions to ENV
run: |
echo "UPDATED_APPS<<EOF" >> $GITHUB_ENV
echo "${{needs.get-latest-app-versions.outputs.UPDATED_APPS}}" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
echo "FAILED_APPS<<EOF" >> $GITHUB_ENV
echo "${{needs.get-latest-app-versions.outputs.FAILED_APPS}}" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
- name: Test installing updated apps on ${{ matrix.os }} - ${{ matrix.arch }}
uses: theofficialgman/arm-runner-action@v12
with:
base_image: ${{ env.image_url }}
# bind mount the directory so any changes propogate to outside the chroot
bind_mount_repository: yes
# give the image more space
image_additional_mb: 5000
# disable image caching to not leak the URL on some systems
enable_image_caching: ${{ matrix.cache }}
# set CPUs to use
cpu: cortex-a7:cortex-a72
# use custom /proc/cpuinfo
cpu_info: cpuinfo/raspberrypi_4b
# user runner name as default path
copy_repository_path: /home/runner/pi-apps
# export github env back to outside the chroot
export_github_env: yes
import_github_env: true
# disable debug which shows all commands to be executed
debug: no
# set shell to bash
shell: /bin/bash
commands: |
sudo chown runner:docker /home/runner
# print user info
echo $USER $USERNAME $(id) $(whoami)
sudo bash -c 'echo $USER $USERNAME $(id) $(whoami)'
# create standard directories
mkdir -p $HOME/.local/share/applications $HOME/.local/bin
sudo mkdir -p /usr/local/bin /usr/local/share/applications
# install pi-apps dependencies
sudo apt update
sudo apt install -y yad curl wget aria2 lsb-release software-properties-common apt-utils imagemagick bc librsvg2-bin locales shellcheck git wmctrl xdotool x11-utils rsync
# runonce-entries is run in the build tester, runonce requires that all api functions be available to subprocess (like is done in the gui script)
#for the will_reinstall() and list_intersect() functions
set -a #make all functions in the api available to subprocesses
#make DIRECTORY equal to GITHUB_WORKSPACE, for subscripts and api functions
DIRECTORY=$(pwd)
source "${DIRECTORY}/api" || error "failed to source ${DIRECTORY}/api"
#Run runonce entries
"${DIRECTORY}/etc/runonce-entries"
set +a #stop exporting functions
cd ${DIRECTORY}
# upgrade cmake to 3.20+ from theofficialgman ppa to fix QEMU only issue https://gitlab.kitware.com/cmake/cmake/-/issues/20568
package_is_new_enough cmake 3.20 || debian_ppa_installer "theofficialgman/cmake-bionic" "bionic" "0ACACB5D1E74E484" || exit 1
# store apps changed from last commit to working directory in variable
mapfile -t changed_apps < <(git diff --name-only | grep ^apps/ | awk -F '/' '{print $2}' | sort -u)
# clean out any app status files
rm -rf ./data/status
# attempt to install updated apps using manage script loop
# if any app fails, add it to the FAILED_INSTALL_APPS or FAILED_UNINSTALL_APPS variable
if [[ ${{ matrix.arch }} == armhf ]]; then
# skip checking DDNet (due to Rust) if on arm32 under QEMU: https://github.com/rust-lang/cargo/issues/8719
# skip checking Microsoft PowerShell due to QEMU instability with .NET: https://github.com/Botspot/pi-apps/pull/2252#issuecomment-1403043945
# skip WPS Office on 32bit as it requires "64bit" kernel to be detected. QEMU reports an armv7 kernel. WPS Office is still tested on arm64 (which will verify if the deb works and installs correctly)
# skip Boxy SVG on 32bit due to QEMU instability
skiplist="DDNet
Microsoft PowerShell
WPS Office
Boxy SVG"
else
# skip checking Microsoft PowerShell due to QEMU instability with .NET: https://github.com/Botspot/pi-apps/pull/2252#issuecomment-1403043945
skiplist="Microsoft PowerShell"
fi
for app in "${changed_apps[@]}"; do
# only attempt install/uninstall if updated app is supported on this architecture
scriptname="$(script_name_cpu "$app")" #will be install, install-32, install-64, or package
if [ -z "$scriptname" ];then
continue
fi
# skip app if is in the skiplist
if echo "$skiplist" | grep -Fxq "$app"; then
continue
fi
./manage install "$app" || { FAILED_INSTALL_APPS+="$app"$'\n'; UPDATED_APPS=$(echo "$UPDATED_APPS" | sed "/$app/d"); }
./manage uninstall "$app" || { FAILED_UNINSTALL_APPS+="$app"$'\n'; UPDATED_APPS=$(echo "$UPDATED_APPS" | sed "/$app/d"); }
done
if [ ! -z "$FAILED_INSTALL_APPS" ] || [ ! -z "$FAILED_UNINSTALL_APPS" ]; then
echo "FAILED_UPDATE_APPS<<EOF" >> $GITHUB_ENV
echo "$FAILED_INSTALL_APPS$FAILED_UNINSTALL_APPS" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
echo "UPDATED_APPS<<EOF" >> $GITHUB_ENV
echo "$UPDATED_APPS" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
fi
- name: Write FAILED_APPS to OUTPUT
id: failed
run: |
echo "FAILED_UPDATE_APPS_${{ matrix.os }}_${{ matrix.arch }}<<EOF" >> $GITHUB_OUTPUT
echo "${{env.FAILED_UPDATE_APPS}}" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Write UPDATED_APPS to OUTPUT
id: updated
run: |
echo "UPDATED_APPS_${{ matrix.os }}_${{ matrix.arch }}<<EOF" >> $GITHUB_OUTPUT
echo "${{env.UPDATED_APPS}}" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
create-commit:
needs: [get-latest-app-versions,test-updated-apps]
runs-on: ubuntu-latest
steps:
# setup github environment variables
- uses: actions/checkout@v3
# restore GITHUB_WORKSPACE
- uses: actions/download-artifact@v3
with:
name: GITHUB_WORKSPACE
path: ${{ runner.temp }}
- name: Extract GITHUB_WORKSPACE
run: |
cd ${{ runner.temp }}
tar xf GITHUB_WORKSPACE.tar -C $GITHUB_WORKSPACE --exclude=".git"
cd $GITHUB_WORKSPACE
- name: Delete artifact
uses: geekyeggo/delete-artifact@v2
with:
name: GITHUB_WORKSPACE
failOnError: false
- name: Revert failed apps and generate list
run: |
ALL_FAILED_APPS="${{needs.test-updated-apps.outputs.FAILED_UPDATE_APPS_bullseye_armhf}}"$'\n'"${{needs.test-updated-apps.outputs.FAILED_UPDATE_APPS_bullseye_arm64}}"$'\n'"${{needs.test-updated-apps.outputs.FAILED_UPDATE_APPS_bookworm_armhf}}"$'\n'"${{needs.test-updated-apps.outputs.FAILED_UPDATE_APPS_bookworm_arm64}}"
ALL_FAILED_APPS="$(echo "$ALL_FAILED_APPS" | sort -u | awk NF)"
echo "ALL_FAILED_APPS<<EOF" >> $GITHUB_ENV
echo "$ALL_FAILED_APPS" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
error_string=""
IFS=$'\n'
for app in $ALL_FAILED_APPS; do
git checkout -- "apps/$app"
error_string+='![badge-error][badge-error]'" Failed to install $app on "
if echo "${{needs.test-updated-apps.outputs.FAILED_UPDATE_APPS_bullseye_armhf}}" | grep -Fxq "$app"; then
error_string+="bullseye armhf, "
fi
if echo "${{needs.test-updated-apps.outputs.FAILED_UPDATE_APPS_bullseye_arm64}}" | grep -Fxq "$app"; then
error_string+="bullseye arm64, "
fi
if echo "${{needs.test-updated-apps.outputs.FAILED_UPDATE_APPS_bookworm_armhf}}" | grep -Fxq "$app"; then
error_string+="bookworm armhf, "
fi
if echo "${{needs.test-updated-apps.outputs.FAILED_UPDATE_APPS_bookworm_arm64}}" | grep -Fxq "$app"; then
error_string+="bookworm arm64, "
fi
error_string+="reverting to previous version."$'\n'$'\n'
done
true
echo "ALL_FAILED_APPS_ERROR_STRING<<EOF" >> $GITHUB_ENV
echo "$error_string" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
- name: Generate updated apps list
run: |
list_subtract() { #Outputs a list of apps from stdin, minus the ones that appear in $1 using the UPDATED_APP format
# for example, the following two inputs will be a match
# - BlockBench-arm64: 4.7.4 -> 4.8.0
# BlockBench
# change \n to -\n | change '^' to '- '
grep -ve "$(echo "$1" | sed -z 's/\n/\-\n/g' | sed 's/^/- /g')"
true
}
ALL_UPDATED_APPS="${{needs.test-updated-apps.outputs.UPDATED_APPS_bullseye_armhf}}"$'\n'"${{needs.test-updated-apps.outputs.UPDATED_APPS_bullseye_arm64}}"$'\n'"${{needs.test-updated-apps.outputs.UPDATED_APPS_bookworm_armhf}}"$'\n'"${{needs.test-updated-apps.outputs.UPDATED_APPS_bookworm_arm64}}"
ALL_UPDATED_APPS="$(echo "$ALL_UPDATED_APPS" | sort -u | awk NF)"
[ ! -z "$ALL_UPDATED_APPS" ] && ALL_UPDATED_APPS="$(echo "$ALL_UPDATED_APPS" | list_subtract "$ALL_FAILED_APPS")"
echo "ALL_UPDATED_APPS<<EOF" >> $GITHUB_ENV
echo "$ALL_UPDATED_APPS" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
- name: Create Commit and Push
uses: stefanzweifel/git-auto-commit-action@v5
with:
commit_author: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
commit_message: |
Update App Versions, run by GitHub Actions - Apps updated:
${{ env.ALL_UPDATED_APPS }}
- name: Create or Update issue
if: ${{ needs.get-latest-app-versions.outputs.FAILED_APPS != '' || env.ALL_FAILED_APPS_ERROR_STRING != '' }}
uses: JasonEtco/create-an-issue@v2
env:
FAILED_APPS: ${{needs.get-latest-app-versions.outputs.FAILED_APPS}}
ALL_FAILED_APPS_ERROR_STRING: ${{ env.ALL_FAILED_APPS_ERROR_STRING }}
GITHUB_REPOSITORY: ${{ github.repository }}
GITHUB_RUN_ID: ${{ github.run_id }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
update_existing: true
search_existing: all
filename: .github/update_apps_issue_template.md