Modify `sourcecred load` to save timeline cred
Test plan: Observe changes to the snapshot for example-github-load. `yarn test --full` passes.
This commit is contained in:
parent
aa7158dd95
commit
a46500d704
File diff suppressed because one or more lines are too long
|
@ -3,6 +3,7 @@
|
|||
|
||||
import mkdirp from "mkdirp";
|
||||
import path from "path";
|
||||
import chalk from "chalk";
|
||||
|
||||
import fs from "fs-extra";
|
||||
import stringify from "json-stable-stringify";
|
||||
|
@ -11,13 +12,17 @@ import {repoIdToString, stringToRepoId, type RepoId} from "../core/repoId";
|
|||
import dedent from "../util/dedent";
|
||||
import type {Command} from "./command";
|
||||
import * as Common from "./common";
|
||||
import {Graph} from "../core/graph";
|
||||
import {loadGraph, type LoadGraphResult} from "../analysis/loadGraph";
|
||||
import {type IBackendAdapterLoader} from "../analysis/analysisAdapter";
|
||||
import {TimelineCred} from "../analysis/timeline/timelineCred";
|
||||
import {defaultWeights} from "../analysis/weights";
|
||||
|
||||
import execDependencyGraph from "../tools/execDependencyGraph";
|
||||
import {loadGithubData} from "../plugins/github/loadGithubData";
|
||||
import {loadGitData} from "../plugins/git/loadGitData";
|
||||
import {defaultAdapterLoaders} from "./pagerank";
|
||||
import {DEFAULT_CRED_CONFIG} from "../plugins/defaultCredConfig";
|
||||
|
||||
function usage(print: (string) => void): void {
|
||||
print(
|
||||
|
@ -170,7 +175,9 @@ export function makeLoadCommand(
|
|||
export type SaveGraph = (
|
||||
$ReadOnlyArray<IBackendAdapterLoader>,
|
||||
RepoId
|
||||
) => Promise<void>;
|
||||
) => Promise<Graph>;
|
||||
|
||||
export type SaveCred = (Graph, RepoId) => Promise<void>;
|
||||
|
||||
/**
|
||||
* A wrapper around the default plugin loader.
|
||||
|
@ -179,7 +186,10 @@ export type SaveGraph = (
|
|||
* (saveGraph depends on the directory state that's generated by running
|
||||
* load.)
|
||||
*/
|
||||
export const makeLoadDefaultPlugins = (saveGraph: SaveGraph) => {
|
||||
export const makeLoadDefaultPlugins = (
|
||||
saveGraph: SaveGraph,
|
||||
saveCred: SaveCred
|
||||
) => {
|
||||
return async (options: LoadOptions) => {
|
||||
const sourcecredCommand = (args) => [
|
||||
process.execPath,
|
||||
|
@ -209,11 +219,39 @@ export const makeLoadDefaultPlugins = (saveGraph: SaveGraph) => {
|
|||
throw new Error("Load tasks failed.");
|
||||
}
|
||||
addToRepoIdRegistry(options.output);
|
||||
await saveGraph(defaultAdapterLoaders(), options.output);
|
||||
const graph = await saveGraph(defaultAdapterLoaders(), options.output);
|
||||
await saveCred(graph, options.output);
|
||||
return;
|
||||
};
|
||||
};
|
||||
|
||||
export const saveCred = async (graph: Graph, repoId: RepoId) => {
|
||||
const id = "compute-cred";
|
||||
console.time(id);
|
||||
// Imitate the task labels from execDependencyGraph for visual consistency
|
||||
console.log(chalk.bgBlue.bold.white(" GO ") + ` ${id}`);
|
||||
const cred = await TimelineCred.compute(
|
||||
graph,
|
||||
{
|
||||
alpha: 0.05,
|
||||
intervalDecay: 0.5,
|
||||
weights: defaultWeights(),
|
||||
},
|
||||
DEFAULT_CRED_CONFIG
|
||||
);
|
||||
const credFile = path.join(
|
||||
Common.sourcecredDirectory(),
|
||||
"data",
|
||||
repoIdToString(repoId),
|
||||
"cred.json"
|
||||
);
|
||||
const credJSON = cred.toJSON();
|
||||
await fs.writeFile(credFile, JSON.stringify(credJSON));
|
||||
const badge = chalk.bgGreen.bold.white(" DONE ");
|
||||
console.log(`${badge} ${id}`);
|
||||
console.timeEnd(id);
|
||||
};
|
||||
|
||||
export const loadIndividualPlugin = async (
|
||||
plugin: Common.PluginName,
|
||||
options: LoadOptions
|
||||
|
@ -266,7 +304,7 @@ function addToRepoIdRegistry(repoId) {
|
|||
export async function saveGraph(
|
||||
adapterLoaders: $ReadOnlyArray<IBackendAdapterLoader>,
|
||||
repoId: RepoId
|
||||
) {
|
||||
): Promise<Graph> {
|
||||
const loadGraphResult: LoadGraphResult = await loadGraph(
|
||||
Common.sourcecredDirectory(),
|
||||
adapterLoaders,
|
||||
|
@ -284,6 +322,7 @@ export async function saveGraph(
|
|||
);
|
||||
const graphJSON = graph.toJSON();
|
||||
await fs.writeFile(graphFile, stringify(graphJSON));
|
||||
return graph;
|
||||
}
|
||||
|
||||
export const help: Command = async (args, std) => {
|
||||
|
@ -296,7 +335,7 @@ export const help: Command = async (args, std) => {
|
|||
}
|
||||
};
|
||||
|
||||
const loadDefaultPlugins = makeLoadDefaultPlugins(saveGraph);
|
||||
const loadDefaultPlugins = makeLoadDefaultPlugins(saveGraph, saveCred);
|
||||
const load = makeLoadCommand(loadIndividualPlugin, loadDefaultPlugins);
|
||||
|
||||
export default load;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
import path from "path";
|
||||
import tmp from "tmp";
|
||||
|
||||
import {Graph} from "../core/graph";
|
||||
import {run} from "./testUtil";
|
||||
import {defaultPlugins} from "./common";
|
||||
import {
|
||||
|
@ -467,7 +468,7 @@ describe("cli/load", () => {
|
|||
const fooCombined = makeRepoId("foo", "combined");
|
||||
const fooBar = makeRepoId("foo", "bar");
|
||||
const fooBaz = makeRepoId("foo", "baz");
|
||||
const loadDefaultPlugins = makeLoadDefaultPlugins(jest.fn());
|
||||
const loadDefaultPlugins = makeLoadDefaultPlugins(jest.fn(), jest.fn());
|
||||
|
||||
it("creates a load sub-task per plugin", async () => {
|
||||
execDependencyGraph.mockResolvedValue({success: true});
|
||||
|
@ -518,7 +519,7 @@ describe("cli/load", () => {
|
|||
|
||||
it("calls saveGraph on success", async () => {
|
||||
const saveGraph = jest.fn();
|
||||
const loadDefaultPlugins = makeLoadDefaultPlugins(saveGraph);
|
||||
const loadDefaultPlugins = makeLoadDefaultPlugins(saveGraph, jest.fn());
|
||||
execDependencyGraph.mockResolvedValue({success: true});
|
||||
await loadDefaultPlugins({
|
||||
output: fooCombined,
|
||||
|
@ -531,6 +532,21 @@ describe("cli/load", () => {
|
|||
);
|
||||
});
|
||||
|
||||
it("calls saveCred with the output of saveGraph", async () => {
|
||||
// $ExpectFlowError
|
||||
const graph: Graph = "pretend_graph";
|
||||
const saveGraph = jest.fn().mockResolvedValue(graph);
|
||||
const saveCred = jest.fn();
|
||||
const loadDefaultPlugins = makeLoadDefaultPlugins(saveGraph, saveCred);
|
||||
execDependencyGraph.mockResolvedValue({success: true});
|
||||
await loadDefaultPlugins({
|
||||
output: fooCombined,
|
||||
repoIds: [fooBar, fooBaz],
|
||||
});
|
||||
expect(saveCred).toHaveBeenCalledTimes(1);
|
||||
expect(saveCred).toHaveBeenCalledWith(graph, fooCombined);
|
||||
});
|
||||
|
||||
it("throws an load error on first execDependencyGraph failure", async () => {
|
||||
execDependencyGraph.mockResolvedValueOnce({success: false});
|
||||
const result = loadDefaultPlugins({
|
||||
|
|
Loading…
Reference in New Issue