mirror of
https://github.com/andwati/zitadel.git
synced 2026-10-18 05:52:51 +00:00
## Problem description - Setup currently creates/updates relational tables, but there is no built-in way to fully reset the relational schema during iterative development. - Re-running setup after schema/projection changes can leave stale relational objects and projection state behind, which makes local/dev validation harder. - There is no explicit, configurable switch in setup steps for destructive schema recreation behavior. ## How the Problems Are Solved - Adds a new setup step configuration section for relational tables with a `ShouldRecreateSchema` flag (default `false`). - Wires the new config flag into the transactional tables setup step. - Extends the transactional tables execution logic to optionally: - Drop the `zitadel` schema with `CASCADE` - Clean related projection state entries for relational tables in `projections.current_states` - Recreate tables through the existing setup flow afterward - Wraps the destructive operations in a transaction and keeps error/rollback handling plus logging for visibility. ## Additional Changes - Adds an explicit warning in step configuration that schema recreation is intended for development and not production use. - Keeps behavior fully backward-compatible by default (`ShouldRecreateSchema: false`), so existing setups are unchanged unless the flag is enabled. ## Additional Context - Follow-up for relational setup/dev workflow improvements. - PR: #11833 ## How to use it ### Env `export ZITADEL_RELATIONALTABLES_SHOULDRECREATESCHEMA=true` ### Config Add the following to your custom setup steps config: ```yaml RelationalTables: ShouldRecreateSchema: true ```
65 lines
1.6 KiB
Go
65 lines
1.6 KiB
Go
package setup
|
|
|
|
import (
|
|
"context"
|
|
_ "embed"
|
|
|
|
"github.com/zitadel/zitadel/backend/v3/instrumentation/logging"
|
|
"github.com/zitadel/zitadel/backend/v3/storage/database/dialect/postgres"
|
|
"github.com/zitadel/zitadel/internal/database"
|
|
"github.com/zitadel/zitadel/internal/eventstore"
|
|
)
|
|
|
|
type TransactionalTables struct {
|
|
dbClient *database.DB
|
|
|
|
ShouldRecreateSchema bool
|
|
}
|
|
|
|
func (mig *TransactionalTables) Execute(ctx context.Context, _ eventstore.Event) error {
|
|
// TODO(adlerhurst): revert changes made in https://github.com/zitadel/zitadel/pull/11833 before v5 release.
|
|
if mig.ShouldRecreateSchema {
|
|
logging.Info(ctx, "dropping schema of relational tables")
|
|
if err := mig.dropSchema(ctx); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
config := &postgres.Config{Pool: mig.dbClient.Pool}
|
|
pool, err := config.Connect(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return pool.Migrate(ctx)
|
|
}
|
|
|
|
func (mig *TransactionalTables) String() string {
|
|
return "repeatable_transactional_tables"
|
|
}
|
|
|
|
func (mig *TransactionalTables) Check(lastRun map[string]interface{}) bool {
|
|
return true
|
|
}
|
|
|
|
func (mig *TransactionalTables) dropSchema(ctx context.Context) (err error) {
|
|
tx, err := mig.dbClient.BeginTx(ctx, nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer func() {
|
|
if err != nil {
|
|
rollbackErr := tx.Rollback()
|
|
logging.OnError(ctx, rollbackErr).Debug("rollback failed")
|
|
return
|
|
}
|
|
err = tx.Commit()
|
|
}()
|
|
|
|
_, err = tx.ExecContext(ctx, "DROP SCHEMA IF EXISTS zitadel CASCADE")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, err = tx.ExecContext(ctx, "DELETE FROM projections.current_states WHERE projection_name LIKE $1 || '%' OR projection_name = $2", "zitadel.", "relational_tables")
|
|
return err
|
|
}
|