Merge remote-tracking branch 'origin/master' into appropriate-context-and-feedback
This commit is contained in:
commit
2e0ea153d5
16 changed files with 461 additions and 11635 deletions
6
.github/actions/update-changelog/action.yml
vendored
6
.github/actions/update-changelog/action.yml
vendored
|
|
@ -1,6 +0,0 @@
|
|||
name: 'Create a changelog'
|
||||
description: 'Create a changelog draft based on merged PR titles'
|
||||
author: 'probablycorey'
|
||||
runs:
|
||||
using: 'node12'
|
||||
main: './lib/index.js'
|
||||
11157
.github/actions/update-changelog/lib/index.js
vendored
11157
.github/actions/update-changelog/lib/index.js
vendored
File diff suppressed because one or more lines are too long
324
.github/actions/update-changelog/package-lock.json
generated
vendored
324
.github/actions/update-changelog/package-lock.json
generated
vendored
|
|
@ -1,324 +0,0 @@
|
|||
{
|
||||
"requires": true,
|
||||
"lockfileVersion": 1,
|
||||
"dependencies": {
|
||||
"@actions/core": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.2.0.tgz",
|
||||
"integrity": "sha512-ZKdyhlSlyz38S6YFfPnyNgCDZuAF2T0Qv5eHflNWytPS8Qjvz39bZFMry9Bb/dpSnqWcNeav5yM2CTYpJeY+Dw=="
|
||||
},
|
||||
"@actions/github": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@actions/github/-/github-2.0.0.tgz",
|
||||
"integrity": "sha512-sNpZ5dJyJyfJIO5lNYx8r/Gha4Tlm8R0MLO2cBkGdOnAAEn3t1M/MHVcoBhY/VPfjGVe5RNAUPz+6INrViiUPA==",
|
||||
"requires": {
|
||||
"@octokit/graphql": "^4.3.1",
|
||||
"@octokit/rest": "^16.15.0"
|
||||
}
|
||||
},
|
||||
"@octokit/endpoint": {
|
||||
"version": "5.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-5.5.1.tgz",
|
||||
"integrity": "sha512-nBFhRUb5YzVTCX/iAK1MgQ4uWo89Gu0TH00qQHoYRCsE12dWcG1OiLd7v2EIo2+tpUKPMOQ62QFy9hy9Vg2ULg==",
|
||||
"requires": {
|
||||
"@octokit/types": "^2.0.0",
|
||||
"is-plain-object": "^3.0.0",
|
||||
"universal-user-agent": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"@octokit/graphql": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.3.1.tgz",
|
||||
"integrity": "sha512-hCdTjfvrK+ilU2keAdqNBWOk+gm1kai1ZcdjRfB30oA3/T6n53UVJb7w0L5cR3/rhU91xT3HSqCd+qbvH06yxA==",
|
||||
"requires": {
|
||||
"@octokit/request": "^5.3.0",
|
||||
"@octokit/types": "^2.0.0",
|
||||
"universal-user-agent": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"@octokit/request": {
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.3.1.tgz",
|
||||
"integrity": "sha512-5/X0AL1ZgoU32fAepTfEoggFinO3rxsMLtzhlUX+RctLrusn/CApJuGFCd0v7GMFhF+8UiCsTTfsu7Fh1HnEJg==",
|
||||
"requires": {
|
||||
"@octokit/endpoint": "^5.5.0",
|
||||
"@octokit/request-error": "^1.0.1",
|
||||
"@octokit/types": "^2.0.0",
|
||||
"deprecation": "^2.0.0",
|
||||
"is-plain-object": "^3.0.0",
|
||||
"node-fetch": "^2.3.0",
|
||||
"once": "^1.4.0",
|
||||
"universal-user-agent": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"@octokit/request-error": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-1.2.0.tgz",
|
||||
"integrity": "sha512-DNBhROBYjjV/I9n7A8kVkmQNkqFAMem90dSxqvPq57e2hBr7mNTX98y3R2zDpqMQHVRpBDjsvsfIGgBzy+4PAg==",
|
||||
"requires": {
|
||||
"@octokit/types": "^2.0.0",
|
||||
"deprecation": "^2.0.0",
|
||||
"once": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"@octokit/rest": {
|
||||
"version": "16.35.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-16.35.2.tgz",
|
||||
"integrity": "sha512-iijaNZpn9hBpUdh8YdXqNiWazmq4R1vCUsmxpBB0kCQ0asHZpCx+HNs22eiHuwYKRhO31ZSAGBJLi0c+3XHaKQ==",
|
||||
"requires": {
|
||||
"@octokit/request": "^5.2.0",
|
||||
"@octokit/request-error": "^1.0.2",
|
||||
"atob-lite": "^2.0.0",
|
||||
"before-after-hook": "^2.0.0",
|
||||
"btoa-lite": "^1.0.0",
|
||||
"deprecation": "^2.0.0",
|
||||
"lodash.get": "^4.4.2",
|
||||
"lodash.set": "^4.3.2",
|
||||
"lodash.uniq": "^4.5.0",
|
||||
"octokit-pagination-methods": "^1.1.0",
|
||||
"once": "^1.4.0",
|
||||
"universal-user-agent": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"@octokit/types": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-2.0.2.tgz",
|
||||
"integrity": "sha512-StASIL2lgT3TRjxv17z9pAqbnI7HGu9DrJlg3sEBFfCLaMEqp+O3IQPUF6EZtQ4xkAu2ml6kMBBCtGxjvmtmuQ==",
|
||||
"requires": {
|
||||
"@types/node": ">= 8"
|
||||
}
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "12.12.21",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.21.tgz",
|
||||
"integrity": "sha512-8sRGhbpU+ck1n0PGAUgVrWrWdjSW2aqNeyC15W88GRsMpSwzv6RJGlLhE7s2RhVSOdyDmxbqlWSeThq4/7xqlA=="
|
||||
},
|
||||
"@zeit/ncc": {
|
||||
"version": "0.20.5",
|
||||
"resolved": "https://registry.npmjs.org/@zeit/ncc/-/ncc-0.20.5.tgz",
|
||||
"integrity": "sha512-XU6uzwvv95DqxciQx+aOLhbyBx/13ky+RK1y88Age9Du3BlA4mMPCy13BGjayOrrumOzlq1XV3SD/BWiZENXlw==",
|
||||
"dev": true
|
||||
},
|
||||
"atob-lite": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/atob-lite/-/atob-lite-2.0.0.tgz",
|
||||
"integrity": "sha1-D+9a1G8b16hQLGVyfwNn1e5D1pY="
|
||||
},
|
||||
"before-after-hook": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.1.0.tgz",
|
||||
"integrity": "sha512-IWIbu7pMqyw3EAJHzzHbWa85b6oud/yfKYg5rqB5hNE8CeMi3nX+2C2sj0HswfblST86hpVEOAb9x34NZd6P7A=="
|
||||
},
|
||||
"btoa-lite": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/btoa-lite/-/btoa-lite-1.0.0.tgz",
|
||||
"integrity": "sha1-M3dm2hWAEhD92VbCLpxokaudAzc="
|
||||
},
|
||||
"cross-spawn": {
|
||||
"version": "6.0.5",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
|
||||
"integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
|
||||
"requires": {
|
||||
"nice-try": "^1.0.4",
|
||||
"path-key": "^2.0.1",
|
||||
"semver": "^5.5.0",
|
||||
"shebang-command": "^1.2.0",
|
||||
"which": "^1.2.9"
|
||||
}
|
||||
},
|
||||
"deprecation": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz",
|
||||
"integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ=="
|
||||
},
|
||||
"end-of-stream": {
|
||||
"version": "1.4.4",
|
||||
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
|
||||
"integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
|
||||
"requires": {
|
||||
"once": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"execa": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz",
|
||||
"integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==",
|
||||
"requires": {
|
||||
"cross-spawn": "^6.0.0",
|
||||
"get-stream": "^4.0.0",
|
||||
"is-stream": "^1.1.0",
|
||||
"npm-run-path": "^2.0.0",
|
||||
"p-finally": "^1.0.0",
|
||||
"signal-exit": "^3.0.0",
|
||||
"strip-eof": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"get-stream": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
|
||||
"integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
|
||||
"requires": {
|
||||
"pump": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"is-plain-object": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.0.tgz",
|
||||
"integrity": "sha512-tZIpofR+P05k8Aocp7UI/2UTa9lTJSebCXpFFoR9aibpokDj/uXBsJ8luUu0tTVYKkMU6URDUuOfJZ7koewXvg==",
|
||||
"requires": {
|
||||
"isobject": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"is-stream": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
|
||||
"integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
|
||||
},
|
||||
"isexe": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
|
||||
},
|
||||
"isobject": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isobject/-/isobject-4.0.0.tgz",
|
||||
"integrity": "sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA=="
|
||||
},
|
||||
"lodash.get": {
|
||||
"version": "4.4.2",
|
||||
"resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
|
||||
"integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk="
|
||||
},
|
||||
"lodash.set": {
|
||||
"version": "4.3.2",
|
||||
"resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz",
|
||||
"integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM="
|
||||
},
|
||||
"lodash.uniq": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
|
||||
"integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M="
|
||||
},
|
||||
"macos-release": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/macos-release/-/macos-release-2.3.0.tgz",
|
||||
"integrity": "sha512-OHhSbtcviqMPt7yfw5ef5aghS2jzFVKEFyCJndQt2YpSQ9qRVSEv2axSJI1paVThEu+FFGs584h/1YhxjVqajA=="
|
||||
},
|
||||
"nice-try": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
|
||||
"integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ=="
|
||||
},
|
||||
"node-fetch": {
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz",
|
||||
"integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA=="
|
||||
},
|
||||
"npm-run-path": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
|
||||
"integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
|
||||
"requires": {
|
||||
"path-key": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"octokit-pagination-methods": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/octokit-pagination-methods/-/octokit-pagination-methods-1.1.0.tgz",
|
||||
"integrity": "sha512-fZ4qZdQ2nxJvtcasX7Ghl+WlWS/d9IgnBIwFZXVNNZUmzpno91SX5bc5vuxiuKoCtK78XxGGNuSCrDC7xYB3OQ=="
|
||||
},
|
||||
"once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"os-name": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/os-name/-/os-name-3.1.0.tgz",
|
||||
"integrity": "sha512-h8L+8aNjNcMpo/mAIBPn5PXCM16iyPGjHNWo6U1YO8sJTMHtEtyczI6QJnLoplswm6goopQkqc7OAnjhWcugVg==",
|
||||
"requires": {
|
||||
"macos-release": "^2.2.0",
|
||||
"windows-release": "^3.1.0"
|
||||
}
|
||||
},
|
||||
"p-finally": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
|
||||
"integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4="
|
||||
},
|
||||
"path-key": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
|
||||
"integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A="
|
||||
},
|
||||
"pump": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
|
||||
"integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
|
||||
"requires": {
|
||||
"end-of-stream": "^1.1.0",
|
||||
"once": "^1.3.1"
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "5.7.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
|
||||
},
|
||||
"shebang-command": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
|
||||
"integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
|
||||
"requires": {
|
||||
"shebang-regex": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"shebang-regex": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
|
||||
"integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM="
|
||||
},
|
||||
"signal-exit": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
|
||||
"integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
|
||||
},
|
||||
"strip-eof": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
|
||||
"integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8="
|
||||
},
|
||||
"universal-user-agent": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-4.0.0.tgz",
|
||||
"integrity": "sha512-eM8knLpev67iBDizr/YtqkJsF3GK8gzDc6st/WKzrTuPtcsOKW/0IdL4cnMBsU69pOx0otavLWBDGTwg+dB0aA==",
|
||||
"requires": {
|
||||
"os-name": "^3.1.0"
|
||||
}
|
||||
},
|
||||
"which": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
|
||||
"integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
|
||||
"requires": {
|
||||
"isexe": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"windows-release": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/windows-release/-/windows-release-3.2.0.tgz",
|
||||
"integrity": "sha512-QTlz2hKLrdqukrsapKsINzqMgOUpQW268eJ0OaOpJN32h272waxR9fkB9VoWRtK7uKHG5EHJcTXQBD8XZVJkFA==",
|
||||
"requires": {
|
||||
"execa": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
|
||||
}
|
||||
}
|
||||
}
|
||||
18
.github/actions/update-changelog/package.json
vendored
18
.github/actions/update-changelog/package.json
vendored
|
|
@ -1,18 +0,0 @@
|
|||
{
|
||||
"license": "ISC",
|
||||
"scripts": {
|
||||
"build": "rm -rf lib && ncc build -s src/index.ts -o lib"
|
||||
},
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.2.0",
|
||||
"@actions/github": "^2.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@zeit/ncc": "^0.20.5"
|
||||
},
|
||||
"prettier": {
|
||||
"trailingComma": "es5",
|
||||
"semi": false,
|
||||
"singleQuote": true
|
||||
}
|
||||
}
|
||||
73
.github/actions/update-changelog/src/index.ts
vendored
73
.github/actions/update-changelog/src/index.ts
vendored
|
|
@ -1,73 +0,0 @@
|
|||
import * as core from '@actions/core'
|
||||
import * as github from '@actions/github'
|
||||
|
||||
const GITHUB_TOKEN = getEnvVar('GITHUB_TOKEN')
|
||||
|
||||
interface Changelog {
|
||||
draft: string[]
|
||||
releases: { [tag: string]: string[] }
|
||||
}
|
||||
|
||||
process.on('unhandledRejection', (reason: any, _: Promise<any>) =>
|
||||
handleError(reason)
|
||||
)
|
||||
main().catch(handleError)
|
||||
|
||||
async function main() {
|
||||
const title =
|
||||
github.context.payload &&
|
||||
github.context.payload.pull_request &&
|
||||
github.context.payload.pull_request.title
|
||||
const { changelog, sha } = await getChangelog()
|
||||
const updatedChangelog = { ...changelog, draft: [title, ...changelog.draft] }
|
||||
await commitChangelog(updatedChangelog, sha)
|
||||
}
|
||||
|
||||
async function getChangelog() {
|
||||
const octokit = new github.GitHub(GITHUB_TOKEN)
|
||||
const owner = github.context.repo.owner
|
||||
const repo = github.context.repo.repo
|
||||
const path = 'changelog.json'
|
||||
const response = await octokit.repos.getContents({ owner, repo, path })
|
||||
const base64Content = (response.data as any).content
|
||||
const sha = (response.data as any).sha
|
||||
const content = Buffer.from(base64Content, 'base64').toString('utf8')
|
||||
return { changelog: JSON.parse(content), sha }
|
||||
}
|
||||
|
||||
async function commitChangelog(changelog: Changelog, sha: string) {
|
||||
const octokit = new github.GitHub(GITHUB_TOKEN)
|
||||
const owner = github.context.repo.owner
|
||||
const repo = github.context.repo.repo
|
||||
const path = 'changelog.json'
|
||||
const message = 'update changelog'
|
||||
const json = JSON.stringify(changelog, null, 2)
|
||||
const content = Buffer.from(json).toString('base64')
|
||||
const response = await octokit.repos.createOrUpdateFile({
|
||||
owner,
|
||||
repo,
|
||||
path,
|
||||
message,
|
||||
content,
|
||||
sha,
|
||||
})
|
||||
|
||||
if (response.status != 200) {
|
||||
throw new Error(
|
||||
'Failed to commit changelog udpates. ' + JSON.stringify(response.data)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
function handleError(err: Error) {
|
||||
console.error(err)
|
||||
core.setFailed(err.message)
|
||||
}
|
||||
|
||||
function getEnvVar(name: string): string {
|
||||
const envVar = process.env[name]
|
||||
if (!envVar) {
|
||||
throw new Error(`env var named "${name} is not set"`)
|
||||
}
|
||||
return envVar
|
||||
}
|
||||
5
.github/actions/update-changelog/test-run.sh
vendored
5
.github/actions/update-changelog/test-run.sh
vendored
|
|
@ -1,5 +0,0 @@
|
|||
set -e
|
||||
|
||||
TOKEN="$(awk '/oauth_token/ {print $2}' ~/.config/gh/config.yml | head -1)"
|
||||
|
||||
env "GITHUB_REPOSITORY=github/gh-cli" "GITHUB_TOKEN=$TOKEN" node lib/index.js
|
||||
19
.github/actions/update-changelog/tsconfig.json
vendored
19
.github/actions/update-changelog/tsconfig.json
vendored
|
|
@ -1,19 +0,0 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"outDir": "./lib",
|
||||
"rootDir": "./src",
|
||||
"module": "commonjs",
|
||||
"target": "esnext",
|
||||
"lib": ["es2017"],
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noImplicitAny": true,
|
||||
"removeComments": false,
|
||||
"preserveConstEnums": true
|
||||
},
|
||||
"include": ["src/**/*.ts"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
46
.github/workflows/go.yml
vendored
46
.github/workflows/go.yml
vendored
|
|
@ -1,8 +1,8 @@
|
|||
name: Go
|
||||
name: Tests
|
||||
on: [push]
|
||||
jobs:
|
||||
build:
|
||||
name: Build
|
||||
build-linux:
|
||||
name: Linux Build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Set up Go 1.13
|
||||
|
|
@ -21,3 +21,43 @@ jobs:
|
|||
run: |
|
||||
go test ./...
|
||||
go build -v .
|
||||
build-windows:
|
||||
name: Windows Build
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- name: Set up Go 1.13
|
||||
uses: actions/setup-go@v1
|
||||
with:
|
||||
go-version: 1.13
|
||||
id: go
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v1
|
||||
|
||||
- name: Verify dependencies
|
||||
run: go mod verify
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
go test ./...
|
||||
go build -v .
|
||||
build-macos:
|
||||
name: MacOS Build
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- name: Set up Go 1.13
|
||||
uses: actions/setup-go@v1
|
||||
with:
|
||||
go-version: 1.13
|
||||
id: go
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v1
|
||||
|
||||
- name: Verify dependencies
|
||||
run: go mod verify
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
go test ./...
|
||||
go build -v .
|
||||
|
|
|
|||
18
.github/workflows/update-changelog.yml
vendored
18
.github/workflows/update-changelog.yml
vendored
|
|
@ -1,18 +0,0 @@
|
|||
name: Changelog
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [closed]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v1
|
||||
|
||||
- name: Update the changelog
|
||||
if: github.event.pull_request.merged == true
|
||||
uses: ./.github/actions/update-changelog
|
||||
env:
|
||||
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"draft": [],
|
||||
"releases": {
|
||||
"0.0.1": ["And so it begins..."]
|
||||
}
|
||||
}
|
||||
|
|
@ -3,13 +3,14 @@ package command
|
|||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/github/gh-cli/api"
|
||||
"github.com/github/gh-cli/context"
|
||||
"github.com/github/gh-cli/git"
|
||||
"github.com/github/gh-cli/pkg/githubtemplate"
|
||||
"github.com/github/gh-cli/utils"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
|
|
@ -245,11 +246,16 @@ func issueCreate(cmd *cobra.Command, args []string) error {
|
|||
|
||||
fmt.Fprintf(colorableErr(cmd), "\nCreating issue in %s/%s\n\n", baseRepo.RepoOwner(), baseRepo.RepoName())
|
||||
|
||||
var templateFiles []string
|
||||
if rootDir, err := git.ToplevelDir(); err == nil {
|
||||
// TODO: figure out how to stub this in tests
|
||||
templateFiles = githubtemplate.Find(rootDir, "ISSUE_TEMPLATE")
|
||||
}
|
||||
|
||||
if isWeb, err := cmd.Flags().GetBool("web"); err == nil && isWeb {
|
||||
// TODO: move URL generation into GitHubRepository
|
||||
openURL := fmt.Sprintf("https://github.com/%s/%s/issues/new", baseRepo.RepoOwner(), baseRepo.RepoName())
|
||||
// TODO: figure out how to stub this in tests
|
||||
if stat, err := os.Stat(".github/ISSUE_TEMPLATE"); err == nil && stat.IsDir() {
|
||||
if len(templateFiles) > 1 {
|
||||
openURL += "/choose"
|
||||
}
|
||||
cmd.Printf("Opening %s in your browser.\n", openURL)
|
||||
|
|
@ -281,7 +287,7 @@ func issueCreate(cmd *cobra.Command, args []string) error {
|
|||
interactive := title == "" || body == ""
|
||||
|
||||
if interactive {
|
||||
tb, err := titleBodySurvey(cmd, title, body)
|
||||
tb, err := titleBodySurvey(cmd, title, body, templateFiles)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not collect title and/or body")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import (
|
|||
"github.com/github/gh-cli/api"
|
||||
"github.com/github/gh-cli/context"
|
||||
"github.com/github/gh-cli/git"
|
||||
"github.com/github/gh-cli/pkg/githubtemplate"
|
||||
"github.com/github/gh-cli/utils"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
|
|
@ -81,7 +82,13 @@ func prCreate(cmd *cobra.Command, _ []string) error {
|
|||
interactive := title == "" || body == ""
|
||||
|
||||
if interactive {
|
||||
tb, err := titleBodySurvey(cmd, title, body)
|
||||
var templateFiles []string
|
||||
if rootDir, err := git.ToplevelDir(); err == nil {
|
||||
// TODO: figure out how to stub this in tests
|
||||
templateFiles = githubtemplate.Find(rootDir, "PULL_REQUEST_TEMPLATE")
|
||||
}
|
||||
|
||||
tb, err := titleBodySurvey(cmd, title, body, templateFiles)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not collect title and/or body")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@ package command
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/AlecAivazis/survey/v2"
|
||||
"github.com/github/gh-cli/pkg/githubtemplate"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
|
@ -44,9 +46,45 @@ func confirm() (int, error) {
|
|||
return confirmAnswers.Confirmation, nil
|
||||
}
|
||||
|
||||
func titleBodySurvey(cmd *cobra.Command, providedTitle string, providedBody string) (*titleBody, error) {
|
||||
func selectTemplate(templatePaths []string) (string, error) {
|
||||
templateResponse := struct {
|
||||
Index int
|
||||
}{}
|
||||
if len(templatePaths) > 1 {
|
||||
templateNames := []string{}
|
||||
for _, p := range templatePaths {
|
||||
templateNames = append(templateNames, githubtemplate.ExtractName(p))
|
||||
}
|
||||
|
||||
selectQs := []*survey.Question{
|
||||
{
|
||||
Name: "index",
|
||||
Prompt: &survey.Select{
|
||||
Message: "Choose a template",
|
||||
Options: templateNames,
|
||||
},
|
||||
},
|
||||
}
|
||||
if err := survey.Ask(selectQs, &templateResponse); err != nil {
|
||||
return "", errors.Wrap(err, "could not prompt")
|
||||
}
|
||||
}
|
||||
|
||||
templateContents := githubtemplate.ExtractContents(templatePaths[templateResponse.Index])
|
||||
return string(templateContents), nil
|
||||
}
|
||||
|
||||
func titleBodySurvey(cmd *cobra.Command, providedTitle string, providedBody string, templatePaths []string) (*titleBody, error) {
|
||||
inProgress := titleBody{}
|
||||
|
||||
if providedBody == "" && len(templatePaths) > 0 {
|
||||
templateContents, err := selectTemplate(templatePaths)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
inProgress.Body = templateContents
|
||||
}
|
||||
|
||||
confirmed := false
|
||||
editor := determineEditor()
|
||||
|
||||
|
|
@ -64,6 +102,7 @@ func titleBodySurvey(cmd *cobra.Command, providedTitle string, providedBody stri
|
|||
Message: fmt.Sprintf("Body (%s)", editor),
|
||||
FileName: "*.md",
|
||||
Default: inProgress.Body,
|
||||
HideDefault: true,
|
||||
AppendDefault: true,
|
||||
Editor: editor,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -111,6 +111,14 @@ func ReadBranchConfig(branch string) (cfg BranchConfig) {
|
|||
return
|
||||
}
|
||||
|
||||
// ToplevelDir returns the top-level directory path of the current repository
|
||||
func ToplevelDir() (string, error) {
|
||||
showCmd := exec.Command("git", "rev-parse", "--show-toplevel")
|
||||
output, err := utils.PrepareCmd(showCmd).Output()
|
||||
return firstLine(output), err
|
||||
|
||||
}
|
||||
|
||||
func outputLines(output []byte) []string {
|
||||
lines := strings.TrimSuffix(string(output), "\n")
|
||||
return strings.Split(lines, "\n")
|
||||
|
|
|
|||
99
pkg/githubtemplate/github_template.go
Normal file
99
pkg/githubtemplate/github_template.go
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
package githubtemplate
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"path"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
// Find returns the list of template file paths
|
||||
func Find(rootDir string, name string) []string {
|
||||
results := []string{}
|
||||
|
||||
// https://help.github.com/en/github/building-a-strong-community/creating-a-pull-request-template-for-your-repository
|
||||
candidateDirs := []string{
|
||||
path.Join(rootDir, ".github"),
|
||||
rootDir,
|
||||
path.Join(rootDir, "docs"),
|
||||
}
|
||||
|
||||
mainLoop:
|
||||
for _, dir := range candidateDirs {
|
||||
files, err := ioutil.ReadDir(dir)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// detect multiple templates in a subdirectory
|
||||
for _, file := range files {
|
||||
if strings.EqualFold(file.Name(), name) && file.IsDir() {
|
||||
templates, err := ioutil.ReadDir(path.Join(dir, file.Name()))
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
for _, tf := range templates {
|
||||
if strings.HasSuffix(tf.Name(), ".md") {
|
||||
results = append(results, path.Join(dir, file.Name(), tf.Name()))
|
||||
}
|
||||
}
|
||||
if len(results) > 0 {
|
||||
break mainLoop
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// detect a single template file
|
||||
for _, file := range files {
|
||||
if strings.EqualFold(file.Name(), name+".md") {
|
||||
results = append(results, path.Join(dir, file.Name()))
|
||||
break
|
||||
}
|
||||
}
|
||||
if len(results) > 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
sort.Sort(sort.StringSlice(results))
|
||||
return results
|
||||
}
|
||||
|
||||
// ExtractName returns the name of the template from YAML front-matter
|
||||
func ExtractName(filePath string) string {
|
||||
contents, err := ioutil.ReadFile(filePath)
|
||||
if err == nil && detectFrontmatter(contents)[0] == 0 {
|
||||
templateData := struct {
|
||||
Name string
|
||||
}{}
|
||||
if err := yaml.Unmarshal(contents, &templateData); err == nil && templateData.Name != "" {
|
||||
return templateData.Name
|
||||
}
|
||||
}
|
||||
return path.Base(filePath)
|
||||
}
|
||||
|
||||
// ExtractContents returns the template contents without the YAML front-matter
|
||||
func ExtractContents(filePath string) []byte {
|
||||
contents, err := ioutil.ReadFile(filePath)
|
||||
if err != nil {
|
||||
return []byte{}
|
||||
}
|
||||
if frontmatterBoundaries := detectFrontmatter(contents); frontmatterBoundaries[0] == 0 {
|
||||
return contents[frontmatterBoundaries[1]:]
|
||||
}
|
||||
return contents
|
||||
}
|
||||
|
||||
var yamlPattern = regexp.MustCompile(`(?m)^---\r?\n(\s*\r?\n)?`)
|
||||
|
||||
func detectFrontmatter(c []byte) []int {
|
||||
if matches := yamlPattern.FindAllIndex(c, 2); len(matches) > 1 {
|
||||
return []int{matches[0][0], matches[1][1]}
|
||||
}
|
||||
return []int{-1, -1}
|
||||
}
|
||||
253
pkg/githubtemplate/github_template_test.go
Normal file
253
pkg/githubtemplate/github_template_test.go
Normal file
|
|
@ -0,0 +1,253 @@
|
|||
package githubtemplate
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestFind(t *testing.T) {
|
||||
tmpdir, err := ioutil.TempDir("", "gh-cli")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
type args struct {
|
||||
rootDir string
|
||||
name string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
prepare []string
|
||||
args args
|
||||
want []string
|
||||
}{
|
||||
{
|
||||
name: "Template in root",
|
||||
prepare: []string{
|
||||
"README.md",
|
||||
"ISSUE_TEMPLATE",
|
||||
"issue_template.md",
|
||||
"issue_template.txt",
|
||||
"pull_request_template.md",
|
||||
},
|
||||
args: args{
|
||||
rootDir: tmpdir,
|
||||
name: "ISSUE_TEMPLATE",
|
||||
},
|
||||
want: []string{
|
||||
path.Join(tmpdir, "issue_template.md"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Template in .github takes precedence",
|
||||
prepare: []string{
|
||||
"ISSUE_TEMPLATE.md",
|
||||
".github/issue_template.md",
|
||||
},
|
||||
args: args{
|
||||
rootDir: tmpdir,
|
||||
name: "ISSUE_TEMPLATE",
|
||||
},
|
||||
want: []string{
|
||||
path.Join(tmpdir, ".github/issue_template.md"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Template in docs",
|
||||
prepare: []string{
|
||||
"README.md",
|
||||
"docs/issue_template.md",
|
||||
},
|
||||
args: args{
|
||||
rootDir: tmpdir,
|
||||
name: "ISSUE_TEMPLATE",
|
||||
},
|
||||
want: []string{
|
||||
path.Join(tmpdir, "docs/issue_template.md"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Multiple templates",
|
||||
prepare: []string{
|
||||
".github/ISSUE_TEMPLATE/nope.md",
|
||||
".github/PULL_REQUEST_TEMPLATE.md",
|
||||
".github/PULL_REQUEST_TEMPLATE/one.md",
|
||||
".github/PULL_REQUEST_TEMPLATE/two.md",
|
||||
".github/PULL_REQUEST_TEMPLATE/three.md",
|
||||
"docs/pull_request_template.md",
|
||||
},
|
||||
args: args{
|
||||
rootDir: tmpdir,
|
||||
name: "PuLl_ReQuEsT_TeMpLaTe",
|
||||
},
|
||||
want: []string{
|
||||
path.Join(tmpdir, ".github/PULL_REQUEST_TEMPLATE/one.md"),
|
||||
path.Join(tmpdir, ".github/PULL_REQUEST_TEMPLATE/three.md"),
|
||||
path.Join(tmpdir, ".github/PULL_REQUEST_TEMPLATE/two.md"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Empty multiple templates directory",
|
||||
prepare: []string{
|
||||
".github/issue_template.md",
|
||||
".github/issue_template/.keep",
|
||||
},
|
||||
args: args{
|
||||
rootDir: tmpdir,
|
||||
name: "ISSUE_TEMPLATE",
|
||||
},
|
||||
want: []string{
|
||||
path.Join(tmpdir, ".github/issue_template.md"),
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
for _, p := range tt.prepare {
|
||||
fp := path.Join(tmpdir, p)
|
||||
os.MkdirAll(path.Dir(fp), 0700)
|
||||
file, err := os.Create(fp)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
file.Close()
|
||||
}
|
||||
|
||||
if got := Find(tt.args.rootDir, tt.args.name); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("Find() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
os.RemoveAll(tmpdir)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExtractName(t *testing.T) {
|
||||
tmpfile, err := ioutil.TempFile("", "gh-cli")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
tmpfile.Close()
|
||||
defer os.Remove(tmpfile.Name())
|
||||
|
||||
type args struct {
|
||||
filePath string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
prepare string
|
||||
args args
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "Complete front-matter",
|
||||
prepare: `---
|
||||
name: Bug Report
|
||||
about: This is how you report bugs
|
||||
---
|
||||
|
||||
Template contents
|
||||
---
|
||||
More of template
|
||||
`,
|
||||
args: args{
|
||||
filePath: tmpfile.Name(),
|
||||
},
|
||||
want: "Bug Report",
|
||||
},
|
||||
{
|
||||
name: "Incomplete front-matter",
|
||||
prepare: `---
|
||||
about: This is how you report bugs
|
||||
---
|
||||
`,
|
||||
args: args{
|
||||
filePath: tmpfile.Name(),
|
||||
},
|
||||
want: path.Base(tmpfile.Name()),
|
||||
},
|
||||
{
|
||||
name: "No front-matter",
|
||||
prepare: `name: This is not yaml!`,
|
||||
args: args{
|
||||
filePath: tmpfile.Name(),
|
||||
},
|
||||
want: path.Base(tmpfile.Name()),
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
ioutil.WriteFile(tmpfile.Name(), []byte(tt.prepare), 0600)
|
||||
if got := ExtractName(tt.args.filePath); got != tt.want {
|
||||
t.Errorf("ExtractName() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestExtractContents(t *testing.T) {
|
||||
tmpfile, err := ioutil.TempFile("", "gh-cli")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
tmpfile.Close()
|
||||
defer os.Remove(tmpfile.Name())
|
||||
|
||||
type args struct {
|
||||
filePath string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
prepare string
|
||||
args args
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "Has front-matter",
|
||||
prepare: `---
|
||||
name: Bug Report
|
||||
---
|
||||
|
||||
|
||||
Template contents
|
||||
---
|
||||
More of template
|
||||
`,
|
||||
args: args{
|
||||
filePath: tmpfile.Name(),
|
||||
},
|
||||
want: `Template contents
|
||||
---
|
||||
More of template
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "No front-matter",
|
||||
prepare: `Template contents
|
||||
---
|
||||
More of template
|
||||
---
|
||||
Even more
|
||||
`,
|
||||
args: args{
|
||||
filePath: tmpfile.Name(),
|
||||
},
|
||||
want: `Template contents
|
||||
---
|
||||
More of template
|
||||
---
|
||||
Even more
|
||||
`,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
ioutil.WriteFile(tmpfile.Name(), []byte(tt.prepare), 0600)
|
||||
if got := ExtractContents(tt.args.filePath); string(got) != tt.want {
|
||||
t.Errorf("ExtractContents() = %v, want %v", string(got), tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue