diff --git a/.github/workflows/js.yml b/.github/workflows/js.yml index cac77df..42a7e8e 100644 --- a/.github/workflows/js.yml +++ b/.github/workflows/js.yml @@ -23,6 +23,16 @@ jobs: with: node-version: "24.22.1" - name: Install dependencies - run: cd crates/markkit-js && npm install + run: cd crates/markkit-js && npm install --ignore-scripts --audit=false --fund=false - name: Build - run: cd crates/markkit-js && npx napi build --release + run: cd crates/markkit-js && npx --no-install napi build --release --platform + - name: Verify build preserved the patched lockfile + run: git diff --exit-code -- Cargo.lock + - name: Verify installed npm package + run: | + cd crates/markkit-js + npm pack --ignore-scripts --json > "$RUNNER_TEMP/markkit-pack.json" + node -e 'const p=require(process.argv[1])[0]; const files=p.files.map(f=>f.path); if(!files.includes("index.js") || !files.some(f=>f.endsWith(".node"))) throw Error("npm package must contain its loader and native binary")' "$RUNNER_TEMP/markkit-pack.json" + TARBALL=$(node -e 'console.log(require(process.argv[1])[0].filename)' "$RUNNER_TEMP/markkit-pack.json") + npm install --prefix "$RUNNER_TEMP/markkit-npm-smoke" --ignore-scripts --audit=false --fund=false "$PWD/$TARBALL" + node -e 'const m=require(process.argv[1]); if(m.extractHtmlSync("

Smoke

").trim()!=="# Smoke") throw Error("native extraction smoke failed")' "$RUNNER_TEMP/markkit-npm-smoke/node_modules/@everruns/markkit" diff --git a/.github/workflows/publish-js.yml b/.github/workflows/publish-js.yml index e703314..6fb33e8 100644 --- a/.github/workflows/publish-js.yml +++ b/.github/workflows/publish-js.yml @@ -19,12 +19,31 @@ jobs: with: node-version: "24.22.1" registry-url: "https://registry.npmjs.org" + - name: Require npm publisher credential + if: inputs.dry_run != 'true' + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + run: | + if [ -z "$NODE_AUTH_TOKEN" ]; then + echo "::error::NPM_TOKEN is unavailable for this publisher" + exit 1 + fi - name: Install dependencies - run: cd crates/markkit-js && npm install + run: cd crates/markkit-js && npm install --ignore-scripts --audit=false --fund=false - name: Build - run: cd crates/markkit-js && npx napi build --release + run: cd crates/markkit-js && npx --no-install napi build --release --platform + - name: Verify build preserved the patched lockfile + run: git diff --exit-code -- Cargo.lock + - name: Verify installed npm package + run: | + cd crates/markkit-js + npm pack --ignore-scripts --json > "$RUNNER_TEMP/markkit-pack.json" + node -e 'const p=require(process.argv[1])[0]; const files=p.files.map(f=>f.path); if(!files.includes("index.js") || !files.some(f=>f.endsWith(".node"))) throw Error("npm package must contain its loader and native binary")' "$RUNNER_TEMP/markkit-pack.json" + TARBALL=$(node -e 'console.log(require(process.argv[1])[0].filename)' "$RUNNER_TEMP/markkit-pack.json") + npm install --prefix "$RUNNER_TEMP/markkit-npm-smoke" --ignore-scripts --audit=false --fund=false "$PWD/$TARBALL" + node -e 'const m=require(process.argv[1]); if(m.extractHtmlSync("

Smoke

