code: func properties(b *buildbot.Build) (result []*ui.PropertyGroup) {
  	groups := map[string]*ui.PropertyGroup{}
  	allProps := map[string]Prop{}
  	for _, prop := range b.Properties {
  		allProps[prop.Name] = Prop{
  			Value: prop.Value,
  			Group: prop.Source,
  		}
  	}
  	for key, prop := range allProps {
  		value := prop.Value
  		groupName := prop.Group
  		if _, ok := groups[groupName]; !ok {
  			groups[groupName] = &ui.PropertyGroup{GroupName: groupName}
  		}
  		vs := parseProp(value)
  		groups[groupName].Property = append(groups[groupName].Property, &ui.Property{
  			Key:   key,
  			Value: vs,
  		})
  	}
  	// Insert the groups into a list in alphabetical order.
  	// You have to make a separate sorting data structure because Go doesn't like
  	// sorting things for you.
  	groupNames := make([]string, 0, len(groups))
  	for n := range groups {
  		groupNames = append(groupNames, n)
  	}
  	sort.Strings(groupNames)
  	for _, k := range groupNames {
  		group := groups[k]
  		// Also take this oppertunity to sort the properties within the groups.
  		sort.Sort(group)
  		result = append(result, group)
  	}
  	return
  }
docs: // properties extracts all properties from buildbot builds and groups them into
  // property groups.