feat(flags): adds support for http proxy config (#82)

Reviewed-on: https://codeberg.org/woodpecker-plugins/go-plugin/pulls/82
Reviewed-by: qwerty287 <qwerty287@noreply.codeberg.org>
Co-authored-by: OCram85 <marco.blessing@googlemail.com>
Co-committed-by: OCram85 <marco.blessing@googlemail.com>
This commit is contained in:
OCram85
2026-03-30 16:29:13 +02:00
committed by qwerty287
parent 4fba2ed06e
commit 320f95afae
3 changed files with 102 additions and 13 deletions
+35 -6
View File
@@ -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()
+50 -2
View File
@@ -20,6 +20,7 @@ import (
"crypto/x509"
"net"
"net/http"
"os"
"time"
"github.com/rs/zerolog/log"
@@ -55,13 +56,60 @@ 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")
@@ -105,4 +153,4 @@ func HTTPClientFromContext(c *cli.Command) *http.Client {
return &http.Client{
Transport: transport,
}
}
}
+17 -5
View File
@@ -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")
@@ -107,4 +119,4 @@ func (p *Plugin) Run() {
log.Error().Err(err).Msg("execution failed")
os.Exit(1)
}
}
}