mirror of
https://github.com/hatchet-dev/hatchet.git
synced 2026-05-03 16:09:37 -05:00
Add guide for downgrading versions (#2588)
* add downgrading guide and migrate cmd * cleanup
This commit is contained in:
@@ -11,6 +11,7 @@ import (
|
||||
)
|
||||
|
||||
var printVersion bool
|
||||
var migrateDown string
|
||||
|
||||
// rootCmd represents the base command when called without any subcommands
|
||||
var rootCmd = &cobra.Command{
|
||||
@@ -26,7 +27,11 @@ var rootCmd = &cobra.Command{
|
||||
ctx, cancel := cmdutils.NewInterruptContext()
|
||||
defer cancel()
|
||||
|
||||
migrate.RunMigrations(ctx)
|
||||
if migrateDown != "" {
|
||||
migrate.RunDownMigration(ctx, migrateDown)
|
||||
} else {
|
||||
migrate.RunMigrations(ctx)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
@@ -41,6 +46,13 @@ func main() {
|
||||
"print version and exit.",
|
||||
)
|
||||
|
||||
rootCmd.PersistentFlags().StringVar(
|
||||
&migrateDown,
|
||||
"down",
|
||||
"",
|
||||
"migrate down to a specific version (e.g., 20240115180414).",
|
||||
)
|
||||
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
|
||||
@@ -326,3 +326,109 @@ func listMigrations() (goose.Migrations, error) {
|
||||
|
||||
return goose.CollectMigrations(".", minVersion, maxVersion)
|
||||
}
|
||||
|
||||
// RunDownMigration runs down migrations to a specific version.
|
||||
func RunDownMigration(ctx context.Context, targetVersion string) {
|
||||
if err := runDownMigrationImpl(ctx, targetVersion); err != nil {
|
||||
log.Fatalf("goose: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func runDownMigrationImpl(ctx context.Context, targetVersion string) error {
|
||||
var db *sql.DB
|
||||
var conn *sql.Conn
|
||||
|
||||
retryCtx, cancel := context.WithTimeout(ctx, 30*time.Second)
|
||||
|
||||
err := retry.Do(retryCtx, retry.NewConstant(1*time.Second), func(ctx context.Context) error {
|
||||
var err error
|
||||
if db == nil {
|
||||
db, err = goose.OpenDBWithDriver("postgres", os.Getenv("DATABASE_URL"))
|
||||
|
||||
if err != nil {
|
||||
return retry.RetryableError(fmt.Errorf("failed to open DB: %w", err))
|
||||
}
|
||||
}
|
||||
|
||||
conn, err = db.Conn(ctx)
|
||||
|
||||
if err != nil {
|
||||
return retry.RetryableError(fmt.Errorf("failed to open DB connection: %w", err))
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
cancel()
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open DB: %w", err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if conn != nil {
|
||||
if err := conn.Close(); err != nil {
|
||||
log.Printf("goose: failed to close DB connection: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if db != nil {
|
||||
if err := db.Close(); err != nil {
|
||||
log.Printf("goose: failed to close DB: %v", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
locker, err := lock.NewPostgresSessionLocker()
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create locker: %w", err)
|
||||
}
|
||||
|
||||
err = locker.SessionLock(ctx, conn)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to lock session: %w", err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err := locker.SessionUnlock(ctx, conn); err != nil {
|
||||
log.Printf("goose: failed to unlock session: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
fsys, err := fs.Sub(embedMigrations, "migrations")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create sub filesystem: %w", err)
|
||||
}
|
||||
goose.SetBaseFS(fsys)
|
||||
|
||||
targetVersionInt, err := strconv.ParseInt(targetVersion, 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid target version %s: %w", targetVersion, err)
|
||||
}
|
||||
|
||||
currentVersion, err := goose.GetDBVersion(db)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get current database version: %w", err)
|
||||
}
|
||||
|
||||
if currentVersion < targetVersionInt {
|
||||
return fmt.Errorf("target version %d is higher than current version %d. Use standard migration (without --down flag) to upgrade", targetVersionInt, currentVersion)
|
||||
}
|
||||
|
||||
if currentVersion == targetVersionInt {
|
||||
fmt.Printf("Database is already at version %d. No migration needed.\n", targetVersionInt)
|
||||
return nil
|
||||
}
|
||||
|
||||
fmt.Printf("Migrating down from version %d to version %d\n", currentVersion, targetVersionInt)
|
||||
|
||||
err = goose.DownTo(db, ".", targetVersionInt)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to migrate down to version %d: %w", targetVersionInt, err)
|
||||
}
|
||||
|
||||
fmt.Printf("Successfully migrated down to version %d\n", targetVersionInt)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ export default {
|
||||
},
|
||||
},
|
||||
"worker-configuration-options": "Worker Configuration Options",
|
||||
"downgrading-versions": "Downgrading Versions",
|
||||
benchmarking: "Benchmarking",
|
||||
"data-retention": "Data Retention",
|
||||
"improving-performance": "Improving Performance",
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
import { Callout } from "nextra/components";
|
||||
|
||||
# Downgrading Hatchet Versions
|
||||
|
||||
This guide explains how to safely downgrade your Hatchet instance to a previous version.
|
||||
|
||||
<Callout type="warning">
|
||||
Downgrading may result in data loss. Always test downgrades in a
|
||||
non-production environment first.
|
||||
</Callout>
|
||||
|
||||
## Overview
|
||||
|
||||
Downgrading Hatchet involves two steps:
|
||||
|
||||
1. Running down migrations to revert database schema changes
|
||||
2. Deploying the older Hatchet version
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- **Critical:** Backup your database before downgrading
|
||||
- Ensure the target version supports the current data in your database
|
||||
- Have access to run `hatchet-migrate` command
|
||||
- Verify that all migrations between your current version and target version have down migrations
|
||||
|
||||
## Finding the Target Migration Version
|
||||
|
||||
To downgrade to a specific Hatchet version, you need to identify the last migration that was included in that version.
|
||||
|
||||
Visit the Hatchet GitHub repository for your target version:
|
||||
|
||||
```
|
||||
https://github.com/hatchet-dev/hatchet/tree/{GIT_TAG}/cmd/hatchet-migrate/migrate/migrations
|
||||
```
|
||||
|
||||
Replace `{GIT_TAG}` with your target version (e.g., `v0.71.0`).
|
||||
|
||||
Find the last migration file in that directory - the timestamp at the beginning of the filename is your target migration version.
|
||||
|
||||
**Example:**
|
||||
|
||||
- Target Hatchet version: `v0.71.0`
|
||||
- Last migration file: `20250813183355_v1_0_36.sql`
|
||||
- Migration version: `20250813183355`
|
||||
|
||||
## Running Down Migrations
|
||||
|
||||
<Callout type="info">
|
||||
Use a stable release of the `hatchet-migrate` binary (avoid alpha tags) from
|
||||
the [Hatchet releases page](https://github.com/hatchet-dev/hatchet/tags) to
|
||||
ensure down migrations work correctly.
|
||||
</Callout>
|
||||
|
||||
Once you have identified the target migration version, use the `hatchet-migrate` command with the `--down` flag:
|
||||
|
||||
```bash
|
||||
hatchet-migrate --down 20241023223039
|
||||
```
|
||||
|
||||
This will:
|
||||
|
||||
1. Connect to your database using the `DATABASE_URL` environment variable
|
||||
2. Check the current migration version
|
||||
3. Run all down migrations from the current version to the target version
|
||||
4. Display progress and confirm when complete
|
||||
|
||||
## Deploying the Older Version
|
||||
|
||||
After successfully running the down migrations, deploy the older Hatchet version:
|
||||
|
||||
### Docker Compose
|
||||
|
||||
Update your `docker-compose.yml`:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
hatchet-engine:
|
||||
image: ghcr.io/hatchet-dev/hatchet/hatchet-engine:v0.71.0
|
||||
# ... rest of configuration
|
||||
|
||||
hatchet-dashboard:
|
||||
image: ghcr.io/hatchet-dev/hatchet/hatchet-dashboard:v0.71.0
|
||||
# ... rest of configuration
|
||||
```
|
||||
|
||||
Then restart:
|
||||
|
||||
```bash
|
||||
docker-compose down
|
||||
docker-compose up -d
|
||||
```
|
||||
Reference in New Issue
Block a user