diff --git a/src/api/load.js b/src/api/load.js index 81847e1..2f42cbb 100644 --- a/src/api/load.js +++ b/src/api/load.js @@ -17,6 +17,7 @@ export type LoadOptions = {| +plugins: $ReadOnlyArray, +sourcecredDirectory: string, +githubToken: ?GithubToken, + +initiativesDirectory: ?string, |}; /** @@ -32,12 +33,14 @@ export async function load( project, params, weightsOverrides, + initiativesDirectory, } = options; const data = new DataDirectory(sourcecredDirectory); const context = new LoadContext({ cache: (data: CacheProvider), githubToken, reporter, + initiativesDirectory, }); const result = await context.load(project, { params: params || {}, diff --git a/src/backend/loadContext.js b/src/backend/loadContext.js index 59bb202..9ed461d 100644 --- a/src/backend/loadContext.js +++ b/src/backend/loadContext.js @@ -28,6 +28,7 @@ export type LoadContextOptions = {| +cache: CacheProvider, +reporter: TaskReporter, +githubToken: ?GithubToken, + +initiativesDirectory: ?string, |}; type OptionalLoadArguments = {| diff --git a/src/backend/loadContext.test.js b/src/backend/loadContext.test.js index 9835265..45f707b 100644 --- a/src/backend/loadContext.test.js +++ b/src/backend/loadContext.test.js @@ -13,6 +13,7 @@ const fakes = { contractedGraph: ({fake: "contractedGraph"}: any), weightedGraph: ({fake: "weightedGraph"}: any), timelineCred: ({fake: "timelineCred"}: any), + initiativesDirectory: ({fake: "initiativesDirectory"}: any), }; const mockCacheProvider = (): CacheProvider => ({ @@ -66,6 +67,7 @@ describe("src/backend/loadContext", () => { const githubToken = validateToken("0".repeat(40)); const project = createProject({id: "testing-project"}); const params = {alpha: 0.123}; + const initiativesDirectory = fakes.initiativesDirectory; describe("constructor", () => { /** @@ -80,7 +82,12 @@ describe("src/backend/loadContext", () => { const reporter = new TestTaskReporter(); // When - const loadContext = new LoadContext({cache, githubToken, reporter}); + const loadContext = new LoadContext({ + cache, + githubToken, + reporter, + initiativesDirectory, + }); // Then expect(loadContext).toMatchObject({ @@ -105,7 +112,12 @@ describe("src/backend/loadContext", () => { const cache = mockCacheProvider(); const reporter = new TestTaskReporter(); const weightsOverrides = Weights.empty(); - const loadContext = new LoadContext({cache, githubToken, reporter}); + const loadContext = new LoadContext({ + cache, + githubToken, + reporter, + initiativesDirectory, + }); const spies = mockProxyMethods(loadContext, project, cache); // When @@ -114,6 +126,7 @@ describe("src/backend/loadContext", () => { // Then const cachedProject = {project, cache}; const expectedEnv = { + initiativesDirectory, githubToken, reporter, cache, @@ -155,7 +168,12 @@ describe("src/backend/loadContext", () => { // Given const cache = mockCacheProvider(); const reporter = new TestTaskReporter(); - const loadContext = new LoadContext({cache, githubToken, reporter}); + const loadContext = new LoadContext({ + cache, + githubToken, + reporter, + initiativesDirectory, + }); const spies = mockProxyMethods(loadContext, project, cache); // When @@ -163,6 +181,7 @@ describe("src/backend/loadContext", () => { // Then const expectedEnv = { + initiativesDirectory, githubToken, reporter, cache, @@ -185,7 +204,12 @@ describe("src/backend/loadContext", () => { const cache = mockCacheProvider(); const reporter = new TestTaskReporter(); const weightsOverrides = Weights.empty(); - const loadContext = new LoadContext({cache, githubToken, reporter}); + const loadContext = new LoadContext({ + cache, + githubToken, + reporter, + initiativesDirectory, + }); mockProxyMethods(loadContext, project, cache); // When diff --git a/src/cli/common.js b/src/cli/common.js index 67cae17..43a4da3 100644 --- a/src/cli/common.js +++ b/src/cli/common.js @@ -21,6 +21,10 @@ export function sourcecredDirectory(): string { return env != null ? env : defaultSourcecredDirectory(); } +export function initiativesDirectory(): string | null { + return process.env.SOURCECRED_INITIATIVES_DIRECTORY || null; +} + export function githubToken(): ?GithubToken { const envToken = process.env.SOURCECRED_GITHUB_TOKEN; if (envToken == null || !envToken.length) { diff --git a/src/cli/common.test.js b/src/cli/common.test.js index 856bbd3..584425c 100644 --- a/src/cli/common.test.js +++ b/src/cli/common.test.js @@ -13,10 +13,13 @@ import { sourcecredDirectory, githubToken, loadWeights, + initiativesDirectory, } from "./common"; describe("cli/common", () => { const exampleGithubToken = validateToken("0".repeat(40)); + const exampleInitiativesDirectory = path.join(__dirname, "initiatives"); + beforeEach(() => { jest .spyOn(require("os"), "tmpdir") @@ -62,6 +65,17 @@ describe("cli/common", () => { }); }); + describe("initiativesDirectory", () => { + it("uses the environment variable when available", () => { + process.env.SOURCECRED_INITIATIVES_DIRECTORY = exampleInitiativesDirectory; + expect(initiativesDirectory()).toEqual(exampleInitiativesDirectory); + }); + it("returns `null` if the environment variable is not set", () => { + delete process.env.SOURCECRED_INITIATIVES_DIRECTORY; + expect(initiativesDirectory()).toBe(null); + }); + }); + describe("loadWeights", () => { function tmpWithContents(contents: mixed) { const name = tmp.tmpNameSync(); diff --git a/src/cli/discourse.js b/src/cli/discourse.js index 11be5a1..801b4f7 100644 --- a/src/cli/discourse.js +++ b/src/cli/discourse.js @@ -102,6 +102,7 @@ const command: Command = async (args, std) => { plugins, sourcecredDirectory: Common.sourcecredDirectory(), githubToken: null, + initiativesDirectory: null, }, taskReporter ); diff --git a/src/cli/load.js b/src/cli/load.js index bf920d2..4586312 100644 --- a/src/cli/load.js +++ b/src/cli/load.js @@ -57,11 +57,17 @@ function usage(print: (string) => void): void { public repositories, no special permissions are required. For private repositories, the 'repo' scope is required. + SOURCECRED_INITIATIVES_DIRECTORY + Local path to a directory containing json files with + initiative declarations. Required when using the Initiatives + plugin; ignored otherwise. + SOURCECRED_DIRECTORY Directory owned by SourceCred, in which data, caches, registries, etc. are stored. Optional: defaults to a directory 'sourcecred' under your OS's temporary directory; namely: + ${Common.defaultSourcecredDirectory()} `.trimRight() ); @@ -112,6 +118,7 @@ const loadCommand: Command = async (args, std) => { weights = await loadWeightOverrides(weightsPath); } + const initiativesDirectory = Common.initiativesDirectory(); const githubToken = Common.githubToken(); if (githubToken == null) { return die(std, "SOURCECRED_GITHUB_TOKEN not set"); @@ -142,6 +149,7 @@ const loadCommand: Command = async (args, std) => { plugins, sourcecredDirectory: Common.sourcecredDirectory(), githubToken, + initiativesDirectory, }; }); // Deliberately load in serial because GitHub requests that their API not diff --git a/src/cli/load.test.js b/src/cli/load.test.js index 9dd8c76..4748020 100644 --- a/src/cli/load.test.js +++ b/src/cli/load.test.js @@ -34,6 +34,7 @@ describe("cli/load", () => { const dirname = tmp.dirSync().name; process.env.SOURCECRED_DIRECTORY = dirname; process.env.SOURCECRED_GITHUB_TOKEN = exampleGithubToken; + process.env.SOURCECRED_INITIATIVES_DIRECTORY = tmp.dirSync().name; return dirname; } @@ -81,6 +82,7 @@ describe("cli/load", () => { plugins: [githubDeclaration], sourcecredDirectory: Common.sourcecredDirectory(), githubToken: exampleGithubToken, + initiativesDirectory: Common.initiativesDirectory(), }; expect(await invocation).toEqual({ exitCode: 0, @@ -105,6 +107,7 @@ describe("cli/load", () => { plugins: [githubDeclaration], sourcecredDirectory: Common.sourcecredDirectory(), githubToken: exampleGithubToken, + initiativesDirectory: Common.initiativesDirectory(), }); expect(await invocation).toEqual({ exitCode: 0, @@ -142,6 +145,7 @@ describe("cli/load", () => { plugins: [githubDeclaration], sourcecredDirectory: Common.sourcecredDirectory(), githubToken: exampleGithubToken, + initiativesDirectory: Common.initiativesDirectory(), }; expect(await invocation).toEqual({ exitCode: 0,