mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-08-10 20:32:54 +00:00
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:
parent
7f3c12f1dd
commit
66f3944b52
32
tests/cmd/github-labels/Makefile
Normal file
32
tests/cmd/github-labels/Makefile
Normal 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
|
71
tests/cmd/github-labels/README.md
Normal file
71
tests/cmd/github-labels/README.md
Normal 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).
|
1
tests/cmd/github-labels/VERSION
Normal file
1
tests/cmd/github-labels/VERSION
Normal file
@ -0,0 +1 @@
|
||||
0.0.1
|
50
tests/cmd/github-labels/archive/README.md
Normal file
50
tests/cmd/github-labels/archive/README.md
Normal 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
|
||||
|
||||
```
|
||||
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
216
tests/cmd/github-labels/check.go
Normal file
216
tests/cmd/github-labels/check.go
Normal 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)
|
||||
}
|
62
tests/cmd/github-labels/clean.go
Normal file
62
tests/cmd/github-labels/clean.go
Normal 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)
|
||||
}
|
83
tests/cmd/github-labels/display.go
Normal file
83
tests/cmd/github-labels/display.go
Normal 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)
|
||||
}
|
75
tests/cmd/github-labels/display_markdown.go
Normal file
75
tests/cmd/github-labels/display_markdown.go
Normal 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
|
||||
}
|
101
tests/cmd/github-labels/display_text.go
Normal file
101
tests/cmd/github-labels/display_text.go
Normal 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
|
||||
}
|
66
tests/cmd/github-labels/display_tsv.go
Normal file
66
tests/cmd/github-labels/display_tsv.go
Normal 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()
|
||||
}
|
176
tests/cmd/github-labels/github-labels.sh
Executable file
176
tests/cmd/github-labels/github-labels.sh
Executable 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 "$@"
|
555
tests/cmd/github-labels/labels.yaml
Normal file
555
tests/cmd/github-labels/labels.yaml
Normal 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
|
555
tests/cmd/github-labels/labels.yaml.in
Normal file
555
tests/cmd/github-labels/labels.yaml.in
Normal 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
|
157
tests/cmd/github-labels/main.go
Normal file
157
tests/cmd/github-labels/main.go
Normal 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)
|
||||
}
|
||||
}
|
102
tests/cmd/github-labels/record.go
Normal file
102
tests/cmd/github-labels/record.go
Normal 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
|
||||
}
|
55
tests/cmd/github-labels/types.go
Normal file
55
tests/cmd/github-labels/types.go
Normal 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
|
||||
}
|
24
tests/cmd/github-labels/utils.go
Normal file
24
tests/cmd/github-labels/utils.go
Normal 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
|
||||
}
|
72
tests/cmd/github-labels/yaml.go
Normal file
72
tests/cmd/github-labels/yaml.go
Normal 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)
|
||||
}
|
Loading…
Reference in New Issue
Block a user