tests: move github-labels to main repo

Move tool as part of static checks migration.

Fixes #8187

Signed-off-by: Chelsea Mafrica <chelsea.e.mafrica@intel.com>
Signed-off-by: Derek Lee <derlee@redhat.com>
Signed-off-by: Gabriela Cervantes <gabriela.cervantes.tellez@intel.com>
Signed-off-by: Graham Whaley <graham.whaley@intel.com>
Signed-off-by: James O. D. Hunt <james.o.hunt@intel.com>
Signed-off-by: Marco Vedovati <mvedovati@suse.com>
Signed-off-by: Peng Tao <bergwolf@hyper.sh>
Signed-off-by: Shiming Zhang <wzshiming@foxmail.com>
Signed-off-by: Snir Sheriber <ssheribe@redhat.com>
Signed-off-by: Wainer dos Santos Moschetta <wainersm@redhat.com>
This commit is contained in:
Chelsea Mafrica 2023-11-21 17:48:18 -08:00
parent 7f3c12f1dd
commit 66f3944b52
22 changed files with 2642 additions and 0 deletions

View File

@ -0,0 +1,32 @@
#
# Copyright (c) 2017-2019 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0
#
TARGET = kata-github-labels
SOURCES = $(shell find . -type f 2>&1 | grep -E '.*\.go$$')
VERSION := ${shell cat ./VERSION}
COMMIT_NO := $(shell git rev-parse HEAD 2> /dev/null || true)
COMMIT := $(if $(shell git status --porcelain --untracked-files=no),"${COMMIT_NO}-dirty","${COMMIT_NO}")
BINDIR := $(GOPATH)/bin
DESTTARGET := $(abspath $(BINDIR)/$(TARGET))
default: install
check: $(SOURCES)
go test -v ./...
$(TARGET): $(SOURCES)
go build -o "$(TARGET)" -ldflags "-X main.name=${TARGET} -X main.commit=${COMMIT} -X main.version=${VERSION}" .
install: $(TARGET)
install -d $(shell dirname $(DESTTARGET))
install $(TARGET) $(DESTTARGET)
clean:
rm -f $(TARGET)
.PHONY: install clean

View File

