From 23a2cea64670a15edb13277857e433910dcc4d93 Mon Sep 17 00:00:00 2001 From: Taras Yemets Date: Thu, 9 May 2024 16:18:35 +0300 Subject: [PATCH] Create a shared Cody Ignore dataset (#61968) --- .bazelignore | 1 + .../.gitignore | 1 + .../BUILD.bazel | 6 + .../CONTRIBUTING.md | 10 + .../README.md | 5 + .../package.json | 17 + .../scripts/generate.js | 54 ++ client/web/BUILD.bazel | 1 + client/web/src/cody/useCodyIgnore.test.ts | 723 +----------------- client/web/tsconfig.json | 1 + cmd/frontend/internal/codycontext/BUILD.bazel | 1 + .../internal/codycontext/enterprise.go | 32 +- .../internal/codycontext/enterprise_test.go | 578 ++------------ .../testdata/enterprise_filter_test_data.json | 699 +++++++++++++++++ package.json | 1 + pnpm-lock.yaml | 7 + pnpm-workspace.yaml | 2 + 17 files changed, 887 insertions(+), 1252 deletions(-) create mode 100644 client/cody-context-filters-test-dataset/.gitignore create mode 100644 client/cody-context-filters-test-dataset/BUILD.bazel create mode 100644 client/cody-context-filters-test-dataset/CONTRIBUTING.md create mode 100644 client/cody-context-filters-test-dataset/README.md create mode 100644 client/cody-context-filters-test-dataset/package.json create mode 100755 client/cody-context-filters-test-dataset/scripts/generate.js create mode 100644 cmd/frontend/internal/codycontext/testdata/enterprise_filter_test_data.json diff --git a/.bazelignore b/.bazelignore index 49dfd63b650..e7bf1796430 100644 --- a/.bazelignore +++ b/.bazelignore @@ -9,6 +9,7 @@ client/build-config/node_modules client/client-api/node_modules client/codeintellify/node_modules client/common/node_modules +client/cody-context-filters-test-dataset/node_modules client/eslint-plugin-wildcard/node_modules client/extension-api/node_modules client/extension-api-types/node_modules diff --git a/client/cody-context-filters-test-dataset/.gitignore b/client/cody-context-filters-test-dataset/.gitignore new file mode 100644 index 00000000000..470a1a68d5c --- /dev/null +++ b/client/cody-context-filters-test-dataset/.gitignore @@ -0,0 +1 @@ +dataset.json diff --git a/client/cody-context-filters-test-dataset/BUILD.bazel b/client/cody-context-filters-test-dataset/BUILD.bazel new file mode 100644 index 00000000000..eeacfe75967 --- /dev/null +++ b/client/cody-context-filters-test-dataset/BUILD.bazel @@ -0,0 +1,6 @@ +load("//dev:defs.bzl", "npm_package") + +npm_package( + name = "cody-context-filters-test-dataset_pkg", + srcs = ["package.json"], +) diff --git a/client/cody-context-filters-test-dataset/CONTRIBUTING.md b/client/cody-context-filters-test-dataset/CONTRIBUTING.md new file mode 100644 index 00000000000..52eb9332542 --- /dev/null +++ b/client/cody-context-filters-test-dataset/CONTRIBUTING.md @@ -0,0 +1,10 @@ +# Publishing a new release + +1. Ensure the updated version of the test dataset is already committed to `main`. +2. Create a new branch from `main` and switch to it. +3. Bump the version in [`package.json`](package.json). +4. Commit the version change. +5. Run `pnpm login` and enter the credentials + from [1Password](https://start.1password.com/open/i?a=HEDEDSLHPBFGRBTKAKJWE23XX4&v=dnrhbauihkhjs5ag6vszsme45a&i=oye4u4faaxmxxesugzqxojr4q4&h=team-sourcegraph.1password.com). +6. Run `pnpm publish` from the package root and check for any errors. +7. Once the release has been published, create a PR and get it merged to `main`. diff --git a/client/cody-context-filters-test-dataset/README.md b/client/cody-context-filters-test-dataset/README.md new file mode 100644 index 00000000000..9a16e221b7f --- /dev/null +++ b/client/cody-context-filters-test-dataset/README.md @@ -0,0 +1,5 @@ +# Cody context filters test dataset + +This package includes a copy of the dataset used for testing the Cody context filtering logic on the backend. +The dataset is exported so that Cody clients can ensure consistency in how Cody context filters are handled across +both the server and clients. diff --git a/client/cody-context-filters-test-dataset/package.json b/client/cody-context-filters-test-dataset/package.json new file mode 100644 index 00000000000..ad70be39bb4 --- /dev/null +++ b/client/cody-context-filters-test-dataset/package.json @@ -0,0 +1,17 @@ +{ + "name": "@sourcegraph/cody-context-filters-test-dataset", + "version": "1.0.0", + "license": "Apache-2.0", + "description": "Cody context filters test dataset", + "repository": { + "type": "git", + "url": "git+https://github.com/sourcegraph/sourcegraph.git", + "directory": "client/cody-context-filters-test-dataset" + }, + "scripts": { + "prepublishOnly": "node scripts/generate.js" + }, + "files": [ + "dataset.json" + ] +} diff --git a/client/cody-context-filters-test-dataset/scripts/generate.js b/client/cody-context-filters-test-dataset/scripts/generate.js new file mode 100755 index 00000000000..38737fbae3a --- /dev/null +++ b/client/cody-context-filters-test-dataset/scripts/generate.js @@ -0,0 +1,54 @@ +const path = require('path') +const shelljs = require('shelljs') +const semver = require('semver') +const signale = require('signale') + +;(() => { + signale.await('Copying test dataset...') + const datasetSource = path.join( + __dirname, + '../../../cmd/frontend/internal/codycontext/testdata/enterprise_filter_test_data.json' + ) + const datasetDest = path.join(__dirname, '../dataset.json') + const packageJSONPath = path.join(__dirname, '../package.json') + + const copyDatasetFileResult = shelljs.cp(datasetSource, datasetDest) + if (copyDatasetFileResult.code !== 0) { + signale.fatal('Failed to copy test dataset:', copyDatasetFileResult.stderr) + shelljs.exit(1) + } + + const readDatasetContent = shelljs.cat(datasetDest) + if (readDatasetContent.code !== 0) { + signale.fatal('Failed to read dataset content:', readDatasetContent.stderr) + shelljs.exit(1) + } + + try { + JSON.parse(readDatasetContent.stdout) + } catch (e) { + signale.fatal('Failed to parse dataset content as JSON:', e) + shelljs.exit(1) + } + + const readPackageJSONContent = shelljs.cat(packageJSONPath) + let versionFromPackageJSON + try { + versionFromPackageJSON = JSON.parse(readPackageJSONContent.stdout).version + } catch (e) { + signale.fatal('Failed to parse package.json:', e) + shelljs.exit(1) + } + + const version = semver.valid(versionFromPackageJSON) + if (!version) { + signale.fatal( + `Invalid version in package.json: ${JSON.stringify( + versionFromPackageJSON + )}. Versions must be valid semantic version strings.` + ) + shelljs.exit(1) + } + + signale.success('Test dataset created successfully!') +})() diff --git a/client/web/BUILD.bazel b/client/web/BUILD.bazel index 1a1185c0d69..b77727a2c34 100644 --- a/client/web/BUILD.bazel +++ b/client/web/BUILD.bazel @@ -2025,6 +2025,7 @@ ts_project( "//:node_modules/@apollo/client", "//:node_modules/@codemirror/state", "//:node_modules/@codemirror/view", + "//:node_modules/@sourcegraph/cody-context-filters-test-dataset", "//:node_modules/@testing-library/dom", "//:node_modules/@testing-library/jest-dom", #keep "//:node_modules/@testing-library/react", diff --git a/client/web/src/cody/useCodyIgnore.test.ts b/client/web/src/cody/useCodyIgnore.test.ts index 5856e5cecc5..eeb064ee0ba 100644 --- a/client/web/src/cody/useCodyIgnore.test.ts +++ b/client/web/src/cody/useCodyIgnore.test.ts @@ -1,5 +1,7 @@ import { describe, expect, it } from 'vitest' +import { testCases } from '@sourcegraph/cody-context-filters-test-dataset/dataset.json' + import { alwaysTrue, getFilterFnsFromCodyContextFilters } from './useCodyIgnore' describe('getFilterFnsFromCodyContextFilters', () => { @@ -12,727 +14,6 @@ describe('getFilterFnsFromCodyContextFilters', () => { expect(isFileIgnored).toBe(alwaysTrue) }) - // TODO: (taras-yemets) replace with shared Cody Ignore test dataset once it's published - const testCases = [ - { - name: 'Cody context filters are not defined', - description: 'Any repo should be included.', - includeByDefault: true, - includeUnknown: false, - 'cody.contextFilters': null, - repos: [ - { name: 'github.com/sourcegraph/about', id: 1 }, - { name: 'github.com/sourcegraph/annotate', id: 2 }, - { name: 'github.com/sourcegraph/sourcegraph', id: 3 }, - { name: 'github.com/docker/compose', id: 4 }, - ], - includedRepos: [ - { name: 'github.com/sourcegraph/about', id: 1 }, - { name: 'github.com/sourcegraph/annotate', id: 2 }, - { name: 'github.com/sourcegraph/sourcegraph', id: 3 }, - { name: 'github.com/docker/compose', id: 4 }, - ], - fileChunks: [ - { - repo: { - name: 'github.com/sourcegraph/about', - id: 1, - }, - Path: '/file1.go', - }, - { - repo: { - name: 'github.com/sourcegraph/annotate', - id: 2, - }, - Path: '/file2.go', - }, - { - repo: { - name: 'github.com/sourcegraph/sourcegraph', - id: 3, - }, - Path: '/file3.go', - }, - { - repo: { - name: 'github.com/docker/compose', - id: 4, - }, - Path: '/file4.go', - }, - ], - includedFileChunks: [ - { - repo: { - name: 'github.com/sourcegraph/about', - id: 1, - }, - Path: '/file1.go', - }, - { - repo: { - name: 'github.com/sourcegraph/annotate', - id: 2, - }, - Path: '/file2.go', - }, - { - repo: { - name: 'github.com/sourcegraph/sourcegraph', - id: 3, - }, - Path: '/file3.go', - }, - { - repo: { - name: 'github.com/docker/compose', - id: 4, - }, - Path: '/file4.go', - }, - ], - }, - { - name: 'Include and exclude rules are not defined', - description: - 'This scenario shouldn\'t happen. "cody.contextFilters" if defined in the site config, should have at least one property. Thus, either "include" or "exclude" should be defined. We rely on site config schema validation.', - includeByDefault: true, - includeUnknown: false, - 'cody.contextFilters': {}, - repos: [ - { name: 'github.com/sourcegraph/about', id: 1 }, - { name: 'github.com/sourcegraph/annotate', id: 2 }, - { name: 'github.com/sourcegraph/sourcegraph', id: 3 }, - { name: 'github.com/docker/compose', id: 4 }, - ], - includedRepos: [ - { name: 'github.com/sourcegraph/about', id: 1 }, - { name: 'github.com/sourcegraph/annotate', id: 2 }, - { name: 'github.com/sourcegraph/sourcegraph', id: 3 }, - { name: 'github.com/docker/compose', id: 4 }, - ], - fileChunks: [ - { - repo: { - name: 'github.com/sourcegraph/about', - id: 1, - }, - path: '/file1.go', - }, - { - repo: { - name: 'github.com/sourcegraph/annotate', - id: 2, - }, - path: '/file2.go', - }, - { - repo: { - name: 'github.com/sourcegraph/sourcegraph', - id: 3, - }, - path: '/file3.go', - }, - { - repo: { - name: 'github.com/docker/compose', - id: 4, - }, - path: '/file4.go', - }, - ], - includedFileChunks: [ - { - repo: { - name: 'github.com/sourcegraph/about', - id: 1, - }, - path: '/file1.go', - }, - { - repo: { - name: 'github.com/sourcegraph/annotate', - id: 2, - }, - path: '/file2.go', - }, - { - repo: { - name: 'github.com/sourcegraph/sourcegraph', - id: 3, - }, - path: '/file3.go', - }, - { - repo: { - name: 'github.com/docker/compose', - id: 4, - }, - path: '/file4.go', - }, - ], - }, - { - name: 'Include and exclude rules are empty lists', - description: - 'This scenario shouldn\'t happen. If either "include" or "exclude" field is defined, it should have at least one item. We rely on site config schema validation.', - includeByDefault: true, - includeUnknown: false, - 'cody.contextFilters': { - include: [], - exclude: [], - }, - repos: [ - { name: 'github.com/sourcegraph/about', id: 1 }, - { name: 'github.com/sourcegraph/annotate', id: 2 }, - { name: 'github.com/sourcegraph/sourcegraph', id: 3 }, - { name: 'github.com/docker/compose', id: 4 }, - ], - includedRepos: [ - { name: 'github.com/sourcegraph/about', id: 1 }, - { name: 'github.com/sourcegraph/annotate', id: 2 }, - { name: 'github.com/sourcegraph/sourcegraph', id: 3 }, - { name: 'github.com/docker/compose', id: 4 }, - ], - fileChunks: [ - { - repo: { - name: 'github.com/sourcegraph/about', - id: 1, - }, - path: '/file1.go', - }, - { - repo: { - name: 'github.com/sourcegraph/annotate', - id: 2, - }, - path: '/file2.go', - }, - { - repo: { - name: 'github.com/sourcegraph/sourcegraph', - id: 3, - }, - path: '/file3.go', - }, - { - repo: { - name: 'github.com/docker/compose', - id: 4, - }, - path: '/file4.go', - }, - ], - includedFileChunks: [ - { - repo: { - name: 'github.com/sourcegraph/about', - id: 1, - }, - path: '/file1.go', - }, - { - repo: { - name: 'github.com/sourcegraph/annotate', - id: 2, - }, - path: '/file2.go', - }, - { - repo: { - name: 'github.com/sourcegraph/sourcegraph', - id: 3, - }, - path: '/file3.go', - }, - { - repo: { - name: 'github.com/docker/compose', - id: 4, - }, - path: '/file4.go', - }, - ], - }, - { - name: 'Only include rules are defined', - description: 'Only repos matching "include" repo name patterns should be included.', - includeByDefault: true, - includeUnknown: false, - 'cody.contextFilters': { - include: [{ repoNamePattern: '^github\\.com\\/sourcegraph\\/.+' }], - }, - repos: [ - { name: 'github.com/sourcegraph/about', id: 1 }, - { name: 'github.com/sourcegraph/annotate', id: 2 }, - { name: 'github.com/sourcegraph/sourcegraph', id: 3 }, - { name: 'github.com/docker/compose', id: 4 }, - ], - includedRepos: [ - { name: 'github.com/sourcegraph/about', id: 1 }, - { name: 'github.com/sourcegraph/annotate', id: 2 }, - { name: 'github.com/sourcegraph/sourcegraph', id: 3 }, - ], - fileChunks: [ - { - repo: { - name: 'github.com/sourcegraph/about', - id: 1, - }, - path: '/file1.go', - }, - { - repo: { - name: 'github.com/sourcegraph/annotate', - id: 2, - }, - path: '/file2.go', - }, - { - repo: { - name: 'github.com/sourcegraph/sourcegraph', - id: 3, - }, - path: '/file3.go', - }, - { - repo: { - name: 'github.com/docker/compose', - id: 4, - }, - path: '/file4.go', - }, - ], - includedFileChunks: [ - { - repo: { - name: 'github.com/sourcegraph/about', - id: 1, - }, - path: '/file1.go', - }, - { - repo: { - name: 'github.com/sourcegraph/annotate', - id: 2, - }, - path: '/file2.go', - }, - { - repo: { - name: 'github.com/sourcegraph/sourcegraph', - id: 3, - }, - path: '/file3.go', - }, - ], - }, - { - name: 'Only exclude rules are defined', - description: 'Only repos not matching any of "include" repo name patterns should be included.', - includeByDefault: true, - includeUnknown: false, - 'cody.contextFilters': { - exclude: [{ repoNamePattern: '^github\\.com\\/sourcegraph\\/.+' }], - }, - repos: [ - { name: 'github.com/sourcegraph/about', id: 1 }, - { name: 'github.com/sourcegraph/annotate', id: 2 }, - { name: 'github.com/sourcegraph/sourcegraph', id: 3 }, - { name: 'github.com/docker/compose', id: 4 }, - ], - includedRepos: [{ name: 'github.com/docker/compose', id: 4 }], - fileChunks: [ - { - repo: { - name: 'github.com/sourcegraph/about', - id: 1, - }, - path: '/file1.go', - }, - { - repo: { - name: 'github.com/sourcegraph/annotate', - id: 2, - }, - path: '/file2.go', - }, - { - repo: { - name: 'github.com/sourcegraph/sourcegraph', - id: 3, - }, - path: '/file3.go', - }, - { - repo: { - name: 'github.com/docker/compose', - id: 4, - }, - path: '/file4.go', - }, - ], - includedFileChunks: [ - { - repo: { - name: 'github.com/docker/compose', - id: 4, - }, - path: '/file4.go', - }, - ], - }, - { - name: 'Include and exclude rules are defined', - description: - 'Only repos matching any of "include" and not matching any of "exclude" repo name patterns should be included.', - includeByDefault: true, - includeUnknown: false, - 'cody.contextFilters': { - include: [{ repoNamePattern: '^github\\.com\\/sourcegraph\\/.+' }], - exclude: [{ repoNamePattern: '.*cody.*' }], - }, - repos: [ - { name: 'github.com/sourcegraph/about', id: 1 }, - { name: 'github.com/sourcegraph/annotate', id: 2 }, - { name: 'github.com/sourcegraph/sourcegraph', id: 3 }, - { name: 'github.com/docker/compose', id: 4 }, - { name: 'github.com/sourcegraph/cody', id: 5 }, - ], - includedRepos: [ - { name: 'github.com/sourcegraph/about', id: 1 }, - { name: 'github.com/sourcegraph/annotate', id: 2 }, - { name: 'github.com/sourcegraph/sourcegraph', id: 3 }, - ], - fileChunks: [ - { - repo: { - name: 'github.com/sourcegraph/about', - id: 1, - }, - path: '/file1.go', - }, - { - repo: { - name: 'github.com/sourcegraph/annotate', - id: 2, - }, - path: '/file2.go', - }, - { - repo: { - name: 'github.com/sourcegraph/sourcegraph', - id: 3, - }, - path: '/file3.go', - }, - { - repo: { - name: 'github.com/docker/compose', - id: 4, - }, - path: '/file4.go', - }, - { - repo: { - name: 'github.com/sourcegraph/cody', - id: 5, - }, - path: '/index.ts', - }, - ], - includedFileChunks: [ - { - repo: { - name: 'github.com/sourcegraph/about', - id: 1, - }, - path: '/file1.go', - }, - { - repo: { - name: 'github.com/sourcegraph/annotate', - id: 2, - }, - path: '/file2.go', - }, - { - repo: { - name: 'github.com/sourcegraph/sourcegraph', - id: 3, - }, - path: '/file3.go', - }, - ], - }, - { - name: 'Multiple include and exclude rules are defined', - description: - 'Only repos matching any of "include" and not matching any of "exclude" repo name patterns should be included.', - includeByDefault: true, - includeUnknown: false, - 'cody.contextFilters': { - include: [ - { repoNamePattern: '^github\\.com\\/sourcegraph\\/.+' }, - { repoNamePattern: '^github\\.com\\/docker\\/compose$' }, - { repoNamePattern: '^github\\.com\\/.+\\/react' }, - ], - exclude: [{ repoNamePattern: '.*cody.*' }, { repoNamePattern: '.+\\/docker\\/.+' }], - }, - repos: [ - { name: 'github.com/sourcegraph/about', id: 1 }, - { name: 'github.com/sourcegraph/annotate', id: 2 }, - { name: 'github.com/sourcegraph/sourcegraph', id: 3 }, - { name: 'github.com/docker/compose', id: 4 }, - { name: 'github.com/sourcegraph/cody', id: 5 }, - { name: 'github.com/facebook/react', id: 6 }, - ], - includedRepos: [ - { name: 'github.com/sourcegraph/about', id: 1 }, - { name: 'github.com/sourcegraph/annotate', id: 2 }, - { name: 'github.com/sourcegraph/sourcegraph', id: 3 }, - { name: 'github.com/facebook/react', id: 6 }, - ], - fileChunks: [ - { - repo: { - name: 'github.com/sourcegraph/about', - id: 1, - }, - path: '/file1.go', - }, - { - repo: { - name: 'github.com/sourcegraph/annotate', - id: 2, - }, - path: '/file2.go', - }, - { - repo: { - name: 'github.com/sourcegraph/sourcegraph', - id: 3, - }, - path: '/file3.go', - }, - { - repo: { - name: 'github.com/docker/compose', - id: 4, - }, - path: '/file4.go', - }, - { - repo: { - name: 'github.com/sourcegraph/cody', - id: 5, - }, - path: '/index.ts', - }, - { - repo: { - name: 'github.com/facebook/react', - id: 6, - }, - path: '/hooks.ts', - }, - ], - includedFileChunks: [ - { - repo: { - name: 'github.com/sourcegraph/about', - id: 1, - }, - path: '/file1.go', - }, - { - repo: { - name: 'github.com/sourcegraph/annotate', - id: 2, - }, - path: '/file2.go', - }, - { - repo: { - name: 'github.com/sourcegraph/sourcegraph', - id: 3, - }, - path: '/file3.go', - }, - { - repo: { - name: 'github.com/facebook/react', - id: 6, - }, - path: '/hooks.ts', - }, - ], - }, - { - name: 'Include rules contain repo name pattern matching any repo', - description: 'Any repo should be included.', - includeByDefault: true, - includeUnknown: false, - 'cody.contextFilters': { - include: [{ repoNamePattern: '.*' }], - }, - repos: [ - { name: 'github.com/sourcegraph/about', id: 1 }, - { name: 'github.com/sourcegraph/annotate', id: 2 }, - { name: 'github.com/sourcegraph/sourcegraph', id: 3 }, - { name: 'github.com/docker/compose', id: 4 }, - { name: 'github.com/sourcegraph/cody', id: 5 }, - { name: 'github.com/facebook/react', id: 6 }, - ], - includedRepos: [ - { name: 'github.com/sourcegraph/about', id: 1 }, - { name: 'github.com/sourcegraph/annotate', id: 2 }, - { name: 'github.com/sourcegraph/sourcegraph', id: 3 }, - { name: 'github.com/docker/compose', id: 4 }, - { name: 'github.com/sourcegraph/cody', id: 5 }, - { name: 'github.com/facebook/react', id: 6 }, - ], - fileChunks: [ - { - repo: { - name: 'github.com/sourcegraph/about', - id: 1, - }, - path: '/file1.go', - }, - { - repo: { - name: 'github.com/sourcegraph/annotate', - id: 2, - }, - path: '/file2.go', - }, - { - repo: { - name: 'github.com/sourcegraph/sourcegraph', - id: 3, - }, - path: '/file3.go', - }, - { - repo: { - name: 'github.com/docker/compose', - id: 4, - }, - path: '/file4.go', - }, - { - repo: { - name: 'github.com/sourcegraph/cody', - id: 5, - }, - path: '/index.ts', - }, - { - repo: { - name: 'github.com/facebook/react', - id: 6, - }, - path: '/hooks.ts', - }, - ], - includedFileChunks: [ - { - repo: { - name: 'github.com/sourcegraph/about', - id: 1, - }, - path: '/file1.go', - }, - { - repo: { - name: 'github.com/sourcegraph/annotate', - id: 2, - }, - path: '/file2.go', - }, - { - repo: { - name: 'github.com/sourcegraph/sourcegraph', - id: 3, - }, - path: '/file3.go', - }, - { - repo: { - name: 'github.com/docker/compose', - id: 4, - }, - path: '/file4.go', - }, - { - repo: { - name: 'github.com/sourcegraph/cody', - id: 5, - }, - path: '/index.ts', - }, - { - repo: { - name: 'github.com/facebook/react', - id: 6, - }, - path: '/hooks.ts', - }, - ], - }, - { - name: 'Exclude rules contain repo name pattern matching any repo', - description: 'Neither repo should be included.', - includeByDefault: true, - includeUnknown: false, - 'cody.contextFilters': { - include: [{ repoNamePattern: '^github\\.com\\/sourcegraph\\/.+' }], - exclude: [{ repoNamePattern: '.*' }], - }, - repos: [ - { name: 'github.com/sourcegraph/about', id: 1 }, - { name: 'github.com/sourcegraph/annotate', id: 2 }, - { name: 'github.com/sourcegraph/sourcegraph', id: 3 }, - { name: 'github.com/docker/compose', id: 4 }, - ], - includedRepos: [], - fileChunks: [ - { - repo: { - name: 'github.com/sourcegraph/about', - id: 1, - }, - path: '/file1.go', - }, - { - repo: { - name: 'github.com/sourcegraph/annotate', - id: 2, - }, - path: '/file2.go', - }, - { - repo: { - name: 'github.com/sourcegraph/sourcegraph', - id: 3, - }, - path: '/file3.go', - }, - { - repo: { - name: 'github.com/docker/compose', - id: 4, - }, - path: '/file4.go', - }, - ], - includedFileChunks: [], - }, - ] - for (const testCase of testCases) { it(testCase.name, async () => { const ccf = testCase['cody.contextFilters'] diff --git a/client/web/tsconfig.json b/client/web/tsconfig.json index 4731d784fcc..8ee1ac8ae00 100644 --- a/client/web/tsconfig.json +++ b/client/web/tsconfig.json @@ -6,6 +6,7 @@ "jsx": "react-jsx", "rootDir": ".", "outDir": "out", + "resolveJsonModule": true, }, "references": [ { diff --git a/cmd/frontend/internal/codycontext/BUILD.bazel b/cmd/frontend/internal/codycontext/BUILD.bazel index d249cb1cd97..94fd37c6cea 100644 --- a/cmd/frontend/internal/codycontext/BUILD.bazel +++ b/cmd/frontend/internal/codycontext/BUILD.bazel @@ -52,6 +52,7 @@ go_test( "dotcom_test.go", "enterprise_test.go", ], + data = glob(["testdata/**"]), embed = [":codycontext"], deps = [ "//internal/api", diff --git a/cmd/frontend/internal/codycontext/enterprise.go b/cmd/frontend/internal/codycontext/enterprise.go index 041b88c53ca..3e2c118354c 100644 --- a/cmd/frontend/internal/codycontext/enterprise.go +++ b/cmd/frontend/internal/codycontext/enterprise.go @@ -19,8 +19,6 @@ import ( "github.com/sourcegraph/sourcegraph/schema" ) -const allowByDefault = true - var ( metricCacheHit = promauto.NewCounter(prometheus.CounterOpts{ Name: "src_codycontext_filter_cache_hit", @@ -88,15 +86,15 @@ func (f *enterpriseRepoFilter) getMatcher(ctx context.Context, repos []types.Rep return []types.RepoIDName{}, func(api.RepoID, string) bool { return false }, errors.New("Cody context filters configuration is invalid. Please contact your admin.") } - allowedRepos := make([]types.RepoIDName, 0, len(repos)) + includedRepos := make([]types.RepoIDName, 0, len(repos)) for _, repo := range repos { - if fc.isRepoAllowed(repo) { - allowedRepos = append(allowedRepos, repo) + if fc.isRepoIncluded(repo) { + includedRepos = append(includedRepos, repo) } } - return allowedRepos, func(repo api.RepoID, path string) bool { - return slices.ContainsFunc(allowedRepos, func(r types.RepoIDName) bool { return r.ID == repo }) + return includedRepos, func(repo api.RepoID, path string) bool { + return slices.ContainsFunc(includedRepos, func(r types.RepoIDName) bool { return r.ID == repo }) }, nil } @@ -149,8 +147,8 @@ func parseCodyContextFilters(ccf *schema.CodyContextFilters) (filtersConfig, err }, nil } -// isRepoAllowed checks if repo name matches Cody context include and exclude rules from the site config and stores result in cache. -func (f filtersConfig) isRepoAllowed(repo types.RepoIDName) bool { +// isRepoIncluded checks if repo name matches Cody context include and exclude rules from the site config and stores result in cache. +func (f filtersConfig) isRepoIncluded(repo types.RepoIDName) bool { cached, ok := f.cache.Get(repo.ID) if ok { metricCacheHit.Inc() @@ -158,13 +156,12 @@ func (f filtersConfig) isRepoAllowed(repo types.RepoIDName) bool { } metricCacheMiss.Inc() - allowed := allowByDefault + included := true if len(f.include) > 0 { for _, p := range f.include { - include := p.RepoNamePattern.MatchString(string(repo.Name)) - allowed = include - if include { + included = p.RepoNamePattern.MatchString(string(repo.Name)) + if included { break } } @@ -172,14 +169,13 @@ func (f filtersConfig) isRepoAllowed(repo types.RepoIDName) bool { if len(f.exclude) > 0 { for _, p := range f.exclude { - exclude := p.RepoNamePattern.MatchString(string(repo.Name)) - if exclude { - allowed = false + if p.RepoNamePattern.MatchString(string(repo.Name)) { + included = false break } } } - f.cache.Add(repo.ID, allowed) - return allowed + f.cache.Add(repo.ID, included) + return included } diff --git a/cmd/frontend/internal/codycontext/enterprise_test.go b/cmd/frontend/internal/codycontext/enterprise_test.go index 2e385923b2f..b659dcd41ea 100644 --- a/cmd/frontend/internal/codycontext/enterprise_test.go +++ b/cmd/frontend/internal/codycontext/enterprise_test.go @@ -2,13 +2,18 @@ package codycontext import ( "context" + "encoding/json" "fmt" + "os" + "path/filepath" "testing" "time" "github.com/sourcegraph/log/logtest" "github.com/stretchr/testify/require" + "github.com/sourcegraph/sourcegraph/internal/api" + "github.com/sourcegraph/sourcegraph/internal/conf" "github.com/sourcegraph/sourcegraph/internal/database/dbmocks" "github.com/sourcegraph/sourcegraph/internal/featureflag" @@ -17,508 +22,54 @@ import ( ) func TestNewEnterpriseFilter(t *testing.T) { - t.Cleanup(func() { conf.Mock(nil) }) + t.Cleanup(func() { + conf.Mock(nil) + }) - tests := []struct { - name string - ccf *schema.CodyContextFilters - repos []types.RepoIDName - chunks []FileChunkContext - wantRepos []types.RepoIDName - wantChunks []FileChunkContext - }{ - { - name: "Cody context filters not set", - ccf: nil, - repos: []types.RepoIDName{ - {Name: "github.com/sourcegraph/about", ID: 1}, - {Name: "github.com/sourcegraph/annotate", ID: 2}, - {Name: "github.com/sourcegraph/sourcegraph", ID: 3}, - {Name: "github.com/docker/compose", ID: 4}, - }, - chunks: []FileChunkContext{ - { - RepoName: "github.com/sourcegraph/about", - RepoID: 1, - Path: "/file1.go", - }, - { - RepoName: "github.com/sourcegraph/annotate", - RepoID: 2, - Path: "/file2.go", - }, - { - RepoName: "github.com/sourcegraph/sourcegraph", - RepoID: 3, - Path: "/file3.go", - }, - { - RepoName: "github.com/docker/compose", - RepoID: 4, - Path: "/file4.go", - }, - }, - wantRepos: []types.RepoIDName{ - {Name: "github.com/sourcegraph/about", ID: 1}, - {Name: "github.com/sourcegraph/annotate", ID: 2}, - {Name: "github.com/sourcegraph/sourcegraph", ID: 3}, - {Name: "github.com/docker/compose", ID: 4}, - }, - wantChunks: []FileChunkContext{ - { - RepoName: "github.com/sourcegraph/about", - RepoID: 1, - Path: "/file1.go", - }, - { - RepoName: "github.com/sourcegraph/annotate", - RepoID: 2, - Path: "/file2.go", - }, - { - RepoName: "github.com/sourcegraph/sourcegraph", - RepoID: 3, - Path: "/file3.go", - }, - { - RepoName: "github.com/docker/compose", - RepoID: 4, - Path: "/file4.go", - }, - }, - }, - { - name: "include and exclude rules are not defined", - ccf: &schema.CodyContextFilters{}, - repos: []types.RepoIDName{ - {Name: "github.com/sourcegraph/about", ID: 1}, - {Name: "github.com/sourcegraph/annotate", ID: 2}, - {Name: "github.com/sourcegraph/sourcegraph", ID: 3}, - {Name: "github.com/docker/compose", ID: 4}, - }, - chunks: []FileChunkContext{ - { - RepoName: "github.com/sourcegraph/about", - RepoID: 1, - Path: "/file1.go", - }, - { - RepoName: "github.com/sourcegraph/annotate", - RepoID: 2, - Path: "/file2.go", - }, - { - RepoName: "github.com/sourcegraph/sourcegraph", - RepoID: 3, - Path: "/file3.go", - }, - { - RepoName: "github.com/docker/compose", - RepoID: 4, - Path: "/file4.go", - }, - }, - wantRepos: []types.RepoIDName{ - {Name: "github.com/sourcegraph/about", ID: 1}, - {Name: "github.com/sourcegraph/annotate", ID: 2}, - {Name: "github.com/sourcegraph/sourcegraph", ID: 3}, - {Name: "github.com/docker/compose", ID: 4}, - }, - wantChunks: []FileChunkContext{ - { - RepoName: "github.com/sourcegraph/about", - RepoID: 1, - Path: "/file1.go", - }, - { - RepoName: "github.com/sourcegraph/annotate", - RepoID: 2, - Path: "/file2.go", - }, - { - RepoName: "github.com/sourcegraph/sourcegraph", - RepoID: 3, - Path: "/file3.go", - }, - { - RepoName: "github.com/docker/compose", - RepoID: 4, - Path: "/file4.go", - }, - }, - }, - { - name: "include and exclude rules empty", - ccf: &schema.CodyContextFilters{ - Include: []*schema.CodyContextFilterItem{}, - Exclude: []*schema.CodyContextFilterItem{}, - }, - repos: []types.RepoIDName{ - {Name: "github.com/sourcegraph/about", ID: 1}, - {Name: "github.com/sourcegraph/annotate", ID: 2}, - {Name: "github.com/sourcegraph/sourcegraph", ID: 3}, - {Name: "github.com/docker/compose", ID: 4}, - }, - chunks: []FileChunkContext{ - { - RepoName: "github.com/sourcegraph/about", - RepoID: 1, - Path: "/file1.go", - }, - { - RepoName: "github.com/sourcegraph/annotate", - RepoID: 2, - Path: "/file2.go", - }, - { - RepoName: "github.com/sourcegraph/sourcegraph", - RepoID: 3, - Path: "/file3.go", - }, - { - RepoName: "github.com/docker/compose", - RepoID: 4, - Path: "/file4.go", - }, - }, - wantRepos: []types.RepoIDName{ - {Name: "github.com/sourcegraph/about", ID: 1}, - {Name: "github.com/sourcegraph/annotate", ID: 2}, - {Name: "github.com/sourcegraph/sourcegraph", ID: 3}, - {Name: "github.com/docker/compose", ID: 4}, - }, - wantChunks: []FileChunkContext{ - { - RepoName: "github.com/sourcegraph/about", - RepoID: 1, - Path: "/file1.go", - }, - { - RepoName: "github.com/sourcegraph/annotate", - RepoID: 2, - Path: "/file2.go", - }, - { - RepoName: "github.com/sourcegraph/sourcegraph", - RepoID: 3, - Path: "/file3.go", - }, - { - RepoName: "github.com/docker/compose", - RepoID: 4, - Path: "/file4.go", - }, - }, - }, - { - name: "only include rules defined", - ccf: &schema.CodyContextFilters{ - Include: []*schema.CodyContextFilterItem{ - {RepoNamePattern: "^github\\.com\\/sourcegraph\\/.+"}, - }, - }, - repos: []types.RepoIDName{ - {Name: "github.com/sourcegraph/about", ID: 1}, - {Name: "github.com/sourcegraph/annotate", ID: 2}, - {Name: "github.com/sourcegraph/sourcegraph", ID: 3}, - {Name: "github.com/docker/compose", ID: 4}, - }, - chunks: []FileChunkContext{ - { - RepoName: "github.com/sourcegraph/about", - RepoID: 1, - Path: "/file1.go", - }, - { - RepoName: "github.com/sourcegraph/annotate", - RepoID: 2, - Path: "/file2.go", - }, - { - RepoName: "github.com/sourcegraph/sourcegraph", - RepoID: 3, - Path: "/file3.go", - }, - { - RepoName: "github.com/docker/compose", - RepoID: 4, - Path: "/file4.go", - }, - }, - wantRepos: []types.RepoIDName{ - {Name: "github.com/sourcegraph/about", ID: 1}, - {Name: "github.com/sourcegraph/annotate", ID: 2}, - {Name: "github.com/sourcegraph/sourcegraph", ID: 3}, - }, - wantChunks: []FileChunkContext{ - { - RepoName: "github.com/sourcegraph/about", - RepoID: 1, - Path: "/file1.go", - }, - { - RepoName: "github.com/sourcegraph/annotate", - RepoID: 2, - Path: "/file2.go", - }, - { - RepoName: "github.com/sourcegraph/sourcegraph", - RepoID: 3, - Path: "/file3.go", - }, - }, - }, - { - name: "only exclude rules defined", - ccf: &schema.CodyContextFilters{ - Exclude: []*schema.CodyContextFilterItem{ - {RepoNamePattern: "^github\\.com\\/sourcegraph\\/.+"}, - }, - }, - repos: []types.RepoIDName{ - {Name: "github.com/sourcegraph/about", ID: 1}, - {Name: "github.com/sourcegraph/annotate", ID: 2}, - {Name: "github.com/sourcegraph/sourcegraph", ID: 3}, - {Name: "github.com/docker/compose", ID: 4}, - }, - chunks: []FileChunkContext{ - { - RepoName: "github.com/sourcegraph/about", - RepoID: 1, - Path: "/file1.go", - }, - { - RepoName: "github.com/sourcegraph/annotate", - RepoID: 2, - Path: "/file2.go", - }, - { - RepoName: "github.com/sourcegraph/sourcegraph", - RepoID: 3, - Path: "/file3.go", - }, - { - RepoName: "github.com/docker/compose", - RepoID: 4, - Path: "/file4.go", - }, - }, - wantRepos: []types.RepoIDName{ - {Name: "github.com/docker/compose", ID: 4}, - }, - wantChunks: []FileChunkContext{ - { - RepoName: "github.com/docker/compose", - RepoID: 4, - Path: "/file4.go", - }, - }, - }, - { - name: "include and exclude rules defined", - ccf: &schema.CodyContextFilters{ - Include: []*schema.CodyContextFilterItem{ - {RepoNamePattern: "^github\\.com\\/sourcegraph\\/.+"}, - }, - Exclude: []*schema.CodyContextFilterItem{ - {RepoNamePattern: ".*cody.*"}, - }, - }, - repos: []types.RepoIDName{ - {Name: "github.com/sourcegraph/about", ID: 1}, - {Name: "github.com/sourcegraph/annotate", ID: 2}, - {Name: "github.com/sourcegraph/sourcegraph", ID: 3}, - {Name: "github.com/docker/compose", ID: 4}, - {Name: "github.com/sourcegraph/cody", ID: 5}, - }, - chunks: []FileChunkContext{ - { - RepoName: "github.com/sourcegraph/about", - RepoID: 1, - Path: "/file1.go", - }, - { - RepoName: "github.com/sourcegraph/annotate", - RepoID: 2, - Path: "/file2.go", - }, - { - RepoName: "github.com/sourcegraph/sourcegraph", - RepoID: 3, - Path: "/file3.go", - }, - { - RepoName: "github.com/docker/compose", - RepoID: 4, - Path: "/file4.go", - }, - { - RepoName: "github.com/sourcegraph/cody", - RepoID: 5, - Path: "/index.ts", - }, - }, - wantRepos: []types.RepoIDName{ - {Name: "github.com/sourcegraph/about", ID: 1}, - {Name: "github.com/sourcegraph/annotate", ID: 2}, - {Name: "github.com/sourcegraph/sourcegraph", ID: 3}, - }, - wantChunks: []FileChunkContext{ - { - RepoName: "github.com/sourcegraph/about", - RepoID: 1, - Path: "/file1.go", - }, - { - RepoName: "github.com/sourcegraph/annotate", - RepoID: 2, - Path: "/file2.go", - }, - { - RepoName: "github.com/sourcegraph/sourcegraph", - RepoID: 3, - Path: "/file3.go", - }, - }, - }, - { - name: "multiple include and exclude rules defined", - ccf: &schema.CodyContextFilters{ - Include: []*schema.CodyContextFilterItem{ - {RepoNamePattern: "^github\\.com\\/sourcegraph\\/.+"}, - {RepoNamePattern: "^github\\.com\\/docker\\/compose$"}, - {RepoNamePattern: "^github\\.com\\/.+\\/react"}, - }, - Exclude: []*schema.CodyContextFilterItem{ - {RepoNamePattern: ".*cody.*"}, - {RepoNamePattern: ".+\\/docker\\/.+"}, - }, - }, - repos: []types.RepoIDName{ - {Name: "github.com/sourcegraph/about", ID: 1}, - {Name: "github.com/sourcegraph/annotate", ID: 2}, - {Name: "github.com/sourcegraph/sourcegraph", ID: 3}, - {Name: "github.com/docker/compose", ID: 4}, - {Name: "github.com/sourcegraph/cody", ID: 5}, - {Name: "github.com/facebook/react", ID: 6}, - }, - chunks: []FileChunkContext{ - { - RepoName: "github.com/sourcegraph/about", - RepoID: 1, - Path: "/file1.go", - }, - { - RepoName: "github.com/sourcegraph/annotate", - RepoID: 2, - Path: "/file2.go", - }, - { - RepoName: "github.com/sourcegraph/sourcegraph", - RepoID: 3, - Path: "/file3.go", - }, - { - RepoName: "github.com/docker/compose", - RepoID: 4, - Path: "/file4.go", - }, - { - RepoName: "github.com/sourcegraph/cody", - RepoID: 5, - Path: "/index.ts", - }, - { - RepoName: "github.com/facebook/react", - RepoID: 6, - Path: "/hooks.ts", - }, - }, - wantRepos: []types.RepoIDName{ - {Name: "github.com/sourcegraph/about", ID: 1}, - {Name: "github.com/sourcegraph/annotate", ID: 2}, - {Name: "github.com/sourcegraph/sourcegraph", ID: 3}, - {Name: "github.com/facebook/react", ID: 6}, - }, - wantChunks: []FileChunkContext{ - { - RepoName: "github.com/sourcegraph/about", - RepoID: 1, - Path: "/file1.go", - }, - { - RepoName: "github.com/sourcegraph/annotate", - RepoID: 2, - Path: "/file2.go", - }, - { - RepoName: "github.com/sourcegraph/sourcegraph", - RepoID: 3, - Path: "/file3.go", - }, - { - RepoName: "github.com/facebook/react", - RepoID: 6, - Path: "/hooks.ts", - }, - }, - }, - { - name: "exclude everything", - ccf: &schema.CodyContextFilters{ - Include: []*schema.CodyContextFilterItem{ - {RepoNamePattern: "^github\\.com\\/sourcegraph\\/.+"}, - {RepoNamePattern: "^github\\.com\\/docker\\/compose$"}, - {RepoNamePattern: "^github\\.com\\/.+\\/react"}, - }, - Exclude: []*schema.CodyContextFilterItem{ - {RepoNamePattern: ".*cody.*"}, - {RepoNamePattern: ".*"}, - }, - }, - repos: []types.RepoIDName{ - {Name: "github.com/sourcegraph/about", ID: 1}, - {Name: "github.com/sourcegraph/annotate", ID: 2}, - {Name: "github.com/sourcegraph/sourcegraph", ID: 3}, - {Name: "github.com/docker/compose", ID: 4}, - {Name: "github.com/sourcegraph/cody", ID: 5}, - {Name: "github.com/facebook/react", ID: 6}, - }, - chunks: []FileChunkContext{ - { - RepoName: "github.com/sourcegraph/about", - RepoID: 1, - Path: "/file1.go", - }, - { - RepoName: "github.com/sourcegraph/annotate", - RepoID: 2, - Path: "/file2.go", - }, - { - RepoName: "github.com/sourcegraph/sourcegraph", - RepoID: 3, - Path: "/file3.go", - }, - { - RepoName: "github.com/docker/compose", - RepoID: 4, - Path: "/file4.go", - }, - { - RepoName: "github.com/sourcegraph/cody", - RepoID: 5, - Path: "/index.ts", - }, - { - RepoName: "github.com/facebook/react", - RepoID: 6, - Path: "/hooks.ts", - }, - }, - wantRepos: []types.RepoIDName{}, - wantChunks: []FileChunkContext{}, - }, + content, err := os.ReadFile(filepath.Join("testdata", "enterprise_filter_test_data.json")) + require.NoError(t, err) + + type repo struct { + Name api.RepoName + Id api.RepoID `json:"id"` + } + type fileChunk struct { + Repo repo + Path string + } + type testCase struct { + Name string `json:"name"` + Description string `json:"description"` + Ccf *schema.CodyContextFilters `json:"cody.contextFilters"` + Repos []repo `json:"repos"` + IncludedRepos []repo `json:"includedRepos"` + FileChunks []fileChunk `json:"fileChunks"` + IncludedFileChunks []fileChunk `json:"includedFileChunks"` + } + var data struct { + TestCases []testCase `json:"testCases"` + } + + err = json.Unmarshal(content, &data) + require.NoError(t, err) + + toRepoIDName := func(r repo) types.RepoIDName { return types.RepoIDName{ID: r.Id, Name: r.Name} } + + normalizeRepos := func(repos []repo) []types.RepoIDName { + result := make([]types.RepoIDName, 0, len(repos)) + for _, r := range repos { + result = append(result, toRepoIDName(r)) + } + return result + } + + normalizeFileChunks := func(fcc []fileChunk) []FileChunkContext { + result := make([]FileChunkContext, 0, len(fcc)) + for _, fc := range fcc { + r := toRepoIDName(fc.Repo) + result = append(result, FileChunkContext{RepoName: r.Name, RepoID: r.ID, Path: fc.Path}) + } + return result } newFF := func(v bool) *featureflag.FeatureFlag { @@ -533,19 +84,20 @@ func TestNewEnterpriseFilter(t *testing.T) { } featureFlagValues := []*featureflag.FeatureFlag{newFF(true), newFF(false), nil} - for _, tt := range tests { + for _, tt := range data.TestCases { for _, ff := range featureFlagValues { - name := tt.name + name := tt.Name if ff != nil { name = name + fmt.Sprintf(" (%q feature flag value: %t)", ff.Name, ff.Bool.Value) } t.Run(name, func(t *testing.T) { conf.Mock(&conf.Unified{ SiteConfiguration: schema.SiteConfiguration{ - CodyContextFilters: tt.ccf, + CodyContextFilters: tt.Ccf, }, }) + // TODO: remove feature flag mocking after `CodyContextFilters` support is added to the IDE clients. featureFlags := dbmocks.NewMockFeatureFlagStore() if ff != nil { featureFlags.GetFeatureFlagFunc.SetDefaultReturn(ff, nil) @@ -554,21 +106,21 @@ func TestNewEnterpriseFilter(t *testing.T) { db.FeatureFlagsFunc.SetDefaultReturn(featureFlags) f := newEnterpriseFilter(logtest.Scoped(t), db) - allowedRepos, matcher, _ := f.getMatcher(context.Background(), tt.repos) - filtered := make([]FileChunkContext, 0, len(tt.chunks)) - for _, chunk := range tt.chunks { - if matcher(chunk.RepoID, chunk.Path) { - filtered = append(filtered, chunk) + includedRepos, matcher, _ := f.getMatcher(context.Background(), normalizeRepos(tt.Repos)) + includedFileChunks := make([]fileChunk, 0, len(tt.FileChunks)) + for _, chunk := range tt.FileChunks { + if matcher(chunk.Repo.Id, chunk.Path) { + includedFileChunks = append(includedFileChunks, chunk) } } if ff != nil && ff.Bool.Value { - require.Equal(t, tt.wantRepos, allowedRepos) - require.Equal(t, tt.wantChunks, filtered) + require.Equal(t, normalizeRepos(tt.IncludedRepos), includedRepos) + require.Equal(t, normalizeFileChunks(tt.IncludedFileChunks), normalizeFileChunks(includedFileChunks)) } else { // If feature flag is not set or is set to false, the Cody context filters are disabled. - require.Equal(t, tt.repos, tt.repos) - require.Equal(t, tt.wantChunks, tt.wantChunks) + require.Equal(t, normalizeRepos(tt.Repos), includedRepos) + require.Equal(t, normalizeFileChunks(tt.FileChunks), normalizeFileChunks(includedFileChunks)) } }) } diff --git a/cmd/frontend/internal/codycontext/testdata/enterprise_filter_test_data.json b/cmd/frontend/internal/codycontext/testdata/enterprise_filter_test_data.json new file mode 100644 index 00000000000..146d0ae771f --- /dev/null +++ b/cmd/frontend/internal/codycontext/testdata/enterprise_filter_test_data.json @@ -0,0 +1,699 @@ +{ + "testCases": [ + { + "name": "Cody context filters are not defined", + "description": "Any repo should be included.", + "cody.contextFilters": null, + "repos": [ + { "name": "github.com/sourcegraph/about", "id": 1 }, + { "name": "github.com/sourcegraph/annotate", "id": 2 }, + { "name": "github.com/sourcegraph/sourcegraph", "id": 3 }, + { "name": "github.com/docker/compose", "id": 4 } + ], + "includedRepos": [ + { "name": "github.com/sourcegraph/about", "id": 1 }, + { "name": "github.com/sourcegraph/annotate", "id": 2 }, + { "name": "github.com/sourcegraph/sourcegraph", "id": 3 }, + { "name": "github.com/docker/compose", "id": 4 } + ], + "fileChunks": [ + { + "repo": { + "name": "github.com/sourcegraph/about", + "id": 1 + }, + "Path": "/file1.go" + }, + { + "repo": { + "name": "github.com/sourcegraph/annotate", + "id": 2 + }, + "Path": "/file2.go" + }, + { + "repo": { + "name": "github.com/sourcegraph/sourcegraph", + "id": 3 + }, + "Path": "/file3.go" + }, + { + "repo": { + "name": "github.com/docker/compose", + "id": 4 + }, + "Path": "/file4.go" + } + ], + "includedFileChunks": [ + { + "repo": { + "name": "github.com/sourcegraph/about", + "id": 1 + }, + "Path": "/file1.go" + }, + { + "repo": { + "name": "github.com/sourcegraph/annotate", + "id": 2 + }, + "Path": "/file2.go" + }, + { + "repo": { + "name": "github.com/sourcegraph/sourcegraph", + "id": 3 + }, + "Path": "/file3.go" + }, + { + "repo": { + "name": "github.com/docker/compose", + "id": 4 + }, + "Path": "/file4.go" + } + ] + }, + { + "name": "Include and exclude rules are not defined", + "description": "This scenario shouldn't happen. \"cody.contextFilters\" if defined in the site config, should have at least one property. Thus, either \"include\" or \"exclude\" should be defined. We rely on site config schema validation.", + "cody.contextFilters": {}, + "repos": [ + { "name": "github.com/sourcegraph/about", "id": 1 }, + { "name": "github.com/sourcegraph/annotate", "id": 2 }, + { "name": "github.com/sourcegraph/sourcegraph", "id": 3 }, + { "name": "github.com/docker/compose", "id": 4 } + ], + "includedRepos": [ + { "name": "github.com/sourcegraph/about", "id": 1 }, + { "name": "github.com/sourcegraph/annotate", "id": 2 }, + { "name": "github.com/sourcegraph/sourcegraph", "id": 3 }, + { "name": "github.com/docker/compose", "id": 4 } + ], + "fileChunks": [ + { + "repo": { + "name": "github.com/sourcegraph/about", + "id": 1 + }, + "path": "/file1.go" + }, + { + "repo": { + "name": "github.com/sourcegraph/annotate", + "id": 2 + }, + "path": "/file2.go" + }, + { + "repo": { + "name": "github.com/sourcegraph/sourcegraph", + "id": 3 + }, + "path": "/file3.go" + }, + { + "repo": { + "name": "github.com/docker/compose", + "id": 4 + }, + "path": "/file4.go" + } + ], + "includedFileChunks": [ + { + "repo": { + "name": "github.com/sourcegraph/about", + "id": 1 + }, + "path": "/file1.go" + }, + { + "repo": { + "name": "github.com/sourcegraph/annotate", + "id": 2 + }, + "path": "/file2.go" + }, + { + "repo": { + "name": "github.com/sourcegraph/sourcegraph", + "id": 3 + }, + "path": "/file3.go" + }, + { + "repo": { + "name": "github.com/docker/compose", + "id": 4 + }, + "path": "/file4.go" + } + ] + }, + { + "name": "Include and exclude rules are empty lists", + "description": "This scenario shouldn't happen. If either \"include\" or \"exclude\" field is defined, it should have at least one item. We rely on site config schema validation.", + "cody.contextFilters": { + "include": [], + "exclude": [] + }, + "repos": [ + { "name": "github.com/sourcegraph/about", "id": 1 }, + { "name": "github.com/sourcegraph/annotate", "id": 2 }, + { "name": "github.com/sourcegraph/sourcegraph", "id": 3 }, + { "name": "github.com/docker/compose", "id": 4 } + ], + "includedRepos": [ + { "name": "github.com/sourcegraph/about", "id": 1 }, + { "name": "github.com/sourcegraph/annotate", "id": 2 }, + { "name": "github.com/sourcegraph/sourcegraph", "id": 3 }, + { "name": "github.com/docker/compose", "id": 4 } + ], + "fileChunks": [ + { + "repo": { + "name": "github.com/sourcegraph/about", + "id": 1 + }, + "path": "/file1.go" + }, + { + "repo": { + "name": "github.com/sourcegraph/annotate", + "id": 2 + }, + "path": "/file2.go" + }, + { + "repo": { + "name": "github.com/sourcegraph/sourcegraph", + "id": 3 + }, + "path": "/file3.go" + }, + { + "repo": { + "name": "github.com/docker/compose", + "id": 4 + }, + "path": "/file4.go" + } + ], + "includedFileChunks": [ + { + "repo": { + "name": "github.com/sourcegraph/about", + "id": 1 + }, + "path": "/file1.go" + }, + { + "repo": { + "name": "github.com/sourcegraph/annotate", + "id": 2 + }, + "path": "/file2.go" + }, + { + "repo": { + "name": "github.com/sourcegraph/sourcegraph", + "id": 3 + }, + "path": "/file3.go" + }, + { + "repo": { + "name": "github.com/docker/compose", + "id": 4 + }, + "path": "/file4.go" + } + ] + }, + { + "name": "Only include rules are defined", + "description": "Only repos matching \"include\" repo name patterns should be included.", + "cody.contextFilters": { + "include": [{ "repoNamePattern": "^github\\.com\\/sourcegraph\\/.+" }] + }, + "repos": [ + { "name": "github.com/sourcegraph/about", "id": 1 }, + { "name": "github.com/sourcegraph/annotate", "id": 2 }, + { "name": "github.com/sourcegraph/sourcegraph", "id": 3 }, + { "name": "github.com/docker/compose", "id": 4 } + ], + "includedRepos": [ + { "name": "github.com/sourcegraph/about", "id": 1 }, + { "name": "github.com/sourcegraph/annotate", "id": 2 }, + { "name": "github.com/sourcegraph/sourcegraph", "id": 3 } + ], + "fileChunks": [ + { + "repo": { + "name": "github.com/sourcegraph/about", + "id": 1 + }, + "path": "/file1.go" + }, + { + "repo": { + "name": "github.com/sourcegraph/annotate", + "id": 2 + }, + "path": "/file2.go" + }, + { + "repo": { + "name": "github.com/sourcegraph/sourcegraph", + "id": 3 + }, + "path": "/file3.go" + }, + { + "repo": { + "name": "github.com/docker/compose", + "id": 4 + }, + "path": "/file4.go" + } + ], + "includedFileChunks": [ + { + "repo": { + "name": "github.com/sourcegraph/about", + "id": 1 + }, + "path": "/file1.go" + }, + { + "repo": { + "name": "github.com/sourcegraph/annotate", + "id": 2 + }, + "path": "/file2.go" + }, + { + "repo": { + "name": "github.com/sourcegraph/sourcegraph", + "id": 3 + }, + "path": "/file3.go" + } + ] + }, + { + "name": "Only exclude rules are defined", + "description": "Only repos not matching any of \"include\" repo name patterns should be included.", + "cody.contextFilters": { + "exclude": [{ "repoNamePattern": "^github\\.com\\/sourcegraph\\/.+" }] + }, + "repos": [ + { "name": "github.com/sourcegraph/about", "id": 1 }, + { "name": "github.com/sourcegraph/annotate", "id": 2 }, + { "name": "github.com/sourcegraph/sourcegraph", "id": 3 }, + { "name": "github.com/docker/compose", "id": 4 } + ], + "includedRepos": [{ "name": "github.com/docker/compose", "id": 4 }], + "fileChunks": [ + { + "repo": { + "name": "github.com/sourcegraph/about", + "id": 1 + }, + "path": "/file1.go" + }, + { + "repo": { + "name": "github.com/sourcegraph/annotate", + "id": 2 + }, + "path": "/file2.go" + }, + { + "repo": { + "name": "github.com/sourcegraph/sourcegraph", + "id": 3 + }, + "path": "/file3.go" + }, + { + "repo": { + "name": "github.com/docker/compose", + "id": 4 + }, + "path": "/file4.go" + } + ], + "includedFileChunks": [ + { + "repo": { + "name": "github.com/docker/compose", + "id": 4 + }, + "path": "/file4.go" + } + ] + }, + { + "name": "Include and exclude rules are defined", + "description": "Only repos matching any of \"include\" and not matching any of \"exclude\" repo name patterns should be included.", + "cody.contextFilters": { + "include": [{ "repoNamePattern": "^github\\.com\\/sourcegraph\\/.+" }], + "exclude": [{ "repoNamePattern": ".*cody.*" }] + }, + "repos": [ + { "name": "github.com/sourcegraph/about", "id": 1 }, + { "name": "github.com/sourcegraph/annotate", "id": 2 }, + { "name": "github.com/sourcegraph/sourcegraph", "id": 3 }, + { "name": "github.com/docker/compose", "id": 4 }, + { "name": "github.com/sourcegraph/cody", "id": 5 } + ], + "includedRepos": [ + { "name": "github.com/sourcegraph/about", "id": 1 }, + { "name": "github.com/sourcegraph/annotate", "id": 2 }, + { "name": "github.com/sourcegraph/sourcegraph", "id": 3 } + ], + "fileChunks": [ + { + "repo": { + "name": "github.com/sourcegraph/about", + "id": 1 + }, + "path": "/file1.go" + }, + { + "repo": { + "name": "github.com/sourcegraph/annotate", + "id": 2 + }, + "path": "/file2.go" + }, + { + "repo": { + "name": "github.com/sourcegraph/sourcegraph", + "id": 3 + }, + "path": "/file3.go" + }, + { + "repo": { + "name": "github.com/docker/compose", + "id": 4 + }, + "path": "/file4.go" + }, + { + "repo": { + "name": "github.com/sourcegraph/cody", + "id": 5 + }, + "path": "/index.ts" + } + ], + "includedFileChunks": [ + { + "repo": { + "name": "github.com/sourcegraph/about", + "id": 1 + }, + "path": "/file1.go" + }, + { + "repo": { + "name": "github.com/sourcegraph/annotate", + "id": 2 + }, + "path": "/file2.go" + }, + { + "repo": { + "name": "github.com/sourcegraph/sourcegraph", + "id": 3 + }, + "path": "/file3.go" + } + ] + }, + { + "name": "Multiple include and exclude rules are defined", + "description": "Only repos matching any of \"include\" and not matching any of \"exclude\" repo name patterns should be included.", + "cody.contextFilters": { + "include": [ + { "repoNamePattern": "^github\\.com\\/sourcegraph\\/.+" }, + { "repoNamePattern": "^github\\.com\\/docker\\/compose$" }, + { "repoNamePattern": "^github\\.com\\/.+\\/react" } + ], + "exclude": [{ "repoNamePattern": ".*cody.*" }, { "repoNamePattern": ".+\\/docker\\/.+" }] + }, + "repos": [ + { "name": "github.com/sourcegraph/about", "id": 1 }, + { "name": "github.com/sourcegraph/annotate", "id": 2 }, + { "name": "github.com/sourcegraph/sourcegraph", "id": 3 }, + { "name": "github.com/docker/compose", "id": 4 }, + { "name": "github.com/sourcegraph/cody", "id": 5 }, + { "name": "github.com/facebook/react", "id": 6 } + ], + "includedRepos": [ + { "name": "github.com/sourcegraph/about", "id": 1 }, + { "name": "github.com/sourcegraph/annotate", "id": 2 }, + { "name": "github.com/sourcegraph/sourcegraph", "id": 3 }, + { "name": "github.com/facebook/react", "id": 6 } + ], + "fileChunks": [ + { + "repo": { + "name": "github.com/sourcegraph/about", + "id": 1 + }, + "path": "/file1.go" + }, + { + "repo": { + "name": "github.com/sourcegraph/annotate", + "id": 2 + }, + "path": "/file2.go" + }, + { + "repo": { + "name": "github.com/sourcegraph/sourcegraph", + "id": 3 + }, + "path": "/file3.go" + }, + { + "repo": { + "name": "github.com/docker/compose", + "id": 4 + }, + "path": "/file4.go" + }, + { + "repo": { + "name": "github.com/sourcegraph/cody", + "id": 5 + }, + "path": "/index.ts" + }, + { + "repo": { + "name": "github.com/facebook/react", + "id": 6 + }, + "path": "/hooks.ts" + } + ], + "includedFileChunks": [ + { + "repo": { + "name": "github.com/sourcegraph/about", + "id": 1 + }, + "path": "/file1.go" + }, + { + "repo": { + "name": "github.com/sourcegraph/annotate", + "id": 2 + }, + "path": "/file2.go" + }, + { + "repo": { + "name": "github.com/sourcegraph/sourcegraph", + "id": 3 + }, + "path": "/file3.go" + }, + { + "repo": { + "name": "github.com/facebook/react", + "id": 6 + }, + "path": "/hooks.ts" + } + ] + }, + { + "name": "Include rules contain repo name pattern matching any repo", + "description": "Any repo should be included.", + "cody.contextFilters": { + "include": [{ "repoNamePattern": ".*" }] + }, + "repos": [ + { "name": "github.com/sourcegraph/about", "id": 1 }, + { "name": "github.com/sourcegraph/annotate", "id": 2 }, + { "name": "github.com/sourcegraph/sourcegraph", "id": 3 }, + { "name": "github.com/docker/compose", "id": 4 }, + { "name": "github.com/sourcegraph/cody", "id": 5 }, + { "name": "github.com/facebook/react", "id": 6 } + ], + "includedRepos": [ + { "name": "github.com/sourcegraph/about", "id": 1 }, + { "name": "github.com/sourcegraph/annotate", "id": 2 }, + { "name": "github.com/sourcegraph/sourcegraph", "id": 3 }, + { "name": "github.com/docker/compose", "id": 4 }, + { "name": "github.com/sourcegraph/cody", "id": 5 }, + { "name": "github.com/facebook/react", "id": 6 } + ], + "fileChunks": [ + { + "repo": { + "name": "github.com/sourcegraph/about", + "id": 1 + }, + "path": "/file1.go" + }, + { + "repo": { + "name": "github.com/sourcegraph/annotate", + "id": 2 + }, + "path": "/file2.go" + }, + { + "repo": { + "name": "github.com/sourcegraph/sourcegraph", + "id": 3 + }, + "path": "/file3.go" + }, + { + "repo": { + "name": "github.com/docker/compose", + "id": 4 + }, + "path": "/file4.go" + }, + { + "repo": { + "name": "github.com/sourcegraph/cody", + "id": 5 + }, + "path": "/index.ts" + }, + { + "repo": { + "name": "github.com/facebook/react", + "id": 6 + }, + "path": "/hooks.ts" + } + ], + "includedFileChunks": [ + { + "repo": { + "name": "github.com/sourcegraph/about", + "id": 1 + }, + "path": "/file1.go" + }, + { + "repo": { + "name": "github.com/sourcegraph/annotate", + "id": 2 + }, + "path": "/file2.go" + }, + { + "repo": { + "name": "github.com/sourcegraph/sourcegraph", + "id": 3 + }, + "path": "/file3.go" + }, + { + "repo": { + "name": "github.com/docker/compose", + "id": 4 + }, + "path": "/file4.go" + }, + { + "repo": { + "name": "github.com/sourcegraph/cody", + "id": 5 + }, + "path": "/index.ts" + }, + { + "repo": { + "name": "github.com/facebook/react", + "id": 6 + }, + "path": "/hooks.ts" + } + ] + }, + { + "name": "Exclude rules contain repo name pattern matching any repo", + "description": "Neither repo should be included.", + "cody.contextFilters": { + "include": [{ "repoNamePattern": "^github\\.com\\/sourcegraph\\/.+" }], + "exclude": [{ "repoNamePattern": ".*" }] + }, + "repos": [ + { "name": "github.com/sourcegraph/about", "id": 1 }, + { "name": "github.com/sourcegraph/annotate", "id": 2 }, + { "name": "github.com/sourcegraph/sourcegraph", "id": 3 }, + { "name": "github.com/docker/compose", "id": 4 } + ], + "includedRepos": [], + "fileChunks": [ + { + "repo": { + "name": "github.com/sourcegraph/about", + "id": 1 + }, + "path": "/file1.go" + }, + { + "repo": { + "name": "github.com/sourcegraph/annotate", + "id": 2 + }, + "path": "/file2.go" + }, + { + "repo": { + "name": "github.com/sourcegraph/sourcegraph", + "id": 3 + }, + "path": "/file3.go" + }, + { + "repo": { + "name": "github.com/docker/compose", + "id": 4 + }, + "path": "/file4.go" + } + ], + "includedFileChunks": [] + } + ] +} diff --git a/package.json b/package.json index c188b0d1d33..05e4315b896 100644 --- a/package.json +++ b/package.json @@ -81,6 +81,7 @@ "@sentry/cli": "^1.74.4", "@sentry/esbuild-plugin": "^2.7.1", "@slack/web-api": "^5.15.0", + "@sourcegraph/cody-context-filters-test-dataset": "^1.0.0", "@sourcegraph/eslint-config": "0.37.1", "@sourcegraph/eslint-plugin-sourcegraph": "^1.0.5", "@sourcegraph/eslint-plugin-wildcard": "workspace:*", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fe12977c821..c28398bf772 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -542,6 +542,9 @@ importers: '@slack/web-api': specifier: ^5.15.0 version: 5.15.0 + '@sourcegraph/cody-context-filters-test-dataset': + specifier: ^1.0.0 + version: 1.0.0 '@sourcegraph/eslint-config': specifier: 0.37.1 version: 0.37.1(@testing-library/dom@8.13.0)(eslint@8.57.0)(typescript@5.4.2) @@ -8426,6 +8429,10 @@ packages: '@sourcegraph/codemod-toolkit-ts': 1.0.1 dev: true + /@sourcegraph/cody-context-filters-test-dataset@1.0.0: + resolution: {integrity: sha512-Uf7wMo5Fu3+g03gl2jvU2qHMaDp0p9RK9U2ucmy6VxWaavxALCC8iy47JL5GdgR5qG3ekEd5mAQV0dIIfoKELA==} + dev: true + /@sourcegraph/eslint-config@0.37.1(@testing-library/dom@8.13.0)(eslint@8.57.0)(typescript@5.4.2): resolution: {integrity: sha512-3G0d3OUgifaADfd27Bdk/kSpECj21BfQ6srbYMY/HVWOv/N8AVuFWNwUMT4Y4slt026RXO5XcwoZhfnaskr5hQ==} dependencies: diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 733521a1e6c..215450fdeac 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,3 +1,5 @@ packages: - 'client/*' + # The test dataset is generated and ignored by Git. Use the published version instead. + - '!client/cody-context-filters-test-dataset' - 'schema'