test-apps.yml 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469
  1. name: "Test random 💯"
  2. env:
  3. TERM: xterm
  4. on:
  5. push:
  6. branches: main
  7. paths:
  8. - 'programs/x86_64/**'
  9. - .github/workflows/test-apps.yml
  10. #pull_request:
  11. # if: github.event.pull_request.head.repo.full_name != github.repository
  12. # branches: main
  13. # paths:
  14. # - 'programs/x86_64/**'
  15. # - .github/workflows/test-apps.yml
  16. workflow_dispatch:
  17. inputs:
  18. reset_stats:
  19. description: "RESET stats"
  20. required: true
  21. default: "false"
  22. type: boolean
  23. schedule:
  24. - cron: '0 23 * * *'
  25. concurrency:
  26. group: ${{ github.workflow }}-${{ github.ref }}
  27. cancel-in-progress: false
  28. permissions:
  29. actions: write
  30. contents: write
  31. jobs:
  32. rebase-testing-branch:
  33. name: "prepare 💤"
  34. runs-on: ubuntu-22.04
  35. steps:
  36. - name: "Checkout repository"
  37. uses: actions/checkout@v4
  38. with:
  39. fetch-depth: 0
  40. - name: "Git Config"
  41. run: |
  42. git config --global user.name "ivan-hc"
  43. git config --global user.email "noreply@github.com"
  44. - name: "Check if histories differ"
  45. id: check_history
  46. run: |
  47. git fetch origin main testing || echo "Branch 'testing' does not exist."
  48. if ! git ls-remote --exit-code --heads origin testing; then
  49. echo "Creating remote 'testing' branch from 'main'..."
  50. git push origin main:testing
  51. echo "RESET_REQUIRED=true" >> $GITHUB_ENV
  52. else
  53. if git merge-base --is-ancestor origin/main origin/testing; then
  54. echo "Histories are compatible, rebase only."
  55. echo "RESET_REQUIRED=false" >> $GITHUB_ENV
  56. else
  57. echo "Histories are different, reset needed."
  58. echo "RESET_REQUIRED=true" >> $GITHUB_ENV
  59. fi
  60. fi
  61. - name: "Reset testing branch if needed"
  62. if: env.RESET_REQUIRED == 'true'
  63. run: |
  64. echo "Resetting testing branch..."
  65. git checkout -B testing origin/testing || git checkout -B testing origin/main
  66. if [[ "${{ github.event.inputs.reset_stats }}" != "true" ]]; then
  67. echo "Preserving test files..."
  68. mkdir -p backup
  69. cp -r tested.list failed.list logs backup/ 2>/dev/null || true
  70. git reset --hard origin/main
  71. mv backup/tested.list backup/failed.list backup/logs . 2>/dev/null || true
  72. rm -rf backup
  73. git add .
  74. git commit -m "update results"
  75. else
  76. echo "Resetting stats..."
  77. echo "Resetting stats" >> $GITHUB_STEP_SUMMARY
  78. git reset --hard origin/main
  79. fi
  80. git push --force origin HEAD:testing
  81. - name: "Check if testing differs from main"
  82. id: check_diff
  83. run: |
  84. git fetch origin main testing
  85. if git diff --quiet origin/main..origin/testing; then
  86. echo "No difference between testing and main. Exiting."
  87. echo "skip=true" >> $GITHUB_ENV
  88. else
  89. echo "skip=false" >> $GITHUB_ENV
  90. fi
  91. - name: "Get last commit from testing"
  92. id: last_commit
  93. if: env.skip == 'false'
  94. run: |
  95. LAST_COMMIT=$(git log origin/testing --format=%H -n 1)
  96. echo "Last commit: $LAST_COMMIT"
  97. echo "LAST_COMMIT=$LAST_COMMIT" >> $GITHUB_ENV
  98. - name: "Rebase testing on main"
  99. if: env.skip == 'false'
  100. run: |
  101. git checkout testing
  102. git rebase origin/main
  103. - name: "Reapply last commit"
  104. if: env.skip == 'false'
  105. run: |
  106. if [[ "$LAST_COMMIT" == 'update results' ]]; then
  107. git cherry-pick $LAST_COMMIT
  108. elif [[ "$LAST_COMMIT" != 'update results' ]]; then
  109. echo "Commit from main branch?"
  110. fi
  111. - name: Push changes back to testing
  112. if: env.skip == 'false'
  113. run: |
  114. git push origin testing --force
  115. show-stats:
  116. name: "stats 📝"
  117. runs-on: ubuntu-22.04
  118. needs: rebase-testing-branch
  119. steps:
  120. - name: "Check out main branch (for programs count) 🏃"
  121. uses: actions/checkout@v4
  122. with:
  123. ref: main # Work on main branch
  124. - name: "Count programs 📊"
  125. run: |
  126. x64Count=$(find programs/x86_64/ -type f | wc -l)
  127. i68Count=$(find programs/i686/ -type f | wc -l)
  128. a64Count=$(find programs/aarch64/ -type f | wc -l)
  129. echo "x64Count=$x64Count" >> $GITHUB_ENV
  130. echo "i68Count=$i68Count" >> $GITHUB_ENV
  131. echo "a64Count=$a64Count" >> $GITHUB_ENV
  132. - name: "Check out testing branch (for tested & failed) 🏃"
  133. uses: actions/checkout@v4
  134. with:
  135. ref: testing # Work on testing branch
  136. - name: "Count tested & failed 📊"
  137. run: |
  138. tested=$(wc -l < tested.list 2>/dev/null || echo 0)
  139. failed=$(wc -l < failed.list 2>/dev/null || echo 0)
  140. echo "x86_64: $x64Count"
  141. echo "i686: $i68Count"
  142. echo "aarch64: $a64Count"
  143. echo "🏁 Tested: $tested"
  144. echo "❌ Failed: $failed"
  145. echo "### 🎬 apps" >> $GITHUB_STEP_SUMMARY
  146. echo "$x64Count x86_64" >> $GITHUB_STEP_SUMMARY
  147. echo "$i68Count i686" >> $GITHUB_STEP_SUMMARY
  148. echo "$a64Count aarch64" >> $GITHUB_STEP_SUMMARY
  149. echo "### 🔨 tests" >> $GITHUB_STEP_SUMMARY
  150. echo " 🏁 $tested" >> $GITHUB_STEP_SUMMARY
  151. echo " ❌ $failed" >> $GITHUB_STEP_SUMMARY
  152. generate-matrix:
  153. name: "matrix 🌀"
  154. needs: rebase-testing-branch
  155. runs-on: ubuntu-22.04
  156. outputs:
  157. skip: ${{ steps.set-matrix.outputs.skip }}
  158. matrix: ${{ steps.set-matrix.outputs.matrix }}
  159. count: ${{ steps.am-install.outputs.count }}
  160. steps:
  161. - name: "Check out repository 🏃"
  162. uses: actions/checkout@v4
  163. with:
  164. ref: testing
  165. - name: "Generate Matrix 🏆"
  166. id: set-matrix
  167. run: |
  168. mkdir -p results
  169. find programs/x86_64/ -maxdepth 1 -type f -printf "%f\n" | sort > all.list
  170. if [[ -f tested.list ]]; then
  171. if diff -q all.list tested.list; then
  172. echo "Everything tested" >> $GITHUB_STEP_SUMMARY
  173. echo "skip=true" >> $GITHUB_OUTPUT
  174. exit 0
  175. else
  176. comm -23 all.list tested.list > totest_tmp.list
  177. fi
  178. else
  179. echo "First run!" >> $GITHUB_STEP_SUMMARY
  180. cp all.list totest_tmp.list
  181. fi
  182. if [[ -f failed.list ]]; then
  183. comm -23 totest_tmp.list failed.list > totest.list
  184. echo "### Excluding failed:" >> $GITHUB_STEP_SUMMARY
  185. cat failed.list >> $GITHUB_STEP_SUMMARY
  186. if [ ! -s totest.list ]; then
  187. echo " 🏁 Nothing to test 🏁" >> $GITHUB_STEP_SUMMARY
  188. echo "skip=true" >> $GITHUB_OUTPUT
  189. exit 0
  190. fi
  191. else
  192. mv totest_tmp.list totest.list
  193. fi
  194. FILES=$(shuf -n 100 totest.list | sort || cat totest.list | sort)
  195. MATRIX="{\"include\": ["
  196. for file in $FILES; do
  197. MATRIX+="{\"file\": \"$file\"},"
  198. done
  199. MATRIX="${MATRIX%,}]}"
  200. echo "matrix=$MATRIX" >> $GITHUB_OUTPUT
  201. run-actions:
  202. name: "🔨"
  203. needs: generate-matrix
  204. runs-on: ubuntu-22.04
  205. if: ${{ needs.generate-matrix.outputs.skip != 'true' }}
  206. strategy:
  207. fail-fast: false
  208. matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix) }}
  209. env:
  210. TIMEOUT: 23
  211. steps:
  212. - name: "Check out repository 🏃"
  213. uses: actions/checkout@v4
  214. with:
  215. ref: testing
  216. - name: "Install dependencies 📦️"
  217. run: |
  218. sudo apt-get -y update 2> /dev/null || apt-get -y update
  219. sudo apt-get -y install wget curl torsocks zsync 2> /dev/null || apt-get -y install git wget curl torsocks zsync
  220. - name: "Install AM 🎁"
  221. run: |
  222. mkdir -p results /usr/local/bin
  223. chmod +x ./INSTALL
  224. sudo ./INSTALL 2> /dev/null || ./INSTALL
  225. - name: "test ${{ matrix.file }} 🚧"
  226. run: |
  227. set -uo pipefail
  228. mkdir -p results
  229. script_content=$(curl -Ls https://raw.githubusercontent.com/ivan-hc/AM/main/programs/x86_64/"${{ matrix.file }}")
  230. pure_arg=$(echo "${{ matrix.file }}" | sed 's/\.appimage//g; s/\^debian-testing-//g; s/\-appimage$//g' | sed 's:.*/::')
  231. if timeout "$TIMEOUT"m am -i "${{ matrix.file }}" --debug 2>&1 | tee -a results/log-"${{ matrix.file }}"; then
  232. echo ""
  233. echo " Structure of the directory in /opt"
  234. echo ""
  235. if test -d /opt/kdegames; then
  236. ls /opt/kdegames | tee -a results/log-"${{ matrix.file }}"
  237. elif test -d /opt/kdeutils; then
  238. ls /opt/kdeutils | tee -a results/log-"${{ matrix.file }}"
  239. elif test -d /opt/platform-tools; then
  240. ls /opt/platform-tools | tee -a results/log-"${{ matrix.file }}"
  241. elif test -d /opt/"$pure_arg"; then
  242. ls /opt/"$pure_arg" | tee -a results/log-"${{ matrix.file }}"
  243. elif [ "$pure_arg" = avidemux ]; then
  244. echo /opt/avidemux | tee -a results/log-"${{ matrix.file }}"
  245. elif [[ "$pure_arg" =~ (bat-extras|code|deadbeef*|kvrt|libfuse2|libreoffice|microsoft-edge*|mpv|node|npm|suyu|swift|wine) ]]; then
  246. echo "App not installed, this is a Known error related to GitHub Actions" | tee -a results/log-"${{ matrix.file }}"
  247. elif test -d /opt/"$pure_arg"*; then
  248. ls /opt/"$pure_arg"* | tee -a results/log-"${{ matrix.file }}"
  249. elif echo "$script_content" | grep -q "spooky"; then
  250. echo "App not installed because marked as \"spooky\", require to be tested manually" | tee -a results/log-"${{ matrix.file }}"
  251. else
  252. ls /opt/"${{ matrix.file }}" | tee -a results/log-"${{ matrix.file }}"
  253. fi
  254. echo ""
  255. echo "-------------------------------------------------------------"
  256. echo ""
  257. echo " Command in \$PATH"
  258. echo ""
  259. command -v "$pure_arg" | tee -a results/log-"${{ matrix.file }}" || ls /usr/local/bin | tee -a results/log-"${{ matrix.file }}"
  260. echo ""
  261. echo "-------------------------------------------------------------"
  262. echo ""
  263. echo " Launchers in /usr/local/share/applications" | tee -a results/log-"${{ matrix.file }}"
  264. echo ""
  265. if test -f /usr/local/share/applications/*AM.desktop 2>/dev/null; then
  266. ls /usr/local/share/applications | grep "AM.desktop$" | tee -a results/log-"${{ matrix.file }}"
  267. else
  268. ls /usr/local/share/applications | tee -a results/log-"${{ matrix.file }}"
  269. fi
  270. echo ""
  271. echo "-------------------------------------------------------------"
  272. am -R "${{ matrix.file }}" && echo "${{ matrix.file }}" >> results/ok-${{ matrix.file }} || echo "${{ matrix.file }}" >> results/log-${{ matrix.file }}
  273. else
  274. if [[ $? -eq 124 ]]; then
  275. echo "### 💥 ${{ matrix.file }} timeout!" >> $GITHUB_STEP_SUMMARY
  276. echo "Installation timeout in 23 minutes" >> results/log-"${{ matrix.file }}"
  277. echo "${{ matrix.file }}" >> results/log-${{ matrix.file }}
  278. else
  279. echo "### 💀 ${{ matrix.file }}" >> $GITHUB_STEP_SUMMARY
  280. echo "${{ matrix.file }}" >> results/log-${{ matrix.file }}
  281. fi
  282. exit 1
  283. fi
  284. - name: "Rename Failed Results ☝️"
  285. if: failure()
  286. run: |
  287. mv results/log-${{ matrix.file }} results/ko-${{ matrix.file }}
  288. - name: "Upload KO Results ☝️"
  289. if: failure()
  290. uses: actions/upload-artifact@v4
  291. with:
  292. name: ko-${{ matrix.file }}
  293. path: results/ko-${{ matrix.file }}
  294. - name: "Upload OK Results ⬆️"
  295. if: success()
  296. uses: actions/upload-artifact@v4
  297. with:
  298. name: ok-${{ matrix.file }}
  299. path: results/ok-${{ matrix.file }}
  300. update-tested-list:
  301. name: "results 📰"
  302. needs: run-actions
  303. runs-on: ubuntu-22.04
  304. if: always()
  305. steps:
  306. - name: "Check out repository 🏃"
  307. uses: actions/checkout@v4
  308. with:
  309. ref: testing
  310. - name: "Download Test Results ⬇️"
  311. if: success()
  312. uses: actions/download-artifact@v4
  313. with:
  314. path: results
  315. merge-multiple: true
  316. - run: ls -R results || echo "Nothing tested"
  317. - name: "Git Config"
  318. if: always()
  319. run: |
  320. git config --global user.name "ivan-hc"
  321. git config --global user.email "noreply@github.com"
  322. - name: "Aggregate and push results"
  323. if: always()
  324. run: |
  325. ls -R results || echo "Nothing tested"
  326. #git checkout -b testing
  327. #git push --set-upstream origin testing
  328. if compgen -G "results/ok-*" > /dev/null; then
  329. for file in results/ok-*; do
  330. cat "$file" >> aggregated.list
  331. done
  332. cat aggregated.list >> tested.list
  333. sort -u tested.list -o tested.list
  334. git add tested.list
  335. else
  336. echo "Nothing tested successfully?"
  337. fi
  338. if compgen -G "results/ko-*" > /dev/null; then
  339. for file in results/ko-*; do
  340. echo "$file" | cut -d'-' -f2- >> fail.list
  341. done
  342. mkdir -p logs
  343. cp results/ko-* logs/
  344. fail=$(wc -l < fail.list)
  345. cat fail.list >> failed.list
  346. sort -u failed.list -o failed.list
  347. git add failed.list logs
  348. else
  349. echo "Nothing failed? Great!"
  350. fi
  351. LAST_COMMIT_MSG=$(git log -1 --pretty=%B)
  352. if git diff --cached --quiet; then
  353. echo "No changes to commit?"
  354. else
  355. if [[ $GITHUB_REF == refs/pull/* ]]; then
  356. echo "This is Pull Request. No saving results."
  357. elif [[ "${{ github.event.inputs.reset_stats }}" == "true" ]]; then
  358. echo "stats resetted"
  359. git commit -m "update results"
  360. git push origin testing
  361. elif [[ "$LAST_COMMIT_MSG" == "update results" ]]; then
  362. echo "Last commit is 'update results'."
  363. git commit --amend -m "update results"
  364. git push --force origin testing
  365. else
  366. git commit -m "update results"
  367. git push --force origin testing
  368. fi
  369. fi
  370. - name: "Show Results 🏁"
  371. if: always()
  372. run: |
  373. tested=$(wc -l < tested.list 2>/dev/null || echo 0)
  374. failed=$(wc -l < failed.list 2>/dev/null || echo 0)
  375. fail=$(wc -l < fail.list 2>/dev/null || echo "0")
  376. count=$(find programs/x86_64/ -type f | wc -l)
  377. remaining=$((count - tested - failed - fail))
  378. if (( remaining < 0 )); then
  379. remaining=0
  380. fi
  381. echo "### 🏁 $tested tested" >> $GITHUB_STEP_SUMMARY
  382. echo "## 🛅 $remaining to test" >> $GITHUB_STEP_SUMMARY
  383. echo "😱 $failed fails listed" >> $GITHUB_STEP_SUMMARY
  384. echo ":x: $fail failed now" >> $GITHUB_STEP_SUMMARY
  385. if [[ -f fail.list ]]; then
  386. echo "💀" >> $GITHUB_STEP_SUMMARY
  387. cat fail.list >> $GITHUB_STEP_SUMMARY
  388. fi
  389. delete-all-artifacts:
  390. name: "cleanup 🧹"
  391. runs-on: ubuntu-22.04
  392. needs: update-tested-list
  393. if: always()
  394. steps:
  395. - name: "Check out repository 🏃"
  396. uses: actions/checkout@v4
  397. - name: "Delete Artifacts 🙈"
  398. env:
  399. REPO_NAME: ${{ github.repository }}
  400. RUN_ID: ${{ github.run_id }}
  401. TOKEN: ${{ secrets.GITHUB_TOKEN }}
  402. run: |
  403. echo "Fetching and deleting all artifacts for run ID: $RUN_ID"
  404. PAGE=1
  405. DELETED=0
  406. while true; do
  407. RESPONSE=$(curl -s -H "Authorization: token $TOKEN" \
  408. "https://api.github.com/repos/$REPO_NAME/actions/runs/$RUN_ID/artifacts?per_page=100&page=$PAGE")
  409. ARTIFACT_IDS=$(echo "$RESPONSE" | jq -r '.artifacts[].id')
  410. if [[ -z "$ARTIFACT_IDS" ]]; then
  411. echo "No more artifacts to delete. Total deleted: $DELETED"
  412. break
  413. fi
  414. for ARTIFACT_ID in $ARTIFACT_IDS; do
  415. echo "Deleting artifact with ID: $ARTIFACT_ID"
  416. curl -X DELETE -s -H "Authorization: token $TOKEN" \
  417. "https://api.github.com/repos/$REPO_NAME/actions/artifacts/$ARTIFACT_ID"
  418. ((DELETED+=1))
  419. done
  420. ((PAGE+=1))
  421. done
  422. echo "Successfully deleted $DELETED artifacts."
  423. already-tested:
  424. name: "all 🏁"
  425. runs-on: ubuntu-22.04
  426. needs: generate-matrix
  427. if: ${{ needs.generate-matrix.outputs.skip == 'true' }}
  428. steps:
  429. - name: "Mark as Successful"
  430. run: echo "All apps already tested..." >> $GITHUB_STEP_SUMMARY