mirror of
https://github.com/kucherenko/jscpd.git
synced 2026-09-19 08:11:03 +08:00
8de72db3ac
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.87.3 to 2.87.8. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/0758d235715de2f3551eacc980d9ae8fce9342c3...d438492cf8a250514fa2d34b30bc3c0dc37c65ff) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-version: 2.87.8 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com>
213 lines
7.5 KiB
YAML
213 lines
7.5 KiB
YAML
name: Rust
|
|
|
|
on:
|
|
push:
|
|
branches: [main, master, "heist/*"]
|
|
pull_request:
|
|
branches: [main, master, "heist/*"]
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
build:
|
|
permissions:
|
|
contents: read
|
|
checks: write # dorny/test-reporter posts check runs
|
|
runs-on: ${{ matrix.os }}
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
|
|
- uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable
|
|
with:
|
|
toolchain: "1.97.1"
|
|
components: clippy, rustfmt
|
|
|
|
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2
|
|
with:
|
|
workspaces: "rust -> rust/target"
|
|
cache-on-failure: true
|
|
|
|
- name: Install cargo-nextest
|
|
uses: taiki-e/install-action@d438492cf8a250514fa2d34b30bc3c0dc37c65ff # v2.87.8
|
|
with:
|
|
tool: nextest
|
|
|
|
- name: Build
|
|
working-directory: rust
|
|
run: cargo build --workspace
|
|
|
|
- name: Test
|
|
working-directory: rust
|
|
run: cargo nextest run --workspace --profile ci
|
|
|
|
- name: Upload test results
|
|
if: always()
|
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
with:
|
|
name: nextest-results-${{ matrix.os }}
|
|
path: rust/target/nextest/ci/nextest.xml
|
|
if-no-files-found: warn
|
|
|
|
- name: Test Report
|
|
if: always()
|
|
continue-on-error: true
|
|
uses: dorny/test-reporter@a43b3a5f7366b97d083190328d2c652e1a8b6aa2 # v3.0.0
|
|
with:
|
|
name: Rust Tests (${{ matrix.os }})
|
|
path: rust/target/nextest/ci/nextest.xml
|
|
reporter: java-junit
|
|
fail-on-error: false
|
|
|
|
- name: Clippy
|
|
working-directory: rust
|
|
run: cargo clippy --workspace -- -D warnings
|
|
|
|
- name: Format check
|
|
working-directory: rust
|
|
run: cargo fmt --check
|
|
|
|
# Bash-only steps below run on Linux; Windows defaults to pwsh.
|
|
- name: Tokenizer purity check
|
|
if: runner.os == 'Linux'
|
|
run: |
|
|
cd rust
|
|
TOKENIZER_DEPS=$(cargo metadata --format-version 1 | \
|
|
python3 -c "
|
|
import sys, json
|
|
meta = json.load(sys.stdin)
|
|
tokenizer_id = next(p['id'] for p in meta['packages'] if p['name'] == 'cpd-tokenizer')
|
|
dep_names = set()
|
|
queue = [tokenizer_id]
|
|
id_to_pkg = {p['id']: p for p in meta['packages']}
|
|
resolve_map = {n['id']: [d['pkg'] for d in n['deps']] for n in meta['resolve']['nodes']}
|
|
visited = set()
|
|
while queue:
|
|
pid = queue.pop()
|
|
if pid in visited: continue
|
|
visited.add(pid)
|
|
if pid in id_to_pkg:
|
|
dep_names.add(id_to_pkg[pid]['name'])
|
|
for dep_id in resolve_map.get(pid, []):
|
|
queue.append(dep_id)
|
|
print('\n'.join(dep_names))
|
|
")
|
|
echo "cpd-tokenizer transitive deps: $TOKENIZER_DEPS"
|
|
for crate in tokio async-std walkdir ignore jwalk; do
|
|
if echo "$TOKENIZER_DEPS" | grep -q "^$crate$"; then
|
|
echo "ERROR: cpd-tokenizer depends on I/O crate: $crate"
|
|
exit 1
|
|
fi
|
|
done
|
|
echo "Tokenizer purity check: PASS"
|
|
|
|
- name: publish=false check
|
|
if: runner.os == 'Linux'
|
|
run: |
|
|
cd rust
|
|
for toml in crates/*/Cargo.toml; do
|
|
if ! grep -q 'publish = false' "$toml"; then
|
|
echo "ERROR: $toml missing 'publish = false'"
|
|
exit 1
|
|
fi
|
|
done
|
|
echo "publish=false check: PASS"
|
|
|
|
- name: cargo-deny
|
|
if: matrix.os == 'ubuntu-latest'
|
|
working-directory: rust
|
|
run: cargo install cargo-deny --locked && cargo deny check
|
|
|
|
msrv:
|
|
name: MSRV
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
|
|
- name: Read declared MSRV
|
|
id: msrv
|
|
run: |
|
|
version=$(sed -nE 's/^rust-version = "([0-9.]+)"$/\1/p' rust/Cargo.toml | head -1)
|
|
if [ -z "$version" ]; then
|
|
echo "ERROR: no rust-version found in rust/Cargo.toml"
|
|
exit 1
|
|
fi
|
|
echo "Declared MSRV: $version"
|
|
echo "version=$version" >> "$GITHUB_OUTPUT"
|
|
|
|
- uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable
|
|
with:
|
|
toolchain: ${{ steps.msrv.outputs.version }}
|
|
|
|
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2
|
|
with:
|
|
workspaces: "rust -> rust/target"
|
|
key: msrv-${{ steps.msrv.outputs.version }}
|
|
cache-on-failure: true
|
|
|
|
# `+toolchain` outranks rust-toolchain.toml, which pins a newer compiler
|
|
# for day-to-day development. Without it this job would silently test the
|
|
# pinned version instead of the MSRV.
|
|
- name: cargo check at MSRV
|
|
working-directory: rust
|
|
run: cargo +${{ steps.msrv.outputs.version }} check --workspace --all-targets --locked
|
|
|
|
# End-to-end run of the release binary over the multi-format corpus in
|
|
# fixtures/ (550 files across 130+ formats). Unit tests cover the parts;
|
|
# this catches a reporter or walker regression that only shows on the
|
|
# real corpus.
|
|
smoke:
|
|
name: smoke test (fixtures corpus)
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
|
|
- uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable
|
|
with:
|
|
toolchain: "1.97.1"
|
|
|
|
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2
|
|
with:
|
|
workspaces: "rust -> rust/target"
|
|
key: smoke-release
|
|
cache-on-failure: true
|
|
|
|
- name: Build release binary
|
|
working-directory: rust
|
|
run: cargo build --release -p jscpd --locked
|
|
|
|
- name: Scan fixtures (console + json)
|
|
working-directory: rust
|
|
run: ./target/release/jscpd ../fixtures --reporters console,json --output ../smoke-report --min-tokens 50
|
|
|
|
- name: Assert JSON report
|
|
run: |
|
|
report=smoke-report/jscpd-report.json
|
|
test -s "$report"
|
|
clones=$(jq '.statistics.total.clones' "$report")
|
|
sources=$(jq '.statistics.total.sources' "$report")
|
|
formats=$(jq '.statistics.formats | keys | length' "$report")
|
|
duplicates=$(jq '.duplicates | length' "$report")
|
|
echo "clones=$clones sources=$sources formats=$formats duplicates=$duplicates"
|
|
[ "$clones" -gt 0 ] || { echo "expected statistics.total.clones > 0"; exit 1; }
|
|
[ "$duplicates" -eq "$clones" ] || { echo "duplicates[] length ($duplicates) != statistics.total.clones ($clones)"; exit 1; }
|
|
[ "$sources" -ge 300 ] || { echo "expected at least 300 scanned files, got $sources"; exit 1; }
|
|
[ "$formats" -ge 100 ] || { echo "expected at least 100 detected formats, got $formats"; exit 1; }
|
|
|
|
- name: SARIF reporter
|
|
working-directory: rust
|
|
run: |
|
|
./target/release/jscpd ../fixtures --reporters sarif,silent --output ../smoke-report --min-tokens 50
|
|
jq -e '.runs[0].results | length > 0' ../smoke-report/jscpd-report.sarif
|
|
|
|
- name: HTML reporter
|
|
working-directory: rust
|
|
run: |
|
|
./target/release/jscpd ../fixtures --reporters html,silent --output ../smoke-report --min-tokens 50
|
|
test -s ../smoke-report/jscpd-report.html
|