cmd/gitops-pusher: support GitHub Actions error syntax (#5060)

GitHub Actions lets you annotate lines in files as errors[1]. This syntax
will only fire on syntax errors. Future improvements can extend this to
properly annotate ACL tests too.

[1]: https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-an-error-message

Signed-off-by: Xe <xe@tailscale.com>
This commit is contained in:
Xe Iaso 2022-07-15 10:20:54 -04:00 committed by GitHub
parent 7fb6781bda
commit 16c85d0dc5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -17,6 +17,7 @@
"log" "log"
"net/http" "net/http"
"os" "os"
"regexp"
"strings" "strings"
"time" "time"
) )
@ -24,6 +25,7 @@
var ( var (
policyFname = flag.String("policy-file", "./policy.hujson", "filename for policy file") policyFname = flag.String("policy-file", "./policy.hujson", "filename for policy file")
timeout = flag.Duration("timeout", 5*time.Minute, "timeout for the entire CI run") timeout = flag.Duration("timeout", 5*time.Minute, "timeout for the entire CI run")
githubSyntax = flag.Bool("github-syntax", true, "use GitHub Action error syntax (https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-an-error-message)")
) )
func main() { func main() {
@ -177,13 +179,15 @@ func testNewACLs(ctx context.Context, tailnet, apiKey, policyFname string) error
return err return err
} }
if len(ate.Data) != 0 { if len(ate.Message) != 0 || len(ate.Data) != 0 {
return ate return ate
} }
return nil return nil
} }
var lineColMessageSplit = regexp.MustCompile(`^line ([0-9]+), column ([0-9]+): (.*)$`)
type ACLTestError struct { type ACLTestError struct {
Message string `json:"message"` Message string `json:"message"`
Data []ACLTestErrorDetail `json:"data"` Data []ACLTestErrorDetail `json:"data"`
@ -192,7 +196,17 @@ type ACLTestError struct {
func (ate ACLTestError) Error() string { func (ate ACLTestError) Error() string {
var sb strings.Builder var sb strings.Builder
if *githubSyntax && lineColMessageSplit.MatchString(ate.Message) {
sp := lineColMessageSplit.FindStringSubmatch(ate.Message)
line := sp[1]
col := sp[2]
msg := sp[3]
fmt.Fprintf(&sb, "::error file=%s,line=%s,col=%s::%s", *policyFname, line, col, msg)
} else {
fmt.Fprintln(&sb, ate.Message) fmt.Fprintln(&sb, ate.Message)
}
fmt.Fprintln(&sb) fmt.Fprintln(&sb)
for _, data := range ate.Data { for _, data := range ate.Data {