Add formatting/linting CI (#18)

This commit is contained in:
sepro
2025-10-23 21:24:31 +02:00
committed by GitHub
parent 52a4f9d19a
commit b57ce18965
12 changed files with 153 additions and 44 deletions

View File

@@ -1,27 +1,13 @@
name: CI
on:
push:
paths:
- ".github/workflows/ci.yml"
- ".github/workflows/release.yml"
- "hatch_build.py"
- "package.json"
- "pyproject.toml"
- "rollup.config.js"
- "run.ts"
- "src/**"
- "yt_dlp_ejs/**"
paths-ignore:
- 'README.md'
- 'LICENSE'
pull_request:
paths:
- ".github/workflows/ci.yml"
- ".github/workflows/release.yml"
- "hatch_build.py"
- "package.json"
- "pyproject.toml"
- "rollup.config.js"
- "run.ts"
- "src/**"
- "yt_dlp_ejs/**"
paths-ignore:
- 'README.md'
- 'LICENSE'
permissions:
contents: read
@@ -31,6 +17,56 @@ concurrency:
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
ruff-format:
name: Ruff format check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: astral-sh/ruff-action@v3
with:
args: "check --output-format github"
ruff-lint:
name: Ruff linting check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: astral-sh/ruff-action@v3
with:
args: "format --check --diff"
prettier:
name: Prettier check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- name: Install Deno v2.x (latest)
uses: denoland/setup-deno@v2
with:
deno-version: v2.x
- name: Install Deno requirements
run: |
deno install
- name: Run Prettier check
run: |
deno task fmt:check
eslint:
name: ESLint check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- name: Install Deno v2.x (latest)
uses: denoland/setup-deno@v2
with:
deno-version: v2.x
- name: Install Deno requirements
run: |
deno install
- name: Run ESLint check
run: |
deno task lint
python_tests:
name: Python tests
runs-on: ubuntu-latest
@@ -304,7 +340,17 @@ jobs:
node --test
all_passed:
needs: [deno_build, deno_tests, bun_build, bun_tests, node_build, node_tests]
needs:
- ruff-format
- ruff-lint
- prettier
- eslint
- deno_build
- deno_tests
- bun_build
- bun_tests
- node_build
- node_tests
runs-on: ubuntu-latest
steps:
- name: All checks passed

14
eslint.config.js Normal file
View File

@@ -0,0 +1,14 @@
import js from "@eslint/js";
import globals from "globals";
import tseslint from "typescript-eslint";
import { defineConfig } from "eslint/config";
export default defineConfig([
{
files: ["**/*.{js,mjs,cjs,ts,mts,cts}"],
plugins: { js },
extends: ["js/recommended"],
languageOptions: { globals: globals.node },
},
tseslint.configs.recommended,
]);

View File

@@ -28,12 +28,15 @@ class CustomBuildHook(BuildHookInterface):
else:
raise RuntimeError(
"One of 'deno', 'bun', or 'npm' could not be found. "
"Please install one of them to proceed with the build.")
"Please install one of them to proceed with the build."
)
build_data["force_include"].update({
"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",
})
build_data["force_include"].update(
{
"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",
}
)
def clean(self, versions):
shutil.rmtree("node_modules", ignore_errors=True)

View File

@@ -3,21 +3,27 @@
"type": "module",
"scripts": {
"bundle": "rollup -c",
"fmt": "prettier --write \"src/**.ts\" \"package.json\" \"rollup.config.js\" \"run.ts\""
"fmt": "prettier --write \"src/**.ts\" \"package.json\" \"rollup.config.js\" \"run.ts\" \"eslint.config.js\"",
"fmt:check": "prettier --check \"src/**.ts\" \"package.json\" \"rollup.config.js\" \"run.ts\" \"eslint.config.js\"",
"lint": "eslint src"
},
"dependencies": {
"astring": "1.9.0",
"meriyah": "6.1.4"
},
"devDependencies": {
"@eslint/js": "9.38.0",
"@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.3.0",
"@types/deno": "2.5.0",
"@types/node": "24.8.1",
"eslint": "9.38.0",
"globals": "16.4.0",
"prettier": "3.6.2",
"rollup": "4.52.5",
"prettier": "3.6.2"
"rollup-plugin-license": "3.6.0",
"typescript-eslint": "8.46.2"
}
}

