This is an automated email from the ASF dual-hosted git repository.
klesh pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/devlake.git
The following commit(s) were added to refs/heads/main by this push:
new d4b31f1ed build(deps): maintain Go dependencies and migrate
mapstructure v2 (#9061)
d4b31f1ed is described below
commit d4b31f1ede5bc326d8ae4893e1a79b0599c51f05
Author: Dirk <[email protected]>
AuthorDate: Wed Aug 26 05:54:15 2026 +0200
build(deps): maintain Go dependencies and migrate mapstructure v2 (#9061)
* build(deps): bump x/mod to v0.40.0
* build(deps): update gorm postgres driver
* build(deps): update go-oidc
* refactor(deps): replace mapstructure with go-viper v2
* fix(db): keep postgres index drops compatible with updated GORM
* fix: make mysql schema migrations idempotent
Signed-off-by: DoDiODev <[email protected]>
* fix(db): keep AutoMigrate from redefining the mysql primary key
gorm.io/driver/mysql v1.6.0 appends 'ADD PRIMARY KEY' to every column added
by
AutoMigrate that carries the primaryKey tag. DevLake migration scripts add
such
columns to tables that already own a primary key, so MySQL rejected them
with
'Error 1068: Multiple primary key defined'.
Wrap the MySQL dialector so AddColumn keeps the pre-v1.6.0 behaviour: the
primary key is only created for AUTO_INCREMENT columns on tables without
one,
every other primary key change stays with the migration scripts.
Signed-off-by: DoDiODev <[email protected]>
---------
Signed-off-by: DoDiODev <[email protected]>
---
backend/core/runner/db.go | 6 +-
backend/core/runner/mysql_dialector.go | 111 +++++++++++++++++++++
backend/go.mod | 20 ++--
backend/go.sum | 47 +++++----
backend/helpers/migrationhelper/migrationhelper.go | 37 +++++++
backend/helpers/pluginhelper/api/mapstructure.go | 2 +-
backend/helpers/utils/mapstructure.go | 2 +-
backend/impls/dalgorm/dalgorm.go | 9 +-
backend/plugins/customize/impl/impl.go | 2 +-
backend/plugins/github/api/connection_api.go | 2 +-
backend/plugins/issue_trace/impl/enricher.go | 2 +-
backend/plugins/jira/api/connection_api.go | 2 +-
.../e2e/issue_code_block_long_component_test.go | 4 +-
backend/plugins/zentao/tasks/task_data.go | 2 +-
backend/server/services/remote/plugin/scope_api.go | 2 +-
15 files changed, 205 insertions(+), 45 deletions(-)
diff --git a/backend/core/runner/db.go b/backend/core/runner/db.go
index 0e3925942..8b1f6fcf1 100644
--- a/backend/core/runner/db.go
+++ b/backend/core/runner/db.go
@@ -145,13 +145,13 @@ func MakeDbConnection(dbUrl string, conf *gorm.Config)
(*gorm.DB, error) {
if err != nil {
return nil, err
}
- gormDB, err := gorm.Open(mysql.New(mysql.Config{
+ gormDB, err :=
gorm.Open(wrapMysqlDialector(mysql.New(mysql.Config{
Conn: db,
- }), &gorm.Config{})
+ })), &gorm.Config{})
return gormDB, err
}
- return gorm.Open(mysql.Open(dbUrl), conf)
+ return gorm.Open(wrapMysqlDialector(mysql.Open(dbUrl)), conf)
case "postgresql", "postgres", "pg":
return gorm.Open(postgres.Open(dbUrl), conf)
default:
diff --git a/backend/core/runner/mysql_dialector.go
b/backend/core/runner/mysql_dialector.go
new file mode 100644
index 000000000..49fb9843a
--- /dev/null
+++ b/backend/core/runner/mysql_dialector.go
@@ -0,0 +1,111 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You 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 runner
+
+import (
+ "fmt"
+ "strings"
+
+ "gorm.io/driver/mysql"
+ "gorm.io/gorm"
+ "gorm.io/gorm/clause"
+ gormmigrator "gorm.io/gorm/migrator"
+ "gorm.io/gorm/schema"
+)
+
+// primaryKeyIndexName is the fixed name MySQL gives to the primary key index
+const primaryKeyIndexName = "PRIMARY"
+
+// wrapMysqlDialector decorates the GORM MySQL dialector so that AutoMigrate
keeps
+// working for DevLake's migration scripts.
+//
+// Since gorm.io/driver/mysql v1.6.0, `AddColumn` appends `ADD PRIMARY KEY
(<col>)`
+// whenever the added field carries the `primaryKey` tag. DevLake migration
scripts
+// regularly add such a column to a table that already owns a primary key,
which
+// makes MySQL fail with `Error 1068: Multiple primary key defined`. Primary
key
+// changes are always performed explicitly by the migration scripts (see
+// migrationhelper.ChangePrimaryKeyColumnsType), so the column is added
without the
+// implicit clause, matching the behaviour of the previous driver release. The
only
+// exception is an `AUTO_INCREMENT` column, which MySQL requires to be a key.
+func wrapMysqlDialector(dialector gorm.Dialector) gorm.Dialector {
+ if mysqlDialector, ok := dialector.(*mysql.Dialector); ok {
+ return safeMysqlDialector{Dialector: *mysqlDialector}
+ }
+ return dialector
+}
+
+type safeMysqlDialector struct {
+ mysql.Dialector
+}
+
+// Migrator returns the MySQL migrator with the AddColumn workaround applied
+func (d safeMysqlDialector) Migrator(db *gorm.DB) gorm.Migrator {
+ return safeMysqlMigrator{Migrator: d.Dialector.Migrator(db), db: db}
+}
+
+type safeMysqlMigrator struct {
+ gorm.Migrator
+ db *gorm.DB
+}
+
+// mysqlMigratorInternals exposes the helpers of the embedded GORM migrator
that
+// are needed to rebuild the `ALTER TABLE ... ADD ...` statement
+type mysqlMigratorInternals interface {
+ RunWithValue(value interface{}, fc func(*gorm.Statement) error) error
+ FullDataTypeOf(field *schema.Field) clause.Expr
+ CurrentTable(stmt *gorm.Statement) interface{}
+}
+
+// AddColumn adds a column without implicitly promoting it to the primary key
of
+// the table, see wrapMysqlDialector for the rationale
+func (m safeMysqlMigrator) AddColumn(value interface{}, name string) error {
+ base, ok := m.Migrator.(mysqlMigratorInternals)
+ if !ok {
+ return m.Migrator.AddColumn(value, name)
+ }
+ return base.RunWithValue(value, func(stmt *gorm.Statement) error {
+ field := stmt.Schema.LookUpField(name)
+ if field == nil {
+ return fmt.Errorf("failed to look up field with name:
%s", name)
+ }
+ if field.IgnoreMigration {
+ return nil
+ }
+ fieldType := base.FullDataTypeOf(field)
+ columnName := clause.Column{Name: field.DBName}
+ values := []interface{}{base.CurrentTable(stmt), columnName,
fieldType}
+ alterSql := "ALTER TABLE ? ADD ? ?"
+ // MySQL requires an AUTO_INCREMENT column to be a key, every
other primary
+ // key is managed explicitly by the migration scripts
+ if strings.Contains(strings.ToLower(fieldType.SQL),
"auto_increment") &&
+ !m.Migrator.HasIndex(value, primaryKeyIndexName) {
+ alterSql += ", ADD PRIMARY KEY (?)"
+ values = append(values, columnName)
+ }
+ return m.db.Exec(alterSql, values...).Error
+ })
+}
+
+// BuildIndexOptions forwards to the embedded migrator, GORM requires every
+// migrator to implement migrator.BuildIndexOptionsInterface while creating
tables
+func (m safeMysqlMigrator) BuildIndexOptions(opts []schema.IndexOption, stmt
*gorm.Statement) []interface{} {
+ if builder, ok := m.Migrator.(gormmigrator.BuildIndexOptionsInterface);
ok {
+ return builder.BuildIndexOptions(opts, stmt)
+ }
+ return nil
+}
diff --git a/backend/go.mod b/backend/go.mod
index 9e92f0890..6b46bc04a 100644
--- a/backend/go.mod
+++ b/backend/go.mod
@@ -10,12 +10,12 @@ require (
github.com/go-errors/errors v1.4.2 // indirect
github.com/go-git/go-git/v5 v5.19.2
github.com/go-playground/validator/v10 v10.19.0
+ github.com/go-viper/mapstructure/v2 v2.5.0
github.com/gocarina/gocsv v0.0.0-20220707092902-b9da1f06c77e
github.com/google/uuid v1.3.0
github.com/jackc/pgx/v5 v5.10.0
github.com/libgit2/git2go/v34 v34.0.0
github.com/magiconair/properties v1.8.5
- github.com/mitchellh/mapstructure v1.5.0
github.com/panjf2000/ants/v2 v2.4.6
github.com/robfig/cron/v3 v3.0.0
github.com/sirupsen/logrus v1.10.0
@@ -34,23 +34,24 @@ require (
golang.org/x/oauth2 v0.36.0
golang.org/x/sync v0.22.0
gorm.io/datatypes v1.0.1
- gorm.io/driver/mysql v1.5.1
- gorm.io/driver/postgres v1.5.2
- gorm.io/gorm v1.25.5
+ gorm.io/driver/mysql v1.6.0
+ gorm.io/driver/postgres v1.6.2
+ gorm.io/gorm v1.31.2
)
require (
github.com/chainguard-dev/git-urls v1.0.2
- github.com/coreos/go-oidc/v3 v3.9.0
- github.com/go-sql-driver/mysql v1.7.1
+ github.com/coreos/go-oidc/v3 v3.20.0
+ github.com/go-sql-driver/mysql v1.8.1
github.com/golang-jwt/jwt/v5 v5.3.1
github.com/merico-ai/graphql v0.0.0-20260206020408-b7fd267bcfac
github.com/rogpeppe/go-internal v1.14.1
- golang.org/x/mod v0.38.0
+ golang.org/x/mod v0.40.0
)
require (
dario.cat/mergo v1.0.0 // indirect
+ filippo.io/edwards25519 v1.1.0 // indirect
github.com/KyleBanks/depth v1.2.1 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/ProtonMail/go-crypto v1.1.6 // indirect
@@ -70,7 +71,7 @@ require (
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
github.com/go-git/go-billy/v5 v5.9.0 // indirect
- github.com/go-jose/go-jose/v3 v3.0.1 // indirect
+ github.com/go-jose/go-jose/v4 v4.1.4 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/jsonreference v0.19.6 // indirect
github.com/go-openapi/spec v0.20.4 // indirect
@@ -98,6 +99,7 @@ require (
github.com/leodido/go-urn v1.4.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
+ github.com/mitchellh/mapstructure v1.4.1 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd //
indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml v1.9.3 // indirect
@@ -120,7 +122,7 @@ require (
golang.org/x/net v0.58.0 // indirect
golang.org/x/sys v0.47.0 // indirect
golang.org/x/text v0.41.0 // indirect
- golang.org/x/tools v0.48.0 // indirect
+ golang.org/x/tools v0.49.0 // indirect
google.golang.org/protobuf v1.36.12 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
diff --git a/backend/go.sum b/backend/go.sum
index 91c719303..bb0abbcb1 100644
--- a/backend/go.sum
+++ b/backend/go.sum
@@ -39,6 +39,8 @@ cloud.google.com/go/storage v1.10.0/go.mod
h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod
h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
+filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
+filippo.io/edwards25519 v1.1.0/go.mod
h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/BurntSushi/toml v0.3.1/go.mod
h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod
h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/KyleBanks/depth v1.2.1
h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
@@ -89,8 +91,8 @@ github.com/cockroachdb/logtags
v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZe
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod
h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs=
github.com/cockroachdb/redact v1.1.5
h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30=
github.com/cockroachdb/redact v1.1.5/go.mod
h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg=
-github.com/coreos/go-oidc/v3 v3.9.0
h1:0J/ogVOd4y8P0f0xUh8l9t07xRP/d8tccvjHl2dcsSo=
-github.com/coreos/go-oidc/v3 v3.9.0/go.mod
h1:rTKz2PYwftcrtoCzV5g5kvfJoWcm0Mk8AF8y1iAQro4=
+github.com/coreos/go-oidc/v3 v3.20.0
h1:EtE0WIBHk03N+DqGkY4+UONzzZHk7amKt6IyNd7OsZE=
+github.com/coreos/go-oidc/v3 v3.20.0/go.mod
h1:DYCf24+ncYi+XkIH97GY1+dqoRlbaSI26KVTCI9SrY4=
github.com/coreos/go-semver v0.3.0/go.mod
h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod
h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod
h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
@@ -147,8 +149,8 @@ github.com/go-git/go-git/v5 v5.19.2/go.mod
h1:QqCBE1EFN5ddFmrliLQ3/ntRCUjZU3EJuw
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod
h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod
h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod
h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
-github.com/go-jose/go-jose/v3 v3.0.1
h1:pWmKFVtt+Jl0vBZTIpz/eAKwsm6LkIxDVVbFHKkchhA=
-github.com/go-jose/go-jose/v3 v3.0.1/go.mod
h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8=
+github.com/go-jose/go-jose/v4 v4.1.4
h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA=
+github.com/go-jose/go-jose/v4 v4.1.4/go.mod
h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08=
github.com/go-openapi/jsonpointer v0.19.3/go.mod
h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonpointer v0.19.5
h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
github.com/go-openapi/jsonpointer v0.19.5/go.mod
h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
@@ -168,10 +170,11 @@ github.com/go-playground/universal-translator
v0.18.1/go.mod h1:xekY+UJKNuX9WP91
github.com/go-playground/validator/v10 v10.19.0
h1:ol+5Fu+cSq9JD7SoSqe04GMI92cbn0+wvQ3bZ8b/AU4=
github.com/go-playground/validator/v10 v10.19.0/go.mod
h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/go-sql-driver/mysql v1.5.0/go.mod
h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
-github.com/go-sql-driver/mysql v1.7.0/go.mod
h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
-github.com/go-sql-driver/mysql v1.7.1
h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
-github.com/go-sql-driver/mysql v1.7.1/go.mod
h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
+github.com/go-sql-driver/mysql v1.8.1
h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
+github.com/go-sql-driver/mysql v1.8.1/go.mod
h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
github.com/go-stack/stack v1.8.0/go.mod
h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
+github.com/go-viper/mapstructure/v2 v2.5.0
h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro=
+github.com/go-viper/mapstructure/v2 v2.5.0/go.mod
h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/gocarina/gocsv v0.0.0-20220707092902-b9da1f06c77e
h1:GMIV+S6grz+vlIaUsP+fedQ6L+FovyMPMY26WO8dwQE=
github.com/gocarina/gocsv v0.0.0-20220707092902-b9da1f06c77e/go.mod
h1:5YoVOkjYAQumqlV356Hj3xeYh4BdZuLE0/nRkf2NKkI=
github.com/goccy/go-json v0.10.2
h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
@@ -393,8 +396,9 @@ github.com/mattn/go-isatty v0.0.9/go.mod
h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2y
github.com/mattn/go-isatty v0.0.12/go.mod
h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
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/mattn/go-sqlite3 v1.14.5
h1:1IdxlwTNazvbKJQSxoJ5/9ECbEeaTTyeU7sEAZ5KKTQ=
github.com/mattn/go-sqlite3 v1.14.5/go.mod
h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI=
+github.com/mattn/go-sqlite3 v1.14.22
h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
+github.com/mattn/go-sqlite3 v1.14.22/go.mod
h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/merico-ai/graphql v0.0.0-20260206020408-b7fd267bcfac
h1:J3wm8OohrRkYf/+Zy5GxqvhzcP2qHGJRduxTUUbBMdw=
github.com/merico-ai/graphql v0.0.0-20260206020408-b7fd267bcfac/go.mod
h1:4WSOgvd/Sv6eLKJE6fvrXlmxePBDGhbwRYKEBeqJr8g=
github.com/miekg/dns v1.0.14/go.mod
h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
@@ -405,9 +409,8 @@ github.com/mitchellh/gox v0.4.0/go.mod
h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS4
github.com/mitchellh/iochan v1.0.0/go.mod
h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod
h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2/go.mod
h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
+github.com/mitchellh/mapstructure v1.4.1
h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
github.com/mitchellh/mapstructure v1.4.1/go.mod
h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
-github.com/mitchellh/mapstructure v1.5.0
h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
-github.com/mitchellh/mapstructure v1.5.0/go.mod
h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod
h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd
h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod
h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -605,8 +608,8 @@ golang.org/x/mod v0.4.0/go.mod
h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod
h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
-golang.org/x/mod v0.38.0 h1:MECBjubtXD7yj4HrhIUcywNaGeNVUdfVnxmPajOk4yk=
-golang.org/x/mod v0.38.0/go.mod h1:V6Xz0pq8TQ3dGqVQ1FVHuelZpAL0uNhSkk9ogYP3c40=
+golang.org/x/mod v0.40.0 h1:hUv+3cXcdRHz08UmSiOob7sadHig73uo5bkXxQ/tvUs=
+golang.org/x/mod v0.40.0/go.mod h1:0/weTWkPWGBikyTWAX3dkjVztMmBA5hM0DH6BElSupE=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod
h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod
h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod
h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -816,8 +819,8 @@ golang.org/x/tools
v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.1.0/go.mod
h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.2/go.mod
h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.12/go.mod
h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
-golang.org/x/tools v0.48.0 h1:3+hClM1aLL5mjMKm5ovokw9epgRXPuu2tILgismM6RE=
-golang.org/x/tools v0.48.0/go.mod
h1:08xX0orndb/F7jJxGDicx061tyd5pcMto75YMAXr6lk=
+golang.org/x/tools v0.49.0 h1:3NI7VXzL9+1WZD52Dx2ttoPwD5DWrFGpl9mFZDlmisI=
+golang.org/x/tools v0.49.0/go.mod
h1:SJNXV9DBKT0UbdttsQjbfJlAE/q+y36++zo3uL3N0Oo=
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod
h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod
h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod
h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -955,13 +958,14 @@ gopkg.in/yaml.v3 v3.0.1/go.mod
h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/datatypes v1.0.1 h1:6npnXbBtjpSb7FFVA2dG/llyTN8tvZfbUqs+WyLrYgQ=
gorm.io/datatypes v1.0.1/go.mod h1:HEHoUU3/PO5ZXfAJcVWl11+zWlE16+O0X2DgJEb4Ixs=
gorm.io/driver/mysql v1.0.5/go.mod
h1:N1OIhHAIhx5SunkMGqWbGFVeh4yTNWKmMo1GOAsohLI=
-gorm.io/driver/mysql v1.5.1 h1:WUEH5VF9obL/lTtzjmML/5e6VfFR/788coz2uaVCAZw=
-gorm.io/driver/mysql v1.5.1/go.mod
h1:Jo3Xu7mMhCyj8dlrb3WoCaRd1FhsVh+yMXb1jUInf5o=
+gorm.io/driver/mysql v1.6.0 h1:eNbLmNTpPpTOVZi8MMxCi2aaIm0ZpInbORNXDwyLGvg=
+gorm.io/driver/mysql v1.6.0/go.mod
h1:D/oCC2GWK3M/dqoLxnOlaNKmXz8WNTfcS9y5ovaSqKo=
gorm.io/driver/postgres v1.0.8/go.mod
h1:4eOzrI1MUfm6ObJU/UcmbXyiHSs8jSwH95G5P5dxcAg=
-gorm.io/driver/postgres v1.5.2 h1:ytTDxxEv+MplXOfFe3Lzm7SjG09fcdb3Z/c056DTBx0=
-gorm.io/driver/postgres v1.5.2/go.mod
h1:fmpX0m2I1PKuR7mKZiEluwrP3hbs+ps7JIGMUBpCgl8=
-gorm.io/driver/sqlite v1.1.4 h1:PDzwYE+sI6De2+mxAneV9Xs11+ZyKV6oxD3wDGkaNvM=
+gorm.io/driver/postgres v1.6.2 h1:BvXQ/cNUg63q5TFNg672DmDcowZSFrNLkkA3Xe6GXq4=
+gorm.io/driver/postgres v1.6.2/go.mod
h1:0c4fQA44XhOklXDkgtuKqysHCycTa5i9e3EIpDGCwXk=
gorm.io/driver/sqlite v1.1.4/go.mod
h1:mJCeTFr7+crvS+TRnWc5Z3UvwxUN1BGBLMrf5LA9DYw=
+gorm.io/driver/sqlite v1.6.0 h1:WHRRrIiulaPiPFmDcod6prc4l2VGVWHz80KspNsxSfQ=
+gorm.io/driver/sqlite v1.6.0/go.mod
h1:AO9V1qIQddBESngQUKWL9yoH93HIeA1X6V633rBwyT8=
gorm.io/driver/sqlserver v1.0.7 h1:uwUtb0kdFwW5PkRbd2KJ2h4wlsqvLSjox1XVg/RnzRE=
gorm.io/driver/sqlserver v1.0.7/go.mod
h1:ng66aHI47ZIKz/vvnxzDoonzmTS8HXP+JYlgg67wOog=
gorm.io/gorm v1.20.7/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
@@ -969,9 +973,8 @@ gorm.io/gorm v1.20.12/go.mod
h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
gorm.io/gorm v1.21.3/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
gorm.io/gorm v1.21.4/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
gorm.io/gorm v1.21.6/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0=
-gorm.io/gorm v1.25.1/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
-gorm.io/gorm v1.25.5 h1:zR9lOiiYf09VNh5Q1gphfyia1JpiClIWG9hQaxB/mls=
-gorm.io/gorm v1.25.5/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
+gorm.io/gorm v1.31.2 h1:3o8FXNo9v9S858gil+3LlZA1LkCOzgb4g5BL64FgaCo=
+gorm.io/gorm v1.31.2/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod
h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod
h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod
h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/backend/helpers/migrationhelper/migrationhelper.go
b/backend/helpers/migrationhelper/migrationhelper.go
index 691413b1a..93186e64c 100644
--- a/backend/helpers/migrationhelper/migrationhelper.go
+++ b/backend/helpers/migrationhelper/migrationhelper.go
@@ -153,6 +153,43 @@ func ChangePrimaryKeyColumnsType[D any](
return err
}
+ // Some GORM dialects recreate the primary key while AutoMigrate
changes the
+ // column type, so adding it unconditionally would fail with a
duplicate key.
+ primaryKeyColumns, err := dal.GetPrimarykeyColumns(db,
dal.DefaultTabler{Name: tableName})
+ if err != nil {
+ return errors.Default.Wrap(err, fmt.Sprintf("failed to check
primary key on table [%s]", tableName))
+ }
+ if len(primaryKeyColumns) == len(TargetPriColumns) {
+ existingPrimaryKeyColumns := make(map[string]struct{},
len(primaryKeyColumns))
+ for _, column := range primaryKeyColumns {
+ existingPrimaryKeyColumns[column.Name()] = struct{}{}
+ }
+ allColumnsPresent := true
+ for _, column := range TargetPriColumns {
+ if _, ok := existingPrimaryKeyColumns[column]; !ok {
+ allColumnsPresent = false
+ break
+ }
+ }
+ if allColumnsPresent {
+ return nil
+ }
+ }
+
+ if len(primaryKeyColumns) > 0 {
+ if u.Scheme == "mysql" {
+ sql := fmt.Sprintf("ALTER TABLE %s DROP PRIMARY KEY",
tableName)
+ if err := db.Exec(sql); err != nil {
+ return err
+ }
+ } else {
+ sql := fmt.Sprintf("ALTER TABLE %s DROP CONSTRAINT
%s_pkey", tableName, tableName)
+ if err := db.Exec(sql); err != nil {
+ return err
+ }
+ }
+ }
+
// Add the primary key
sql := fmt.Sprintf("ALTER TABLE %s ADD PRIMARY KEY (%s)", tableName,
strings.Join(TargetPriColumns, ","))
if err := db.Exec(sql); err != nil {
diff --git a/backend/helpers/pluginhelper/api/mapstructure.go
b/backend/helpers/pluginhelper/api/mapstructure.go
index ff8e84ee1..8a1a348ec 100644
--- a/backend/helpers/pluginhelper/api/mapstructure.go
+++ b/backend/helpers/pluginhelper/api/mapstructure.go
@@ -28,7 +28,7 @@ import (
"github.com/apache/incubator-devlake/core/models/common"
"github.com/go-playground/validator/v10"
- "github.com/mitchellh/mapstructure"
+ "github.com/go-viper/mapstructure/v2"
)
var defaultCustomDecoderHooks =
[]mapstructure.DecodeHookFunc{decodeHookStringFloat64, decodeHookStringToTime,
DecodeHook}
diff --git a/backend/helpers/utils/mapstructure.go
b/backend/helpers/utils/mapstructure.go
index 22ea85949..4b9684156 100644
--- a/backend/helpers/utils/mapstructure.go
+++ b/backend/helpers/utils/mapstructure.go
@@ -28,7 +28,7 @@ import (
"github.com/apache/incubator-devlake/core/errors"
"github.com/go-playground/validator/v10"
- "github.com/mitchellh/mapstructure"
+ "github.com/go-viper/mapstructure/v2"
)
func DecodeHook(f reflect.Type, t reflect.Type, data interface{})
(interface{}, error) {
diff --git a/backend/impls/dalgorm/dalgorm.go b/backend/impls/dalgorm/dalgorm.go
index 0445995fd..bf5538dda 100644
--- a/backend/impls/dalgorm/dalgorm.go
+++ b/backend/impls/dalgorm/dalgorm.go
@@ -456,7 +456,14 @@ func (d *Dalgorm) DropIndexes(table string, indexNames
...string) errors.Error {
if !d.db.Migrator().HasIndex(table, indexName) {
continue
}
- err := d.db.Migrator().DropIndex(table, indexName)
+ var err error
+ if d.Dialect() == "postgres" {
+ // gorm.io/driver/postgres v1.6.x quotes its
CURRENT_SCHEMA()
+ // expression when dropping an index, yielding invalid
SQL.
+ err = d.db.Exec("DROP INDEX IF EXISTS ?",
clause.Column{Name: indexName}).Error
+ } else {
+ err = d.db.Migrator().DropIndex(table, indexName)
+ }
if err != nil {
return d.convertGormError(err)
}
diff --git a/backend/plugins/customize/impl/impl.go
b/backend/plugins/customize/impl/impl.go
index dd689b794..6df6359a0 100644
--- a/backend/plugins/customize/impl/impl.go
+++ b/backend/plugins/customize/impl/impl.go
@@ -26,7 +26,7 @@ import (
"github.com/apache/incubator-devlake/plugins/customize/models"
"github.com/apache/incubator-devlake/plugins/customize/models/migrationscripts"
"github.com/apache/incubator-devlake/plugins/customize/tasks"
- "github.com/mitchellh/mapstructure"
+ "github.com/go-viper/mapstructure/v2"
)
var _ interface {
diff --git a/backend/plugins/github/api/connection_api.go
b/backend/plugins/github/api/connection_api.go
index a5f0e922d..f09c8def8 100644
--- a/backend/plugins/github/api/connection_api.go
+++ b/backend/plugins/github/api/connection_api.go
@@ -23,7 +23,7 @@ import (
"net/http"
"strings"
- "github.com/mitchellh/mapstructure"
+ "github.com/go-viper/mapstructure/v2"
"github.com/apache/incubator-devlake/core/errors"
"github.com/apache/incubator-devlake/core/plugin"
diff --git a/backend/plugins/issue_trace/impl/enricher.go
b/backend/plugins/issue_trace/impl/enricher.go
index 1506f2563..73280d323 100644
--- a/backend/plugins/issue_trace/impl/enricher.go
+++ b/backend/plugins/issue_trace/impl/enricher.go
@@ -30,7 +30,7 @@ import (
"github.com/apache/incubator-devlake/plugins/issue_trace/models"
"github.com/apache/incubator-devlake/plugins/issue_trace/models/migrationscripts"
"github.com/apache/incubator-devlake/plugins/issue_trace/tasks"
- "github.com/mitchellh/mapstructure"
+ "github.com/go-viper/mapstructure/v2"
)
type IssueTrace struct{}
diff --git a/backend/plugins/jira/api/connection_api.go
b/backend/plugins/jira/api/connection_api.go
index 209ab6c5c..fa1de5848 100644
--- a/backend/plugins/jira/api/connection_api.go
+++ b/backend/plugins/jira/api/connection_api.go
@@ -30,7 +30,7 @@ import (
"github.com/apache/incubator-devlake/core/plugin"
"github.com/apache/incubator-devlake/helpers/pluginhelper/api"
"github.com/apache/incubator-devlake/plugins/jira/models"
- "github.com/mitchellh/mapstructure"
+ "github.com/go-viper/mapstructure/v2"
)
type JiraTestConnResponse struct {
diff --git
a/backend/plugins/sonarqube/e2e/issue_code_block_long_component_test.go
b/backend/plugins/sonarqube/e2e/issue_code_block_long_component_test.go
index e1a7d52b5..5eecac7be 100644
--- a/backend/plugins/sonarqube/e2e/issue_code_block_long_component_test.go
+++ b/backend/plugins/sonarqube/e2e/issue_code_block_long_component_test.go
@@ -80,10 +80,10 @@ func TestSonarqubeIssueCodeBlockLongComponent(t *testing.T)
{
&sonarqubeIssueCodeBlockBeforeText{},
&cqIssueCodeBlockBeforeText{},
))
- require.NoError(t, dataflowTester.Db.Migrator().DropIndex(
+ require.NoError(t, dataflowTester.Dal.DropIndexes(
"cq_issue_code_blocks", "idx_cq_issue_code_blocks_component",
))
- require.NoError(t, dataflowTester.Db.Migrator().DropIndex(
+ require.NoError(t, dataflowTester.Dal.DropIndexes(
"_tool_sonarqube_issue_code_blocks",
"idx__tool_sonarqube_issue_code_blocks_component",
))
diff --git a/backend/plugins/zentao/tasks/task_data.go
b/backend/plugins/zentao/tasks/task_data.go
index 26bc9734c..b1f4d56b1 100644
--- a/backend/plugins/zentao/tasks/task_data.go
+++ b/backend/plugins/zentao/tasks/task_data.go
@@ -24,7 +24,7 @@ import (
"github.com/apache/incubator-devlake/core/errors"
helper "github.com/apache/incubator-devlake/helpers/pluginhelper/api"
"github.com/apache/incubator-devlake/plugins/zentao/models"
- "github.com/mitchellh/mapstructure"
+ "github.com/go-viper/mapstructure/v2"
)
type ZentaoApiParams models.ZentaoApiParams
diff --git a/backend/server/services/remote/plugin/scope_api.go
b/backend/server/services/remote/plugin/scope_api.go
index 9450422e7..78c36f33c 100644
--- a/backend/server/services/remote/plugin/scope_api.go
+++ b/backend/server/services/remote/plugin/scope_api.go
@@ -23,7 +23,7 @@ import (
"strings"
"github.com/apache/incubator-devlake/server/services/remote/models"
- "github.com/mitchellh/mapstructure"
+ "github.com/go-viper/mapstructure/v2"
"github.com/apache/incubator-devlake/core/errors"
"github.com/apache/incubator-devlake/core/plugin"