Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package semaphore for openSUSE:Factory checked in at 2025-11-06 18:15:01 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/semaphore (Old) and /work/SRC/openSUSE:Factory/.semaphore.new.1980 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "semaphore" Thu Nov 6 18:15:01 2025 rev:20 rq:1315943 version:2.16.43 Changes: -------- --- /work/SRC/openSUSE:Factory/semaphore/semaphore.changes 2025-11-02 22:34:29.895515191 +0100 +++ /work/SRC/openSUSE:Factory/.semaphore.new.1980/semaphore.changes 2025-11-06 18:18:14.092202727 +0100 @@ -1,0 +2,13 @@ +Thu Nov 06 06:44:26 UTC 2025 - Johannes Kastl <[email protected]> + +- Update to version 2.16.43 (no releases between .37 and this one): + * ci: fix pro workflow + * ci: download goreleaser binary + * ci: upgrade golang + * ci: fix go version + * feat(integrations): add unit tests + * fix(integrations): rename target name for extracted values + * fix(integrations): pass extracted vars to playbook + * fix(ui): correct placeholders for templates + +------------------------------------------------------------------- Old: ---- semaphore-2.16.37.obscpio web-2.16.37.tar.gz New: ---- semaphore-2.16.43.obscpio web-2.16.43.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ semaphore.spec ++++++ --- /var/tmp/diff_new_pack.2iJ85R/_old 2025-11-06 18:18:16.376299305 +0100 +++ /var/tmp/diff_new_pack.2iJ85R/_new 2025-11-06 18:18:16.376299305 +0100 @@ -17,7 +17,7 @@ Name: semaphore -Version: 2.16.37 +Version: 2.16.43 Release: 0 Summary: Modern UI for Ansible License: MIT ++++++ _service ++++++ --- /var/tmp/diff_new_pack.2iJ85R/_old 2025-11-06 18:18:16.448302349 +0100 +++ /var/tmp/diff_new_pack.2iJ85R/_new 2025-11-06 18:18:16.452302519 +0100 @@ -3,7 +3,7 @@ <param name="url">https://github.com/ansible-semaphore/semaphore</param> <param name="scm">git</param> <param name="exclude">.git</param> - <param name="revision">v2.16.37</param> + <param name="revision">v2.16.43</param> <param name="versionformat">@PARENT_TAG@</param> <param name="versionrewrite-pattern">v(.*)</param> <param name="changesgenerate">enable</param> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.2iJ85R/_old 2025-11-06 18:18:16.472303364 +0100 +++ /var/tmp/diff_new_pack.2iJ85R/_new 2025-11-06 18:18:16.484303872 +0100 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/ansible-semaphore/semaphore</param> - <param name="changesrevision">349f60d914a90b21708229cad99b43326ca16109</param></service></servicedata> + <param name="changesrevision">5507a117fcc6d48ac3bd35315d83dce211c47ff8</param></service></servicedata> (No newline at EOF) ++++++ semaphore-2.16.37.obscpio -> semaphore-2.16.43.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/semaphore-2.16.37/Taskfile.yml new/semaphore-2.16.43/Taskfile.yml --- old/semaphore-2.16.37/Taskfile.yml 2025-10-30 08:26:59.000000000 +0100 +++ new/semaphore-2.16.43/Taskfile.yml 2025-11-05 20:48:26.000000000 +0100 @@ -21,20 +21,17 @@ deps: desc: Install all build dependencies cmds: - - task: deps:tools - task: deps:be - task: deps:fe deps:tools: desc: Installs required tools to build and publish vars: - SWAGGER_VERSION: v0.30.5 GORELEASER_VERSION: v1.25.1 - GOLINTER_VERSION: v1.57.2 cmds: -# - go install github.com/go-swagger/go-swagger/cmd/swagger@{{ .SWAGGER_VERSION }} - - go install github.com/goreleaser/goreleaser@{{ .GORELEASER_VERSION }} -# - go install github.com/golangci/golangci-lint/cmd/golangci-lint@{{ .GOLINTER_VERSION }} + - wget https://github.com/goreleaser/goreleaser/releases/download/{{ .GORELEASER_VERSION }}/goreleaser_Linux_x86_64.tar.gz + - tar xf goreleaser_Linux_x86_64.tar.gz + - mv goreleaser /usr/local/bin/ dir: /tmp deps:be: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/semaphore-2.16.37/api/integration.go new/semaphore-2.16.43/api/integration.go --- old/semaphore-2.16.37/api/integration.go 2025-10-30 08:26:59.000000000 +0100 +++ new/semaphore-2.16.43/api/integration.go 2025-11-05 20:48:26.000000000 +0100 @@ -295,8 +295,12 @@ if err != nil { return } + } - for k, v := range extractedEnvResults { + // Add extracted environment variables only if they don't conflict with + // existing task definition variables (task definition has higher priority) + for k, v := range extractedEnvResults { + if _, exists := env[k]; !exists { env[k] = v } } @@ -308,7 +312,7 @@ taskDefinition.Environment = string(envStr) - extractedTaskResults := ExtractAsAnyForTaskParams(taskValues, h, payload) + extractedTaskResults := Extract(taskValues, h, payload) for k, v := range extractedTaskResults { taskDefinition.Params[k] = v } @@ -357,8 +361,10 @@ case db.IntegrationExtractBodyValue: switch extractValue.BodyDataType { case db.IntegrationBodyDataJSON: - var extractedResult = fmt.Sprintf("%v", gojsonq.New().JSONString(string(payload)).Find(extractValue.Key)) - result[extractValue.Variable] = extractedResult + val := gojsonq.New().JSONString(string(payload)).Find(extractValue.Key) + if val != nil { + result[extractValue.Variable] = fmt.Sprintf("%v", val) + } case db.IntegrationBodyDataString: result[extractValue.Variable] = string(payload) } @@ -366,29 +372,3 @@ } return } - -func ExtractAsAnyForTaskParams(extractValues []db.IntegrationExtractValue, h http.Header, payload []byte) db.MapStringAnyField { - // Create a result map that accepts any type - result := make(db.MapStringAnyField) - - for _, extractValue := range extractValues { - switch extractValue.ValueSource { - case db.IntegrationExtractHeaderValue: - // Extract the header value - result[extractValue.Variable] = h.Get(extractValue.Key) - - case db.IntegrationExtractBodyValue: - switch extractValue.BodyDataType { - case db.IntegrationBodyDataJSON: - // Query the JSON payload for the key using gojsonq - rawValue := gojsonq.New().JSONString(string(payload)).Find(extractValue.Key) - result[extractValue.Variable] = rawValue - - case db.IntegrationBodyDataString: - // Simply use the entire payload as a string - result[extractValue.Variable] = string(payload) - } - } - } - return result -} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/semaphore-2.16.37/api/integration_test.go new/semaphore-2.16.43/api/integration_test.go --- old/semaphore-2.16.37/api/integration_test.go 2025-10-30 08:26:59.000000000 +0100 +++ new/semaphore-2.16.43/api/integration_test.go 2025-11-05 20:48:26.000000000 +0100 @@ -8,8 +8,153 @@ "github.com/semaphoreui/semaphore/db" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) +func TestExtract_HeaderAndCaseInsensitive(t *testing.T) { + h := http.Header{} + h.Set("x-token", "abc123") // lower-case to verify case-insensitive get + + values := []db.IntegrationExtractValue{ + { + Name: "Token header", + ValueSource: db.IntegrationExtractHeaderValue, + Key: "X-Token", // different case + Variable: "TOKEN", + VariableType: db.IntegrationVariableEnvironment, + }, + } + + got := Extract(values, h, nil) + + require.Equal(t, "abc123", got["TOKEN"], "TOKEN header value should match") +} + +func TestExtract_JSONBody_VariousTypesAndMissing(t *testing.T) { + payload := []byte(`{ + "num": 42, + "str": "hello", + "bool": true, + "nullv": null, + "obj": {"k":"v"}, + "arr": [1,2,3], + "nested": {"items":[{"c":123},{"c":"str"}]} + }`) + + values := []db.IntegrationExtractValue{ + { // number coerced to string via fmt.Sprintf + ValueSource: db.IntegrationExtractBodyValue, + BodyDataType: db.IntegrationBodyDataJSON, + Key: "num", + Variable: "NUM", + }, + { // string stays same content + ValueSource: db.IntegrationExtractBodyValue, + BodyDataType: db.IntegrationBodyDataJSON, + Key: "str", + Variable: "STR", + }, + { // boolean -> "true" + ValueSource: db.IntegrationExtractBodyValue, + BodyDataType: db.IntegrationBodyDataJSON, + Key: "bool", + Variable: "BOOL", + }, + { // null should not be set (Find returns nil or we skip when nil) + ValueSource: db.IntegrationExtractBodyValue, + BodyDataType: db.IntegrationBodyDataJSON, + Key: "nullv", + Variable: "NULLV", + }, + { // array will be formatted with %v, expect Go-like format + ValueSource: db.IntegrationExtractBodyValue, + BodyDataType: db.IntegrationBodyDataJSON, + Key: "arr", + Variable: "ARR", + }, + { // object -> formatted map with %v + ValueSource: db.IntegrationExtractBodyValue, + BodyDataType: db.IntegrationBodyDataJSON, + Key: "obj", + Variable: "OBJ", + }, + { // missing key should not create an entry + ValueSource: db.IntegrationExtractBodyValue, + BodyDataType: db.IntegrationBodyDataJSON, + Key: "missing", + Variable: "MISSING", + }, + { // nested array index path + ValueSource: db.IntegrationExtractBodyValue, + BodyDataType: db.IntegrationBodyDataJSON, + Key: "nested.items.[0].c", + Variable: "NESTED_C", + }, + { // first element of arr + ValueSource: db.IntegrationExtractBodyValue, + BodyDataType: db.IntegrationBodyDataJSON, + Key: "arr.[0]", + Variable: "ARR0", + }, + } + + got := Extract(values, http.Header{}, payload) + + // Basic scalar assertions + assert.Equal(t, "42", got["NUM"], "NUM should equal stringified number") + assert.Equal(t, "hello", got["STR"], "STR should match") + assert.Equal(t, "true", got["BOOL"], "BOOL should be string 'true'") + + // Indexed lookups + assert.Equal(t, "123", got["NESTED_C"], "NESTED_C should equal nested.items[0].c") + assert.Equal(t, "1", got["ARR0"], "ARR0 should equal arr[0]") + + // Null should be absent + assert.NotContains(t, got, "NULLV", "NULLV should not be present for null JSON value") + + // Array/object string formats: we assert non-empty presence rather than exact formatting, + // because %v formatting of gojsonq return types may vary across versions. + assert.Contains(t, got, "ARR", "ARR key should be present") + assert.NotEmpty(t, got["ARR"], "ARR value should be non-empty") + assert.Contains(t, got, "OBJ", "OBJ key should be present") + assert.NotEmpty(t, got["OBJ"], "OBJ value should be non-empty") + + // Missing should not appear + assert.NotContains(t, got, "MISSING", "MISSING should not be present for missing key") +} + +func TestExtract_BodyString_ReturnsFullPayload(t *testing.T) { + payload := []byte("raw body data here") + values := []db.IntegrationExtractValue{ + { + ValueSource: db.IntegrationExtractBodyValue, + BodyDataType: db.IntegrationBodyDataString, + Variable: "BODY", + Key: "ignored", + }, + } + got := Extract(values, http.Header{}, payload) + if got["BODY"] != string(payload) { + t.Fatalf("expected BODY to equal full payload; got %q", got["BODY"]) + } +} + +func TestExtract_MalformedJSON_SkipsSetting(t *testing.T) { + payload := []byte("{not: valid json}") + values := []db.IntegrationExtractValue{ + { + ValueSource: db.IntegrationExtractBodyValue, + BodyDataType: db.IntegrationBodyDataJSON, + Variable: "BAD", + Key: "a.b", + }, + } + got := Extract(values, http.Header{}, payload) + if _, ok := got["BAD"]; ok { + t.Fatalf("expected BAD to be absent for malformed JSON payload") + } +} + func TestIntegrationMatch(t *testing.T) { body := []byte("{\"hook_id\": 4856239453}") var header = make(http.Header) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/semaphore-2.16.37/deployment/docker/dredd/Dockerfile new/semaphore-2.16.43/deployment/docker/dredd/Dockerfile --- old/semaphore-2.16.37/deployment/docker/dredd/Dockerfile 2025-10-30 08:26:59.000000000 +0100 +++ new/semaphore-2.16.43/deployment/docker/dredd/Dockerfile 2025-11-05 20:48:26.000000000 +0100 @@ -14,7 +14,6 @@ go mod download -x RUN --mount=type=cache,target=/go/pkg --mount=type=cache,target=/root/.cache/go-build \ - task deps:tools && \ task deps:be && \ task dredd:goodman && \ task dredd:hooks diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/semaphore-2.16.37/go.mod new/semaphore-2.16.43/go.mod --- old/semaphore-2.16.37/go.mod 2025-10-30 08:26:59.000000000 +0100 +++ new/semaphore-2.16.43/go.mod 2025-11-05 20:48:26.000000000 +0100 @@ -1,6 +1,6 @@ module github.com/semaphoreui/semaphore -go 1.24.2 +go 1.24.6 require ( github.com/Masterminds/squirrel v1.5.4 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/semaphore-2.16.37/pro/go.mod new/semaphore-2.16.43/pro/go.mod --- old/semaphore-2.16.37/pro/go.mod 2025-10-30 08:26:59.000000000 +0100 +++ new/semaphore-2.16.43/pro/go.mod 2025-11-05 20:48:26.000000000 +0100 @@ -1,6 +1,6 @@ module github.com/semaphoreui/semaphore/pro -go 1.24.2 +go 1.24.6 require github.com/semaphoreui/semaphore v0.0.0-20250712180151-72836311c5b9 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/semaphore-2.16.37/web/src/components/AppFieldsMixin.js new/semaphore-2.16.43/web/src/components/AppFieldsMixin.js --- old/semaphore-2.16.37/web/src/components/AppFieldsMixin.js 2025-10-30 08:26:59.000000000 +0100 +++ new/semaphore-2.16.43/web/src/components/AppFieldsMixin.js 2025-11-05 20:48:26.000000000 +0100 @@ -10,6 +10,14 @@ methods: { + fieldPlaceholder(f) { + return this.$t((this.fields[f] || { label: f }).placeholder); + }, + + fieldHint(f) { + return this.$t((this.fields[f] || { label: f }).hint); + }, + fieldLabel(f) { return this.$t((this.fields[f] || { label: f }).label); }, @@ -21,5 +29,9 @@ isFieldRequired(f) { return this.fields[f] != null && !this.fields[f].optional; }, + + fieldRequiredError(f) { + return this.$t((this.fields[f] || { label: f }).required); + }, }, }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/semaphore-2.16.37/web/src/components/IntegrationExtractValueForm.vue new/semaphore-2.16.43/web/src/components/IntegrationExtractValueForm.vue --- old/semaphore-2.16.37/web/src/components/IntegrationExtractValueForm.vue 2025-10-30 08:26:59.000000000 +0100 +++ new/semaphore-2.16.43/web/src/components/IntegrationExtractValueForm.vue 2025-11-05 20:48:26.000000000 +0100 @@ -107,10 +107,10 @@ }], variableTypes: [{ id: 'environment', - text: 'Environment', + text: 'Variables', }, { id: 'task', - text: 'Task', + text: 'Task Params', }], }; }, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/semaphore-2.16.37/web/src/components/TemplateForm.vue new/semaphore-2.16.43/web/src/components/TemplateForm.vue --- old/semaphore-2.16.37/web/src/components/TemplateForm.vue 2025-10-30 08:26:59.000000000 +0100 +++ new/semaphore-2.16.43/web/src/components/TemplateForm.vue 2025-11-05 20:48:26.000000000 +0100 @@ -173,7 +173,8 @@ dense :required="isFieldRequired('playbook')" :disabled="formSaving" - :placeholder="$t('exampleSiteyml')" + :placeholder="fieldPlaceholder('playbook')" + :hint="fieldHint('playbook')" v-if="needField('playbook')" ></v-text-field> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/semaphore-2.16.37/web/src/lib/constants.js new/semaphore-2.16.43/web/src/lib/constants.js --- old/semaphore-2.16.37/web/src/lib/constants.js 2025-10-30 08:26:59.000000000 +0100 +++ new/semaphore-2.16.43/web/src/lib/constants.js 2025-11-05 20:48:26.000000000 +0100 @@ -175,6 +175,10 @@ export const ANSIBLE_FIELDS = { ...BASE_FIELDS, + playbook: { + label: 'playbookFilename', + placeholder: 'exampleSiteyml', + }, vault: { label: 'vaultPassword2', }, @@ -207,7 +211,9 @@ export const TERRAFORM_FIELDS = { ...BASE_FIELDS, playbook: { - label: 'Subdirectory path (Optional)', + label: 'Terraform code path (Optional)', + placeholder: '', + hint: 'Path to the folder in the repository containing Terraform code.', optional: true, }, inventory: { @@ -236,7 +242,8 @@ export const UNKNOWN_APP_FIELDS = { ...BASE_FIELDS, playbook: { - label: 'Script Filename *', + label: 'Script file path', + placeholder: 'Example: path/to/script/in/repo', }, inventory: undefined, }; ++++++ semaphore.obsinfo ++++++ --- /var/tmp/diff_new_pack.2iJ85R/_old 2025-11-06 18:18:17.712355797 +0100 +++ /var/tmp/diff_new_pack.2iJ85R/_new 2025-11-06 18:18:17.720356136 +0100 @@ -1,5 +1,5 @@ name: semaphore -version: 2.16.37 -mtime: 1761809219 -commit: 349f60d914a90b21708229cad99b43326ca16109 +version: 2.16.43 +mtime: 1762372106 +commit: 5507a117fcc6d48ac3bd35315d83dce211c47ff8 ++++++ vendor.tar.gz ++++++ /work/SRC/openSUSE:Factory/semaphore/vendor.tar.gz /work/SRC/openSUSE:Factory/.semaphore.new.1980/vendor.tar.gz differ: char 13, line 1 ++++++ web-2.16.37.tar.gz -> web-2.16.43.tar.gz ++++++ /work/SRC/openSUSE:Factory/semaphore/web-2.16.37.tar.gz /work/SRC/openSUSE:Factory/.semaphore.new.1980/web-2.16.43.tar.gz differ: char 14, line 1
