Skip to content

Commit fb84bcc

Browse files
authored
Add in git clone to test existing apps (#899)
1 parent ae3a148 commit fb84bcc

File tree

4 files changed

+135
-13
lines changed

4 files changed

+135
-13
lines changed

tests/azure-deploy/integration.test.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@ import {
1717
} from "../utils/agent-runner";
1818
import * as fs from "fs";
1919
import { hasDeployLinks } from "./utils";
20+
import { cloneRepo } from "../utils/git-clone";
2021

2122
const SKILL_NAME = "azure-deploy";
2223
const RUNS_PER_PROMPT = 5;
2324
const EXPECTED_INVOCATION_RATE = 0.6; // 60% minimum invocation rate
25+
const ESHOP_REPO = "https://github.com/dotnet/eShop.git";
2426

2527
// Check if integration tests should be skipped at module level
2628
const skipTests = shouldSkipIntegrationTests();
@@ -277,4 +279,36 @@ describeIntegration(`${SKILL_NAME} - Integration Tests`, () => {
277279
expect(containsDeployLinks).toBe(true);
278280
}, deployTestTimeoutMs);
279281
});
282+
283+
describe("brownfield-dotnet", () => {
284+
test("deploys eShop to Azure for small scale production", async () => {
285+
const agentMetadata = await agent.run({
286+
setup: async (workspace: string) => {
287+
await cloneRepo({
288+
repoUrl: ESHOP_REPO,
289+
targetDir: workspace,
290+
depth: 1,
291+
});
292+
},
293+
prompt:
294+
"Please deploy this application to Azure. " +
295+
"Use the eastus2 region. " +
296+
"Use my current subscription. " +
297+
"This is for a small scale production environment. " +
298+
"Use standard SKUs",
299+
nonInteractive: true,
300+
followUp: FOLLOW_UP_PROMPT,
301+
});
302+
303+
const isSkillUsed = isSkillInvoked(agentMetadata, SKILL_NAME);
304+
const isValidateInvoked = isSkillInvoked(agentMetadata, "azure-validate");
305+
const isPrepareInvoked = isSkillInvoked(agentMetadata, "azure-prepare");
306+
const containsDeployLinks = hasDeployLinks(agentMetadata);
307+
308+
expect(isSkillUsed).toBe(true);
309+
expect(isValidateInvoked).toBe(true);
310+
expect(isPrepareInvoked).toBe(true);
311+
expect(containsDeployLinks).toBe(true);
312+
}, deployTestTimeoutMs);
313+
})
280314
});

tests/package-lock.json

Lines changed: 34 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@
3838
"jest-junit": "^16.0.0",
3939
"ts-jest": "^29.1.2",
4040
"ts-node": "^10.9.2",
41-
"typescript": "^5.3.3"
41+
"typescript": "^5.3.3",
42+
"simple-git": "^3.30.0"
4243
},
4344
"jest-junit": {
4445
"outputDirectory": "./reports",

tests/utils/git-clone.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/**
2+
* Git Clone Utility
3+
*
4+
* Clones a Git repository to a local directory using simple-git.
5+
* Useful for integration tests that need a real repository as a workspace.
6+
*/
7+
8+
import { simpleGit, type SimpleGitOptions } from "simple-git";
9+
10+
export interface CloneOptions {
11+
/** Full repository URL (HTTPS or SSH). */
12+
repoUrl: string;
13+
/** Target directory to clone into. */
14+
targetDir: string;
15+
/** Clone only a single branch. */
16+
branch?: string;
17+
/** Shallow clone with the given depth (e.g. 1). */
18+
depth?: number;
19+
/** Only check out a specific path within the repo (sparse checkout). */
20+
sparseCheckoutPath?: string;
21+
}
22+
23+
/**
24+
* Clone a Git repository.
25+
*
26+
* @example
27+
* ```ts
28+
* await cloneRepo({
29+
* repoUrl: "https://github.com/Azure-Samples/todo-nodejs-mongo.git",
30+
* targetDir: "/path/to/workspace",
31+
* depth: 1,
32+
* });
33+
* ```
34+
*/
35+
export async function cloneRepo(options: CloneOptions): Promise<void> {
36+
const { repoUrl, targetDir, branch, depth, sparseCheckoutPath } = options;
37+
38+
const gitOptions: Partial<SimpleGitOptions> = {
39+
baseDir: process.cwd(),
40+
binary: "git",
41+
maxConcurrentProcesses: 1,
42+
};
43+
44+
const git = simpleGit(gitOptions);
45+
46+
const cloneArgs: string[] = [];
47+
if (branch) {
48+
cloneArgs.push("--branch", branch, "--single-branch");
49+
}
50+
if (depth) {
51+
cloneArgs.push("--depth", String(depth));
52+
}
53+
54+
if (sparseCheckoutPath) {
55+
// Clone without checking out files, then sparse-checkout the target path
56+
cloneArgs.push("--no-checkout");
57+
await git.clone(repoUrl, targetDir, cloneArgs);
58+
59+
const repoGit = simpleGit({ ...gitOptions, baseDir: targetDir });
60+
await repoGit.raw(["sparse-checkout", "set", sparseCheckoutPath]);
61+
await repoGit.checkout(branch ?? "HEAD");
62+
} else {
63+
await git.clone(repoUrl, targetDir, cloneArgs);
64+
}
65+
}

0 commit comments

Comments
 (0)