Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions build/azure-pipelines/copilot/test-integration-steps.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,19 @@ parameters:
type: string # linux, darwin, win32

steps:
- script: git lfs install --local
displayName: Initialize Git LFS

- script: git lfs pull --include="extensions/copilot/test/simulation/cache/**"
condition: and(succeeded(), eq(variables['Build.Repository.Provider'], 'GitHub'))
displayName: Pull Copilot test cache from GitHub

- script: git --config-env=http.extraheader=GIT_AUTH_HEADER lfs pull --include="extensions/copilot/test/simulation/cache/**"
condition: and(succeeded(), eq(variables['Build.Repository.Provider'], 'TfsGit'))
displayName: Pull Copilot test cache from Azure Repos
env:
GIT_AUTH_HEADER: "AUTHORIZATION: bearer $(System.AccessToken)"

# Setup copilot test environment (tokens, env vars)
- task: AzureCLI@2
inputs:
Expand Down
5 changes: 3 additions & 2 deletions build/azure-pipelines/distro/download-distro.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ steps:
- checkout: distro
path: s/.build/distro
fetchDepth: 0
persistCredentials: true
Comment thread
rzhao271 marked this conversation as resolved.
retryCountOnTaskFailure: 3
displayName: Checkout microsoft/vscode-distro

Expand All @@ -17,10 +18,10 @@ steps:
git -C .build/distro checkout $DistroVersion
displayName: Checkout distro commit

- script: git lfs install --local
- script: git -C .build/distro lfs install --local
displayName: Initialize Git LFS

- script: git lfs pull
- script: git -C .build/distro lfs pull
displayName: Pull Git LFS objects

# Check out the private microsoft/vscode-encrypt, microsoft/vsda and
Expand Down
4 changes: 4 additions & 0 deletions extensions/copilot/.github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,10 @@ If `start-watch-tasks` is already running, use its diagnostics. Start it or run
- **Event-driven**: Extensive use of VS Code's event system and disposables
- **Layered**: Clear separation between platform services and extension features

### Dependency Boundaries
- Do not import directly from the repository's root `src/vs/` tree. The extension is compiled and bundled from its own `src/` tree, and root VS Code internals are not an extension dependency.
- Use the corresponding implementation under `extensions/copilot/src/` or the vendored compatibility code under `extensions/copilot/src/util/vs/` when it is already available. Keep shared behavior behind the extension's own platform abstractions.

### Testing Standards
- **Unit Tests**: Vitest for isolated component testing
- **Integration Tests**: VS Code extension host tests for API integration
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,34 +24,43 @@ function findGitRoot(startDir: string): string {
return dir;
}

function getOriginInfo(gitRoot: string): { org: string; repo: string } {
type OriginInfo =
| { type: 'github'; org: string; repo: string }
| { type: 'ado'; org: string; project: string; repo: string };

function getOriginInfo(gitRoot: string): OriginInfo {
const originUrl = execSync('git config --get remote.origin.url', { cwd: gitRoot, encoding: 'utf-8' }).trim();
const match = originUrl.match(/github\.com[:/](?<org>[^/]+)\/(?<repo>[^/.]+)/);
if (!match?.groups) {
throw new Error(`Could not parse origin URL: ${originUrl}`);
const githubMatch = originUrl.match(/github\.com[:/](?<org>[^/]+)\/(?<repo>[^/.]+)/);
if (githubMatch?.groups) {
return {
type: 'github',
org: githubMatch.groups.org,
repo: githubMatch.groups.repo
};
}
return { org: match.groups.org, repo: match.groups.repo };
}

suite('Extract repo info tests', function () {
const gitRoot = findGitRoot(__dirname);
const baseFolder = { uri: makeFsUri(gitRoot) };
const origin = getOriginInfo(gitRoot);

test('Extract repo info', async function () {
const accessor = createLibTestingContext().createTestingAccessor();
const info = await extractRepoInfo(accessor, baseFolder.uri);
const adoMatch = originUrl.match(/dev\.azure\.com\/(?<org>[^/]+)\/(?<project>[^/]+)\/_git\/(?<repo>[^/.]+)/);
if (adoMatch?.groups) {
return {
type: 'ado',
org: adoMatch.groups.org,
project: adoMatch.groups.project,
repo: adoMatch.groups.repo
};
}

assert.ok(info);
throw new Error(`Could not parse origin URL: ${originUrl}`);
}

// url and pathname get their own special treatment because they depend on how the repo was cloned.
const { url, pathname, repoId, ...repoInfo } = info;
function assertRepoInfo(info: NonNullable<Awaited<ReturnType<typeof extractRepoInfo>>>, baseFolder: { uri: string }, origin: OriginInfo): void {
const { url, pathname, repoId, ...repoInfo } = info;
assert.ok(repoId);

if (origin.type === 'github') {
assert.deepStrictEqual(repoInfo, {
baseFolder,
hostname: 'github.com'
});
assert.ok(repoId);
assert.deepStrictEqual(
{ org: repoId.org, repo: repoId.repo, type: repoId.type },
{ org: origin.org, repo: origin.repo, type: 'github' }
Expand All @@ -64,7 +73,31 @@ suite('Extract repo info tests', function () {
].includes(url),
`url is ${url}`
);
assert.ok(pathname.includes(`/${origin.repo}`));
} else {
assert.deepStrictEqual(repoInfo, {
baseFolder,
hostname: 'dev.azure.com'
});
assert.deepStrictEqual(
{ org: repoId.org, project: repoId.type === 'ado' ? repoId.project : undefined, repo: repoId.repo, type: repoId.type },
{ org: origin.org, project: origin.project, repo: origin.repo, type: 'ado' }
);
}

assert.ok(pathname.includes(`/${origin.repo}`));
}

suite('Extract repo info tests', function () {
const gitRoot = findGitRoot(__dirname);
const baseFolder = { uri: makeFsUri(gitRoot) };
const origin = getOriginInfo(gitRoot);

test('Extract repo info', async function () {
const accessor = createLibTestingContext().createTestingAccessor();
const info = await extractRepoInfo(accessor, baseFolder.uri);

assert.ok(info);
assertRepoInfo(info, baseFolder, origin);

assert.deepStrictEqual(await extractRepoInfo(accessor, 'file:///tmp/does/not/exist/.git/config'), undefined);
});
Expand All @@ -77,28 +110,7 @@ suite('Extract repo info tests', function () {
const info = await extractRepoInfo(accessor, cellUri);

assert.ok(info);

// url and pathname get their own special treatment because they depend on how the repo was cloned.
const { url, pathname, repoId, ...repoInfo } = info;

assert.deepStrictEqual(repoInfo, {
baseFolder,
hostname: 'github.com'
});
assert.ok(repoId);
assert.deepStrictEqual(
{ org: repoId.org, repo: repoId.repo, type: repoId.type },
{ org: origin.org, repo: origin.repo, type: 'github' }
);
assert.ok(
[
`git@github.com:${origin.org}/${origin.repo}`,
`https://github.com/${origin.org}/${origin.repo}`,
`https://github.com/${origin.org}/${origin.repo}.git`,
].includes(url),
`url is ${url}`
);
assert.ok(pathname.includes(`/${origin.repo}`));
assertRepoInfo(info, baseFolder, origin);

assert.deepStrictEqual(await instantiationService.invokeFunction(extractRepoInfo, 'file:///tmp/does/not/exist/.git/config'), undefined);
});
Expand Down
Loading