Skip to content
This repository has been archived by the owner on Feb 27, 2020. It is now read-only.

Commit

Permalink
Merge pull request #234 from taskcluster/worker-docs
Browse files Browse the repository at this point in the history
Abstractions to let plugins and engines export end-user documentation
  • Loading branch information
jonasfj committed Apr 18, 2017
2 parents 1e09991 + 670c93b commit 472a4bd
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 0 deletions.
11 changes: 11 additions & 0 deletions engines/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ type SandboxOptions struct {
// can be implemented on all platforms. See individual methods to see which are
// required and which can be implemented by returning ErrFeatureNotSupported.
type Engine interface {
// Documentation returns a list of sections with end-user documentation.
//
// These sections will be combined with documentation sections from all
// enabled plugins in-order to form end-user documentation.
Documentation() []runtime.Section

// PayloadSchema returns a JSON schema description of the payload options,
// accepted by this engine.
PayloadSchema() schematypes.Object
Expand Down Expand Up @@ -130,6 +136,11 @@ type Capabilities struct {
// compatibility when we add more optional methods to Engine.
type EngineBase struct{}

// Documentation returns no documentation.
func (EngineBase) Documentation() []runtime.Section {
return nil
}

// PayloadSchema returns an empty schematypes.Object indicating no contraints
// on keys of the payload object.
func (EngineBase) PayloadSchema() schematypes.Object {
Expand Down
11 changes: 11 additions & 0 deletions plugins/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ type TaskPluginOptions struct {
//
// All methods on this interface must be thread-safe.
type Plugin interface {
// Documentation returns a list of sections with end-user documentation.
//
// These sections will be combined with documentation sections from all
// enabled plugins in-order to form end-user documentation.
Documentation() []runtime.Section

// PayloadSchema returns a schematypes.Object with the properties for
// for the TaskPluginOptions.Payload property.
//
Expand Down Expand Up @@ -174,6 +180,11 @@ type TaskPlugin interface {
// new optional methods.
type PluginBase struct{}

// Documentation returns no documentation.
func (PluginBase) Documentation() []runtime.Section {
return nil
}

// PayloadSchema returns a schema for an empty object for plugins that doesn't
// take any payload.
func (PluginBase) PayloadSchema() schematypes.Object {
Expand Down
20 changes: 20 additions & 0 deletions plugins/pluginmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,26 @@ func NewPluginManager(options PluginOptions) (*PluginManager, error) {
}, nil
}

// Documentation will collect documentation from all managed plugins.
func (pm *PluginManager) Documentation() []runtime.Section {
pluginDocs := make([][]runtime.Section, len(pm.plugins))
spawn(len(pm.plugins), func(i int) {
m := pm.monitors[i].WithTag("hook", "Documentation")
incidentID := capturePanicOrTimeout(m, func() {
pluginDocs[i] = pm.plugins[i].Documentation()
})
if incidentID != "" {
m.Errorf("stopping worker now due to panic reported as incidentID=%s", incidentID)
pm.environment.Worker.StopNow()
}
})
docs := []runtime.Section{}
for _, sections := range pluginDocs {
docs = append(docs, sections...)
}
return docs
}

// ReportIdle call ReportIdle on all the managed plugins.
func (pm *PluginManager) ReportIdle(durationSinceBusy time.Duration) {
spawn(len(pm.plugins), func(i int) {
Expand Down
27 changes: 27 additions & 0 deletions runtime/docs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package runtime

import (
"fmt"
"sort"
)

// A Section represents a section of markdown documentation.
type Section struct {
Title string // Title of section rendered as headline level 2
Content string // Section contents, maybe contains headline level 3 and higher
}

// RenderDocument creates a markdown document with given title from a list of
// sections. Ordering sections alphabetically.
func RenderDocument(title string, sections []Section) string {
sections = append([]Section{}, sections...)
sort.Slice(sections, func(i int, j int) bool {
return sections[i].Title < sections[j].Title
})

docs := fmt.Sprintf("# %s\n", title)
for _, section := range sections {
docs += fmt.Sprintf("\n\n## %s\n%s\n", section.Title, section.Content)
}
return docs
}

0 comments on commit 472a4bd

Please sign in to comment.