").trim()!=="# Smoke") throw Error("native extraction smoke failed")' "$RUNNER_TEMP/markkit-npm-smoke/node_modules/@everruns/markkit" - name: Publish if: inputs.dry_run != 'true' - run: cd crates/markkit-js && npm publish + run: cd crates/markkit-js && npm publish --ignore-scripts env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/publish-python.yml b/.github/workflows/publish-python.yml index 4bd1890..69c3b23 100644 --- a/.github/workflows/publish-python.yml +++ b/.github/workflows/publish-python.yml @@ -18,10 +18,27 @@ jobs: - uses: actions/setup-python@v5 with: python-version: "3.12" + - name: Require PyPI publisher credential + if: inputs.dry_run != 'true' + env: + TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} + run: | + if [ -z "$TWINE_PASSWORD" ]; then + echo "::error::PYPI_API_TOKEN is unavailable for this publisher" + exit 1 + fi - name: Install maturin run: pip install maturin twine - name: Build wheels run: cd crates/markkit-python && maturin build --release + - name: Verify build preserved the patched lockfile + run: git diff --exit-code -- Cargo.lock + - name: Verify wheel metadata and native import + run: | + twine check target/wheels/*.whl + python -m venv "$RUNNER_TEMP/markkit-wheel-smoke" + "$RUNNER_TEMP/markkit-wheel-smoke/bin/python" -m pip install --no-deps target/wheels/*.whl + "$RUNNER_TEMP/markkit-wheel-smoke/bin/python" -c 'import markkit_python; assert markkit_python.extract_html_sync("

Smoke

").strip() == "# Smoke"' - name: Publish if: inputs.dry_run != 'true' run: twine upload target/wheels/*.whl diff --git a/.gitignore b/.gitignore index 84f1074..211833a 100644 --- a/.gitignore +++ b/.gitignore @@ -36,3 +36,10 @@ node_modules/ # WASM build artifacts *.wasm + +# Generated NAPI package artifacts +crates/markkit-js/*.node +crates/markkit-js/index.js +crates/markkit-js/index.d.ts +crates/markkit-js/package-lock.json +crates/markkit-js/*.tgz diff --git a/CHANGELOG.md b/CHANGELOG.md index 830011d..219fca7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,11 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/). ## [Unreleased] +## [0.1.1] - 2026-10-22 + ### Security - Upgrade the HTTP, spreadsheet and ZIP dependency graph to patched TLS and archive releases. - Track the workspace lockfile so CI audits the same resolution used by CLI and binding builds. + Library consumers must refresh their application lockfiles to receive transitive TLS fixes; + a dependency library's lockfile is not inherited. - Run JavaScript build and packaging workflows on Node.js 24.22.1. +- Include the generated JavaScript loader and native binary in npm packages and verify installed package loading. +- Scope npm native artifacts explicitly to Linux x64/glibc; other platforms are not included in this release. +- Verify Python wheel metadata and native extraction before upload; the wheel publisher targets Linux x64/CPython 3.12. ### Changed diff --git a/Cargo.lock b/Cargo.lock index 3252f1f..3b7beee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1292,7 +1292,7 @@ checksum = "4050469837a6ff301cd14c1f8f24f88549e6d548f24f64e2148eb0f72cebc51f" [[package]] name = "markkit" -version = "0.1.0" +version = "0.1.1" dependencies = [ "anyhow", "async-trait", @@ -1323,7 +1323,7 @@ dependencies = [ [[package]] name = "markkit-bench" -version = "0.1.0" +version = "0.1.1" dependencies = [ "anyhow", "clap", @@ -1339,7 +1339,7 @@ dependencies = [ [[package]] name = "markkit-cli" -version = "0.1.0" +version = "0.1.1" dependencies = [ "anyhow", "clap", @@ -1352,7 +1352,7 @@ dependencies = [ [[package]] name = "markkit-eval" -version = "0.1.0" +version = "0.1.1" dependencies = [ "anyhow", "async-trait", @@ -1367,7 +1367,7 @@ dependencies = [ [[package]] name = "markkit-js" -version = "0.1.0" +version = "0.1.1" dependencies = [ "markkit", "napi", @@ -1380,7 +1380,7 @@ dependencies = [ [[package]] name = "markkit-python" -version = "0.1.0" +version = "0.1.1" dependencies = [ "markkit", "pyo3", diff --git a/Cargo.toml b/Cargo.toml index 497a02c..fe4a37d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ members = [ ] [workspace.package] -version = "0.1.0" +version = "0.1.1" edition = "2024" license = "MIT" authors = ["Everruns "] diff --git a/crates/markkit-cli/Cargo.toml b/crates/markkit-cli/Cargo.toml index 89cf8bd..21cf10d 100644 --- a/crates/markkit-cli/Cargo.toml +++ b/crates/markkit-cli/Cargo.toml @@ -26,7 +26,7 @@ docx = ["markkit/docx"] spreadsheet = ["markkit/spreadsheet"] [dependencies] -markkit = { path = "../markkit", version = "0.1.0", features = ["http_client"] } +markkit = { path = "../markkit", version = "0.1.1", features = ["http_client"] } tokio = { workspace = true, features = ["macros", "net", "rt", "rt-multi-thread", "time", "fs"] } clap.workspace = true anyhow.workspace = true diff --git a/crates/markkit-js/README.md b/crates/markkit-js/README.md new file mode 100644 index 0000000..ccd1d8a --- /dev/null +++ b/crates/markkit-js/README.md @@ -0,0 +1,17 @@ +# @everruns/markkit + +Native Node.js bindings for Markkit HTML-to-Markdown extraction. + +This npm release supports **Linux x64 with glibc**. It does not include binaries for +macOS, Windows, ARM64 or musl Linux. Other platforms require a separate future +native release; Rust and Python package availability is independent. + +The package contains its JavaScript loader and native binary. CI verifies a clean +installation and extraction smoke on Node.js 24.22.1 before publication. Use a +currently supported Node.js release with its security patches installed. + +```js +const { extractHtmlSync } = require('@everruns/markkit'); +console.log(extractHtmlSync('

