-
Notifications
You must be signed in to change notification settings - Fork 34
/
actions.go
163 lines (138 loc) · 4.78 KB
/
actions.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
// Copyright 2020 The Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// githubactions provides an SDK for authoring GitHub Actions in Go. It has no
// external dependencies and provides a Go-like interface for interacting with
// GitHub Actions' build system.
package githubactions
import (
"fmt"
"io"
"os"
"sort"
"strings"
)
const (
addMaskFmt = "::add-mask::%s\n"
addPathFmt = "::add-path::%s\n"
setEnvFmt = "::set-env name=%s::%s\n"
setOutputFmt = "::set-output name=%s::%s\n"
saveStateFmt = "::save-state name=%s::%s\n"
addMatcherFmt = "::add-matcher::%s\n"
removeMatcherFmt = "::remove-matcher owner=%s::\n"
groupFmt = "::group::%s\n"
endGroupFmt = "::endgroup::\n"
debugFmt = "::debug%s::%s\n"
errorFmt = "::error%s::%s\n"
warningFmt = "::warning%s::%s\n"
)
// New creates a new wrapper with helpers for outputting information in GitHub
// actions format.
func New() *Action {
return &Action{w: os.Stdout}
}
// NewWithWriter creates a wrapper using the given writer. This is useful for
// tests. The given writer cannot add any prefixes to the string, since GitHub
// requires these special strings to match a very particular format.
func NewWithWriter(w io.Writer) *Action {
return &Action{w: w}
}
// Action is an internal wrapper around GitHub Actions' output and magic
// strings.
type Action struct {
w io.Writer
fields string
}
// AddMask adds a new field mask for the given string "p". After called, future
// attempts to log "p" will be replaced with "***" in log output.
func (c *Action) AddMask(p string) {
fmt.Fprintf(c.w, addMaskFmt, p)
}
// AddMatcher adds a new matcher with the given file path.
func (c *Action) AddMatcher(p string) {
fmt.Fprintf(c.w, addMatcherFmt, p)
}
// RemoveMatcher removes a matcher with the given owner name.
func (c *Action) RemoveMatcher(o string) {
fmt.Fprintf(c.w, removeMatcherFmt, o)
}
// AddPath adds the string "p" to the path for the invocation.
func (c *Action) AddPath(p string) {
fmt.Fprintf(c.w, addPathFmt, p)
}
// SaveState saves state to be used in the "finally" post job entry point.
func (c *Action) SaveState(k, v string) {
fmt.Fprintf(c.w, saveStateFmt, k, v)
}
// GetInput gets the input by the given name.
func (c *Action) GetInput(i string) string {
e := strings.ReplaceAll(i, " ", "_")
e = strings.ToUpper(e)
e = "INPUT_" + e
return strings.TrimSpace(os.Getenv(e))
}
// Group starts a new collapsable region up to the next ungroup invocation.
func (c *Action) Group(t string) {
fmt.Fprintf(c.w, groupFmt, t)
}
// EndGroup ends the current group.
func (c *Action) EndGroup() {
fmt.Fprint(c.w, endGroupFmt)
}
// SetEnv sets an environment variable.
func (c *Action) SetEnv(k, v string) {
fmt.Fprintf(c.w, setEnvFmt, k, v)
}
// SetOutput sets an output parameter.
func (c *Action) SetOutput(k, v string) {
fmt.Fprintf(c.w, setOutputFmt, k, v)
}
// Debugf prints a debug-level message. The arguments follow the standard Printf
// arguments.
func (c *Action) Debugf(msg string, args ...interface{}) {
fmt.Fprintf(c.w, debugFmt, c.fields, fmt.Sprintf(msg, args...))
}
// Errorf prints a error-level message. The arguments follow the standard Printf
// arguments.
func (c *Action) Errorf(msg string, args ...interface{}) {
fmt.Fprintf(c.w, errorFmt, c.fields, fmt.Sprintf(msg, args...))
}
// Fatalf prints a error-level message and exits. This is equivalent to Errorf
// followed by os.Exit(1).
func (c *Action) Fatalf(msg string, args ...interface{}) {
c.Errorf(msg, args...)
os.Exit(1)
}
// Warningf prints a warning-level message. The arguments follow the standard
// Printf arguments.
func (c *Action) Warningf(msg string, args ...interface{}) {
fmt.Fprintf(c.w, warningFmt, c.fields, fmt.Sprintf(msg, args...))
}
// WithFieldsSlice includes the provided fields in log output. "f" must be a
// slice of k=v pairs. The given slice will be sorted.
func (c *Action) WithFieldsSlice(f []string) *Action {
sort.Strings(f)
return &Action{
w: c.w,
fields: " " + strings.Join(f, ","),
}
}
// WithFieldsMap includes the provided fields in log output. The fields in "m"
// are automatically converted to k=v pairs and sorted.
func (c *Action) WithFieldsMap(m map[string]string) *Action {
l := make([]string, 0, len(m))
for k, v := range m {
l = append(l, fmt.Sprintf("%s=%s", k, v))
}
return c.WithFieldsSlice(l)
}