Skip to content

Build and Test

Build and Test #86

name: Build and Test
# Builds and tests on all combinations of OS and python version.
# Also builds the docs.
#
# Runs when a pull request is opened or updated.
#
# Can also be run manually for debugging purposes.
on:
pull_request_target:
types: [opened, synchronize, reopened]
workflow_dispatch:
inputs:
ref:
description: "The ref to build and test."
required: false
schedule:
# Run every night at midnight PST / 8am UTC, testing against the main branch.
- cron: '0 8 * * *'
defaults:
run:
shell: bash
# If another instance of this workflow is started for the same PR, cancel the
# old one. If a PR is updated and a new test run is started, the old test run
# will be cancelled automatically to conserve resources.
concurrency:
group: ${{ github.workflow }}-${{ github.event.number || inputs.ref }}
cancel-in-progress: true
jobs:
# Configure the build matrix based on repo variables. The list of objects in
# the build matrix contents can't be changed by conditionals, but it can be
# computed by another job and deserialized. This uses
# vars.ENABLE_SELF_HOSTED to determine the build matrix, based on the
# metadata in build-matrix.json.
matrix_config:
runs-on: ubuntu-latest
outputs:
MATRIX: ${{ steps.configure.outputs.MATRIX }}
steps:
- uses: actions/checkout@v4
with:
ref: ${{ inputs.ref || (github.event.number && format('refs/pull/{0}/merge', github.event.number)) }}
persist-credentials: false
- name: Configure Build Matrix
id: configure
shell: node {0}
run: |
const fs = require('fs');
const enableDebug = "${{ vars.ENABLE_DEBUG }}" != '';
const enableSelfHosted = "${{ vars.ENABLE_SELF_HOSTED }}" != '';
// Use ENABLE_SELF_HOSTED to decide what the build matrix below
// should include.
const buildMatrix = JSON.parse(fs.readFileSync("${{ github.workspace }}/build-matrix.json"));
const {hosted, selfHosted, pythonVersions} = buildMatrix;
const devices = enableSelfHosted ? hosted.concat(selfHosted) : hosted;
const matrix = [];
for (const device of devices) {
for (const version of pythonVersions) {
// Clone device, add "python" field, push onto the matrix.
matrix.push(Object.assign({}, device, {python_version: version}));
}
}
// Output a JSON object consumed by the build matrix below.
fs.appendFileSync(
process.env['GITHUB_OUTPUT'],
`MATRIX=${ JSON.stringify(matrix) }\n`);
// Output the debug flag directly.
fs.appendFileSync(
process.env['GITHUB_OUTPUT'],
`ENABLE_DEBUG=${ enableDebug }\n`);
// Log the outputs, for the sake of debugging this script.
console.log({enableDebug, enableSelfHosted, matrix});
build_and_test:
needs: matrix_config
strategy:
# Let other matrix entries complete, so we have all results on failure
# instead of just the first failure.
fail-fast: false
matrix:
include: ${{ fromJSON(needs.matrix_config.outputs.MATRIX) }}
name: Build and test ${{ matrix.os_name }} ${{ matrix.target_arch }} Python ${{ matrix.python_version }}
runs-on: ${{ matrix.os }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
ref: ${{ inputs.ref || (github.event.number && format('refs/pull/{0}/merge', github.event.number)) }}
persist-credentials: false
- name: Set Python version
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python_version }}
- name: Debug Python version
run: python3 --version
- name: Install Linux deps
if: runner.os == 'Linux'
run: |
sudo apt -y install \
libva2 libva-drm2 \
nodejs npm xvfb
- name: Install Chromium (non-Snap, arm64 Linux only)
if: runner.os == 'Linux' && matrix.target_arch == 'arm64'
run: |
sudo add-apt-repository ppa:xtradeb/apps -y
sudo apt update
sudo apt -y install chromium
# Running inside a Docker container, we need to kill the sandbox.
# Heredocs interpolate variables, so escape the dollar sign below.
cat >/usr/local/bin/chromium <<EOF
#!/bin/bash
exec /usr/bin/chromium --no-sandbox "\$@"
EOF
chmod 755 /usr/local/bin/chromium
echo "CHROME_BIN=/usr/local/bin/chromium" >> $GITHUB_ENV
- name: Install Python deps
run: |
python3 -m pip install -r requirements.txt
python3 -m pip install -r optional_requirements.txt
- name: Download and install binaries
run: |
# Fetch binaries locally instead of installing the release version of
# the binary package. This lets us test changes to the binary package
# before it is released.
# In case of network flake, try it three times. This is arbitrary.
python3 binaries/build_wheels.py || python3 binaries/build_wheels.py || python3 binaries/build_wheels.py
# Make sure the locally-created binary package for each platform can
# be locally installed, so we know they are correctly formatted/named.
# This also makes these binaries available for the test run.
if [[ '${{ runner.os }}' == 'Windows' ]]; then
python3 -m pip install binaries/dist/shaka_streamer_binaries*win*amd64.whl
elif [[ '${{ runner.os }}' == 'Linux' ]]; then
if [[ '${{ matrix.target_arch }}' == 'x64' ]]; then
python3 -m pip install binaries/dist/shaka_streamer_binaries*linux*x86_64.whl
elif [[ '${{ matrix.target_arch }}' == 'arm64' ]]; then
python3 -m pip install binaries/dist/shaka_streamer_binaries*linux*aarch64.whl
fi
elif [[ '${{ runner.os }}' == 'macOS' ]]; then
if [[ '${{ matrix.target_arch }}' == 'x64' ]]; then
python3 -m pip install binaries/dist/shaka_streamer_binaries*mac*x86_64.whl
elif [[ '${{ matrix.target_arch }}' == 'arm64' ]]; then
python3 -m pip install binaries/dist/shaka_streamer_binaries*mac*arm64.whl
fi
fi
- name: Build docs (Linux only)
if: runner.os == 'Linux'
run: bash docs/build.sh
- name: Run tests
run: |
if [[ '${{ runner.os }}' == 'Linux' ]]; then
# Run without X11 on Linux by using xvfb.
WRAPPER="xvfb-run -a"
else
WRAPPER=""
fi
if [[ '${{ runner.os }}' == 'Linux' && '${{ matrix.target_arch }}' == 'arm64' ]]; then
# There is no Widevine CDM for Linux arm64 at this time.
# By setting this here instead of probing during the test, we can
# be sure to notice failures if Widevine disappears from our
# testing environment on platforms where this would not be
# expected.
EXTRA_ARGS="--no-test-widevine"
else
EXTRA_ARGS=""
fi
# Use the "spec" reporter for clearer logs in GitHub Actions
$WRAPPER python3 run_end_to_end_tests.py --reporters spec $EXTRA_ARGS
- name: Debug on failure
uses: mxschmitt/[email protected]
with:
limit-access-to-actor: true
if: failure() && vars.ENABLE_DEBUG != ''