Hello

')); +// # Hello +``` diff --git a/crates/markkit-js/package.json b/crates/markkit-js/package.json index 1d1df88..2d8b9f0 100644 --- a/crates/markkit-js/package.json +++ b/crates/markkit-js/package.json @@ -1,6 +1,6 @@ { "name": "@everruns/markkit", - "version": "0.1.0", + "version": "0.1.1", "description": "Extract clean markdown from any format – Node.js bindings", "main": "index.js", "types": "index.d.ts", @@ -17,9 +17,22 @@ }, "files": [ "index.js", - "index.d.ts" + "index.d.ts", + "*.node" ], "devDependencies": { "@napi-rs/cli": "^3" - } + }, + "publishConfig": { + "access": "public" + }, + "os": [ + "linux" + ], + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ] } diff --git a/crates/markkit-python/README.md b/crates/markkit-python/README.md new file mode 100644 index 0000000..fff75d2 --- /dev/null +++ b/crates/markkit-python/README.md @@ -0,0 +1,17 @@ +# markkit-python + +Native Python bindings for Markkit HTML-to-Markdown extraction. + +The current wheel publisher builds for **Linux x64 and CPython 3.12**. It does not +publish macOS, Windows, ARM64 or other Python-version wheels. Other wheel targets +require a separate future release; Rust and npm availability is independent. + +```python +import markkit_python + +print(markkit_python.extract_html_sync("

Hello

")) +# # Hello +``` + +Publication verifies wheel metadata, installs the actual wheel into a clean +virtual environment and exercises native extraction before upload. diff --git a/specs/release-process.md b/specs/release-process.md index 8564025..e7c8219 100644 --- a/specs/release-process.md +++ b/specs/release-process.md @@ -35,3 +35,17 @@ version from `Cargo.toml`. Python and npm packages are published separately with | Rust crate | `cargo publish` | crates.io | | Python wheel | `maturin build` | PyPI | | npm package | `napi build` | npm | + +## Native package scope and verification + +Run the Python and npm publishers from the same verified release tag as Rust. +The initial npm artifact supports Linux x64/glibc only, and the current Python +wheel publisher targets Linux x64/CPython 3.12 only. Other platforms and interpreters +are not claimed as available; a future native release can expand coverage. + +Both publishers default to a credential-free dry run. Actual publication requires +an existing publisher credential before building; missing credentials fail without +printing values. Do not create credentials or alter permissions to complete a release. +Before upload, npm installs and loads its packed tarball (loader plus native binary), +and Python checks metadata and imports the built wheel in a clean virtual environment. +Both builds must preserve the patched Cargo.lock.