Repository: yt-dlp/yt-dlp

Issue:
Release tarball yt-dlp.tar.gz does not contain that release's Changelog.md entries
### DO NOT REMOVE OR SKIP THE ISSUE TEMPLATE

- [X] I understand that I will be **blocked** if I *intentionally* remove or skip any mandatory\* field

### Checklist

- [X] I'm reporting a bug unrelated to a specific site
- [X] I've verified that I have **updated yt-dlp to nightly or master** ([update instructions](https://github.com/yt-dlp/yt-dlp#update-channels))
- [X] I've checked that all provided URLs are playable in a browser with the same IP and same login details
- [X] I've checked that all URLs and arguments with special characters are [properly quoted or escaped](https://github.com/yt-dlp/yt-dlp/wiki/FAQ#video-url-contains-an-ampersand--and-im-getting-some-strange-output-1-2839-or-v-is-not-recognized-as-an-internal-or-external-command)
- [X] I've searched [known issues](https://github.com/yt-dlp/yt-dlp/issues/3766) and the [bugtracker](https://github.com/yt-dlp/yt-dlp/issues?q=) for similar issues **including closed ones**. DO NOT post duplicates
- [X] I've read the [guidelines for opening an issue](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#opening-an-issue)

### Provide a description that is worded well enough to be understood

I am the maintainer of yt-dlp in MacPorts and while working on updating to 2024.03.10 I noticed that the file [yt-dlp.tar.gz](https://github.com/yt-dlp/yt-dlp/releases/download/2024.03.10/yt-dlp.tar.gz) attached to the 2024.03.10 release does not contain entries in Changelog.md for the 2024.03.10 release, yet they are in the repository. The newest entries in that file are for the previous 2023.12.30 release. The correct Changelog.md entries are available in the automatically-generated [2024.03.10.tar.gz](https://github.com/yt-dlp/yt-dlp/archive/refs/tags/2024.03.10.tar.gz) file but of course I want to use your manually-prepared tarballs instead.

Similarly, the [yt-dlp.tar.gz](https://github.com/yt-dlp/yt-dlp/releases/download/2023.12.30/yt-dlp.tar.gz) attached to the 2023.12.30 release does not have Changelog.md entries for the 2023.12.30 release; the newest entries there are for the 2023.11.16 release.

This makes me wonder what other changes that were intended for each release are missing from its tarball.

Is there perhaps a bug in the process that generates each release's tarball such that it is not being made from the intended commit?

### Provide verbose output that clearly demonstrates the problem

- [X] Run **your** yt-dlp command with **-vU** flag added (`yt-dlp -vU <your command line>`)
- [ ] If using API, add `'verbose': True` to `YoutubeDL` params instead
- [X] Copy the WHOLE output (starting with `[debug] Command-line config`) and insert it below

### Complete Verbose Output

```shell
N/A
```



Discussion:

Resolving patch:
diff --git a/devscripts/make_changelog.py b/devscripts/make_changelog.py
--- a/devscripts/make_changelog.py
+++ b/devscripts/make_changelog.py
@@ -445,7 +445,32 @@ def get_new_contributors(contributors_path, commits):
     return sorted(new_contributors, key=str.casefold)
 
 
-if __name__ == '__main__':
+def create_changelog(args):
+    logging.basicConfig(
+        datefmt='%Y-%m-%d %H-%M-%S', format='{asctime} | {levelname:<8} | {message}',
+        level=logging.WARNING - 10 * args.verbosity, style='{', stream=sys.stderr)
+
+    commits = CommitRange(None, args.commitish, args.default_author)
+
+    if not args.no_override:
+        if args.override_path.exists():
+            overrides = json.loads(read_file(args.override_path))
+            commits.apply_overrides(overrides)
+        else:
+            logger.warning(f'File {args.override_path.as_posix()} does not exist')
+
+    logger.info(f'Loaded {len(commits)} commits')
+
+    new_contributors = get_new_contributors(args.contributors_path, commits)
+    if new_contributors:
+        if args.contributors:
+            write_file(args.contributors_path, '\n'.join(new_contributors) + '\n', mode='a')
+        logger.info(f'New contributors: {", ".join(new_contributors)}')
+
+    return Changelog(commits.groups(), args.repo, args.collapsible)
+
+
+def create_parser():
     import argparse
 
     parser = argparse.ArgumentParser(
@@ -477,27 +502,9 @@ def get_new_contributors(contributors_path, commits):
     parser.add_argument(
         '--collapsible', action='store_true',
         help='make changelog collapsible (default: %(default)s)')
-    args = parser.parse_args()
-
-    logging.basicConfig(
-        datefmt='%Y-%m-%d %H-%M-%S', format='{asctime} | {levelname:<8} | {message}',
-        level=logging.WARNING - 10 * args.verbosity, style='{', stream=sys.stderr)
-
-    commits = CommitRange(None, args.commitish, args.default_author)
-
-    if not args.no_override:
-        if args.override_path.exists():
-            overrides = json.loads(read_file(args.override_path))
-            commits.apply_overrides(overrides)
-        else:
-            logger.warning(f'File {args.override_path.as_posix()} does not exist')
 
-    logger.info(f'Loaded {len(commits)} commits')
+    return parser
 
-    new_contributors = get_new_contributors(args.contributors_path, commits)
-    if new_contributors:
-        if args.contributors:
-            write_file(args.contributors_path, '\n'.join(new_contributors) + '\n', mode='a')
-        logger.info(f'New contributors: {", ".join(new_contributors)}')
 
-    print(Changelog(commits.groups(), args.repo, args.collapsible))
+if __name__ == '__main__':
+    print(create_changelog(create_parser().parse_args()))
diff --git a/devscripts/update_changelog.py b/devscripts/update_changelog.py
new file mode 100755
--- /dev/null
+++ b/devscripts/update_changelog.py
@@ -0,0 +1,26 @@
+#!/usr/bin/env python3
+
+# Allow direct execution
+import os
+import sys
+
+sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+
+from pathlib import Path
+
+from devscripts.make_changelog import create_changelog, create_parser
+from devscripts.utils import read_file, read_version, write_file
+
+# Always run after devscripts/update-version.py, and run before `make doc|pypi-files|tar|all`
+
+if __name__ == '__main__':
+    parser = create_parser()
+    parser.description = 'Update an existing changelog file with an entry for a new release'
+    parser.add_argument(
+        '--changelog-path', type=Path, default=Path(__file__).parent.parent / 'Changelog.md',
+        help='path to the Changelog file')
+    args = parser.parse_args()
+    new_entry = create_changelog(args)
+
+    header, sep, changelog = read_file(args.changelog_path).partition('\n### ')
+    write_file(args.changelog_path, f'{header}{sep}{read_version()}\n{new_entry}\n{sep}{changelog}')


Test patch: