Skip to content

Commit

Permalink
Merge pull request #9463 from joshcooper/references_function_12064
Browse files Browse the repository at this point in the history
(PUP-12064) Add task to generate function reference
  • Loading branch information
cthorn42 authored Aug 30, 2024
2 parents 7f67aef + eb9eee1 commit 0e2c0b4
Show file tree
Hide file tree
Showing 6 changed files with 5,634 additions and 0 deletions.
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ end
group(:documentation, optional: true) do
gem 'gettext-setup', '~> 1.0', require: false, platforms: [:ruby]
gem 'ronn', '~> 0.7.3', require: false, platforms: [:ruby]
gem 'puppet-strings', require: false, platforms: [:ruby]
end

if File.exist? "#{__FILE__}.local"
Expand Down
44 changes: 44 additions & 0 deletions rakelib/generate_references.rake
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ METAPARAMETER_ERB = File.join(__dir__, 'references/metaparameter.erb')
METAPARAMETER_MD = File.join(OUTPUT_DIR, 'metaparameter.md')
REPORT_ERB = File.join(__dir__, 'references/report.erb')
REPORT_MD = File.join(OUTPUT_DIR, 'report.md')
FUNCTIONS_TEMPLATE_ERB = File.join(__dir__, 'references/functions_template.erb')
FUNCTION_ERB = File.join(__dir__, 'references/function.erb')
FUNCTION_MD = File.join(OUTPUT_DIR, 'function.md')

def render_erb(erb_file, variables)
# Create a binding so only the variables we specify will be visible
Expand Down Expand Up @@ -56,4 +59,45 @@ namespace :references do
body = puppet_doc('report')
generate_reference('report', REPORT_ERB, body, REPORT_MD)
end

desc "Generate function reference"
task :function do
# Locate puppet-strings
begin
require 'puppet-strings'
require 'puppet-strings/version'
rescue LoadError
abort("Run `bundle config set with documentation` and `bundle update` to install the `puppet-strings` gem.")
end

strings_data = {}
Tempfile.create do |tmpfile|
puts "Running puppet strings #{PuppetStrings::VERSION}"
PuppetStrings.generate(['lib/puppet/{functions,parser/functions}/**/*.rb'], json: true, path: tmpfile.path)
strings_data = JSON.load_file(tmpfile.path)
end

# Based on https://github.com/puppetlabs/puppet-docs/blob/1a13be3fc6981baa8a96ff832ab090abc986830e/lib/puppet_references/puppet/functions.rb#L24-L56
functions = strings_data['puppet_functions']

# Deal with the duplicate 3.x and 4.x functions
# 1. Figure out which functions are duplicated.
names = functions.map { |func| func['name'] }
duplicates = names.uniq.select { |name| names.count(name) > 1 }
# 2. Reject the 3.x version of any dupes.
functions = functions.reject do |func|
duplicates.include?(func['name']) && func['type'] != 'ruby4x'
end

# renders the list of functions
body = render_erb(FUNCTIONS_TEMPLATE_ERB, functions: functions)

