Commit Graph

787 Commits

Author SHA1 Message Date
William Chargin 04f7e9ea8c
graphql: generate Flow types from a schema (#927)
Summary:
Generating Flow types from a structured schema is both straightforward
and terribly useful. This commit implements it.

Test Plan:
Inspect the snapshot for correctness manually. Then, copy it into a new
file, remove backslash-escapes, and verify that it passes Flow.
A subsequent commit will generate types for the actual GitHub schema.

wchargin-branch: graphql-generate-flow-types
2018-10-19 09:02:49 -07:00
William Chargin e787db53c4
schema: allow annotating primitive field types (#926)
Summary:
Prior to this change, primitive fields were un\[i\]typed. This commit
allows adding type annotations. Such annotations do not change the
semantics at all, but we will be able to use them to generate Flow types
corresponding to a schema.

This commit also strengthens the validation on schemata to catch some
errors that would previously have gone unnoticed at schema construction
time: e.g., a node reference to a type that does not exist.

Test Plan:
Unit tests updated, retaining full coverage. The demo script continues
to work when loading `example-github` or `sourcecred`.

wchargin-branch: schema-annotated-primitives
2018-10-19 09:00:52 -07:00
William Chargin 4558d775a5
flow-typed: fix Prettier libdefs (#925)
Summary:
This patches in the following two pull requests from upstream:

  - https://github.com/flow-typed/flow-typed/pull/2856
  - https://github.com/flow-typed/flow-typed/pull/2860

The first exports types so that they can be used in client code.
The second fixes a broken type definition.

Test Plan:
See the test plans in those two PRs.

wchargin-branch: flow-typed-fix-prettier
2018-10-19 08:54:00 -07:00
William Chargin ee4900616b
github: fetch commit parent oids (#924)
Summary:
To ease the transition from manual continuation resolution to the Mirror
API, we update the old system to fetch commit parent OIDs, as described
in #923.

Test Plan:
To check that the continuations are wired correctly, apply the following
patch to force continuations to be followed at every step:

```diff
diff --git a/src/plugins/github/graphql.js b/src/plugins/github/graphql.js
index 05761ca..a21a364 100644
--- a/src/plugins/github/graphql.js
+++ b/src/plugins/github/graphql.js
@@ -53,7 +53,7 @@ const PAGE_SIZE_COMMENTS = 20;
 const PAGE_SIZE_REVIEWS = 5;
 const PAGE_SIZE_REVIEW_COMMENTS = 10;
 const PAGE_SIZE_COMMIT_HISTORY = 100;
-const PAGE_SIZE_COMMIT_PARENTS = 5;
+const PAGE_SIZE_COMMIT_PARENTS = 0;
 const PAGE_SIZE_REACTIONS = 5;

 /**
@@ -358,6 +358,7 @@ function* continuationsFromCommit(
 ) {
   const b = build;
   if (result.parents && result.parents.pageInfo.hasNextPage) {
+    console.warn(result.parents.pageInfo);
     yield {
       enclosingNodeType: "COMMIT",
       enclosingNodeId: nodeId,
@@ -366,7 +367,7 @@ function* continuationsFromCommit(
           b.field(
             "parents",
             {
-              first: b.literal(PAGE_LIMIT),
+              first: b.literal(1),
               after: b.literal(result.parents.pageInfo.endCursor),
             },
             [b.fragmentSpread("commitParents")]
```

(It is important that the initial page limit be `0` and not (say) `1`,
because the `defaultBranchRef` is likely to have just one parent; by
using `0`, we test its continuations as long as it has at least one
parent.)

Then run `./src/plugins/github/fetchGithubRepoTest.sh` and note that the
test passes and the output is

```
{ hasNextPage: true, endCursor: null }
{ hasNextPage: true, endCursor: null }
{ hasNextPage: true, endCursor: null }
{ hasNextPage: true, endCursor: null }
{ hasNextPage: true, endCursor: null }
{ hasNextPage: true, endCursor: null }
{ hasNextPage: true, endCursor: null }
{ hasNextPage: true, endCursor: 'MQ==' }
{ hasNextPage: true, endCursor: 'MQ==' }
```

Note that the test output (as updated in this commit) includes commits
with a unique parent, a commit with no parents, and a commit with two
parents.

I also ran `node ./bin/sourcecred.js load` on sourcecred/sourcecred and
ipfs/js-ipfs. Each worked, and the resulting credit attributions loaded
fine.

wchargin-branch: github-commit-parent-oids
2018-10-18 19:16:44 -07:00
William Chargin 7c5923959e
github: fetch dates from commits (#919)
Summary:
This has two benefits:

  - The dates on commits are data that we will probably want when we add
    timestamps to authorship edges to accommodate time-weighted cred.

  - Once the mirror module is integrated with the GitHub plugin, we’ll
    want to fetch dates on commits, because this is the only real-world
    test case for a nested field that contains a primitive field (as
    opposed to a node reference), so it’ll be nice to be continually
    exercising that somewhat-edge case.

Date strings are in commit-local time and do not depend on the time zone
of the requester (in contrast to [cursors]). For example, on SourceCred:

```shell
$ time node ./bin/fetchAndPrintGithubRepo.js \
> sourcecred sourcecred "${GITHUB_TOKEN}" |
> jq -rc '
>     .repository.defaultBranchRef.target.history.nodes[]
>     .author?.date[-6:]
> ' | sort | uniq -c
      1 +03:00
      6 -04:00
    717 -07:00
     58 -08:00
```

[cursors]: <https://github.com/sourcecred/sourcecred/pull/129#issuecomment-382970474>

Test Plan:
The snapshot contains 8 instances of `oid` and 8 instances of `date`,
which is good (each of these properties appears exactly once on each
commit, and nowhere else). Running `yarn test --full` passes.

wchargin-branch: github-commit-dates
2018-10-16 22:54:39 -07:00
William Chargin 1155c439b9
mirror: add support for shallow-nested fields (#918)
Summary:
This commit follows up on the previous two pull requests by drawing the
rest of the owl.

Resolves #915.

Test Plan:
Unit tests included.

To verify the snapshot change, open the snapshot file, and copy
everything from `query TestUpdate {` through the matching `}`, not
including the enclosing quotes. Strip all backslashes (Jest adds them).
Post the resulting query to GitHub and verify that it completes
successfully and that the result contains a commit with an `author`.

In other words, `xsel -ob | tr -d '\\' | ghquery | jq .` with [ghquery].

[ghquery]: https://gist.github.com/wchargin/630e03e66fa084b7b2297189615326d1

The demo entry point has also been updated. For an end-to-end test, you
can run the following command to see a commit with a `null` author (with
the current state of the repository) and a commit with a non-`null`
author:

```
$ node bin/mirror.js /tmp/mirror-example.db \
>     Repository MDEwOlJlcG9zaXRvcnkxMjMyNTUwMDY= \
>     3600 2>/dev/null |
> jq '(.defaultBranchRef.target, .pullRequests[0].mergeCommit) | {url, author}'
{
  "url": "6bd1b4c0b7",
  "author": {
    "date": "2018-09-12T19:48:21-07:00",
    "user": null
  }
}
{
  "url": "0a223346b4",
  "author": {
    "date": "2018-02-28T00:43:47-08:00",
    "user": {
      "id": "MDQ6VXNlcjE0MDAwMjM=",
      "__typename": "User",
      "url": "https://github.com/decentralion",
      "login": "decentralion"
    }
  }
}
```

You can also check that it is possible to fetch the whole SourceCred
repository (ID: `MDEwOlJlcG9zaXRvcnkxMjAxNDU1NzA=`).

wchargin-branch: mirror-shallow
2018-10-04 16:00:07 -07:00
William Chargin 49f0803a7a
mirror: reflect nested fields in schema info (#917)
Summary:
See #915 for context. This adds nested field data to the “useful info”
data structure added in #857.

Test Plan:
Unit tests for `_buildSchemaInfo` updated.

wchargin-branch: mirror-schemainfo-shallow
2018-10-04 15:30:04 -07:00
William Chargin 3d2206088c
schema: support shallow-nested object fields (#916)
Summary:
See #915 for context. This commit changes the `schema` module only.

I had a hard time picking names that clearly distinguish the top-level
field on the object and the subfields that it contains. @decentralion
and I independently came up with “nest” and “egg”. It’s a bit colorful,
but it’s certainly easy to remember which one is which, and it doesn’t
conflict with existing notions like “parent”/“child”.

Test Plan:
Unit tests expanded slightly, retaining full coverage.

wchargin-branch: schema-shallow
2018-10-04 15:28:58 -07:00
William Chargin d8d857fdd3
ci: remove Travis (#914)
Summary:
Closes #902. CircleCI continues to work fast and well, on both the
commit and nightly workflows. Travis continues to be slower. It is time.

I have disabled Travis for `sourcecred/sourcecred` via:
<https://travis-ci.org/profile/sourcecred>

This commit removes the vestigial configuration files and code.

Test Plan:
Running `yarn test` still works. Running `yarn test --full` still works,
and properly invokes `sharness-full` and the various extra tests.
Running `git grep -i travis` yields no results.

wchargin-branch: ci-remove-travis
2018-10-04 12:31:14 -07:00
William Chargin 48b68b221a
link: remove `styles` attribute from child (#911)
Summary:
By using `<a {...this.props}>{children}</a>`, we were forwarding the
Aphrodite selectors as `styles`. This caused the static HTML for the
page to include `<a styles="[object Object]">`, which is annoying.

Test Plan:
Unit tests extended: they fail before this change and pass after it.
Also clicked a router link and an external link in the application.

wchargin-branch: link-child-styles
2018-10-03 12:14:07 -07:00
William Chargin 16ed92549a
readme: replace Travis badge with CircleCI badge (#912)
Summary:
See #902 for context.

Test Plan:
Push to GitHub; observe badge in rendered README.

wchargin-branch: readme-circleci-badge
2018-10-03 11:43:10 -07:00
William Chargin 55950f5354
mirror: add an end-to-end `update` function (#909)
Summary:
This completes the minimum viable public API for the `Mirror` class. As
described on the docstring, the typical workflow for a client is:

  - Invoke the constructor to acquire a `Mirror` instance.
  - Invoke `registerObject` to register a root object of interest.
  - Invoke `update` to update all transitive dependencies.
  - Invoke `extract` to retrieve the data in structured form.

It is the third step that is added in this commit.

In this commit, we also include a command-line demo of the Mirror
module, which exercises exactly the workflow above with a hard-coded
GitHub schema. This can be used to test the module’s behavior with
real-world data. I plan to remove this entry point once we integrate
this module into SourceCred.

This commit makes progress toward #622.

Test Plan:
Unit tests included for the core functionality. The imperative shell
does not have automated tests. You can test it as follows.

First, run `yarn backend` to build `bin/mirror.js`. Then, run:

```shell
$ node bin/mirror.js /tmp/mirror-demo.db \
> Repository MDEwOlJlcG9zaXRvcnkxMjMyNTUwMDY= \
> 60
```

Here, the big base64 string is the ID for the sourcecred/example-github
repository. (This is listed in `graphql/demo.js`, alongside the ID for
the SourceCred repository itself.) The value 60 is a TTL in seconds. The
database filename is arbitrary.

This will print out a ton of output to stderr (all intermediate queries
and responses, for debugging purposes), and then the full contents of
the example repository to stdout.

Run the command again, and it should finish instantly. On my machine,
the main function runs faster than the Node startup time (50ms vs 60ms).

Then, re-run the command, changing the TTL from `60` to `1`. Note that
it sends off some queries and then prints the same repository.

It is safe to kill the program at any time, either while waiting for a
response from GitHub or while processing the results, because the mirror
module takes advantage of SQLite’s transaction-safety. Intermediate
updates will be persisted, so you’ll lose just a few seconds of
progress.

You can also of course dive into the generated database yourself to
explore the data. It’s good fun.

wchargin-branch: mirror-e2e-update
2018-10-02 21:06:01 -07:00
William Chargin 23e56f481a
mirror: paginate own-data node updates (#908)
Summary:
GitHub has an undocumented node limit on the number of IDs that can be
provided to the top-level `nodes` connection. This is silly, because we
can just spread the IDs over multiple identical connections. This commit
implements the logic to do so.

Test Plan:
Create some queries that use `nodes(ids: ...)` to fetch varying numbers
of objects:

```shell
id="MDEwOlJlcG9zaXRvcnkxMjAxNDU1NzA="
nodes() {
    n="$1"
    ids="$(yes "$id" | head -n "$n" | jq -R . | jq -sc .)"
    printf 'nodes(ids: %s) { __typename }' "$ids"
}
query() {
    printf '{ '
    for num; do
        printf 'nodes_%s: %s ' "$num" "$(nodes "$num")"
    done
    printf '}'
}
```

Note that the query given by `query 101` results in an error…

```json
{
  "data": null,
  "errors": [
    {
      "message": "You may not provide more than 100 node ids; you provided 101.",
      "type": "ARGUMENT_LIMIT",
      "path": [
        "nodes_101"
      ],
      "locations": [
        {
          "line": 1,
          "column": 3
        }
      ]
    }
  ]
}
```

…but the query given by `query 98 99` happily returns 197 node entries.

wchargin-branch: mirror-paginate-own-data
2018-10-02 20:49:01 -07:00
William Chargin 1b09a7f61b
markdown: ignore references in HTML code elements (#907)
Summary:
Fixes #903. We already ignore Markdown code syntax (backticks), but
prior to this commit we treated the contents of all HTML elements,
including `<code>`, as normal text. As of this commit, `<code>` elements
are stripped entirely. Other HTML elements, like `<em>`, are unaffected.

Test Plan:
Unit tests added. Also, load data for `ipfs/js-ipfs-block-service`, and
observe in the UI that PR `#36` (Update aegir to version 9.0.0) no
longer has any outward references.

wchargin-branch: markdown-html-code
2018-10-02 20:34:49 -07:00
William Chargin 3e49466ad5
ci: add "commit" and "nightly" CircleCI workflows (#906)
Summary:
This should run `yarn test` on every commit, and `yarn test --full`
on `master` once per day at 15:00 PDT/14:00 PST.

Useful documentation links:

  - <https://circleci.com/docs/2.0/workflows/#scheduling-a-workflow>
  - <https://circleci.com/docs/2.0/reusing-config/#authoring-reusable-commands>

Test Plan:
I’ve pushed this branch and verified that the “commit” workflow executes
successfully on CircleCI. To test the cron workflow, we’ll have to wait
until the daily build.

wchargin-branch: circleci-workflows
2018-10-02 10:57:33 -07:00
William Chargin 163b2c1377
env: drop `--date=format:...` to support Git 2.1.4 (#901)
Summary:
Git only learned `--date=format:...` in Git 2.6.0. Some old Docker
images have older versions of Git. It’s not too much work to reimplement
this particular bit of functionality, so this commit does so.

Test Plan:
Install Git 2.1.4 (as used on CircleCI): from the Git repository for
Git itself, run:

    git checkout v2.1.4
    make
    make install

Watch `yarn test --full` pass. Before this commit, `yarn unit` failed.

wchargin-branch: env-support-git-2.1.4
2018-10-01 18:07:52 -07:00
William Chargin 440b6c2567
env: pass parent PATH to Git invocations (#900)
Summary:
Our environment-stripping logic used in `config/env.js` to read the
current Git state included stripping the `PATH` environment variable.
This had the effect that the system Git executable would always be used
in preference to a user-installed version.

Test Plan:
Run `/usr/bin/git --version`, and then install a different version of
Git. (For instance, check out an old tag, then `make && make install`
from the `git/git` repository.) Then, add

```js
  console.log(execFileSync("git", ["--version"], {env}).toString());
```

to `getGitState` in `config/env.js`, and run

    NODE_ENV=development node ./config/env.js

Note that this prints the version of the system Git before this change,
and the user Git after this change.

Alternately, local-install a version of Git earlier than 2.6.0, and note
that `yarn unit` now _fails_ because the `--date=format:…` syntax is not
known to such versions of Git. Prior to this commit, the tests would
pass as long as the system Git were more recent.

wchargin-branch: env-git-path
2018-10-01 17:52:56 -07:00
William Chargin e0dcce220b
ci: add CircleCI config (#899)
Summary:
CircleCI seems fast.

This config file copied from the one suggested by CircleCI, with the
following modifications: Node version changed from 7.10 to 8.12.0;
commented-out MongoDB dependency removed; capitalization error in header
comment fixed.

Test Plan:
Per the CircleCI instructions, merge this PR and then turn on the
project.

wchargin-branch: circleci-config
2018-09-28 16:58:54 -07:00
Dandelion Mané 4a374d755e
Hyperlink Git commits to GitHub (#887)
This modifies the `nodeDescription` code for the Git plugin so that when
given a Git commit, it will hyperlink to that commit on GitHub. It does
this by looking up the corresponding `RepoId`s from the newly-added
`commitToRepoId` field in the `Repository` (#884).

Per a [suggestion in review], rather than hardcoding the GitHub url
logic in the Git plugin, we provide them via a `GitGateway`.

[suggestion in review]: https://github.com/sourcecred/sourcecred/pull/887#issuecomment-424059649

When no `RepoId` is found, it errors to console and does not include a
hyperlink. When multiple `RepoId`s are available, it chooses to link to
one arbitrarily. (In the future, we could amend this behavior to add
links to every valid repo). This behavior is tested.

Test plan:
I ran the application on newly-generated data and verified that it sets
up commit hyperlinks appropriately. Also, see unit tests.
2018-09-27 20:32:43 -07:00
William Chargin 65d811fb44
mirror: add helpers for full queries and updates (#898)
Summary:
An update step is now roughly as simple as:

    _updateData(postQuery(_queryFromPlan(_findOutdated())))

(with some option/config parameters thrown in).

This makes progress toward #622.

Test Plan:
Unit tests included. They are light, because these functions are light.
They still retain full coverage.

wchargin-branch: mirror-full-pipeline
2018-09-27 19:12:47 -07:00
William Chargin 9a4c91887b
mirror: include typenames in extracted data (#897)
Summary:
These typenames are often superfluous, but sometimes they are useful.
For instance, we might want to fetch the same data for `User`s, `Bot`s,
and `Organization`s, but still differentiate which kind of node we
fetched from an `Actor` union reference. Similarly, many timeline events
may have similar signatures (like, “issue closed” vs. “issue reopened”).

Test Plan:
Existing unit tests have been updated; run `yarn unit`.

wchargin-branch: mirror-extract-typenames
2018-09-26 21:24:30 -07:00
William Chargin c7ba89b807
license: relicense under MIT + Apache-2 (#896)
Summary:
All contributors to SourceCred have agreed to this more permissive
licensing option:

  - @decentralion: [link to comment][decentralion]
  - @wchargin: [link to comment][wchargin]
  - @claireandcode: [link to comment][claireandcode]

[decentralion]: https://github.com/sourcecred/sourcecred/issues/812#issuecomment-420817902
[wchargin]: https://github.com/sourcecred/sourcecred/issues/812#issuecomment-420819732
[claireandcode]: https://github.com/sourcecred/sourcecred/issues/812#issuecomment-424914639

Archive link to thread: <https://archive.fo/BH2v5>

Resolves #812.

Test Plan:
Note that the GitHub tree explorer correctly links from the README to
the individual license files.

wchargin-branch: license-dual-mit-apache2
2018-09-26 19:28:41 -07:00
William Chargin b74f1f3714
mirror: add public method `extract` (#894)
Summary:
The `extract` method lets you get data out of a mirror in a structured
format.

The mirror module now contains all the plumbing needed to provide
meaningful value. Remaining to be implemented are some internal
porcelain and a public method to perform an update step.

This makes progress toward #622.

Test Plan:
Comprehensive unit tests included, with full coverage; run `yarn unit`.

wchargin-branch: mirror-extract
2018-09-26 12:04:10 -07:00
William Chargin 90ace93f91
mirror: add helper to find unused table name (#895)
Summary:
Per <https://github.com/sourcecred/sourcecred/pull/894#discussion_r220406780>.

Test Plan:
Unit tests included; run `yarn unit`.

wchargin-branch: mirror-unused-table-name
2018-09-26 11:37:21 -07:00
Dandelion Mané 42cdfa4332
Upgrade jest and typings (#893)
Motivated by my desire for `.toMatchInlineSnapshot()`. Really we just
need and updated typing file for this, but I upgraded `jest` too to just
get us in a clean state.

Commit generated via:
```
yarn add --dev jest
flow-typed install jest@23.6.0
```

Test plan: `yarn test`
2018-09-25 18:48:54 -07:00
William Chargin a5e0707cb9
ui: remove `:visited` color change for nav links (#892)
Test Plan:
Note that the nav links are now a lighter color, except when `:active`
(e.g., when you’re holding down the mouse button).

wchargin-branch: remove-visited
2018-09-25 16:38:46 -07:00
William Chargin a7f29cb057
mirror: add connection object types to query plan (#891)
Summary:
This reestablishes harmony in light of #882.

Test Plan:
Existing unit tests suffice; run `yarn unit`.

wchargin-branch: mirror-query-plan-connection-object-typename
2018-09-25 14:25:11 -07:00
William Chargin 892c498f9c
mirror: query and process own-data updates (#883)
Summary:
This commit adds internal functions to (a) emit a GraphQL query to fetch
data for own-data of an object, and (b) ingest the results of said query
back into the database.

The API and implementation differ from the connection-updating analogues
introduced in #878 in that the query for own data is independent of an
object’s ID: it depends only on the object’s type. This affords us more
flexibility in composing queries.

As described in a internal documentation comment, values are stored in
the database in JSON-stringified form: we cannot use the obvious raw SQL
values, because there is no native encoding of booleans (`0`/`1` is
conventional), and we need to distinguish them from other data types.
There are other ways to solve this problem. Notably:

 1. We could take inspiration from OCaml: encode stronger static types
    and a simpler runtime representation. That is, we could change the
    schema field types from simply “primitive” to the various specific
    primitive types. Then, when reading data out from the database, we
    could reinterpret the values appropriately.

 2. We could take advantage of the fact that we are not using all of
    SQLite’s data types. In particular, we do not store anything as a
    binary blob, so we could encode `false` as a length-0 zeroblob and
    `true` as a length-1 zeroblob, for instance. Again, when reading
    data out from the database, we would reinterpret the values—but in
    this approach we would not need an explicit schema from the user.

For now, we take the easiest and simplest approach just to get ourselves
off the ground. We can easily move to the second option described above
later.

This commit makes progress toward #622.

Test Plan:
Unit tests included, with full coverage. While these tests check that
the GraphQL queries are as expected, they cannot check that they are
actually valid in production. To check this, follow the instructions in
the added snapshot test.

wchargin-branch: mirror-own-data-updates
2018-09-25 11:58:32 -07:00
William Chargin 2af8566e6a
app: add and use a shared Link component (#890)
Summary:
This will enable us to style links consistently across our application.

Our previous link colors for base and `:visited` were so similar that I
didn’t actually realize that they were different. In this change, I’ve
kept the same base color, and selected a more contrasting `:visited`
color. I also added an `:active` color, which is good for usability
(color chosen via <http://paletton.com/>’s “triad” suggestion).

Example screenshot, with active, visited, and base links:
![Screenshot as in this commit][img-underline]

I also considered implementing the link underlines with `border-bottom`
instead of `text-decoration` (an oft-touted suggestion that has always
smelled fishy to me, but [the W3 does it][w3], so I guess it’s okay).
That would look like this:

![Screenshot with `border-bottom` underlines][img-border]

…but I did not do so ([rationale in a comment on #890][rationale]).

[w3]: https://www.w3.org/TR/WCAG20-TECHS/F73.html
[img-underline]: https://user-images.githubusercontent.com/4317806/45987381-f154f580-c025-11e8-8b0f-63c1e1ddce02.png
[img-border]: https://user-images.githubusercontent.com/4317806/45926176-a081b780-bed4-11e8-96f2-d0d24d11c8f7.png
[rationale]: https://github.com/sourcecred/sourcecred/pull/890#issuecomment-424146773

We can certainly change these decisions later—that’s one of the purposes
of having this abstraction—so I’m not inclined to bikeshed on them too
much in this commit.

Implementation adapted from:
<80263b190e/src/components/Link.js>

Test Plan:
Check that `<a>` elements and React Router link elements are used only
in `Link` and snapshots:

```
$ git grep --name-only -Fw '<a'
src/app/Link.js
src/assets/logo/discourse_512.png
src/plugins/github/__snapshots__/render.test.js.snap
$ git grep '"react-router"' | grep 'Link'
src/app/Link.js:import {Link as RouterLink} from "react-router";
src/app/Link.test.js:import {Link as RouterLink} from "react-router";
src/app/createRelativeHistory.test.js:import {Router, Route, Link} from "react-router";
src/app/withAssets.test.js:import {IndexRoute, Link, Router, Route} from "react-router";
```

Check that the primary color now appears in just one spot:

```
$ git grep -i 0872a2
src/app/Link.js:    ...colorAttributes("#0872A2"),
```

Then, run `yarn start` and click all the links. Note in particular that
the SVG icons in the header have the correct colors in the active state
as well as the base state.

wchargin-branch: app-link
2018-09-24 18:26:52 -07:00
William Chargin 3257df63fe
mirror: add helper to register nullable node results (#889)
Summary:
As <https://github.com/sourcecred/sourcecred/pull/883/files#r219648511>.
It is somewhat unfortunate that this mixes a command with a query, but
the concession is acceptable in this instance, I think.

Test Plan:
Existing unit tests suffice, retaining full coverage.

wchargin-branch: mirror-register-node-field-results
2018-09-24 18:20:28 -07:00
William Chargin 28c4e497fb
mirror: factor out `_makeSingleUpdateFunction` (#888)
Summary:
This helpful utility is already used in some test code, and will shortly
be used in main code. @decentralion suggested factoring it out in
<https://github.com/sourcecred/sourcecred/pull/883#discussion_r219647781>.

Test Plan:
Unit tests included, with full coverage; run `yarn unit`.

wchargin-branch: mirror-make-update-helper
2018-09-24 18:06:14 -07:00
William Chargin 252400d5e7
flow: fix `Statement` properties (#886)
Summary:
These were completely wrong; my bad.

[The docs][1] list `source` and `returnsData` but not `database`.
I include the latter only for consistency with `Transaction`, and will
consider removing them both as they are technically undocumented (though
not underscore-named, so it’s not clear-cut).

[1]: https://wchargin.github.io/better-sqlite3/api.html#properties-1

Test Plan:
At a Node console:

```js
> require("better-sqlite3")(":memory:").prepare("BEGIN")
Statement {
  returnsData: false,
  source: 'BEGIN',
  database:
   Database {
     inTransaction: false,
     open: true,
     memory: false,
     readonly: false,
     name: ':memory:' } }
```

wchargin-branch: flow-better-sqlite3-statement-properties
2018-09-21 17:48:28 -07:00
Dandelion Mané 3b962eacea
Git: track the repositories containing each commit (#884)
This modifies the Git `Repository` data structure so that for every
commit, we track the `RepoId`s of repos containing that commit. This way
we will be able to do things like hyperlink to the right url for that
commit.

`loadRepository` has been modified to set the initial `repoId`.
`mergeRepository` has been updated to ensure that it concatenates the
`repoId`s properly.
Tests were added for both cases.

The example-git snapshot has been updated accordingly.

Test plan: `yarn test --full`
2018-09-21 17:06:14 -07:00
Dandelion Mané b506d40efd
Add the `RepoIdString` type (#885)
This modifies `core/repoId` so that `repoIdToString` returns not a
`string`, but an opaque subtype of `string` called `RepoIdString`.

This allows us to store stringified `RepoId`s (which is useful whenever
we want value-not-reference semantics, like for use as a map key)
while still maintaining a type assertion that the strings, in fact,
represent valid `RepoId`s.

Test plan: A unit test verifies that it's a flow error to cast a string
to a `RepoIdString`.
2018-09-21 16:54:20 -07:00
William Chargin 838092194b
mirror: add support for connections of union types (#882)
Summary:
Almost every GitHub connection has nodes of an object type, like `User`
or `IssueComment`. But a few have nodes of union type, including
`IssueTimelineItemConnection` (which we will likely want to query), and
those require special handling. This commit adds susupport for such
connections.

Analysis to determine which connections have non-object elements:
<https://gist.github.com/wchargin/647fa7ed8d6d17ae2e204bd098104407>

Test Plan:
Unit tests modified appropriately, retaining full coverage.

The easiest way to verify the snapshot is probably to copy the raw
contents (everything inside the quotes) into `/tmp/snapshot`, then run:

```shell
$ sed -e 's/\\//g' </tmp/snapshot >/tmp/query  # Jest adds backslashes
$ jq -csR '{query: ., variables: {}}' </tmp/query >/tmp/payload
$ ENDPOINT='https://api.github.com/graphql'
$ AUTH="Authorization: bearer ${SOURCECRED_GITHUB_TOKEN}"
$ curl "$ENDPOINT" -X POST -H "$AUTH" -d @- </tmp/payload >/tmp/result
```

and then execute the JQ program mentioned in the comment in the test
case, and verify that it prints `true`.

wchargin-branch: connection-of-union
2018-09-21 16:20:58 -07:00
Dandelion Mané 23ae7e2f08
Rename the core `Repo` type to `RepoId` (#881)
We have a core type called `Repo`, but it really is an identifier to a
repo, rather than being a repo itself. This is confusing since we have a
data type called `Repository` which actually represents the data in a
repository. I've renamed `Repo` to `RepoId` for clarity.

Test plan: `yarn test --full` passes. Running the frontend passes after
wholly regenerating the sourcecred data directory.
2018-09-21 14:44:29 -07:00
Dandelion Mané 1e5f728e29
Cred explorer: display commit short hash + summary (#879)
This modifies how commits are displayed in the cred explorer. Rather
than printing the full hash, we now print a short hash followed by the
summary.

Test plan:
Snapshot is updated, also I tested it by running SourceCred on a real
repository.
2018-09-21 13:24:28 -07:00
William Chargin 09ed51ed6e
mirror: align test schema more with GitHub schema (#880)
Summary:
This commit changes the `Issue` type of the schema used in the `mirror`
tests to have fields a faithful subset of those in the actual GitHub
schema. The tests are self-contained, so this is not strictly required.
However, it is convenient, because it means that we can snapshot a query
that can actually be posted to GitHub.

Test Plan:
Running `yarn unit mirror` suffices for the code change. The GitHub
schema docs at <https://developer.github.com/v4/object/issue/> indicate
that each of `id`, `url`, `author`, `repository`, `title`, and
`comments` is a valid field.

wchargin-branch: mirror-test-schema
2018-09-20 17:17:27 -07:00
Dandelion Mané 0b3e2e7f7f
Load commits' short hash and summary (#876)
This modifies the Git Commit type to includea short hash and a oneline
summary, and modifies `loadRepository` so that we actually get that
data.

The example-git repository has been updated to include a commit with
leading whitespace and a pipe in the summary, to ensure that these are
respected.

Test plan: Observe that the snapshot is updated, and the updates are
correct. `yarn test --full` passes.
2018-09-20 15:51:58 -07:00
William Chargin 6ae5c56624
mirror: query and process connection updates (#878)
Summary:
This commit adds internal functions to (a) emit a GraphQL query to fetch
data for a particular connection, and (b) ingest the results of said
query back into the database.

This commit makes progress toward #622.

Test Plan:
Unit tests included, with full coverage. While these tests check that
the GraphQL queries are as expected, they cannot check that they are
actually valid in production. To check this, follow the instructions in
the added snapshot test.

wchargin-branch: mirror-connection-updates
2018-09-20 15:46:03 -07:00
Dandelion Mané 5348fe68bf
Remove git adresses for trees, blobs, and entries (#877)
In #873 I removed the data types for trees, blobs, and entries, but
neglected to remove the address related code. This commit corrects that
mistake. Some test cases in other modules have been removed because the
failure is now structurally impossible, e.g. it is not possible that we
would provide a non-commit address to the GitHub plugin, because
non-commit addresses do not exist.

Test plan: `yarn test --full` passes.
2018-09-20 15:18:01 -07:00
William Chargin 1dd8b7bcb7
mirror: add internal method `_findOutdated` (#875)
Summary:
This function finds all objects whose own data has not been updated
since a given time, and all connections whose entries have not been
updated since that time.

Note that this is scoped to the entirety of the database. In #622,
I discussed using a recursive common table expression to identify only
those transitive dependencies of the root. I think that this is overkill
for the `_findOutdated` method: you’ll usually want to update everything
in the database. Don’t worry—the cool recursive query will still be used
in the `extract` function. :-)

This commit makes progress toward #622.

Test Plan:
Unit tests added, with full coverage; run `yarn unit`.

wchargin-branch: mirror-findoutdated
2018-09-20 14:19:47 -07:00
Dandelion Mané e3f04c5079
Git plugin serializes the repository and graph (#874)
This modifies the behavior when loading the Git plugin so that it
serializes the Repository as well as the graph. This will allow us to
get extra information, like the commit headline, to the Git plugin in
the frontend.

As an added bonus, we can now refactor `loadRepositoryTest` to depend on
`sourcecred.js load` rather than `loadAndPrintRepository`. As this was
the only use for `loadAndPrintRepository`, we can safely delete it. This
improves our test quality because it means we are also testing the
actual CLI behavior.

Note that the switch from using `stringify` to `json.tool` for
pretty-printing has resulted in a trivial diff in the snapshot.

Test plan: `yarn test --full` passes.
2018-09-20 14:07:58 -07:00
Dandelion Mané 5b8ec53b13
Remove all git tree related code (#873)
In #627, I made a case for removing all trees and blobs from the cred
graph. The issue was that the data was bloated and noisy, and did not
provide much value in its current form. This commit follows on that by
actually removing the code from the codebase (rather than keeping it
unused).

I want to delete this code because I believe:
1. It is unlikely to see further use in its current form (because
collecting the entire Git tree structure is just too noisy for our
purposes)
2. In the event that we do need it, reviving it will not be too
difficult (because it is all quite locally scoped to the Git plugin).
3. Keeping unused code increases ongoing maintenance + development
costs, and I'd like to bias towards keeping the codebase simple and
lean.

In the event that a future contributor is reviving this code and finds
it a pain, I pre-emptively apologize to you.

Test plan:
`yarn test --full` passees.
2018-09-20 13:50:27 -07:00
William Chargin ab5b6ecb68
mirror: add public method `registerObject` (#870)
Summary:
This function informs the GraphQL mirror of the existence of an object,
specified by its global ID and its concrete typename (“concrete” meaning
“object type”—like `User`, not `Actor`).

The function will be called extensively internally as more objects are
discovered while traversing the graph, but also needs to be exposed as a
public entry point: a client needs to call this function at least once
to register the root node of interest. A typical client workflow, once
all of #622 is implemented, might be:

 1. Issue a standalone GraphQL query to find the ID of a root node, like
    a GitHub repository: `repository(owner: "foo", name: "bar") { id }`.
 2. Call `registerObject` with the ID found in the previous step.
 3. Instruct the mirror to recursively update all dependencies.
 4. Extract data from the mirror.

As of this commit, steps (1) and (2) are possible.

This commit makes progress toward #622.

Test Plan:
Unit tests included, with full coverage; run `yarn unit`.

wchargin-branch: mirror-registerobject
2018-09-20 13:03:06 -07:00
Dandelion Mané 12aa5b7439
Add `mergeRepository` for merging Git repositories (#871)
This commit adds a utility method, `mergeRepository`, which can merge
multiple Git repository data structures. `loadGitData` has been updated
to create a merged repository and then subsequently generate a graph
from it.

Test plan:
New unit tests were added. `yarn test --full` passes. Loading a project
and viewing its git data in the cred explorer works.
2018-09-20 12:57:57 -07:00
Dandelion Mané 8442255db3
Remove obsolete eslint TODOs (#872)
I wanted to add two new flowtype lint rules. However, as seen in #853
and #854, these rules don't work very well. As such, I'm giving up on
those two and removing the TODOs.

Test plan: n/a
2018-09-20 12:52:07 -07:00
William Chargin 7702bb2e1d
flow: simplify better-sqlite3 bound parameters (#869)
Summary:
The actual constraints for bound parameters are too complicated to
express within Flow. This commit changes the type definitions from one
approximation to another, simpler one. Neither approximation is likely
to cause many problems in practice, either in terms of spurious errors
or spurious lacks of error. (The failure mode for the new formulation is
having multiple dictionaries of binding values, which would pass Flow
but quickly raise a `TypeError` at runtime.)

The reason for the change is that it makes the method definitions
considerably simpler, in a way that is likely to avoid other problems
with Flow. In particular, this removes method overloads and the need for
parameter disambiguation.

I fix a typo while in the area.

Test Plan:
Note that the following file typechecks:

```js
// @flow
import Database from "better-sqlite3";
const db = new Database(":memory:");
const stmt = db.prepare("BEGIN"); // SQL text doesn't matter

stmt.run();
stmt.run(null, 2, "three", new Buffer(Array(4)));
stmt.run(+false);
stmt.run(1, {dos: 2}, 3); // the binding dictionary can go anywhere
stmt.run({a: 1}, {b: 2}); // this will fail at runtime (TypeError)

// $ExpectFlowError
stmt.run(false); // booleans cannot be bound
// $ExpectFlowError
stmt.run({x: {y: "z"}}); // named parameters are not recursive
```

All but the last two success cases (lines 9 and 10) would also have
passed before this change.

wchargin-branch: flow-better-sqlite3-bound-parameters-simplify
2018-09-20 11:31:26 -07:00
William Chargin e572551cd8
mirror: add internal method `_createUpdate` (#868)
Summary:
It’s useful to add this simple function now because the rest of the
commits required to implement #622 will want to use it extensively in
test code. Actual clients of the API will not need to use it, because
the concept of “updates” is an implementation detail: clients will
always provide simple timestamps.

Test Plan:
Unit tests included, with full coverage; run `yarn unit`.

wchargin-branch: mirror-createupdate
2018-09-20 11:12:21 -07:00
Dandelion Mané cdceedef8d
Display urls in the cred explorer (#860)
This commit modifies the plugin adapter's `nodeDescription` method so
that it may return a React node.

This enables the GitHub plugin's `nodeDescription` method to include
hyperlinks directly to the referenced content on GitHub. This makes
examining e.g. comment cred much easier.

I've also made two other changes to the descriptions:
- Pull requests diffs now color-encode the additions and deletions
- Descriptions for comments and reviews no longer include the authors

The Git plugin's behavior is unchanged.

Test plan:
I loaded a large repository in the cred explorer and verified that
exploring comments and pulls and issues is much easier. The descriptions
are as expected for every category of node. Snapshot tests updated.

Fixes #590.
2018-09-20 10:48:05 -07:00