From 9042576dc3dff5714cbaae9d236aa536d5128bc5 Mon Sep 17 00:00:00 2001 From: jupblb Date: Mon, 18 May 2026 15:29:40 +0200 Subject: [PATCH 01/22] Add flake.nix for Nix packaging and Docker image - packages.scip-rust: writeShellApplication wrapping the scip-rust script with rust-analyzer, cargo, and rustc on PATH via runtimeInputs. - packages.docker (Linux only): minimal layered image built with dockerTools.buildLayeredImage; bundles scip-rust, CA certs, and git. - devShells.default: rust-analyzer, rustc, cargo. - checks.shellcheck: runs shellcheck against the wrapper script. --- flake.lock | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++ flake.nix | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100644 flake.lock create mode 100644 flake.nix diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..86c022c --- /dev/null +++ b/flake.lock @@ -0,0 +1,61 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1778737229, + "narHash": "sha256-6xWoytx8jFW4PF1GjRm/i/53trbpKGfz6zjzQGBr4cI=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "d7a713c0b7e47c908258e71cba7a2d77cc8d71d5", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-25.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..3c5ab16 --- /dev/null +++ b/flake.nix @@ -0,0 +1,65 @@ +{ + inputs = { + flake-utils.url = "github:numtide/flake-utils"; + nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11"; + }; + + outputs = + { + self, + flake-utils, + nixpkgs, + }: + flake-utils.lib.eachDefaultSystem ( + system: + let + pkgs = import nixpkgs { inherit system; }; + scip-rust = pkgs.writeShellApplication { + name = "scip-rust"; + runtimeInputs = with pkgs; [ + rust-analyzer + cargo + rustc + ]; + text = builtins.readFile ./scip-rust; + }; + in + { + packages = { + inherit scip-rust; + default = scip-rust; + } + // pkgs.lib.optionalAttrs pkgs.stdenv.isLinux { + docker = pkgs.dockerTools.buildLayeredImage { + name = "scip-rust"; + tag = "latest"; + contents = [ + scip-rust + pkgs.dockerTools.caCertificates + pkgs.git + ]; + fakeRootCommands = "mkdir -p /work /tmp"; + enableFakechroot = true; + config = { + Cmd = [ "scip-rust" ]; + WorkingDir = "/work"; + Env = [ "HOME=/tmp" ]; + }; + }; + }; + + checks.shellcheck = pkgs.runCommand "check-shellcheck" { } '' + ${pkgs.shellcheck}/bin/shellcheck ${./scip-rust} + touch $out + ''; + + devShells.default = pkgs.mkShellNoCC { + buildInputs = with pkgs; [ + rust-analyzer + rustc + cargo + ]; + }; + } + ); +} From 94a5c6afae62dcb3e38a9a35d4c7a0541d04235d Mon Sep 17 00:00:00 2001 From: jupblb Date: Mon, 18 May 2026 15:29:48 +0200 Subject: [PATCH 02/22] scip-rust: prefer bundled rust-analyzer, validate rustup toolchain Make the wrapper work both inside the Nix flake / Docker image (where rust-analyzer comes from PATH) and from a standalone release tarball (where rust-analyzer sits next to the wrapper). Fail fast with a friendly error pointing at rustup when cargo or rustc is missing on the host. --- scip-rust | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/scip-rust b/scip-rust index 3dc69a8..b9dc4c7 100755 --- a/scip-rust +++ b/scip-rust @@ -1,6 +1,26 @@ #!/usr/bin/env sh -set -eux +set -eu + +# Prefer a rust-analyzer bundled alongside this script (release-tarball layout); +# fall back to one on PATH (Nix flake / dev shell / Docker image with rustup). +HERE=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +if [ -x "$HERE/rust-analyzer" ]; then + RA="$HERE/rust-analyzer" +else + RA="rust-analyzer" +fi + +# rust-analyzer shells out to cargo/rustc to read project metadata; fail fast +# with an actionable error if the host toolchain is missing. +for tool in cargo rustc; do + if ! command -v "$tool" >/dev/null 2>&1; then + echo "error: scip-rust requires '$tool' on PATH." >&2 + echo "Install a Rust toolchain via rustup (https://rustup.rs)" >&2 + echo "and add the rust-src component: rustup component add rust-src" >&2 + exit 1 + fi +done # rust-analyzer's path lookup looks in subdirectories by default. For example, # in the general case, if you have multiple parallel workspaces, under say @@ -10,4 +30,5 @@ set -eux # crates (X1, X2, Y1 and Y2). So it is enough to run rust-analyzer once, # instead of once per workspace, or once per crate. -rust-analyzer scip . > dump.scip +set -x +exec "$RA" scip . From 5a553a0fd2a9fd04ef1db7e0d2ffabf79decd6ae Mon Sep 17 00:00:00 2001 From: jupblb Date: Mon, 18 May 2026 15:29:55 +0200 Subject: [PATCH 03/22] release: publish per-OS tarballs bundling rust-analyzer Add a release-tarballs matrix job alongside the existing Docker image release. Each tarball pairs the scip-rust wrapper with the pinned upstream rust-analyzer binary for that target, giving non-Nix users a small, self-contained download (~16 MB). Users still need a Rust toolchain on PATH (rustup); the wrapper enforces this. Targets: - aarch64-apple-darwin - x86_64-apple-darwin - aarch64-unknown-linux-gnu (rust-analyzer has no aarch64 musl build) - x86_64-unknown-linux-musl --- .github/workflows/release.yml | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 25f21c1..2c7254b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -5,7 +5,38 @@ on: tags: - v* +env: + RUST_ANALYZER_VERSION: "2026-05-18" + jobs: + release-tarballs: + runs-on: ubuntu-latest + permissions: + contents: write + strategy: + matrix: + target: + - aarch64-apple-darwin + - x86_64-apple-darwin + - aarch64-unknown-linux-gnu + - x86_64-unknown-linux-musl + steps: + - uses: actions/checkout@v4 + - name: Build tarball + run: | + set -eux + STAGE=stage/scip-rust + mkdir -p "$STAGE" + curl -fL "https://github.com/rust-lang/rust-analyzer/releases/download/${RUST_ANALYZER_VERSION}/rust-analyzer-${{ matrix.target }}.gz" \ + | gunzip > "$STAGE/rust-analyzer" + chmod +x "$STAGE/rust-analyzer" + install -m 755 scip-rust "$STAGE/scip-rust" + tar -C stage -czf "scip-rust-${{ matrix.target }}.tar.gz" scip-rust + - name: Upload to release + uses: softprops/action-gh-release@v2 + with: + files: scip-rust-${{ matrix.target }}.tar.gz + release-image: runs-on: ubuntu-latest steps: From a86ee5e30d4df10a1d0de19c4f27b9347cd40d39 Mon Sep 17 00:00:00 2001 From: jupblb Date: Mon, 18 May 2026 15:30:33 +0200 Subject: [PATCH 04/22] --- .github/PULL_REQUEST_TEMPLATE.md | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 .github/PULL_REQUEST_TEMPLATE.md diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md deleted file mode 100644 index a47c164..0000000 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ /dev/null @@ -1,9 +0,0 @@ -### Test plan - - From b462cc9113586556321614813600c6b36c6978af Mon Sep 17 00:00:00 2001 From: jupblb Date: Mon, 18 May 2026 16:05:52 +0200 Subject: [PATCH 05/22] ci: remove pr-auditor workflow Sourcegraph-internal SOC 2 audit bot. Not relevant to this repo. --- .github/workflows/pr-auditor.yml | 28 ---------------------------- 1 file changed, 28 deletions(-) delete mode 100644 .github/workflows/pr-auditor.yml diff --git a/.github/workflows/pr-auditor.yml b/.github/workflows/pr-auditor.yml deleted file mode 100644 index e39ed38..0000000 --- a/.github/workflows/pr-auditor.yml +++ /dev/null @@ -1,28 +0,0 @@ -# See https://docs.sourcegraph.com/dev/background-information/ci#pr-auditor -name: pr-auditor -on: - pull_request_target: - types: [ closed, edited, opened, synchronize, ready_for_review ] - workflow_dispatch: - -jobs: - check-pr: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - repository: 'sourcegraph/devx-service' - token: ${{ secrets.PR_AUDITOR_TOKEN }} - - uses: actions/setup-go@v4 - with: { go-version: '1.22' } - - - run: 'go run ./cmd/pr-auditor' - env: - GITHUB_EVENT_PATH: ${{ env.GITHUB_EVENT_PATH }} - GITHUB_TOKEN: ${{ secrets.PR_AUDITOR_TOKEN }} - GITHUB_RUN_URL: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} - report_failure: - needs: check-pr - if: ${{ failure() }} - uses: sourcegraph/workflows/.github/workflows/report-job-failure.yml@main - secrets: inherit From f149ab08d836d3587447290089af2be61212e2a2 Mon Sep 17 00:00:00 2001 From: jupblb Date: Mon, 18 May 2026 16:10:54 +0200 Subject: [PATCH 06/22] Build container image with Nix, drop Dockerfile The flake's packages.docker output produces the same kind of image the hand-written Dockerfile did (scip-rust + rust-analyzer + rustc + cargo + ca-certs + git, with a /work workdir), so there's no need to keep two parallel build paths. - Delete Dockerfile. - release.yml release-image: install Nix via DeterminateSystems' installer, 'nix build .#docker', then docker load / tag / push (matches the scip-go pattern). Tag scheme and DockerHub destination are unchanged. - Delete test-container.sh and the container-test.yml workflow that ran it; both existed only to smoke-test the Dockerfile and have no equivalent purpose now that nix flake check exercises the image build. --- .github/workflows/container-test.yml | 22 ---------------- .github/workflows/release.yml | 26 +++++++++---------- Dockerfile | 7 ----- test-container.sh | 39 ---------------------------- 4 files changed, 13 insertions(+), 81 deletions(-) delete mode 100644 .github/workflows/container-test.yml delete mode 100644 Dockerfile delete mode 100755 test-container.sh diff --git a/.github/workflows/container-test.yml b/.github/workflows/container-test.yml deleted file mode 100644 index 4458a27..0000000 --- a/.github/workflows/container-test.yml +++ /dev/null @@ -1,22 +0,0 @@ -name: Container Test - -on: - push: - branches: [ main ] - pull_request: - branches: [ main ] - -jobs: - container-test: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - name: Install Podman - run: | - sudo apt-get update - sudo apt-get install -y podman - - - name: Run container test - run: ./test-container.sh diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2c7254b..2ee6679 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -40,23 +40,23 @@ jobs: release-image: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: docker/setup-buildx-action@v1 + - uses: actions/checkout@v4 + - uses: DeterminateSystems/nix-installer-action@v22 - run: echo "PATCH=${GITHUB_REF/refs\/tags\//}" >> $GITHUB_ENV - run: echo "MINOR=${PATCH%.*}" >> $GITHUB_ENV - run: echo "MAJOR=${MINOR%.*}" >> $GITHUB_ENV - name: Login to DockerHub - uses: docker/login-action@v1 + uses: docker/login-action@v3 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - - name: Build and push - id: docker_build - uses: docker/build-push-action@v2 - with: - push: true - tags: | - sourcegraph/scip-rust:latest - sourcegraph/scip-rust:${{ env.PATCH }} - sourcegraph/scip-rust:${{ env.MINOR }} - sourcegraph/scip-rust:${{ env.MAJOR }} + - name: Build image with Nix + run: nix build .#docker + - name: Tag and push + run: | + set -eux + docker load < result + for TAG in latest "$PATCH" "$MINOR" "$MAJOR"; do + docker tag scip-rust:latest "sourcegraph/scip-rust:$TAG" + docker push "sourcegraph/scip-rust:$TAG" + done diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index fee0057..0000000 --- a/Dockerfile +++ /dev/null @@ -1,7 +0,0 @@ -FROM rust:1.89.0@sha256:e090f7b4adf86191313dba91260351d7f5e15cac0fe34f26706a805c0cb9641f - -COPY scip-rust /usr/local/bin/scip-rust - -RUN chmod +x /usr/local/bin/scip-rust - -RUN rustup component add rust-analyzer diff --git a/test-container.sh b/test-container.sh deleted file mode 100755 index 053b20b..0000000 --- a/test-container.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/bash -set -euo pipefail - -# Colors for output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -NC='\033[0m' # No Color - -echo -e "${GREEN}Starting container test...${NC}" - -# Create scratch directory if it doesn't exist -if [[ ! -d "./scratch" ]]; then - echo -e "${YELLOW}Creating scratch directory...${NC}" - mkdir -p scratch -fi - -# Clone or update ripgrep repo -if [[ ! -d "./scratch/ripgrep" ]]; then - echo -e "${YELLOW}Cloning ripgrep repository...${NC}" - git clone https://github.com/BurntSushi/ripgrep.git ./scratch/ripgrep -else - echo -e "${YELLOW}Updating ripgrep repository...${NC}" - cd ./scratch/ripgrep - git fetch origin - git reset --hard origin/master - cd ../.. -fi - -# Build the container with linux/amd64 platform -echo -e "${YELLOW}Building container image...${NC}" -podman build --platform=linux/amd64 -t scip-rust-test . - -# Run the container against the ripgrep codebase -echo -e "${YELLOW}Running scip-rust against ripgrep codebase...${NC}" -podman run --platform=linux/amd64 --rm -v "./scratch/ripgrep:/workspace:z" scip-rust-test \ - /usr/local/bin/scip-rust /workspace - -echo -e "${GREEN}Container test completed successfully!${NC}" From 6d5f2174969c94a65d67f18207ed33f63cd818f8 Mon Sep 17 00:00:00 2001 From: jupblb Date: Tue, 19 May 2026 13:04:42 +0200 Subject: [PATCH 07/22] scip-rust: prefer rust-analyzer on PATH over bundled fallback rustup's rust-analyzer shim is guaranteed to match the user's active toolchain (incl. rust-toolchain.toml resolution); a pinned bundled copy can drift. Defer to PATH and only fall back to an adjacent bundled binary when nothing better is installed. Collapse the tool existence checks into a single loop now that command -v handles both a bare name and an absolute path. --- scip-rust | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/scip-rust b/scip-rust index b9dc4c7..7ad5f38 100755 --- a/scip-rust +++ b/scip-rust @@ -2,22 +2,19 @@ set -eu -# Prefer a rust-analyzer bundled alongside this script (release-tarball layout); -# fall back to one on PATH (Nix flake / dev shell / Docker image with rustup). +# Prefer rust-analyzer on PATH (typically a rustup shim that matches the +# active toolchain); fall back to one bundled alongside this script +# (release-tarball layout). HERE=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) -if [ -x "$HERE/rust-analyzer" ]; then - RA="$HERE/rust-analyzer" -else - RA="rust-analyzer" -fi +RA="$HERE/rust-analyzer" +command -v rust-analyzer >/dev/null 2>&1 && RA="rust-analyzer" -# rust-analyzer shells out to cargo/rustc to read project metadata; fail fast -# with an actionable error if the host toolchain is missing. -for tool in cargo rustc; do +for tool in "$RA" cargo rustc; do if ! command -v "$tool" >/dev/null 2>&1; then - echo "error: scip-rust requires '$tool' on PATH." >&2 + echo "error: scip-rust requires '$tool' to be available." >&2 echo "Install a Rust toolchain via rustup (https://rustup.rs)" >&2 - echo "and add the rust-src component: rustup component add rust-src" >&2 + echo "and add the rust-analyzer and rust-src components:" >&2 + echo " rustup component add rust-analyzer rust-src" >&2 exit 1 fi done From 97eea4d0631b8b36937b61d6bdc956d784a54081 Mon Sep 17 00:00:00 2001 From: jupblb Date: Tue, 19 May 2026 13:05:40 +0200 Subject: [PATCH 08/22] scip-rust: use plain if/else for rust-analyzer lookup --- scip-rust | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/scip-rust b/scip-rust index 7ad5f38..68ddae3 100755 --- a/scip-rust +++ b/scip-rust @@ -5,16 +5,16 @@ set -eu # Prefer rust-analyzer on PATH (typically a rustup shim that matches the # active toolchain); fall back to one bundled alongside this script # (release-tarball layout). -HERE=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) -RA="$HERE/rust-analyzer" -command -v rust-analyzer >/dev/null 2>&1 && RA="rust-analyzer" +if command -v rust-analyzer >/dev/null 2>&1; then + RA="rust-analyzer" +else + HERE=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) + RA="$HERE/rust-analyzer" +fi for tool in "$RA" cargo rustc; do if ! command -v "$tool" >/dev/null 2>&1; then echo "error: scip-rust requires '$tool' to be available." >&2 - echo "Install a Rust toolchain via rustup (https://rustup.rs)" >&2 - echo "and add the rust-analyzer and rust-src components:" >&2 - echo " rustup component add rust-analyzer rust-src" >&2 exit 1 fi done From 00b731a667edcf3ef4d1234063c2f30019c96ea7 Mon Sep 17 00:00:00 2001 From: jupblb Date: Tue, 19 May 2026 13:07:23 +0200 Subject: [PATCH 09/22] scip-rust: replace command -v one-liner with explicit if --- scip-rust | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/scip-rust b/scip-rust index 68ddae3..043aff8 100755 --- a/scip-rust +++ b/scip-rust @@ -5,11 +5,10 @@ set -eu # Prefer rust-analyzer on PATH (typically a rustup shim that matches the # active toolchain); fall back to one bundled alongside this script # (release-tarball layout). +HERE=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +RA="$HERE/rust-analyzer" if command -v rust-analyzer >/dev/null 2>&1; then RA="rust-analyzer" -else - HERE=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) - RA="$HERE/rust-analyzer" fi for tool in "$RA" cargo rustc; do From d8273382ec9bd3c79b2da67516570da6b0ea62f3 Mon Sep 17 00:00:00 2001 From: jupblb Date: Tue, 19 May 2026 13:07:39 +0200 Subject: [PATCH 10/22] scip-rust: shorten rust-analyzer lookup comment --- scip-rust | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/scip-rust b/scip-rust index 043aff8..b21f50f 100755 --- a/scip-rust +++ b/scip-rust @@ -2,9 +2,7 @@ set -eu -# Prefer rust-analyzer on PATH (typically a rustup shim that matches the -# active toolchain); fall back to one bundled alongside this script -# (release-tarball layout). +# Prefer rust-analyzer on PATH; fall back to one bundled next to this script. HERE=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) RA="$HERE/rust-analyzer" if command -v rust-analyzer >/dev/null 2>&1; then From 823b6c08c38743563805f5f8cb33caf89e2df2a9 Mon Sep 17 00:00:00 2001 From: jupblb Date: Tue, 19 May 2026 13:09:30 +0200 Subject: [PATCH 11/22] scip-rust: drop set -x The trace 'exec rust-analyzer scip .' adds noise to stderr (where rust-analyzer's own progress also lives) without conveying anything the user couldn't already infer. Anyone who wants a trace can run 'sh -x scip-rust'. --- scip-rust | 2 -- 1 file changed, 2 deletions(-) diff --git a/scip-rust b/scip-rust index b21f50f..231b82d 100755 --- a/scip-rust +++ b/scip-rust @@ -23,6 +23,4 @@ done # and you run rust-analyzer with A/ as the project path, it will pick up all # crates (X1, X2, Y1 and Y2). So it is enough to run rust-analyzer once, # instead of once per workspace, or once per crate. - -set -x exec "$RA" scip . From c703f9ef4e2568a28ee3eec5cd9fd95861d3a03b Mon Sep 17 00:00:00 2001 From: jupblb Date: Tue, 19 May 2026 13:13:17 +0200 Subject: [PATCH 12/22] ci: replace Dependabot with Renovate --- .github/dependabot.yml | 6 ------ .github/renovate.json | 4 ++++ 2 files changed, 4 insertions(+), 6 deletions(-) delete mode 100644 .github/dependabot.yml create mode 100644 .github/renovate.json diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index 84c87d6..0000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,6 +0,0 @@ -version: 2 -updates: - - package-ecosystem: "docker" - directory: "/" - schedule: - interval: "weekly" diff --git a/.github/renovate.json b/.github/renovate.json new file mode 100644 index 0000000..72343d0 --- /dev/null +++ b/.github/renovate.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": ["config:recommended"], +} From 5bbd3f1510f396aad4d0458ac195ebe26352c558 Mon Sep 17 00:00:00 2001 From: jupblb Date: Tue, 19 May 2026 13:13:20 +0200 Subject: [PATCH 13/22] flake: add nixfmt check --- flake.nix | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/flake.nix b/flake.nix index 3c5ab16..6ac34d9 100644 --- a/flake.nix +++ b/flake.nix @@ -48,10 +48,16 @@ }; }; - checks.shellcheck = pkgs.runCommand "check-shellcheck" { } '' - ${pkgs.shellcheck}/bin/shellcheck ${./scip-rust} - touch $out - ''; + checks = { + shellcheck = pkgs.runCommand "check-shellcheck" { } '' + ${pkgs.shellcheck}/bin/shellcheck ${./scip-rust} + touch $out + ''; + nixfmt = pkgs.runCommand "check-nixfmt" { } '' + ${pkgs.nixfmt}/bin/nixfmt --check ${./flake.nix} + touch $out + ''; + }; devShells.default = pkgs.mkShellNoCC { buildInputs = with pkgs; [ From 02a95e1ac7e2e9a4ead04a71f27d4130b3e7c417 Mon Sep 17 00:00:00 2001 From: jupblb Date: Tue, 19 May 2026 13:28:50 +0200 Subject: [PATCH 14/22] release: drop tarballs, point at upstream rust-analyzer The bundled rust-analyzer + wrapper tarballs duplicated work that rust-lang/rust-analyzer already does well for every target we care about. Drop the matrix job, simplify the wrapper to just require rust-analyzer on PATH, and document the direct invocation in the README. The docker image continues to be published for users who want a single artifact. --- .github/workflows/release.yml | 31 ------------------------------- README.md | 19 +++++++++++++++++++ scip-rust | 11 ++--------- 3 files changed, 21 insertions(+), 40 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2ee6679..976b7ad 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -5,38 +5,7 @@ on: tags: - v* -env: - RUST_ANALYZER_VERSION: "2026-05-18" - jobs: - release-tarballs: - runs-on: ubuntu-latest - permissions: - contents: write - strategy: - matrix: - target: - - aarch64-apple-darwin - - x86_64-apple-darwin - - aarch64-unknown-linux-gnu - - x86_64-unknown-linux-musl - steps: - - uses: actions/checkout@v4 - - name: Build tarball - run: | - set -eux - STAGE=stage/scip-rust - mkdir -p "$STAGE" - curl -fL "https://github.com/rust-lang/rust-analyzer/releases/download/${RUST_ANALYZER_VERSION}/rust-analyzer-${{ matrix.target }}.gz" \ - | gunzip > "$STAGE/rust-analyzer" - chmod +x "$STAGE/rust-analyzer" - install -m 755 scip-rust "$STAGE/scip-rust" - tar -C stage -czf "scip-rust-${{ matrix.target }}.tar.gz" scip-rust - - name: Upload to release - uses: softprops/action-gh-release@v2 - with: - files: scip-rust-${{ matrix.target }}.tar.gz - release-image: runs-on: ubuntu-latest steps: diff --git a/README.md b/README.md index b3d7698..f1a3b7a 100644 --- a/README.md +++ b/README.md @@ -3,5 +3,24 @@ At the moment, this is just a tiny wrapper around `rust-analyzer` to generate SCIP data, with the configuration set up for use by Sourcegraph. +## Usage + +Install [`rust-analyzer`](https://rust-analyzer.github.io/book/installation.html) (any recent +release works), make sure `cargo` and `rustc` are on `PATH`, then from the root of your +workspace run: + +```sh +rust-analyzer scip . +``` + +The [`scip-rust`](./scip-rust) script in this repo is the same one-liner with a few +preflight checks; you can drop it into `PATH` if you prefer a stable command name. + +For CI, the `sourcegraph/scip-rust` Docker image bundles everything: + +```sh +docker run --rm -v "$PWD:/work" sourcegraph/scip-rust +``` + If you want to upload LSIF to Sourcegraph.com in CI, check out [lsif-rust-action](https://github.com/sourcegraph/lsif-rust-action) instead. diff --git a/scip-rust b/scip-rust index 231b82d..c05718f 100755 --- a/scip-rust +++ b/scip-rust @@ -2,14 +2,7 @@ set -eu -# Prefer rust-analyzer on PATH; fall back to one bundled next to this script. -HERE=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) -RA="$HERE/rust-analyzer" -if command -v rust-analyzer >/dev/null 2>&1; then - RA="rust-analyzer" -fi - -for tool in "$RA" cargo rustc; do +for tool in cargo rust-analyzer rustc; do if ! command -v "$tool" >/dev/null 2>&1; then echo "error: scip-rust requires '$tool' to be available." >&2 exit 1 @@ -23,4 +16,4 @@ done # and you run rust-analyzer with A/ as the project path, it will pick up all # crates (X1, X2, Y1 and Y2). So it is enough to run rust-analyzer once, # instead of once per workspace, or once per crate. -exec "$RA" scip . +exec rust-analyzer scip . From 14686f798723d916305f0466c22d76e3f0514ac6 Mon Sep 17 00:00:00 2001 From: jupblb Date: Tue, 19 May 2026 13:46:04 +0200 Subject: [PATCH 15/22] gitignore: ignore /result, drop scratch/ --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index e8ee010..c4a847d 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -scratch/ +/result From 2eeff87345c1dc72ba4c8a5e7169d8739110204f Mon Sep 17 00:00:00 2001 From: jupblb Date: Tue, 19 May 2026 13:46:10 +0200 Subject: [PATCH 16/22] scip-rust: fall back to bundled tools only when missing from PATH Previously, the Nix-built scip-rust wrapper used runtimeInputs to prepend bundled cargo, rustc, and rust-analyzer to PATH, shadowing any toolchain the user had installed. This broke projects with pinned toolchains via rustup or rust-toolchain.toml, since rust-analyzer shells out to cargo for metadata. Switch to per-tool SCIP_RUST_FALLBACK_* env vars via runtimeEnv, and have the script append a tool's fallback bin directory only when that tool is not already on PATH. This keeps the user's toolchain in charge while still providing a working out-of-the-box experience in CI or container environments without a Rust toolchain installed. --- flake.nix | 10 +++++----- scip-rust | 12 ++++++++++++ 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/flake.nix b/flake.nix index 6ac34d9..a2013d3 100644 --- a/flake.nix +++ b/flake.nix @@ -16,11 +16,11 @@ pkgs = import nixpkgs { inherit system; }; scip-rust = pkgs.writeShellApplication { name = "scip-rust"; - runtimeInputs = with pkgs; [ - rust-analyzer - cargo - rustc - ]; + runtimeEnv = { + SCIP_RUST_FALLBACK_CARGO = "${pkgs.cargo}/bin"; + SCIP_RUST_FALLBACK_RUSTC = "${pkgs.rustc}/bin"; + SCIP_RUST_FALLBACK_RUST_ANALYZER = "${pkgs.rust-analyzer}/bin"; + }; text = builtins.readFile ./scip-rust; }; in diff --git a/scip-rust b/scip-rust index c05718f..d71f986 100755 --- a/scip-rust +++ b/scip-rust @@ -2,7 +2,19 @@ set -eu +# Prefer tools already on PATH (so project-pinned toolchains via rustup or +# `rust-toolchain.toml` are honored). For any tool that is missing, fall +# back to the per-tool path provided by the Nix package; useful in CI +# environments without a local Rust toolchain. for tool in cargo rust-analyzer rustc; do + if command -v "$tool" >/dev/null 2>&1; then + continue + fi + case "$tool" in + cargo) export PATH="${PATH}:${SCIP_RUST_FALLBACK_CARGO:-}" ;; + rustc) export PATH="${PATH}:${SCIP_RUST_FALLBACK_RUSTC:-}" ;; + rust-analyzer) export PATH="${PATH}:${SCIP_RUST_FALLBACK_RUST_ANALYZER:-}" ;; + esac if ! command -v "$tool" >/dev/null 2>&1; then echo "error: scip-rust requires '$tool' to be available." >&2 exit 1 From 4ef6e0e6a5a20deca8faaa8897f8023f545d7b66 Mon Sep 17 00:00:00 2001 From: jupblb Date: Tue, 19 May 2026 13:47:26 +0200 Subject: [PATCH 17/22] flake: add renovate config check --- flake.nix | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/flake.nix b/flake.nix index a2013d3..4d4ba53 100644 --- a/flake.nix +++ b/flake.nix @@ -57,6 +57,11 @@ ${pkgs.nixfmt}/bin/nixfmt --check ${./flake.nix} touch $out ''; + renovate = pkgs.runCommand "check-renovate" { } '' + LOG_LEVEL=warn ${pkgs.renovate}/bin/renovate-config-validator \ + ${./.github/renovate.json} + touch $out + ''; }; devShells.default = pkgs.mkShellNoCC { From 7f7bce3487143a9288c9aebb2134530f669d6d08 Mon Sep 17 00:00:00 2001 From: jupblb Date: Tue, 19 May 2026 13:48:03 +0200 Subject: [PATCH 18/22] flake: add nixfmt and shellcheck to devshell --- flake.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/flake.nix b/flake.nix index 4d4ba53..14ec023 100644 --- a/flake.nix +++ b/flake.nix @@ -69,6 +69,8 @@ rust-analyzer rustc cargo + nixfmt + shellcheck ]; }; } From fec096b4cf9968016d3df974f9700087445cb461 Mon Sep 17 00:00:00 2001 From: jupblb Date: Tue, 19 May 2026 13:49:22 +0200 Subject: [PATCH 19/22] flake: extend formatting check with shfmt, add to devshell Replaces the nixfmt-only check with a formatting check that also runs shfmt against the scip-rust shell script (configured with -i 4 -ci to match the existing style). Adds shfmt to the devshell alongside nixfmt and shellcheck. --- flake.nix | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/flake.nix b/flake.nix index 14ec023..3dd660f 100644 --- a/flake.nix +++ b/flake.nix @@ -53,8 +53,9 @@ ${pkgs.shellcheck}/bin/shellcheck ${./scip-rust} touch $out ''; - nixfmt = pkgs.runCommand "check-nixfmt" { } '' + formatting = pkgs.runCommand "check-formatting" { } '' ${pkgs.nixfmt}/bin/nixfmt --check ${./flake.nix} + ${pkgs.shfmt}/bin/shfmt -i 4 -ci -d ${./scip-rust} touch $out ''; renovate = pkgs.runCommand "check-renovate" { } '' @@ -66,11 +67,12 @@ devShells.default = pkgs.mkShellNoCC { buildInputs = with pkgs; [ - rust-analyzer - rustc cargo nixfmt + rust-analyzer + rustc shellcheck + shfmt ]; }; } From 599fb3561ca672eb6a300356a8df0d11555bbe74 Mon Sep 17 00:00:00 2001 From: jupblb Date: Tue, 19 May 2026 14:25:14 +0200 Subject: [PATCH 20/22] ci: add flake-check, docker, and index jobs - nix flake check on PRs and pushes to main. - docker job builds the image and indexes ripgrep through it, asserting the produced index is non-negligible (>=100 KB). - index job builds scip-rust via nix build and runs it against a small matrix of representative Rust repos (ripgrep, tokio, serde, ruff), validating the resulting SCIP index with the scip CLI. - renovate custom manager keeps the matrix and docker job refs in sync with upstream releases; tokio uses extractVersion to filter the tokio-x.y.z tag namespace. - scip-rust forwards extra args to rust-analyzer (defaults to "."). --- .github/renovate.json | 21 ++++++ .github/workflows/ci.yaml | 131 ++++++++++++++++++++++++++++++++++++++ scip-rust | 8 ++- 3 files changed, 159 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/ci.yaml diff --git a/.github/renovate.json b/.github/renovate.json index 72343d0..8cea826 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -1,4 +1,25 @@ { "$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": ["config:recommended"], + "customManagers": [ + { + "customType": "regex", + "fileMatch": ["^\\.github/workflows/ci\\.yaml$"], + "matchStrings": [ + "(?:repo|repository): (?[^\\s${]+)\\s+ref: (?[^\\s${]+)" + ], + "datasourceTemplate": "github-releases" + } + ], + "packageRules": [ + { + "matchManagers": ["custom.regex"], + "matchFileNames": [".github/workflows/ci.yaml"], + "schedule": ["* * 1 */3 *"] + }, + { + "matchPackageNames": ["tokio-rs/tokio"], + "extractVersion": "^tokio-(?\\d+\\.\\d+\\.\\d+)$" + } + ] } diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..26c6b77 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,131 @@ +name: ci + +on: + push: + branches: [main] + pull_request: + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + flake-check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - uses: DeterminateSystems/nix-installer-action@v22 + with: + summarize: false + - uses: DeterminateSystems/magic-nix-cache-action@v13 + - run: nix flake check + + docker: + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - uses: actions/checkout@v6 + - uses: DeterminateSystems/nix-installer-action@v22 + with: + summarize: false + - uses: DeterminateSystems/magic-nix-cache-action@v13 + + - name: Build docker image + run: nix build .#docker + + - name: Load image into Docker + run: docker load < result + + - name: Checkout target repo + uses: actions/checkout@v6 + with: + repository: BurntSushi/ripgrep + ref: 15.1.0 + path: target + + - name: Index target via Docker + run: docker run --rm -v "$PWD/target:/work" scip-rust:latest + + - name: Check index size + run: | + size=$(stat --format='%s' target/index.scip) + echo "Index size: $size bytes" + [ "$size" -ge 102400 ] || { echo "FAIL: index too small"; exit 1; } + + index: + strategy: + fail-fast: false + matrix: + include: + - name: ripgrep + repo: BurntSushi/ripgrep + ref: 15.1.0 + expect_file: crates/core/main.rs + - name: tokio + repo: tokio-rs/tokio + ref: tokio-1.52.3 + expect_file: tokio/src/lib.rs + - name: serde + repo: serde-rs/serde + ref: v1.0.228 + expect_file: serde/src/lib.rs + - name: ruff + repo: astral-sh/ruff + ref: 0.15.13 + expect_file: crates/ruff/src/main.rs + + runs-on: ubuntu-latest + name: ${{ matrix.name }} + timeout-minutes: 60 + + steps: + - uses: actions/checkout@v6 + - uses: DeterminateSystems/nix-installer-action@v22 + with: + summarize: false + - uses: DeterminateSystems/magic-nix-cache-action@v13 + + - name: Build scip-rust + run: nix build .#scip-rust + + - name: Download scip CLI + run: | + curl -fsSL https://github.com/sourcegraph/scip/releases/latest/download/scip-linux-amd64.tar.gz \ + | tar -xz -C /usr/local/bin scip + + - name: Checkout target repo + uses: actions/checkout@v6 + with: + repository: ${{ matrix.repo }} + ref: ${{ matrix.ref }} + path: target + + - name: Fetch dependencies + working-directory: target + run: cargo fetch + + - name: Run scip-rust + run: ./result/bin/scip-rust --output index.scip target + + - name: Validate index + run: | + size=$(stat --format='%s' index.scip) + echo "Index size: $size bytes" + [ "$size" -ge 1024 ] || { echo "FAIL: index too small"; exit 1; } + + scip stats --from index.scip --project-root target \ + | jq -e '.documents > 0 and .occurrences > 0 and .definitions > 0' + + scip print --json index.scip \ + | jq -e --arg f "${{ matrix.expect_file }}" \ + 'any(.documents[]; .relative_path == $f)' + + ci-pass: + if: always() + needs: [flake-check, docker, index] + runs-on: ubuntu-latest + steps: + - if: >- + contains(needs.*.result, 'failure') || + contains(needs.*.result, 'cancelled') + run: exit 1 diff --git a/scip-rust b/scip-rust index d71f986..a62c93d 100755 --- a/scip-rust +++ b/scip-rust @@ -28,4 +28,10 @@ done # and you run rust-analyzer with A/ as the project path, it will pick up all # crates (X1, X2, Y1 and Y2). So it is enough to run rust-analyzer once, # instead of once per workspace, or once per crate. -exec rust-analyzer scip . +# +# Forward any extra args (e.g. `--output PATH`) to rust-analyzer; default +# to indexing the current directory if no path is given. +if [ $# -eq 0 ]; then + set -- . +fi +exec rust-analyzer scip "$@" From a024d665ee9a19538cf43f8b61eb37e1b09459f7 Mon Sep 17 00:00:00 2001 From: jupblb Date: Tue, 19 May 2026 14:28:47 +0200 Subject: [PATCH 21/22] scip-rust: probe tool with --version to detect broken rustup proxies A rustup install whose `rust-analyzer` component is not installed still exposes a `rust-analyzer` proxy on PATH, so the previous `command -v` check would pass and the wrapper would then exec the broken proxy ("Unknown binary rust-analyzer in official toolchain ..."). Probe each tool by running `--version` instead, and prepend the Nix fallback so it wins over the broken proxy. --- result-1 | 1 + scip-rust | 17 +++++++++-------- 2 files changed, 10 insertions(+), 8 deletions(-) create mode 120000 result-1 diff --git a/result-1 b/result-1 new file mode 120000 index 0000000..2cb6766 --- /dev/null +++ b/result-1 @@ -0,0 +1 @@ +/nix/store/szgsk3x403qdxj1lfmg8bfjx99mgw058-check-formatting \ No newline at end of file diff --git a/scip-rust b/scip-rust index a62c93d..b2c5687 100755 --- a/scip-rust +++ b/scip-rust @@ -3,19 +3,20 @@ set -eu # Prefer tools already on PATH (so project-pinned toolchains via rustup or -# `rust-toolchain.toml` are honored). For any tool that is missing, fall -# back to the per-tool path provided by the Nix package; useful in CI -# environments without a local Rust toolchain. +# `rust-toolchain.toml` are honored). For any tool that is missing or broken +# (e.g. a rustup proxy whose component is not installed), prepend the per-tool +# path provided by the Nix package so it takes precedence; useful in CI +# environments without a fully provisioned local Rust toolchain. for tool in cargo rust-analyzer rustc; do - if command -v "$tool" >/dev/null 2>&1; then + if "$tool" --version >/dev/null 2>&1; then continue fi case "$tool" in - cargo) export PATH="${PATH}:${SCIP_RUST_FALLBACK_CARGO:-}" ;; - rustc) export PATH="${PATH}:${SCIP_RUST_FALLBACK_RUSTC:-}" ;; - rust-analyzer) export PATH="${PATH}:${SCIP_RUST_FALLBACK_RUST_ANALYZER:-}" ;; + cargo) export PATH="${SCIP_RUST_FALLBACK_CARGO:-}:${PATH}" ;; + rustc) export PATH="${SCIP_RUST_FALLBACK_RUSTC:-}:${PATH}" ;; + rust-analyzer) export PATH="${SCIP_RUST_FALLBACK_RUST_ANALYZER:-}:${PATH}" ;; esac - if ! command -v "$tool" >/dev/null 2>&1; then + if ! "$tool" --version >/dev/null 2>&1; then echo "error: scip-rust requires '$tool' to be available." >&2 exit 1 fi From 611c53e518a039cc25a6df372f95ed25885ceee7 Mon Sep 17 00:00:00 2001 From: jupblb Date: Tue, 19 May 2026 14:29:45 +0200 Subject: [PATCH 22/22] gitignore: ignore result* symlinks, drop stray result-1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Local `nix build` runs that compete for `./result` create `./result-1`, `./result-2`, ... — ignore the whole family. The stray `result-1` symlink was accidentally committed in the previous commit. --- .gitignore | 2 +- result-1 | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) delete mode 120000 result-1 diff --git a/.gitignore b/.gitignore index c4a847d..d6944e3 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -/result +/result* diff --git a/result-1 b/result-1 deleted file mode 120000 index 2cb6766..0000000 --- a/result-1 +++ /dev/null @@ -1 +0,0 @@ -/nix/store/szgsk3x403qdxj1lfmg8bfjx99mgw058-check-formatting \ No newline at end of file