[build] Move bundle scripts into `bundle` submodule
[yt-dlp3.git] / .github / workflows / build.yml
blob4b05e7cf93f80ec8b01a0f751b9dccd861d75983
1 name: Build Artifacts
2 on:
3   workflow_call:
4     inputs:
5       version:
6         required: true
7         type: string
8       channel:
9         required: false
10         default: stable
11         type: string
12       unix:
13         default: true
14         type: boolean
15       linux_arm:
16         default: true
17         type: boolean
18       macos:
19         default: true
20         type: boolean
21       macos_legacy:
22         default: true
23         type: boolean
24       windows:
25         default: true
26         type: boolean
27       windows32:
28         default: true
29         type: boolean
30       meta_files:
31         default: true
32         type: boolean
33       origin:
34         required: false
35         default: ''
36         type: string
37     secrets:
38       GPG_SIGNING_KEY:
39         required: false
41   workflow_dispatch:
42     inputs:
43       version:
44         description: |
45           VERSION: yyyy.mm.dd[.rev] or rev
46         required: true
47         type: string
48       channel:
49         description: |
50           SOURCE of this build's updates: stable/nightly/master/<repo>
51         required: true
52         default: stable
53         type: string
54       unix:
55         description: yt-dlp, yt-dlp.tar.gz, yt-dlp_linux, yt-dlp_linux.zip
56         default: true
57         type: boolean
58       linux_arm:
59         description: yt-dlp_linux_aarch64, yt-dlp_linux_armv7l
60         default: true
61         type: boolean
62       macos:
63         description: yt-dlp_macos, yt-dlp_macos.zip
64         default: true
65         type: boolean
66       macos_legacy:
67         description: yt-dlp_macos_legacy
68         default: true
69         type: boolean
70       windows:
71         description: yt-dlp.exe, yt-dlp_min.exe, yt-dlp_win.zip
72         default: true
73         type: boolean
74       windows32:
75         description: yt-dlp_x86.exe
76         default: true
77         type: boolean
78       meta_files:
79         description: SHA2-256SUMS, SHA2-512SUMS, _update_spec
80         default: true
81         type: boolean
82       origin:
83         description: Origin
84         required: false
85         default: 'current repo'
86         type: choice
87         options:
88         - 'current repo'
90 permissions:
91   contents: read
93 jobs:
94   process:
95     runs-on: ubuntu-latest
96     outputs:
97       origin: ${{ steps.process_origin.outputs.origin }}
98     steps:
99       - name: Process origin
100         id: process_origin
101         run: |
102           echo "origin=${{ inputs.origin == 'current repo' && github.repository || inputs.origin }}" | tee "$GITHUB_OUTPUT"
104   unix:
105     needs: process
106     if: inputs.unix
107     runs-on: ubuntu-latest
108     steps:
109       - uses: actions/checkout@v4
110       - uses: actions/setup-python@v4
111         with:
112           python-version: "3.10"
113       - uses: conda-incubator/setup-miniconda@v2
114         with:
115           miniforge-variant: Mambaforge
116           use-mamba: true
117           channels: conda-forge
118           auto-update-conda: true
119           activate-environment: ""
120           auto-activate-base: false
121       - name: Install Requirements
122         run: |
123           sudo apt -y install zip pandoc man sed
124           reqs=$(mktemp)
125           cat > "$reqs" << EOF
126           python=3.10.*
127           pyinstaller
128           cffi
129           brotli-python
130           secretstorage
131           EOF
132           sed -E '/^(brotli|secretstorage).*/d' requirements.txt >> "$reqs"
133           mamba create -n build --file "$reqs"
135       - name: Prepare
136         run: |
137           python devscripts/update-version.py -c "${{ inputs.channel }}" -r "${{ needs.process.outputs.origin }}" "${{ inputs.version }}"
138           python devscripts/make_lazy_extractors.py
139       - name: Build Unix platform-independent binary
140         run: |
141           make all tar
142       - name: Build Unix standalone binary
143         shell: bash -l {0}
144         run: |
145           unset LD_LIBRARY_PATH  # Harmful; set by setup-python
146           conda activate build
147           python -m bundle.pyinstaller --onedir
148           (cd ./dist/yt-dlp_linux && zip -r ../yt-dlp_linux.zip .)
149           python -m bundle.pyinstaller
150           mv ./dist/yt-dlp_linux ./yt-dlp_linux
151           mv ./dist/yt-dlp_linux.zip ./yt-dlp_linux.zip
153       - name: Verify --update-to
154         if: vars.UPDATE_TO_VERIFICATION
155         run: |
156           binaries=("yt-dlp" "yt-dlp_linux")
157           for binary in "${binaries[@]}"; do
158             chmod +x ./${binary}
159             cp ./${binary} ./${binary}_downgraded
160             version="$(./${binary} --version)"
161             ./${binary}_downgraded -v --update-to yt-dlp/yt-dlp@2023.03.04
162             downgraded_version="$(./${binary}_downgraded --version)"
163             [[ "$version" != "$downgraded_version" ]]
164           done
166       - name: Upload artifacts
167         uses: actions/upload-artifact@v3
168         with:
169           path: |
170             yt-dlp
171             yt-dlp.tar.gz
172             yt-dlp_linux
173             yt-dlp_linux.zip
175   linux_arm:
176     needs: process
177     if: inputs.linux_arm
178     permissions:
179       contents: read
180       packages: write # for creating cache
181     runs-on: ubuntu-latest
182     strategy:
183       matrix:
184         architecture:
185           - armv7
186           - aarch64
188     steps:
189       - uses: actions/checkout@v4
190         with:
191           path: ./repo
192       - name: Virtualized Install, Prepare & Build
193         uses: yt-dlp/run-on-arch-action@v2
194         with:
195           # Ref: https://github.com/uraimo/run-on-arch-action/issues/55
196           env: |
197             GITHUB_WORKFLOW: build
198           githubToken: ${{ github.token }} # To cache image
199           arch: ${{ matrix.architecture }}
200           distro: ubuntu18.04 # Standalone executable should be built on minimum supported OS
201           dockerRunArgs: --volume "${PWD}/repo:/repo"
202           install: | # Installing Python 3.10 from the Deadsnakes repo raises errors
203             apt update
204             apt -y install zlib1g-dev python3.8 python3.8-dev python3.8-distutils python3-pip
205             python3.8 -m pip install -U pip setuptools wheel
206             # Cannot access requirements.txt from the repo directory at this stage
207             python3.8 -m pip install -U Pyinstaller mutagen pycryptodomex websockets brotli certifi secretstorage
209           run: |
210             cd repo
211             python3.8 -m pip install -U Pyinstaller secretstorage -r requirements.txt  # Cached version may be out of date
212             python3.8 devscripts/update-version.py -c "${{ inputs.channel }}" -r "${{ needs.process.outputs.origin }}" "${{ inputs.version }}"
213             python3.8 devscripts/make_lazy_extractors.py
214             python3.8 -m bundle.pyinstaller
216             if ${{ vars.UPDATE_TO_VERIFICATION && 'true' || 'false' }}; then
217               arch="${{ (matrix.architecture == 'armv7' && 'armv7l') || matrix.architecture }}"
218               chmod +x ./dist/yt-dlp_linux_${arch}
219               cp ./dist/yt-dlp_linux_${arch} ./dist/yt-dlp_linux_${arch}_downgraded
220               version="$(./dist/yt-dlp_linux_${arch} --version)"
221               ./dist/yt-dlp_linux_${arch}_downgraded -v --update-to yt-dlp/yt-dlp@2023.03.04
222               downgraded_version="$(./dist/yt-dlp_linux_${arch}_downgraded --version)"
223               [[ "$version" != "$downgraded_version" ]]
224             fi
226       - name: Upload artifacts
227         uses: actions/upload-artifact@v3
228         with:
229           path: | # run-on-arch-action designates armv7l as armv7
230             repo/dist/yt-dlp_linux_${{ (matrix.architecture == 'armv7' && 'armv7l') || matrix.architecture }}
232   macos:
233     needs: process
234     if: inputs.macos
235     runs-on: macos-11
237     steps:
238       - uses: actions/checkout@v4
239       # NB: Building universal2 does not work with python from actions/setup-python
240       - name: Install Requirements
241         run: |
242           brew install coreutils
243           python3 -m pip install -U --user pip setuptools wheel
244           # We need to ignore wheels otherwise we break universal2 builds
245           python3 -m pip install -U --user --no-binary :all: Pyinstaller -r requirements.txt
247       - name: Prepare
248         run: |
249           python3 devscripts/update-version.py -c "${{ inputs.channel }}" -r "${{ needs.process.outputs.origin }}" "${{ inputs.version }}"
250           python3 devscripts/make_lazy_extractors.py
251       - name: Build
252         run: |
253           python3 -m bundle.pyinstaller --target-architecture universal2 --onedir
254           (cd ./dist/yt-dlp_macos && zip -r ../yt-dlp_macos.zip .)
255           python3 -m bundle.pyinstaller --target-architecture universal2
257       - name: Verify --update-to
258         if: vars.UPDATE_TO_VERIFICATION
259         run: |
260           chmod +x ./dist/yt-dlp_macos
261           cp ./dist/yt-dlp_macos ./dist/yt-dlp_macos_downgraded
262           version="$(./dist/yt-dlp_macos --version)"
263           ./dist/yt-dlp_macos_downgraded -v --update-to yt-dlp/yt-dlp@2023.03.04
264           downgraded_version="$(./dist/yt-dlp_macos_downgraded --version)"
265           [[ "$version" != "$downgraded_version" ]]
267       - name: Upload artifacts
268         uses: actions/upload-artifact@v3
269         with:
270           path: |
271             dist/yt-dlp_macos
272             dist/yt-dlp_macos.zip
274   macos_legacy:
275     needs: process
276     if: inputs.macos_legacy
277     runs-on: macos-latest
279     steps:
280       - uses: actions/checkout@v4
281       - name: Install Python
282         # We need the official Python, because the GA ones only support newer macOS versions
283         env:
284           PYTHON_VERSION: 3.10.5
285           MACOSX_DEPLOYMENT_TARGET: 10.9 # Used up by the Python build tools
286         run: |
287           # Hack to get the latest patch version. Uncomment if needed
288           #brew install python@3.10
289           #export PYTHON_VERSION=$( $(brew --prefix)/opt/python@3.10/bin/python3 --version | cut -d ' ' -f 2 )
290           curl https://www.python.org/ftp/python/${PYTHON_VERSION}/python-${PYTHON_VERSION}-macos11.pkg -o "python.pkg"
291           sudo installer -pkg python.pkg -target /
292           python3 --version
293       - name: Install Requirements
294         run: |
295           brew install coreutils
296           python3 -m pip install -U --user pip setuptools wheel
297           python3 -m pip install -U --user Pyinstaller -r requirements.txt
299       - name: Prepare
300         run: |
301           python3 devscripts/update-version.py -c "${{ inputs.channel }}" -r "${{ needs.process.outputs.origin }}" "${{ inputs.version }}"
302           python3 devscripts/make_lazy_extractors.py
303       - name: Build
304         run: |
305           python3 -m bundle.pyinstaller
306           mv dist/yt-dlp_macos dist/yt-dlp_macos_legacy
308       - name: Verify --update-to
309         if: vars.UPDATE_TO_VERIFICATION
310         run: |
311           chmod +x ./dist/yt-dlp_macos_legacy
312           cp ./dist/yt-dlp_macos_legacy ./dist/yt-dlp_macos_legacy_downgraded
313           version="$(./dist/yt-dlp_macos_legacy --version)"
314           ./dist/yt-dlp_macos_legacy_downgraded -v --update-to yt-dlp/yt-dlp@2023.03.04
315           downgraded_version="$(./dist/yt-dlp_macos_legacy_downgraded --version)"
316           [[ "$version" != "$downgraded_version" ]]
318       - name: Upload artifacts
319         uses: actions/upload-artifact@v3
320         with:
321           path: |
322             dist/yt-dlp_macos_legacy
324   windows:
325     needs: process
326     if: inputs.windows
327     runs-on: windows-latest
329     steps:
330       - uses: actions/checkout@v4
331       - uses: actions/setup-python@v4
332         with: # 3.8 is used for Win7 support
333           python-version: "3.8"
334       - name: Install Requirements
335         run: | # Custom pyinstaller built with https://github.com/yt-dlp/pyinstaller-builds
336           python -m pip install -U pip setuptools wheel py2exe
337           pip install -U "https://yt-dlp.github.io/Pyinstaller-Builds/x86_64/pyinstaller-5.8.0-py3-none-any.whl" -r requirements.txt
339       - name: Prepare
340         run: |
341           python devscripts/update-version.py -c "${{ inputs.channel }}" -r "${{ needs.process.outputs.origin }}" "${{ inputs.version }}"
342           python devscripts/make_lazy_extractors.py
343       - name: Build
344         run: |
345           python -m bundle.py2exe
346           Move-Item ./dist/yt-dlp.exe ./dist/yt-dlp_min.exe
347           python -m bundle.pyinstaller
348           python -m bundle.pyinstaller --onedir
349           Compress-Archive -Path ./dist/yt-dlp/* -DestinationPath ./dist/yt-dlp_win.zip
351       - name: Verify --update-to
352         if: vars.UPDATE_TO_VERIFICATION
353         run: |
354           foreach ($name in @("yt-dlp","yt-dlp_min")) {
355             Copy-Item "./dist/${name}.exe" "./dist/${name}_downgraded.exe"
356             $version = & "./dist/${name}.exe" --version
357             & "./dist/${name}_downgraded.exe" -v --update-to yt-dlp/yt-dlp@2023.03.04
358             $downgraded_version = & "./dist/${name}_downgraded.exe" --version
359             if ($version -eq $downgraded_version) {
360               exit 1
361             }
362           }
364       - name: Upload artifacts
365         uses: actions/upload-artifact@v3
366         with:
367           path: |
368             dist/yt-dlp.exe
369             dist/yt-dlp_min.exe
370             dist/yt-dlp_win.zip
372   windows32:
373     needs: process
374     if: inputs.windows32
375     runs-on: windows-latest
377     steps:
378       - uses: actions/checkout@v4
379       - uses: actions/setup-python@v4
380         with:
381           python-version: "3.8"
382           architecture: "x86"
383       - name: Install Requirements
384         run: |
385           python -m pip install -U pip setuptools wheel
386           pip install -U "https://yt-dlp.github.io/Pyinstaller-Builds/i686/pyinstaller-5.8.0-py3-none-any.whl" -r requirements.txt
388       - name: Prepare
389         run: |
390           python devscripts/update-version.py -c "${{ inputs.channel }}" -r "${{ needs.process.outputs.origin }}" "${{ inputs.version }}"
391           python devscripts/make_lazy_extractors.py
392       - name: Build
393         run: |
394           python -m bundle.pyinstaller
396       - name: Verify --update-to
397         if: vars.UPDATE_TO_VERIFICATION
398         run: |
399           foreach ($name in @("yt-dlp_x86")) {
400             Copy-Item "./dist/${name}.exe" "./dist/${name}_downgraded.exe"
401             $version = & "./dist/${name}.exe" --version
402             & "./dist/${name}_downgraded.exe" -v --update-to yt-dlp/yt-dlp@2023.03.04
403             $downgraded_version = & "./dist/${name}_downgraded.exe" --version
404             if ($version -eq $downgraded_version) {
405               exit 1
406             }
407           }
409       - name: Upload artifacts
410         uses: actions/upload-artifact@v3
411         with:
412           path: |
413             dist/yt-dlp_x86.exe
415   meta_files:
416     if: inputs.meta_files && always() && !cancelled()
417     needs:
418       - process
419       - unix
420       - linux_arm
421       - macos
422       - macos_legacy
423       - windows
424       - windows32
425     runs-on: ubuntu-latest
426     steps:
427       - uses: actions/download-artifact@v3
429       - name: Make SHA2-SUMS files
430         run: |
431           cd ./artifact/
432           sha256sum * > ../SHA2-256SUMS
433           sha512sum * > ../SHA2-512SUMS
435       - name: Make Update spec
436         run: |
437           cat >> _update_spec << EOF
438           # This file is used for regulating self-update
439           lock 2022.08.18.36 .+ Python 3\.6
440           lock 2023.11.16 (?!win_x86_exe).+ Python 3\.7
441           lock 2023.11.16 win_x86_exe .+ Windows-(?:Vista|2008Server)
442           lockV2 yt-dlp/yt-dlp 2022.08.18.36 .+ Python 3\.6
443           lockV2 yt-dlp/yt-dlp 2023.11.16 (?!win_x86_exe).+ Python 3\.7
444           lockV2 yt-dlp/yt-dlp 2023.11.16 win_x86_exe .+ Windows-(?:Vista|2008Server)
445           lockV2 yt-dlp/yt-dlp-nightly-builds 2023.11.15.232826 (?!win_x86_exe).+ Python 3\.7
446           lockV2 yt-dlp/yt-dlp-nightly-builds 2023.11.15.232826 win_x86_exe .+ Windows-(?:Vista|2008Server)
447           lockV2 yt-dlp/yt-dlp-master-builds 2023.11.15.232812 (?!win_x86_exe).+ Python 3\.7
448           lockV2 yt-dlp/yt-dlp-master-builds 2023.11.15.232812 win_x86_exe .+ Windows-(?:Vista|2008Server)
449           EOF
451       - name: Sign checksum files
452         env:
453           GPG_SIGNING_KEY: ${{ secrets.GPG_SIGNING_KEY }}
454         if: env.GPG_SIGNING_KEY != ''
455         run: |
456           gpg --batch --import <<< "${{ secrets.GPG_SIGNING_KEY }}"
457           for signfile in ./SHA*SUMS; do
458             gpg --batch --detach-sign "$signfile"
459           done
461       - name: Upload artifacts
462         uses: actions/upload-artifact@v3
463         with:
464           path: |
465             SHA*SUMS*
466             _update_spec