diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c53e39baac..1668de0c35 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -36,7 +36,8 @@ jobs: strategy: fail-fast: false matrix: - test-group: [content, meta, rendering, routing, unit, links-and-images] + test-group: + [content, meta, rendering, routing, unit, links-and-images, graphql] steps: # Each of these ifs needs to be repeated at each step to make sure the required check still runs # Even if if doesn't do anything diff --git a/.github/workflows/update-graphql-files.yml b/.github/workflows/update-graphql-files.yml index febfcf618c..0ba265a0f7 100644 --- a/.github/workflows/update-graphql-files.yml +++ b/.github/workflows/update-graphql-files.yml @@ -37,20 +37,15 @@ jobs: env: # need to use a token from a user with access to github/github for this step GITHUB_TOKEN: ${{ secrets.ZEKE_PAT_WITH_REPO_AND_WORKFLOW_SCOPE_FOR_REPO_SYNC }} - # technically the changelog should only be updated once per day, but we can safely - # run build-changelog-from-markdown.js in its current form once per hour; when we - # rewrite the changelog script, we may need to run it in a separate workflow on a - # once-per-day schedule; see details in https://github.com/github/docs-internal/issues/12722. run: | script/graphql/update-files.js - script/graphql/build-changelog-from-markdown.js - name: Create pull request id: create-pull-request uses: peter-evans/create-pull-request@938e6aea6f8dbdaced2064e948cb806c77fe87b8 with: # need to use a token with repo and workflow scopes for this step token: ${{ secrets.OCTOMERGER_PAT_WITH_REPO_AND_WORKFLOW_SCOPE }} - commit-message: 'Action ran graphql scripts "update-files" and "build-changelog-from-markdown"' + commit-message: 'Action ran graphql script"update-files"' title: GraphQL schema update body: "Hello! Some GraphQL data in github/github was updated recently. This PR diff --git a/lib/graphql/README.md b/lib/graphql/README.md index bd34672912..00d5b0e110 100644 --- a/lib/graphql/README.md +++ b/lib/graphql/README.md @@ -24,9 +24,6 @@ Generated by `script/graphql/update-files.js`: * `lib/graphql/static/schema-VERSION.json` (separate files per version) * `lib/graphql/static/previews.json` * `lib/graphql/static/upcoming-changes.json` - -Generated by `script/graphql/build-changelog-from-markdown.js`: - * `lib/graphql/static/changelog.json` ## Rendering docs diff --git a/package-lock.json b/package-lock.json index c6a01e1737..cae8206600 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,21 @@ "integrity": "sha512-ZQYitnqiyBc3D+k7LsgSBmMDVkOVidaagDG7j3fOym77jNunWRuYx7VSHa9GNfFZh+zh61xsCjRj4JxMZlDqTA==", "dev": true }, + "@ardatan/aggregate-error": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@ardatan/aggregate-error/-/aggregate-error-0.0.6.tgz", + "integrity": "sha512-vyrkEHG1jrukmzTPtyWB4NLPauUw5bQeg4uhn8f+1SSynmrOcyvlb1GKQjjgoBzElLdfXCRYX8UnBlhklOHYRQ==", + "requires": { + "tslib": "~2.0.1" + }, + "dependencies": { + "tslib": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz", + "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==" + } + } + }, "@babel/code-frame": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", @@ -1187,6 +1202,256 @@ "revalidator": "^0.3.1" } }, + "@graphql-inspector/core": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@graphql-inspector/core/-/core-2.3.0.tgz", + "integrity": "sha512-bxYqAvVK7vDQ0O/ygZ/JNs5XCxSe+DtKwkCsov7RMPoSkkFuHyyC9BDTm6eN57wPwVk5AJ5b5s32oYVTphvELA==", + "requires": { + "dependency-graph": "0.9.0", + "tslib": "^2.0.0" + }, + "dependencies": { + "tslib": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz", + "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==" + } + } + }, + "@graphql-tools/load": { + "version": "6.2.5", + "resolved": "https://registry.npmjs.org/@graphql-tools/load/-/load-6.2.5.tgz", + "integrity": "sha512-TpDgp+id0hhD1iMhdFSgWgWumdI/IpFWwouJeaEhEEAEBkdvH4W9gbBiJBSbPQwMPRNWx8/AZtry0cYKLW4lHg==", + "requires": { + "@graphql-tools/merge": "^6.2.5", + "@graphql-tools/utils": "^7.0.0", + "globby": "11.0.1", + "import-from": "3.0.0", + "is-glob": "4.0.1", + "p-limit": "3.0.2", + "tslib": "~2.0.1", + "unixify": "1.0.0", + "valid-url": "1.0.9" + }, + "dependencies": { + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==" + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "requires": { + "fill-range": "^7.0.1" + } + }, + "fast-glob": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.4.tgz", + "integrity": "sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ==", + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.0", + "merge2": "^1.3.0", + "micromatch": "^4.0.2", + "picomatch": "^2.2.1" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "requires": { + "is-glob": "^4.0.1" + } + }, + "globby": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.1.tgz", + "integrity": "sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ==", + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" + } + }, + "ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==" + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "requires": { + "is-extglob": "^2.1.1" + } + }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, + "p-limit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.0.2.tgz", + "integrity": "sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg==", + "requires": { + "p-try": "^2.0.0" + } + }, + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==" + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "requires": { + "is-number": "^7.0.0" + } + }, + "tslib": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz", + "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==" + } + } + }, + "@graphql-tools/merge": { + "version": "6.2.5", + "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-6.2.5.tgz", + "integrity": "sha512-T2UEm7L5MeS1ggbGKBkdV9kTqLqSHQM13RrjPzIAYzkFL/mK837sf+oq8h2+R8B+senuHX8akUhMTcU85kcMvw==", + "requires": { + "@graphql-tools/schema": "^7.0.0", + "@graphql-tools/utils": "^7.0.0", + "tslib": "~2.0.1" + }, + "dependencies": { + "tslib": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz", + "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==" + } + } + }, + "@graphql-tools/schema": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-7.0.0.tgz", + "integrity": "sha512-yDKgoT2+Uf3cdLYmiFB9lRIGsB6lZhILtCXHgZigYgURExrEPmfj3ZyszfEpPKYcPmKaO9FI4coDhIN0Toxl3w==", + "requires": { + "@graphql-tools/utils": "^7.0.0", + "tslib": "~2.0.1" + }, + "dependencies": { + "tslib": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz", + "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==" + } + } + }, + "@graphql-tools/utils": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-7.0.2.tgz", + "integrity": "sha512-VQQ7krHeoXO0FS3qbWsb/vZb8c8oyiCYPIH4RSgeK9SKOUpatWYt3DW4jmLmyHZLVVMk0yjUbsOhKTBEMejKSA==", + "requires": { + "@ardatan/aggregate-error": "0.0.6", + "camel-case": "4.1.1", + "tslib": "~2.0.1" + }, + "dependencies": { + "camel-case": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.1.tgz", + "integrity": "sha512-7fa2WcG4fYFkclIvEmxBbTvmibwF2/agfEBc6q3lOpVu0A13ltLsA+Hr/8Hp6kp5f+G7hKi6t8lys6XxP+1K6Q==", + "requires": { + "pascal-case": "^3.1.1", + "tslib": "^1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + } + } + }, + "lower-case": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.1.tgz", + "integrity": "sha512-LiWgfDLLb1dwbFQZsSglpRj+1ctGnayXz3Uv0/WO8n558JycT5fg6zkNcnW0G68Nn0aEldTFeEfmjCfmqry/rQ==", + "requires": { + "tslib": "^1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + } + } + }, + "no-case": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.3.tgz", + "integrity": "sha512-ehY/mVQCf9BL0gKfsJBvFJen+1V//U+0HQMPrWct40ixE4jnv0bfvxDbWtAHL9EcaPEOJHVVYKoQn1TlZUB8Tw==", + "requires": { + "lower-case": "^2.0.1", + "tslib": "^1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + } + } + }, + "pascal-case": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.1.tgz", + "integrity": "sha512-XIeHKqIrsquVTQL2crjq3NfJUxmdLasn3TYOU0VBM+UX2a6ztAWBlJQBePLGY7VHW8+2dRadeIPK5+KImwTxQA==", + "requires": { + "no-case": "^3.0.3", + "tslib": "^1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + } + } + }, + "tslib": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz", + "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==" + } + } + }, "@hapi/address": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/@hapi/address/-/address-2.1.4.tgz", @@ -4586,9 +4851,9 @@ "dev": true }, "ccount": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.1.0.tgz", - "integrity": "sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg==" + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.0.5.tgz", + "integrity": "sha512-MOli1W+nfbPLlKEhInaxhRdp7KVLFxLN5ykwzHgLsLI3H3gs5jjFAK4Eoj3OzzcxCtumDaI8onoVDeQyWaNTkw==" }, "chalk": { "version": "4.1.0", @@ -6242,6 +6507,11 @@ } } }, + "dependency-graph": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.9.0.tgz", + "integrity": "sha512-9YLIBURXj4DJMFALxXw9K3Y3rwb5Fk0X5/8ipCzaN84+gKxoHK43tVKRNakCQbiEx07E8Uwhuq21BpUagFhZ8w==" + }, "deprecation": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", @@ -6262,9 +6532,9 @@ "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, "detab": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/detab/-/detab-2.0.4.tgz", - "integrity": "sha512-8zdsQA5bIkoRECvCrNKPla84lyoR7DSAyf7p0YgXzBO9PDJx8KntPUay7NS6yp+KdxdVtiE5SpHKtbp2ZQyA9g==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detab/-/detab-2.0.3.tgz", + "integrity": "sha512-Up8P0clUVwq0FnFjDclzZsy9PadzRn5FFxrr47tQQvMHqyiFYVbpH8oXDzWtF0Q7pYy3l+RPmtBl+BsFF6wH0A==", "requires": { "repeat-string": "^1.5.4" } @@ -9660,6 +9930,13 @@ "vfile": "^4.0.0", "vfile-location": "^3.2.0", "web-namespaces": "^1.0.0" + }, + "dependencies": { + "vfile-location": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-3.2.0.tgz", + "integrity": "sha512-aLEIZKv/oxuCDZ8lkJGhuhztf/BW4M+iHdCwglA/eWc+vtuRFJj8EtgceYFX4LRjOhCAAiNHsKGssC6onJ+jbA==" + } } }, "hast-util-has-property": { @@ -9673,9 +9950,9 @@ "integrity": "sha512-oUmNua0bFbdrD/ELDSSEadRVtWZOf3iF6Lbv81naqsIV99RnSCieTbWuWCY8BAeEfKJTKl0gRdokv+dELutHGQ==" }, "hast-util-parse-selector": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz", - "integrity": "sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==" + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.4.tgz", + "integrity": "sha512-gW3sxfynIvZApL4L07wryYF4+C9VvH3AUi7LAnVXV4MneGEgwOByXvFo18BgmTWnm7oHAe874jKbIB1YhHSIzA==" }, "hast-util-raw": { "version": "5.0.2", @@ -9859,9 +10136,9 @@ "integrity": "sha512-Io1zA2yOA1YJslkr+AJlWSf2yWFkKjvkcL9Ni1XSUqnGLr/qRQe2UI3Cn/J9MsJht7yEVCe0SscY1HgVMujbgg==" }, "highlight.js": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.4.0.tgz", - "integrity": "sha512-EfrUGcQ63oLJbj0J0RI9ebX6TAITbsDBLbsjr881L/X5fMO9+oadKzEF21C7R3ULKG6Gv3uoab2HiqVJa/4+oA==" + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.3.1.tgz", + "integrity": "sha512-jeW8rdPdhshYKObedYg5XGbpVgb1/DT4AHvDFXhkU7UnGSIjy9kkJ7zHG7qplhFHMitTSzh5/iClKQk3Kb2RFQ==" }, "highlightjs-graphql": { "version": "1.0.2", @@ -10282,6 +10559,21 @@ "resolve-from": "^4.0.0" } }, + "import-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/import-from/-/import-from-3.0.0.tgz", + "integrity": "sha512-CiuXOFFSzkU5x/CR0+z7T91Iht4CXgfCxVOFRhh2Zyhg5wOpWvvDLQUsWl+gcN+QscYBjez8hDCt85O7RLDttQ==", + "requires": { + "resolve-from": "^5.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==" + } + } + }, "import-lazy": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", @@ -14984,12 +15276,12 @@ "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" }, "lowlight": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/lowlight/-/lowlight-1.17.0.tgz", - "integrity": "sha512-vmtBgYKD+QVNy7tIa7ulz5d//Il9R4MooOVh4nkOf9R9Cb/Dk5TXMSTieg/vDulkBkIWj59/BIlyFQxT9X1oAQ==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/lowlight/-/lowlight-1.16.0.tgz", + "integrity": "sha512-ECLdzIJvBEjK4ef51sWiGZyz21yx4IEPaF/62DRxLehoOHkWqN3OsLB1GUMfc6Mcf87rR5eW7z6lI9cNEXZDsQ==", "requires": { "fault": "^1.0.0", - "highlight.js": "~10.4.0" + "highlight.js": "~10.3.0" } }, "macos-release": { @@ -15650,6 +15942,12 @@ "integrity": "sha1-mDaL6wnfdT9k9m2U5VNql7NqJDA=", "dev": true }, + "mockdate": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mockdate/-/mockdate-3.0.2.tgz", + "integrity": "sha512-ldfYSUW1ocqSHGTK6rrODUiqAFPGAg0xaHqYJ5tvj1hQyFsjuHpuWgWFTZWwDVlzougN/s2/mhDr8r5nY5xDpA==", + "dev": true + }, "morgan": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.1.tgz", @@ -17736,13 +18034,6 @@ "unist-util-remove-position": "^1.0.0", "vfile-location": "^2.0.0", "xtend": "^4.0.1" - }, - "dependencies": { - "vfile-location": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.6.tgz", - "integrity": "sha512-sSFdyCP3G6Ka0CEmN83A2YCMKIieHx0EDaj5IDP4g1pa5ZJ4FJDvpO0WODLxo4LUX4oe52gmSCK7Jw4SBghqxA==" - } } }, "remark-rehype": { @@ -19909,9 +20200,9 @@ "integrity": "sha512-C4+gOpvmxaSMKuEf9Qc134F1ZuOHVXKRbtEflf4NTtuuJDEIJ9p5PXsalL8SkeRw+qit1Mo+yuvMPAKwWg/1hA==" }, "trim-trailing-lines": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.4.tgz", - "integrity": "sha512-rjUWSqnfTNrjbB9NQWfPMH/xRK1deHeGsHoVfpxJ++XeYXE0d6B1En37AHfw3jtfTU7dzMzZL2jjpe8Qb5gLIQ==" + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.3.tgz", + "integrity": "sha512-4ku0mmjXifQcTVfYDfR5lpgV7zVqPg6zV9rdZmwOPqq0+Zq19xDqEgagqVbc4pOOShbncuAOIs59R3+3gcF3ZA==" }, "trough": { "version": "1.0.5", @@ -20197,9 +20488,9 @@ } }, "unist-util-generated": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.6.tgz", - "integrity": "sha512-cln2Mm1/CZzN5ttGK7vkoGw+RZ8VcUH6BtGbq98DDtRGquAAOXig1mrBQYelOwMXYS8rK+vZDyyojSjp7JX+Lg==" + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.5.tgz", + "integrity": "sha512-1TC+NxQa4N9pNdayCYA1EGUOCAO0Le3fVp7Jzns6lnua/mYgwHo0tz5WUAfrdpNch1RZLHc61VZ1SDgrtNXLSw==" }, "unist-util-is": { "version": "3.0.0", @@ -20267,6 +20558,14 @@ "nan": "^2.13.2" } }, + "unixify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unixify/-/unixify-1.0.0.tgz", + "integrity": "sha1-OmQcjC/7zk2mg6XHDwOkYpQMIJA=", + "requires": { + "normalize-path": "^2.1.1" + } + }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -20518,6 +20817,11 @@ } } }, + "valid-url": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/valid-url/-/valid-url-1.0.9.tgz", + "integrity": "sha1-HBRHm0DxOXp1eC8RXkCGRHQzogA=" + }, "validate-npm-package-license": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", @@ -20564,16 +20868,16 @@ }, "dependencies": { "is-buffer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", - "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==" + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", + "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==" } } }, "vfile-location": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-3.2.0.tgz", - "integrity": "sha512-aLEIZKv/oxuCDZ8lkJGhuhztf/BW4M+iHdCwglA/eWc+vtuRFJj8EtgceYFX4LRjOhCAAiNHsKGssC6onJ+jbA==" + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.6.tgz", + "integrity": "sha512-sSFdyCP3G6Ka0CEmN83A2YCMKIieHx0EDaj5IDP4g1pa5ZJ4FJDvpO0WODLxo4LUX4oe52gmSCK7Jw4SBghqxA==" }, "vfile-message": { "version": "2.0.4", diff --git a/package.json b/package.json index 248c4d753a..934a935fba 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,8 @@ "@babel/runtime": "^7.11.2", "@github-docs/data-directory": "^1.2.0", "@github-docs/frontmatter": "^1.3.1", + "@graphql-inspector/core": "^2.3.0", + "@graphql-tools/load": "^6.2.5", "@octokit/rest": "^16.38.1", "@primer/css": "^15.1.0", "@primer/octicons": "^11.0.0", @@ -119,6 +121,7 @@ "make-promises-safe": "^5.1.0", "mime": "^2.4.4", "mock-express-response": "^0.2.2", + "mockdate": "^3.0.2", "nock": "^13.0.4", "nodemon": "^2.0.4", "npm-merge-driver-install": "^2.0.0", diff --git a/script/README.md b/script/README.md index 8b78476c08..ceae876753 100644 --- a/script/README.md +++ b/script/README.md @@ -193,12 +193,6 @@ Given: /github/getting-started-with-github/using-github Returns: /free-pro-team@ Given: /enterprise/admin/installation/upgrading-github-enterprise Returns: /enterprise-server@2.22/admin/installation/upgrading-github-enterprise ---- - - -### [`graphql/build-changelog-from-markdown.js`](graphql/build-changelog-from-markdown.js) - - --- @@ -488,5 +482,3 @@ This script is used by other scripts to update temporary AWS credentials and aut Use this script to upload individual or batched asset files to a versioned S3 bucket. Run `upload-images-to-s3.js --help` for usage details. --- - - diff --git a/script/graphql/README.md b/script/graphql/README.md index da3904a448..4588357efd 100644 --- a/script/graphql/README.md +++ b/script/graphql/README.md @@ -1,10 +1,9 @@ # GraphQL scripts A [scheduled workflow](../.github/workflows/update-graphql-files.yml) runs the following -scripts on an hourly basis: +scripts on a daily basis: ``` script/graphql/update-files.js -script/graphql/build-changelog-from-markdown.js ``` These scripts update the [static JSON files](../../lib/graphql/static) used to render GraphQL docs. See the [`lib/graphql/README`](../../lib/graphql/README.md) diff --git a/script/graphql/build-changelog-from-markdown.js b/script/graphql/build-changelog-from-markdown.js deleted file mode 100755 index 15d5fb3e52..0000000000 --- a/script/graphql/build-changelog-from-markdown.js +++ /dev/null @@ -1,130 +0,0 @@ -#!/usr/bin/env node - -const fs = require('fs') -const path = require('path') -const { sortBy, reverse } = require('lodash') -const frontmatter = require('../../lib/frontmatter') -const git = require('../../lib/git-utils') -const staticChangelog = path.join(process.cwd(), 'lib/graphql/static/changelog.json') - -// values for api -const owner = 'github' -const repo = 'internal-developer.github.com' -const ref = 'heads/master' - -const previewsBaseLink = '/graphql/overview/schema-previews' - -const changesList = /(\n*[\s\S]*?\n)$/m - -// until 2018-02-14, all changelogs used the phrase 'The following changes were made to the GraphQL schema' -const schemaRegexGlobal = new RegExp('(The GraphQL schema includes these changes:|The following changes were made to the GraphQL schema:)' + changesList.source, 'mg') -const previewRegexGlobal = new RegExp('(The .*?preview.*? includes these changes:)' + changesList.source, 'mg') -const upcomingRegexGlobal = new RegExp('(The following changes will be made to the schema:)' + changesList.source, 'mg') - -const schemaRegexSingle = new RegExp(schemaRegexGlobal.source, 'm') -const previewRegexSingle = new RegExp(previewRegexGlobal.source, 'm') -const upcomingRegexSingle = new RegExp(upcomingRegexGlobal.source, 'm') - -main() - -async function main () { - const tree = await git.getTree(owner, repo, ref) - const changelogFiles = tree.filter(entry => entry.path.includes('v4/changelog') && entry.type === 'blob') - - const changelog = [] - - await Promise.all(changelogFiles.map(async (blob) => { - // get the contents of `content/v4/changelog/*` files from internal-developer.github.com - const contents = await git.getContentsForBlob(owner, repo, blob) - const file = blob.path - - if (file.endsWith('index.html')) return - process.stdout.write('.') - - const date = path.basename(file).replace('-schema-changes.md', '') - const { content } = frontmatter(contents) - - // match each section title and list of changes - const schemaChangesMatches = content.match(schemaRegexGlobal) - const previewChangesMatches = content.match(previewRegexGlobal) - const upcomingChangesMatches = content.match(upcomingRegexGlobal) - - const entry = {} - - // do a little formatting cleanup - entry.date = date - entry.schemaChanges = getEntry(schemaChangesMatches, schemaRegexSingle) - entry.previewChanges = getEntry(previewChangesMatches, previewRegexSingle) - entry.upcomingChanges = getEntry(upcomingChangesMatches, upcomingRegexSingle) - - // very first changelog has custom content - if (date === '2017-05-22') { - entry.schemaChanges[0].changes.push('Nothing! The schema was made public!') - } - - changelog.push(entry) - })) - - // sort by newest entries first - const sortedChangelog = reverse(sortBy(changelog, ['date'])) - - // write json file - fs.writeFileSync(staticChangelog, JSON.stringify(sortedChangelog, null, 2)) - console.log(`\n\nupdated ${staticChangelog}`) -} - -function getEntry (matches, regex) { - return matches - ? matches.map(match => { - const entry = {} - entry.title = cleanPreviewLinks(match.match(regex)[1]) - entry.changes = getChangedItems(match.match(regex)[2]) - return entry - }) - : [] -} - -function getChangedItems (string) { - return string - .split('\n*') - .slice(1) - .map(i => i.trim()) -} - -// do some cleanup of preview links -function cleanPreviewLinks (title) { - const previewMarkup = title.match(/\[(.*?)\]\((.*?)\)/) - if (!previewMarkup) return title - - const rawName = previewMarkup[1] - const rawLink = previewMarkup[2] - - let cleanName = rawName - let cleanLink = rawLink - - // fix two malformed links - if (cleanName.includes('MergeInfoPreview')) { - cleanName = 'Merge info preview' - cleanLink = `${previewsBaseLink}#merge-info-preview` - } - - if (cleanName.includes('UpdateRefsPreview')) { - cleanName = 'Update refs preview' - cleanLink = `${previewsBaseLink}#update-refs-preview` - } - - cleanName = !cleanName.endsWith('preview') - ? `${cleanName} preview` - : cleanName - - cleanLink = !cleanLink.endsWith('-preview') - ? `${cleanLink}-preview` - : cleanLink - - cleanLink = cleanLink - .replace('/v4/previews/', previewsBaseLink) - - return title - .replace(rawName, cleanName) - .replace(rawLink, cleanLink) -} diff --git a/script/graphql/build-changelog.js b/script/graphql/build-changelog.js new file mode 100644 index 0000000000..fc67d5f558 --- /dev/null +++ b/script/graphql/build-changelog.js @@ -0,0 +1,265 @@ +const { diff, ChangeType } = require('@graphql-inspector/core') +const { loadSchema } = require('@graphql-tools/load') +const fs = require('fs') + +/** + * Tag `changelogEntry` with `date: YYYY-mm-dd`, then prepend it to the JSON + * structure written to `targetPath`. (`changelogEntry` and that file are modified in place.) + * @param {object} changelogEntry + * @param {string} targetPath + * @return {void} + */ +function prependDatedEntry (changelogEntry, targetPath) { + // Build a `yyyy-mm-dd`-formatted date string + // and tag the changelog entry with it + const todayString = new Date().toISOString().slice(0, 10) + changelogEntry.date = todayString + + const previousChangelogString = fs.readFileSync(targetPath) + const previousChangelog = JSON.parse(previousChangelogString) + // add a new entry to the changelog data + previousChangelog.unshift(changelogEntry) + // rewrite the updated changelog + fs.writeFileSync(targetPath, JSON.stringify(previousChangelog, null, 2)) +} + +/** + * Compare `oldSchemaString` to `newSchemaString`, and if there are any + * changes that warrant a changelog entry, return a changelog entry. + * Based on the parsed `previews`, identify changes that are under a preview. + * Otherwise, return null. + * @param {string} [oldSchemaString] + * @param {string} [newSchemaString] + * @param {Array} [previews] + * @param {Array} [oldUpcomingChanges] + * @param {Array} [newUpcomingChanges] + * @return {object?} + */ +async function createChangelogEntry (oldSchemaString, newSchemaString, previews, oldUpcomingChanges, newUpcomingChanges) { + // Create schema objects out of the strings + const oldSchema = await loadSchema(oldSchemaString) + const newSchema = await loadSchema(newSchemaString) + + // Generate changes between the two schemas + const changes = diff(oldSchema, newSchema) + const changesToReport = [] + changes.forEach(function (change) { + if (CHANGES_TO_REPORT.includes(change.type)) { + changesToReport.push(change) + } else if (CHANGES_TO_IGNORE.includes(change.type)) { + // Do nothing + } else { + throw new Error('This change type should be added to CHANGES_TO_REPORT or CHANGES_TO_IGNORE: ' + change.type) + } + }) + + const { schemaChangesToReport, previewChangesToReport } = segmentPreviewChanges(changesToReport, previews) + + const addedUpcomingChanges = newUpcomingChanges.filter(function (change) { + // Manually check each of `newUpcomingChanges` for an equivalent entry + // in `oldUpcomingChanges`. + return !oldUpcomingChanges.find(function (oldChange) { + return (oldChange.location === change.location && + oldChange.date === change.date && + oldChange.description === change.description + ) + }) + }) + + // If there were any changes, create a changelog entry + if (schemaChangesToReport.length > 0 || previewChangesToReport.length > 0 || addedUpcomingChanges.length > 0) { + const changelogEntry = { + schemaChanges: [], + previewChanges: [], + upcomingChanges: [] + } + + const schemaChange = { + title: 'The GraphQL schema includes these changes:', + // Replace single quotes which wrap field/argument/type names with backticks + changes: cleanMessagesFromChanges(schemaChangesToReport) + } + changelogEntry.schemaChanges.push(schemaChange) + + for (const previewTitle in previewChangesToReport) { + const previewChanges = previewChangesToReport[previewTitle] + const cleanTitle = cleanPreviewTitle(previewTitle) + const entryTitle = 'The [' + cleanTitle + '](/graphql/overview/schema-previews#' + previewAnchor(cleanTitle) + ') includes these changes:' + changelogEntry.previewChanges.push({ + title: entryTitle, + changes: cleanMessagesFromChanges(previewChanges.changes) + }) + } + + if (addedUpcomingChanges.length > 0) { + changelogEntry.upcomingChanges.push({ + title: 'The following changes will be made to the schema:', + changes: addedUpcomingChanges.map(function (change) { + const location = change.location + const description = change.description + const date = change.date.split('T')[0] + return 'On member `' + location + '`:' + description + ' **Effective ' + date + '**.' + }) + }) + } + + return changelogEntry + } else { + return null + } +} + +/** + * Prepare the preview title from github/github source for the docs. + * @param {string} title + * @return {string} + */ +function cleanPreviewTitle (title) { + if (title === 'UpdateRefsPreview') { + title = 'Update refs preview' + } else if (title === 'MergeInfoPreview') { + title = 'Merge info preview' + } else if (!title.endsWith('preview')) { + title = title + ' preview' + } + return title +} + +/** + * Turn the given title into an HTML-ready anchor. + * (ported from https://github.com/github/graphql-docs/blob/master/lib/graphql_docs/update_internal_developer/change_log.rb#L281) + * @param {string} [previewTitle] + * @return {string} +*/ +function previewAnchor (previewTitle) { + return previewTitle + .toLowerCase() + .replace(/ /g, '-') + .replace(/[^\w-]/g, '') +} + +/** + * Turn changes from graphql-inspector into messages for the HTML changelog. + * @param {Array} changes + * @return {Array} + */ +function cleanMessagesFromChanges (changes) { + return changes.map(function (change) { + // replace single quotes around graphql names with backticks, + // to match previous behavior from graphql-schema-comparator + return change.message.replace(/'([a-zA-Z. :!]+)'/g, '`$1`') + }) +} + +/** + * Split `changesToReport` into two parts, + * one for changes in the main schema, + * and another for changes that are under preview. + * (Ported from https://github.com/github/graphql-docs/blob/7e6a5ccbf13cc7d875fee65527b25bc49e886b41/lib/graphql_docs/update_internal_developer/change_log.rb#L230) + * @param {Array} changesToReport + * @param {object} previews + * @return {object} + */ +function segmentPreviewChanges (changesToReport, previews) { + // Build a map of `{ path => previewTitle` } + // for easier lookup of change to preview + const pathToPreview = {} + previews.forEach(function (preview) { + preview.toggled_on.forEach(function (path) { + pathToPreview[path] = preview.title + }) + }) + const schemaChanges = [] + const changesByPreview = {} + + changesToReport.forEach(function (change) { + // For each change, see if its path _or_ one of its ancestors + // is covered by a preview. If it is, mark this change as belonging to a preview + const pathParts = change.path.split('.') + let testPath = null + let previewTitle = null + let previewChanges = null + while (pathParts.length > 0 && !previewTitle) { + testPath = pathParts.join('.') + previewTitle = pathToPreview[testPath] + // If that path didn't find a match, then we'll + // check the next ancestor. + pathParts.pop() + } + if (previewTitle) { + previewChanges = changesByPreview[previewTitle] || (changesByPreview[previewTitle] = { + title: previewTitle, + changes: [] + }) + previewChanges.changes.push(change) + } else { + schemaChanges.push(change) + } + }) + return { schemaChangesToReport: schemaChanges, previewChangesToReport: changesByPreview } +} + +// We only want to report changes to schema structure. +// Deprecations are covered by "upcoming changes." +// By listing the changes explicitly here, we can make sure that, +// if the library changes, we don't miss publishing anything that we mean to. +// This was originally ported from https://github.com/github/graphql-docs/blob/7e6a5ccbf13cc7d875fee65527b25bc49e886b41/lib/graphql_docs/update_internal_developer/change_log.rb#L35-L103 +const CHANGES_TO_REPORT = [ + ChangeType.FieldArgumentDefaultChanged, + ChangeType.FieldArgumentTypeChanged, + ChangeType.EnumValueRemoved, + ChangeType.EnumValueAdded, + ChangeType.FieldRemoved, + ChangeType.FieldAdded, + ChangeType.FieldTypeChanged, + ChangeType.FieldArgumentAdded, + ChangeType.FieldArgumentRemoved, + ChangeType.ObjectTypeInterfaceAdded, + ChangeType.ObjectTypeInterfaceRemoved, + ChangeType.InputFieldRemoved, + ChangeType.InputFieldAdded, + ChangeType.InputFieldDefaultValueChanged, + ChangeType.InputFieldTypeChanged, + ChangeType.TypeRemoved, + ChangeType.TypeAdded, + ChangeType.TypeKindChanged, + ChangeType.UnionMemberRemoved, + ChangeType.UnionMemberAdded, + ChangeType.SchemaQueryTypeChanged, + ChangeType.SchemaMutationTypeChanged, + ChangeType.SchemaSubscriptionTypeChanged +] + +const CHANGES_TO_IGNORE = [ + ChangeType.FieldArgumentDescriptionChanged, + ChangeType.DirectiveRemoved, + ChangeType.DirectiveAdded, + ChangeType.DirectiveDescriptionChanged, + ChangeType.DirectiveLocationAdded, + ChangeType.DirectiveLocationRemoved, + ChangeType.DirectiveArgumentAdded, + ChangeType.DirectiveArgumentRemoved, + ChangeType.DirectiveArgumentDescriptionChanged, + ChangeType.DirectiveArgumentDefaultValueChanged, + ChangeType.DirectiveArgumentTypeChanged, + ChangeType.EnumValueDescriptionChanged, + ChangeType.EnumValueDeprecationReasonChanged, + ChangeType.EnumValueDeprecationReasonAdded, + ChangeType.EnumValueDeprecationReasonRemoved, + ChangeType.FieldDescriptionChanged, + ChangeType.FieldDescriptionAdded, + ChangeType.FieldDescriptionRemoved, + ChangeType.FieldDeprecationAdded, + ChangeType.FieldDeprecationRemoved, + ChangeType.FieldDeprecationReasonChanged, + ChangeType.FieldDeprecationReasonAdded, + ChangeType.FieldDeprecationReasonRemoved, + ChangeType.InputFieldDescriptionAdded, + ChangeType.InputFieldDescriptionRemoved, + ChangeType.InputFieldDescriptionChanged, + ChangeType.TypeDescriptionChanged, + ChangeType.TypeDescriptionRemoved, + ChangeType.TypeDescriptionAdded +] + +module.exports = { createChangelogEntry, cleanPreviewTitle, previewAnchor, prependDatedEntry } diff --git a/script/graphql/update-files.js b/script/graphql/update-files.js index a12269d505..b33d8cec42 100755 --- a/script/graphql/update-files.js +++ b/script/graphql/update-files.js @@ -14,6 +14,7 @@ const processPreviews = require('./utils/process-previews') const processUpcomingChanges = require('./utils/process-upcoming-changes') const processSchemas = require('./utils/process-schemas') const prerenderObjects = require('./utils/prerender-objects') +const { prependDatedEntry, createChangelogEntry } = require('./build-changelog') // check for required PAT if (!process.env.GITHUB_TOKEN) { @@ -57,6 +58,7 @@ async function main () { // 2. UPDATE UPCOMING CHANGES const upcomingChangesPath = getDataFilepath('upcomingChanges', graphqlVersion) + const previousUpcomingChanges = yaml.safeLoad(fs.readFileSync(upcomingChangesPath, 'utf8')) const safeForPublicChanges = await getRemoteRawContent(upcomingChangesPath, graphqlVersion) updateFile(upcomingChangesPath, safeForPublicChanges) upcomingChangesJson[graphqlVersion] = await processUpcomingChanges(safeForPublicChanges) @@ -64,6 +66,7 @@ async function main () { // 3. UPDATE SCHEMAS // note: schemas live in separate files per version const schemaPath = getDataFilepath('schemas', graphqlVersion) + const previousSchemaString = fs.readFileSync(schemaPath, 'utf8') const latestSchema = await getRemoteRawContent(schemaPath, graphqlVersion) const safeForPublicSchema = removeHiddenMembers(schemaPath, latestSchema) updateFile(schemaPath, safeForPublicSchema) @@ -73,6 +76,21 @@ async function main () { // 4. PRERENDER OBJECTS HTML // because the objects page is too big to render on page load prerenderedObjects[graphqlVersion] = await prerenderObjects(schemaJsonPerVersion, version) + + // 5. UPDATE CHANGELOG + if (allVersions[version].nonEnterpriseDefault) { + // The Changelog is only build for free-pro-team@latest + const changelogEntry = await createChangelogEntry( + previousSchemaString, + safeForPublicSchema, + safeForPublicPreviews, + previousUpcomingChanges.upcoming_changes, + yaml.safeLoad(safeForPublicChanges).upcoming_changes + ) + if (changelogEntry) { + prependDatedEntry(changelogEntry, path.join(process.cwd(), 'lib/graphql/static/changelog.json')) + } + } } updateStaticFile(previewsJson, path.join(graphqlStaticDir, 'previews.json')) diff --git a/tests/fixtures/changelog-entry.json b/tests/fixtures/changelog-entry.json new file mode 100644 index 0000000000..900dbe3a3b --- /dev/null +++ b/tests/fixtures/changelog-entry.json @@ -0,0 +1,31 @@ +{ + "previewChanges": [ + { + "changes": [ + "Field `Query.previewField` changed type from `PreviewType` to `PreviewType!`", + "Type for argument `changeTypeArgument` on field 'PreviewType.field1` changed from `Int` to `Float'" + ], + "title": "The [Test preview](/graphql/overview/schema-previews#test-preview) includes these changes:" + } + ], + "schemaChanges": [ + { + "changes": [ + "Field `removedField` was removed from object type `Query`", + "Type for argument `argumentMadeRequired` on field `Query.argumentsField` changed from `Int` to `Int!`", + "Type for argument `argumentMadeOptional` on field `Query.argumentsField` changed from `Int!` to `Int`", + "Argument `removedRequiredArgument: Int!` was removed from field `Query.argumentsField`", + "Argument `removedOptionalArgument: Int!` was removed from field `Query.argumentsField`" + ], + "title": "The GraphQL schema includes these changes:" + } + ], + "upcomingChanges": [ + { + "changes": [ + "On member `Query.stableField`:`stableField` will be removed. **Effective 2021-06-01**." + ], + "title": "The following changes will be made to the schema:" + } + ] +} diff --git a/tests/fixtures/updated-changelog-file.json b/tests/fixtures/updated-changelog-file.json new file mode 100644 index 0000000000..3e8ee60410 --- /dev/null +++ b/tests/fixtures/updated-changelog-file.json @@ -0,0 +1,12 @@ +[ + { + "someStuff": true, + "date": "2020-11-20" + }, + { + "previous_entry": "..." + }, + { + "another_previous_entry": "..." + } +] diff --git a/tests/graphql/build-changelog-test.js b/tests/graphql/build-changelog-test.js new file mode 100644 index 0000000000..1a55d59bab --- /dev/null +++ b/tests/graphql/build-changelog-test.js @@ -0,0 +1,130 @@ +const yaml = require('js-yaml') +const { createChangelogEntry, cleanPreviewTitle, previewAnchor, prependDatedEntry } = require('../../script/graphql/build-changelog') +const fs = require('fs') +const MockDate = require('mockdate') +const expectedChangelogEntry = require('../fixtures/changelog-entry') +const expectedUpdatedChangelogFile = require('../fixtures/updated-changelog-file') + +describe('creating a changelog from old schema and new schema', () => { + afterEach(() => { + MockDate.reset() + }) + + it('finds a diff of schema changes, upcoming changes, and preview changes', async () => { + const oldSchemaString = ` + type PreviewType { + field1(changeTypeArgument: Int): Int + } + + type Query { + stableField: String + removedField: Boolean + argumentsField( + removedRequiredArgument: Int! + removedOptionalArgument: Int! + argumentMadeRequired: Int + argumentMadeOptional: Int! + ): String + previewField: PreviewType + } + ` + + const newSchemaString = ` + type PreviewType { + field1(changeTypeArgument: Float): Int + } + + type Query { + stableField: String + argumentsField( + argumentMadeRequired: Int! + argumentMadeOptional: Int + ): String + previewField: PreviewType! + } + ` + + const previews = yaml.safeLoad(` +- title: Test preview + description: This preview is just for test + toggled_by: ':test_preview' + announcement: null + updates: null + toggled_on: + - PreviewType + - Query.previewField + owning_teams: + - '@github/engineering' +`) + + const oldUpcomingChanges = yaml.safeLoad(` +upcoming_changes: + - location: EnterprisePendingCollaboratorEdge.isUnlicensed + description: '\`isUnlicensed\` will be removed.' + date: '2021-01-01T00:00:00+00:00' +`).upcoming_changes + + const newUpcomingChanges = yaml.safeLoad(` +upcoming_changes: + - location: Query.stableField + description: '\`stableField\` will be removed.' + date: '2021-06-01T00:00:00+00:00' + - location: EnterprisePendingCollaboratorEdge.isUnlicensed + description: '\`isUnlicensed\` will be removed.' + date: '2021-01-01T00:00:00+00:00' +`).upcoming_changes + + const entry = await createChangelogEntry(oldSchemaString, newSchemaString, previews, oldUpcomingChanges, newUpcomingChanges) + expect(entry).toEqual(expectedChangelogEntry) + }) + + it('returns null when there isnt any difference', async () => { + const schemaString = ` + type Query { + i: Int! + }` + + const nullEntry = await createChangelogEntry(schemaString, schemaString, [], [], []) + expect(nullEntry).toBeNull() + }) +}) + +describe('Preparing preview links', () => { + it('fixes preview names', () => { + // These two are special cases + expect(cleanPreviewTitle('UpdateRefsPreview')).toEqual('Update refs preview') + expect(cleanPreviewTitle('MergeInfoPreview')).toEqual('Merge info preview') + // Previews that don't end in " preview" have it added + expect(cleanPreviewTitle('something interesting')).toEqual('something interesting preview') + // Other things are left as-is + expect(cleanPreviewTitle('nice preview')).toEqual('nice preview') + }) + + it('creates anchors from preview titles', () => { + expect(previewAnchor('Merge info preview')).toEqual('merge-info-preview') + expect(previewAnchor('some.punct123 preview')).toEqual('somepunct123-preview') + }) +}) + +describe('updating the changelog file', () => { + afterEach(() => { + MockDate.reset() + }) + + it('modifies the entry object and the file on disk', () => { + const testTargetPath = 'tests/graphql/example_changelog.json' + const previousContents = fs.readFileSync(testTargetPath) + + const exampleEntry = { someStuff: true } + const expectedDate = '2020-11-20' + MockDate.set(expectedDate) + + prependDatedEntry(exampleEntry, testTargetPath) + const newContents = fs.readFileSync(testTargetPath, 'utf8') + // reset the file: + fs.writeFileSync(testTargetPath, previousContents) + + expect(exampleEntry).toEqual({ someStuff: true, date: expectedDate }) + expect(JSON.parse(newContents)).toEqual(expectedUpdatedChangelogFile) + }) +}) diff --git a/tests/graphql/example_changelog.json b/tests/graphql/example_changelog.json new file mode 100644 index 0000000000..a132be4304 --- /dev/null +++ b/tests/graphql/example_changelog.json @@ -0,0 +1,8 @@ +[ + { + "previous_entry": "..." + }, + { + "another_previous_entry": "..." + } +]