generate-docs.ts 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import * as fs from 'fs'
  2. import * as os from 'os'
  3. import * as path from 'path'
  4. import * as yaml from 'js-yaml'
  5. //
  6. // SUMMARY
  7. //
  8. // This script rebuilds the usage section in the README.md to be consistent with the action.yml
  9. function updateUsage(
  10. actionReference: string,
  11. actionYamlPath: string = 'action.yml',
  12. readmePath: string = 'README.md',
  13. startToken: string = '<!-- start usage -->',
  14. endToken: string = '<!-- end usage -->'
  15. ): void {
  16. if (!actionReference) {
  17. throw new Error('Parameter actionReference must not be empty')
  18. }
  19. // Load the action.yml
  20. const actionYaml = yaml.safeLoad(fs.readFileSync(actionYamlPath).toString())
  21. // Load the README
  22. const originalReadme = fs.readFileSync(readmePath).toString()
  23. // Find the start token
  24. const startTokenIndex = originalReadme.indexOf(startToken)
  25. if (startTokenIndex < 0) {
  26. throw new Error(`Start token '${startToken}' not found`)
  27. }
  28. // Find the end token
  29. const endTokenIndex = originalReadme.indexOf(endToken)
  30. if (endTokenIndex < 0) {
  31. throw new Error(`End token '${endToken}' not found`)
  32. } else if (endTokenIndex < startTokenIndex) {
  33. throw new Error('Start token must appear before end token')
  34. }
  35. // Build the new README
  36. const newReadme: string[] = []
  37. // Append the beginning
  38. newReadme.push(originalReadme.substr(0, startTokenIndex + startToken.length))
  39. // Build the new usage section
  40. newReadme.push('```yaml', `- uses: ${actionReference}`, ' with:')
  41. const inputs = actionYaml.inputs
  42. let firstInput = true
  43. for (const key of Object.keys(inputs)) {
  44. const input = inputs[key]
  45. // Line break between inputs
  46. if (!firstInput) {
  47. newReadme.push('')
  48. }
  49. // Constrain the width of the description
  50. const width = 80
  51. let description = input.description as string
  52. while (description) {
  53. // Longer than width? Find a space to break apart
  54. let segment: string = description
  55. if (description.length > width) {
  56. segment = description.substr(0, width + 1)
  57. while (!segment.endsWith(' ')) {
  58. segment = segment.substr(0, segment.length - 1)
  59. }
  60. } else {
  61. segment = description
  62. }
  63. description = description.substr(segment.length) // Remaining
  64. segment = segment.trimRight() // Trim the trailing space
  65. newReadme.push(` # ${segment}`)
  66. }
  67. // Input and default
  68. if (input.default !== undefined) {
  69. newReadme.push(` # Default: ${input.default}`)
  70. }
  71. newReadme.push(` ${key}: ''`)
  72. firstInput = false
  73. }
  74. newReadme.push('```')
  75. // Append the end
  76. newReadme.push(originalReadme.substr(endTokenIndex))
  77. // Write the new README
  78. fs.writeFileSync(readmePath, newReadme.join(os.EOL))
  79. }
  80. updateUsage(
  81. 'actions/checkout@v2-beta',
  82. path.join(__dirname, '..', '..', 'action.yml'),
  83. path.join(__dirname, '..', '..', 'README.md')
  84. )