@ -0,0 +1,71 @@
# Overview
The Kata Project uses a number of GitHub repositories. To allow issues and PRs
to be handled consistently between repositories a standard set of issue labels
are used. These labels are stored in YAML format in the master
[labels database template](labels.yaml.in). This file is human-readable,
machine-readable, and self-describing (see the file for the introductory
description).
Each repository can contain a set of additional (repository-specific) labels,
which are stored in a top-level YAML template file called `labels.yaml.in`.
Expanding the templates and merging the two databases describes the full set
of labels a repository uses.
# Generating the combined labels database
You can run the `github_labels.sh` script with the `generate` argument to
create the combined labels database. The additional arguments specify the
repository (in order to generate the combined labels database) and the name of
a file to write the combined database:
```sh
$ ./github-labels.sh generate github.com/kata-containers/kata-containers /tmp/combined.yaml
```
This script validates the combined labels database by performing a number of
checks, including running the `kata-github-labels` tool in checking mode. See
the
[Checking and summarising the labels database](#checking-and-summarising-the-labels-database)
section for more information.
# Checking and summarising the labels database
The `kata-github-labels` tool checks and summarizes the labels database for
each repository.
## Show labels
Displays a summary of the labels:
```sh
$ kata-github-labels show labels labels.yaml
```
## Show categories
Shows all information about categories:
```sh
$ kata-github-labels show categories --with-labels labels.yaml
```
## Check only
Performs checks on a specified labels database:
```sh
$ kata-github-labels check labels.yaml
```
## Full details
Lists all available options:
```sh
$ kata-github-labels -h
```
# Archive of old GitHub labels
See the [archive documentation](archive).

View File

@ -0,0 +1 @@
0.0.1

View File

@ -0,0 +1,50 @@
# GitHub labels archive
## Overview
This directory contains one YAML file per repository containing the original
set of GitHub labels before the
[new ones were applied on 2019-06-04](../labels.yaml.in).
## How the YAML files were created
This section explains how the YAML files were created.
The [`labeler`](https://github.com/tonglil/labeler) tool was used to read
the labels and write them to a YAML file.
### Install and patch the `labeler` tool
This isn't ideal but our [labels database](../labels.yaml.in) mandates
descriptions for every label. However, at the time of writing, the `labeler`
tool does not support descriptions. But,
[there is a PR](https://github.com/tonglil/labeler/pull/37)
to add in description support.
To enable description support:
```sh
$ go get -u github.com/tonglil/labeler
$ cd $GOPATH/src/github.com/tonglil/labeler
$ pr=37
$ pr_branch="PR${pr}"
$ git fetch origin "refs/pull/${pr}/head:{pr_branch}"
$ git checkout "${pr_branch}"
$ go install -v ./...
```
### Save GitHub labels for a repository
Run the following for reach repository:
```sh
$ labeler scan -r ${github_repo_slug} ${output_file}
```
For example, to save the labels for the `tests` repository:
```sh
$ labeler scan -r kata-containers/tests tests.yaml
```

View File

@ -0,0 +1,58 @@
# Scanned and autogenerated by https://github.com/tonglil/labeler
---
repo: kata-containers/ci
labels:
- name: P1
color: b60205
description: Highest priority issue (Critical)
- name: P2
color: d93f0b
description: Urgent issue
- name: P3
color: fbca04
description: Important issue
- name: P4
color: fef2c0
description: Noteworthy issue
- name: backlog
color: ededed
- name: bitesize
color: d4c5f9
description: small/easy task
- name: bug
color: d73a4a
description: Something isn't working
- name: do-not-merge
color: b60205
- name: duplicate
color: cfd3d7
description: This issue or pull request already exists
- name: enhancement
color: a2eeef
description: New feature or request
- name: good first issue
color: 7057ff
description: Good for newcomers
- name: help wanted
color: "008672"
description: Extra attention is needed
- name: in progress
color: ededed
- name: invalid
color: e4e669
description: This doesn't seem right
- name: next
color: ededed
- name: question
color: d876e3
description: Further information is requested
- name: review
color: ededed
- name: security
color: fbca04
- name: wip
color: b60205
description: Work In Progress
- name: wontfix
color: ffffff
description: This will not be worked on

View File

@ -0,0 +1,27 @@
# Scanned and autogenerated by https://github.com/tonglil/labeler
---
repo: kata-containers/community
labels:
- name: WIP
color: b60205
- name: bitesize
color: d4c5f9
description: small/easy task
- name: bug
color: ee0701
- name: do-not-merge
color: b60205
- name: duplicate
color: cccccc
- name: enhancement
color: 84b6eb
- name: good first issue
color: 7057ff
- name: help wanted
color: 33aa3f
- name: invalid
color: e6e6e6
- name: question
color: cc317c
- name: wontfix
color: ffffff

View File

@ -0,0 +1,44 @@
# Scanned and autogenerated by https://github.com/tonglil/labeler
---
repo: kata-containers/kata-containers
labels:
- name: P1
color: b60205
description: Highest priority issue (Critical)
- name: P2
color: d93f0b
description: Urgent issue
- name: P3
color: fbca04
description: Important issue
- name: P4
color: fef2c0
description: Noteworthy issue
- name: bitesize
color: d4c5f9
description: small/easy task
- name: bug
color: ee0701
- name: devices
color: 006b75
description: direct device support
- name: duplicate
color: cccccc
- name: enhancement
color: 84b6eb
- name: feature
color: ef70a3
- name: good first issue
color: 7057ff
- name: help wanted
color: 33aa3f
- name: invalid
color: e6e6e6
- name: limitation
color: c2e0c6
- name: question
color: cc317c
- name: security
color: fbca04
- name: wontfix
color: ffffff

View File

@ -0,0 +1,60 @@
# Scanned and autogenerated by https://github.com/tonglil/labeler
---
repo: kata-containers/tests
labels:
- name: CI
color: 0052cc
description: Continuous Integration
- name: P1
color: b60205
description: Highest priority issue (Critical)
- name: P2
color: d93f0b
description: Urgent issue
- name: P3
color: fbca04
description: Important issue
- name: P4
color: fef2c0
description: Noteworthy issue
- name: backlog
color: ededed
- name: bitesize
color: d4c5f9
description: small/easy task
- name: bug
color: ee0701
- name: do-not-merge
color: b60205
- name: duplicate
color: cccccc
- name: enhancement
color: 84b6eb
- name: good first issue
color: 7057ff
- name: hackathon
color: 35bfa1
description: PR/Issues in hackathon events
- name: help wanted
color: 33aa3f
- name: in progress
color: ededed
- name: invalid
color: e6e6e6
- name: limitation
color: c2e0c6
- name: next
color: ededed
- name: question
color: cc317c
- name: review
color: ededed
- name: security
color: fbca04
- name: stable-candidate
color: bfdadc
description: Candidate to backport to stable branches
- name: wip
color: b60205
- name: wontfix
color: ffffff

View File

@ -0,0 +1,216 @@
// Copyright (c) 2019 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
package main
import (
"errors"
"fmt"
"strings"
"unicode"
)
func containsWhitespace(s string) bool {
for _, ch := range s {
if unicode.IsSpace(ch) {
return true
}
}
return false
}
func isLower(s string) bool {
for _, ch := range s {
if !unicode.IsLetter(ch) {
continue
}
if !unicode.IsLower(ch) {
return false
}
}
return true
}
func checkCategory(c Category) error {
if c.Name == "" {
return fmt.Errorf("category name cannot be blank: %+v", c)
}
if containsWhitespace(c.Name) {
return fmt.Errorf("category name cannot contain whitespace: %+v", c)
}
if !isLower(c.Name) {
return fmt.Errorf("category name must be all lower case: %+v", c)
}
if c.Description == "" {
return fmt.Errorf("category description cannot be blank: %+v", c)
}
first := c.Description[0]
if !unicode.IsUpper(rune(first)) {
return fmt.Errorf("category description needs initial capital letter: %+v", c)
}
if !strings.HasSuffix(c.Description, ".") {
return fmt.Errorf("category description needs trailing period: %+v", c)
}
return nil
}
func checkLabel(l Label) error {
if l.Name == "" {
return fmt.Errorf("label name cannot be blank: %+v", l)
}
if !isLower(l.Name) {
return fmt.Errorf("label name must be all lower case: %+v", l)
}
if containsWhitespace(l.Name) {
return fmt.Errorf("label name cannot contain whitespace: %+v", l)
}
if l.Description == "" {
return fmt.Errorf("label description cannot be blank: %+v", l)
}
first := l.Description[0]
if !unicode.IsUpper(rune(first)) {
return fmt.Errorf("label description needs initial capital letter: %+v", l)
}
if l.CategoryName == "" {
return fmt.Errorf("label category name cannot be blank: %+v", l)
}
if l.Colour == "" {
return fmt.Errorf("label colour cannot be blank: %+v", l)
}
return nil
}
func checkLabelsAndCategories(lf *LabelsFile) error {
catCount := 0
var catNameMap map[string]int
var catDescMap map[string]int
var labelNameMap map[string]int
var labelDescMap map[string]int
catNameMap = make(map[string]int)
catDescMap = make(map[string]int)
labelNameMap = make(map[string]int)
labelDescMap = make(map[string]int)
for _, c := range lf.Categories {
if err := checkCategory(c); err != nil {
return err
}
catCount++
if _, ok := catNameMap[c.Name]; ok {
return fmt.Errorf("duplicate category name: %+v", c)
}
catNameMap[c.Name] = 0
if _, ok := catDescMap[c.Description]; ok {
return fmt.Errorf("duplicate category description: %+v", c)
}
catDescMap[c.Description] = 0
}
if catCount == 0 {
return errors.New("no categories found")
}
labelCount := 0
for _, l := range lf.Labels {
if err := checkLabel(l); err != nil {
return err
}
if _, ok := labelNameMap[l.Name]; ok {
return fmt.Errorf("duplicate label name: %+v", l)
}
labelNameMap[l.Name] = 0
if _, ok := labelDescMap[l.Description]; ok {
return fmt.Errorf("duplicate label description: %+v", l)
}
labelDescMap[l.Description] = 0
labelCount++
catName := l.CategoryName
var value int
var ok bool
if value, ok = catNameMap[catName]; !ok {
return fmt.Errorf("invalid category %v found for label %+v", catName, l)
}
// Record category name seen and count of occurrences
value++
catNameMap[catName] = value
}
if labelCount == 0 {
return errors.New("no labels found")
}
if debug {
fmt.Printf("DEBUG: category count: %v\n", catCount)
fmt.Printf("DEBUG: label count: %v\n", labelCount)
}
for name, count := range catNameMap {
if count == 0 {
return fmt.Errorf("category %v not used", name)
}
if debug {
fmt.Printf("DEBUG: category %v: label count: %d\n",
name, count)
}
}
return nil
}
func check(lf *LabelsFile) error {
if lf.Description == "" {
return errors.New("description cannot be blank")
}
if lf.Repo == "" {
return errors.New("repo cannot be blank")
}
if len(lf.Categories) == 0 {
return errors.New("no categories")
}
if len(lf.Labels) == 0 {
return errors.New("no labels")
}
return checkLabelsAndCategories(lf)
}

View File

@ -0,0 +1,62 @@
// Copyright (c) 2019 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
package main
import "strings"
func cleanString(s string) string {
result := strings.Replace(s, "\n", " ", -1)
result = strings.Replace(result, "\t", "\\t", -1)
result = strings.TrimSpace(result)
return result
}
func cleanLabel(l Label) Label {
return Label{
Name: cleanString(l.Name),
Description: cleanString(l.Description),
CategoryName: cleanString(l.CategoryName),
Colour: cleanString(l.Colour),
From: cleanString(l.From),
}
}
func cleanCategory(c *Category) {
c.Name = cleanString(c.Name)
c.Description = cleanString(c.Description)
c.URL = cleanString(c.URL)
}
func cleanCategories(lf *LabelsFile) {
var cleaned Categories
for _, c := range lf.Categories {
cleanCategory(&c)
cleaned = append(cleaned, c)
}
lf.Categories = cleaned
}
func cleanLabels(lf *LabelsFile) {
var cleaned Labels
for _, l := range lf.Labels {
new := cleanLabel(l)
cleaned = append(cleaned, new)
}
lf.Labels = cleaned
}
func clean(lf *LabelsFile) {
lf.Description = cleanString(lf.Description)
lf.Repo = cleanString(lf.Repo)
cleanCategories(lf)
cleanLabels(lf)
}

View File

@ -0,0 +1,83 @@
// Copyright (c) 2019 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
package main
import (
"os"
"sort"
)
var outputFile = os.Stdout
// displayHandler is an interface that all output display handlers
// (formatters) must implement.
type DisplayHandler interface {
DisplayLabels(lf *LabelsFile) error
DisplayCategories(lf *LabelsFile, showLabels bool) error
}
// DisplayHandlers encapsulates the list of available display handlers.
type DisplayHandlers struct {
handlers map[string]DisplayHandler
}
// handlers is a map of the available output format display handling
// implementations.
var handlers map[string]DisplayHandler
// NewDisplayHandlers create a new DisplayHandler.
func NewDisplayHandlers() *DisplayHandlers {
if handlers == nil {
handlers = make(map[string]DisplayHandler)
handlers["md"] = NewDisplayMD(outputFile)
handlers[textFormat] = NewDisplayText(outputFile)
handlers["tsv"] = NewDisplayTSV(outputFile)
}
h := &DisplayHandlers{
handlers: handlers,
}
return h
}
// find looks for a display handler corresponding to the specified format
func (d *DisplayHandlers) find(format string) DisplayHandler {
for f, handler := range d.handlers {
if f == format {
return handler
}
}
return nil
}
// Get returns a list of the available formatters (display handler names).
func (d *DisplayHandlers) Get() []string {
var formats []string
for f := range d.handlers {
formats = append(formats, f)
}
sort.Strings(formats)
return formats
}
func show(inputFilename string, handler DisplayHandler, what DataToShow, withLabels bool) error {
lf, err := readYAML(inputFilename)
if err != nil {
return err
}
if what == showLabels {
return handler.DisplayLabels(lf)
}
return handler.DisplayCategories(lf, withLabels)
}

View File

@ -0,0 +1,75 @@
// Copyright (c) 2019 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
package main
import (
"os"
"github.com/olekukonko/tablewriter"
)
type displayMD struct {
writer *tablewriter.Table
}
func NewDisplayMD(file *os.File) DisplayHandler {
md := &displayMD{}
md.writer = tablewriter.NewWriter(file)
md.writer.SetCenterSeparator("|")
md.writer.SetBorders(tablewriter.Border{
Left: true,
Right: true,
Top: false,
Bottom: false,
})
// Critical for GitHub Flavoured Markdown
md.writer.SetAutoWrapText(false)
return md
}
func (d *displayMD) render(headerFields []string, records [][]string) {
d.writer.SetHeader(headerFields)
d.writer.AppendBulk(records)
d.writer.Render()
}
func (d *displayMD) DisplayLabels(lf *LabelsFile) error {
var records [][]string
for _, l := range lf.Labels {
record := labelToRecord(l, true)
records = append(records, record)
}
headerFields := labelHeaderRecord()
d.render(headerFields, records)
return nil
}
func (d *displayMD) DisplayCategories(lf *LabelsFile, showLabels bool) error {
headerFields := categoryHeaderRecord(showLabels)
var records [][]string
for _, c := range lf.Categories {
record, err := categoryToRecord(lf, c, showLabels, true)
if err != nil {
return err
}
records = append(records, record)
}
d.render(headerFields, records)
return nil
}

View File

@ -0,0 +1,101 @@
// Copyright (c) 2019 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
package main
import (
"fmt"
"os"
)
type displayText struct {
file *os.File
}
func NewDisplayText(file *os.File) DisplayHandler {
return &displayText{
file: file,
}
}
func (d *displayText) DisplayLabels(lf *LabelsFile) error {
_, err := fmt.Fprintf(d.file, "Labels (count: %d):\n", len(lf.Labels))
if err != nil {
return err
}
for _, l := range lf.Labels {
err = d.displayLabel(l)
if err != nil {
return err
}
}
return nil
}
func (d *displayText) displayLabel(l Label) error {
_, err := fmt.Fprintf(d.file, " %s (%q) [category %q, colour %q, from %q]\n",
l.Name,
l.Description,
l.CategoryName,
l.Colour,
l.From)
return err
}
func (d *displayText) DisplayCategories(lf *LabelsFile, showLabels bool) error {
_, err := fmt.Fprintf(d.file, "Categories (count: %d):\n", len(lf.Categories))
if err != nil {
return err
}
for _, c := range lf.Categories {
err := d.displayCategory(c, lf, showLabels)
if err != nil {
return err
}
}
return nil
}
func (d *displayText) displayCategory(c Category, lf *LabelsFile, showLabels bool) error {
if showLabels {
labels, err := getLabelsByCategory(c.Name, lf)
if err != nil {
return err
}
_, err = fmt.Fprintf(d.file, " %s (%q, label count: %d, url: %v)\n",
c.Name,
c.Description,
len(labels),
c.URL)
if err != nil {
return err
}
for _, label := range labels {
_, err := fmt.Fprintf(d.file, " %s (%q)\n",
label.Name,
label.Description)
if err != nil {
return err
}
}
} else {
_, err := fmt.Printf(" %s (%q, url: %v)\n",
c.Name,
c.Description,
c.URL)
if err != nil {
return err
}
}
return nil
}

View File

@ -0,0 +1,66 @@
// Copyright (c) 2019 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
package main
import (
"encoding/csv"
"os"
)
type displayTSV struct {
writer *csv.Writer
}
func NewDisplayTSV(file *os.File) DisplayHandler {
tsv := &displayTSV{}
tsv.writer = csv.NewWriter(file)
// Tab separator
tsv.writer.Comma = rune('\t')
return tsv
}
func (d *displayTSV) DisplayLabels(lf *LabelsFile) error {
record := labelHeaderRecord()
if err := d.writer.Write(record); err != nil {
return err
}
for _, l := range lf.Labels {
record := labelToRecord(l, false)
if err := d.writer.Write(record); err != nil {
return err
}
}
d.writer.Flush()
return d.writer.Error()
}
func (d *displayTSV) DisplayCategories(lf *LabelsFile, showLabels bool) error {
record := categoryHeaderRecord(showLabels)
if err := d.writer.Write(record); err != nil {
return err
}
for _, c := range lf.Categories {
record, err := categoryToRecord(lf, c, showLabels, false)
if err != nil {
return err
}
if err := d.writer.Write(record); err != nil {
return err
}
}
d.writer.Flush()
return d.writer.Error()
}

View File

@ -0,0 +1,176 @@
#!/bin/bash
#
# Copyright (c) 2019 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0
#
# Description: Generate the combined GitHub labels database for the
# specified repository.
set -e
script_name=${0##*/}
source "/etc/os-release" || "source /usr/lib/os-release"
self_dir=$(dirname "$(readlink -f "$0")")
cidir="${self_dir}/../../.ci"
source "${cidir}/lib.sh"
typeset -r labels_file="labels.yaml"
typeset -r labels_template="${labels_file}.in"
typeset -r master_labels_file="${self_dir}/${labels_file}"
typeset -r master_labels_template="${self_dir}/${labels_template}"
# The GitHub labels API requires a colour for each label so
# default to a white background.
typeset -r default_color="ffffff"
need_yq() {
# install yq if not exist
${cidir}/install_yq.sh
command -v yq &>/dev/null || \
die 'yq command not found. Ensure "$GOPATH/bin" is in your $PATH.'
}
merge_yaml()
{
local -r file1="$1"
local -r file2="$2"
local -r out="$3"
[ -n "$file1" ] || die "need 1st file"
[ -n "$file2" ] || die "need 2nd file"
[ -n "$out" ] || die "need output file"
need_yq
yq merge "$file1" --append "$file2" > "$out"
}
check_yaml()
{
local -r file="$1"
[ -n "$file" ] || die "need file to check"
need_yq
yq read "$file" >/dev/null
[ -z "$(command -v yamllint)" ] && die "need yamllint installed"
# Deal with different versions of the tool
local opts=""
local has_strict_opt=$(yamllint --help 2>&1|grep -- --strict)
[ -n "$has_strict_opt" ] && opts+="--strict"
yamllint $opts "$file"
}
# Expand the variables in the labels database.
generate_yaml()
{
local repo="$1"
local template="$2"
local out="$3"
[ -n "$repo" ] || die "need repo"
[ -n "$template" ] || die "need template"
[ -n "$out" ] || die "need output file"
local repo_slug=$(echo "${repo}"|sed 's!github.com/!!g')
sed \
-e "s|REPO_SLUG|${repo_slug}|g" \
-e "s|DEFAULT_COLOUR|${default_color}|g" \
"$template" > "$out"
check_yaml "$out"
}
cmd_generate()
{
local repo="$1"
local out_file="$2"
[ -n "$repo" ] || die "need repo"
[ -n "$out_file" ] || die "need output file"
# Create the master database from the template
generate_yaml \
"${repo}" \
"${master_labels_template}" \
"${master_labels_file}"
local -r repo_labels_template="${GOPATH}/src/${repo}/${labels_template}"
local -r repo_labels_file="${GOPATH}/src/${repo}/${labels_file}"
# Check for a repo-specific set of labels
if [ -e "${repo_labels_template}" ]; then
info "Found repo-specific labels database"
# Generate repo-specific labels from template
generate_yaml \
"${repo}" \
"${repo_labels_template}" \
"${repo_labels_file}"
# Combine the two databases
tmp=$(mktemp)
merge_yaml \
"${master_labels_file}" \
"${repo_labels_file}" \
"${tmp}"
mv "${tmp}" "${out_file}"
else
info "No repo-specific labels database"
cp "${master_labels_file}" "${out_file}"
fi
info "Generated labels database ${out_file}"
# Perform checks
kata-github-labels check "${out_file}"
}
usage()
{
cat <<EOF
Usage: ${script_name} help
${script_name} generate <repo-name> <output-file>
Examples:
# Generate combined labels database for runtime repo and write to
# specified file
\$ ${script_name} generate github.com/kata-containers/kata-containers /tmp/out.yaml
EOF
}
main()
{
case "$1" in
generate)
shift
cmd_generate "$@"
;;
help|"")
usage
exit 0
;;
*)
die "Invalid command: '$1'"
;;
esac
}
main "$@"

View File

@ -0,0 +1,555 @@
# Copyright (c) 2019 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0
#
---
description: |
This file contains a list of all the generic GitHub labels used by all Kata
Containers GitHub repositories.
Each repository can optionally contain a top-level `labels.yaml` that
specifies a list of repository-specific labels (and possibly additional
categories). The labels in the repository-specific labels file plus the
labels defined in this file define the minimum list of labels for the
repository in question.
Each label must specify:
- Name (which must be lower-case without spaces)
- Description
- Category
- Colour (explicit colour, or `ffffff`)
A label may also specify a "From" value. This is used for renaming labels;
if a label has an associated "From" value, an existing label whose name is
specified by the "From" value will be renamed to the label name.
A category is a collective name used to describe one or more related labels.
Each category must specify:
- Name (which must be lower-case without spaces)
- Description
A category may also specify a related URL which points to a document
containing further information.
categories:
- name: api
description: Change related to an Application Programming Interface.
- name: architecture-committee
description: Needs input from the Architecture Committee.
url: https://github.com/kata-containers/community#architecture-committee
- name: area
description: Code component / general part of product affected.
- name: backport
description: |
Code that needs to be applied to other branches, generally older stable
ones.
- name: behaviour
description: |
How the issue affect the operation of the system. A more precise version
of regression.
- name: block
description: |
Stop a PR from being merged.
- name: cleanup
description: Refactoring, restructuring or general tidy-up needed.
- name: customer
description: Related to a customer.
- name: design
description: Requires formal review on the approach to solving the problem.
- name: detail
description: Need further information from the user or author.
- name: documentation
description: Needs more documentation.
- name: environment
description: Related to particular system environment.
- name: help
description: |
Request for technical help / extra resource. Also used for assisted
workflow.
- name: label-admin
description: Relates to the administration of labels.
- name: limitation
description: |
Issue cannot be resolved (too hard/impossible, would be too slow,
insufficient resources, etc).
url: |
https://github.com/kata-containers/kata-containers/blob/main/docs/Documentation-Requirements.md
- name: new-contributor
description: Small, self-contained tasks suitable for newcomers.
url: |
https://github.com/kata-containers/community/blob/main/CONTRIBUTING.md
- name: priority
description: |
Relative urgency (time-critical).
- name: question
description: Needs input from the team.
- name: rebase
description: Code conflicts need to be resolved.
- name: related
description: |
Related project. Base set can be generated from
https://github.com/kata-containers/kata-containers/blob/main/versions.yaml.
- name: release
description: Related to production of new versions.
- name: resolution
description: |
Issue is not (or no longer) valid for some reason. Label specifies
reason for closing.
- name: security
description: Potential or actual vulnerability / CVE.
url: https://github.com/kata-containers/community/blob/main/VMT/VMT.md
- name: severity
description: Relative importance (mission-critical).
- name: sizing
description: Estimate of the complexity of the task (story points).
- name: sub-type
description: More specific detail on the type category.
- name: team
description: Team that needs to analyse the issue.
- name: test
description: New tests needed.
- name: type
description: High-level summary of the issue.
- name: vendor
description: Related to handling imported code.
url: |
https://github.com/kata-containers/community/blob/main/CONTRIBUTING.md#re-vendor-prs
repo: kata-containers/kata-containers
labels:
- name: api-breakage
description: API was broken
category: api
color: ff0000
- name: api-change
description: API change
category: api
color: ffffff
- name: architecture-specific
description: Affects subset of architectures
category: environment
color: ffffff
- name: area/api
description: Application Programming Interface
category: area
color: ffffff
- name: area/cli
description: Command Line Interface (flags/options and arguments)
category: area
color: ffffff
- name: area/comms
description: Communications (gRPC, Yamux, etc)
category: area
color: ffffff
- name: area/config
description: Configuration
category: area
color: ffffff
- name: area/logging
description: Logging
category: area
color: ffffff
- name: area/networking
description: Networking
category: area
color: ffffff
- name: area/storage
description: Storage
category: area
color: ffffff
- name: area/tracing
description: Tracing
category: area
color: ffffff
- name: backport
description: Code needs to be applied to older (stable) releases
category: backport
color: ffffff
- name: bug
description: Incorrect behaviour
category: type
color: ff0000
- name: cannot-reproduce
description: Issue cannot be recreated
category: resolution
color: ffffff
- name: cleanup
description: General tidy-up
category: cleanup
color: ffffff
- name: crash
description: Causes part of the system to crash
category: behaviour
color: ffffff
- name: customer
description: Relates to a customer
category: customer
color: ffffff
- name: data-loss
description: System loses information
category: behaviour
color: ffffff
- name: deprecate
description: Highlight a feature that will soon be removed
category: cleanup
color: ffffff
- name: do-not-merge
description: PR has problems or depends on another
category: block
color: ff0000
- name: duplicate
description: Same issue as one already reported
category: resolution
color: ffffff
- name: enhancement
description: Improvement to an existing feature
category: type
color: ffffff
- name: feature
description: New functionality
category: type
color: ffffff
- name: good-first-issue
description: Small and simple task for new contributors
category: new-contributor
color: ffffff
- name: hang
description: System appears to stop operating or freeze
category: behaviour
color: ffffff
- name: high-priority
description: Very urgent issue (resolve quickly)
category: priority
color: ff7f00
- name: high-severity
description: Very important issue
category: severity
color: 00d7ff
- name: highest-priority
description: Critically urgent issue (must be resolved as soon as possible)
category: priority
color: ff0000
- name: highest-severity
description: Extremely important issue
category: severity
color: 00ffff
- name: invalid
description: Issue does not make sense
category: resolution
color: ffffff
- name: limitation
description: Issue cannot be resolved
category: limitation
color: ffffff
- name: medium-priority
description: Urgent issue (resolve before unprioritised issues)
category: priority
color: ffff00
- name: medium-severity
description: Important issue
category: severity
color: 0000ff
- name: needs-decision
description: Requires input from the Architecture Committee
category: architecture-committee
color: ffffff
- name: needs-design-doc
description: Needs a document explaining the design
category: design
color: ffffff
- name: needs-design-review
description: Needs a formal design review of the approach
category: design
color: ffffff
- name: needs-docs
description: Needs some new or updated documentation
category: documentation
color: ffffff
- name: needs-help
description: Request for extra help (technical, resource, etc)
category: help
color: ffffff
- name: needs-integration-tests
description: |
Needs new system/integration tests to validate behaviour in the tests
repository
category: test
color: ffffff
- name: needs-more-info
description: Blocked until user or author provides further details
category: detail
color: ffffff
- name: needs-new-label
description: New label required to categorise this issue
category: label-admin
color: ffffff
- name: needs-rebase
description: PR contains conflicts which need resolving
category: rebase
color: ffffff
- name: needs-revendor
description: Needs imported code to be re-vendored
category: vendor
color: ffffff
- name: needs-review
description: Needs to be assessed by the team.
category: team
color: 00ff00
- name: needs-unit-tests
description: Needs new unit tests to validate behaviour in this repository
category: test
color: ffffff
- name: os-specific
description: Affects subset of operating system / distro versions
category: environment
color: ffffff
- name: performance
description: System runs too slowly
category: behaviour
color: ffffff
- name: question
description: Requires an answer
category: question
color: ffffff
- name: refactor
description: Remove duplication, improve organisation, etc
category: cleanup
color: ffffff
- name: regression
description: Behaviour inadvertently reverted to older behaviour
category: sub-type
color: ffffff
- name: related/containerd
description: Containerd
category: related
color: ffffff
- name: related/cri
description: CRI
category: related
color: ffffff
- name: related/crio
description: CRIO
category: related
color: ffffff
- name: related/docker
description: Docker
category: related
color: ffffff
- name: related/firecracker
description: Firecracker
category: related
color: ffffff
- name: related/k8s
description: Kubernetes
category: related
color: ffffff
- name: related/qemu
description: QEMU
category: related
color: ffffff
- name: related/runc
description: Runc
category: related
color: ffffff
- name: release-gating
description: Release must wait for this to be resolved before release
category: release
color: ffffff
- name: resource-hog
description: System uses too many resources (such as memory)
category: behaviour
color: ffffff
- name: resource-leak
description: System does not free resources (such as memory)
category: behaviour
color: ffffff
- name: rfc
description: Requires input from the team
category: question
color: ffffff
- name: security
description: Potential or actual security issue
category: security
color: ff0000
- name: size/huge
description: |
Largest and most complex task (probably needs breaking into small
pieces)
category: sizing
color: ffffff
- name: size/large
description: Task of significant size
category: sizing
color: ffffff
- name: size/medium
description: Average sized task
category: sizing
color: ffffff
- name: size/small
description: Small and simple task
category: sizing
color: ffffff
- name: size/tiny
description: Smallest and simplest task
category: sizing
color: ffffff
- name: stale
description: Issue or PR was not updated in a timely fashion
category: resolution
color: ffffff
- name: team/ci
description: Need Continuous Integration Team input
category: team
color: ffffff
- name: team/developer
description: Need Developer Team input
category: team
color: ffffff
- name: team/documentation
description: Need Documentation Team input
category: team
color: ffffff
- name: team/kernel
description: Need Kernel Team input
category: team
color: ffffff
- name: team/metrics
description: Need Metrics Team input
category: team
color: ffffff
- name: team/packaging
description: Need Packaging Team input
category: team
color: ffffff
- name: team/test
description: Need Test Team input
category: team
color: ffffff
- name: unreliable
description: Part of the system is not stable
category: behaviour
color: ffffff
- name: wip
description: Work in Progress (PR incomplete - needs more work or rework)
category: block
color: ff0000
- name: wont-fix
description: Issue will not be fixed (not a good use of limited resources)
category: resolution
color: ffffff
- name: wrong-repo
description: Raised in incorrect repository
category: resolution
color: ffffff

View File

@ -0,0 +1,555 @@
# Copyright (c) 2019 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0
#
---
description: |
This file contains a list of all the generic GitHub labels used by all Kata
Containers GitHub repositories.
Each repository can optionally contain a top-level `labels.yaml` that
specifies a list of repository-specific labels (and possibly additional
categories). The labels in the repository-specific labels file plus the
labels defined in this file define the minimum list of labels for the
repository in question.
Each label must specify:
- Name (which must be lower-case without spaces)
- Description
- Category
- Colour (explicit colour, or `DEFAULT_COLOUR`)
A label may also specify a "From" value. This is used for renaming labels;
if a label has an associated "From" value, an existing label whose name is
specified by the "From" value will be renamed to the label name.
A category is a collective name used to describe one or more related labels.
Each category must specify:
- Name (which must be lower-case without spaces)
- Description
A category may also specify a related URL which points to a document
containing further information.
categories:
- name: api
description: Change related to an Application Programming Interface.
- name: architecture-committee
description: Needs input from the Architecture Committee.
url: https://github.com/kata-containers/community#architecture-committee
- name: area
description: Code component / general part of product affected.
- name: backport
description: |
Code that needs to be applied to other branches, generally older stable
ones.
- name: behaviour
description: |
How the issue affect the operation of the system. A more precise version
of regression.
- name: block
description: |
Stop a PR from being merged.
- name: cleanup
description: Refactoring, restructuring or general tidy-up needed.
- name: customer
description: Related to a customer.
- name: design
description: Requires formal review on the approach to solving the problem.
- name: detail
description: Need further information from the user or author.
- name: documentation
description: Needs more documentation.
- name: environment
description: Related to particular system environment.
- name: help
description: |
Request for technical help / extra resource. Also used for assisted
workflow.
- name: label-admin
description: Relates to the administration of labels.
- name: limitation
description: |
Issue cannot be resolved (too hard/impossible, would be too slow,
insufficient resources, etc).
url: |
https://github.com/kata-containers/kata-containers/blob/main/docs/Documentation-Requirements.md
- name: new-contributor
description: Small, self-contained tasks suitable for newcomers.
url: |
https://github.com/kata-containers/community/blob/main/CONTRIBUTING.md
- name: priority
description: |
Relative urgency (time-critical).
- name: question
description: Needs input from the team.
- name: rebase
description: Code conflicts need to be resolved.
- name: related
description: |
Related project. Base set can be generated from
https://github.com/kata-containers/kata-containers/blob/main/versions.yaml.
- name: release
description: Related to production of new versions.
- name: resolution
description: |
Issue is not (or no longer) valid for some reason. Label specifies
reason for closing.
- name: security
description: Potential or actual vulnerability / CVE.
url: https://github.com/kata-containers/community/blob/main/VMT/VMT.md
- name: severity
description: Relative importance (mission-critical).
- name: sizing
description: Estimate of the complexity of the task (story points).
- name: sub-type
description: More specific detail on the type category.
- name: team
description: Team that needs to analyse the issue.
- name: test
description: New tests needed.
- name: type
description: High-level summary of the issue.
- name: vendor
description: Related to handling imported code.
url: |
https://github.com/kata-containers/community/blob/main/CONTRIBUTING.md#re-vendor-prs
repo: REPO_SLUG
labels:
- name: api-breakage
description: API was broken
category: api
color: ff0000
- name: api-change
description: API change
category: api
color: DEFAULT_COLOUR
- name: architecture-specific
description: Affects subset of architectures
category: environment
color: DEFAULT_COLOUR
- name: area/api
description: Application Programming Interface
category: area
color: DEFAULT_COLOUR
- name: area/cli
description: Command Line Interface (flags/options and arguments)
category: area
color: DEFAULT_COLOUR
- name: area/comms
description: Communications (gRPC, Yamux, etc)
category: area
color: DEFAULT_COLOUR
- name: area/config
description: Configuration
category: area
color: DEFAULT_COLOUR
- name: area/logging
description: Logging
category: area
color: DEFAULT_COLOUR
- name: area/networking
description: Networking
category: area
color: DEFAULT_COLOUR
- name: area/storage
description: Storage
category: area
color: DEFAULT_COLOUR
- name: area/tracing
description: Tracing
category: area
color: DEFAULT_COLOUR
- name: backport
description: Code needs to be applied to older (stable) releases
category: backport
color: DEFAULT_COLOUR
- name: bug
description: Incorrect behaviour
category: type
color: ff0000
- name: cannot-reproduce
description: Issue cannot be recreated
category: resolution
color: DEFAULT_COLOUR
- name: cleanup
description: General tidy-up
category: cleanup
color: DEFAULT_COLOUR
- name: crash
description: Causes part of the system to crash
category: behaviour
color: DEFAULT_COLOUR
- name: customer
description: Relates to a customer
category: customer
color: DEFAULT_COLOUR
- name: data-loss
description: System loses information
category: behaviour
color: DEFAULT_COLOUR
- name: deprecate
description: Highlight a feature that will soon be removed
category: cleanup
color: DEFAULT_COLOUR
- name: do-not-merge
description: PR has problems or depends on another
category: block
color: ff0000
- name: duplicate
description: Same issue as one already reported
category: resolution
color: DEFAULT_COLOUR
- name: enhancement
description: Improvement to an existing feature
category: type
color: DEFAULT_COLOUR
- name: feature
description: New functionality
category: type
color: DEFAULT_COLOUR
- name: good-first-issue
description: Small and simple task for new contributors
category: new-contributor
color: DEFAULT_COLOUR
- name: hang
description: System appears to stop operating or freeze
category: behaviour
color: DEFAULT_COLOUR
- name: high-priority
description: Very urgent issue (resolve quickly)
category: priority
color: ff7f00
- name: high-severity
description: Very important issue
category: severity
color: 00d7ff
- name: highest-priority
description: Critically urgent issue (must be resolved as soon as possible)
category: priority
color: ff0000
- name: highest-severity
description: Extremely important issue
category: severity
color: 00ffff
- name: invalid
description: Issue does not make sense
category: resolution
color: DEFAULT_COLOUR
- name: limitation
description: Issue cannot be resolved
category: limitation
color: DEFAULT_COLOUR
- name: medium-priority
description: Urgent issue (resolve before unprioritised issues)
category: priority
color: ffff00
- name: medium-severity
description: Important issue
category: severity
color: 0000ff
- name: needs-decision
description: Requires input from the Architecture Committee
category: architecture-committee
color: DEFAULT_COLOUR
- name: needs-design-doc
description: Needs a document explaining the design
category: design
color: DEFAULT_COLOUR
- name: needs-design-review
description: Needs a formal design review of the approach
category: design
color: DEFAULT_COLOUR
- name: needs-docs
description: Needs some new or updated documentation
category: documentation
color: DEFAULT_COLOUR
- name: needs-help
description: Request for extra help (technical, resource, etc)
category: help
color: DEFAULT_COLOUR
- name: needs-integration-tests
description: |
Needs new system/integration tests to validate behaviour in the tests
repository
category: test
color: DEFAULT_COLOUR
- name: needs-more-info
description: Blocked until user or author provides further details
category: detail
color: DEFAULT_COLOUR
- name: needs-new-label
description: New label required to categorise this issue
category: label-admin
color: DEFAULT_COLOUR
- name: needs-rebase
description: PR contains conflicts which need resolving
category: rebase
color: DEFAULT_COLOUR
- name: needs-revendor
description: Needs imported code to be re-vendored
category: vendor
color: DEFAULT_COLOUR
- name: needs-review
description: Needs to be assessed by the team.
category: team
color: 00ff00
- name: needs-unit-tests
description: Needs new unit tests to validate behaviour in this repository
category: test
color: DEFAULT_COLOUR
- name: os-specific
description: Affects subset of operating system / distro versions
category: environment
color: DEFAULT_COLOUR
- name: performance
description: System runs too slowly
category: behaviour
color: DEFAULT_COLOUR
- name: question
description: Requires an answer
category: question
color: DEFAULT_COLOUR
- name: refactor
description: Remove duplication, improve organisation, etc
category: cleanup
color: DEFAULT_COLOUR
- name: regression
description: Behaviour inadvertently reverted to older behaviour
category: sub-type
color: DEFAULT_COLOUR
- name: related/containerd
description: Containerd
category: related
color: DEFAULT_COLOUR
- name: related/cri
description: CRI
category: related
color: DEFAULT_COLOUR
- name: related/crio
description: CRIO
category: related
color: DEFAULT_COLOUR
- name: related/docker
description: Docker
category: related
color: DEFAULT_COLOUR
- name: related/firecracker
description: Firecracker
category: related
color: DEFAULT_COLOUR
- name: related/k8s
description: Kubernetes
category: related
color: DEFAULT_COLOUR
- name: related/qemu
description: QEMU
category: related
color: DEFAULT_COLOUR
- name: related/runc
description: Runc
category: related
color: DEFAULT_COLOUR
- name: release-gating
description: Release must wait for this to be resolved before release
category: release
color: DEFAULT_COLOUR
- name: resource-hog
description: System uses too many resources (such as memory)
category: behaviour
color: DEFAULT_COLOUR
- name: resource-leak
description: System does not free resources (such as memory)
category: behaviour
color: DEFAULT_COLOUR
- name: rfc
description: Requires input from the team
category: question
color: DEFAULT_COLOUR
- name: security
description: Potential or actual security issue
category: security
color: ff0000
- name: size/huge
description: |
Largest and most complex task (probably needs breaking into small
pieces)
category: sizing
color: DEFAULT_COLOUR
- name: size/large
description: Task of significant size
category: sizing
color: DEFAULT_COLOUR
- name: size/medium
description: Average sized task
category: sizing
color: DEFAULT_COLOUR
- name: size/small
description: Small and simple task
category: sizing
color: DEFAULT_COLOUR
- name: size/tiny
description: Smallest and simplest task
category: sizing
color: DEFAULT_COLOUR
- name: stale
description: Issue or PR was not updated in a timely fashion
category: resolution
color: DEFAULT_COLOUR
- name: team/ci
description: Need Continuous Integration Team input
category: team
color: DEFAULT_COLOUR
- name: team/developer
description: Need Developer Team input
category: team
color: DEFAULT_COLOUR
- name: team/documentation
description: Need Documentation Team input
category: team
color: DEFAULT_COLOUR
- name: team/kernel
description: Need Kernel Team input
category: team
color: DEFAULT_COLOUR
- name: team/metrics
description: Need Metrics Team input
category: team
color: DEFAULT_COLOUR
- name: team/packaging
description: Need Packaging Team input
category: team
color: DEFAULT_COLOUR
- name: team/test
description: Need Test Team input
category: team
color: DEFAULT_COLOUR
- name: unreliable
description: Part of the system is not stable
category: behaviour
color: DEFAULT_COLOUR
- name: wip
description: Work in Progress (PR incomplete - needs more work or rework)
category: block
color: ff0000
- name: wont-fix
description: Issue will not be fixed (not a good use of limited resources)
category: resolution
color: DEFAULT_COLOUR
- name: wrong-repo
description: Raised in incorrect repository
category: resolution
color: DEFAULT_COLOUR

View File

@ -0,0 +1,157 @@
// Copyright (c) 2019 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
// Description: Program to check and summarise the Kata GitHub
// labels YAML file.
package main
import (
"errors"
"fmt"
"os"
"github.com/urfave/cli"
)
type DataToShow int
const (
showLabels DataToShow = iota
showCategories DataToShow = iota
textFormat = "text"
defaultOutputFormat = textFormat
)
var errNeedYAMLFile = errors.New("need YAML file")
var (
// set by the build
name = ""
version = ""
commit = ""
debug = false
)
var formatFlag = cli.StringFlag{
Name: "format",
Usage: "display in specified format ('help' to show all)",
Value: defaultOutputFormat,
}
func commonHandler(context *cli.Context, what DataToShow, withLabels bool) error {
handlers := NewDisplayHandlers()
format := context.String("format")
if format == "help" {
availableFormats := handlers.Get()
for _, format := range availableFormats {
fmt.Fprintf(outputFile, "%s\n", format)
}
return nil
}
handler := handlers.find(format)
if handler == nil {
return fmt.Errorf("no handler for format %q", format)
}
if context.NArg() == 0 {
return errNeedYAMLFile
}
file := context.Args().Get(0)
return show(file, handler, what, withLabels)
}
func main() {
app := cli.NewApp()
app.Description = "tool to manipulate Kata GitHub labels"
app.Usage = app.Description
app.Version = fmt.Sprintf("%s %s (commit %v)", name, version, commit)
app.Flags = []cli.Flag{
cli.BoolFlag{
Name: "debug, d",
Usage: "enable debug output",
Destination: &debug,
},
}
app.Commands = []cli.Command{
{
Name: "check",
Usage: "Perform tests on the labels database",
Description: "Exit code denotes success",
Action: func(context *cli.Context) error {
if context.NArg() == 0 {
return errNeedYAMLFile
}
file := context.Args().Get(0)
return checkYAML(file)
},
},
{
Name: "show",
Usage: "Display labels database details",
Subcommands: []cli.Command{
{
Name: "categories",
Usage: "Display categories from labels database",
Flags: []cli.Flag{
formatFlag,
cli.BoolFlag{
Name: "with-labels",
Usage: "Add labels in each category to output",
},
},
Action: func(context *cli.Context) error {
withLabels := context.Bool("with-labels")
return commonHandler(context, showCategories, withLabels)
},
},
{
Name: "labels",
Usage: "Display labels from labels database",
Flags: []cli.Flag{
formatFlag,
},
Action: func(context *cli.Context) error {
withLabels := context.Bool("with-labels")
return commonHandler(context, showLabels, withLabels)
},
},
},
},
{
Name: "sort",
Usage: "Sort the specified YAML labels file and write to a new file",
Description: "Can be used to keep the master labels file sorted",
ArgsUsage: "<input-file> <output-file>",
Action: func(context *cli.Context) error {
if context.NArg() != 2 {
return errors.New("need two YAML files: <input-file> <output-file>")
}
from := context.Args().Get(0)
to := context.Args().Get(1)
return sortYAML(from, to)
},
},
}
err := app.Run(os.Args)
if err != nil {
fmt.Fprintf(os.Stderr, "ERROR: %v\n", err)
os.Exit(1)
}
}

View File

@ -0,0 +1,102 @@
// Copyright (c) 2019 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
package main
import (
"fmt"
"strings"
)
const (
labelNamesSeparator = ","
)
func labelToRecord(l Label, quote bool) (record []string) {
name := l.Name
category := l.CategoryName
colour := l.Colour
from := l.From
if quote {
name = fmt.Sprintf("`%s`", l.Name)
category = fmt.Sprintf("`%s`", l.CategoryName)
colour = fmt.Sprintf("`%s`", l.Colour)
if from != "" {
from = fmt.Sprintf("`%s`", l.From)
}
}
record = append(record, name)
record = append(record, l.Description)
record = append(record, category)
record = append(record, colour)
record = append(record, from)
return record
}
func labelHeaderRecord() []string {
return []string{
"Name",
"Description",
"Category",
"Colour",
"From",
}
}
func categoryHeaderRecord(showLabels bool) []string {
var fields []string
fields = append(fields, "Name")
fields = append(fields, "Description")
fields = append(fields, "URL")
if showLabels {
fields = append(fields, "Labels")
}
return fields
}
func categoryToRecord(lf *LabelsFile, c Category, showLabels, quote bool) ([]string, error) {
var record []string
name := c.Name
if quote {
name = fmt.Sprintf("`%s`", c.Name)
}
record = append(record, name)
record = append(record, c.Description)
record = append(record, c.URL)
if showLabels {
var labelNames []string
labels, err := getLabelsByCategory(c.Name, lf)
if err != nil {
return nil, err
}
for _, l := range labels {
labelName := l.Name
if quote {
labelName = fmt.Sprintf("`%s`", l.Name)
}
labelNames = append(labelNames, labelName)
}
result := strings.Join(labelNames, labelNamesSeparator)
record = append(record, result)
}
return record, nil
}

View File

@ -0,0 +1,55 @@
// Copyright (c) 2019 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
package main
type Category struct {
Name string
Description string
URL string `yaml:",omitempty"`
}
type Label struct {
Name string
Description string
CategoryName string `yaml:"category"`
Colour string `yaml:"color"`
From string `yaml:",omitempty"`
}
type Categories []Category
func (c Categories) Len() int {
return len(c)
}
func (c Categories) Swap(i, j int) {
c[i], c[j] = c[j], c[i]
}
func (c Categories) Less(i, j int) bool {
return c[i].Name < c[j].Name
}
type Labels []Label
func (l Labels) Len() int {
return len(l)
}
func (l Labels) Swap(i, j int) {
l[i], l[j] = l[j], l[i]
}
func (l Labels) Less(i, j int) bool {
return l[i].Name < l[j].Name
}
type LabelsFile struct {
Description string
Categories Categories
Repo string
Labels Labels
}

View File

@ -0,0 +1,24 @@
// Copyright (c) 2019 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
package main
import "errors"
func getLabelsByCategory(categoryName string, lf *LabelsFile) ([]Label, error) {
var labels []Label
if categoryName == "" {
return nil, errors.New("need category name")
}
for _, label := range lf.Labels {
if label.CategoryName == categoryName {
labels = append(labels, label)
}
}
return labels, nil
}

View File

@ -0,0 +1,72 @@
// Copyright (c) 2019 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
package main
import (
"fmt"
"os"
"sort"
yaml "gopkg.in/yaml.v2"
)
const fileMode os.FileMode = 0600
func readYAML(file string) (*LabelsFile, error) {
bytes, err := os.ReadFile(file)
if err != nil {
return nil, err
}
lf := LabelsFile{}
err = yaml.Unmarshal(bytes, &lf)
if err != nil {
return nil, err
}
sort.Sort(lf.Labels)
sort.Sort(lf.Categories)
clean(&lf)
err = check(&lf)
if err != nil {
return nil, fmt.Errorf("file was not in expected format: %v", err)
}
return &lf, nil
}
func writeYAML(lf *LabelsFile, file string) error {
bytes, err := yaml.Marshal(lf)
if err != nil {
return err
}
return os.WriteFile(file, bytes, fileMode)
}
func checkYAML(file string) error {
// read and check
_, err := readYAML(file)
if err == nil {
fmt.Printf("Checked file %v\n", file)
}
return err
}
func sortYAML(fromFile, toFile string) error {
// read and sort
lf, err := readYAML(fromFile)
if err != nil {
return err
}
return writeYAML(lf, toFile)
}