mirror of
https://codeberg.org/woodpecker-plugins/go-plugin
synced 2026-06-16 14:49:10 +08:00
Compare commits
35 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ff27774e34 | |||
| 0307b473fd | |||
| 39109f4f0d | |||
| d79c1b9e73 | |||
| 9b54bb824c | |||
| 04d11d71e2 | |||
| 6c31fd4eca | |||
| 6d2dd250f2 | |||
| b9901cb0a4 | |||
| 35e4580f92 | |||
| 7c2ff72c02 | |||
| 8cc8f11ed6 | |||
| c437b69716 | |||
| ff7388263c | |||
| deb8bebb75 | |||
| 715e1e0802 | |||
| c8a8fc1983 | |||
| 320f95afae | |||
| 4fba2ed06e | |||
| 64071307b1 | |||
| 00f2fd05f9 | |||
| 4cfd9035eb | |||
| e8db412499 | |||
| 685ac42fc4 | |||
| f0168dce22 | |||
| a811e40032 | |||
| e5e33d41e5 | |||
| 8eadd31abf | |||
| aded02e977 | |||
| 9e3162422c | |||
| e9e7d50eb6 | |||
| 5959a73881 | |||
| dc3aea27df | |||
| 87698ede13 | |||
| 3393bdb542 |
@@ -34,6 +34,14 @@ linters:
|
||||
- third_party$
|
||||
- builtin$
|
||||
- examples$
|
||||
revive:
|
||||
rules:
|
||||
- name: var-naming
|
||||
arguments:
|
||||
- []
|
||||
- []
|
||||
- - skipPackageNameChecks: true
|
||||
skip-package-name-collision-with-go-std: true
|
||||
formatters:
|
||||
enable:
|
||||
- gci
|
||||
|
||||
@@ -6,7 +6,7 @@ when:
|
||||
- "renovate/*"
|
||||
|
||||
variables:
|
||||
- &golang "golang:1.25"
|
||||
- &golang "golang:1.26"
|
||||
|
||||
steps:
|
||||
vendor:
|
||||
|
||||
@@ -6,7 +6,7 @@ when:
|
||||
|
||||
steps:
|
||||
- name: release-helper
|
||||
image: docker.io/woodpeckerci/plugin-ready-release-go:3.4.0
|
||||
image: docker.io/woodpeckerci/plugin-ready-release-go:4.1.1
|
||||
settings:
|
||||
release_branch: ${CI_COMMIT_BRANCH}
|
||||
git_email: woodpecker-bot@obermui.de
|
||||
|
||||
@@ -1,5 +1,45 @@
|
||||
# Changelog
|
||||
|
||||
## [1.2.0](https://codeberg.org/woodpecker-plugins/go-plugin/releases/tag/v1.2.0) - 2026-05-30
|
||||
|
||||
### ❤️ Thanks to all contributors! ❤️
|
||||
|
||||
@6543, @woodpecker-bot
|
||||
|
||||
### ✨ Features
|
||||
|
||||
- Support CI_STEP_NAME and CI_STEP_TYPE [[#88](https://codeberg.org/woodpecker-plugins/go-plugin/pulls/88)]
|
||||
|
||||
### 📦️ Dependency
|
||||
|
||||
- fix(deps): update module golang.org/x/net to v0.55.0 [[#86](https://codeberg.org/woodpecker-plugins/go-plugin/pulls/86)]
|
||||
- fix(deps): update module golang.org/x/net to v0.54.0 [[#84](https://codeberg.org/woodpecker-plugins/go-plugin/pulls/84)]
|
||||
|
||||
## [1.1.0](https://codeberg.org/woodpecker-plugins/go-plugin/releases/tag/v1.1.0) - 2026-03-30
|
||||
|
||||
### ❤️ Thanks to all contributors! ❤️
|
||||
|
||||
@OCram85
|
||||
|
||||
### 📈 Enhancement
|
||||
|
||||
- feat(flags): adds support for http proxy config [[#82](https://codeberg.org/woodpecker-plugins/go-plugin/pulls/82)]
|
||||
|
||||
## [1.0.3](https://codeberg.org/woodpecker-plugins/go-plugin/releases/tag/v1.0.3) - 2026-03-07
|
||||
|
||||
### ❤️ Thanks to all contributors! ❤️
|
||||
|
||||
@woodpecker-bot
|
||||
|
||||
### 📦️ Dependency
|
||||
|
||||
- fix(deps): update module github.com/urfave/cli/v3 to v3.7.0 [[#80](https://codeberg.org/woodpecker-plugins/go-plugin/pulls/80)]
|
||||
- chore(deps): update docker.io/woodpeckerci/plugin-ready-release-go docker tag to v4 [[#78](https://codeberg.org/woodpecker-plugins/go-plugin/pulls/78)]
|
||||
- fix(deps): update module golang.org/x/net to v0.51.0 [[#79](https://codeberg.org/woodpecker-plugins/go-plugin/pulls/79)]
|
||||
- chore(deps): update dependency go to v1.26.0 [[#74](https://codeberg.org/woodpecker-plugins/go-plugin/pulls/74)]
|
||||
- chore(deps): update golang docker tag to v1.26 [[#75](https://codeberg.org/woodpecker-plugins/go-plugin/pulls/75)]
|
||||
- fix(deps): update module golang.org/x/net to v0.50.0 [[#76](https://codeberg.org/woodpecker-plugins/go-plugin/pulls/76)]
|
||||
|
||||
## [1.0.2](https://codeberg.org/woodpecker-plugins/go-plugin/releases/tag/v1.0.2) - 2026-01-09
|
||||
|
||||
### ❤️ Thanks to all contributors! ❤️
|
||||
|
||||
@@ -9,12 +9,40 @@ HTTP client library.
|
||||
## Builtin settings
|
||||
|
||||
| Settings Name | Environment variable | Default | Description |
|
||||
| ------------- | -------------------- | ------- | ---------------------------------------------------------------------------- | ------------------------------------ |
|
||||
| ------------- | -------------------- | ------- | ---------------------------------------------------------------------------- |
|
||||
| `log_level` | - | `info` | Sets log level (`panic`, `fatal`, `error`, `warn`, `info`, `debug`, `trace`) |
|
||||
| `skip_verify` | - | `false` | - | Skip verification of TLS certificate |
|
||||
| `skip_verify` | - | `false` | Skip verification of TLS certificate |
|
||||
| | `SOCKS_PROXY` | _none_ | SOCKS5 proxy to use for connections |
|
||||
| | `SOCKS_PROXY_OFF` | _none_ | Do not use SOCKS5 proxy |
|
||||
|
||||
### Optional: HTTP proxy support
|
||||
|
||||
HTTP proxy support is **opt-in** and must be explicitly enabled by the plugin author via `EnableHTTPProxy: true` in `plugin.Options`. When enabled, the following settings become available:
|
||||
|
||||
| Settings Name | Environment variable | Default | Description |
|
||||
| ------------- | -------------------- | ------- | ------------------------------------------------------ |
|
||||
| `http_proxy` | `HTTP_PROXY` | _none_ | HTTP proxy URL for outgoing connections |
|
||||
| `https_proxy` | `HTTPS_PROXY` | _none_ | HTTPS proxy URL for outgoing connections |
|
||||
| `no_proxy` | `NO_PROXY` | _none_ | Comma-separated list of hosts to exclude from proxying |
|
||||
|
||||
The settings are resolved in the following order of precedence:
|
||||
|
||||
1. **Plugin settings** — `PLUGIN_HTTP_PROXY`, `PLUGIN_HTTPS_PROXY`, `PLUGIN_NO_PROXY`
|
||||
2. **Lowercase env vars** — `http_proxy`, `https_proxy`, `no_proxy`
|
||||
3. **Uppercase env vars** — `HTTP_PROXY`, `HTTPS_PROXY`, `NO_PROXY`
|
||||
|
||||
Example Woodpecker CI pipeline configuration:
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- name: my-plugin
|
||||
image: my-plugin:latest
|
||||
settings:
|
||||
http_proxy: http://proxy.example.com:3128
|
||||
https_proxy: http://proxy.example.com:3128
|
||||
no_proxy: "localhost,internal.example.com"
|
||||
```
|
||||
|
||||
## Creating plugin
|
||||
|
||||
```go
|
||||
@@ -62,10 +90,11 @@ func main() {
|
||||
}
|
||||
|
||||
p.Plugin = plugin.New(plugin.Options{
|
||||
Name: "sample-plugin",
|
||||
Description: "Sample plugin",
|
||||
Flags: p.Flags(),
|
||||
Execute: p.Execute,
|
||||
Name: "sample-plugin",
|
||||
Description: "Sample plugin",
|
||||
Flags: p.Flags(),
|
||||
Execute: p.Execute,
|
||||
EnableHTTPProxy: true, // opt-in to HTTP proxy support
|
||||
})
|
||||
|
||||
p.Run()
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
module codeberg.org/woodpecker-plugins/go-plugin
|
||||
|
||||
go 1.24.0
|
||||
go 1.25.0
|
||||
|
||||
toolchain go1.25.5
|
||||
toolchain go1.26.4
|
||||
|
||||
require (
|
||||
github.com/joho/godotenv v1.5.1
|
||||
github.com/rs/zerolog v1.34.0
|
||||
github.com/rs/zerolog v1.35.1
|
||||
github.com/stretchr/testify v1.11.1
|
||||
github.com/urfave/cli/v3 v3.6.1
|
||||
golang.org/x/net v0.48.0
|
||||
github.com/urfave/cli/v3 v3.10.0
|
||||
golang.org/x/net v0.56.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.19 // indirect
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
golang.org/x/sys v0.39.0 // indirect
|
||||
golang.org/x/sys v0.46.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
@@ -1,31 +1,24 @@
|
||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
|
||||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
||||
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
|
||||
github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY=
|
||||
github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ=
|
||||
github.com/rs/zerolog v1.35.1 h1:m7xQeoiLIiV0BCEY4Hs+j2NG4Gp2o2KPKmhnnLiazKI=
|
||||
github.com/rs/zerolog v1.35.1/go.mod h1:EjML9kdfa/RMA7h/6z6pYmq1ykOuA8/mjWaEvGI+jcw=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/urfave/cli/v3 v3.6.1 h1:j8Qq8NyUawj/7rTYdBGrxcH7A/j7/G8Q5LhWEW4G3Mo=
|
||||
github.com/urfave/cli/v3 v3.6.1/go.mod h1:ysVLtOEmg2tOy6PknnYVhDoouyC/6N42TMeoMzskhso=
|
||||
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
|
||||
golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
github.com/urfave/cli/v3 v3.10.0 h1:0aU8yOObVDMkM13Cj4G+zb4P0PdeJMec65f81Ak1ioM=
|
||||
github.com/urfave/cli/v3 v3.10.0/go.mod h1:ysVLtOEmg2tOy6PknnYVhDoouyC/6N42TMeoMzskhso=
|
||||
golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o=
|
||||
golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
|
||||
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw=
|
||||
golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"crypto/x509"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
@@ -55,13 +56,59 @@ func httpClientFlags() []cli.Flag {
|
||||
}
|
||||
}
|
||||
|
||||
func HTTPClientFromContext(c *cli.Command) *http.Client {
|
||||
// httpProxyFlags returns the optional HTTP proxy flags.
|
||||
// Only added to the app when EnableHTTPProxy is set in Options.
|
||||
func httpProxyFlags() []cli.Flag {
|
||||
return []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "transport.http-proxy",
|
||||
Usage: "HTTP proxy URL",
|
||||
Sources: cli.EnvVars(
|
||||
"PLUGIN_HTTP_PROXY",
|
||||
),
|
||||
Hidden: true,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "transport.https-proxy",
|
||||
Usage: "HTTPS proxy URL",
|
||||
Sources: cli.EnvVars(
|
||||
"PLUGIN_HTTPS_PROXY",
|
||||
),
|
||||
Hidden: true,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "transport.no-proxy",
|
||||
Usage: "Hosts to exclude from proxy (comma-separated)",
|
||||
Sources: cli.EnvVars(
|
||||
"PLUGIN_NO_PROXY",
|
||||
),
|
||||
Hidden: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func HTTPClientFromContext(c *cli.Command, httpProxyEnabled bool) *http.Client {
|
||||
var (
|
||||
skip = c.Bool("transport.skip-verify")
|
||||
socks = c.String("transport.socks-proxy")
|
||||
socksOff = c.Bool("transport.socks-proxy-off")
|
||||
)
|
||||
|
||||
if httpProxyEnabled {
|
||||
if v := c.String("transport.http-proxy"); v != "" {
|
||||
os.Setenv("HTTP_PROXY", v)
|
||||
os.Setenv("http_proxy", v)
|
||||
}
|
||||
if v := c.String("transport.https-proxy"); v != "" {
|
||||
os.Setenv("HTTPS_PROXY", v)
|
||||
os.Setenv("https_proxy", v)
|
||||
}
|
||||
if v := c.String("transport.no-proxy"); v != "" {
|
||||
os.Setenv("NO_PROXY", v)
|
||||
os.Setenv("no_proxy", v)
|
||||
}
|
||||
}
|
||||
|
||||
certs, err := x509.SystemCertPool()
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("failed to find system CA certs")
|
||||
|
||||
@@ -38,6 +38,10 @@ type Options struct {
|
||||
Execute ExecuteFunc
|
||||
// Context the plugin will use while executing.
|
||||
Context context.Context
|
||||
// EnableHTTPProxy allows plugins to opt-in to HTTP/HTTPS proxy support.
|
||||
// When true, PLUGIN_HTTP_PROXY, PLUGIN_HTTPS_PROXY and PLUGIN_NO_PROXY
|
||||
// are accepted as settings and applied to the HTTP client.
|
||||
EnableHTTPProxy bool
|
||||
}
|
||||
|
||||
// Plugin defines the plugin instance.
|
||||
@@ -46,6 +50,8 @@ type Plugin struct {
|
||||
execute ExecuteFunc
|
||||
client *http.Client
|
||||
ctx context.Context
|
||||
// enableHTTPProxy controls whether HTTP proxy flags are registered and applied.
|
||||
enableHTTPProxy bool
|
||||
// Metadata of the current pipeline.
|
||||
Metadata Metadata
|
||||
}
|
||||
@@ -68,10 +74,16 @@ func New(opt Options) *Plugin {
|
||||
}
|
||||
|
||||
plugin := &Plugin{
|
||||
App: app,
|
||||
execute: opt.Execute,
|
||||
ctx: opt.Context,
|
||||
App: app,
|
||||
execute: opt.Execute,
|
||||
ctx: opt.Context,
|
||||
enableHTTPProxy: opt.EnableHTTPProxy,
|
||||
}
|
||||
|
||||
if opt.EnableHTTPProxy {
|
||||
app.Flags = append(app.Flags, httpProxyFlags()...)
|
||||
}
|
||||
|
||||
plugin.App.Action = plugin.action
|
||||
|
||||
if plugin.ctx == nil {
|
||||
@@ -87,7 +99,7 @@ func (p *Plugin) action(ctx context.Context, c *cli.Command) error {
|
||||
}
|
||||
|
||||
p.Metadata = MetadataFromContext(c)
|
||||
p.client = HTTPClientFromContext(c)
|
||||
p.client = HTTPClientFromContext(c, p.enableHTTPProxy)
|
||||
|
||||
if p.execute == nil {
|
||||
panic("plugin execute function is not set")
|
||||
|
||||
@@ -22,13 +22,40 @@ import (
|
||||
|
||||
// Step defines runtime metadata for a step.
|
||||
type Step struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Type StepType `json:"type,omitempty"`
|
||||
Number int `json:"number,omitempty"`
|
||||
Started time.Time `json:"started,omitempty"`
|
||||
Finished time.Time `json:"finished,omitempty"`
|
||||
}
|
||||
|
||||
// StepType identifies the type of step.
|
||||
type StepType string
|
||||
|
||||
const (
|
||||
StepTypeClone StepType = "clone"
|
||||
StepTypeService StepType = "service"
|
||||
StepTypePlugin StepType = "plugin"
|
||||
StepTypeCommands StepType = "commands"
|
||||
StepTypeCache StepType = "cache"
|
||||
)
|
||||
|
||||
func stepFlags() []cli.Flag {
|
||||
return []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "step.name",
|
||||
Usage: "step name",
|
||||
Sources: cli.EnvVars(
|
||||
"CI_STEP_NAME",
|
||||
),
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "step.type",
|
||||
Usage: "step type",
|
||||
Sources: cli.EnvVars(
|
||||
"CI_STEP_TYPE",
|
||||
),
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: "step.number",
|
||||
Usage: "step number",
|
||||
@@ -56,6 +83,8 @@ func stepFlags() []cli.Flag {
|
||||
|
||||
func stepFromContext(c *cli.Command) Step {
|
||||
return Step{
|
||||
Name: c.String("step.name"),
|
||||
Type: StepType(c.String("step.type")),
|
||||
Number: c.Int("step.number"),
|
||||
Started: time.Unix(c.Int64("step.started"), 0),
|
||||
Finished: time.Unix(c.Int64("step.finished"), 0),
|
||||
|
||||
Reference in New Issue
Block a user