Commit Graph

56 Commits

Author SHA1 Message Date
apk 9ce7b6b39c chore(ci): retire basta-release.yml, basta releases from its own repo
basta now has a proper release: github.com/kucherenko/basta got its
own signed GitHub release with binaries, checksums, provenance and
sigstore signatures (mirroring what this repo's own release does),
built on the release surface its repo was already designed for (a
submodule pin to this workspace + its own v*-tag-triggered workflow)
but had never actually used.

That makes this repo's basta-release.yml redundant — it duplicated
that same publish logic and never created a release with artifacts
anywhere. Remove it; jscpd's own crates-publish.yml is unaffected,
since its basta-backfill logic (publishing basta as a dependency when
a fresh jscpd release needs it on crates.io first) is self-contained
and doesn't depend on basta-release.yml existing.
2026-09-18 17:48:24 +02:00
apk 94fb6c3ef0 fix(ci): don't recreate the jscpd GitHub release over a basta-only bump
basta is a workspace member but releases on its own basta-v* tag; a
version bump to it alone still made the crates_needs_publish loop
over crates/*/Cargo.toml return true, which made create-rust-github-
release try to recreate the still-current jscpd release and fail with
"Release.tag_name already exists" (seen pushing the basta 0.1.2 bump
to master before tagging it).

Track a narrower cpd_needs_publish signal (true only when the jscpd
crate itself is unpublished) and gate the GitHub release on that
instead of the broad crates_needs_publish, which stays as-is for
gating the crates.io publish job — that one is supposed to backfill
basta too.
2026-09-18 16:07:56 +02:00
apk afea9b1cc6 feat(release): publish jscpd platform wheels to PyPI
Closes #1037.

Adds rust/scripts/build-pypi-wheels.py, which repacks the eight
jscpd-<platform>.tar.gz release tarballs into platform wheels: the same
binary under <pkg>.data/scripts/ as both `jscpd` and `cpd`, one wheel
per target, stdlib only, no maturin and no recompilation. glibc wheels
take their manylinux floor from the GLIBC_x.y symbols in the binary
(manylinux_2_34 today), musl builds are static so they tag as
musllinux_1_2, macOS and Windows use the Rust minimums. Semver
pre-releases map to PEP 440 (5.3.0-beta.1 -> 5.3.0b1); other labels
fail rather than guess.

release.yml gains a rust-publish-pypi job after the npm publish: it
takes the binary artifacts from this run, refills any missing target
from the published npm platform package (resumed releases, or a version
already on npm), builds the wheels, pip-installs the matching one and
checks `jscpd --version` and `cpd --version`, then uploads with PyPI
trusted publishing (environment `pypi`, no token, skip-existing). The
detect job treats a version missing from PyPI as pending, so the wheels
for the current release publish on the next push to master without a
new release commit. The GitHub release lists the PyPI package and waits
on the upload the same way it waits on crates.io and npm.

Docs: PyPI in the README install table and packages table, rust/README
and docs/rust.md install sections, and a `language: python` pre-commit
option in docs/ci-and-hooks.md so the hook no longer needs Node.js.

Claude-Session: https://claude.ai/code/session_01WztdFKZAwW9b51iJe9zhtV
2026-09-10 13:56:08 +02:00
apk d790c6c1d3 chore: make master v5-only
Everything belonging to the v4 TypeScript engine moves to the master-v4
branch: apps/, packages/, build-utils/, changesets, pnpm workspace, turbo,
the Node.js CI workflow and the ts-* release jobs. What remains is the
Rust workspace under rust/, the npm wrapper and platform packages, the
GitHub Action, Docker image, flake, skills, benchmark and fixtures/.

- rust.yml gains a smoke job that runs the release binary against
  fixtures/ (json, sarif, html) and asserts clones and reporters
- release.yml keeps only the Rust jobs; pnpm removed from every workflow;
  audit.yml keeps cargo audit + cargo deny; dependabot drops the root npm entry
- root package.json becomes a thin private package depending on the exact
  jscpd@5 version so the pre-commit hook keeps installing the binary;
  sync-version.mjs keeps it in step
- .pre-commit-hooks.yaml used v4-only flags that the v5 CLI rejects; fixed
- FORMATS.md is now generated from the Rust tokenizer (224 formats)
- README, docs, CONTRIBUTING, SECURITY, package and crate descriptions,
  benchmark and skills rewritten for v5 on its own terms: no v5-vs-v4 speed
  multipliers anywhere, a single "Looking for v4?" pointer to master-v4
2026-09-02 10:15:10 +02:00
apk b0c31a4042 chore: apply audit fixes across repo, crates, npm wrapper and pipelines
Rust / crates.io
- report the invoked binary name in --version/--help (jscpd vs cpd)
- add repository, documentation, keywords, categories to all crates
- exclude tests/ from the jscpd crate package; add cargo-binstall metadata
- expand the crates.io README and render it on docs.rs

npm
- add funding field to jscpd, cpd and jscpd@4 packages
- add jscpd-linux-arm64-musl platform package and clearer unsupported-platform error
- enable provenance for the v4 changeset publish

Pipelines
- rust.yml: windows-latest in the matrix, drop dead schedule guard
- release.yml: cosign-sign release assets, floating v5 tag, LICENSE in tarballs,
  invoke the new docker.yml (GHCR multi-arch image) after each release
- audit.yml: nightly cargo audit, cargo deny and pnpm audit
- Dockerfile: multi-stage image from release binaries (distroless), mcp target for Glama

Docs / community
- README: shields badges, single primary install per OS, GitHub Action snippet,
  link to jscpd.dev, v5.1 features, 15 reporters, 224 formats, 8 platforms
- docs: @v5 action tag, Docker usage, baseline section, current crate versions
- YAML issue forms with engine selector, config.yml, CODEOWNERS
- remove stale .github/CONTRIBUTING.md stub, custom.md, TODO.md; untrack rust/jscpd-report.json
- examples: mark as v4 API, add a Rust cpd-finder example
2026-09-02 09:57:06 +02:00
apk 5a125dad51 fix(release): don't report just-published packages as 'Not Yet Published'
The release-notes package check ran a single 'npm view' per package
immediately after publishing. npm reads are eventually consistent, so a
package published seconds earlier can still be invisible — v5.1.0 shipped
with a stale 'Not Yet Published: jscpd@5.1.0 (published: 5.0.16)' section
even though the publish had succeeded.

Re-check only the packages still missing, against one shared deadline
(5 min) so a genuinely unpublished package can't stretch the wait, and
report the results in stable package order. Same fix in the TypeScript
release job, which had the identical single-shot check.
2026-08-30 15:09:09 +02:00
apk 3aee6c4c58 fix(ci): install clippy/rustfmt for pinned 1.97.1 toolchain
Pinning rust-toolchain.toml to 1.97.1 made rustup auto-install a bare
1.97.1 toolchain in CI instead of using the dtolnay-installed 1.97 one
that carried clippy and rustfmt, failing the Clippy step. Declare the
components in the toolchain file so any auto-install includes them, and
align the workflow toolchain pins to 1.97.1 so CI installs the exact
toolchain cargo resolves.

Claude-Session: https://claude.ai/code/session_01VvWzWfEK6oV4HTe6EoGkff
2026-08-29 13:34:21 +02:00
Marvin Luchs b01910ddc2 feat: add support for Windows on ARM 2026-08-26 16:47:39 +02:00
apk f23f39ea03 ci: sign releases with SLSA provenance, pin download pipes (Scorecard)
Improves the OpenSSF Scorecard results (currently 7.2):

- Signed-Releases (0/10): release jobs now generate a sha256
  checksums.txt and signed SLSA build provenance for the binary
  tarballs via actions/attest-build-provenance (keyless, OIDC), and
  upload the Sigstore bundle as a multiple.intoto.jsonl release asset.
  Users can verify assets with
  `gh attestation verify <asset> --repo kucherenko/jscpd`.
- Pinned-Dependencies (8/10): the five `curl | node -e` pipelines that
  parse the crates.io API response are `curl | jq` now — jq consumes
  the download as data, so nothing downloaded is piped into an
  interpreter. The remaining npm warning is the post-publish smoke
  test installing the just-published exact version from the live
  registry, which is the point of that step.
- README: add Socket.dev and OpenSSF Scorecard badges.

release-rust.yml is currently uncalled (release.yml creates the
releases) but gets the same signing steps so it stays correct if
revived.
2026-08-21 08:02:20 +02:00
dependabot[bot] 4a3218d4d1 chore(deps): bump actions/checkout from 5.1.0 to 7.0.1
Bumps [actions/checkout](https://github.com/actions/checkout) from 5.1.0 to 7.0.1.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09...3d3c42e5aac5ba805825da76410c181273ba90b1)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-21 03:07:39 +00:00
apk 35d287e9f4 chore(rust): bump toolchain to 1.97, fix new clippy lints 2026-08-15 20:52:56 +02:00
Andrey Kucherenko 9c36be5535 Merge pull request #928 from kucherenko/dependabot/github_actions/actions/setup-node-7.0.0
chore(deps): bump actions/setup-node from 5.0.0 to 7.0.0
2026-08-14 12:48:25 +02:00
Andrey Kucherenko 326c72e652 Merge pull request #926 from kucherenko/dependabot/github_actions/actions/download-artifact-8.0.1
chore(deps): bump actions/download-artifact from 4.3.0 to 8.0.1
2026-08-14 12:47:55 +02:00
Andrey Kucherenko 6ad657eb33 Merge pull request #924 from kucherenko/dependabot/github_actions/dorny/test-reporter-3
chore(deps): bump dorny/test-reporter from 1 to 3
2026-08-14 12:47:17 +02:00
Andrey Kucherenko 780a13c835 Merge pull request #923 from kucherenko/dependabot/github_actions/pnpm/action-setup-6.0.10
chore(deps): bump pnpm/action-setup from 4.3.0 to 6.0.10
2026-08-14 12:47:01 +02:00
dependabot[bot] 0a5d76ccfd chore(deps): bump actions/setup-node from 5.0.0 to 7.0.0
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 5.0.0 to 7.0.0.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/a0853c24544627f65ddf259abe73b1d18a591444...820762786026740c76f36085b0efc47a31fe5020)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-14 09:05:21 +00:00
dependabot[bot] 451838f549 chore(deps): bump actions/download-artifact from 4.3.0 to 8.0.1
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4.3.0 to 8.0.1.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/d3f86a106a0bac45b974a628896c90dbdf5c8093...3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: 8.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-14 09:05:13 +00:00
dependabot[bot] 506d68fb70 chore(deps): bump dorny/test-reporter from 1 to 3
Bumps [dorny/test-reporter](https://github.com/dorny/test-reporter) from 1 to 3.
- [Release notes](https://github.com/dorny/test-reporter/releases)
- [Changelog](https://github.com/dorny/test-reporter/blob/main/CHANGELOG.md)
- [Commits](https://github.com/dorny/test-reporter/compare/3eeb9fc888e82e8be2fb356bbeec2750231672bc...a43b3a5f7366b97d083190328d2c652e1a8b6aa2)

---
updated-dependencies:
- dependency-name: dorny/test-reporter
  dependency-version: '3'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-14 09:05:08 +00:00
dependabot[bot] 209ddd3e17 chore(deps): bump pnpm/action-setup from 4.3.0 to 6.0.10
Bumps [pnpm/action-setup](https://github.com/pnpm/action-setup) from 4.3.0 to 6.0.10.
- [Release notes](https://github.com/pnpm/action-setup/releases)
- [Commits](https://github.com/pnpm/action-setup/compare/b906affcce14559ad1aafd4ab0e942779e9f58b1...0977fd99725f1db4007ccb2928dbb4e90d06cc86)

---
updated-dependencies:
- dependency-name: pnpm/action-setup
  dependency-version: 6.0.10
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-14 09:05:02 +00:00
dependabot[bot] 1d9314e6b5 chore(deps): bump actions/upload-artifact from 4 to 7
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 7.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4...v7)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-14 09:04:57 +00:00
apk 968c2af122 sec: harden supply chain per OpenSSF Scorecard findings
- pin every GitHub Action to a full commit SHA (with version comments);
  add github-actions ecosystem to Dependabot to keep the pins fresh
- follow least privilege for workflow tokens: top-level contents:read
  everywhere, checks/id-token/contents write grants scoped to the jobs
  that need them (test-reporter, npm/crates trusted publishing,
  gh release create)
- add SECURITY.md with private disclosure channels and supported versions

Also enabled outside the repo: master branch ruleset (no force-push or
deletion) and GitHub private vulnerability reporting.
2026-08-14 11:04:03 +02:00
apk 7a01672634 chore: pin GitHub 'Latest' badge to v5 releases, polish npm package page
- release.yml: mark the Rust v5 release --latest, the legacy TS v4 and
  cpd releases --latest=false so v4 tags never steal the Latest badge
- rust/jscpd/README.md: use absolute GitHub URLs so links work on npmjs.com
- rust/jscpd/package.json: richer description and search keywords
2026-08-14 10:57:36 +02:00
apk 8d83e984ef fix(ci): npm rejects 'v4' as a dist-tag (valid semver range); use latest-4 2026-08-13 18:23:24 +02:00
apk 494602ed50 fix(ci): keep the jscpd npm latest tag on the v5 line
The jscpd package ships from two release lines: 4.x (TypeScript) and
5.x (Rust wrapper). changeset publish always passes --tag latest (it
ignores publishConfig.tag), so the v4.3.0 maintenance release moved
'latest' from 5.0.15 back to 4.3.0 and 'npx jscpd' started installing
v4 again.

Add a guard step after the TS publish that re-points 'latest' at the
newest 5.x and keeps a 'v4' dist-tag on the newest 4.x, plus a
manually-dispatchable npm-dist-tags workflow with the same logic for
one-off repairs.
2026-08-13 18:21:21 +02:00
apk 1b03f0e9b4 fix(security): resolve all 27 open Dependabot alerts; restore pnpm overrides
The security overrides lived in package.json's "pnpm.overrides", which
pnpm 10 silently stopped reading (settings moved to pnpm-workspace.yaml)
— so none of them applied and transitive-dependency alerts piled up.

- Move all overrides to pnpm-workspace.yaml and update them to the
  patched minimums for every open alert: fast-uri >=3.1.5, hono
  >=4.12.34, @hono/node-server >=1.19.15, js-yaml >=3.15.1/4.3.1,
  brace-expansion >=1.1.16/5.0.9, nanoid >=3.3.17, postcss >=8.5.23,
  ip-address >=10.3.1, body-parser >=2.3.0 (each annotated with its
  GHSA id).
- Regenerate pnpm-lock.yaml; pnpm dedupe cleared a stale postcss peer
  resolution. All affected packages now resolve to patched versions and
  --frozen-lockfile passes.
- Drop the now-ignored pnpm block from package.json so dead config
  can't mask itself as protection again.
- CI: install with --frozen-lockfile in nodejs.yml and release.yml so
  lockfile corruption or drift fails loudly instead of silently
  re-resolving dependencies from the registry (follow-up from #901).

Verified: pnpm build (10/10 tasks), pnpm test (5/5 suites), and
jscpd-server tests (43/43) all pass on the updated resolutions.
2026-08-13 11:46:32 +02:00
Andrey Kucherenko ff1ae361fb fix(rust): rename cpd binary and npm platform packages to jscpd
Renames the compiled binary from cpd(.exe) to jscpd(.exe) and the
platform-specific optional-dependency npm packages from cpd-* to
jscpd-* to avoid collision with an antivirus-flagged executable name.

Fixes #826
2026-07-08 17:38:18 +02:00
apk 151725602f chore: update release pipelline, wait for cpd before publish jscpd 2026-06-21 07:40:22 +02:00
apk 65e4b26abb ci: quote multiline package-list outputs to avoid backtick command substitution
Fixes release note step failing with "cpd-core@0.1.5: command not found" because markdown backticks in the published/failed package lists were interpreted as command substitution when assigned inside double quotes.
2026-06-17 20:09:56 +02:00
apk 89730b56ad fix(ci): resilient action install + release binary assets
- action.yml: retry install script 3x with 10s delay between attempts
- action.yml: fallback to npm install when install script fails
- action.yml: Windows install retries with jscpd then cpd fallback
- action.yml: add skip-install input for pre-installed binaries
- action.yml: add exit-code output from jscpd run step
- action.yml: parse-output step uses always() instead of success() || failure()
- action.yml: Run step captures exit code instead of failing workflow
- release.yml: download binary artifacts and upload as release assets
- release.yml: replace awk/sed with node for changelog extraction (exit 127 fix)
- release-rust.yml: same binary asset + node changelog fixes
- npm-rust-publish.yml: archive and upload platform binaries as artifacts
2026-06-13 08:48:01 +02:00
apk 9002cf50b7 fix(ci): replace awk/sed with node for changelog extraction
awk was failing with exit code 127 on the GitHub Actions runner.
Use node -e (guaranteed available) for CHANGELOG parsing instead.
2026-06-13 08:04:00 +02:00
apk b3ed51adb0 feat(ci): add published packages info to GitHub releases
- Rust releases now list crates.io and npm packages with publish status
- TypeScript releases now list all workspace npm packages with publish status
- Fix crates.io User-Agent from kucheren/jscpd to kucherenko/jscpd
2026-06-12 10:26:47 +02:00
apk 4233370f43 fix(ci): disable setup-node package-manager-cache and enable rust-cache-on-failure
actions/setup-node@v5 enables package-manager-cache by default, which tries
to save the pnpm store in post-cleanup. When pnpm install is never run
(e.g. idempotent publish skip), the store path doesn't exist, causing
'Path Validation Error: Path(s) specified for caching do not exist'.

Also added cache-on-failure: true to all Swatinem/rust-cache steps to
ensure Cargo cache is saved even on failed builds.
2026-06-09 07:22:07 +02:00
apk 9533a08cd6 fix(ci): handle empty result for skipped reusable workflows in release conditions
When a reusable workflow call is skipped, GitHub Actions returns an
empty string for needs.*.result instead of 'skipped'. This caused the
GitHub release job to be skipped even when crates were successfully
published, because the npm publish workflow was skipped (already
published) and its result was '' which matched neither 'success' nor
'skipped'.

Switch from whitelisting result values to blacklisting 'failure' and
'cancelled', which correctly handles empty string results from skipped
reusable workflows.
2026-06-07 22:21:05 +02:00
apk 4c2e21ea22 fix(ci): allow rust-release to run when npm publish is skipped
When rust-publish-npm is skipped (npm already published), GitHub skips
all dependent jobs by default. Add always() && !cancelled() so the if
condition is actually evaluated, allowing the release to be created.
2026-06-07 21:26:48 +02:00
apk 442426cfc0 fix(ci): add User-Agent header to crates.io API calls and handle publish failures gracefully
The crates.io API returns 403 without a User-Agent header, causing curl -sf
to silently fail and return empty string. This made the skip check (comparing
max_version) always fail, so already-published crates were not skipped.

Also wrap cargo publish in if/then to continue past failures instead of
aborting the entire loop with set -e.
2026-06-07 21:20:28 +02:00
apk d7cd83a34c fix(ci): use HTTP API for pre-publish checks, cargo info for post-publish wait loop 2026-06-07 21:10:27 +02:00
apk a42646a51b fix(ci): use crates.io HTTP API for exact version detection instead of cargo info 2026-06-07 20:30:35 +02:00
apk dff140e93d fix(ci): move registry-based release detection into detect job so pipelines trigger even without rust/ file changes 2026-06-07 20:21:17 +02:00
apk 41920980ef fix(ci): split rust version detection into crates.io and npm checks against published versions 2026-06-07 20:16:51 +02:00
apk 14da1bee4e fix(ci): detect version bumps by comparing against published versions instead of git diff 2026-06-07 20:14:03 +02:00
apk a83fd2ca8a fix(ci): handle workspace Cargo.toml in rust version detection 2026-06-07 19:47:45 +02:00
apk f23a1122b7 ci: add pnpm/action-setup to rust-version and ts-version jobs
setup-node needs pnpm available because the repo uses pnpm as its
package manager (packageManager field in package.json).
2026-06-07 18:55:00 +02:00
apk f315385c12 ci: add checks:write permission to ts-ci job for test-reporter 2026-06-07 18:47:31 +02:00
apk 3c69d1c574 ci: build before test in ts-ci job
Turbo packages need built artifacts before tests can resolve workspace
dependencies like @jscpd/core. Order: install → build → lint → test.
2026-06-07 18:34:50 +02:00
apk 228961a62a ci: fix dual-branch triggers and robust version detection
- Both rust_changed and ts_changed can be true simultaneously
- Replace fragile echo|node -p /dev/stdin pattern with node -e stdin reader
  that handles pipefail and empty input gracefully
- Add actions/setup-node to rust-version and ts-version jobs (needed for
  node CLI after merged pipeline)
2026-06-07 17:05:14 +02:00
apk eb609c0295 ci: unified release pipeline for Rust (v5) and TypeScript (v4)
- Rewrite release.yml as single entry point on push to master
- Detect changed paths (rust/** vs non-rust) to select branch
- Rust branch: clippy → test → build, then version bump detection
- TypeScript branch: lint → test → build, then version bump detection
- Publish crates.io in topological order via cargo metadata (no hardcoding)
- Publish npm packages via existing changeset flow
- Create GitHub releases with CHANGELOG-extracted notes (v5.x / v4.x tags)
- Remove push triggers from helper workflows (crates-publish, npm-rust-publish, release-rust)
- release-rust.yml now workflow_call only with CHANGELOG extraction
- Add rust/CHANGELOG.md for v5 release notes
2026-06-07 16:11:02 +02:00
apk 82beadcc81 ci: improve GitHub Actions workflows
- add cargo-nextest test steps to all Rust pipelines (rust.yml,
  crates-publish.yml, npm-rust-publish.yml) with JUnit report upload
  via dorny/test-reporter
- add Vitest JUnit reporter to Node.js pipelines (nodejs.yml,
  release.yml) with test report display
- add rust/.config/nextest.toml with ci profile for JUnit output
- move platform-published check before build in npm-rust-publish.yml
  so already-published targets skip the entire build chain
- make each cargo publish step idempotent (skip if version exists)
- add master to rust.yml push/pull_request branch triggers
- publish-packages: remove changeset version (run separately)
2026-06-07 08:26:22 +02:00
apk c9ed823eae fix(ci): remove version param from pnpm/action-setup (uses packageManager), add FORCE_JAVASCRIPT_ACTIONS_TO_NODE24 2026-06-07 07:46:30 +02:00
apk e613929fc5 fix(ci): move pnpm/action-setup before setup-node for correct PATH resolution 2026-06-07 07:44:18 +02:00
apk 7def72ad57 fix(ci): use pnpm/action-setup instead of npm global install for PATH compatibility 2026-06-07 07:43:32 +02:00