From 8523e91b51453ca48fea011106066cc1578049c1 Mon Sep 17 00:00:00 2001 From: Danite Date: Mon, 6 Apr 2026 18:41:34 +0200 Subject: [PATCH 1/4] ci: add publish workflow --- .github/workflows/release.yml | 37 +++++++++++++++++++ Cargo.lock | 4 +- Cargo.toml | 8 +++- README.md | 4 +- tests/json_output_test.rs | 4 +- tests/sarif_output_test.rs | 7 +++- .../json_output_test__json_manifest.snap | 2 +- .../sarif_output_test__sarif_output.snap | 2 +- 8 files changed, 56 insertions(+), 12 deletions(-) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..f50f738 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,37 @@ +name: Release + +on: + release: + types: [published] + +env: + CARGO_TERM_COLOR: always + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - uses: Swatinem/rust-cache@v2 + + - name: Extract version from tag + id: version + run: | + VERSION="${GITHUB_REF_NAME#v}" + if ! echo "$VERSION" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+$'; then + echo "::error::Tag must be in vX.Y.Z format, got: $GITHUB_REF_NAME" + exit 1 + fi + echo "value=$VERSION" >> "$GITHUB_OUTPUT" + + - name: Patch Cargo.toml version + run: sed -i "s/^version = .*/version = \"${{ steps.version.outputs.value }}\"/" Cargo.toml + + - name: Run tests + run: cargo test + + - name: Publish to crates.io + run: cargo publish --allow-dirty + env: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} diff --git a/Cargo.lock b/Cargo.lock index 2f9e973..21abe75 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -670,8 +670,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] -name = "looper" -version = "0.1.0" +name = "looper-cli" +version = "0.0.0-dev" dependencies = [ "chrono", "clap", diff --git a/Cargo.toml b/Cargo.toml index d36fd8b..b557ff4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "looper" -version = "0.1.0" +name = "looper-cli" +version = "0.0.0-dev" edition = "2021" description = "Static analysis tool that discovers implicit shadow dependencies in JavaScript/TypeScript codebases" license = "MIT" @@ -10,6 +10,10 @@ homepage = "https://github.com/Danite/looper" readme = "README.md" keywords = ["static-analysis", "shadow-dependencies", "javascript", "typescript", "devops"] categories = ["command-line-utilities", "development-tools"] +exclude = [".beads/", ".cursor/", ".github/", "sandbox/", "working/"] + +[lib] +name = "looper" [[bin]] name = "looper" diff --git a/README.md b/README.md index 2996347..e93b921 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ looper v0.1.0 — scanned 142 files in 48ms ## Install ```bash -cargo install looper +cargo install looper-cli ``` ## What It Finds @@ -77,7 +77,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - run: cargo install looper + - run: cargo install looper-cli - run: looper check - run: looper drift --fail-on-missing ``` diff --git a/tests/json_output_test.rs b/tests/json_output_test.rs index 3c0d63b..2354c3f 100644 --- a/tests/json_output_test.rs +++ b/tests/json_output_test.rs @@ -56,7 +56,7 @@ fn json_output_is_valid() { let parsed: serde_json::Value = serde_json::from_str(&json_str).unwrap(); assert_eq!(parsed["schema_version"], "1"); - assert_eq!(parsed["tool_version"], "0.1.0"); + assert_eq!(parsed["tool_version"], env!("CARGO_PKG_VERSION")); assert_eq!(parsed["root"], "."); assert_eq!(parsed["files_scanned"], 142); assert_eq!(parsed["scan_duration_ms"], 48); @@ -87,8 +87,8 @@ fn json_output_snapshot() { let json_str = format_json(&manifest).unwrap(); let mut parsed: serde_json::Value = serde_json::from_str(&json_str).unwrap(); - // Redact dynamic field for stable snapshots parsed["scanned_at"] = serde_json::Value::String("[timestamp]".into()); + parsed["tool_version"] = serde_json::Value::String("[version]".into()); insta::assert_json_snapshot!("json_manifest", parsed); } diff --git a/tests/sarif_output_test.rs b/tests/sarif_output_test.rs index 492c22b..a98531d 100644 --- a/tests/sarif_output_test.rs +++ b/tests/sarif_output_test.rs @@ -56,7 +56,7 @@ fn sarif_has_tool_info() { let driver = &parsed["runs"][0]["tool"]["driver"]; assert_eq!(driver["name"], "looper"); - assert_eq!(driver["version"], "0.1.0"); + assert_eq!(driver["version"], env!("CARGO_PKG_VERSION")); } #[test] @@ -137,7 +137,10 @@ fn sarif_snapshot() { let sarif_str = format_sarif(&manifest).unwrap(); let parsed: serde_json::Value = serde_json::from_str(&sarif_str).unwrap(); - insta::assert_json_snapshot!("sarif_output", parsed); + let mut redacted = parsed.clone(); + redacted["runs"][0]["tool"]["driver"]["version"] = + serde_json::Value::String("[version]".into()); + insta::assert_json_snapshot!("sarif_output", redacted); } #[test] diff --git a/tests/snapshots/json_output_test__json_manifest.snap b/tests/snapshots/json_output_test__json_manifest.snap index db29fd7..257aaa7 100644 --- a/tests/snapshots/json_output_test__json_manifest.snap +++ b/tests/snapshots/json_output_test__json_manifest.snap @@ -62,5 +62,5 @@ expression: parsed "scan_duration_ms": 48, "scanned_at": "[timestamp]", "schema_version": "1", - "tool_version": "0.1.0" + "tool_version": "[version]" } diff --git a/tests/snapshots/sarif_output_test__sarif_output.snap b/tests/snapshots/sarif_output_test__sarif_output.snap index fa32bcb..c05ca95 100644 --- a/tests/snapshots/sarif_output_test__sarif_output.snap +++ b/tests/snapshots/sarif_output_test__sarif_output.snap @@ -133,7 +133,7 @@ expression: parsed } } ], - "version": "0.1.0" + "version": "[version]" } } } From fe6c29270777298b875ce26a80fb12465b2c9482 Mon Sep 17 00:00:00 2001 From: Danite Date: Mon, 6 Apr 2026 18:49:37 +0200 Subject: [PATCH 2/4] fix tests --- Cargo.lock | 2 +- Cargo.toml | 2 +- tests/sarif_output_test.rs | 7 +++---- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 21abe75..444eebf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -671,7 +671,7 @@ checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] name = "looper-cli" -version = "0.0.0-dev" +version = "0.0.1" dependencies = [ "chrono", "clap", diff --git a/Cargo.toml b/Cargo.toml index b557ff4..c229ebf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "looper-cli" -version = "0.0.0-dev" +version = "0.0.1" edition = "2021" description = "Static analysis tool that discovers implicit shadow dependencies in JavaScript/TypeScript codebases" license = "MIT" diff --git a/tests/sarif_output_test.rs b/tests/sarif_output_test.rs index a98531d..62557a1 100644 --- a/tests/sarif_output_test.rs +++ b/tests/sarif_output_test.rs @@ -135,12 +135,11 @@ fn sarif_properties_include_metadata() { fn sarif_snapshot() { let manifest = build_manifest(".", 10, 5, sample_deps()); let sarif_str = format_sarif(&manifest).unwrap(); - let parsed: serde_json::Value = serde_json::from_str(&sarif_str).unwrap(); + let mut parsed: serde_json::Value = serde_json::from_str(&sarif_str).unwrap(); - let mut redacted = parsed.clone(); - redacted["runs"][0]["tool"]["driver"]["version"] = + parsed["runs"][0]["tool"]["driver"]["version"] = serde_json::Value::String("[version]".into()); - insta::assert_json_snapshot!("sarif_output", redacted); + insta::assert_json_snapshot!("sarif_output", parsed); } #[test] From 3fdea3fb1c11ddfc616554f30e6e3e036aba15f7 Mon Sep 17 00:00:00 2001 From: Danite Date: Mon, 6 Apr 2026 18:53:27 +0200 Subject: [PATCH 3/4] fix format --- tests/sarif_output_test.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/sarif_output_test.rs b/tests/sarif_output_test.rs index 62557a1..8f79494 100644 --- a/tests/sarif_output_test.rs +++ b/tests/sarif_output_test.rs @@ -137,8 +137,7 @@ fn sarif_snapshot() { let sarif_str = format_sarif(&manifest).unwrap(); let mut parsed: serde_json::Value = serde_json::from_str(&sarif_str).unwrap(); - parsed["runs"][0]["tool"]["driver"]["version"] = - serde_json::Value::String("[version]".into()); + parsed["runs"][0]["tool"]["driver"]["version"] = serde_json::Value::String("[version]".into()); insta::assert_json_snapshot!("sarif_output", parsed); } From 8f50b844979800f175534c8092844a8db59376f9 Mon Sep 17 00:00:00 2001 From: Danite Date: Mon, 6 Apr 2026 19:06:13 +0200 Subject: [PATCH 4/4] clean up --- .github/workflows/release.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f50f738..6a92de9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,6 +10,8 @@ env: jobs: publish: runs-on: ubuntu-latest + permissions: + contents: read steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable @@ -26,7 +28,7 @@ jobs: echo "value=$VERSION" >> "$GITHUB_OUTPUT" - name: Patch Cargo.toml version - run: sed -i "s/^version = .*/version = \"${{ steps.version.outputs.value }}\"/" Cargo.toml + run: sed -i "0,/^version = /{s/^version = .*/version = \"${{ steps.version.outputs.value }}\"/}" Cargo.toml - name: Run tests run: cargo test