diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..6a92de9 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,39 @@ +name: Release + +on: + release: + types: [published] + +env: + CARGO_TERM_COLOR: always + +jobs: + publish: + runs-on: ubuntu-latest + permissions: + contents: read + 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 "0,/^version = /{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..444eebf 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.1" dependencies = [ "chrono", "clap", diff --git a/Cargo.toml b/Cargo.toml index d36fd8b..c229ebf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "looper" -version = "0.1.0" +name = "looper-cli" +version = "0.0.1" 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..8f79494 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] @@ -135,8 +135,9 @@ 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(); + parsed["runs"][0]["tool"]["driver"]["version"] = serde_json::Value::String("[version]".into()); insta::assert_json_snapshot!("sarif_output", parsed); } 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]" } } }