Finalize for release (#8)

Co-authored-by: bashonly <bashonly@protonmail.com>
This commit is contained in:
Simon Sawicki
2025-10-21 21:29:49 +02:00
committed by GitHub
parent c38bd7d1ab
commit 130f6952d7
9 changed files with 196 additions and 1718 deletions

View File

@@ -1,31 +1,95 @@
name: Release
on:
push:
tags:
- "*"
permissions:
contents: read
jobs:
release:
build:
name: Build artifacts
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 0
- uses: denoland/setup-deno@v2
with:
deno-version: v2.x
- uses: astral-sh/setup-uv@v6
- uses: actions/setup-python@v6
with:
python-version: "3.13"
- name: Bundle
run:
# XXX: uv build fails for some reason
uv tool run hatch build --target wheel
python-version: "3.10"
- name: Install Python requirements
run: |
python -m pip install -U build
- name: Build Python artifacts
run: |
python -m build
- name: Upload Python artifacts
uses: actions/upload-artifact@v4
with:
name: artifacts-py
path: |
dist/yt_dlp_ejs-*.whl
dist/yt_dlp_ejs-*.tar.gz
compression-level: 0
- name: Build JavaScript artifacts
run: |
deno install
deno task bundle
- name: Upload JavaScript artifacts
uses: actions/upload-artifact@v4
with:
name: artifacts-js
path: |
dist/yt.solver.*.js
compression-level: 0
publish_pypi:
name: Publish to PyPI
needs: [build]
if: github.repository == 'yt-dlp/ejs'
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write # required for PyPI trusted publishing
steps:
- uses: actions/download-artifact@v5
with:
path: dist
name: artifacts-py
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
verbose: true
release:
name: Create GitHub release
needs: [build, publish_pypi]
if: always() && !failure() && !cancelled()
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 0
- uses: actions/download-artifact@v5
with:
path: dist
pattern: artifacts-*
merge-multiple: true
- name: Create GitHub Release
env:
TAG: ${{ github.ref_name }}
GH_TOKEN: ${{ github.token }}
run: |
gh release create ${TAG} \
gh release create "${TAG}" \
--title "yt-dlp-ejs ${TAG}" \
--notes-from-tag \
--verify-tag \
dist/yt.solver.* \
dist/yt_dlp_ejs*.whl
dist/yt.solver.*.js \
dist/yt_dlp_ejs-*.whl \
dist/yt_dlp_ejs-*.tar.gz

1
.gitignore vendored
View File

@@ -4,4 +4,5 @@
/node_modules
/bun.lock
/deno.lock
/package-lock.json
/.idea

24
LICENSE Normal file
View File

@@ -0,0 +1,24 @@
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <https://unlicense.org/>

View File

@@ -13,13 +13,31 @@ In the yt-dlp repository, install the python package, either directly or from ur
pip install git+https://github.com/yt-dlp/ejs@main
```
## Build scripts
## Development
```
deno install
deno task bundle
```
While this project does pin its dependencies,
it does not use lockfiles or enforce a particular package manager.
You may install dependencies using any compatible package manager.
If you notice differences between different runtimes builds
please open an issue [here](<https://github.com/yt-dlp/ejs/issues/new>).
## Tests
### Build
todo
To build the Python package you need a PEP518 compatible builder.
The build hook will automatically invoke `deno`, `bun` or `node` as required.
Alternatively, to only build the JavaScript files you can run the `bundle` script manually.
### Tests
First, to download the player files, run `src/yt/solver/test/download.ts`.
After running that once, use any of `deno test`, `bun test` or `node --test`.
## Licensing
This code is licensed under [Unlicense](<https://unlicense.org/>).
An exception to this are the prebuilt wheels, which contain both
[`meriyah`](<https://github.com/meriyah/meriyah>) and [`astring`](<https://github.com/davidbonnet/astring>),
licensed under [`ISC`](<https://github.com/meriyah/meriyah?tab=ISC-1-ov-file>) and [`MIT`](<https://github.com/davidbonnet/astring?tab=MIT-1-ov-file>), respectively.

38
hatch_build.py Normal file
View File

@@ -0,0 +1,38 @@
import os
import shutil
import subprocess
from hatchling.builders.hooks.plugin.interface import BuildHookInterface
class CustomBuildHook(BuildHookInterface):
def initialize(self, version, build_data):
if shutil.which("deno"):
print("Building with deno...", flush=True)
os.environ["DENO_NO_UPDATE_CHECK"] = "1"
subprocess.run(["deno", "install"], check=True)
subprocess.run(["deno", "task", "bundle"], check=True)
elif shutil.which("bun"):
print("Building with bun...", flush=True)
subprocess.run(["bun", "install", "--frozen-lockfile"], check=True)
subprocess.run(["bun", "run", "bundle"], check=True)
elif shutil.which("npm"):
print("Building with npm...", flush=True)
# npm is a batch file (`npm.cmd`) on windows, which requires `shell=True`
requires_shell = os.name == "nt"
subprocess.run(["npm", "ci"], check=True, shell=requires_shell)
subprocess.run(["npm", "run", "bundle"], check=True, shell=requires_shell)
else:
raise RuntimeError(
"One of 'deno', 'bun', or 'npm' could not be found. "
"Please install one of them to proceed with the build.")
build_data["force_include"]["dist/yt.solver.core.min.js"] = "yt_dlp_ejs/yt/solver/core.min.js"
build_data["force_include"]["dist/yt.solver.lib.min.js"] = "yt_dlp_ejs/yt/solver/lib.min.js"
def clean(self, versions):
shutil.rmtree('node_modules', ignore_errors=True)

1650
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -3,21 +3,21 @@
"type": "module",
"scripts": {
"bundle": "rollup -c",
"fmt": "prettier --write \"src/**.ts\" \"tests/**.ts\" \"package.json\" \"rollup.config.js\" \"run.ts\""
"fmt": "prettier --write \"src/**.ts\" \"package.json\" \"rollup.config.js\" \"run.ts\""
},
"dependencies": {
"astring": "1.9.0",
"meriyah": "6.1.4"
},
"devDependencies": {
"@rollup/plugin-node-resolve": "^16.0.1",
"@rollup/plugin-node-resolve": "16.0.3",
"@rollup/plugin-sucrase": "5.0.2",
"@rollup/plugin-terser": "0.4.4",
"rollup-plugin-license": "^3.6.0",
"@types/bun": "1.2.21",
"@types/deno": "2.3.0",
"@types/node": "24.3.0",
"rollup": "4.50.0",
"prettier": "^3.6.2"
"rollup-plugin-license": "3.6.0",
"@types/bun": "1.3.0",
"@types/deno": "2.5.0",
"@types/node": "24.8.1",
"rollup": "4.52.5",
"prettier": "3.6.2"
}
}

View File

@@ -1,5 +1,8 @@
[build-system]
requires = ["hatchling", "hatch-build-scripts", "hatch-vcs"]
requires = [
"hatchling>=1.27.0",
"hatch-vcs",
]
build-backend = "hatchling.build"
[project]
@@ -7,16 +10,16 @@ name = "yt-dlp-ejs"
description = "External JavaScript for yt-dlp supporting many runtimes"
dynamic = ["version"]
readme = "README.md"
requires-python = ">=3.9"
license = "Unlicense"
keywords = []
requires-python = ">=3.10"
license = "Unlicense AND MIT AND ISC"
license-files = ["LICENSE"]
keywords = ["yt-dlp"]
authors = [
{ name = "Simon Sawicki", email = "contact@grub4k.dev" },
]
classifiers = [
"Development Status :: 5 - Production/Stable",
"Programming Language :: Python",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
@@ -35,15 +38,13 @@ Source = "https://github.com/yt-dlp/ejs"
[tool.hatch.version]
source = "vcs"
[tool.hatch.build.targets.sdist]
exclude = [
"/.github/**",
"/src/yt/solver/test/players/*",
]
[tool.hatch.build.hooks.vcs]
version-file = "yt_dlp_ejs/_version.py"
[[tool.hatch.build.hooks.build-scripts.scripts]]
commands = [
"deno install",
"deno task bundle",
]
[tool.hatch.build.targets.wheel.force-include]
"dist/yt.solver.core.min.js" = "yt_dlp_ejs/yt/solver/core.min.js"
"dist/yt.solver.lib.min.js" = "yt_dlp_ejs/yt/solver/lib.min.js"
[tool.hatch.build.targets.wheel.hooks.custom]

View File

@@ -3,7 +3,6 @@ import nodeResolve from "@rollup/plugin-node-resolve";
import sucrase from "@rollup/plugin-sucrase";
import terser from "@rollup/plugin-terser";
import { createHash } from "node:crypto";
import { Buffer } from "node:buffer";
import license from "rollup-plugin-license";
import { readFileSync } from "node:fs";
import prettier from "prettier";
@@ -12,7 +11,7 @@ const pkg = JSON.parse(readFileSync("./package.json"));
const LICENSE_BANNER =
"SPDX-License-Identifier: Unlicense\n" +
"This file was automatically generated by https://github.com/yt-dlp/ejs on <%= moment().toISOString() %>" +
"This file was automatically generated by https://github.com/yt-dlp/ejs" +
"<% if (dependencies && dependencies.length) { %>" +
"\n\nBundled Dependencies:" +
"<% _.forEach(dependencies, function (dependency) { if (!dependency.private) { %>" +
@@ -25,8 +24,6 @@ const LICENSE_BANNER =
"<% if (dependency.licenseText) { %>\n\n<%= dependency.licenseText %><% } %>" +
"\n---<% } }) %>\n<% } %>";
const ALLOWED_COMMENTS_RE = /SPDX-License-Identifier:/;
function printHash() {
return {
name: "hash-output-plugin",
@@ -34,9 +31,8 @@ function printHash() {
for (const [fileName, assetInfo] of Object.entries(bundle)) {
if (assetInfo.code) {
try {
const data = Buffer.from(assetInfo.code);
const hash = createHash("sha3-512").update(data).digest("hex");
console.log(`SHA3-512 for ${assetInfo.fileName}: ${hash}`);
const digest = createHash("sha3-512").update(assetInfo.code).digest("hex");
console.log(`SHA3-512 for ${assetInfo.fileName}: ${digest}`);
} catch (err) {
console.error(`Error hashing ${fileName}:`, err.message);
}
@@ -103,14 +99,12 @@ export default defineConfig([
}),
license({
banner: {
commentStyle: "ignored",
content: LICENSE_BANNER,
},
}),
// Use terser to remove comments but do not minify
terser({
format: {
comments: ALLOWED_COMMENTS_RE,
},
compress: false,
mangle: false,
}),
@@ -139,16 +133,13 @@ export default defineConfig([
exclude: ["node_modules/**"],
transforms: ["typescript"],
}),
terser({
format: {
comments: ALLOWED_COMMENTS_RE,
},
}),
license({
banner: {
commentStyle: "ignored",
content: LICENSE_BANNER,
},
}),
terser(),
printHash(),
],
},
@@ -168,14 +159,12 @@ export default defineConfig([
}),
license({
banner: {
commentStyle: "ignored",
content: LICENSE_BANNER,
},
}),
// Use terser to remove comments but do not minify
terser({
format: {
comments: ALLOWED_COMMENTS_RE,
},
compress: false,
mangle: false,
}),
@@ -198,16 +187,13 @@ export default defineConfig([
exclude: ["node_modules/**"],
transforms: ["typescript"],
}),
terser({
format: {
comments: ALLOWED_COMMENTS_RE,
},
}),
license({
banner: {
commentStyle: "ignored",
content: LICENSE_BANNER,
},
}),
terser(),
printHash(),
],
},
@@ -222,14 +208,12 @@ export default defineConfig([
dynamicImportRewrite(),
license({
banner: {
commentStyle: "ignored",
content: LICENSE_BANNER,
},
}),
// Use terser to remove comments but do not minify
terser({
format: {
comments: ALLOWED_COMMENTS_RE,
},
compress: false,
mangle: false,
}),
@@ -248,14 +232,12 @@ export default defineConfig([
dynamicImportRewrite({ format: "bun" }),
license({
banner: {
commentStyle: "ignored",
content: LICENSE_BANNER,
},
}),
// Use terser to remove comments but do not minify
terser({
format: {
comments: ALLOWED_COMMENTS_RE,
},
compress: false,
mangle: false,
}),