diff options
author | Sean McGivern <sean@gitlab.com> | 2019-07-11 08:06:36 +0000 |
---|---|---|
committer | Sean McGivern <sean@gitlab.com> | 2019-07-11 08:06:36 +0000 |
commit | 836dc2c22002c5d593aa7d3004fdfb3a50f3e408 (patch) | |
tree | 210dc43a22594bcbc5b40e421b7b56b7d31a5e83 | |
parent | 3a55ba7de49a1e3ce54bbf7b10640d66ed5af0bc (diff) | |
parent | f0683aab0512c54c09f6dd2c245bd27fdde6bc16 (diff) | |
download | gitlab-ce-836dc2c22002c5d593aa7d3004fdfb3a50f3e408.tar.gz |
Merge branch 'issue_57694' into 'master'
Improve Graphql Docs
Closes #57694
See merge request gitlab-org/gitlab-ce!29998
-rw-r--r-- | Gemfile | 1 | ||||
-rw-r--r-- | Gemfile.lock | 12 | ||||
-rw-r--r-- | doc/api/graphql/index.md | 6 | ||||
-rw-r--r-- | doc/api/graphql/reference/index.md | 507 | ||||
-rw-r--r-- | lib/gitlab/graphql/docs/helper.rb | 50 | ||||
-rw-r--r-- | lib/gitlab/graphql/docs/renderer.rb | 43 | ||||
-rw-r--r-- | lib/gitlab/graphql/docs/templates/default.md.haml | 25 | ||||
-rw-r--r-- | lib/tasks/gitlab/graphql.rake | 26 |
8 files changed, 670 insertions, 0 deletions
@@ -84,6 +84,7 @@ gem 'rack-cors', '~> 1.0.0', require: 'rack/cors' gem 'graphql', '~> 1.8.0' gem 'graphiql-rails', '~> 1.4.10' gem 'apollo_upload_server', '~> 2.0.0.beta3' +gem 'graphql-docs', '~> 1.6.0', group: [:development, :test] # Disable strong_params so that Mash does not respond to :permitted? gem 'hashie-forbidden_attributes' diff --git a/Gemfile.lock b/Gemfile.lock index 1f4705dd173..1a3b3b8e125 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -216,6 +216,8 @@ GEM excon (0.62.0) execjs (2.6.0) expression_parser (0.9.0) + extended-markdown-filter (0.6.0) + html-pipeline (~> 2.0) factory_bot (4.8.2) activesupport (>= 3.0.0) factory_bot_rails (4.8.2) @@ -290,6 +292,7 @@ GEM fuubar (2.2.0) rspec-core (~> 3.0) ruby-progressbar (~> 1.4) + gemoji (3.0.1) gemojione (3.3.0) json get_process_mem (0.2.3) @@ -370,6 +373,14 @@ GEM railties sprockets-rails graphql (1.8.1) + graphql-docs (1.6.0) + commonmarker (~> 0.16) + escape_utils (~> 1.2) + extended-markdown-filter (~> 0.4) + gemoji (~> 3.0) + graphql (~> 1.6) + html-pipeline (~> 2.8) + sass (~> 3.4) grpc (1.19.0) google-protobuf (~> 3.1) googleapis-common-protos-types (~> 1.0.0) @@ -1118,6 +1129,7 @@ DEPENDENCIES grape_logging (~> 1.7) graphiql-rails (~> 1.4.10) graphql (~> 1.8.0) + graphql-docs (~> 1.6.0) grpc (~> 1.19.0) haml_lint (~> 0.31.0) hamlit (~> 2.8.8) diff --git a/doc/api/graphql/index.md b/doc/api/graphql/index.md index 4e4b9418e47..bdc7c1959d2 100644 --- a/doc/api/graphql/index.md +++ b/doc/api/graphql/index.md @@ -47,6 +47,12 @@ info about multiplexed queries is also available for [graphql-ruby](https://graphql-ruby.org/queries/multiplex.html) the library GitLab uses on the backend. +## Reference + +GitLab's GraphQL reference [is available](reference/index.md). + +It is automatically generated from GitLab's GraphQL schema and embedded in a Markdown file. + ## GraphiQL The API can be explored by using the GraphiQL IDE, it is available on your diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md new file mode 100644 index 00000000000..2d3bec4ff67 --- /dev/null +++ b/doc/api/graphql/reference/index.md @@ -0,0 +1,507 @@ +<!--- + This documentation is auto generated by a script. + + Please do not edit this file directly, check compile_docs task on lib/tasks/gitlab/graphql.rake. +---> + +# GraphQL API Resources + +This documentation is self-generated based on GitLab current GraphQL schema. + +The API can be explored interactively using the [GraphiQL IDE](../index.md#graphiql). + +## Objects + +### AddAwardEmojiPayload + +| Name | Type | Description | +| --- | ---- | ---------- | +| `clientMutationId` | String | A unique identifier for the client performing the mutation. | +| `errors` | String! => Array | Reasons why the mutation failed. | +| `awardEmoji` | AwardEmoji | The award emoji after mutation | + +### AwardEmoji + +| Name | Type | Description | +| --- | ---- | ---------- | +| `name` | String! | The emoji name | +| `description` | String! | The emoji description | +| `unicode` | String! | The emoji in unicode | +| `emoji` | String! | The emoji as an icon | +| `unicodeVersion` | String! | The unicode version for this emoji | +| `user` | User! | The user who awarded the emoji | + +### Blob + +| Name | Type | Description | +| --- | ---- | ---------- | +| `id` | ID! | | +| `name` | String! | | +| `type` | EntryType! | | +| `path` | String! | | +| `flatPath` | String! | | +| `webUrl` | String | | +| `lfsOid` | String | | + +### Commit + +| Name | Type | Description | +| --- | ---- | ---------- | +| `id` | ID! | | +| `sha` | String! | | +| `title` | String | | +| `description` | String | | +| `message` | String | | +| `authoredDate` | Time | | +| `webUrl` | String! | | +| `author` | User | | +| `latestPipeline` | Pipeline | Latest pipeline for this commit | + +### DetailedStatus + +| Name | Type | Description | +| --- | ---- | ---------- | +| `group` | String! | | +| `icon` | String! | | +| `favicon` | String! | | +| `detailsPath` | String! | | +| `hasDetails` | Boolean! | | +| `label` | String! | | +| `text` | String! | | +| `tooltip` | String! | | + +### DiffPosition + +| Name | Type | Description | +| --- | ---- | ---------- | +| `headSha` | String! | The sha of the head at the time the comment was made | +| `baseSha` | String | The merge base of the branch the comment was made on | +| `startSha` | String! | The sha of the branch being compared against | +| `filePath` | String! | The path of the file that was changed | +| `oldPath` | String | The path of the file on the start sha. | +| `newPath` | String | The path of the file on the head sha. | +| `positionType` | DiffPositionType! | | +| `oldLine` | Int | The line on start sha that was changed | +| `newLine` | Int | The line on head sha that was changed | +| `x` | Int | The X postion on which the comment was made | +| `y` | Int | The Y position on which the comment was made | +| `width` | Int | The total width of the image | +| `height` | Int | The total height of the image | + +### Discussion + +| Name | Type | Description | +| --- | ---- | ---------- | +| `id` | ID! | | +| `createdAt` | Time! | | + +### Group + +| Name | Type | Description | +| --- | ---- | ---------- | +| `id` | ID! | | +| `name` | String! | | +| `path` | String! | | +| `fullName` | String! | | +| `fullPath` | ID! | | +| `description` | String | | +| `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` | +| `visibility` | String | | +| `lfsEnabled` | Boolean | | +| `requestAccessEnabled` | Boolean | | +| `userPermissions` | GroupPermissions! | Permissions for the current user on the resource | +| `webUrl` | String! | | +| `avatarUrl` | String | | +| `parent` | Group | | + +### GroupPermissions + +| Name | Type | Description | +| --- | ---- | ---------- | +| `readGroup` | Boolean! | Whether or not a user can perform `read_group` on this resource | + +### Issue + +| Name | Type | Description | +| --- | ---- | ---------- | +| `userPermissions` | IssuePermissions! | Permissions for the current user on the resource | +| `iid` | ID! | | +| `title` | String! | | +| `titleHtml` | String | The GitLab Flavored Markdown rendering of `title` | +| `description` | String | | +| `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` | +| `state` | IssueState! | | +| `reference` | String! | | +| `author` | User! | | +| `milestone` | Milestone | | +| `dueDate` | Time | | +| `confidential` | Boolean! | | +| `discussionLocked` | Boolean! | | +| `upvotes` | Int! | | +| `downvotes` | Int! | | +| `userNotesCount` | Int! | | +| `webPath` | String! | | +| `webUrl` | String! | | +| `relativePosition` | Int | | +| `closedAt` | Time | | +| `createdAt` | Time! | | +| `updatedAt` | Time! | | +| `taskCompletionStatus` | TaskCompletionStatus! | | + +### IssuePermissions + +| Name | Type | Description | +| --- | ---- | ---------- | +| `readIssue` | Boolean! | Whether or not a user can perform `read_issue` on this resource | +| `adminIssue` | Boolean! | Whether or not a user can perform `admin_issue` on this resource | +| `updateIssue` | Boolean! | Whether or not a user can perform `update_issue` on this resource | +| `createNote` | Boolean! | Whether or not a user can perform `create_note` on this resource | +| `reopenIssue` | Boolean! | Whether or not a user can perform `reopen_issue` on this resource | + +### Label + +| Name | Type | Description | +| --- | ---- | ---------- | +| `description` | String | | +| `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` | +| `title` | String! | | +| `color` | String! | | +| `textColor` | String! | | + +### MergeRequest + +| Name | Type | Description | +| --- | ---- | ---------- | +| `userPermissions` | MergeRequestPermissions! | Permissions for the current user on the resource | +| `id` | ID! | | +| `iid` | String! | | +| `title` | String! | | +| `titleHtml` | String | The GitLab Flavored Markdown rendering of `title` | +| `description` | String | | +| `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` | +| `state` | MergeRequestState! | | +| `createdAt` | Time! | | +| `updatedAt` | Time! | | +| `sourceProject` | Project | | +| `targetProject` | Project! | | +| `project` | Project! | | +| `projectId` | Int! | | +| `sourceProjectId` | Int | | +| `targetProjectId` | Int! | | +| `sourceBranch` | String! | | +| `targetBranch` | String! | | +| `workInProgress` | Boolean! | | +| `mergeWhenPipelineSucceeds` | Boolean | | +| `diffHeadSha` | String | | +| `mergeCommitSha` | String | | +| `userNotesCount` | Int | | +| `shouldRemoveSourceBranch` | Boolean | | +| `forceRemoveSourceBranch` | Boolean | | +| `mergeStatus` | String | | +| `inProgressMergeCommitSha` | String | | +| `mergeError` | String | | +| `allowCollaboration` | Boolean | | +| `shouldBeRebased` | Boolean! | | +| `rebaseCommitSha` | String | | +| `rebaseInProgress` | Boolean! | | +| `mergeCommitMessage` | String | | +| `defaultMergeCommitMessage` | String | | +| `mergeOngoing` | Boolean! | | +| `sourceBranchExists` | Boolean! | | +| `mergeableDiscussionsState` | Boolean | | +| `webUrl` | String | | +| `upvotes` | Int! | | +| `downvotes` | Int! | | +| `subscribed` | Boolean! | | +| `headPipeline` | Pipeline | | +| `taskCompletionStatus` | TaskCompletionStatus! | | + +### MergeRequestPermissions + +| Name | Type | Description | +| --- | ---- | ---------- | +| `readMergeRequest` | Boolean! | Whether or not a user can perform `read_merge_request` on this resource | +| `adminMergeRequest` | Boolean! | Whether or not a user can perform `admin_merge_request` on this resource | +| `updateMergeRequest` | Boolean! | Whether or not a user can perform `update_merge_request` on this resource | +| `createNote` | Boolean! | Whether or not a user can perform `create_note` on this resource | +| `pushToSourceBranch` | Boolean! | Whether or not a user can perform `push_to_source_branch` on this resource | +| `removeSourceBranch` | Boolean! | Whether or not a user can perform `remove_source_branch` on this resource | +| `cherryPickOnCurrentMergeRequest` | Boolean! | Whether or not a user can perform `cherry_pick_on_current_merge_request` on this resource | +| `revertOnCurrentMergeRequest` | Boolean! | Whether or not a user can perform `revert_on_current_merge_request` on this resource | + +### MergeRequestSetWipPayload + +| Name | Type | Description | +| --- | ---- | ---------- | +| `clientMutationId` | String | A unique identifier for the client performing the mutation. | +| `errors` | String! => Array | Reasons why the mutation failed. | +| `mergeRequest` | MergeRequest | The merge request after mutation | + +### Metadata + +| Name | Type | Description | +| --- | ---- | ---------- | +| `version` | String! | | +| `revision` | String! | | + +### Milestone + +| Name | Type | Description | +| --- | ---- | ---------- | +| `description` | String | | +| `title` | String! | | +| `state` | String! | | +| `dueDate` | Time | | +| `startDate` | Time | | +| `createdAt` | Time! | | +| `updatedAt` | Time! | | + +### Namespace + +| Name | Type | Description | +| --- | ---- | ---------- | +| `id` | ID! | | +| `name` | String! | | +| `path` | String! | | +| `fullName` | String! | | +| `fullPath` | ID! | | +| `description` | String | | +| `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` | +| `visibility` | String | | +| `lfsEnabled` | Boolean | | +| `requestAccessEnabled` | Boolean | | + +### Note + +| Name | Type | Description | +| --- | ---- | ---------- | +| `userPermissions` | NotePermissions! | Permissions for the current user on the resource | +| `id` | ID! | | +| `project` | Project | The project this note is associated to | +| `author` | User! | The user who wrote this note | +| `resolvedBy` | User | The user that resolved the discussion | +| `system` | Boolean! | Whether or not this note was created by the system or by a user | +| `body` | String! | The content note itself | +| `bodyHtml` | String | The GitLab Flavored Markdown rendering of `note` | +| `createdAt` | Time! | | +| `updatedAt` | Time! | | +| `discussion` | Discussion | The discussion this note is a part of | +| `resolvable` | Boolean! | | +| `resolvedAt` | Time | The time the discussion was resolved | +| `position` | DiffPosition | The position of this note on a diff | + +### NotePermissions + +| Name | Type | Description | +| --- | ---- | ---------- | +| `readNote` | Boolean! | Whether or not a user can perform `read_note` on this resource | +| `createNote` | Boolean! | Whether or not a user can perform `create_note` on this resource | +| `adminNote` | Boolean! | Whether or not a user can perform `admin_note` on this resource | +| `resolveNote` | Boolean! | Whether or not a user can perform `resolve_note` on this resource | +| `awardEmoji` | Boolean! | Whether or not a user can perform `award_emoji` on this resource | + +### PageInfo + +| Name | Type | Description | +| --- | ---- | ---------- | +| `hasNextPage` | Boolean! | When paginating forwards, are there more items? | +| `hasPreviousPage` | Boolean! | When paginating backwards, are there more items? | +| `startCursor` | String | When paginating backwards, the cursor to continue. | +| `endCursor` | String | When paginating forwards, the cursor to continue. | + +### Pipeline + +| Name | Type | Description | +| --- | ---- | ---------- | +| `userPermissions` | PipelinePermissions! | Permissions for the current user on the resource | +| `id` | ID! | | +| `iid` | String! | | +| `sha` | String! | | +| `beforeSha` | String | | +| `status` | PipelineStatusEnum! | | +| `detailedStatus` | DetailedStatus! | | +| `duration` | Int | Duration of the pipeline in seconds | +| `coverage` | Float | Coverage percentage | +| `createdAt` | Time! | | +| `updatedAt` | Time! | | +| `startedAt` | Time | | +| `finishedAt` | Time | | +| `committedAt` | Time | | + +### PipelinePermissions + +| Name | Type | Description | +| --- | ---- | ---------- | +| `updatePipeline` | Boolean! | Whether or not a user can perform `update_pipeline` on this resource | +| `adminPipeline` | Boolean! | Whether or not a user can perform `admin_pipeline` on this resource | +| `destroyPipeline` | Boolean! | Whether or not a user can perform `destroy_pipeline` on this resource | + +### Project + +| Name | Type | Description | +| --- | ---- | ---------- | +| `userPermissions` | ProjectPermissions! | Permissions for the current user on the resource | +| `id` | ID! | | +| `fullPath` | ID! | | +| `path` | String! | | +| `nameWithNamespace` | String! | | +| `name` | String! | | +| `description` | String | | +| `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` | +| `tagList` | String | | +| `sshUrlToRepo` | String | | +| `httpUrlToRepo` | String | | +| `webUrl` | String | | +| `starCount` | Int! | | +| `forksCount` | Int! | | +| `createdAt` | Time | | +| `lastActivityAt` | Time | | +| `archived` | Boolean | | +| `visibility` | String | | +| `containerRegistryEnabled` | Boolean | | +| `sharedRunnersEnabled` | Boolean | | +| `lfsEnabled` | Boolean | | +| `mergeRequestsFfOnlyEnabled` | Boolean | | +| `avatarUrl` | String | | +| `issuesEnabled` | Boolean | | +| `mergeRequestsEnabled` | Boolean | | +| `wikiEnabled` | Boolean | | +| `snippetsEnabled` | Boolean | | +| `jobsEnabled` | Boolean | | +| `publicJobs` | Boolean | | +| `openIssuesCount` | Int | | +| `importStatus` | String | | +| `onlyAllowMergeIfPipelineSucceeds` | Boolean | | +| `requestAccessEnabled` | Boolean | | +| `onlyAllowMergeIfAllDiscussionsAreResolved` | Boolean | | +| `printingMergeRequestLinkEnabled` | Boolean | | +| `namespace` | Namespace | | +| `group` | Group | | +| `statistics` | ProjectStatistics | | +| `repository` | Repository | | +| `mergeRequest` | MergeRequest | | +| `issue` | Issue | | + +### ProjectPermissions + +| Name | Type | Description | +| --- | ---- | ---------- | +| `changeNamespace` | Boolean! | Whether or not a user can perform `change_namespace` on this resource | +| `changeVisibilityLevel` | Boolean! | Whether or not a user can perform `change_visibility_level` on this resource | +| `renameProject` | Boolean! | Whether or not a user can perform `rename_project` on this resource | +| `removeProject` | Boolean! | Whether or not a user can perform `remove_project` on this resource | +| `archiveProject` | Boolean! | Whether or not a user can perform `archive_project` on this resource | +| `removeForkProject` | Boolean! | Whether or not a user can perform `remove_fork_project` on this resource | +| `removePages` | Boolean! | Whether or not a user can perform `remove_pages` on this resource | +| `readProject` | Boolean! | Whether or not a user can perform `read_project` on this resource | +| `createMergeRequestIn` | Boolean! | Whether or not a user can perform `create_merge_request_in` on this resource | +| `readWiki` | Boolean! | Whether or not a user can perform `read_wiki` on this resource | +| `readProjectMember` | Boolean! | Whether or not a user can perform `read_project_member` on this resource | +| `createIssue` | Boolean! | Whether or not a user can perform `create_issue` on this resource | +| `uploadFile` | Boolean! | Whether or not a user can perform `upload_file` on this resource | +| `readCycleAnalytics` | Boolean! | Whether or not a user can perform `read_cycle_analytics` on this resource | +| `downloadCode` | Boolean! | Whether or not a user can perform `download_code` on this resource | +| `downloadWikiCode` | Boolean! | Whether or not a user can perform `download_wiki_code` on this resource | +| `forkProject` | Boolean! | Whether or not a user can perform `fork_project` on this resource | +| `createProjectSnippet` | Boolean! | Whether or not a user can perform `create_project_snippet` on this resource | +| `readCommitStatus` | Boolean! | Whether or not a user can perform `read_commit_status` on this resource | +| `requestAccess` | Boolean! | Whether or not a user can perform `request_access` on this resource | +| `createPipeline` | Boolean! | Whether or not a user can perform `create_pipeline` on this resource | +| `createPipelineSchedule` | Boolean! | Whether or not a user can perform `create_pipeline_schedule` on this resource | +| `createMergeRequestFrom` | Boolean! | Whether or not a user can perform `create_merge_request_from` on this resource | +| `createWiki` | Boolean! | Whether or not a user can perform `create_wiki` on this resource | +| `pushCode` | Boolean! | Whether or not a user can perform `push_code` on this resource | +| `createDeployment` | Boolean! | Whether or not a user can perform `create_deployment` on this resource | +| `pushToDeleteProtectedBranch` | Boolean! | Whether or not a user can perform `push_to_delete_protected_branch` on this resource | +| `adminWiki` | Boolean! | Whether or not a user can perform `admin_wiki` on this resource | +| `adminProject` | Boolean! | Whether or not a user can perform `admin_project` on this resource | +| `updatePages` | Boolean! | Whether or not a user can perform `update_pages` on this resource | +| `adminRemoteMirror` | Boolean! | Whether or not a user can perform `admin_remote_mirror` on this resource | +| `createLabel` | Boolean! | Whether or not a user can perform `create_label` on this resource | +| `updateWiki` | Boolean! | Whether or not a user can perform `update_wiki` on this resource | +| `destroyWiki` | Boolean! | Whether or not a user can perform `destroy_wiki` on this resource | +| `createPages` | Boolean! | Whether or not a user can perform `create_pages` on this resource | +| `destroyPages` | Boolean! | Whether or not a user can perform `destroy_pages` on this resource | +| `readPagesContent` | Boolean! | Whether or not a user can perform `read_pages_content` on this resource | + +### ProjectStatistics + +| Name | Type | Description | +| --- | ---- | ---------- | +| `commitCount` | Int! | | +| `storageSize` | Int! | | +| `repositorySize` | Int! | | +| `lfsObjectsSize` | Int! | | +| `buildArtifactsSize` | Int! | | +| `packagesSize` | Int! | | +| `wikiSize` | Int | | + +### RemoveAwardEmojiPayload + +| Name | Type | Description | +| --- | ---- | ---------- | +| `clientMutationId` | String | A unique identifier for the client performing the mutation. | +| `errors` | String! => Array | Reasons why the mutation failed. | +| `awardEmoji` | AwardEmoji | The award emoji after mutation | + +### Repository + +| Name | Type | Description | +| --- | ---- | ---------- | +| `rootRef` | String | | +| `empty` | Boolean! | | +| `exists` | Boolean! | | +| `tree` | Tree | | + +### Submodule + +| Name | Type | Description | +| --- | ---- | ---------- | +| `id` | ID! | | +| `name` | String! | | +| `type` | EntryType! | | +| `path` | String! | | +| `flatPath` | String! | | + +### TaskCompletionStatus + +| Name | Type | Description | +| --- | ---- | ---------- | +| `count` | Int! | | +| `completedCount` | Int! | | + +### ToggleAwardEmojiPayload + +| Name | Type | Description | +| --- | ---- | ---------- | +| `clientMutationId` | String | A unique identifier for the client performing the mutation. | +| `errors` | String! => Array | Reasons why the mutation failed. | +| `awardEmoji` | AwardEmoji | The award emoji after mutation | +| `toggledOn` | Boolean! | True when the emoji was awarded, false when it was removed | + +### Tree + +| Name | Type | Description | +| --- | ---- | ---------- | +| `lastCommit` | Commit | | + +### TreeEntry + +| Name | Type | Description | +| --- | ---- | ---------- | +| `id` | ID! | | +| `name` | String! | | +| `type` | EntryType! | | +| `path` | String! | | +| `flatPath` | String! | | +| `webUrl` | String | | + +### User + +| Name | Type | Description | +| --- | ---- | ---------- | +| `name` | String! | | +| `username` | String! | | +| `avatarUrl` | String! | | +| `webUrl` | String! | | + diff --git a/lib/gitlab/graphql/docs/helper.rb b/lib/gitlab/graphql/docs/helper.rb new file mode 100644 index 00000000000..ac2a78c0f28 --- /dev/null +++ b/lib/gitlab/graphql/docs/helper.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +return if Rails.env.production? + +module Gitlab + module Graphql + module Docs + # Helper with functions to be used by HAML templates + # This includes graphql-docs gem helpers class. + # You can check the included module on: https://github.com/gjtorikian/graphql-docs/blob/v1.6.0/lib/graphql-docs/helpers.rb + module Helper + include GraphQLDocs::Helpers + + def auto_generated_comment + <<-MD.strip_heredoc + <!--- + This documentation is auto generated by a script. + + Please do not edit this file directly, check compile_docs task on lib/tasks/gitlab/graphql.rake. + ---> + MD + end + + # Some fields types are arrays of other types and are displayed + # on docs wrapped in square brackets, for example: [String!]. + # This makes GitLab docs renderer thinks they are links so here + # we change them to be rendered as: String! => Array. + def render_field_type(type) + array_type = type[/\[(.+)\]/, 1] + + if array_type + "#{array_type} => Array" + else + type + end + end + + # We are ignoring connections and built in types for now, + # they should be added when queries are generated. + def objects + graphql_object_types.select do |object_type| + !object_type[:name]["Connection"] && + !object_type[:name]["Edge"] && + !object_type[:name]["__"] + end + end + end + end + end +end diff --git a/lib/gitlab/graphql/docs/renderer.rb b/lib/gitlab/graphql/docs/renderer.rb new file mode 100644 index 00000000000..f47a372aa19 --- /dev/null +++ b/lib/gitlab/graphql/docs/renderer.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +return if Rails.env.production? + +module Gitlab + module Graphql + module Docs + # Gitlab renderer for graphql-docs. + # Uses HAML templates to parse markdown and generate .md files. + # It uses graphql-docs helpers and schema parser, more information in https://github.com/gjtorikian/graphql-docs. + # + # Arguments: + # schema - the GraphQL schema defition. For GitLab should be: GitlabSchema.graphql_definition + # output_dir: The folder where the markdown files will be saved + # template: The path of the haml template to be parsed + class Renderer + include Gitlab::Graphql::Docs::Helper + + def initialize(schema, output_dir:, template:) + @output_dir = output_dir + @template = template + @layout = Haml::Engine.new(File.read(template)) + @parsed_schema = GraphQLDocs::Parser.new(schema, {}).parse + end + + def render + contents = @layout.render(self) + + write_file(contents) + end + + private + + def write_file(contents) + filename = File.join(@output_dir, 'index.md') + + FileUtils.mkdir_p(@output_dir) + File.write(filename, contents) + end + end + end + end +end diff --git a/lib/gitlab/graphql/docs/templates/default.md.haml b/lib/gitlab/graphql/docs/templates/default.md.haml new file mode 100644 index 00000000000..cc22d43ab4f --- /dev/null +++ b/lib/gitlab/graphql/docs/templates/default.md.haml @@ -0,0 +1,25 @@ +-# haml-lint:disable UnnecessaryStringOutput + += auto_generated_comment + +:plain + # GraphQL API Resources + + This documentation is self-generated based on GitLab current GraphQL schema. + + The API can be explored interactively using the [GraphiQL IDE](../index.md#graphiql). + + ## Objects +\ +- objects.each do |type| + - unless type[:fields].empty? + = "### #{type[:name]}" + \ + ~ "| Name | Type | Description |" + ~ "| --- | ---- | ---------- |" + - type[:fields].each do |field| + = "| `#{field[:name]}` | #{render_field_type(field[:type][:info])} | #{field[:description]} |" + \ + + + diff --git a/lib/tasks/gitlab/graphql.rake b/lib/tasks/gitlab/graphql.rake new file mode 100644 index 00000000000..c53d55ceea2 --- /dev/null +++ b/lib/tasks/gitlab/graphql.rake @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +return if Rails.env.production? + +namespace :gitlab do + OUTPUT_DIR = Rails.root.join("doc/api/graphql/reference").freeze + TEMPLATES_DIR = 'lib/gitlab/graphql/docs/templates/'.freeze + + namespace :graphql do + desc 'GitLab | Generate GraphQL docs' + task compile_docs: :environment do + renderer = Gitlab::Graphql::Docs::Renderer.new(GitlabSchema.graphql_definition, render_options) + + renderer.render + + puts "Documentation compiled." + end + end +end + +def render_options + { + output_dir: OUTPUT_DIR, + template: Rails.root.join(TEMPLATES_DIR, 'default.md.haml') + } +end |