Skip to content

Commit

Permalink
Merge pull request #29 from openconfig/wenbli-dev
Browse files Browse the repository at this point in the history
Upload Badges for Widely Used Tools for Push to Master
  • Loading branch information
wenovus authored Jun 16, 2020
2 parents defbea2 + 1ce60be commit 3842ece
Show file tree
Hide file tree
Showing 17 changed files with 430 additions and 124 deletions.
14 changes: 14 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,17 @@ RUN pip3 install wheel && \
pip3 install --no-cache-dir -r /workspace/oc-pyang-repo/requirements.txt && \
pip3 install --no-cache-dir -r /workspace/pyangbind-repo/requirements.txt
# pip3 install pyangbind

RUN apt install -y npm && npm install -g npm && npm install -g badge-maker

# Downloading gcloud package
RUN curl https://dl.google.com/dl/cloudsdk/release/google-cloud-sdk.tar.gz > /tmp/google-cloud-sdk.tar.gz

# Installing the package
RUN mkdir -p /usr/local/gcloud \
&& tar -C /usr/local/gcloud -xvf /tmp/google-cloud-sdk.tar.gz \
&& /usr/local/gcloud/google-cloud-sdk/install.sh

# Adding the package path to local
ENV PATH $PATH:/usr/local/gcloud/google-cloud-sdk/bin

