Skip to content

Commit 95ae9de

Browse files
authored
Merge pull request kubernetes-csi#9 from pohly/prow
Prow testing
2 parents 2069a0a + d87eccb commit 95ae9de

File tree

4 files changed

+1130
-0
lines changed

4 files changed

+1130
-0
lines changed

.prow.sh

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#! /bin/bash -e
2+
#
3+
# This is for testing csi-release-tools itself in Prow. All other
4+
# repos use prow.sh for that, but as csi-release-tools isn't a normal
5+
# repo with some Go code in it, it has a custom Prow test script.
6+
7+
./verify-shellcheck.sh "$(pwd)"

README.md

+45
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,48 @@ errors shell scripts, like missing quotation marks. The default
6161
`test-shellcheck` target in [build.make](./build.make) only checks the
6262
scripts in this directory. Components can add more directories to
6363
`TEST_SHELLCHECK_DIRS` to check also other scripts.
64+
65+
End-to-end testing
66+
------------------
67+
68+
A repo that wants to opt into testing via Prow must set up a top-level
69+
`.prow.sh`. Typically that will source `prow.sh` and then transfer
70+
control to it:
71+
72+
``` bash
73+
#! /bin/bash -e
74+
75+
. release-tools/prow.sh
76+
main
77+
```
78+
79+
All Kubernetes-CSI repos are expected to switch to Prow. For details
80+
on what is enabled in Prow, see
81+
https://github.com/kubernetes/test-infra/tree/master/config/jobs/kubernetes-csi
82+
83+
Test results for periodic jobs are visible in
84+
https://testgrid.k8s.io/sig-storage-csi
85+
86+
It is possible to reproduce the Prow testing locally on a suitable machine:
87+
- Linux host
88+
- Docker installed
89+
- code to be tested checkout out in `$GOPATH/src/<import path>`
90+
- `cd $GOPATH/src/<import path> && ./.prow.sh`
91+
92+
Beware that the script intentionally doesn't clean up after itself and
93+
modifies the content of `$GOPATH`, in particular the `kubernetes` and
94+
`kind` repositories there. Better run it in an empty, disposable
95+
`$GOPATH`.
96+
97+
When it terminates, the following command can be used to get access to
98+
the Kubernetes cluster that was brought up for testing (assuming that
99+
this step succeeded):
100+
101+
export KUBECONFIG="$(kind get kubeconfig-path --name="csi-prow")"
102+
103+
It is possible to control the execution via environment variables. See
104+
`prow.sh` for details. Particularly useful is testing against different
105+
Kubernetes releases:
106+
107+
CSI_PROW_KUBERNETES_VERSION=1.13.3 ./.prow.sh
108+
CSI_PROW_KUBERNETES_VERSION=latest ./.prow.sh

filter-junit.go

+133
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
/*
2+
Copyright 2019 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
/*
18+
* This command filters a JUnit file such that only tests with a name
19+
* matching a regular expression are passed through. By concatenating
20+
* multiple input files it is possible to merge them into a single file.
21+
*/
22+
package main
23+
24+
import (
25+
"encoding/xml"
26+
"flag"
27+
"io/ioutil"
28+
"os"
29+
"regexp"
30+
)
31+
32+
var (
33+
output = flag.String("o", "-", "junit file to write, - for stdout")
34+
tests = flag.String("t", "", "regular expression matching the test names that are to be included in the output")
35+
)
36+
37+
/*
38+
* TestSuite represents a JUnit file. Due to how encoding/xml works, we have
39+
* represent all fields that we want to be passed through. It's therefore
40+
* not a complete solution, but good enough for Ginkgo + Spyglass.
41+
*/
42+
type TestSuite struct {
43+
XMLName string `xml:"testsuite"`
44+
TestCases []TestCase `xml:"testcase"`
45+
}
46+
47+
type TestCase struct {
48+
Name string `xml:"name,attr"`
49+
Time string `xml:"time,attr"`
50+
SystemOut string `xml:"system-out,omitempty"`
51+
Failure string `xml:"failure,omitempty"`
52+
Skipped SkipReason `xml:"skipped,omitempty"`
53+
}
54+
55+
// SkipReason deals with the special <skipped></skipped>:
56+
// if present, we must re-encode it, even if empty.
57+
type SkipReason string
58+
59+
func (s *SkipReason) UnmarshalText(text []byte) error {
60+
*s = SkipReason(text)
61+
if *s == "" {
62+
*s = " "
63+
}
64+
return nil
65+
}
66+
67+
func (s SkipReason) MarshalText() ([]byte, error) {
68+
if s == " " {
69+
return []byte{}, nil
70+
}
71+
return []byte(s), nil
72+
}
73+
74+
func main() {
75+
var junit TestSuite
76+
var data []byte
77+
78+
flag.Parse()
79+
80+
re := regexp.MustCompile(*tests)
81+
82+
// Read all input files.
83+
for _, input := range flag.Args() {
84+
if input == "-" {
85+
if _, err := os.Stdin.Read(data); err != nil {
86+
panic(err)
87+
}
88+
} else {
89+
var err error
90+
data, err = ioutil.ReadFile(input)
91+
if err != nil {
92+
panic(err)
93+
}
94+
}
95+
if err := xml.Unmarshal(data, &junit); err != nil {
96+
panic(err)
97+
}
98+
}
99+
100+
// Keep only matching testcases. Testcases skipped in all test runs are only stored once.
101+
filtered := map[string]TestCase{}
102+
for _, testcase := range junit.TestCases {
103+
if !re.MatchString(testcase.Name) {
104+
continue
105+
}
106+
entry, ok := filtered[testcase.Name]
107+
if !ok || // not present yet
108+
entry.Skipped != "" && testcase.Skipped == "" { // replaced skipped test with real test run
109+
filtered[testcase.Name] = testcase
110+
}
111+
}
112+
junit.TestCases = nil
113+
for _, testcase := range filtered {
114+
junit.TestCases = append(junit.TestCases, testcase)
115+
}
116+
117+
// Re-encode.
118+
data, err := xml.MarshalIndent(junit, "", " ")
119+
if err != nil {
120+
panic(err)
121+
}
122+
123+
// Write to output.
124+
if *output == "-" {
125+
if _, err := os.Stdout.Write(data); err != nil {
126+
panic(err)
127+
}
128+
} else {
129+
if err := ioutil.WriteFile(*output, data, 0644); err != nil {
130+
panic(err)
131+
}
132+
}
133+
}

0 commit comments

Comments
 (0)