mirror of
				https://github.com/yt-dlp/yt-dlp.git
				synced 2025-11-04 00:20:47 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			385 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			YAML
		
	
	
	
	
	
			
		
		
	
	
			385 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			YAML
		
	
	
	
	
	
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@v5
 | 
						|
        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: |
 | 
						|
          python devscripts/update_changelog.py -vv
 | 
						|
          make doc
 | 
						|
 | 
						|
      - 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
 | 
						|
      actions: write  # For cleaning up cache
 | 
						|
    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@v4
 | 
						|
        with:
 | 
						|
          fetch-depth: 0
 | 
						|
      - uses: actions/setup-python@v5
 | 
						|
        with:
 | 
						|
          python-version: "3.10"
 | 
						|
 | 
						|
      - name: Install Requirements
 | 
						|
        run: |
 | 
						|
          sudo apt -y install pandoc man
 | 
						|
          python devscripts/install_deps.py -o --include 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 "${{ env.channel }}" -r "${{ env.target_repo }}" -s "${{ env.suffix }}" "${{ env.version }}"
 | 
						|
          python devscripts/update_changelog.py -vv
 | 
						|
          python devscripts/make_lazy_extractors.py
 | 
						|
          sed -i -E '0,/(name = ")[^"]+(")/s//\1${{ env.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: Publish to PyPI
 | 
						|
        uses: pypa/gh-action-pypi-publish@release/v1
 | 
						|
        with:
 | 
						|
          verbose: true
 | 
						|
 | 
						|
  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
 | 
						|
        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' \
 | 
						|
            '[]' \
 | 
						|
              '(https://github.com/${{ github.repository }}#installation "Installation instructions") ' \
 | 
						|
            '[]' \
 | 
						|
              '(https://discord.gg/H5MNcFW63r "Discord") ' \
 | 
						|
            '[]' \
 | 
						|
              '(https://github.com/yt-dlp/yt-dlp/blob/master/Collaborators.md#collaborators "Donate") ' \
 | 
						|
            '[]' \
 | 
						|
              '(https://github.com/${{ github.repository }}' \
 | 
						|
              '${{ env.target_repo == github.repository && format('/tree/{0}', env.target_tag) || '' }}#readme "Documentation") ' \
 | 
						|
            ${{ env.target_repo == 'yt-dlp/yt-dlp' && '\
 | 
						|
              "[]" \
 | 
						|
              "(https://github.com/yt-dlp/yt-dlp-nightly-builds/releases/latest \"Nightly builds\") " \
 | 
						|
              "[]" \
 | 
						|
              "(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/*
 |