Test all supported databases in CI (#2000)

* add mysql and postgres tests to CI
This commit is contained in:
Doug Lauder 2021-12-17 12:30:47 -05:00 committed by GitHub
parent bf22a6faf9
commit 7af9e18a49
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 172 additions and 25 deletions

View file

@ -43,9 +43,15 @@ jobs:
name: focalboard-server-linux-amd64.tar.gz
path: ${{ github.workspace }}/dist/focalboard-server-linux-amd64.tar.gz
- name: Test server
- name: "Test server: sqlite"
run: make server-test
- name: "Test server: mysql"
run: make server-test-mysql
- name: "Test server: postgres"
run: make server-test-postgres
- name: "Test webapp: Jest"
run: cd webapp; npm run test

View file

@ -105,6 +105,28 @@ watch-server-test: modd-precheck ## Run server tests watching for changes
server-test: ## Run server tests
cd server; go test -race -v -count=1 ./...
server-test-mysql: export FB_UNIT_TESTING=1
server-test-mysql: export FB_STORE_TEST_DB_TYPE=mysql
server-test-mysql: export FB_STORE_TEST_DOCKER_PORT=44445
server-test-mysql: ## Run server tests using mysql
@echo Starting docker container for mysql
docker-compose -f ./docker-testing/docker-compose-mysql.yml run start_dependencies
cd server; go test -race -v -count=1 ./...
docker-compose -f ./docker-testing/docker-compose-mysql.yml down -v --remove-orphans
server-test-postgres: export FB_UNIT_TESTING=1
server-test-postgres: export FB_STORE_TEST_DB_TYPE=postgres
server-test-postgres: export FB_STORE_TEST_DOCKER_PORT=44446
server-test-postgres: ## Run server tests using postgres
@echo Starting docker container for postgres
docker-compose -f ./docker-testing/docker-compose-postgres.yml run start_dependencies
cd server; go test -race -v -count=1 ./...
docker-compose -f ./docker-testing/docker-compose-postgres.yml down -v --remove-orphans
webapp: ## Build webapp.
cd webapp; npm run pack

View file

@ -0,0 +1,25 @@
version: '2.4'
services:
mysql:
image: "mysql/mysql-server:5.7.12"
restart: always
environment:
MYSQL_ROOT_HOST: "%"
MYSQL_ROOT_PASSWORD: mostest
MYSQL_PASSWORD: mostest
MYSQL_USER: mmuser
healthcheck:
test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost"]
interval: 5s
timeout: 10s
retries: 3
tmpfs: /var/lib/mysql
ports:
- 44445:3306
start_dependencies:
image: mattermost/mattermost-wait-for-dep:latest
depends_on:
- mysql
command: mysql

View file

@ -0,0 +1,23 @@
version: '2.4'
services:
postgres:
image: "postgres:10"
restart: always
environment:
POSTGRES_USER: mmuser
POSTGRES_PASSWORD: mostest
healthcheck:
test: [ "CMD", "pg_isready", "-h", "localhost" ]
interval: 5s
timeout: 10s
retries: 3
tmpfs: /var/lib/postgresql/data
ports:
- 44446:5432
start_dependencies:
image: mattermost/mattermost-wait-for-dep:latest
depends_on:
- postgres
command: postgres:5432

View file

@ -10,6 +10,7 @@ import (
"github.com/mattermost/focalboard/server/client"
"github.com/mattermost/focalboard/server/server"
"github.com/mattermost/focalboard/server/services/config"
"github.com/mattermost/focalboard/server/services/store/sqlstore"
"github.com/mattermost/focalboard/server/utils"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
@ -21,15 +22,10 @@ type TestHelper struct {
Client2 *client.Client
}
func getTestConfig() *config.Configuration {
dbType := os.Getenv("FB_STORE_TEST_DB_TYPE")
if dbType == "" {
dbType = "sqlite3"
}
connectionString := os.Getenv("FB_STORE_TEST_CONN_STRING")
if connectionString == "" {
connectionString = ":memory:"
func getTestConfig() (*config.Configuration, error) {
dbType, connectionString, err := sqlstore.PrepareNewTestDatabase()
if err != nil {
return nil, err
}
logging := `
@ -66,15 +62,19 @@ func getTestConfig() *config.Configuration {
LoggingCfgJSON: logging,
SessionExpireTime: int64(30 * time.Second),
AuthMode: "native",
}
}, nil
}
func newTestServer(singleUserToken string) *server.Server {
logger, _ := mlog.NewLogger()
if err := logger.Configure("", getTestConfig().LoggingCfgJSON, nil); err != nil {
cfg, err := getTestConfig()
if err != nil {
panic(err)
}
logger, _ := mlog.NewLogger()
if err = logger.Configure("", cfg.LoggingCfgJSON, nil); err != nil {
panic(err)
}
cfg := getTestConfig()
db, err := server.NewStore(cfg, logger)
if err != nil {
panic(err)

View file

@ -182,7 +182,7 @@ func (s *SQLStore) getSubTree3(db sq.BaseRunner, c store.Container, blockID stri
Join(s.tablePrefix + "blocks" + " as l3 on l3.parent_id = l2.id or l3.id = l2.id").
Where(sq.Eq{"l1.id": blockID}).
Where(sq.Eq{"COALESCE(l3.workspace_id, '0')": c.WorkspaceID}).
OrderBy("l3.insert_at")
OrderBy("l3.id, l3.insert_at")
if opts.BeforeUpdateAt != 0 {
query = query.Where(sq.LtOrEq{"update_at": opts.BeforeUpdateAt})

View file

@ -2,7 +2,6 @@ package sqlstore
import (
"database/sql"
"os"
"testing"
"github.com/mattermost/focalboard/server/services/store"
@ -12,15 +11,8 @@ import (
)
func SetupTests(t *testing.T) (store.Store, func()) {
dbType := os.Getenv("FB_STORE_TEST_DB_TYPE")
if dbType == "" {
dbType = sqliteDBType
}
connectionString := os.Getenv("FB_STORE_TEST_CONN_STRING")
if connectionString == "" {
connectionString = ":memory:"
}
dbType, connectionString, err := PrepareNewTestDatabase()
require.NoError(t, err)
logger := mlog.CreateConsoleTestLogger(false, mlog.LvlDebug)

View file

@ -2,8 +2,12 @@ package sqlstore
import (
"database/sql"
"fmt"
"os"
"strings"
"github.com/mattermost/focalboard/server/services/store"
"github.com/mattermost/focalboard/server/utils"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
)
@ -17,3 +21,78 @@ func (s *SQLStore) CloseRows(rows *sql.Rows) {
func (s *SQLStore) IsErrNotFound(err error) bool {
return store.IsErrNotFound(err)
}
func PrepareNewTestDatabase() (dbType string, connectionString string, err error) {
dbType = strings.TrimSpace(os.Getenv("FB_STORE_TEST_DB_TYPE"))
if dbType == "" {
dbType = sqliteDBType
}
var dbName string
var rootUser string
if dbType == sqliteDBType {
connectionString = ":memory:"
} else if port := strings.TrimSpace(os.Getenv("FB_STORE_TEST_DOCKER_PORT")); port != "" {
// docker unit tests take priority over any DSN env vars
var template string
switch dbType {
case mysqlDBType:
template = "%s:mostest@tcp(localhost:%s)/%s?charset=utf8mb4,utf8&writeTimeout=30s"
rootUser = "root"
case postgresDBType:
template = "postgres://%s:mostest@localhost:%s/%s?sslmode=disable\u0026connect_timeout=10"
rootUser = "mmuser"
default:
return "", "", newErrInvalidDBType(dbType)
}
connectionString = fmt.Sprintf(template, rootUser, port, "")
// create a new database each run
sqlDB, err := sql.Open(dbType, connectionString)
if err != nil {
return "", "", fmt.Errorf("cannot connect to %s database: %w", dbType, err)
}
defer sqlDB.Close()
err = sqlDB.Ping()
if err != nil {
return "", "", fmt.Errorf("cannot ping %s database: %w", dbType, err)
}
dbName = "testdb_" + utils.NewID(utils.IDTypeNone)[:8]
_, err = sqlDB.Exec(fmt.Sprintf("CREATE DATABASE %s;", dbName))
if err != nil {
return "", "", fmt.Errorf("cannot create %s database %s: %w", dbType, dbName, err)
}
if dbType != postgresDBType {
_, err = sqlDB.Exec(fmt.Sprintf("GRANT ALL PRIVILEGES ON %s.* TO mmuser;", dbName))
if err != nil {
return "", "", fmt.Errorf("cannot grant permissions on %s database %s: %w", dbType, dbName, err)
}
}
connectionString = fmt.Sprintf(template, "mmuser", port, dbName)
} else {
// mysql or postgres need a DSN (connection string)
connectionString = strings.TrimSpace(os.Getenv("FB_STORE_TEST_CONN_STRING"))
}
return dbType, connectionString, nil
}
type ErrInvalidDBType struct {
dbType string
}
func newErrInvalidDBType(dbType string) error {
return ErrInvalidDBType{
dbType: dbType,
}
}
func (e ErrInvalidDBType) Error() string {
return "unsupported database type: " + e.dbType
}