10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,16 @@ To run this CI tool on GCB for a GitHub project, the
[GCB App](https://github.com/marketplace/google-cloud-build) needs to be enabled
for the target OpenConfig models repo.

## Posting Status Badges

This is done through a code path in `post_results` that generates an
`upload-badge.sh` file if the CI was triggered on a master branch push. The
badge is created using the
[badge-maker](https://www.npmjs.com/package/badge-maker) package used by
[shields.io](https://shields.io/), whose output svg file is then uploaded to
cloud storage and made public. The script also sets the no-cache option to avoid
GitHub from excessively caching the badge.

## Future Improvements

A custom build container image would,
Expand Down
38 changes: 30 additions & 8 deletions cmd_gen/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ var (
modelRoot string // modelRoot is the root directory of the models.
repoSlug string // repoSlug is the "owner/repo" name of the models repo (e.g. openconfig/public).
commitSHA string
branchName string // branchName is the name of the branch where the commit occurred.
prNumber int
compatReports string // e.g. "goyang-ygot,pyangbind,[email protected]"
extraPyangVersions string // e.g. "1.2.3,3.4.5"
Expand Down Expand Up @@ -68,6 +69,7 @@ func init() {
flag.StringVar(&repoSlug, "repo-slug", "openconfig/public", "repo where CI is run")
flag.StringVar(&commitSHA, "commit-sha", "", "commit SHA of the PR")
flag.IntVar(&prNumber, "pr-number", 0, "PR number")
flag.StringVar(&branchName, "branch", "", "branch name of commit")
flag.StringVar(&compatReports, "compat-report", "", "comma-separated validators (e.g. goyang-ygot,[email protected],pyang@head) in compatibility report instead of a standalone PR status")
flag.StringVar(&skippedValidators, "skipped-validators", "", "comma-separated validators (e.g. goyang-ygot,[email protected],pyang@head) not to be ran at all, not even in the compatibility report")
flag.StringVar(&extraPyangVersions, "extra-pyang-versions", "", "comma-separated extra pyang versions to run")
Expand Down Expand Up @@ -225,7 +227,9 @@ func genOpenConfigValidatorScript(g labelPoster, validatorId, version string, mo
for _, modelDirName := range modelDirNames {
if disabledModelPaths[modelDirName] {
log.Printf("skipping disabled model directory %s", modelDirName)
g.PostLabel("skipped: "+modelDirName, commonci.LabelColors["orange"], owner, repo, prNumber)
if prNumber != 0 {
g.PostLabel("skipped: "+modelDirName, commonci.LabelColors["orange"], owner, repo, prNumber)
}
continue
}
cmdStr, err := genValidatorCommandForModelDir(validatorId, resultsDir, modelDirName, modelMap)
Expand Down Expand Up @@ -301,15 +305,31 @@ func main() {
log.Fatalf("modelDirName and validator can only be specified for local cmd generation")
}

badgeOnly := false
// If it's a push on master, just upload badge for normal validators as the only action.
if prNumber == 0 {
if branchName != "master" {
log.Fatalf("cmd_gen: There is no action to take for a non-master branch push, please re-examine your push triggers")
}
badgeOnly = true
}

// Skip testing non-widely used validators, as we don't need to post badges for those tools.
if badgeOnly {
for validatorId, validator := range commonci.Validators {
if !validator.IsWidelyUsedTool {
// Here we assume simply that non widely-used checks don't have a version specified.
skippedValidators += "," + validatorId
}
}
}

repoSplit := strings.Split(repoSlug, "/")
owner = repoSplit[0]
repo = repoSplit[1]
if commitSHA == "" {
log.Fatalf("no commit SHA")
}
if prNumber == 0 {
log.Fatalf("no PR number")
}

h, err := commonci.NewGitHubRequestHandler()
if err != nil {
Expand All @@ -324,9 +344,11 @@ func main() {
}

compatReports = commonci.ValidatorAndVersionsDiff(compatReports, skippedValidators)
// Notify later CI steps of the validators that should be reported as a compatibility report.
if err := ioutil.WriteFile(commonci.CompatReportValidatorsFile, []byte(compatReports), 0444); err != nil {
log.Fatalf("error while writing compatibility report validators file %q: %v", commonci.CompatReportValidatorsFile, err)
if !badgeOnly {
// Notify later CI steps of the validators that should be reported as a compatibility report.
if err := ioutil.WriteFile(commonci.CompatReportValidatorsFile, []byte(compatReports), 0444); err != nil {
log.Fatalf("error while writing compatibility report validators file %q: %v", commonci.CompatReportValidatorsFile, err)
}
}

_, compatValidatorsMap := commonci.GetValidatorAndVersionsFromString(compatReports)
Expand Down Expand Up @@ -367,7 +389,7 @@ func main() {
}

// Post initial PR status.
if !compatValidatorsMap[validatorId][version] {
if !badgeOnly && !compatValidatorsMap[validatorId][version] {
if errs := postInitialStatus(h, validatorId, version); errs != nil {
log.Fatal(errs)
}
Expand Down
1 change: 1 addition & 0 deletions cmd_gen/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ func (p *postLabelRecorder) PostLabel(labelName, labelColor, owner, repo string,
}

func TestGenOpenConfigLinterScript(t *testing.T) {
prNumber = 1
basicModelMap, err := commonci.ParseOCModels("testdata")
if err != nil {
t.Fatalf("TestGenOpenConfigLinterScript: Failed to parse models for testing: %v", err)
Expand Down
38 changes: 26 additions & 12 deletions commonci/commonci.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ const (
OutFileName = "out"
// FailFileName by convention contains the stderr of the script file.
FailFileName = "fail"
// BadgeUploadCmdFile is output by post_results to upload the correct
// status badge to GCS.
BadgeUploadCmdFile = "upload-badge.sh"
)

// AppendVersionToName appends the version to the given validator name
Expand Down Expand Up @@ -82,6 +85,9 @@ type Validator struct {
// ReportOnly indicates that it's not itself a validator, it's just a
// CI item that does reporting on other validators.
ReportOnly bool
// IsWidelyUsedTool indicates that the tool is a widely used tool whose
// status should be reported on the front page of the repository.
IsWidelyUsedTool bool
}

// StatusName determines the status description for the version of the validator.
Expand All @@ -97,28 +103,33 @@ var (
// The key is a unique identifier that's safe to use as a directory name.
Validators = map[string]*Validator{
"pyang": &Validator{
Name: "pyang",
IsPerModel: true,
Name: "pyang",
IsPerModel: true,
IsWidelyUsedTool: true,
},
"oc-pyang": &Validator{
Name: "OpenConfig Linter",
IsPerModel: true,
},
"pyangbind": &Validator{
Name: "pyangbind",
IsPerModel: true,
Name: "pyangbind",
IsPerModel: true,
IsWidelyUsedTool: true,
},
"goyang-ygot": &Validator{
Name: "goyang/ygot",
IsPerModel: true,
Name: "goyang/ygot",
IsPerModel: true,
IsWidelyUsedTool: true,
},
"yanglint": &Validator{
Name: "yanglint",
IsPerModel: true,
Name: "yanglint",
IsPerModel: true,
IsWidelyUsedTool: true,
},
"confd": &Validator{
Name: "ConfD Basic",
IsPerModel: true,
Name: "ConfD Basic",
IsPerModel: true,
IsWidelyUsedTool: true,
},
"regexp": &Validator{
Name: "regexp tests",
Expand Down Expand Up @@ -252,13 +263,16 @@ func GetValidatorAndVersionsFromString(validatorsAndVersionsStr string) ([]Valid
if len(vvSegments) == 2 {
vv.Version = vvSegments[1]
}
compatValidators = append(compatValidators, vv)
m, ok := compatValidatorsMap[vv.ValidatorId]
if !ok {
m = map[string]bool{}
compatValidatorsMap[vv.ValidatorId] = m
}
m[vv.Version] = true
// De-dup validator@version names.
if !m[vv.Version] {
compatValidators = append(compatValidators, vv)
m[vv.Version] = true
}
}
return compatValidators, compatValidatorsMap
}
Expand Down
17 changes: 11 additions & 6 deletions commonci/commonci_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,8 @@ func TestGetValidatorAndVersionsFromString(t *testing.T) {
wantVVList: []ValidatorAndVersion{{ValidatorId: "pyang", Version: "1.7.2"}},
wantVVMap: map[string]map[string]bool{"pyang": map[string]bool{"1.7.2": true}},
}, {
desc: "more than one version",
inStr: "[email protected],pyang,oc-pyang,pyang@head",
desc: "more than one version with an extraneous comma",
inStr: "[email protected],,pyang,oc-pyang,pyang@head",
wantVVList: []ValidatorAndVersion{
{ValidatorId: "pyang", Version: "1.7.2"},
{ValidatorId: "pyang", Version: ""},
Expand All @@ -176,8 +176,8 @@ func TestGetValidatorAndVersionsFromString(t *testing.T) {
},
},
}, {
desc: "more than one version with ending comma",
inStr: "[email protected],pyang,oc-pyang,pyang@head,",
desc: "more than one version with ending comma and with a duplicate",
inStr: "[email protected],pyang,oc-pyang,pyang@1.7.2,pyang@head,",
wantVVList: []ValidatorAndVersion{
{ValidatorId: "pyang", Version: "1.7.2"},
{ValidatorId: "pyang", Version: ""},
Expand Down Expand Up @@ -241,15 +241,20 @@ func TestValidatorAndVersionsDiff(t *testing.T) {
inBStr: "[email protected]",
wantStr: "",
}, {
desc: "more than one version",
inAStr: "[email protected],pyang,oc-pyang,pyang@head",
desc: "more than one version and with an extraneous comma",
inAStr: "[email protected],pyang,oc-pyang,,pyang@head",
inBStr: "pyang@head",
wantStr: "[email protected],pyang,oc-pyang",
}, {
desc: "more than one version deletes",
inAStr: "[email protected],pyang,oc-pyang,pyang@head",
inBStr: "oc-pyang,[email protected]",
wantStr: "pyang,pyang@head",
}, {
desc: "more than one version deletes with duplicates",
inAStr: "[email protected],pyang,oc-pyang,pyang@head,oc-pyang,goyang-ygot",
inBStr: "[email protected],goyang-ygot,oc-pyang,[email protected]",
wantStr: "pyang,pyang@head",
}, {
desc: "more than one version deletes with deleting something not there",
inAStr: "[email protected],pyang,oc-pyang,pyang@head",
Expand Down
Loading

0 comments on commit 3842ece

Please sign in to comment.