# This substitution could potentially make things a bit brittle, but it has to be done because the jump
# From H2s to H4s is causing issues with the DITA-OT, which sees this as a rule violation. If it
# Does become an issue, we should return to this and figure out a better way to generate the functions doc.
body.gsub!(/#####\s(.*?:)/,'**\1**').gsub!(/####\s/,'### ').chomp!

# renders the preamble and list of functions
generate_reference('function', FUNCTION_ERB, body, FUNCTION_MD)
end
end
2 changes: 2 additions & 0 deletions rakelib/manpages.rake
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ task :gen_manpages do

non_face_applications = helpface.legacy_applications
faces = Puppet::Face.faces.map(&:to_s)
# exclude puppet-strings
faces.delete('strings')
apps = non_face_applications + faces

ronn_args = '--manual="Puppet manual" --organization="Puppet, Inc." --roff'
Expand Down
37 changes: 37 additions & 0 deletions rakelib/references/function.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
layout: default
built_from_commit: <%= sha %>
title: Built-in function reference
canonical: "/puppet/latest/function.html"
toc_levels: 2
toc: columns
---

# Built-in function reference

> **NOTE:** This page was generated from the Puppet source code on <%= now %>



This page is a list of Puppet's built-in functions, with descriptions of what they do and how to use them.

Functions are plugins you can call during catalog compilation. A call to any function is an expression that resolves to a value. For more information on how to call functions, see [the language reference page about function calls.](lang_functions.dita)

Many of these function descriptions include auto-detected _signatures,_ which are short reminders of the function's allowed arguments. These signatures aren't identical to the syntax you use to call the function; instead, they resemble a parameter list from a Puppet [class](lang_classes.dita), [defined resource type](lang_defined_types.dita), [function](lang_write_functions_in_puppet.dita), or [lambda](lang_lambdas.dita). The syntax of a signature is:

```
<FUNCTION NAME>(<DATA TYPE> <ARGUMENT NAME>, ...)
```

The `<DATA TYPE>` is a [Puppet data type value](lang_data_type.dita), like `String` or `Optional[Array[String]]`. The `<ARGUMENT NAME>` is a descriptive name chosen by the function's author to indicate what the argument is used for.

* Any arguments with an `Optional` data type can be omitted from the function call.
* Arguments that start with an asterisk (like `*$values`) can be repeated any number of times.
* Arguments that start with an ampersand (like `&$block`) aren't normal arguments; they represent a code block, provided with [Puppet's lambda syntax.](lang_lambdas.dita)

## `undef` values in Puppet 6

In Puppet 6, many Puppet types were moved out of the Puppet codebase, and into modules on the Puppet Forge. The new functions handle `undef` values more strictly than their stdlib counterparts. In Puppet 6, code that relies on `undef` values being implicitly treated as other types will return an evaluation error. For more information on which types were moved into modules, see the [Puppet 6 release notes](https://puppet.com/docs/puppet/6.0/release_notes_puppet.html#select-types-moved-to-modules).


<%= body %>
47 changes: 47 additions & 0 deletions rakelib/references/functions_template.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<% functions.sort{|a,b| a['name'] <=> b['name'] }.each do |func| -%>
## `<%= func['name'] %>`

<%= func['docstring']['text'] %>

<% func_signatures = func['signatures']
multiple_signatures = func_signatures.count > 1
if func_signatures
func['signatures'].each_with_index do |signature, index| -%>

<% if multiple_signatures -%>
Signature <%= index+1 %>

<% end -%>
`<%= signature['signature'] %>`
<% has_parameters = signature.dig('docstring', 'tags')&.detect {|tag| tag['tag_name'] == 'param' && tag['text'] != '' && tag['text'] != nil } || false
if has_parameters -%>

### Parameters

<% signature['docstring']['tags'].select {|tag| tag['tag_name'] == 'param' && tag['text'] != '' && tag['text'] != nil}.each do |param| -%>

* `<%= param['name'] %>` --- <%= param['text'] %>
<% end # each param

return_types = signature['docstring']['tags'].detect {|tag| tag['tag_name'] == 'return'}
if return_types -%>

Return type(s): <%= return_types['types'].map {|t| "`#{t}`"}.join(', ') %>. <%= return_types['text'] %>
<% end # if return_types
has_examples = signature['docstring']['tags'].detect {|tag| tag['tag_name'] == 'example' && tag['text'] != '' && tag['text'] != nil }
if has_examples %>

### Examples

<% signature['docstring']['tags'].select {|tag| tag['tag_name'] == 'example' && tag['text'] != '' && tag['text'] != nil}.each do |example| -%>
<%= example['name'] %>

<%= example['text'] %>

<% end # each example
end # if has_examples
end-%>
<% end # each signature
end -%>

<% end -%>
Loading

0 comments on commit 0e2c0b4

Please sign in to comment.