Repository navigation
273 lines (253 loc) · 12.3 KB
/
Copy pathffmpeg-patch-stack.yml
File metadata and controls
273 lines (253 loc) · 12.3 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
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
name: FFmpeg Patch Stack
on:
push:
branches: [master]
pull_request:
branches: [master]
types: [opened, synchronize, reopened, ready_for_review]
schedule:
- cron: "43 5 * * *"
workflow_dispatch:
permissions:
contents: read
concurrency:
group: ffmpeg-patch-stack-${{ github.event_name }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
jobs:
tier:
name: CI tier (FFmpeg Patch Stack)
if: github.event_name != 'pull_request' || github.event.pull_request.draft == false
permissions:
contents: read
pull-requests: read
uses: ./.github/workflows/ci-tier.yml
check:
needs: tier
if: needs.tier.outputs.light == 'true' && github.event_name != 'schedule'
# required-aggregator
name: FFmpeg Patch Stack
runs-on: ubuntu-26.04
timeout-minutes: 20
steps:
- name: Check out source
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false
- name: Enforce FFmpeg input contract
run: make ffmpeg-input-contract
- name: Install pytest for the zero-copy comparator tests
run: |
python3 -m venv "$RUNNER_TEMP/zc-venv"
"$RUNNER_TEMP/zc-venv/bin/python" -m pip install --require-hashes \
-r requirements/locks/pytest-timeout.txt
echo "$RUNNER_TEMP/zc-venv/bin" >> "$GITHUB_PATH"
- name: Enforce SYCL zero-copy routing and e2e comparator contracts
run: make sycl-zerocopy-contract
- name: Plan CI impact (ADR-1140)
id: impact
env:
EVENT_NAME: ${{ github.event_name }}
BASE_SHA: ${{ github.event.pull_request.base.sha || github.event.before }}
HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
run: |
python3 scripts/ci/plan-ci-impact.py --event "$EVENT_NAME" \
--base "$BASE_SHA" --head "$HEAD_SHA" --github-output "$GITHUB_OUTPUT"
# The replay applies the shared FFmpeg fix series first (ADR-3143). This
# gate is where its release signature is checked on every change: with
# cosign installed, FFMPEG_FIX_SERIES_VERIFY=cosign fails closed.
- name: Install cosign
if: steps.impact.outputs.mode == 'full' || steps.impact.outputs.c_core == 'true' || steps.impact.outputs.actions == 'true'
uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
- name: Check configured FFmpeg release
id: replay
if: steps.impact.outputs.mode == 'full' || steps.impact.outputs.c_core == 'true' || steps.impact.outputs.actions == 'true'
shell: bash
env:
FFMPEG_FIX_SERIES_VERIFY: cosign
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
output_dir="$RUNNER_TEMP/ffmpeg-patch-check"
mkdir -p "$output_dir"
python3 scripts/ci/ffmpeg_patch_stack.py --check --output-dir "$output_dir" \
2>&1 | tee "$output_dir/workflow-command.log"
- name: Report no replay needed
if: steps.impact.outputs.mode != 'full' && steps.impact.outputs.c_core != 'true' && steps.impact.outputs.actions != 'true'
run: echo 'Patch automation contracts passed; this change does not require FFmpeg replay.'
- name: Retain replay diagnostics
if: ${{ (always() && (steps.replay.outcome == 'success' || steps.replay.outcome == 'failure')) && env.GITEA_ACTIONS != 'true' }}
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: ffmpeg-patch-check-${{ github.run_id }}-${{ github.run_attempt }}
path: ${{ runner.temp }}/ffmpeg-patch-check/
if-no-files-found: error
retention-days: 14
- name: Retain replay diagnostics (Gitea)
if: ${{ (always() && (steps.replay.outcome == 'success' || steps.replay.outcome == 'failure')) && env.GITEA_ACTIONS == 'true' }}
uses: actions/upload-artifact@c6a366c94c3e0affe28c06c8df20a878f24da3cf # v3.2.2
with:
name: ffmpeg-patch-check-${{ github.run_id }}-${{ github.run_attempt }}
path: ${{ runner.temp }}/ffmpeg-patch-check/
if-no-files-found: error
retention-days: 14
filter:
needs: tier
if: needs.tier.outputs.light == 'true' && github.event_name != 'schedule'
# required-aggregator
name: FFmpeg vmafx Filter
runs-on: ubuntu-26.04
timeout-minutes: 45
env:
DEBIAN_FRONTEND: noninteractive
steps:
- name: Check out source
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false
- name: Plan CI impact (ADR-1140)
id: impact
env:
EVENT_NAME: ${{ github.event_name }}
BASE_SHA: ${{ github.event.pull_request.base.sha || github.event.before }}
HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
run: |
python3 scripts/ci/plan-ci-impact.py --event "$EVENT_NAME" \
--base "$BASE_SHA" --head "$HEAD_SHA" --github-output "$GITHUB_OUTPUT"
- name: Report no filter build needed
if: steps.impact.outputs.mode != 'full' && steps.impact.outputs.c_core != 'true' && steps.impact.outputs.actions != 'true'
run: |
echo "skip: no C core, FFmpeg patch or workflow change; the FFmpeg Patch Stack job covers the series"
- name: Load build config
if: steps.impact.outputs.mode == 'full' || steps.impact.outputs.c_core == 'true' || steps.impact.outputs.actions == 'true'
run: scripts/ci/load-build-config.sh >> "$GITHUB_ENV"
- name: Setup python
if: steps.impact.outputs.mode == 'full' || steps.impact.outputs.c_core == 'true' || steps.impact.outputs.actions == 'true'
uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
with:
python-version: 3.14.10
- name: Install build tools
if: steps.impact.outputs.mode == 'full' || steps.impact.outputs.c_core == 'true' || steps.impact.outputs.actions == 'true'
run: |
python -m pip install --require-hashes -r requirements/locks/build.txt
sudo apt-get update
sudo -E apt-get -yq install ninja-build gcc nasm pkg-config libzimg-dev
- name: Fetch the Netflix 576x324 pair
if: steps.impact.outputs.mode == 'full' || steps.impact.outputs.c_core == 'true' || steps.impact.outputs.actions == 'true'
run: bash scripts/test/fetch-test-yuvs.sh src01_hrc00_576x324.yuv src01_hrc01_576x324.yuv
- name: Build libvmafx and the vmaf CLI
if: steps.impact.outputs.mode == 'full' || steps.impact.outputs.c_core == 'true' || steps.impact.outputs.actions == 'true'
run: |
# ADR-2170: this libvmaf build prints no warnings, so they are errors.
# shellcheck disable=SC2046 # the helper prints one option per line, split on purpose
meson setup core core/build --buildtype release -Denable_metal=disabled \
-Dwerror=true \
$(scripts/ci/werror-args.sh true)
ninja -C core/build
- name: Install cosign
if: steps.impact.outputs.mode == 'full' || steps.impact.outputs.c_core == 'true' || steps.impact.outputs.actions == 'true'
uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
- name: Build FFmpeg with the vmafx filter
if: steps.impact.outputs.mode == 'full' || steps.impact.outputs.c_core == 'true' || steps.impact.outputs.actions == 'true'
shell: bash
env:
FFMPEG_FIX_SERIES_VERIFY: cosign
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
tree="$RUNNER_TEMP/ffmpeg"
python3 scripts/ci/ffmpeg_patch_stack.py --check --keep-tree "$tree"
export PKG_CONFIG_PATH="$GITHUB_WORKSPACE/core/build/meson-uninstalled"
cd "$tree"
# The series' own C code is compiled by gcc only here, so this job
# carries the warning gate the other FFmpeg builds carry (issue 2477).
./configure --fatal-warnings --enable-version3 --enable-libvmafx \
--disable-doc --disable-indevs --enable-indev=lavfi --disable-outdevs
grep -qE '^#define CONFIG_VMAFX_FILTER 1$' config_components.h
make -j "$(getconf _NPROCESSORS_ONLN)" ffmpeg 2>&1 | tee "$RUNNER_TEMP/ffmpeg-build.log"
# grep exit 1 means no warning; any other failure (exit 2, unreadable
# log) fails this assignment and so the step under set -e.
warnings="$(grep -Ei '(^|[[:space:]])warning([[:space:]#:])' "$RUNNER_TEMP/ffmpeg-build.log" || [[ $? -eq 1 ]])"
if [[ -n "$warnings" ]]; then
printf '%s\n' "$warnings" >&2
echo "FATAL: FFmpeg emitted compiler warnings" >&2
exit 1
fi
- name: Check the vmafx filter against the CLI
if: steps.impact.outputs.mode == 'full' || steps.impact.outputs.c_core == 'true' || steps.impact.outputs.actions == 'true'
shell: bash
run: |
set -euo pipefail
# A skip (77) is a failure here: every fixture of the golden pair is fetched above.
for check in filters parity windows contract provenance; do
echo "::group::vmafx_filter_check.py $check"
python3 ffmpeg-patches/test/vmafx_filter_check.py "$check" \
--ffmpeg "$RUNNER_TEMP/ffmpeg/ffmpeg" --vmaf core/build/tools/vmaf \
--libdir core/build/src --pairs golden
echo "::endgroup::"
done
- name: Check input colorimetry propagation
if: steps.impact.outputs.mode == 'full' || steps.impact.outputs.c_core == 'true' || steps.impact.outputs.actions == 'true'
shell: bash
env:
FFMPEG: ${{ runner.temp }}/ffmpeg/ffmpeg
VMAF_CLI: core/build/tools/vmaf
run: |
set -euo pipefail
export LD_LIBRARY_PATH="$GITHUB_WORKSPACE/core/build/src:${LD_LIBRARY_PATH:-}"
bash ffmpeg-patches/test/check-vmafx-input-colorimetry.sh
refresh:
if: github.event_name == 'schedule'
name: FFmpeg Release Refresh
runs-on: ubuntu-26.04
timeout-minutes: 30
steps:
- name: Check out master
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: master
fetch-depth: 0
persist-credentials: false
- name: Enforce FFmpeg input contract
run: make ffmpeg-input-contract
- name: Install cosign
uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
- name: Refresh to the latest stable release
id: refresh
shell: bash
env:
FFMPEG_FIX_SERIES_VERIFY: cosign
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
output_dir="$RUNNER_TEMP/ffmpeg-patch-refresh"
mkdir -p "$output_dir"
python3 scripts/ci/ffmpeg_patch_stack.py --refresh --latest --output-dir "$output_dir" \
2>&1 | tee "$output_dir/workflow-command.log"
- name: Record proposed refresh
if: always()
shell: bash
run: |
set -euo pipefail
output_dir="$RUNNER_TEMP/ffmpeg-patch-refresh"
mkdir -p "$output_dir"
git diff --binary > "$output_dir/proposed-refresh.patch"
git status --short > "$output_dir/worktree-status.txt"
git rev-parse HEAD > "$output_dir/source-revision.txt"
- name: Retain refresh proposal
if: ${{ (always()) && env.GITEA_ACTIONS != 'true' }}
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: ffmpeg-patch-refresh-${{ github.run_id }}-${{ github.run_attempt }}
path: ${{ runner.temp }}/ffmpeg-patch-refresh/
if-no-files-found: error
retention-days: 14
- name: Retain refresh proposal (Gitea)
if: ${{ (always()) && env.GITEA_ACTIONS == 'true' }}
uses: actions/upload-artifact@c6a366c94c3e0affe28c06c8df20a878f24da3cf # v3.2.2
with:
name: ffmpeg-patch-refresh-${{ github.run_id }}-${{ github.run_attempt }}
path: ${{ runner.temp }}/ffmpeg-patch-refresh/
if-no-files-found: error
retention-days: 14