Add events garbage collection system and API. #1239
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: GitHub CI | |
on: | |
push: | |
branches: [master, ci, coverity_scan] | |
pull_request: | |
jobs: | |
build: | |
runs-on: ${{ matrix.os }} | |
name: build(${{ matrix.msystem || matrix.docker_image || matrix.os }}, | |
${{ matrix.cc }}${{ matrix.api && ', ' }}${{ matrix.api }}) | |
strategy: | |
fail-fast: false | |
matrix: | |
include: | |
# Enable distcheck for one build | |
- os: ubuntu-latest | |
cc: gcc | |
do_distc: yes | |
# Run Coverity on a clang build; Coverity's gcc causes issues | |
- os: ubuntu-latest | |
cc: clang | |
do_coverity: yes | |
# Add a tcc build | |
- os: ubuntu-latest | |
cc: tcc | |
ld: tcc | |
# Add docker-build on Alpine | |
- os: ubuntu-latest | |
cc: gcc | |
docker_image: alpine:latest | |
shell: '/tmp/docker_shell {0}' | |
art_reg_skip: 'font_nonunicode' | |
# Add docker-build with minimum version of dependencies | |
- os: ubuntu-latest | |
cc: gcc | |
docker_image: oldlibs | |
docker_pullprefix: 'ghcr.io/theoneric/libass-containers/' | |
shell: '/tmp/docker_shell {0}' | |
# Crash Tests detect (false?) leaks in Fontconfig, and | |
# various regression test fail, assumed due to older deps | |
skip_tests: yes | |
# MacOS Intel | |
- os: macos-13 | |
cc: clang | |
# MacOS arm64 | |
- os: macos-14 | |
cc: clang | |
# Add a Windows build (MinGW-gcc via MSYS2) with no extras | |
- os: windows-2019 | |
msystem: MINGW32 | |
cc: gcc | |
api: desktop | |
shell: 'msys2 {0}' | |
# Add a best-effort build for UWP apps for Microsoft Store | |
- os: windows-2019 | |
msystem: UCRT64 | |
cc: gcc | |
api: app | |
extra_cflags: -DWINAPI_FAMILY=WINAPI_FAMILY_APP -specs=/tmp/windowsapp.specs | |
shell: 'msys2 {0}' | |
defaults: | |
run: | |
shell: ${{ matrix.shell || 'bash' }} | |
env: | |
ART_SAMPLES: ext_art-samples | |
steps: | |
# Available core count changes on runner type and over time, but GHA | |
# doesn’t easily expose this, so we’ll have to query this ourselves. Based on: | |
# https://github.com/orgs/community/discussions/25057#discussioncomment-5957241 | |
- name: determine logical cpu core count | |
id: cpus | |
shell: python | |
run: | | |
import os | |
import multiprocessing | |
try: | |
num_cpus = len(os.sched_getaffinity(0)) | |
except AttributeError: | |
num_cpus = multiprocessing.cpu_count() | |
print(f"num_cpus={num_cpus}") | |
output_file = os.environ["GITHUB_OUTPUT"] | |
with open(output_file, "a", encoding="utf-8") as output_stream: | |
output_stream.write(f"count={num_cpus}\n") | |
- name: checkout code | |
uses: actions/checkout@v4 | |
- name: download test samples | |
uses: actions/checkout@v4 | |
with: | |
repository: libass/libass-tests | |
path: ${{ env.ART_SAMPLES }} | |
- name: Start Docker | |
if: matrix.docker_image | |
shell: bash | |
run: | | |
# Note: Many containers default to the root user | |
docker pull "${{ matrix.docker_pullprefix }}${{ matrix.docker_image }}" | |
docker create --name dockerciimage \ | |
-v "/home/runner/work:/home/runner/work" --workdir "$PWD" \ | |
--entrypoint "tail" \ | |
"${{ matrix.docker_pullprefix }}${{ matrix.docker_image }}" \ | |
"-f" "/dev/null" | |
docker start dockerciimage | |
# Create a proxy-shell for Docker containers | |
# Scripts for each step and the output file are inside the mounted | |
# directories, but some environment variable must be forwarded. | |
echo '#!/bin/sh | |
set -eu | |
if [ "$#" -ne 1 ] ; then | |
echo "Usage: $0 <script file>" | |
exit 1 | |
fi | |
exec /usr/bin/docker exec \ | |
--env GITHUB_OUTPUT --env GITHUB_ENV --env GITHUB_PATH --env GITHUB_STATE \ | |
dockerciimage sh -e "$1" | |
' > /tmp/docker_shell | |
chmod a+x /tmp/docker_shell | |
- name: Setup MSys2 | |
uses: msys2/setup-msys2@v2 | |
if: matrix.msystem | |
with: | |
msystem: ${{ matrix.msystem }} | |
update: false | |
- name: install deps | |
run: | | |
case "${{ matrix.docker_image || matrix.os }}" in | |
macos-*) | |
#brew update | |
brew install autoconf automake libtool nasm pkg-config \ | |
harfbuzz freetype fribidi fontconfig | |
;; | |
windows-*) | |
pre="$MINGW_PACKAGE_PREFIX" | |
pacman --noconfirm -S \ | |
automake autoconf libtool nasm make \ | |
$pre-pkg-config $pre-gcc \ | |
$pre-fribidi $pre-freetype $pre-harfbuzz $pre-fontconfig \ | |
$pre-libpng | |
;; | |
alpine:*) | |
apk add nasm ${{ matrix.cc }} musl-dev \ | |
make automake autoconf libtool pkgconf \ | |
fontconfig-dev freetype-dev fribidi-dev harfbuzz-dev \ | |
libpng-dev | |
;; | |
oldlibs) | |
: # Everything is preinstalled | |
;; | |
*) | |
sudo apt-get update #&& sudo apt-get upgrade | |
ubver="$(apt-cache search libubsan | awk '/^libubsan[0-9]* / {print substr($1, 9)}' | sort -rn | head -n1)" | |
asver="$(apt-cache search libasan | awk '/^libasan[0-9]* / {print substr($1, 8)}' | sort -rn | head -n1)" | |
sudo apt-get install -y --no-install-recommends \ | |
autoconf automake make libtool \ | |
libfontconfig1-dev libfreetype6-dev libfribidi-dev \ | |
libharfbuzz-dev nasm ${{ matrix.cc }} \ | |
libpng-dev libubsan"$ubver" libasan"$asver" | |
;; | |
esac | |
- name: Determine Sanitizer Flags | |
id: sanitizer | |
run: | | |
aflags="-fsanitize=address" | |
uflags="-fsanitize=undefined -fsanitize=float-cast-overflow" | |
if [ "${{ startsWith(matrix.cc, 'clang') }}" = "true" ] ; then | |
# Clang's UBSAN exits with code zero even if issues were found | |
# This options will instead force an SIGILL, but remove a report being printed | |
# see https://reviews.llvm.org/D35085 | |
uflags="$uflags -fsanitize-undefined-trap-on-error" | |
fi | |
# UBSAN: Alpine and MSys2 doesn't ship the UBSAN library, | |
# but when SIGILL'ing the lib is not needed | |
# ASAN: Not supported with musl and in Windows | |
case "${{ matrix.docker_image || matrix.os }}" in | |
alpine*|windows-*) | |
flags="$uflags -fsanitize-undefined-trap-on-error" ;; | |
*) | |
flags="$aflags $uflags" ;; | |
esac | |
if [ -n "$flags" ] ; then | |
flags="$flags -fno-sanitize-recover=all" | |
fi | |
if [ "${{ matrix.cc }}" = "tcc" ] || [ "${{ matrix.skip_tests }}" = "yes" ] ; then | |
flags="" | |
fi | |
echo "SANFLAGS=$flags" | |
echo "flags=${flags}" >> $GITHUB_OUTPUT | |
- name: Customize compiler | |
if: matrix.api == 'app' && matrix.cc == 'gcc' | |
run: > | |
gcc -dumpspecs | |
| sed 's/-lmsvcrt/-lucrtapp/g; s/-lkernel32/-lwindowsapp/g; | |
s/-ladvapi32//g; s/-lshell32//g; s/-luser32//g' | |
> /tmp/windowsapp.specs | |
- name: configure | |
run: | | |
export CC="${{ matrix.cc }}\ | |
-DDEBUG_LEVEL=3\ | |
${{ matrix.extra_cflags && ' ' }}${{ matrix.extra_cflags }}\ | |
${{ steps.sanitizer.outputs.flags && ' ' }}${{ steps.sanitizer.outputs.flags }}" | |
export LD="${{ matrix.ld }}" | |
export ART_SAMPLES="${{ env.ART_SAMPLES }}" | |
./autogen.sh | |
./configure --enable-compare --enable-fuzz | |
- name: distcheck | |
if: matrix.do_distc == 'yes' | |
run: make -j '${{ steps.cpus.outputs.count }}' distcheck | |
- name: compile | |
run: make -j '${{ steps.cpus.outputs.count }}' | |
- name: ensure internal functions are namespaced | |
if: startsWith(matrix.os, 'ubuntu-') | |
run: | | |
test -f libass/.libs/libass.a || (echo "Static lib is missing!"; exit 1) | |
set +e | |
list="$(nm libass/.libs/libass.a | grep ' T ' | grep -v ' ass_')" | |
case "$?" in | |
1) | |
: # All good | |
;; | |
0) | |
echo "There are non-namespaced functions! Prefix them with 'ass_'." | |
echo "$list" | |
exit 1 | |
;; | |
*) | |
echo "Internal grep error occured!" | |
echo "$list" | |
exit 2 | |
;; | |
esac | |
- name: run tests | |
if: matrix.skip_tests != 'yes' | |
run: | | |
ART_REG_SKIP="${{ matrix.art_reg_skip }}" make -j 1 check \ | |
|| (cat test-suite.log; exit 1;) | |
- name: Coverity scan | |
if: > | |
matrix.do_coverity == 'yes' | |
&& github.repository == 'libass/libass' | |
&& github.event_name != 'pull_request' | |
env: | |
COVERITY_SCAN_TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }} | |
PROJECT_NAME: libass/libass | |
NOTIFY_EMAIL: [email protected] | |
TOOL_URL: https://scan.coverity.com/download/ | |
UPLOAD_URL: https://scan.coverity.com/builds?project=libass%2Flibass | |
SCAN_URL: https://scan.coverity.com | |
RES_DIR: cov-int | |
run: | | |
exit_code=0 | |
echo "Running Coverity ..." | |
# Remove previous build output | |
make clean | |
# The upstream script is borked and always exits with 1 even on success | |
# To get meaningful success/error status we're using our own script | |
# but we still want to be informed about upstream script changes | |
if curl -s https://scan.coverity.com/scripts/travisci_build_coverity_scan.sh \ | |
| shasum -a 256 \ | |
| grep -Eq '^234d71b4a5257a79559e66dd3ba5765576d2af4845da83af4975b77b14ab536b ' | |
then | |
: remote unchanged | |
else | |
echo "Coverity's travis script changed!" | |
exit_code=1 | |
fi | |
# Check if we are within quoata | |
quota_res="$(curl -s --form project="$PROJECT_NAME" \ | |
--form token="$COVERITY_SCAN_TOKEN" \ | |
"$SCAN_URL"/api/upload_permitted)" | |
if [ "$?" -ne 0 ] || [ "x$quota_res" = "xAccess denied" ] ; then | |
echo "Coverity denied access or did not respond!" | |
exit 1 | |
elif echo "$quota_res" | grep -Eq 'upload_permitted": *true' ; then | |
echo "Within Coverity quota." | |
else | |
echo "Exceeding Coverity quota! Try again later." | |
echo "$quota_res" | grep -Eo 'next_upload_permitted_at":[^,}]*' | |
exit 0 | |
fi | |
# Download cov tool and make it available | |
wget -nv "$TOOL_URL""$(uname)" \ | |
--post-data "project=$PROJECT_NAME&token=$COVERITY_SCAN_TOKEN" \ | |
-O cov-analysis-tool.tar.gz | |
mkdir cov-analysis-tool | |
tar xzf cov-analysis-tool.tar.gz --strip 1 -C cov-analysis-tool | |
export PATH="$(pwd)/cov-analysis-tool/bin:$PATH" | |
# Coverity Build | |
echo "Starting Coverity build..." | |
#mkdir "$RES_DIR" # already done by cov-build | |
COVERITY_UNSUPPORTED=1 cov-build --dir "$RES_DIR" make -j '${{ steps.cpus.outputs.count }}' | |
cov-import-scm --dir "$RES_DIR" --scm git --log "$RES_DIR/scm_log.txt" 2>&1 | |
# Submit results to Coverity's server | |
tar czf libass.tar.gz "$RES_DIR" | |
upstat="$(curl --silent --write-out "\n%{http_code}\n" \ | |
--form project="PROJECT_NAME" \ | |
--form token="$COVERITY_SCAN_TOKEN" \ | |
--form email="$NOTIFY_EMAIL" \ | |
--form [email protected] \ | |
--form version="${{ github.sha }}" \ | |
--form description="GitHubActions CI build" \ | |
"$UPLOAD_URL")" | |
if [ "$?" -ne 0 ] ; then | |
echo "Upload failed (curl error)" | |
exit_code=1 | |
elif echo "$upstat" | tail -n 1 | grep -Eq '^2[0-9]{2}$' ; then | |
echo "Upload successful." | |
else | |
echo "Upload failed (server error)" | |
exit_code=1 | |
fi | |
echo "$upstat" | head | |
exit $exit_code | |
- name: Stop Docker | |
if: matrix.docker_image | |
shell: bash | |
run: | | |
docker rm --force dockerciimage |