Release #16
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: Release | |
on: | |
workflow_call: | |
inputs: | |
prerelease: | |
required: false | |
default: true | |
type: boolean | |
source: | |
required: false | |
default: '' | |
type: string | |
target: | |
required: false | |
default: '' | |
type: string | |
version: | |
required: false | |
default: '' | |
type: string | |
workflow_dispatch: | |
inputs: | |
source: | |
description: | | |
SOURCE of this release's updates: | |
channel, repo, tag, or channel/repo@tag | |
(default: <current_repo>) | |
required: false | |
default: '' | |
type: string | |
target: | |
description: | | |
TARGET to publish this release to: | |
channel, tag, or channel@tag | |
(default: <source> if writable else <current_repo>[@source_tag]) | |
required: false | |
default: '' | |
type: string | |
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 | |
permissions: | |
contents: read | |
jobs: | |
prepare: | |
permissions: | |
contents: write | |
runs-on: ubuntu-latest | |
outputs: | |
channel: ${{ steps.setup_variables.outputs.channel }} | |
version: ${{ steps.setup_variables.outputs.version }} | |
target_repo: ${{ steps.setup_variables.outputs.target_repo }} | |
target_repo_token: ${{ steps.setup_variables.outputs.target_repo_token }} | |
target_tag: ${{ steps.setup_variables.outputs.target_tag }} | |
pypi_project: ${{ steps.setup_variables.outputs.pypi_project }} | |
pypi_suffix: ${{ steps.setup_variables.outputs.pypi_suffix }} | |
head_sha: ${{ steps.get_target.outputs.head_sha }} | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 | |
- uses: actions/setup-python@v4 | |
with: | |
python-version: "3.10" | |
- name: Process inputs | |
id: process_inputs | |
run: | | |
cat << EOF | |
::group::Inputs | |
prerelease=${{ inputs.prerelease }} | |
source=${{ inputs.source }} | |
target=${{ inputs.target }} | |
version=${{ inputs.version }} | |
::endgroup:: | |
EOF | |
IFS='@' read -r source_repo source_tag <<<"${{ inputs.source }}" | |
IFS='@' read -r target_repo target_tag <<<"${{ inputs.target }}" | |
cat << EOF >> "$GITHUB_OUTPUT" | |
source_repo=${source_repo} | |
source_tag=${source_tag} | |
target_repo=${target_repo} | |
target_tag=${target_tag} | |
EOF | |
- name: Setup variables | |
id: setup_variables | |
env: | |
source_repo: ${{ steps.process_inputs.outputs.source_repo }} | |
source_tag: ${{ steps.process_inputs.outputs.source_tag }} | |
target_repo: ${{ steps.process_inputs.outputs.target_repo }} | |
target_tag: ${{ steps.process_inputs.outputs.target_tag }} | |
run: | | |
# unholy bash monstrosity (sincere apologies) | |
fallback_token () { | |
if ${{ !secrets.ARCHIVE_REPO_TOKEN }}; then | |
echo "::error::Repository access secret ${target_repo_token^^} not found" | |
exit 1 | |
fi | |
target_repo_token=ARCHIVE_REPO_TOKEN | |
return 0 | |
} | |
source_is_channel=0 | |
[[ "${source_repo}" == 'stable' ]] && source_repo='yt-dlp/yt-dlp' | |
if [[ -z "${source_repo}" ]]; then | |
source_repo='${{ github.repository }}' | |
elif [[ '${{ vars[format('{0}_archive_repo', env.source_repo)] }}' ]]; then | |
source_is_channel=1 | |
source_channel='${{ vars[format('{0}_archive_repo', env.source_repo)] }}' | |
elif [[ -z "${source_tag}" && "${source_repo}" != */* ]]; then | |
source_tag="${source_repo}" | |
source_repo='${{ github.repository }}' | |
fi | |
resolved_source="${source_repo}" | |
if [[ "${source_tag}" ]]; then | |
resolved_source="${resolved_source}@${source_tag}" | |
elif [[ "${source_repo}" == 'yt-dlp/yt-dlp' ]]; then | |
resolved_source='stable' | |
fi | |
revision="${{ (inputs.prerelease || !vars.PUSH_VERSION_COMMIT) && '$(date -u +"%H%M%S")' || '' }}" | |
version="$( | |
python devscripts/update-version.py \ | |
-c "${resolved_source}" -r "${{ github.repository }}" ${{ inputs.version || '$revision' }} | \ | |
grep -Po "version=\K\d+\.\d+\.\d+(\.\d+)?")" | |
if [[ "${target_repo}" ]]; then | |
if [[ -z "${target_tag}" ]]; then | |
if [[ '${{ vars[format('{0}_archive_repo', env.target_repo)] }}' ]]; then | |
target_tag="${source_tag:-${version}}" | |
else | |
target_tag="${target_repo}" | |
target_repo='${{ github.repository }}' | |
fi | |
fi | |
if [[ "${target_repo}" != '${{ github.repository}}' ]]; then | |
target_repo='${{ vars[format('{0}_archive_repo', env.target_repo)] }}' | |
target_repo_token='${{ env.target_repo }}_archive_repo_token' | |
${{ !!secrets[format('{0}_archive_repo_token', env.target_repo)] }} || fallback_token | |
pypi_project='${{ vars[format('{0}_pypi_project', env.target_repo)] }}' | |
pypi_suffix='${{ vars[format('{0}_pypi_suffix', env.target_repo)] }}' | |
fi | |
else | |
target_tag="${source_tag:-${version}}" | |
if ((source_is_channel)); then | |
target_repo="${source_channel}" | |
target_repo_token='${{ env.source_repo }}_archive_repo_token' | |
${{ !!secrets[format('{0}_archive_repo_token', env.source_repo)] }} || fallback_token | |
pypi_project='${{ vars[format('{0}_pypi_project', env.source_repo)] }}' | |
pypi_suffix='${{ vars[format('{0}_pypi_suffix', env.source_repo)] }}' | |
else | |
target_repo='${{ github.repository }}' | |
fi | |
fi | |
if [[ "${target_repo}" == '${{ github.repository }}' ]] && ${{ !inputs.prerelease }}; then | |
pypi_project='${{ vars.PYPI_PROJECT }}' | |
fi | |
echo "::group::Output variables" | |
cat << EOF | tee -a "$GITHUB_OUTPUT" | |
channel=${resolved_source} | |
version=${version} | |
target_repo=${target_repo} | |
target_repo_token=${target_repo_token} | |
target_tag=${target_tag} | |
pypi_project=${pypi_project} | |
pypi_suffix=${pypi_suffix} | |
EOF | |
echo "::endgroup::" | |
- name: Update documentation | |
env: | |
version: ${{ steps.setup_variables.outputs.version }} | |
target_repo: ${{ steps.setup_variables.outputs.target_repo }} | |
if: | | |
!inputs.prerelease && env.target_repo == github.repository | |
run: | | |
make doc | |
sed '/### /Q' Changelog.md >> ./CHANGELOG | |
echo '### ${{ env.version }}' >> ./CHANGELOG | |
python ./devscripts/make_changelog.py -vv -c >> ./CHANGELOG | |
echo >> ./CHANGELOG | |
grep -Poz '(?s)### \d+\.\d+\.\d+.+' 'Changelog.md' | head -n -1 >> ./CHANGELOG | |
cat ./CHANGELOG > Changelog.md | |
- name: Push to release | |
id: push_release | |
env: | |
version: ${{ steps.setup_variables.outputs.version }} | |
target_repo: ${{ steps.setup_variables.outputs.target_repo }} | |
if: | | |
!inputs.prerelease && env.target_repo == github.repository | |
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 ${{ env.version }}" \ | |
-m "Created by: ${{ github.event.sender.login }}" -m ":ci skip all :ci run dl" | |
git push origin --force ${{ github.event.ref }}: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 && env.target_repo == github.repository | |
run: git push origin ${{ github.event.ref }} | |
build: | |
needs: prepare | |
uses: ./.github/workflows/build.yml | |
with: | |
version: ${{ needs.prepare.outputs.version }} | |
channel: ${{ needs.prepare.outputs.channel }} | |
origin: ${{ needs.prepare.outputs.target_repo }} | |
permissions: | |
contents: read | |
packages: write # For package cache | |
secrets: | |
GPG_SIGNING_KEY: ${{ secrets.GPG_SIGNING_KEY }} | |
publish: | |
needs: [prepare, build] | |
permissions: | |
contents: write | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 | |
- uses: actions/download-artifact@v3 | |
- uses: actions/setup-python@v4 | |
with: | |
python-version: "3.10" | |
- name: Generate release notes | |
env: | |
head_sha: ${{ needs.prepare.outputs.head_sha }} | |
target_repo: ${{ needs.prepare.outputs.target_repo }} | |
target_tag: ${{ needs.prepare.outputs.target_tag }} | |
run: | | |
printf '%s' \ | |
'[![Installation](https://img.shields.io/badge/-Which%20file%20should%20I%20download%3F-white.svg?style=for-the-badge)]' \ | |
'(https://github.com/${{ github.repository }}#installation "Installation instructions") ' \ | |
'[![Documentation](https://img.shields.io/badge/-Docs-brightgreen.svg?style=for-the-badge&logo=GitBook&labelColor=555555)]' \ | |
'(https://github.com/${{ github.repository }}' \ | |
'${{ env.target_repo == github.repository && format('/tree/{0}', env.target_tag) || '' }}#readme "Documentation") ' \ | |
'[![Donate](https://img.shields.io/badge/_-Donate-red.svg?logo=githubsponsors&labelColor=555555&style=for-the-badge)]' \ | |
'(https://github.com/yt-dlp/yt-dlp/blob/master/Collaborators.md#collaborators "Donate") ' \ | |
'[![Discord](https://img.shields.io/discord/807245652072857610?color=blue&labelColor=555555&label=&logo=discord&style=for-the-badge)]' \ | |
'(https://discord.gg/H5MNcFW63r "Discord") ' \ | |
${{ env.target_repo == 'yt-dlp/yt-dlp' && '\ | |
"[![Nightly](https://img.shields.io/badge/Get%20nightly%20builds-purple.svg?style=for-the-badge)]" \ | |
"(https://github.com/yt-dlp/yt-dlp-nightly-builds/releases/latest \"Nightly builds\") " \ | |
"[![Master](https://img.shields.io/badge/Get%20master%20builds-lightblue.svg?style=for-the-badge)]" \ | |
"(https://github.com/yt-dlp/yt-dlp-master-builds/releases/latest \"Master builds\")"' || '' }} > ./RELEASE_NOTES | |
printf '\n\n' >> ./RELEASE_NOTES | |
cat >> ./RELEASE_NOTES << EOF | |
#### A description of the various files are in the [README](https://github.com/${{ github.repository }}#release-files) | |
--- | |
$(python ./devscripts/make_changelog.py -vv --collapsible) | |
EOF | |
printf '%s\n\n' '**This is a pre-release build**' >> ./PRERELEASE_NOTES | |
cat ./RELEASE_NOTES >> ./PRERELEASE_NOTES | |
printf '%s\n\n' 'Generated from: https://github.com/${{ github.repository }}/commit/${{ env.head_sha }}' >> ./ARCHIVE_NOTES | |
cat ./RELEASE_NOTES >> ./ARCHIVE_NOTES | |
- name: Publish to archive repo | |
env: | |
GH_TOKEN: ${{ secrets[needs.prepare.outputs.target_repo_token] }} | |
GH_REPO: ${{ needs.prepare.outputs.target_repo }} | |
version: ${{ needs.prepare.outputs.version }} | |
channel: ${{ needs.prepare.outputs.channel }} | |
if: | | |
inputs.prerelease && env.GH_TOKEN != '' && env.GH_REPO != '' && env.GH_REPO != github.repository | |
run: | | |
title="${{ startswith(env.GH_REPO, 'yt-dlp/') && 'yt-dlp ' || '' }}${{ env.channel }}" | |
gh release create \ | |
--notes-file ARCHIVE_NOTES \ | |
--title "${title} ${{ env.version }}" \ | |
${{ env.version }} \ | |
artifact/* | |
- name: Prune old release | |
env: | |
GH_TOKEN: ${{ github.token }} | |
version: ${{ needs.prepare.outputs.version }} | |
target_repo: ${{ needs.prepare.outputs.target_repo }} | |
target_tag: ${{ needs.prepare.outputs.target_tag }} | |
if: | | |
env.target_repo == github.repository && env.target_tag != env.version | |
run: | | |
gh release delete --yes --cleanup-tag "${{ env.target_tag }}" || true | |
git tag --delete "${{ env.target_tag }}" || true | |
sleep 5 # Enough time to cover deletion race condition | |
- name: Publish release | |
env: | |
GH_TOKEN: ${{ github.token }} | |
version: ${{ needs.prepare.outputs.version }} | |
target_repo: ${{ needs.prepare.outputs.target_repo }} | |
target_tag: ${{ needs.prepare.outputs.target_tag }} | |
head_sha: ${{ needs.prepare.outputs.head_sha }} | |
if: | | |
env.target_repo == github.repository | |
run: | | |
title="${{ github.repository == 'yt-dlp/yt-dlp' && 'yt-dlp ' || '' }}" | |
title+="${{ env.target_tag != env.version && format('{0} ', env.target_tag) || '' }}" | |
gh release create \ | |
--notes-file ${{ inputs.prerelease && 'PRERELEASE_NOTES' || 'RELEASE_NOTES' }} \ | |
--target ${{ env.head_sha }} \ | |
--title "${title}${{ env.version }}" \ | |
${{ inputs.prerelease && '--prerelease' || '' }} \ | |
${{ env.target_tag }} \ | |
artifact/* |