Skip to content

Commit

Permalink
Download replay file instead of RepoResult.zip file (#158)
Browse files Browse the repository at this point in the history
* Download replay file instead of RepoResult.zip file

* Fixed package-lock

---------

Co-authored-by: Armando Aguirre Sepulveda <araguir@microsoft.com>
  • Loading branch information
armanio123 and Armando Aguirre Sepulveda committed May 16, 2024
1 parent cccbc2f commit b8f135a
Show file tree
Hide file tree
Showing 12 changed files with 435 additions and 40 deletions.
4 changes: 2 additions & 2 deletions azure-pipelines-gitTests-template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ jobs:
npm run build
npm install -g pnpm
mkdir 'RepoResults$(System.JobPositionInPhase)'
node dist/checkGithubRepos ${{ parameters.ENTRYPOINT }} ${{ parameters.OLD_VERSION }} ${{ parameters.NEW_VERSION }} '$(Pipeline.Workspace)/RepoList/repos.json' $(System.TotalJobsInPhase) $(System.JobPositionInPhase) 'RepoResults$(System.JobPositionInPhase)' ${{ parameters.DIAGNOSTIC_OUTPUT }} ${{ parameters.PRNG_SEED }}
node dist/checkGithubRepos ${{ parameters.ENTRYPOINT }} ${{ parameters.OLD_VERSION }} ${{ parameters.NEW_VERSION }} '$(Pipeline.Workspace)/RepoList/repos.json' $(System.TotalJobsInPhase) $(System.JobPositionInPhase) 'RepoResults$(System.JobPositionInPhase)' ${{ parameters.DIAGNOSTIC_OUTPUT }} ${{ parameters.PRNG_SEED }} $(Build.BuildId) '$(System.TeamFoundationCollectionUri)' '$(System.TeamProject)'
displayName: 'Run TypeScript on repos'
continueOnError: true
env:
Expand All @@ -91,7 +91,7 @@ jobs:
- script: |
npm ci
npm run build
node dist/postGithubIssue ${{ parameters.ENTRYPOINT }} ${{ parameters.LANGUAGE }} ${{ parameters.REPO_COUNT }} ${{ parameters.REPO_START_INDEX }} '$(Pipeline.Workspace)' '$(System.TeamFoundationCollectionUri)$(System.TeamProject)/_build/results?buildId=$(Build.BuildId)' '$(System.TeamFoundationCollectionUri)$(System.TeamProject)/_build/results?buildId=$(Build.BuildId)&view=artifacts&type=publishedArtifacts' ${{ parameters.POST_RESULT }} '$(System.TeamFoundationCollectionUri)$(System.TeamProject)/_apis/build/builds/$(Build.BuildId)/artifacts'
node dist/postGithubIssue ${{ parameters.ENTRYPOINT }} ${{ parameters.LANGUAGE }} ${{ parameters.REPO_COUNT }} ${{ parameters.REPO_START_INDEX }} '$(Pipeline.Workspace)' '$(System.TeamFoundationCollectionUri)$(System.TeamProject)/_build/results?buildId=$(Build.BuildId)' '$(System.TeamFoundationCollectionUri)$(System.TeamProject)/_build/results?buildId=$(Build.BuildId)&view=artifacts&type=publishedArtifacts' ${{ parameters.POST_RESULT }}
displayName: 'Create issue from new errors'
env:
GITHUB_PAT: $(GITHUB_PAT)
4 changes: 2 additions & 2 deletions azure-pipelines-userTests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ jobs:
npm run build
npm install -g pnpm
mkdir 'RepoResults$(System.JobPositionInPhase)'
node dist/checkUserTestRepos ${{ parameters.ENTRYPOINT }} ${{ parameters.OLD_TS_REPO_URL }} ${{ parameters.OLD_HEAD_REF }} ${{ parameters.SOURCE_ISSUE }} ${{ parameters.TOP_REPOS }} '$(Pipeline.Workspace)/RepoList/repos.json' $(System.TotalJobsInPhase) $(System.JobPositionInPhase) 'RepoResults$(System.JobPositionInPhase)' ${{ parameters.DIAGNOSTIC_OUTPUT }} ${{ parameters.PRNG_SEED }}
node dist/checkUserTestRepos ${{ parameters.ENTRYPOINT }} ${{ parameters.OLD_TS_REPO_URL }} ${{ parameters.OLD_HEAD_REF }} ${{ parameters.SOURCE_ISSUE }} ${{ parameters.TOP_REPOS }} '$(Pipeline.Workspace)/RepoList/repos.json' $(System.TotalJobsInPhase) $(System.JobPositionInPhase) 'RepoResults$(System.JobPositionInPhase)' ${{ parameters.DIAGNOSTIC_OUTPUT }} ${{ parameters.PRNG_SEED }} $(Build.BuildId) '$(System.TeamFoundationCollectionUri)' '$(System.TeamProject)'
displayName: 'Run user tests'
env:
GITHUB_PAT: $(GITHUB_PAT)
Expand All @@ -123,7 +123,7 @@ jobs:
- script: |
npm ci
npm run build
node dist/postGithubComments ${{ parameters.REQUESTING_USER }} ${{ parameters.SOURCE_ISSUE }} ${{ parameters.STATUS_COMMENT }} ${{ parameters.DISTINCT_ID }} ${{ parameters.TOP_REPOS }} '$(Pipeline.Workspace)' '$(System.TeamFoundationCollectionUri)$(System.TeamProject)/_build/results?buildId=$(Build.BuildId)&view=artifacts&type=publishedArtifacts' ${{ parameters.POST_RESULT }} ${{ parameters.REPO_COUNT }} '$(System.TeamFoundationCollectionUri)$(System.TeamProject)/_apis/build/builds/$(Build.BuildId)/artifacts'
node dist/postGithubComments ${{ parameters.REQUESTING_USER }} ${{ parameters.SOURCE_ISSUE }} ${{ parameters.STATUS_COMMENT }} ${{ parameters.DISTINCT_ID }} ${{ parameters.TOP_REPOS }} '$(Pipeline.Workspace)' '$(System.TeamFoundationCollectionUri)$(System.TeamProject)/_build/results?buildId=$(Build.BuildId)&view=artifacts&type=publishedArtifacts' ${{ parameters.POST_RESULT }} ${{ parameters.REPO_COUNT }}
displayName: 'Update PR comment with new errors'
env:
GITHUB_PAT: $(GITHUB_PAT)
348 changes: 343 additions & 5 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"@typescript/github-link": "^0.2.2",
"@typescript/server-harness": "^0.3.5",
"@typescript/server-replay": "^0.2.12",
"azure-devops-node-api": "^13.0.0",
"glob": "^10.3.10",
"js-yaml": "^4.1.0",
"json5": "^2.2.3",
Expand Down
9 changes: 6 additions & 3 deletions src/checkGithubRepos.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import { mainAsync, reportError, TsEntrypoint } from "./main";

const { argv } = process;

if (argv.length !== 11) {
console.error(`Usage: ${path.basename(argv[0])} ${path.basename(argv[1])} <ts_entrypoint> <old_ts_npm_version> <new_ts_npm_version> <repo_list_path> <worker_count> <worker_number> <result_dir_name> <diagnostic_output> <prng_seed>`);
if (argv.length !== 14) {
console.error(`Usage: ${path.basename(argv[0])} ${path.basename(argv[1])} <ts_entrypoint> <old_ts_npm_version> <new_ts_npm_version> <repo_list_path> <worker_count> <worker_number> <result_dir_name> <diagnostic_output> <prng_seed> <buildId> <teamFoundationCollectionUri> <teamProject>`);
process.exit(-1);
}

const [,, entrypoint, oldTsNpmVersion, newTsNpmVersion, repoListPath, workerCount, workerNumber, resultDirName, diagnosticOutput, prngSeed] = argv;
const [, , entrypoint, oldTsNpmVersion, newTsNpmVersion, repoListPath, workerCount, workerNumber, resultDirName, diagnosticOutput, prngSeed, buildId, teamFoundationCollectionUri, teamProject] = argv;

mainAsync({
testType: "github",
Expand All @@ -23,6 +23,9 @@ mainAsync({
newTsNpmVersion,
resultDirName,
prngSeed: prngSeed.toLowerCase() === "n/a" ? undefined : prngSeed,
buildId: +buildId,
teamFoundationCollectionUri,
teamProject,
}).catch(err => {
reportError(err, "Unhandled exception");
process.exit(1);
Expand Down
9 changes: 6 additions & 3 deletions src/checkUserTestRepos.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import { mainAsync, reportError, TsEntrypoint } from "./main";

const { argv } = process;

if (argv.length !== 13) {
console.error(`Usage: ${path.basename(argv[0])} ${path.basename(argv[1])} <ts_entrypoint> <old_ts_repo_url> <old_head_ref> <pr_number> <is_top_repos> <repo_list_path> <worker_count> <worker_number> <result_dir_name> <diagnostic_output> <prng_seed>`);
if (argv.length !== 16) {
console.error(`Usage: ${path.basename(argv[0])} ${path.basename(argv[1])} <ts_entrypoint> <old_ts_repo_url> <old_head_ref> <pr_number> <is_top_repos> <repo_list_path> <worker_count> <worker_number> <result_dir_name> <diagnostic_output> <prng_seed> <buildId> <teamFoundationCollectionUri> <teamProject>`);
process.exit(-1);
}

const [,, entrypoint, oldTsRepoUrl, oldHeadRef, prNumber, buildWithNewWhenOldFails, repoListPath, workerCount, workerNumber, resultDirName, diagnosticOutput, prngSeed] = argv;
const [,, entrypoint, oldTsRepoUrl, oldHeadRef, prNumber, buildWithNewWhenOldFails, repoListPath, workerCount, workerNumber, resultDirName, diagnosticOutput, prngSeed, buildId, teamFoundationCollectionUri, teamProject] = argv;

mainAsync({
testType: "user",
Expand All @@ -24,6 +24,9 @@ mainAsync({
resultDirName,
diagnosticOutput: diagnosticOutput.toLowerCase() === "true",
prngSeed: prngSeed.toLowerCase() === "n/a" ? undefined : prngSeed,
buildId: +buildId,
teamFoundationCollectionUri,
teamProject,
}).catch(err => {
reportError(err, "Unhandled exception");
process.exit(1);
Expand Down
28 changes: 20 additions & 8 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ import mdEscape = require("markdown-escape");
import randomSeed = require("random-seed");
import { getErrorMessageFromStack, getHash, getHashForStack } from "./utils/hashStackTrace";
import { createCopyingOverlayFS, createTempOverlayFS, OverlayBaseFS } from "./utils/overlayFS";
import { getReplayScriptDownloadUrl } from "./utils/devOpsUtils";

interface Params {
export interface Params {
/**
* Store test repos on a tmpfs.
* Basically, the only reason not to do this would be lack of `sudo`.
Expand Down Expand Up @@ -54,6 +55,18 @@ interface Params {
* Pass undefined to have a seed generated.
*/
prngSeed: string | undefined;
/**
* Build number to reference when downloading files.
*/
buildId: number;
/**
* URL of the DevOps organization.
*/
teamFoundationCollectionUri: string;
/**
* Name of the project that contains the build.
*/
teamProject: string;
}
export interface GitParams extends Params {
testType: "github";
Expand Down Expand Up @@ -96,7 +109,7 @@ interface TSServerResult {
installCommands: ip.InstallCommand[];
}

interface Summary {
export interface Summary {
tsServerResult: TSServerResult;
repo: git.Repo;
oldTsEntrypointPath: string;
Expand Down Expand Up @@ -429,7 +442,7 @@ ${oldServerError}
return text;
}

async function createNewErrorSummaryAsync(summaries: Summary[]): Promise<string> {
async function createNewErrorSummaryAsync(summaries: Summary[], params: Params): Promise<string> {
let text = `<h2>${getErrorMessage(summaries[0].tsServerResult.newSpawnResult.stdout)}</h2>
\`\`\`
Expand Down Expand Up @@ -483,9 +496,9 @@ ${summary.replayScript}
text += `${command.tool} ${workingDirFlag} "${command.directory}" ${command.arguments.join(" ")}\n`;
}

text += `downloadUrl=$(curl -s "${getArtifactsApiUrlPlaceholder}?artifactName=${summary.resultDirName}&api-version=7.0" | jq -r ".resource.downloadUrl")
wget -O ${summary.resultDirName}.zip "$downloadUrl"
unzip -p ${summary.resultDirName}.zip ${summary.resultDirName}/${summary.replayScriptName} > ${summary.replayScriptName}
const replayScriptUrl = await getReplayScriptDownloadUrl(summary, params);

text += `wget -O ${summary.replayScriptName} "${replayScriptUrl!.toString()}"
npm install --no-save @typescript/server-replay
\`\`\`
Expand Down Expand Up @@ -710,7 +723,6 @@ export const resultFileNameSuffix = "results.txt";
export const replayScriptFileNameSuffix = "replay.txt";
export const rawErrorFileNameSuffix = "rawError.txt";
export const artifactFolderUrlPlaceholder = "PLACEHOLDER_ARTIFACT_FOLDER";
export const getArtifactsApiUrlPlaceholder = "PLACEHOLDER_GETARTIFACTS_API";

export type StatusCounts = {
[P in RepoStatus]?: number
Expand Down Expand Up @@ -846,7 +858,7 @@ export async function mainAsync(params: GitParams | UserParams): Promise<void> {
}

for (let [key, value] of groupedNewErrors) {
const summary = await createNewErrorSummaryAsync(value);
const summary = await createNewErrorSummaryAsync(value, params);
const resultFileName = `${key}.${resultFileNameSuffix}`;

await fs.promises.writeFile(path.join(resultDirPath, resultFileName), summary, { encoding: "utf-8" });
Expand Down
11 changes: 5 additions & 6 deletions src/postGithubComments.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import fs = require("fs");
import path = require("path");
import { artifactFolderUrlPlaceholder, getArtifactsApiUrlPlaceholder, Metadata, metadataFileName, RepoStatus, resultFileNameSuffix } from "./main";
import { artifactFolderUrlPlaceholder, Metadata, metadataFileName, RepoStatus, resultFileNameSuffix } from "./main";
import git = require("./utils/gitUtils");
import pu = require("./utils/packageUtils");

const { argv } = process;

if (argv.length !== 12) {
console.error(`Usage: ${path.basename(argv[0])} ${path.basename(argv[1])} <user_to_tag> <pr_number> <comment_number> <distinct_id> <is_top_repos_run> <result_dir_path> <artifacts_uri> <post_result> <repo_count> <get_artifacts_api>`);
if (argv.length !== 11) {
console.error(`Usage: ${path.basename(argv[0])} ${path.basename(argv[1])} <user_to_tag> <pr_number> <comment_number> <distinct_id> <is_top_repos_run> <result_dir_path> <artifacts_uri> <post_result> <repo_count>`);
process.exit(-1);
}

const [, , userToTag, prNumber, commentNumber, distinctId, isTop, resultDirPath, artifactsUri, post, repoCount, getArtifactsApi] = argv;
const [, , userToTag, prNumber, commentNumber, distinctId, isTop, resultDirPath, artifactsUri, post, repoCount] = argv;
const isTopReposRun = isTop.toLowerCase() === "true";
const postResult = post.toLowerCase() === "true";

Expand Down Expand Up @@ -72,8 +72,7 @@ const hasOldErrors = pu.glob(resultDirPath, `**/!*.${resultFileNameSuffix}`).len
const resultPaths = pu.glob(resultDirPath, `**/*.${resultFileNameSuffix}`).sort((a, b) => path.basename(a).localeCompare(path.basename(b)));
const outputs = resultPaths.map(p =>
fs.readFileSync(p, { encoding: "utf-8" })
.replaceAll(artifactFolderUrlPlaceholder, artifactsUri)
.replaceAll(getArtifactsApiUrlPlaceholder, getArtifactsApi));
.replaceAll(artifactFolderUrlPlaceholder, artifactsUri));

const suiteDescription = isTopReposRun ? `top ${repoCount} repos` : "user tests";
let header = `@${userToTag} Here are the results of running the ${suiteDescription} comparing \`${oldTscResolvedVersion}\` and \`${newTscResolvedVersion}\`:
Expand Down
11 changes: 5 additions & 6 deletions src/postGithubIssue.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import fs = require("fs");
import path = require("path");
import { artifactFolderUrlPlaceholder, getArtifactsApiUrlPlaceholder, Metadata, metadataFileName, RepoStatus, resultFileNameSuffix, StatusCounts, TsEntrypoint } from "./main";
import { artifactFolderUrlPlaceholder, Metadata, metadataFileName, RepoStatus, resultFileNameSuffix, StatusCounts, TsEntrypoint } from "./main";
import git = require("./utils/gitUtils");
import pu = require("./utils/packageUtils");

const { argv } = process;

if (argv.length !== 11) {
console.error(`Usage: ${path.basename(argv[0])} ${path.basename(argv[1])} <ts_entrypoint> <language> <repo_count> <repo_start_index> <result_dir_path> <log_uri> <artifacts_uri> <post_result> <get_artifacts_api>`);
if (argv.length !== 10) {
console.error(`Usage: ${path.basename(argv[0])} ${path.basename(argv[1])} <ts_entrypoint> <language> <repo_count> <repo_start_index> <result_dir_path> <log_uri> <artifacts_uri> <post_result>`);
process.exit(-1);
}

const [, , ep, language, repoCount, repoStartIndex, resultDirPath, logUri, artifactsUri, post, getArtifactsApi] = argv;
const [, , ep, language, repoCount, repoStartIndex, resultDirPath, logUri, artifactsUri, post] = argv;
const postResult = post.toLowerCase() === "true";
const entrypoint = ep as TsEntrypoint;

Expand Down Expand Up @@ -74,8 +74,7 @@ ${Object.keys(statusCounts).sort().map(status => `| ${status} | ${statusCounts[s
const resultPaths = pu.glob(resultDirPath, `**/*.${resultFileNameSuffix}`).sort((a, b) => path.basename(a).localeCompare(path.basename(b)));
const outputs = resultPaths.map(p =>
fs.readFileSync(p, { encoding: "utf-8" })
.replaceAll(artifactFolderUrlPlaceholder, artifactsUri)
.replaceAll(getArtifactsApiUrlPlaceholder, getArtifactsApi));
.replaceAll(artifactFolderUrlPlaceholder, artifactsUri));

for (let i = 0; i < outputs.length; i++) {
const resultPath = resultPaths[i];
Expand Down
31 changes: 31 additions & 0 deletions src/utils/devOpsUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import ado = require("azure-devops-node-api");
import { Params, Summary } from "../main";

interface ArtifactContent {
items: [{
path: string;
blob: {
id: string;
};
}];
};

export async function getReplayScriptDownloadUrl(summary: Summary, params: Params) {
const cli = new ado.WebApi(`${params.teamFoundationCollectionUri}defaultcollection`, ado.getHandlerFromToken("")); // Empty token, anon auth
const build = await cli.getBuildApi();
const artifact = await build.getArtifact(params.teamProject, params.buildId, summary.resultDirName);

if (artifact.resource?.url) {
const repoResultUrl = new URL(artifact.resource.url);
repoResultUrl.search = `artifactName=${summary.resultDirName}&fileId=${artifact.resource.data}&fileName=${summary.resultDirName}`;

const artifactContent = await (await fetch(repoResultUrl)).json() as ArtifactContent;

const item = artifactContent.items.find(x => x.path.endsWith(summary.replayScriptName));

const replayScriptUrl = new URL(artifact.resource.url);
replayScriptUrl.search = `artifactName=${summary.resultDirName}&fileId=${item!.blob.id}&fileName=${summary.replayScriptName}`;

return replayScriptUrl;
}
}
4 changes: 1 addition & 3 deletions test/__snapshots__/main.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,7 @@ git -C "./MockRepoName" reset --hard 57b462387e88aa7e363af0daf867a5dc1e83a935
npm --prefix "./dirA" install --prefer-offline --no-audit --no-progress --legacy-peer-deps --ignore-scripts -q
npm --prefix "./dirB/dirC" install --prefer-offline --no-audit --no-progress --legacy-peer-deps --ignore-scripts -q
npm --prefix "./dirD/dirE/dirF" install --prefer-offline --no-audit --no-progress --legacy-peer-deps --ignore-scripts -q
downloadUrl=$(curl -s "PLACEHOLDER_GETARTIFACTS_API?artifactName=RepoResults123&api-version=7.0" | jq -r ".resource.downloadUrl")
wget -O RepoResults123.zip "$downloadUrl"
unzip -p RepoResults123.zip RepoResults123/MockRepoOwner.MockRepoName.replay.txt > MockRepoOwner.MockRepoName.replay.txt
wget -O MockRepoOwner.MockRepoName.replay.txt "http://anazuredevops.buildpage.com_teamproject_atypescriptproject_buildid_1/?artifactName=RepoResults123&fileId=999&fileName=MockRepoOwner.MockRepoName.replay.txt"
npm install --no-save @typescript/server-replay
\`\`\`
Expand Down
15 changes: 13 additions & 2 deletions test/main.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getTscRepoResult, downloadTsRepoAsync, mainAsync } from '../src/main'
import { getTscRepoResult, downloadTsRepoAsync, mainAsync, Params, Summary } from '../src/main'
import { execSync } from "child_process"
import path = require("path")
import { createCopyingOverlayFS } from '../src/utils/overlayFS'
Expand Down Expand Up @@ -109,6 +109,14 @@ jest.mock('../src/utils/installPackages', () => {
}
}
});
jest.mock('../src/utils/devOpsUtils', () => ({
getReplayScriptDownloadUrl: async (summary: Summary, params: Params) => {
var url = new URL(`${params.teamFoundationCollectionUri}_teamProject_${params.teamProject}_buildId_${params.buildId}`);
url.search = `artifactName=${summary.resultDirName}&fileId=999&fileName=${summary.replayScriptName}`;

return url;
}
}));

describe("main", () => {
jest.setTimeout(10 * 60 * 1000);
Expand Down Expand Up @@ -159,6 +167,9 @@ describe("main", () => {
newTsNpmVersion: 'next',
resultDirName: 'RepoResults123',
prngSeed: 'testSeed',
buildId: 1,
teamFoundationCollectionUri: "http://anAzureDevOps.buildPage.com",
teamProject: "ATypeScriptProject"
});

// Remove all references to the base path so that snapshot pass successfully.
Expand All @@ -168,4 +179,4 @@ describe("main", () => {

expect(mockedFs.promises.writeFile).toMatchSnapshot();
});
})
});

0 comments on commit b8f135a

Please sign in to comment.