View File

@@ -30,6 +30,11 @@ classifiers = [
]
dependencies = []
[dependency-groups]
dev = [
"ruff>=0.14.1",
]
[project.urls]
Documentation = "https://github.com/yt-dlp/ejs#readme"
Issues = "https://github.com/yt-dlp/ejs/issues"
@@ -51,3 +56,33 @@ packages = ["yt_dlp_ejs"]
version-file = "yt_dlp_ejs/_version.py"
[tool.hatch.build.targets.wheel.hooks.custom]
[tool.ruff.lint]
select = [
"C4",
"E",
"F",
"I",
"PLC",
"PLE",
"PLW",
"PYI",
"RET",
"RUF",
"SIM",
"TD",
"TID",
"W",
]
ignore = [
"TD003",
"E402",
"E501",
"PLR09",
]
[tool.ruff.lint.isort]
force-single-line = true
[tool.ruff.lint.flake8-tidy-imports]
ban-relative-imports = "all"

View File

@@ -31,7 +31,9 @@ function printHash() {
for (const [fileName, assetInfo] of Object.entries(bundle)) {
if (assetInfo.code) {
try {
const digest = createHash("sha3-512").update(assetInfo.code).digest("hex");
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);

View File

@@ -25,7 +25,9 @@ export function matchesStructure<T extends ESTree.Node>(
if ("anykey" in structure && Array.isArray(structure.anykey)) {
// Handle `{ anykey: [a, b] }`
const haystack = Array.isArray(obj) ? obj : Object.values(obj);
return structure.anykey.every(value => haystack.some((el) => matchesStructure(el, value)));
return structure.anykey.every((value) =>
haystack.some((el) => matchesStructure(el, value)),
);
}
for (const [key, value] of Object.entries(structure)) {
if (!matchesStructure(obj[key as keyof typeof obj], value)) {

View File

@@ -24,6 +24,7 @@ export async function getIO(): Promise<IO> {
async function _getIO(): Promise<IO> {
// Old Deno requires casting to any as globalThis lacks an index signature
// eslint-disable-next-line @typescript-eslint/no-explicit-any
if ((globalThis as any).process?.release?.name === "node") {
// Assume node compatibility
const { access, readFile } = await import("node:fs/promises");

View File

@@ -4,15 +4,21 @@ from pathlib import Path
import yt_dlp_ejs.yt.solver
BASE_PATH = Path(__file__).parent.parent
CORE_PATH = BASE_PATH / 'yt_dlp_ejs/yt/solver/core.min.js'
LIB_PATH = BASE_PATH / 'yt_dlp_ejs/yt/solver/lib.min.js'
CORE_PATH = BASE_PATH / "yt_dlp_ejs/yt/solver/core.min.js"
LIB_PATH = BASE_PATH / "yt_dlp_ejs/yt/solver/lib.min.js"
class TestModules(unittest.TestCase):
def test_yt_solver(self):
self.assertEqual(yt_dlp_ejs.yt.solver.core(), CORE_PATH.read_text(encoding='utf-8'))
self.assertEqual(yt_dlp_ejs.yt.solver.lib(), LIB_PATH.read_text(encoding='utf-8'))
self.assertEqual(
yt_dlp_ejs.yt.solver.core(),
CORE_PATH.read_text(encoding="utf-8"),
)
self.assertEqual(
yt_dlp_ejs.yt.solver.lib(),
LIB_PATH.read_text(encoding="utf-8"),
)
if __name__ == '__main__':
if __name__ == "__main__":
unittest.main()

View File

@@ -1,7 +1,3 @@
from yt_dlp_ejs._version import version
from yt_dlp_ejs import yt
__all__ = [
"version",
"yt"
]
__all__ = ["version"]

View File

@@ -1,3 +0,0 @@
from . import solver
__all__ = ["solver"]

View File

@@ -2,6 +2,7 @@ import importlib.resources
import yt_dlp_ejs.yt.solver
def core() -> str:
"""
Read the contents of the JavaScript core solver bundle as string.