diff --git a/sharness/__snapshots__/example-github-load/projects/c291cmNlY3JlZC10ZXN0L2V4YW1wbGUtZ2l0aHVi/project.json b/sharness/__snapshots__/example-github-load/projects/c291cmNlY3JlZC10ZXN0L2V4YW1wbGUtZ2l0aHVi/project.json index 8301ab5..01562ef 100644 --- a/sharness/__snapshots__/example-github-load/projects/c291cmNlY3JlZC10ZXN0L2V4YW1wbGUtZ2l0aHVi/project.json +++ b/sharness/__snapshots__/example-github-load/projects/c291cmNlY3JlZC10ZXN0L2V4YW1wbGUtZ2l0aHVi/project.json @@ -1 +1 @@ -[{"type":"sourcecred/project","version":"0.4.0"},{"discourseServer":null,"id":"sourcecred-test/example-github","identities":[],"repoIds":[{"name":"example-github","owner":"sourcecred-test"}]}] \ No newline at end of file +[{"type":"sourcecred/project","version":"0.5.0"},{"discourseServer":null,"id":"sourcecred-test/example-github","identities":[],"initiatives":null,"repoIds":[{"name":"example-github","owner":"sourcecred-test"}]}] \ No newline at end of file diff --git a/src/core/project.js b/src/core/project.js index d84b31d..7170087 100644 --- a/src/core/project.js +++ b/src/core/project.js @@ -3,6 +3,7 @@ import base64url from "base64url"; import {type RepoId} from "../plugins/github/repoId"; import {toCompat, fromCompat, type Compatible} from "../util/compat"; +import {type ProjectParameters as Initiatives} from "../plugins/initiatives/params"; import {type Identity} from "../plugins/identity/identity"; import {type DiscourseServer} from "../plugins/discourse/server"; @@ -24,17 +25,22 @@ export type ProjectId = string; * the future (e.g. showing the last update time for each of the project's data * dependencies). */ -export type Project = ProjectV040; -export type SupportedProject = ProjectV030 | ProjectV031 | ProjectV040; +export type Project = ProjectV050; +export type SupportedProject = + | ProjectV030 + | ProjectV031 + | ProjectV040 + | ProjectV050; -type ProjectV040 = {| +export type ProjectV050 = {| +id: ProjectId, + +initiatives: Initiatives | null, +repoIds: $ReadOnlyArray, +discourseServer: DiscourseServer | null, +identities: $ReadOnlyArray, |}; -const COMPAT_INFO = {type: "sourcecred/project", version: "0.4.0"}; +const COMPAT_INFO = {type: "sourcecred/project", version: "0.5.0"}; /** * Creates a new Project instance with default values. @@ -50,6 +56,7 @@ export function createProject(p: $Shape): Project { repoIds: [], identities: [], discourseServer: null, + initiatives: null, ...p, }; } @@ -72,13 +79,28 @@ export function encodeProjectId(id: ProjectId): string { return base64url.encode(id); } -const upgradeFrom030 = (p: ProjectV030 | ProjectV031): ProjectV040 => ({ +const upgradeFrom040 = (p: ProjectV040): ProjectV050 => ({ ...p, - discourseServer: - p.discourseServer != null ? {serverUrl: p.discourseServer.serverUrl} : null, + initiatives: null, }); -type ProjectV031 = {| +export type ProjectV040 = {| + +id: ProjectId, + +repoIds: $ReadOnlyArray, + +discourseServer: DiscourseServer | null, + +identities: $ReadOnlyArray, +|}; + +const upgradeFrom030 = (p: ProjectV030 | ProjectV031) => + upgradeFrom040({ + ...p, + discourseServer: + p.discourseServer != null + ? {serverUrl: p.discourseServer.serverUrl} + : null, + }); + +export type ProjectV031 = {| +id: ProjectId, +repoIds: $ReadOnlyArray, +discourseServer: {| @@ -88,7 +110,7 @@ type ProjectV031 = {| +identities: $ReadOnlyArray, |}; -type ProjectV030 = {| +export type ProjectV030 = {| +id: ProjectId, +repoIds: $ReadOnlyArray, +discourseServer: {| @@ -101,4 +123,5 @@ type ProjectV030 = {| const upgrades = { "0.3.0": upgradeFrom030, "0.3.1": upgradeFrom030, + "0.4.0": upgradeFrom040, }; diff --git a/src/core/project.test.js b/src/core/project.test.js index 12e0937..e6dc398 100644 --- a/src/core/project.test.js +++ b/src/core/project.test.js @@ -8,6 +8,9 @@ import { type Project, encodeProjectId, createProject, + type ProjectV040, + type ProjectV031, + type ProjectV030, } from "./project"; import {makeRepoId} from "../plugins/github/repoId"; @@ -20,12 +23,14 @@ describe("core/project", () => { id: "foo/bar", repoIds: [foobar], discourseServer: null, + initiatives: null, identities: [], }); const p2: Project = deepFreeze({ id: "@foo", repoIds: [foobar, foozod], discourseServer: {serverUrl: "https://example.com"}, + initiatives: {remoteUrl: "http://foo.bar/initiatives"}, identities: [ { username: "example", @@ -45,7 +50,7 @@ describe("core/project", () => { }); it("should upgrade from 0.3.0 formatting", () => { // Given - const body = { + const body: ProjectV030 = { id: "example-030", repoIds: [foobar, foozod], discourseServer: { @@ -63,15 +68,18 @@ describe("core/project", () => { const project = projectFromJSON(compat); // Then - expect(project).toEqual({ - ...body, - // It should strip the apiUsername field, keeping just serverUrl. - discourseServer: {serverUrl: "https://example.com"}, - }); + expect(project).toEqual( + ({ + ...body, + // It should strip the apiUsername field, keeping just serverUrl. + discourseServer: {serverUrl: "https://example.com"}, + initiatives: null, + }: Project) + ); }); it("should upgrade from 0.3.1 formatting", () => { // Given - const body = { + const body: ProjectV031 = { id: "example-031", repoIds: [foobar, foozod], discourseServer: { @@ -89,11 +97,39 @@ describe("core/project", () => { const project = projectFromJSON(compat); // Then - expect(project).toEqual({ - ...body, - // It should strip the apiUsername field, keeping just serverUrl. + expect(project).toEqual( + ({ + ...body, + // It should strip the apiUsername field, keeping just serverUrl. + discourseServer: {serverUrl: "https://example.com"}, + initiatives: null, + }: Project) + ); + }); + it("should upgrade from 0.4.0 formatting", () => { + // Given + const body: ProjectV040 = { + id: "example-040", + repoIds: [foobar, foozod], discourseServer: {serverUrl: "https://example.com"}, - }); + identities: [], + }; + const compat = toCompat( + {type: "sourcecred/project", version: "0.4.0"}, + body + ); + + // When + const project = projectFromJSON(compat); + + // Then + expect(project).toEqual( + ({ + ...body, + // It should add a default initiatives field. + initiatives: null, + }: Project) + ); }); }); describe("encodeProjectId", () => { @@ -130,6 +166,7 @@ describe("core/project", () => { expect(project).toEqual({ id: projectShape.id, discourseServer: null, + initiatives: null, repoIds: [], identities: [], }); @@ -141,6 +178,7 @@ describe("core/project", () => { id: "@foo", repoIds: [foobar, foozod], discourseServer: {serverUrl: "https://example.com"}, + initiatives: {remoteUrl: "http://foo.bar/initiatives"}, identities: [ { username: "example", diff --git a/src/core/project_io.test.js b/src/core/project_io.test.js index 5746a3b..9c2cee9 100644 --- a/src/core/project_io.test.js +++ b/src/core/project_io.test.js @@ -37,6 +37,7 @@ describe("core/project_io", () => { repoIds: [foobar, foozod], discourseServer: {serverUrl: "https://example.com"}, identities: [{username: "foo", aliases: ["github/foo", "discourse/foo"]}], + initiatives: {remoteUrl: "https://example.com/initiatives"}, }); it("setupProjectDirectory results in a loadable project", async () => { diff --git a/src/plugins/initiatives/params.js b/src/plugins/initiatives/params.js new file mode 100644 index 0000000..9f36d9e --- /dev/null +++ b/src/plugins/initiatives/params.js @@ -0,0 +1,11 @@ +// @flow + +/** + * Options to add to Project spec. + * Assumes we're loading an InitiativesDirectory. We're not including the local + * path here, as this is environment dependent. It should be passed as an ENV + * or CLI parameter instead. + */ +export type ProjectParameters = {| + +remoteUrl: string, +|};