diff --git a/.github/actionlint.yml b/.github/actionlint.yml index ee319fef54..e1b6359d2e 100644 --- a/.github/actionlint.yml +++ b/.github/actionlint.yml @@ -1,5 +1,4 @@ config-variables: - - PUSH_VERSION_COMMIT - UPDATE_TO_VERIFICATION - PYPI_PROJECT - PYPI_SUFFIX diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ad364f3012..414503024f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -27,6 +27,8 @@ on: required: false GPG_SIGNING_KEY: required: false + RELEASE_KEY: + required: false workflow_dispatch: inputs: source: @@ -67,7 +69,7 @@ jobs: prepare: name: Prepare permissions: - contents: write # Needed to git-push the release commit + contents: read # Push via SSH; HTTPS write token is not needed runs-on: ubuntu-latest outputs: channel: ${{ steps.setup_variables.outputs.channel }} @@ -83,6 +85,7 @@ jobs: with: fetch-depth: 0 persist-credentials: true # Needed to git-push the release commit + ssh-key: ${{ secrets.RELEASE_KEY }} - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: @@ -101,7 +104,6 @@ jobs: 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)] }} @@ -110,6 +112,7 @@ jobs: 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_ARCHIVE_REPO_TOKEN: ${{ !!secrets.ARCHIVE_REPO_TOKEN }} + HAS_RELEASE_KEY: ${{ !!secrets.RELEASE_KEY }} run: | python -m devscripts.setup_variables @@ -124,32 +127,26 @@ jobs: python devscripts/update_changelog.py -vv make doc - - name: Push to release - id: push_release + - name: Push release commit env: VERSION: ${{ steps.setup_variables.outputs.version }} GITHUB_EVENT_SENDER_LOGIN: ${{ github.event.sender.login }} GITHUB_EVENT_REF: ${{ github.event.ref }} - if: steps.setup_variables.outputs.target_repo == github.repository && !inputs.prerelease + RELEASE_KEY: ${{ secrets.RELEASE_KEY }} + if: steps.setup_variables.outputs.target_repo == github.repository && env.RELEASE_KEY && !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: ${GITHUB_EVENT_SENDER_LOGIN}" -m ":ci skip all" - git push origin --force "${GITHUB_EVENT_REF}:release" + git push origin "${GITHUB_EVENT_REF}" - 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: name: Build needs: [prepare] @@ -243,7 +240,8 @@ jobs: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 - persist-credentials: false + persist-credentials: true # Needed to git-push the release tag + ssh-key: ${{ secrets.RELEASE_KEY }} - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: path: artifact @@ -311,6 +309,13 @@ jobs: git tag --delete "${TARGET_TAG}" || true sleep 5 # Enough time to cover deletion race condition + - name: Push tag + if: env.TARGET_REPO == github.repository + run: | + git tag "${TARGET_TAG}" "${HEAD_SHA}" + git push origin "${TARGET_TAG}" + sleep 5 # Enough time to cover git-push vs gh-release-create race condition + - name: Publish release env: GH_TOKEN: ${{ github.token }} @@ -322,7 +327,7 @@ jobs: run: | gh_options=( --notes-file "${NOTES_FILE}" - --target "${HEAD_SHA}" + --verify-tag --title "${TITLE_PREFIX}${TITLE}${VERSION}" ) if ((PRERELEASE)); then diff --git a/devscripts/setup_variables.py b/devscripts/setup_variables.py index a5bde4701c..f3c39e581a 100644 --- a/devscripts/setup_variables.py +++ b/devscripts/setup_variables.py @@ -16,12 +16,11 @@ STABLE_REPOSITORY = 'yt-dlp/yt-dlp' def setup_variables(environment): """ `environment` must contain these keys: - REPOSITORY, INPUTS, PROCESSED, - PUSH_VERSION_COMMIT, PYPI_PROJECT, + REPOSITORY, INPUTS, PROCESSED, PYPI_PROJECT, SOURCE_PYPI_PROJECT, SOURCE_PYPI_SUFFIX, TARGET_PYPI_PROJECT, TARGET_PYPI_SUFFIX, SOURCE_ARCHIVE_REPO, TARGET_ARCHIVE_REPO, - HAS_ARCHIVE_REPO_TOKEN + HAS_ARCHIVE_REPO_TOKEN, HAS_RELEASE_KEY `INPUTS` must contain these keys: prerelease @@ -57,7 +56,7 @@ def setup_variables(environment): resolved_source = 'stable' revision = None - if INPUTS['prerelease'] or not environment['PUSH_VERSION_COMMIT']: + if INPUTS['prerelease'] or not json.loads(environment['HAS_RELEASE_KEY']): revision = dt.datetime.now(tz=dt.timezone.utc).strftime('%H%M%S') version = calculate_version(INPUTS.get('version') or revision) diff --git a/devscripts/setup_variables_tests.py b/devscripts/setup_variables_tests.py index 22efe0a804..7a9eff7d85 100644 --- a/devscripts/setup_variables_tests.py +++ b/devscripts/setup_variables_tests.py @@ -27,7 +27,6 @@ def _test(github_repository, note, repo_vars, repo_secrets, inputs, expected, ig 'INPUTS': json.dumps(inp), 'PROCESSED': json.dumps(processed), 'REPOSITORY': github_repository, - 'PUSH_VERSION_COMMIT': variables.get('PUSH_VERSION_COMMIT') or '', 'PYPI_PROJECT': variables.get('PYPI_PROJECT') or '', 'SOURCE_PYPI_PROJECT': variables.get(f'{source_repo}_PYPI_PROJECT') or '', 'SOURCE_PYPI_SUFFIX': variables.get(f'{source_repo}_PYPI_SUFFIX') or '', @@ -36,6 +35,7 @@ def _test(github_repository, note, repo_vars, repo_secrets, inputs, expected, ig 'SOURCE_ARCHIVE_REPO': variables.get(f'{source_repo}_ARCHIVE_REPO') or '', 'TARGET_ARCHIVE_REPO': variables.get(f'{target_repo}_ARCHIVE_REPO') or '', 'HAS_ARCHIVE_REPO_TOKEN': json.dumps(bool(secrets.get('ARCHIVE_REPO_TOKEN'))), + 'HAS_RELEASE_KEY': json.dumps(bool(secrets.get('RELEASE_KEY'))), } result = setup_variables(env) @@ -67,11 +67,11 @@ def test_setup_variables(): 'NIGHTLY_ARCHIVE_REPO': 'yt-dlp/yt-dlp-nightly-builds', 'NIGHTLY_PYPI_PROJECT': 'yt-dlp', 'NIGHTLY_PYPI_SUFFIX': 'dev', - 'PUSH_VERSION_COMMIT': '1', 'PYPI_PROJECT': 'yt-dlp', } BASE_REPO_SECRETS = { 'ARCHIVE_REPO_TOKEN': '1', + 'RELEASE_KEY': '1', } FORK_REPOSITORY = 'fork/yt-dlp' FORK_ORG = FORK_REPOSITORY.partition('/')[0] @@ -227,8 +227,8 @@ def test_setup_variables(): }) _test( - FORK_REPOSITORY, 'fork w/ PUSH_VERSION_COMMIT, stable', - {'PUSH_VERSION_COMMIT': '1'}, {}, {}, { + FORK_REPOSITORY, 'fork w/ RELEASE_KEY, stable', + {}, {'RELEASE_KEY': '1'}, {}, { 'channel': FORK_REPOSITORY, 'version': DEFAULT_VERSION, 'target_repo': FORK_REPOSITORY, @@ -237,8 +237,8 @@ def test_setup_variables(): 'pypi_suffix': None, }) _test( - FORK_REPOSITORY, 'fork w/ PUSH_VERSION_COMMIT, prerelease', - {'PUSH_VERSION_COMMIT': '1'}, {}, {'prerelease': True}, { + FORK_REPOSITORY, 'fork w/ RELEASE_KEY, prerelease', + {}, {'RELEASE_KEY': '1'}, {'prerelease': True}, { 'channel': FORK_REPOSITORY, 'version': DEFAULT_VERSION_WITH_REVISION, 'target_repo': FORK_REPOSITORY,