diff --git a/.drone.yml b/.drone.yml index cd7a0394a..1e0037b06 100644 --- a/.drone.yml +++ b/.drone.yml @@ -172,6 +172,20 @@ pipeline: when: event: [ push, tag, pull_request ] + test-mssql: + image: golang:1.10 + pull: true + group: test + environment: + TAGS: bindata + TEST_LDAP: "1" + commands: + - curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | bash + - apt-get install -y git-lfs + - make test-mssql + when: + event: [ push, tag, pull_request ] + generate-coverage: image: golang:1.10 pull: true @@ -340,6 +354,15 @@ services: when: event: [ push, tag, pull_request ] + mssql: + image: microsoft/mssql-server-linux:latest + environment: + - ACCEPT_EULA=Y + - SA_PASSWORD=MwantsaSecurePassword1 + - MSSQL_PID=Standard + when: + event: [ push, tag, pull_request ] + ldap: image: gitea/test-openldap:latest when: diff --git a/.gitignore b/.gitignore index 9a5f01bb9..941ec41e0 100644 --- a/.gitignore +++ b/.gitignore @@ -53,11 +53,14 @@ coverage.all /integrations/gitea-integration-mysql /integrations/gitea-integration-pgsql /integrations/gitea-integration-sqlite +/integrations/gitea-integration-mssql /integrations/indexers-mysql /integrations/indexers-pgsql /integrations/indexers-sqlite +/integrations/indexers-mssql /integrations/mysql.ini /integrations/pgsql.ini +/integrations/mssql.ini /node_modules diff --git a/Makefile b/Makefile index 256e872ad..2ca272a01 100644 --- a/Makefile +++ b/Makefile @@ -50,6 +50,10 @@ TEST_PGSQL_HOST ?= pgsql:5432 TEST_PGSQL_DBNAME ?= testgitea TEST_PGSQL_USERNAME ?= postgres TEST_PGSQL_PASSWORD ?= postgres +TEST_MSSQL_HOST ?= mssql:1433 +TEST_MSSQL_DBNAME ?= gitea +TEST_MSSQL_USERNAME ?= sa +TEST_MSSQL_PASSWORD ?= MwantsaSecurePassword1 ifeq ($(OS), Windows_NT) EXECUTABLE := gitea.exe @@ -70,9 +74,9 @@ clean: $(GO) clean -i ./... rm -rf $(EXECUTABLE) $(DIST) $(BINDATA) \ integrations*.test \ - integrations/gitea-integration-pgsql/ integrations/gitea-integration-mysql/ integrations/gitea-integration-sqlite/ \ - integrations/indexers-mysql/ integrations/indexers-pgsql integrations/indexers-sqlite \ - integrations/mysql.ini integrations/pgsql.ini + integrations/gitea-integration-pgsql/ integrations/gitea-integration-mysql/ integrations/gitea-integration-sqlite/ integrations/gitea-integration-mssql/ \ + integrations/indexers-mysql/ integrations/indexers-pgsql integrations/indexers-sqlite integrations/indexers-mssql \ + integrations/mysql.ini integrations/pgsql.ini integrations/mssql.ini .PHONY: fmt fmt: @@ -197,6 +201,11 @@ generate-ini: -e 's|{{TEST_PGSQL_USERNAME}}|${TEST_PGSQL_USERNAME}|g' \ -e 's|{{TEST_PGSQL_PASSWORD}}|${TEST_PGSQL_PASSWORD}|g' \ integrations/pgsql.ini.tmpl > integrations/pgsql.ini + sed -e 's|{{TEST_MSSQL_HOST}}|${TEST_MSSQL_HOST}|g' \ + -e 's|{{TEST_MSSQL_DBNAME}}|${TEST_MSSQL_DBNAME}|g' \ + -e 's|{{TEST_MSSQL_USERNAME}}|${TEST_MSSQL_USERNAME}|g' \ + -e 's|{{TEST_MSSQL_PASSWORD}}|${TEST_MSSQL_PASSWORD}|g' \ + integrations/mssql.ini.tmpl > integrations/mssql.ini .PHONY: test-mysql test-mysql: integrations.test generate-ini @@ -206,6 +215,10 @@ test-mysql: integrations.test generate-ini test-pgsql: integrations.test generate-ini GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/pgsql.ini ./integrations.test +.PHONY: test-mssql +test-mssql: integrations.test generate-ini + GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/mssql.ini ./integrations.test + .PHONY: bench-sqlite bench-sqlite: integrations.sqlite.test GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/sqlite.ini ./integrations.sqlite.test -test.cpuprofile=cpu.out -test.run DontRunTests -test.bench . diff --git a/integrations/integration_test.go b/integrations/integration_test.go index a1e66ffdf..971bdbf3b 100644 --- a/integrations/integration_test.go +++ b/integrations/integration_test.go @@ -47,6 +47,8 @@ func TestMain(m *testing.M) { helper = &testfixtures.PostgreSQL{} } else if setting.UseSQLite3 { helper = &testfixtures.SQLite{} + } else if setting.UseMSSQL { + helper = &testfixtures.SQLServer{} } else { fmt.Println("Unsupported RDBMS for integration tests") os.Exit(1) @@ -130,6 +132,17 @@ func initIntegrationTest() { if _, err = db.Exec("CREATE DATABASE testgitea"); err != nil { log.Fatalf("db.Exec: %v", err) } + case setting.UseMSSQL: + host, port := models.ParseMSSQLHostPort(models.DbCfg.Host) + db, err := sql.Open("mssql", fmt.Sprintf("server=%s; port=%s; database=%s; user id=%s; password=%s;", + host, port, "master", models.DbCfg.User, models.DbCfg.Passwd)) + if err != nil { + log.Fatalf("sql.Open: %v", err) + } + if _, err := db.Exec("If(db_id(N'gitea') IS NULL) BEGIN CREATE DATABASE gitea; END;"); err != nil { + log.Fatalf("db.Exec: %v", err) + } + defer db.Close() } routers.GlobalInit() } diff --git a/integrations/mssql.ini.tmpl b/integrations/mssql.ini.tmpl new file mode 100644 index 000000000..08f7e9ca3 --- /dev/null +++ b/integrations/mssql.ini.tmpl @@ -0,0 +1,72 @@ +APP_NAME = Gitea: Git with a cup of tea +RUN_MODE = prod + +[database] +DB_TYPE = mssql +HOST = {{TEST_MSSQL_HOST}} +NAME = {{TEST_MSSQL_DBNAME}} +USER = {{TEST_MSSQL_USERNAME}} +PASSWD = {{TEST_MSSQL_PASSWORD}} +SSL_MODE = disable + +[indexer] +ISSUE_INDEXER_PATH = integrations/indexers-mssql/issues.bleve +REPO_INDEXER_ENABLED = true +REPO_INDEXER_PATH = integrations/indexers-mssql/repos.bleve + +[repository] +ROOT = integrations/gitea-integration-mssql/gitea-repositories + +[repository.local] +LOCAL_COPY_PATH = tmp/local-repo-mssql +LOCAL_WIKI_PATH = tmp/local-wiki-mssql + +[server] +SSH_DOMAIN = localhost +HTTP_PORT = 3003 +ROOT_URL = http://localhost:3003/ +DISABLE_SSH = false +SSH_LISTEN_HOST = localhost +SSH_PORT = 2201 +START_SSH_SERVER = true +LFS_START_SERVER = true +LFS_CONTENT_PATH = data/lfs-mssql +OFFLINE_MODE = false +LFS_JWT_SECRET = Tv_MjmZuHqpIY6GFl12ebgkRAMt4RlWt0v4EHKSXO0w +APP_DATA_PATH = integrations/gitea-integration-mssql/data + +[mailer] +ENABLED = false + +[service] +REGISTER_EMAIL_CONFIRM = false +ENABLE_NOTIFY_MAIL = false +DISABLE_REGISTRATION = false +ENABLE_CAPTCHA = false +REQUIRE_SIGNIN_VIEW = false +DEFAULT_KEEP_EMAIL_PRIVATE = false +DEFAULT_ALLOW_CREATE_ORGANIZATION = true +NO_REPLY_ADDRESS = noreply.example.org + +[picture] +DISABLE_GRAVATAR = false +ENABLE_FEDERATED_AVATAR = false + +[session] +PROVIDER = file +PROVIDER_CONFIG = data/sessions-mssql + +[log] +MODE = console,file +ROOT_PATH = mssql-log + +[log.console] +LEVEL = Warn + +[log.file] +LEVEL = Debug + +[security] +INSTALL_LOCK = true +SECRET_KEY = 9pCviYTWSb +INTERNAL_TOKEN = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE0OTU1NTE2MTh9.hhSVGOANkaKk3vfCd2jDOIww4pUk0xtg9JRde5UogyQ diff --git a/models/models.go b/models/models.go index 9477b6950..2624f48f8 100644 --- a/models/models.go +++ b/models/models.go @@ -199,7 +199,8 @@ func getPostgreSQLConnectionString(DBHost, DBUser, DBPasswd, DBName, DBParam, DB return } -func parseMSSQLHostPort(info string) (string, string) { +// ParseMSSQLHostPort splits the host into host and port +func ParseMSSQLHostPort(info string) (string, string) { host, port := "127.0.0.1", "1433" if strings.Contains(info, ":") { host = strings.Split(info, ":")[0] @@ -231,7 +232,7 @@ func getEngine() (*xorm.Engine, error) { case "postgres": connStr = getPostgreSQLConnectionString(DbCfg.Host, DbCfg.User, DbCfg.Passwd, DbCfg.Name, Param, DbCfg.SSLMode) case "mssql": - host, port := parseMSSQLHostPort(DbCfg.Host) + host, port := ParseMSSQLHostPort(DbCfg.Host) connStr = fmt.Sprintf("server=%s; port=%s; database=%s; user id=%s; password=%s;", host, port, DbCfg.Name, DbCfg.User, DbCfg.Passwd) case "sqlite3": if !EnableSQLite3 {