mirror of
https://github.com/ytdl-org/youtube-dl.git
synced 2024-11-28 13:11:49 +00:00
[ci] Implement release workflow
This commit is contained in:
parent
16f5bbc464
commit
a2eb11b428
4 changed files with 463 additions and 0 deletions
170
.github/workflows/build.yml
vendored
Normal file
170
.github/workflows/build.yml
vendored
Normal file
|
@ -0,0 +1,170 @@
|
||||||
|
name: Build Artifacts
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
inputs:
|
||||||
|
version:
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
unix:
|
||||||
|
default: true
|
||||||
|
type: boolean
|
||||||
|
windows32:
|
||||||
|
default: true
|
||||||
|
type: boolean
|
||||||
|
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
version:
|
||||||
|
description: |
|
||||||
|
VERSION: yyyy.mm.dd[.rev] or rev
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
unix:
|
||||||
|
description: youtube-dl, youtube-dl.tar.gz
|
||||||
|
default: true
|
||||||
|
type: boolean
|
||||||
|
windows32:
|
||||||
|
description: youtube-dl.exe
|
||||||
|
default: true
|
||||||
|
type: boolean
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
unix:
|
||||||
|
if: inputs.unix
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0 # Needed for changelog
|
||||||
|
|
||||||
|
- uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "3.9"
|
||||||
|
|
||||||
|
- name: Install Requirements
|
||||||
|
run: |
|
||||||
|
sudo apt -y install zip pandoc man sed
|
||||||
|
|
||||||
|
- name: Prepare
|
||||||
|
run: |
|
||||||
|
python devscripts/update_version.py "${{ inputs.version }}"
|
||||||
|
python devscripts/changelog.py --update
|
||||||
|
python devscripts/make_lazy_extractors.py youtube_dl/extractor/lazy_extractors.py
|
||||||
|
|
||||||
|
- name: Build Unix platform-independent binary
|
||||||
|
run: |
|
||||||
|
make all tar
|
||||||
|
|
||||||
|
- name: Upload artifacts
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: build-bin-${{ github.job }}
|
||||||
|
path: |
|
||||||
|
youtube-dl
|
||||||
|
youtube-dl.tar.gz
|
||||||
|
compression-level: 0
|
||||||
|
|
||||||
|
windows32:
|
||||||
|
if: inputs.windows32
|
||||||
|
runs-on: windows-2022
|
||||||
|
env:
|
||||||
|
PYCRYPTO: pycrypto-2.6.1-cp34-none-win32
|
||||||
|
# Temporary workaround for Python 3.4/5 failures - May 2024
|
||||||
|
PIP_TRUSTED_HOST: "pypi.python.org pypi.org files.pythonhosted.org"
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Python 3.4
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "3.4"
|
||||||
|
architecture: x86
|
||||||
|
|
||||||
|
- name: Install packages
|
||||||
|
# https://pip.pypa.io/en/stable/news/#v19-2
|
||||||
|
# https://setuptools.pypa.io/en/latest/history.html#v44-0-0
|
||||||
|
# https://wheel.readthedocs.io/en/stable/news.html
|
||||||
|
# https://pypi.org/project/py2exe/0.9.2.2
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
python -m pip install --upgrade \
|
||||||
|
"pip<19.2" \
|
||||||
|
"setuptools<44" \
|
||||||
|
"wheel<0.34.0" \
|
||||||
|
"py2exe==0.9.2.2" \
|
||||||
|
;
|
||||||
|
|
||||||
|
- name: PyCrypto cache
|
||||||
|
id: cache_pycrypto
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
key: ${{ env.PYCRYPTO }}
|
||||||
|
path: ./${{ env.PYCRYPTO }}
|
||||||
|
|
||||||
|
- name: PyCrypto download
|
||||||
|
if: |
|
||||||
|
steps.cache_pycrypto.outputs.cache-hit != 'true'
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
mkdir -p "${PYCRYPTO}"
|
||||||
|
cd "${PYCRYPTO}"
|
||||||
|
curl -L -O "https://web.archive.org/web/20200627032153/http://www.voidspace.org.uk/python/pycrypto-2.6.1/${PYCRYPTO}.whl"
|
||||||
|
|
||||||
|
- name: PyCrypto install
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
python -m pip install "./${PYCRYPTO}/${PYCRYPTO}.whl"
|
||||||
|
|
||||||
|
- name: Prepare
|
||||||
|
run: |
|
||||||
|
python devscripts/update_version.py "${{ inputs.version }}"
|
||||||
|
python devscripts/make_lazy_extractors.py youtube_dl/extractor/lazy_extractors.py
|
||||||
|
|
||||||
|
- name: Build binary
|
||||||
|
run: python setup.py py2exe
|
||||||
|
|
||||||
|
- name: Upload artifacts
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: build-bin-${{ github.job }}
|
||||||
|
path: |
|
||||||
|
youtube-dl.exe
|
||||||
|
compression-level: 0
|
||||||
|
|
||||||
|
meta_files:
|
||||||
|
if: always() && !cancelled()
|
||||||
|
needs:
|
||||||
|
- unix
|
||||||
|
- windows32
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
path: artifact
|
||||||
|
pattern: build-bin-*
|
||||||
|
merge-multiple: true
|
||||||
|
|
||||||
|
- name: Make SHA2-SUMS files
|
||||||
|
run: |
|
||||||
|
cd ./artifact/
|
||||||
|
# make sure SHA sums are also printed to stdout
|
||||||
|
sha256sum -- * | tee ../SHA2-256SUMS
|
||||||
|
sha512sum -- * | tee ../SHA2-512SUMS
|
||||||
|
# also print as permanent annotations to the summary page
|
||||||
|
while read -r shasum; do
|
||||||
|
echo "::notice title=${shasum##* }::sha256: ${shasum% *}"
|
||||||
|
done < ../SHA2-256SUMS
|
||||||
|
|
||||||
|
- name: Upload artifacts
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: build-${{ github.job }}
|
||||||
|
path: |
|
||||||
|
SHA*SUMS*
|
||||||
|
compression-level: 0
|
||||||
|
overwrite: true
|
147
.github/workflows/release.yml
vendored
Normal file
147
.github/workflows/release.yml
vendored
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
name: Release
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
version:
|
||||||
|
description: |
|
||||||
|
VERSION: yyyy.mm.dd[.rev] or rev
|
||||||
|
(default: auto-generated)
|
||||||
|
required: false
|
||||||
|
default: ""
|
||||||
|
type: string
|
||||||
|
prerelease:
|
||||||
|
description: Pre-release
|
||||||
|
default: false
|
||||||
|
type: boolean
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
prepare:
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
version: ${{ steps.setup_variables.outputs.version }}
|
||||||
|
head_sha: ${{ steps.get_target.outputs.head_sha }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "3.10"
|
||||||
|
|
||||||
|
- name: Setup variables
|
||||||
|
id: setup_variables
|
||||||
|
run: |
|
||||||
|
revision="${{ (inputs.prerelease || !vars.PUSH_VERSION_COMMIT) && '$(date -u +"%H%M%S")' || '' }}"
|
||||||
|
version="$(
|
||||||
|
python devscripts/update_version.py \
|
||||||
|
${{ inputs.version || '"${revision}"' }} )"
|
||||||
|
echo "::group::Output variables"
|
||||||
|
cat << EOF | tee -a "$GITHUB_OUTPUT"
|
||||||
|
version=${version}
|
||||||
|
EOF
|
||||||
|
echo "::endgroup::"
|
||||||
|
|
||||||
|
- name: Update documentation
|
||||||
|
env:
|
||||||
|
version: ${{ steps.setup_variables.outputs.version }}
|
||||||
|
target_repo: ${{ steps.setup_variables.outputs.target_repo }}
|
||||||
|
if: |
|
||||||
|
!inputs.prerelease
|
||||||
|
run: |
|
||||||
|
python devscripts/changelog.py --update
|
||||||
|
make README.md
|
||||||
|
make issuetemplates
|
||||||
|
make supportedsites
|
||||||
|
|
||||||
|
- name: Push to release
|
||||||
|
id: push_release
|
||||||
|
env:
|
||||||
|
version: ${{ steps.setup_variables.outputs.version }}
|
||||||
|
creator: ${{ github.event.sender.login }}
|
||||||
|
if: |
|
||||||
|
!inputs.prerelease
|
||||||
|
run: |
|
||||||
|
git config --global user.name "github-actions[bot]"
|
||||||
|
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||||
|
git add -u
|
||||||
|
git commit -m "Release ${version}" \
|
||||||
|
-m "Created by: ${creator}" \
|
||||||
|
-m ":ci skip all"
|
||||||
|
git push origin --force master:release
|
||||||
|
|
||||||
|
- name: Get target commitish
|
||||||
|
id: get_target
|
||||||
|
run: |
|
||||||
|
echo "head_sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
- name: Update master
|
||||||
|
env:
|
||||||
|
target_repo: ${{ steps.setup_variables.outputs.target_repo }}
|
||||||
|
if: |
|
||||||
|
vars.PUSH_VERSION_COMMIT != '' && !inputs.prerelease
|
||||||
|
run: |
|
||||||
|
git push origin ${{ github.event.ref }}
|
||||||
|
|
||||||
|
build:
|
||||||
|
needs: prepare
|
||||||
|
uses: ./.github/workflows/build.yml
|
||||||
|
with:
|
||||||
|
version: ${{ needs.prepare.outputs.version }}
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
publish:
|
||||||
|
needs: [prepare, build]
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
path: artifact
|
||||||
|
pattern: build-*
|
||||||
|
merge-multiple: true
|
||||||
|
|
||||||
|
- uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "3.10"
|
||||||
|
|
||||||
|
- name: Generate release notes
|
||||||
|
run: |
|
||||||
|
cat >> ./RELEASE_NOTES << EOF
|
||||||
|
<details><summary><h3>Changelog</h3></summary>
|
||||||
|
|
||||||
|
$(python devscripts/changelog.py)
|
||||||
|
|
||||||
|
</details>
|
||||||
|
EOF
|
||||||
|
cat > ./PRERELEASE_NOTES << EOF
|
||||||
|
**This is a pre-release build**
|
||||||
|
---
|
||||||
|
|
||||||
|
$(cat ./RELEASE_NOTES)
|
||||||
|
EOF
|
||||||
|
|
||||||
|
- name: Publish release
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ github.token }}
|
||||||
|
version: ${{ needs.prepare.outputs.version }}
|
||||||
|
head_sha: ${{ needs.prepare.outputs.head_sha }}
|
||||||
|
run: |
|
||||||
|
gh release create \
|
||||||
|
--notes-file ${{ inputs.prerelease && 'PRERELEASE_NOTES' || 'RELEASE_NOTES' }} \
|
||||||
|
--target ${{ env.head_sha }} \
|
||||||
|
--title "youtube-dl ${version}" \
|
||||||
|
${{ inputs.prerelease && '--prerelease' || '' }} \
|
||||||
|
"${version}" \
|
||||||
|
artifact/*
|
100
devscripts/changelog.py
Executable file
100
devscripts/changelog.py
Executable file
|
@ -0,0 +1,100 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
def run(args):
|
||||||
|
process = subprocess.Popen(args, stdout=subprocess.PIPE, universal_newlines=True)
|
||||||
|
return process.communicate()[0].strip()
|
||||||
|
|
||||||
|
|
||||||
|
def is_core(short):
|
||||||
|
prefix = None
|
||||||
|
if ']' in short:
|
||||||
|
prefix = short.partition(']')[0][1:]
|
||||||
|
elif ': ' in short:
|
||||||
|
prefix = short.partition(': ')[0]
|
||||||
|
|
||||||
|
if not prefix or ' ' in prefix:
|
||||||
|
return True
|
||||||
|
|
||||||
|
prefix = prefix.partition(':')[0].lower()
|
||||||
|
if prefix.startswith('extractor/'):
|
||||||
|
prefix = prefix[len('extractor/'):]
|
||||||
|
if prefix.endswith('ie'):
|
||||||
|
prefix = prefix[:-len('ie')]
|
||||||
|
return not os.path.exists('youtube_dl/extractor/%s.py' % prefix)
|
||||||
|
|
||||||
|
|
||||||
|
def format_line(markdown, short, sha):
|
||||||
|
if not markdown:
|
||||||
|
return '* ' + short
|
||||||
|
|
||||||
|
return '* [%s](https://github.com/ytdl-org/youtube-dl/commit/%s)' % (short, sha)
|
||||||
|
|
||||||
|
|
||||||
|
def generate_changelog(markdown):
|
||||||
|
most_recent_tag = run([
|
||||||
|
'git', 'tag', '--list', '--sort=-v:refname',
|
||||||
|
'????.??.??', '????.??.??.?',
|
||||||
|
]).split('\n')[0]
|
||||||
|
lines = run([
|
||||||
|
'git', 'log',
|
||||||
|
'--format=format:%H%n%s', '--no-merges', '-z',
|
||||||
|
most_recent_tag + '..HEAD',
|
||||||
|
]).split('\x00')
|
||||||
|
|
||||||
|
core = []
|
||||||
|
extractor = []
|
||||||
|
for line in lines:
|
||||||
|
if not line:
|
||||||
|
continue
|
||||||
|
sha, short = line.split('\n')
|
||||||
|
|
||||||
|
if ' * ' in short:
|
||||||
|
short = short.partition(' * ')[0]
|
||||||
|
|
||||||
|
target = core if is_core(short) else extractor
|
||||||
|
target.append((sha, short))
|
||||||
|
|
||||||
|
result = []
|
||||||
|
if core:
|
||||||
|
result.append('#### Core' if markdown else 'Core')
|
||||||
|
for sha, short in core:
|
||||||
|
result.append(format_line(markdown, short, sha))
|
||||||
|
result.append('')
|
||||||
|
|
||||||
|
if extractor:
|
||||||
|
result.append('#### Extractor' if markdown else 'Extractor')
|
||||||
|
for sha, short in extractor:
|
||||||
|
result.append(format_line(markdown, short, sha))
|
||||||
|
result.append('')
|
||||||
|
|
||||||
|
return '\n'.join(result)
|
||||||
|
|
||||||
|
|
||||||
|
def read_version():
|
||||||
|
with open('youtube_dl/version.py', 'r') as f:
|
||||||
|
exec(compile(f.read(), 'youtube_dl/version.py', 'exec'))
|
||||||
|
|
||||||
|
return locals()['__version__']
|
||||||
|
|
||||||
|
|
||||||
|
update_in_place = len(sys.argv) > 1 and sys.argv[1] == '--update'
|
||||||
|
changelog = generate_changelog(not update_in_place)
|
||||||
|
|
||||||
|
if not update_in_place:
|
||||||
|
print(changelog)
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
|
with open('ChangeLog', 'rb') as file:
|
||||||
|
data = file.read()
|
||||||
|
|
||||||
|
with open('ChangeLog', 'wb') as file:
|
||||||
|
file.write(('version %s\n\n' % read_version()).encode('utf-8'))
|
||||||
|
file.write(changelog.encode('utf-8'))
|
||||||
|
file.write('\n\n'.encode('utf-8'))
|
||||||
|
file.write(data)
|
46
devscripts/update_version.py
Executable file
46
devscripts/update_version.py
Executable file
|
@ -0,0 +1,46 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import datetime as dt
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
VERSION_FILE_FORMAT = '''\
|
||||||
|
# Autogenerated by devscripts/update_version.py
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
__version__ = {!r}
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
def split_version(version):
|
||||||
|
if '.' not in version:
|
||||||
|
return None, version
|
||||||
|
|
||||||
|
version_list = version.split('.')
|
||||||
|
version = '.'.join(version_list[:3])
|
||||||
|
revision = version_list[3] if len(version_list) > 3 else None
|
||||||
|
|
||||||
|
return version, revision
|
||||||
|
|
||||||
|
|
||||||
|
with open('youtube_dl/version.py', 'r') as f:
|
||||||
|
exec(compile(f.read(), 'youtube_dl/version.py', 'exec'))
|
||||||
|
|
||||||
|
old_ver, old_rev = split_version(locals()['__version__'])
|
||||||
|
ver, rev = split_version(sys.argv[1]) if len(sys.argv) > 1 else (None, None)
|
||||||
|
|
||||||
|
if not ver:
|
||||||
|
ver = (
|
||||||
|
dt.datetime.now(dt.timezone.utc) if sys.version_info >= (3,)
|
||||||
|
else dt.datetime.utcnow()).strftime('%Y.%m.%d')
|
||||||
|
if not rev and old_ver == ver:
|
||||||
|
rev = str(int(old_rev or 0) + 1)
|
||||||
|
|
||||||
|
if rev:
|
||||||
|
ver = ver + '.' + rev
|
||||||
|
|
||||||
|
with open('youtube_dl/version.py', 'w') as f:
|
||||||
|
f.write(VERSION_FILE_FORMAT.format(ver))
|
||||||
|
|
||||||
|
print(ver)
|
Loading…
Reference in a new issue