Release #96
This file contains hidden or 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: | |
| source: | |
| required: false | |
| default: '' | |
| type: string | |
| target: | |
| required: false | |
| default: '' | |
| type: string | |
| version: | |
| required: false | |
| default: '' | |
| type: string | |
| linux_armv7l: | |
| required: false | |
| default: false | |
| type: boolean | |
| prerelease: | |
| required: false | |
| default: true | |
| type: boolean | |
| 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 | |
| linux_armv7l: | |
| description: Include linux_armv7l | |
| default: true | |
| type: boolean | |
| 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@v5 | |
| with: | |
| fetch-depth: 0 | |
| - uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.10" # Keep this in sync with test-workflows.yml | |
| - name: Process inputs | |
| id: process_inputs | |
| env: | |
| INPUTS: ${{ toJSON(inputs) }} | |
| run: | | |
| python -m devscripts.setup_variables process_inputs | |
| - name: Setup variables | |
| id: setup_variables | |
| env: | |
| INPUTS: ${{ toJSON(inputs) }} | |
| PROCESSED: ${{ toJSON(steps.process_inputs.outputs) }} | |
| REPOSITORY: ${{ github.repository }} | |
| PUSH_VERSION_COMMIT: ${{ vars.PUSH_VERSION_COMMIT }} | |
| PYPI_PROJECT: ${{ vars.PYPI_PROJECT }} | |
| SOURCE_PYPI_PROJECT: ${{ vars[format('{0}_pypi_project', steps.process_inputs.outputs.source_repo)] }} | |
| SOURCE_PYPI_SUFFIX: ${{ vars[format('{0}_pypi_suffix', steps.process_inputs.outputs.source_repo)] }} | |
| TARGET_PYPI_PROJECT: ${{ vars[format('{0}_pypi_project', steps.process_inputs.outputs.target_repo)] }} | |
| TARGET_PYPI_SUFFIX: ${{ vars[format('{0}_pypi_suffix', steps.process_inputs.outputs.target_repo)] }} | |
| SOURCE_ARCHIVE_REPO: ${{ vars[format('{0}_archive_repo', steps.process_inputs.outputs.source_repo)] }} | |
| TARGET_ARCHIVE_REPO: ${{ vars[format('{0}_archive_repo', steps.process_inputs.outputs.target_repo)] }} | |
| HAS_SOURCE_ARCHIVE_REPO_TOKEN: ${{ !!secrets[format('{0}_archive_repo_token', steps.process_inputs.outputs.source_repo)] }} | |
| HAS_TARGET_ARCHIVE_REPO_TOKEN: ${{ !!secrets[format('{0}_archive_repo_token', steps.process_inputs.outputs.target_repo)] }} | |
| HAS_ARCHIVE_REPO_TOKEN: ${{ !!secrets.ARCHIVE_REPO_TOKEN }} | |
| run: | | |
| python -m devscripts.setup_variables | |
| - name: Update version & documentation | |
| env: | |
| CHANNEL: ${{ steps.setup_variables.outputs.channel }} | |
| # Use base repo since this could be committed; build jobs will call this again with true origin | |
| REPOSITORY: ${{ github.repository }} | |
| VERSION: ${{ steps.setup_variables.outputs.version }} | |
| run: | | |
| python devscripts/update-version.py -c "${CHANNEL}" -r "${REPOSITORY}" "${VERSION}" | |
| python devscripts/update_changelog.py -vv | |
| make doc | |
| - name: Push to release | |
| id: push_release | |
| env: | |
| VERSION: ${{ steps.setup_variables.outputs.version }} | |
| GITHUB_EVENT_SENDER_LOGIN: ${{ github.event.sender.login }} | |
| GITHUB_EVENT_REF: ${{ github.event.ref }} | |
| if: | | |
| !inputs.prerelease && steps.setup_variables.outputs.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 ${VERSION}" \ | |
| -m "Created by: ${GITHUB_EVENT_SENDER_LOGIN}" -m ":ci skip all" | |
| 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: | |
| GITHUB_EVENT_REF: ${{ github.event.ref }} | |
| if: | | |
| vars.PUSH_VERSION_COMMIT && !inputs.prerelease && steps.setup_variables.outputs.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 }} | |
| linux_armv7l: ${{ inputs.linux_armv7l }} | |
| permissions: | |
| contents: read | |
| secrets: | |
| GPG_SIGNING_KEY: ${{ secrets.GPG_SIGNING_KEY }} | |
| publish_pypi: | |
| needs: [prepare, build] | |
| if: ${{ needs.prepare.outputs.pypi_project }} | |
| runs-on: ubuntu-latest | |
| permissions: | |
| id-token: write # mandatory for trusted publishing | |
| steps: | |
| - uses: actions/checkout@v5 | |
| with: | |
| fetch-depth: 0 | |
| - uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.10" | |
| - name: Install Requirements | |
| run: | | |
| sudo apt -y install pandoc man | |
| python devscripts/install_deps.py --only-optional-groups --include-group build | |
| - name: Prepare | |
| env: | |
| VERSION: ${{ needs.prepare.outputs.version }} | |
| SUFFIX: ${{ needs.prepare.outputs.pypi_suffix }} | |
| CHANNEL: ${{ needs.prepare.outputs.channel }} | |
| TARGET_REPO: ${{ needs.prepare.outputs.target_repo }} | |
| PYPI_PROJECT: ${{ needs.prepare.outputs.pypi_project }} | |
| run: | | |
| python devscripts/update-version.py -c "${CHANNEL}" -r "${TARGET_REPO}" -s "${SUFFIX}" "${VERSION}" | |
| python devscripts/update_changelog.py -vv | |
| python devscripts/make_lazy_extractors.py | |
| sed -i -E '0,/(name = ")[^"]+(")/s//\1'"${PYPI_PROJECT}"'\2/' pyproject.toml | |
| - name: Build | |
| run: | | |
| rm -rf dist/* | |
| make pypi-files | |
| printf '%s\n\n' \ | |
| 'Official repository: <https://github.com/yt-dlp/yt-dlp>' \ | |
| '**PS**: Some links in this document will not work since this is a copy of the README.md from Github' > ./README.md.new | |
| cat ./README.md >> ./README.md.new && mv -f ./README.md.new ./README.md | |
| python devscripts/set-variant.py pip -M "You installed yt-dlp with pip or using the wheel from PyPi; Use that to update" | |
| make clean-cache | |
| python -m build --no-isolation . | |
| - name: Upload artifacts | |
| if: github.event_name != 'workflow_dispatch' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: build-pypi | |
| path: | | |
| dist/* | |
| compression-level: 0 | |
| - name: Publish to PyPI | |
| if: github.event_name == 'workflow_dispatch' | |
| uses: pypa/gh-action-pypi-publish@release/v1 | |
| with: | |
| verbose: true | |
| publish: | |
| needs: [prepare, build] | |
| permissions: | |
| contents: write | |
| runs-on: ubuntu-latest | |
| env: | |
| TARGET_REPO: ${{ needs.prepare.outputs.target_repo }} | |
| TARGET_TAG: ${{ needs.prepare.outputs.target_tag }} | |
| VERSION: ${{ needs.prepare.outputs.version }} | |
| HEAD_SHA: ${{ needs.prepare.outputs.head_sha }} | |
| steps: | |
| - uses: actions/checkout@v5 | |
| with: | |
| fetch-depth: 0 | |
| - uses: actions/download-artifact@v5 | |
| with: | |
| path: artifact | |
| pattern: build-* | |
| merge-multiple: true | |
| - uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.10" | |
| - name: Generate release notes | |
| env: | |
| REPOSITORY: ${{ github.repository }} | |
| BASE_REPO: yt-dlp/yt-dlp | |
| NIGHTLY_REPO: yt-dlp/yt-dlp-nightly-builds | |
| MASTER_REPO: yt-dlp/yt-dlp-master-builds | |
| DOCS_PATH: ${{ env.TARGET_REPO == github.repository && format('/tree/{0}', env.TARGET_TAG) || '' }} | |
| run: | | |
| printf '%s' \ | |
| "[]" \ | |
| "(https://github.com/${REPOSITORY}#installation \"Installation instructions\") " \ | |
| "[]" \ | |
| "(https://discord.gg/H5MNcFW63r \"Discord\") " \ | |
| "[]" \ | |
| "(https://github.com/${BASE_REPO}/blob/master/Maintainers.md#maintainers \"Donate\") " \ | |
| "[]" \ | |
| "(https://github.com/${REPOSITORY}${DOCS_PATH}#readme \"Documentation\") " > ./RELEASE_NOTES | |
| if [[ "${TARGET_REPO}" == "${BASE_REPO}" ]]; then | |
| printf '%s' \ | |
| "[]" \ | |
| "(https://github.com/${NIGHTLY_REPO}/releases/latest \"Nightly builds\") " \ | |
| "[]" \ | |
| "(https://github.com/${MASTER_REPO}/releases/latest \"Master builds\")" >> ./RELEASE_NOTES | |
| fi | |
| printf '\n\n%s\n\n%s%s%s\n\n---\n' \ | |
| "#### A description of the various files is in the [README](https://github.com/${REPOSITORY}#release-files)" \ | |
| "The zipimport Unix executable contains code licensed under ISC and MIT. " \ | |
| "The PyInstaller-bundled executables are subject to these and other licenses, all of which are compiled in " \ | |
| "[THIRD_PARTY_LICENSES.txt](https://github.com/${BASE_REPO}/blob/${HEAD_SHA}/THIRD_PARTY_LICENSES.txt)" >> ./RELEASE_NOTES | |
| python ./devscripts/make_changelog.py -vv --collapsible >> ./RELEASE_NOTES | |
| 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/${REPOSITORY}/commit/${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 }} | |
| TITLE_PREFIX: ${{ startswith(env.TARGET_REPO, 'yt-dlp/') && 'yt-dlp ' || '' }} | |
| TITLE: ${{ inputs.target != env.TARGET_REPO && inputs.target || needs.prepare.outputs.channel }} | |
| if: | | |
| inputs.prerelease && env.GH_TOKEN && env.GH_REPO && env.GH_REPO != github.repository | |
| run: | | |
| gh release create \ | |
| --notes-file ARCHIVE_NOTES \ | |
| --title "${TITLE_PREFIX}${TITLE} ${VERSION}" \ | |
| "${VERSION}" \ | |
| artifact/* | |
| - name: Prune old release | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| if: | | |
| env.TARGET_REPO == github.repository && env.TARGET_TAG != env.VERSION | |
| run: | | |
| gh release delete --yes --cleanup-tag "${TARGET_TAG}" || true | |
| git tag --delete "${TARGET_TAG}" || true | |
| sleep 5 # Enough time to cover deletion race condition | |
| - name: Publish release | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| NOTES_FILE: ${{ inputs.prerelease && 'PRERELEASE_NOTES' || 'RELEASE_NOTES' }} | |
| TITLE_PREFIX: ${{ github.repository == 'yt-dlp/yt-dlp' && 'yt-dlp ' || '' }} | |
| TITLE: ${{ env.TARGET_TAG != env.VERSION && format('{0} ', env.TARGET_TAG) || '' }} | |
| PRERELEASE: ${{ inputs.prerelease && '1' || '0' }} | |
| if: | | |
| env.TARGET_REPO == github.repository | |
| run: | | |
| gh_options=( | |
| --notes-file "${NOTES_FILE}" | |
| --target "${HEAD_SHA}" | |
| --title "${TITLE_PREFIX}${TITLE}${VERSION}" | |
| ) | |
| if ((PRERELEASE)); then | |
| gh_options+=(--prerelease) | |
| fi | |
| gh release create "${gh_options[@]}" "${TARGET_TAG}" artifact/* |