mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2024-12-24 10:07:21 +02:00
Merge branch 'main' into clarify-secrets-in-docs
This commit is contained in:
commit
54cd945010
@ -2,12 +2,14 @@ when:
|
||||
- event: tag
|
||||
- event: pull_request
|
||||
branch: ${CI_REPO_DEFAULT_BRANCH}
|
||||
path: Makefile
|
||||
path:
|
||||
- Makefile
|
||||
- .woodpecker/binaries.yaml
|
||||
|
||||
variables:
|
||||
- &golang_image 'docker.io/golang:1.23'
|
||||
- &node_image 'docker.io/node:23-alpine'
|
||||
- &xgo_image 'docker.io/techknowlogick/xgo:go-1.23.x'
|
||||
- &xgo_image 'docker.io/techknowlogick/xgo:go-1.23.1'
|
||||
|
||||
# cspell:words bindata netgo
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
variables:
|
||||
- &golang_image 'docker.io/golang:1.23'
|
||||
- &node_image 'docker.io/node:23-alpine'
|
||||
- &xgo_image 'docker.io/techknowlogick/xgo:go-1.23.x'
|
||||
- &xgo_image 'docker.io/techknowlogick/xgo:go-1.23.1'
|
||||
- &buildx_plugin 'docker.io/woodpeckerci/plugin-docker-buildx:5.0.0'
|
||||
- &platforms_release 'linux/arm/v6,linux/arm/v7,linux/arm64/v8,linux/386,linux/amd64,linux/ppc64le,linux/riscv64,linux/s390x,freebsd/arm64,freebsd/amd64,openbsd/arm64,openbsd/amd64'
|
||||
- &platforms_server 'linux/arm/v7,linux/arm64/v8,linux/amd64,linux/ppc64le,linux/riscv64'
|
||||
|
@ -1,6 +1,6 @@
|
||||
steps:
|
||||
- name: release-helper
|
||||
image: woodpeckerci/plugin-ready-release-go:2.0.0
|
||||
image: docker.io/woodpeckerci/plugin-ready-release-go:2.1.1
|
||||
settings:
|
||||
release_branch: ${CI_COMMIT_BRANCH}
|
||||
forge_type: github
|
||||
@ -13,5 +13,3 @@ when:
|
||||
branch:
|
||||
- ${CI_REPO_DEFAULT_BRANCH}
|
||||
- release/*
|
||||
- event: manual
|
||||
evaluate: 'TASK == "release-helper"'
|
||||
|
@ -27,14 +27,34 @@ import (
|
||||
|
||||
var flags = append([]cli.Flag{
|
||||
&cli.BoolFlag{
|
||||
Sources: cli.EnvVars("WOODPECKER_LOG_XORM"),
|
||||
Name: "log-xorm",
|
||||
Usage: "enable xorm logging",
|
||||
Sources: cli.EnvVars("WOODPECKER_DATABASE_LOG", "WOODPECKER_LOG_XORM"),
|
||||
Name: "db-log",
|
||||
Aliases: []string{"log-xorm"}, // TODO: remove in v4.0.0
|
||||
Usage: "enable logging in database engine (currently xorm)",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Sources: cli.EnvVars("WOODPECKER_LOG_XORM_SQL"),
|
||||
Name: "log-xorm-sql",
|
||||
Usage: "enable xorm sql command logging",
|
||||
Sources: cli.EnvVars("WOODPECKER_DATABASE_LOG_SQL", "WOODPECKER_LOG_XORM_SQL"),
|
||||
Name: "db-log-sql",
|
||||
Aliases: []string{"log-xorm-sql"}, // TODO: remove in v4.0.0
|
||||
Usage: "enable logging of sql commands",
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Sources: cli.EnvVars("WOODPECKER_DATABASE_MAX_CONNECTIONS"),
|
||||
Name: "db-max-open-connections",
|
||||
Usage: "max connections xorm is allowed create",
|
||||
Value: 100,
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Sources: cli.EnvVars("WOODPECKER_DATABASE_IDLE_CONNECTIONS"),
|
||||
Name: "db-max-idle-connections",
|
||||
Usage: "amount of connections xorm will hold open",
|
||||
Value: 2,
|
||||
},
|
||||
&cli.DurationFlag{
|
||||
Sources: cli.EnvVars("WOODPECKER_DATABASE_CONNECTION_TIMEOUT"),
|
||||
Name: "db-max-connection-timeout",
|
||||
Usage: "time an active connection is allowed to stay open",
|
||||
Value: 3 * time.Second,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Sources: cli.EnvVars("WOODPECKER_HOST"),
|
||||
@ -205,7 +225,8 @@ var flags = append([]cli.Flag{
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Sources: cli.EnvVars("WOODPECKER_DATABASE_DRIVER"),
|
||||
Name: "driver",
|
||||
Name: "db-driver",
|
||||
Aliases: []string{"driver"}, // TODO: remove in v4.0.0
|
||||
Usage: "database driver",
|
||||
Value: "sqlite3",
|
||||
},
|
||||
@ -213,9 +234,10 @@ var flags = append([]cli.Flag{
|
||||
Sources: cli.NewValueSourceChain(
|
||||
cli.File(os.Getenv("WOODPECKER_DATABASE_DATASOURCE_FILE")),
|
||||
cli.EnvVar("WOODPECKER_DATABASE_DATASOURCE")),
|
||||
Name: "datasource",
|
||||
Usage: "database driver configuration string",
|
||||
Value: datasourceDefaultValue(),
|
||||
Name: "db-datasource",
|
||||
Aliases: []string{"datasource"}, // TODO: remove in v4.0.0
|
||||
Usage: "database driver configuration string",
|
||||
Value: datasourceDefaultValue(),
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Sources: cli.NewValueSourceChain(
|
||||
|
@ -51,11 +51,14 @@ const (
|
||||
)
|
||||
|
||||
func setupStore(ctx context.Context, c *cli.Command) (store.Store, error) {
|
||||
datasource := c.String("datasource")
|
||||
driver := c.String("driver")
|
||||
datasource := c.String("db-datasource")
|
||||
driver := c.String("db-driver")
|
||||
xorm := store.XORM{
|
||||
Log: c.Bool("log-xorm"),
|
||||
ShowSQL: c.Bool("log-xorm-sql"),
|
||||
Log: c.Bool("db-log"),
|
||||
ShowSQL: c.Bool("db-log-sql"),
|
||||
MaxOpenConns: int(c.Int("db-max-open-connections")),
|
||||
MaxIdleConns: int(c.Int("db-max-idle-connections")),
|
||||
ConnMaxLifetime: c.Duration("db-max-connection-timeout"),
|
||||
}
|
||||
|
||||
if driver == "sqlite3" {
|
||||
|
@ -159,17 +159,35 @@ Configures the logging level. Possible values are `trace`, `debug`, `info`, `war
|
||||
Output destination for logs.
|
||||
'stdout' and 'stderr' can be used as special keywords.
|
||||
|
||||
### `WOODPECKER_LOG_XORM`
|
||||
### `WOODPECKER_DATABASE_LOG`
|
||||
|
||||
> Default: `false`
|
||||
|
||||
Enable XORM logs.
|
||||
Enable logging in database engine (currently xorm).
|
||||
|
||||
### `WOODPECKER_LOG_XORM_SQL`
|
||||
### `WOODPECKER_DATABASE_LOG_SQL`
|
||||
|
||||
> Default: `false`
|
||||
|
||||
Enable XORM SQL command logs.
|
||||
Enable logging of sql commands.
|
||||
|
||||
### `WOODPECKER_DATABASE_MAX_CONNECTIONS`
|
||||
|
||||
> Default: `100`
|
||||
|
||||
Max database connections xorm is allowed create.
|
||||
|
||||
### `WOODPECKER_DATABASE_IDLE_CONNECTIONS`
|
||||
|
||||
> Default: `2`
|
||||
|
||||
Amount of database connections xorm will hold open.
|
||||
|
||||
### `WOODPECKER_DATABASE_CONNECTION_TIMEOUT`
|
||||
|
||||
> Default: `3 Seconds`
|
||||
|
||||
Time an active database connection is allowed to stay open.
|
||||
|
||||
### `WOODPECKER_DEBUG_PRETTY`
|
||||
|
||||
|
@ -36,6 +36,7 @@ This will be the next version of Woodpecker.
|
||||
|
||||
## Admin migrations
|
||||
|
||||
- Deprecate `WOODPECKER_LOG_XORM` and `WOODPECKER_LOG_XORM_SQL` use `"WOODPECKER_DATABASE_LOG` and `"WOODPECKER_DATABASE_LOG_SQL`
|
||||
- Deprecate `WOODPECKER_FILTER_LABELS` use `WOODPECKER_AGENT_LABELS`
|
||||
- Move docker resource limit settings from server into agent configuration
|
||||
- Rename server environment variable `WOODPECKER_ESCALATE` to `WOODPECKER_PLUGINS_PRIVILEGED`
|
||||
|
@ -18,15 +18,15 @@ import (
|
||||
"encoding/base64"
|
||||
)
|
||||
|
||||
func GenerateContainerConf(commands []string, goos string) (env map[string]string, entry []string) {
|
||||
func GenerateContainerConf(commands []string, goos, workDir string) (env map[string]string, entry []string) {
|
||||
env = make(map[string]string)
|
||||
if goos == "windows" {
|
||||
env["CI_SCRIPT"] = base64.StdEncoding.EncodeToString([]byte(generateScriptWindows(commands)))
|
||||
env["CI_SCRIPT"] = base64.StdEncoding.EncodeToString([]byte(generateScriptWindows(commands, workDir)))
|
||||
env["SHELL"] = "powershell.exe"
|
||||
// cspell:disable-next-line
|
||||
entry = []string{"powershell", "-noprofile", "-noninteractive", "-command", "[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($Env:CI_SCRIPT)) | iex"}
|
||||
} else {
|
||||
env["CI_SCRIPT"] = base64.StdEncoding.EncodeToString([]byte(generateScriptPosix(commands)))
|
||||
env["CI_SCRIPT"] = base64.StdEncoding.EncodeToString([]byte(generateScriptPosix(commands, workDir)))
|
||||
env["SHELL"] = "/bin/sh"
|
||||
entry = []string{"/bin/sh", "-c", "echo $CI_SCRIPT | base64 -d | /bin/sh -e"}
|
||||
}
|
||||
|
@ -17,16 +17,22 @@ package common
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"text/template"
|
||||
|
||||
"al.essio.dev/pkg/shellescape"
|
||||
)
|
||||
|
||||
// generateScriptPosix is a helper function that generates a step script
|
||||
// for a linux container using the given.
|
||||
func generateScriptPosix(commands []string) string {
|
||||
func generateScriptPosix(commands []string, workDir string) string {
|
||||
var buf bytes.Buffer
|
||||
|
||||
buf.WriteString(setupScript)
|
||||
if err := setupScriptTmpl.Execute(&buf, map[string]string{
|
||||
"WorkDir": workDir,
|
||||
}); err != nil {
|
||||
// should never happen but well we have an error to trance
|
||||
return fmt.Sprintf("echo 'failed to generate posix script from commands: %s'; exit 1", err.Error())
|
||||
}
|
||||
|
||||
for _, command := range commands {
|
||||
buf.WriteString(fmt.Sprintf(
|
||||
@ -39,9 +45,9 @@ func generateScriptPosix(commands []string) string {
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// setupScript is a helper script this is added to the step script to ensure
|
||||
// setupScriptProto is a helper script this is added to the step script to ensure
|
||||
// a minimum set of environment variables are set correctly.
|
||||
const setupScript = `
|
||||
const setupScriptProto = `
|
||||
if [ -n "$CI_NETRC_MACHINE" ]; then
|
||||
cat <<EOF > $HOME/.netrc
|
||||
machine $CI_NETRC_MACHINE
|
||||
@ -53,10 +59,12 @@ fi
|
||||
unset CI_NETRC_USERNAME
|
||||
unset CI_NETRC_PASSWORD
|
||||
unset CI_SCRIPT
|
||||
mkdir -p "$CI_WORKSPACE"
|
||||
cd "$CI_WORKSPACE"
|
||||
mkdir -p "{{.WorkDir}}"
|
||||
cd "{{.WorkDir}}"
|
||||
`
|
||||
|
||||
var setupScriptTmpl, _ = template.New("").Parse(setupScriptProto)
|
||||
|
||||
// traceScript is a helper script that is added to the step script
|
||||
// to trace a command.
|
||||
const traceScript = `
|
||||
|
@ -16,6 +16,7 @@ package common
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"text/template"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
@ -39,8 +40,8 @@ fi
|
||||
unset CI_NETRC_USERNAME
|
||||
unset CI_NETRC_PASSWORD
|
||||
unset CI_SCRIPT
|
||||
mkdir -p "$CI_WORKSPACE"
|
||||
cd "$CI_WORKSPACE"
|
||||
mkdir -p "/woodpecker/some"
|
||||
cd "/woodpecker/some"
|
||||
|
||||
echo + 'echo ${PATH}'
|
||||
echo ${PATH}
|
||||
@ -54,7 +55,13 @@ go test
|
||||
},
|
||||
}
|
||||
for _, test := range testdata {
|
||||
script := generateScriptPosix(test.from)
|
||||
script := generateScriptPosix(test.from, "/woodpecker/some")
|
||||
assert.EqualValues(t, test.want, script, "Want encoded script for %s", test.from)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetupScriptProtoParse(t *testing.T) {
|
||||
// just ensure that we have a working `setupScriptTmpl` on runntime
|
||||
_, err := template.New("").Parse(setupScriptProto)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
@ -21,16 +21,16 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
windowsScriptBase64 = "CiRFcnJvckFjdGlvblByZWZlcmVuY2UgPSAnU3RvcCc7CmlmIChbRW52aXJvbm1lbnRdOjpHZXRFbnZpcm9ubWVudFZhcmlhYmxlKCdDSV9XT1JLU1BBQ0UnKSkgeyBpZiAoLW5vdCAoVGVzdC1QYXRoICIkZW52OkNJX1dPUktTUEFDRSIpKSB7IE5ldy1JdGVtIC1QYXRoICIkZW52OkNJX1dPUktTUEFDRSIgLUl0ZW1UeXBlIERpcmVjdG9yeSAtRm9yY2UgfX07CmlmICgtbm90IFtFbnZpcm9ubWVudF06OkdldEVudmlyb25tZW50VmFyaWFibGUoJ0hPTUUnKSkgeyBbRW52aXJvbm1lbnRdOjpTZXRFbnZpcm9ubWVudFZhcmlhYmxlKCdIT01FJywgJ2M6XHJvb3QnKSB9OwppZiAoLW5vdCAoVGVzdC1QYXRoICIkZW52OkhPTUUiKSkgeyBOZXctSXRlbSAtUGF0aCAiJGVudjpIT01FIiAtSXRlbVR5cGUgRGlyZWN0b3J5IC1Gb3JjZSB9OwppZiAoJEVudjpDSV9ORVRSQ19NQUNISU5FKSB7CiRuZXRyYz1bc3RyaW5nXTo6Rm9ybWF0KCJ7MH1cX25ldHJjIiwkRW52OkhPTUUpOwoibWFjaGluZSAkRW52OkNJX05FVFJDX01BQ0hJTkUiID4+ICRuZXRyYzsKImxvZ2luICRFbnY6Q0lfTkVUUkNfVVNFUk5BTUUiID4+ICRuZXRyYzsKInBhc3N3b3JkICRFbnY6Q0lfTkVUUkNfUEFTU1dPUkQiID4+ICRuZXRyYzsKfTsKW0Vudmlyb25tZW50XTo6U2V0RW52aXJvbm1lbnRWYXJpYWJsZSgiQ0lfTkVUUkNfUEFTU1dPUkQiLCRudWxsKTsKW0Vudmlyb25tZW50XTo6U2V0RW52aXJvbm1lbnRWYXJpYWJsZSgiQ0lfU0NSSVBUIiwkbnVsbCk7CmlmIChbRW52aXJvbm1lbnRdOjpHZXRFbnZpcm9ubWVudFZhcmlhYmxlKCdDSV9XT1JLU1BBQ0UnKSkgeyBjZCAiJGVudjpDSV9XT1JLU1BBQ0UiIH07CgpXcml0ZS1PdXRwdXQgKCcrICJlY2hvIGhlbGxvIHdvcmxkIicpOwomIGVjaG8gaGVsbG8gd29ybGQ7IGlmICgkTEFTVEVYSVRDT0RFIC1uZSAwKSB7ZXhpdCAkTEFTVEVYSVRDT0RFfQoK"
|
||||
posixScriptBase64 = "CmlmIFsgLW4gIiRDSV9ORVRSQ19NQUNISU5FIiBdOyB0aGVuCmNhdCA8PEVPRiA+ICRIT01FLy5uZXRyYwptYWNoaW5lICRDSV9ORVRSQ19NQUNISU5FCmxvZ2luICRDSV9ORVRSQ19VU0VSTkFNRQpwYXNzd29yZCAkQ0lfTkVUUkNfUEFTU1dPUkQKRU9GCmNobW9kIDA2MDAgJEhPTUUvLm5ldHJjCmZpCnVuc2V0IENJX05FVFJDX1VTRVJOQU1FCnVuc2V0IENJX05FVFJDX1BBU1NXT1JECnVuc2V0IENJX1NDUklQVApta2RpciAtcCAiJENJX1dPUktTUEFDRSIKY2QgIiRDSV9XT1JLU1BBQ0UiCgplY2hvICsgJ2VjaG8gaGVsbG8gd29ybGQnCmVjaG8gaGVsbG8gd29ybGQK"
|
||||
windowsScriptBase64 = "CiRFcnJvckFjdGlvblByZWZlcmVuY2UgPSAnU3RvcCc7CmlmICgtbm90IChUZXN0LVBhdGggIi93b29kcGVja2VyL3NvbWUiKSkgeyBOZXctSXRlbSAtUGF0aCAiL3dvb2RwZWNrZXIvc29tZSIgLUl0ZW1UeXBlIERpcmVjdG9yeSAtRm9yY2UgfTsKaWYgKC1ub3QgW0Vudmlyb25tZW50XTo6R2V0RW52aXJvbm1lbnRWYXJpYWJsZSgnSE9NRScpKSB7IFtFbnZpcm9ubWVudF06OlNldEVudmlyb25tZW50VmFyaWFibGUoJ0hPTUUnLCAnYzpccm9vdCcpIH07CmlmICgtbm90IChUZXN0LVBhdGggIiRlbnY6SE9NRSIpKSB7IE5ldy1JdGVtIC1QYXRoICIkZW52OkhPTUUiIC1JdGVtVHlwZSBEaXJlY3RvcnkgLUZvcmNlIH07CmlmICgkRW52OkNJX05FVFJDX01BQ0hJTkUpIHsKJG5ldHJjPVtzdHJpbmddOjpGb3JtYXQoInswfVxfbmV0cmMiLCRFbnY6SE9NRSk7CiJtYWNoaW5lICRFbnY6Q0lfTkVUUkNfTUFDSElORSIgPj4gJG5ldHJjOwoibG9naW4gJEVudjpDSV9ORVRSQ19VU0VSTkFNRSIgPj4gJG5ldHJjOwoicGFzc3dvcmQgJEVudjpDSV9ORVRSQ19QQVNTV09SRCIgPj4gJG5ldHJjOwp9OwpbRW52aXJvbm1lbnRdOjpTZXRFbnZpcm9ubWVudFZhcmlhYmxlKCJDSV9ORVRSQ19QQVNTV09SRCIsJG51bGwpOwpbRW52aXJvbm1lbnRdOjpTZXRFbnZpcm9ubWVudFZhcmlhYmxlKCJDSV9TQ1JJUFQiLCRudWxsKTsKY2QgIi93b29kcGVja2VyL3NvbWUiOwoKV3JpdGUtT3V0cHV0ICgnKyAiZWNobyBoZWxsbyB3b3JsZCInKTsKJiBlY2hvIGhlbGxvIHdvcmxkOyBpZiAoJExBU1RFWElUQ09ERSAtbmUgMCkge2V4aXQgJExBU1RFWElUQ09ERX0K"
|
||||
posixScriptBase64 = "CmlmIFsgLW4gIiRDSV9ORVRSQ19NQUNISU5FIiBdOyB0aGVuCmNhdCA8PEVPRiA+ICRIT01FLy5uZXRyYwptYWNoaW5lICRDSV9ORVRSQ19NQUNISU5FCmxvZ2luICRDSV9ORVRSQ19VU0VSTkFNRQpwYXNzd29yZCAkQ0lfTkVUUkNfUEFTU1dPUkQKRU9GCmNobW9kIDA2MDAgJEhPTUUvLm5ldHJjCmZpCnVuc2V0IENJX05FVFJDX1VTRVJOQU1FCnVuc2V0IENJX05FVFJDX1BBU1NXT1JECnVuc2V0IENJX1NDUklQVApta2RpciAtcCAiL3dvb2RwZWNrZXIvc29tZSIKY2QgIi93b29kcGVja2VyL3NvbWUiCgplY2hvICsgJ2VjaG8gaGVsbG8gd29ybGQnCmVjaG8gaGVsbG8gd29ybGQK"
|
||||
)
|
||||
|
||||
func TestGenerateContainerConf(t *testing.T) {
|
||||
gotEnv, gotEntry := GenerateContainerConf([]string{"echo hello world"}, "windows")
|
||||
gotEnv, gotEntry := GenerateContainerConf([]string{"echo hello world"}, "windows", "/woodpecker/some")
|
||||
assert.Equal(t, windowsScriptBase64, gotEnv["CI_SCRIPT"])
|
||||
assert.Equal(t, "powershell.exe", gotEnv["SHELL"])
|
||||
assert.Equal(t, []string{"powershell", "-noprofile", "-noninteractive", "-command", "[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($Env:CI_SCRIPT)) | iex"}, gotEntry)
|
||||
gotEnv, gotEntry = GenerateContainerConf([]string{"echo hello world"}, "linux")
|
||||
gotEnv, gotEntry = GenerateContainerConf([]string{"echo hello world"}, "linux", "/woodpecker/some")
|
||||
assert.Equal(t, posixScriptBase64, gotEnv["CI_SCRIPT"])
|
||||
assert.Equal(t, "/bin/sh", gotEnv["SHELL"])
|
||||
assert.Equal(t, []string{"/bin/sh", "-c", "echo $CI_SCRIPT | base64 -d | /bin/sh -e"}, gotEntry)
|
||||
|
@ -18,10 +18,19 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
func generateScriptWindows(commands []string) string {
|
||||
func generateScriptWindows(commands []string, workDir string) string {
|
||||
var buf bytes.Buffer
|
||||
|
||||
if err := setupScriptWinTmpl.Execute(&buf, map[string]string{
|
||||
"WorkDir": workDir,
|
||||
}); err != nil {
|
||||
// should never happen but well we have an error to trance
|
||||
return fmt.Sprintf("echo 'failed to generate posix script from commands: %s'; exit 1", err.Error())
|
||||
}
|
||||
|
||||
for _, command := range commands {
|
||||
escaped := fmt.Sprintf("%q", command)
|
||||
escaped = strings.ReplaceAll(escaped, "$", `\$`)
|
||||
@ -31,16 +40,13 @@ func generateScriptWindows(commands []string) string {
|
||||
command,
|
||||
))
|
||||
}
|
||||
script := fmt.Sprintf(
|
||||
setupScriptWin,
|
||||
buf.String(),
|
||||
)
|
||||
return script
|
||||
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
const setupScriptWin = `
|
||||
const setupScriptWinProto = `
|
||||
$ErrorActionPreference = 'Stop';
|
||||
if ([Environment]::GetEnvironmentVariable('CI_WORKSPACE')) { if (-not (Test-Path "$env:CI_WORKSPACE")) { New-Item -Path "$env:CI_WORKSPACE" -ItemType Directory -Force }};
|
||||
if (-not (Test-Path "{{.WorkDir}}")) { New-Item -Path "{{.WorkDir}}" -ItemType Directory -Force };
|
||||
if (-not [Environment]::GetEnvironmentVariable('HOME')) { [Environment]::SetEnvironmentVariable('HOME', 'c:\root') };
|
||||
if (-not (Test-Path "$env:HOME")) { New-Item -Path "$env:HOME" -ItemType Directory -Force };
|
||||
if ($Env:CI_NETRC_MACHINE) {
|
||||
@ -51,10 +57,11 @@ $netrc=[string]::Format("{0}\_netrc",$Env:HOME);
|
||||
};
|
||||
[Environment]::SetEnvironmentVariable("CI_NETRC_PASSWORD",$null);
|
||||
[Environment]::SetEnvironmentVariable("CI_SCRIPT",$null);
|
||||
if ([Environment]::GetEnvironmentVariable('CI_WORKSPACE')) { cd "$env:CI_WORKSPACE" };
|
||||
%s
|
||||
cd "{{.WorkDir}}";
|
||||
`
|
||||
|
||||
var setupScriptWinTmpl, _ = template.New("").Parse(setupScriptWinProto)
|
||||
|
||||
// traceScript is a helper script that is added to the step script
|
||||
// to trace a command.
|
||||
const traceScriptWin = `
|
||||
|
@ -16,6 +16,7 @@ package common
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"text/template"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
@ -29,7 +30,7 @@ func TestGenerateScriptWin(t *testing.T) {
|
||||
from: []string{"echo %PATH%", "go build", "go test"},
|
||||
want: `
|
||||
$ErrorActionPreference = 'Stop';
|
||||
if ([Environment]::GetEnvironmentVariable('CI_WORKSPACE')) { if (-not (Test-Path "$env:CI_WORKSPACE")) { New-Item -Path "$env:CI_WORKSPACE" -ItemType Directory -Force }};
|
||||
if (-not (Test-Path "/woodpecker/some")) { New-Item -Path "/woodpecker/some" -ItemType Directory -Force };
|
||||
if (-not [Environment]::GetEnvironmentVariable('HOME')) { [Environment]::SetEnvironmentVariable('HOME', 'c:\root') };
|
||||
if (-not (Test-Path "$env:HOME")) { New-Item -Path "$env:HOME" -ItemType Directory -Force };
|
||||
if ($Env:CI_NETRC_MACHINE) {
|
||||
@ -40,7 +41,7 @@ $netrc=[string]::Format("{0}\_netrc",$Env:HOME);
|
||||
};
|
||||
[Environment]::SetEnvironmentVariable("CI_NETRC_PASSWORD",$null);
|
||||
[Environment]::SetEnvironmentVariable("CI_SCRIPT",$null);
|
||||
if ([Environment]::GetEnvironmentVariable('CI_WORKSPACE')) { cd "$env:CI_WORKSPACE" };
|
||||
cd "/woodpecker/some";
|
||||
|
||||
Write-Output ('+ "echo %PATH%"');
|
||||
& echo %PATH%; if ($LASTEXITCODE -ne 0) {exit $LASTEXITCODE}
|
||||
@ -50,12 +51,17 @@ Write-Output ('+ "go build"');
|
||||
|
||||
Write-Output ('+ "go test"');
|
||||
& go test; if ($LASTEXITCODE -ne 0) {exit $LASTEXITCODE}
|
||||
|
||||
`,
|
||||
},
|
||||
}
|
||||
for _, test := range testdata {
|
||||
script := generateScriptWindows(test.from)
|
||||
script := generateScriptWindows(test.from, "/woodpecker/some")
|
||||
assert.EqualValues(t, test.want, script, "Want encoded script for %s", test.from)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetupScriptWinProtoParse(t *testing.T) {
|
||||
// just ensure that we have a working `setupScriptWinTmpl` on runntime
|
||||
_, err := template.New("").Parse(setupScriptWinProto)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
@ -47,11 +47,14 @@ func (e *docker) toConfig(step *types.Step) *container.Config {
|
||||
maps.Copy(configEnv, step.Environment)
|
||||
|
||||
if len(step.Commands) > 0 {
|
||||
env, entry := common.GenerateContainerConf(step.Commands, e.info.OSType)
|
||||
env, entry := common.GenerateContainerConf(step.Commands, e.info.OSType, step.WorkingDir)
|
||||
for k, v := range env {
|
||||
configEnv[k] = v
|
||||
}
|
||||
config.Entrypoint = entry
|
||||
|
||||
// step.WorkingDir will be respected by the generated script
|
||||
config.WorkingDir = step.WorkspaceBase
|
||||
}
|
||||
if len(step.Entrypoint) > 0 {
|
||||
config.Entrypoint = step.Entrypoint
|
||||
|
@ -185,7 +185,7 @@ func TestToConfigSmall(t *testing.T) {
|
||||
"wp_uuid": "09238932",
|
||||
},
|
||||
Env: []string{
|
||||
"CI_SCRIPT=CmlmIFsgLW4gIiRDSV9ORVRSQ19NQUNISU5FIiBdOyB0aGVuCmNhdCA8PEVPRiA+ICRIT01FLy5uZXRyYwptYWNoaW5lICRDSV9ORVRSQ19NQUNISU5FCmxvZ2luICRDSV9ORVRSQ19VU0VSTkFNRQpwYXNzd29yZCAkQ0lfTkVUUkNfUEFTU1dPUkQKRU9GCmNobW9kIDA2MDAgJEhPTUUvLm5ldHJjCmZpCnVuc2V0IENJX05FVFJDX1VTRVJOQU1FCnVuc2V0IENJX05FVFJDX1BBU1NXT1JECnVuc2V0IENJX1NDUklQVApta2RpciAtcCAiJENJX1dPUktTUEFDRSIKY2QgIiRDSV9XT1JLU1BBQ0UiCgplY2hvICsgJ2dvIHRlc3QnCmdvIHRlc3QK",
|
||||
"CI_SCRIPT=CmlmIFsgLW4gIiRDSV9ORVRSQ19NQUNISU5FIiBdOyB0aGVuCmNhdCA8PEVPRiA+ICRIT01FLy5uZXRyYwptYWNoaW5lICRDSV9ORVRSQ19NQUNISU5FCmxvZ2luICRDSV9ORVRSQ19VU0VSTkFNRQpwYXNzd29yZCAkQ0lfTkVUUkNfUEFTU1dPUkQKRU9GCmNobW9kIDA2MDAgJEhPTUUvLm5ldHJjCmZpCnVuc2V0IENJX05FVFJDX1VTRVJOQU1FCnVuc2V0IENJX05FVFJDX1BBU1NXT1JECnVuc2V0IENJX1NDUklQVApta2RpciAtcCAiIgpjZCAiIgoKZWNobyArICdnbyB0ZXN0JwpnbyB0ZXN0Cg==",
|
||||
"SHELL=/bin/sh",
|
||||
},
|
||||
}, conf)
|
||||
@ -207,36 +207,37 @@ func TestToConfigFull(t *testing.T) {
|
||||
}
|
||||
|
||||
conf := engine.toConfig(&backend.Step{
|
||||
Name: "test",
|
||||
UUID: "09238932",
|
||||
Type: backend.StepTypeCommands,
|
||||
Image: "golang:1.2.3",
|
||||
Pull: true,
|
||||
Detached: true,
|
||||
Privileged: true,
|
||||
WorkingDir: "/src/abc",
|
||||
Environment: map[string]string{"TAGS": "sqlite"},
|
||||
Commands: []string{"go test", "go vet ./..."},
|
||||
ExtraHosts: []backend.HostAlias{{Name: "t", IP: "1.2.3.4"}},
|
||||
Volumes: []string{"/cache:/cache"},
|
||||
Tmpfs: []string{"/tmp"},
|
||||
Devices: []string{"/dev/sdc"},
|
||||
Networks: []backend.Conn{{Name: "extra-net", Aliases: []string{"extra.net"}}},
|
||||
DNS: []string{"9.9.9.9", "8.8.8.8"},
|
||||
DNSSearch: nil,
|
||||
OnFailure: true,
|
||||
OnSuccess: true,
|
||||
Failure: "fail",
|
||||
AuthConfig: backend.Auth{Username: "user", Password: "123456"},
|
||||
NetworkMode: "bridge",
|
||||
Ports: []backend.Port{{Number: 21}, {Number: 22}},
|
||||
Name: "test",
|
||||
UUID: "09238932",
|
||||
Type: backend.StepTypeCommands,
|
||||
Image: "golang:1.2.3",
|
||||
Pull: true,
|
||||
Detached: true,
|
||||
Privileged: true,
|
||||
WorkingDir: "/src/abc",
|
||||
WorkspaceBase: "/src",
|
||||
Environment: map[string]string{"TAGS": "sqlite"},
|
||||
Commands: []string{"go test", "go vet ./..."},
|
||||
ExtraHosts: []backend.HostAlias{{Name: "t", IP: "1.2.3.4"}},
|
||||
Volumes: []string{"/cache:/cache"},
|
||||
Tmpfs: []string{"/tmp"},
|
||||
Devices: []string{"/dev/sdc"},
|
||||
Networks: []backend.Conn{{Name: "extra-net", Aliases: []string{"extra.net"}}},
|
||||
DNS: []string{"9.9.9.9", "8.8.8.8"},
|
||||
DNSSearch: nil,
|
||||
OnFailure: true,
|
||||
OnSuccess: true,
|
||||
Failure: "fail",
|
||||
AuthConfig: backend.Auth{Username: "user", Password: "123456"},
|
||||
NetworkMode: "bridge",
|
||||
Ports: []backend.Port{{Number: 21}, {Number: 22}},
|
||||
})
|
||||
|
||||
assert.NotNil(t, conf)
|
||||
sort.Strings(conf.Env)
|
||||
assert.EqualValues(t, &container.Config{
|
||||
Image: "golang:1.2.3",
|
||||
WorkingDir: "/src/abc",
|
||||
WorkingDir: "/src",
|
||||
AttachStdout: true,
|
||||
AttachStderr: true,
|
||||
Entrypoint: []string{"/bin/sh", "-c", "echo $CI_SCRIPT | base64 -d | /bin/sh -e"},
|
||||
@ -245,7 +246,7 @@ func TestToConfigFull(t *testing.T) {
|
||||
"wp_uuid": "09238932",
|
||||
},
|
||||
Env: []string{
|
||||
"CI_SCRIPT=CmlmIFsgLW4gIiRDSV9ORVRSQ19NQUNISU5FIiBdOyB0aGVuCmNhdCA8PEVPRiA+ICRIT01FLy5uZXRyYwptYWNoaW5lICRDSV9ORVRSQ19NQUNISU5FCmxvZ2luICRDSV9ORVRSQ19VU0VSTkFNRQpwYXNzd29yZCAkQ0lfTkVUUkNfUEFTU1dPUkQKRU9GCmNobW9kIDA2MDAgJEhPTUUvLm5ldHJjCmZpCnVuc2V0IENJX05FVFJDX1VTRVJOQU1FCnVuc2V0IENJX05FVFJDX1BBU1NXT1JECnVuc2V0IENJX1NDUklQVApta2RpciAtcCAiJENJX1dPUktTUEFDRSIKY2QgIiRDSV9XT1JLU1BBQ0UiCgplY2hvICsgJ2dvIHRlc3QnCmdvIHRlc3QKCmVjaG8gKyAnZ28gdmV0IC4vLi4uJwpnbyB2ZXQgLi8uLi4K",
|
||||
"CI_SCRIPT=CmlmIFsgLW4gIiRDSV9ORVRSQ19NQUNISU5FIiBdOyB0aGVuCmNhdCA8PEVPRiA+ICRIT01FLy5uZXRyYwptYWNoaW5lICRDSV9ORVRSQ19NQUNISU5FCmxvZ2luICRDSV9ORVRSQ19VU0VSTkFNRQpwYXNzd29yZCAkQ0lfTkVUUkNfUEFTU1dPUkQKRU9GCmNobW9kIDA2MDAgJEhPTUUvLm5ldHJjCmZpCnVuc2V0IENJX05FVFJDX1VTRVJOQU1FCnVuc2V0IENJX05FVFJDX1BBU1NXT1JECnVuc2V0IENJX1NDUklQVApta2RpciAtcCAiL3NyYy9hYmMiCmNkICIvc3JjL2FiYyIKCmVjaG8gKyAnZ28gdGVzdCcKZ28gdGVzdAoKZWNobyArICdnbyB2ZXQgLi8uLi4nCmdvIHZldCAuLy4uLgo=",
|
||||
"SHELL=/bin/sh",
|
||||
"TAGS=sqlite",
|
||||
},
|
||||
|
@ -183,7 +183,7 @@ func podContainer(step *types.Step, podName, goos string, options BackendOptions
|
||||
container := v1.Container{
|
||||
Name: podName,
|
||||
Image: step.Image,
|
||||
WorkingDir: step.WorkspaceBase,
|
||||
WorkingDir: step.WorkingDir,
|
||||
Ports: containerPorts(step.Ports),
|
||||
SecurityContext: containerSecurityContext(options.SecurityContext, step.Privileged),
|
||||
}
|
||||
@ -193,9 +193,12 @@ func podContainer(step *types.Step, podName, goos string, options BackendOptions
|
||||
}
|
||||
|
||||
if len(step.Commands) > 0 {
|
||||
scriptEnv, command := common.GenerateContainerConf(step.Commands, goos)
|
||||
scriptEnv, command := common.GenerateContainerConf(step.Commands, goos, step.WorkingDir)
|
||||
container.Command = command
|
||||
maps.Copy(step.Environment, scriptEnv)
|
||||
|
||||
// step.WorkingDir will be respected by the generated script
|
||||
container.WorkingDir = step.WorkspaceBase
|
||||
}
|
||||
if len(step.Entrypoint) > 0 {
|
||||
container.Command = step.Entrypoint
|
||||
|
@ -105,7 +105,7 @@ func TestTinyPod(t *testing.T) {
|
||||
},
|
||||
{
|
||||
"name": "CI_SCRIPT",
|
||||
"value": "CmlmIFsgLW4gIiRDSV9ORVRSQ19NQUNISU5FIiBdOyB0aGVuCmNhdCA8PEVPRiA+ICRIT01FLy5uZXRyYwptYWNoaW5lICRDSV9ORVRSQ19NQUNISU5FCmxvZ2luICRDSV9ORVRSQ19VU0VSTkFNRQpwYXNzd29yZCAkQ0lfTkVUUkNfUEFTU1dPUkQKRU9GCmNobW9kIDA2MDAgJEhPTUUvLm5ldHJjCmZpCnVuc2V0IENJX05FVFJDX1VTRVJOQU1FCnVuc2V0IENJX05FVFJDX1BBU1NXT1JECnVuc2V0IENJX1NDUklQVApta2RpciAtcCAiJENJX1dPUktTUEFDRSIKY2QgIiRDSV9XT1JLU1BBQ0UiCgplY2hvICsgJ2dyYWRsZSBidWlsZCcKZ3JhZGxlIGJ1aWxkCg=="
|
||||
"value": "CmlmIFsgLW4gIiRDSV9ORVRSQ19NQUNISU5FIiBdOyB0aGVuCmNhdCA8PEVPRiA+ICRIT01FLy5uZXRyYwptYWNoaW5lICRDSV9ORVRSQ19NQUNISU5FCmxvZ2luICRDSV9ORVRSQ19VU0VSTkFNRQpwYXNzd29yZCAkQ0lfTkVUUkNfUEFTU1dPUkQKRU9GCmNobW9kIDA2MDAgJEhPTUUvLm5ldHJjCmZpCnVuc2V0IENJX05FVFJDX1VTRVJOQU1FCnVuc2V0IENJX05FVFJDX1BBU1NXT1JECnVuc2V0IENJX1NDUklQVApta2RpciAtcCAiL3dvb2RwZWNrZXIvc3JjIgpjZCAiL3dvb2RwZWNrZXIvc3JjIgoKZWNobyArICdncmFkbGUgYnVpbGQnCmdyYWRsZSBidWlsZAo="
|
||||
}
|
||||
],
|
||||
"resources": {},
|
||||
@ -198,7 +198,7 @@ func TestFullPod(t *testing.T) {
|
||||
},
|
||||
{
|
||||
"name": "CI_SCRIPT",
|
||||
"value": "CmlmIFsgLW4gIiRDSV9ORVRSQ19NQUNISU5FIiBdOyB0aGVuCmNhdCA8PEVPRiA+ICRIT01FLy5uZXRyYwptYWNoaW5lICRDSV9ORVRSQ19NQUNISU5FCmxvZ2luICRDSV9ORVRSQ19VU0VSTkFNRQpwYXNzd29yZCAkQ0lfTkVUUkNfUEFTU1dPUkQKRU9GCmNobW9kIDA2MDAgJEhPTUUvLm5ldHJjCmZpCnVuc2V0IENJX05FVFJDX1VTRVJOQU1FCnVuc2V0IENJX05FVFJDX1BBU1NXT1JECnVuc2V0IENJX1NDUklQVApta2RpciAtcCAiJENJX1dPUktTUEFDRSIKY2QgIiRDSV9XT1JLU1BBQ0UiCgplY2hvICsgJ2dvIGdldCcKZ28gZ2V0CgplY2hvICsgJ2dvIHRlc3QnCmdvIHRlc3QK"
|
||||
"value": "CmlmIFsgLW4gIiRDSV9ORVRSQ19NQUNISU5FIiBdOyB0aGVuCmNhdCA8PEVPRiA+ICRIT01FLy5uZXRyYwptYWNoaW5lICRDSV9ORVRSQ19NQUNISU5FCmxvZ2luICRDSV9ORVRSQ19VU0VSTkFNRQpwYXNzd29yZCAkQ0lfTkVUUkNfUEFTU1dPUkQKRU9GCmNobW9kIDA2MDAgJEhPTUUvLm5ldHJjCmZpCnVuc2V0IENJX05FVFJDX1VTRVJOQU1FCnVuc2V0IENJX05FVFJDX1BBU1NXT1JECnVuc2V0IENJX1NDUklQVApta2RpciAtcCAiL3dvb2RwZWNrZXIvc3JjIgpjZCAiL3dvb2RwZWNrZXIvc3JjIgoKZWNobyArICdnbyBnZXQnCmdvIGdldAoKZWNobyArICdnbyB0ZXN0JwpnbyB0ZXN0Cg=="
|
||||
},
|
||||
{
|
||||
"name": "SHELL",
|
||||
|
@ -1,3 +1,4 @@
|
||||
export default {
|
||||
commentOnReleasedPullRequests: false,
|
||||
skipLabels: ['skip-release', 'skip-changelog', 'regression', 'backport-done'],
|
||||
};
|
||||
|
@ -16,6 +16,7 @@
|
||||
package gitea
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
@ -111,6 +112,11 @@ func parsePullRequestHook(payload io.Reader) (*model.Repo, *model.Pipeline, erro
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if pr.PullRequest == nil {
|
||||
// this should never have happened but it did - so we check
|
||||
return nil, nil, fmt.Errorf("parsed pull_request webhook does not contain pull_request info")
|
||||
}
|
||||
|
||||
// Don't trigger pipelines for non-code changes ...
|
||||
if pr.Action != actionOpen && pr.Action != actionSync && pr.Action != actionClose {
|
||||
log.Debug().Msgf("pull_request action is '%s' and no open or sync", pr.Action)
|
||||
|
@ -14,9 +14,14 @@
|
||||
|
||||
package store
|
||||
|
||||
import "time"
|
||||
|
||||
type XORM struct {
|
||||
Log bool
|
||||
ShowSQL bool
|
||||
Log bool
|
||||
ShowSQL bool
|
||||
MaxIdleConns int
|
||||
MaxOpenConns int
|
||||
ConnMaxLifetime time.Duration
|
||||
}
|
||||
|
||||
// Opts are options for a new database connection.
|
||||
|
@ -45,6 +45,9 @@ func NewEngine(opts *store.Opts) (store.Store, error) {
|
||||
logger := newXORMLogger(level)
|
||||
engine.SetLogger(logger)
|
||||
engine.ShowSQL(opts.XORM.ShowSQL)
|
||||
engine.SetMaxOpenConns(opts.XORM.MaxOpenConns)
|
||||
engine.SetMaxIdleConns(opts.XORM.MaxIdleConns)
|
||||
engine.SetConnMaxLifetime(opts.XORM.ConnMaxLifetime)
|
||||
|
||||
return &storage{
|
||||
engine: engine,
|
||||
|
59
server/store/datastore/migration/018_fix-orgs-users-match.go
Normal file
59
server/store/datastore/migration/018_fix-orgs-users-match.go
Normal file
@ -0,0 +1,59 @@
|
||||
// Copyright 2024 Woodpecker 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.
|
||||
|
||||
package migration
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"src.techknowlogick.com/xormigrate"
|
||||
"xorm.io/xorm"
|
||||
"xorm.io/xorm/schemas"
|
||||
)
|
||||
|
||||
var correctPotentialCorruptOrgsUsersRelation = xormigrate.Migration{
|
||||
ID: "correct-potential-corrupt-orgs-users-relation",
|
||||
MigrateSession: func(sess *xorm.Session) error {
|
||||
type users struct {
|
||||
ID int64 `xorm:"pk autoincr 'id'"`
|
||||
ForgeID int64 `xorm:"forge_id"`
|
||||
Login string `xorm:"UNIQUE 'login'"`
|
||||
OrgID int64 `xorm:"org_id"`
|
||||
}
|
||||
|
||||
type orgs struct {
|
||||
ID int64 `xorm:"pk autoincr 'id'"`
|
||||
ForgeID int64 `xorm:"forge_id"`
|
||||
Name string `xorm:"UNIQUE 'name'"`
|
||||
}
|
||||
|
||||
if err := sess.Sync(new(users), new(orgs)); err != nil {
|
||||
return fmt.Errorf("sync new models failed: %w", err)
|
||||
}
|
||||
|
||||
dialect := sess.Engine().Dialect().URI().DBType
|
||||
var err error
|
||||
switch dialect {
|
||||
case schemas.MYSQL:
|
||||
_, err = sess.Exec(`UPDATE users u JOIN orgs o ON o.name = u.login AND o.forge_id = u.forge_id SET u.org_id = o.id;`)
|
||||
case schemas.POSTGRES:
|
||||
_, err = sess.Exec(`UPDATE users u SET org_id = o.id FROM orgs o WHERE o.name = u.login AND o.forge_id = u.forge_id;`)
|
||||
case schemas.SQLITE:
|
||||
_, err = sess.Exec(`UPDATE users SET org_id = ( SELECT orgs.id FROM orgs WHERE orgs.name = users.login AND orgs.forge_id = users.forge_id ) WHERE users.login IN (SELECT orgs.name FROM orgs);`)
|
||||
default:
|
||||
err = fmt.Errorf("dialect '%s' not supported", dialect)
|
||||
}
|
||||
return err
|
||||
},
|
||||
}
|
@ -46,6 +46,7 @@ var migrationTasks = []*xormigrate.Migration{
|
||||
&addOrgAgents,
|
||||
&addCustomLabelsToAgent,
|
||||
&splitTrusted,
|
||||
&correctPotentialCorruptOrgsUsersRelation,
|
||||
}
|
||||
|
||||
var allBeans = []any{
|
||||
|
Loading…
Reference in New Issue
Block a user