Skip to content

Commit fcfbf13

Browse files
authored
chore: try to speed up integration test downloads (#6611)
1 parent babf18a commit fcfbf13

File tree

6 files changed

+126
-26
lines changed

6 files changed

+126
-26
lines changed

integration-tests/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
"dependencies": {
3030
"@cspell/cspell-types": "workspace:*",
3131
"@octokit/rest": "^21.0.2",
32+
"ansi-escapes": "^7.0.0",
3233
"chalk": "^5.3.0",
3334
"commander": "^12.1.0",
3435
"csv-parse": "^5.6.0",

integration-tests/src/PrefixLogger.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
/* eslint-disable @typescript-eslint/no-explicit-any */
22

3-
import { errorWithPrefix, logWithPrefix } from './outputHelper.js';
3+
import { errorWithPrefix, logWithPrefix, outputWithPrefix } from './outputHelper.js';
44
import type { Logger } from './types.js';
55

66
export class PrefixLogger implements Logger {
77
constructor(readonly prefix: string) {}
88

9+
readonly output = (message: string, ...optionalParams: unknown[]): void => {
10+
outputWithPrefix(this.prefix, message, ...optionalParams);
11+
};
12+
913
readonly log = (message?: any, ...optionalParams: any[]): void => {
1014
logWithPrefix(this.prefix, message, ...optionalParams);
1115
};

integration-tests/src/outputHelper.ts

+30-1
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,44 @@ export function prefix(pfx: string, text: string): string {
4141
return text
4242
.split('\n')
4343
.map((line) => pfx + line)
44-
.join('\n');
44+
.join('\n')
45+
.replaceAll('\r\n', '\n')
46+
.replaceAll('\r', '\r' + pfx);
47+
}
48+
49+
let lastPrefix = '';
50+
let pending = false;
51+
52+
function clearLastPrefix() {
53+
if (pending) {
54+
process.stdout.write('\r\n');
55+
pending = false;
56+
}
57+
lastPrefix = '';
58+
}
59+
60+
function setLastPrefix(pfx: string) {
61+
if (pending && lastPrefix !== pfx) {
62+
process.stdout.write('\r\n');
63+
}
64+
pending = true;
65+
lastPrefix = pfx;
66+
}
67+
68+
export function outputWithPrefix(pfx: string, text: string, ...params: unknown[]): void {
69+
setLastPrefix(pfx);
70+
const s = text ? format(text, ...params) : '';
71+
process.stdout.write(prefix(pfx, s).replaceAll('\n', '\r\n'));
4572
}
4673

4774
export function logWithPrefix(pfx: string, text: string, ...params: unknown[]): void {
75+
clearLastPrefix();
4876
const s = text ? format(text, ...params) : '';
4977
console.log(prefix(pfx, s));
5078
}
5179

5280
export function errorWithPrefix(pfx: string, text: string, ...params: unknown[]): void {
81+
clearLastPrefix();
5382
const s = text ? format(text, ...params) : '';
5483
console.error(prefix(pfx, red(s)));
5584
}

integration-tests/src/repositoryHelper.ts

+58-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import * as Path from 'node:path';
33
import { fileURLToPath } from 'node:url';
44

55
import { Octokit } from '@octokit/rest';
6+
import { eraseEndLine } from 'ansi-escapes';
67
import chalk from 'chalk';
78
import { simpleGit } from 'simple-git';
89

@@ -85,7 +86,11 @@ export async function checkoutRepositoryAsync(
8586
if (!fs.existsSync(path)) {
8687
try {
8788
const repoInfo = await fetchRepositoryInfoForRepo(url);
88-
const c = await cloneRepo(logger, url, path, !branch || branch === repoInfo.defaultBranch);
89+
const cloneOptions: CloneOptions = {
90+
commit: commit || branch || repoInfo.defaultBranch,
91+
depth: 1,
92+
};
93+
const c = await cloneRepoFast(logger, url, path, cloneOptions);
8994
if (!c) {
9095
return false;
9196
}
@@ -108,7 +113,7 @@ export async function checkoutRepositoryAsync(
108113
return true;
109114
}
110115

111-
async function cloneRepo(
116+
async function _cloneRepo(
112117
{ log, error }: Logger,
113118
url: string,
114119
path: string,
@@ -187,3 +192,54 @@ function getOctokit(auth?: string | undefined): Octokit {
187192
const options = auth ? { auth } : undefined;
188193
return new Octokit(options);
189194
}
195+
196+
interface CloneOptions {
197+
commit: string;
198+
depth?: number;
199+
}
200+
201+
/**
202+
* Clone a repository
203+
* ```sh
204+
* mkdir <repo-name>
205+
* cd <repo-name>
206+
* git init
207+
* git remote add origin <repository-url>
208+
* git fetch origin <commit-hash> --depth=1
209+
* git checkout FETCH_HEAD
210+
* ```
211+
* @param logger
212+
* @param url
213+
* @param path
214+
* @param options
215+
* @returns
216+
*/
217+
async function cloneRepoFast(logger: Logger, url: string, path: string, options: CloneOptions): Promise<boolean> {
218+
const { log, error } = logger;
219+
const stdOut = logger.output || log;
220+
log(`Cloning ${url}`);
221+
await mkdirp(path);
222+
const gitOptions = [];
223+
if (options.depth) {
224+
gitOptions.push(`--depth=${options.depth}`);
225+
}
226+
try {
227+
const git = simpleGit({
228+
baseDir: path,
229+
progress({ method, stage, progress }) {
230+
stdOut(`\r${method} ${stage} stage ${progress}% complete${eraseEndLine}`);
231+
},
232+
});
233+
log(`Init ${url}`);
234+
await git.init().addRemote('origin', url);
235+
log(`Fetch ${url}`);
236+
await git.fetch('origin', options.commit, gitOptions);
237+
log(`Checkout ${url}`);
238+
await git.checkout('FETCH_HEAD');
239+
log(`Cloned: ${url} with options: ${gitOptions.join(' ')}`);
240+
} catch (e) {
241+
error(e);
242+
return false;
243+
}
244+
return true;
245+
}

integration-tests/src/types.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export interface Logger {
2+
output?: (message: string, ...optionalParams: unknown[]) => void;
23
// eslint-disable-next-line @typescript-eslint/no-explicit-any
34
log: (message?: any, ...optionalParams: any[]) => void;
45
// eslint-disable-next-line @typescript-eslint/no-explicit-any

pnpm-lock.yaml

+31-22
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)