mirror of
https://github.com/lobehub/lobehub.git
synced 2026-03-27 13:29:15 +07:00
👷 build: add api key hash column migration (#12862)
* ✨ feat(database): extract openapi database changes * 📝 docs: update db-migrations and version-release skills --------- Co-authored-by: MarioJames <mocha.wyh@msn.com> Co-authored-by: YuTengjing <ytj2713151713@gmail.com>
This commit is contained in:
@@ -21,6 +21,23 @@ And updates:
|
|||||||
- `packages/database/src/core/migrations.json`
|
- `packages/database/src/core/migrations.json`
|
||||||
- `docs/development/database-schema.dbml`
|
- `docs/development/database-schema.dbml`
|
||||||
|
|
||||||
|
## Custom Migrations (e.g. CREATE EXTENSION)
|
||||||
|
|
||||||
|
For migrations that don't involve Drizzle schema changes (e.g. enabling PostgreSQL extensions), use the `--custom` flag:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bunx drizzle-kit generate --custom --name=enable_pg_search
|
||||||
|
```
|
||||||
|
|
||||||
|
This generates an empty SQL file and properly updates `_journal.json` and snapshot. Then edit the generated SQL file to add your custom SQL:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Custom SQL migration file, put your code below! --
|
||||||
|
CREATE EXTENSION IF NOT EXISTS pg_search;
|
||||||
|
```
|
||||||
|
|
||||||
|
**Do NOT manually create migration files or edit `_journal.json`** — always use `drizzle-kit generate` to ensure correct journal entries and snapshots.
|
||||||
|
|
||||||
## Step 2: Optimize Migration SQL Filename
|
## Step 2: Optimize Migration SQL Filename
|
||||||
|
|
||||||
Rename auto-generated filename to be meaningful:
|
Rename auto-generated filename to be meaningful:
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ Version number is automatically bumped by patch +1. There are 4 common scenarios
|
|||||||
| Weekly Release | canary | `release/weekly-{YYYYMMDD}` | Weekly release train, canary → main |
|
| Weekly Release | canary | `release/weekly-{YYYYMMDD}` | Weekly release train, canary → main |
|
||||||
| Bug Hotfix | main | `hotfix/v{version}-{hash}` | Emergency bug fix |
|
| Bug Hotfix | main | `hotfix/v{version}-{hash}` | Emergency bug fix |
|
||||||
| New Model Launch | canary | Community PR merged directly | New model launch, triggered by PR title prefix |
|
| New Model Launch | canary | Community PR merged directly | New model launch, triggered by PR title prefix |
|
||||||
| DB Schema Migration | canary | `release/db-migration-{name}` | Database migration, requires dedicated changelog |
|
| DB Schema Migration | main | `release/db-migration-{name}` | Database migration, requires dedicated changelog |
|
||||||
|
|
||||||
All scenarios auto-bump patch +1. Patch PR titles do not need a version number. See `reference/patch-release-scenarios.md` for detailed steps per scenario.
|
All scenarios auto-bump patch +1. Patch PR titles do not need a version number. See `reference/patch-release-scenarios.md` for detailed steps per scenario.
|
||||||
|
|
||||||
@@ -116,6 +116,14 @@ When the user requests a release:
|
|||||||
3. Push and create a PR — **title must be `🚀 release: v{version}`**
|
3. Push and create a PR — **title must be `🚀 release: v{version}`**
|
||||||
4. Inform the user that merging the PR will automatically trigger the release
|
4. Inform the user that merging the PR will automatically trigger the release
|
||||||
|
|
||||||
|
### Precheck
|
||||||
|
|
||||||
|
Before creating the release branch, verify the source branch:
|
||||||
|
|
||||||
|
- **Weekly Release** (`release/weekly-*`): must branch from `canary`
|
||||||
|
- **All other release/hotfix branches**: must branch from `main` — run `git merge-base --is-ancestor main <branch> && echo OK` to confirm
|
||||||
|
- If the branch is based on the wrong source, delete and recreate from the correct base
|
||||||
|
|
||||||
### Patch Release
|
### Patch Release
|
||||||
|
|
||||||
Choose the appropriate workflow based on the scenario (see `reference/patch-release-scenarios.md`):
|
Choose the appropriate workflow based on the scenario (see `reference/patch-release-scenarios.md`):
|
||||||
@@ -123,7 +131,7 @@ Choose the appropriate workflow based on the scenario (see `reference/patch-rele
|
|||||||
- **Weekly Release**: Create a `release/weekly-{YYYYMMDD}` branch from canary, scan `git log main..canary` to write the changelog, title like `🚀 release: 20260222`
|
- **Weekly Release**: Create a `release/weekly-{YYYYMMDD}` branch from canary, scan `git log main..canary` to write the changelog, title like `🚀 release: 20260222`
|
||||||
- **Bug Hotfix**: Create a `hotfix/` branch from main, use a gitmoji prefix title (e.g. `🐛 fix: ...`)
|
- **Bug Hotfix**: Create a `hotfix/` branch from main, use a gitmoji prefix title (e.g. `🐛 fix: ...`)
|
||||||
- **New Model Launch**: Community PRs trigger automatically via title prefix (`feat` / `style`), no extra steps needed
|
- **New Model Launch**: Community PRs trigger automatically via title prefix (`feat` / `style`), no extra steps needed
|
||||||
- **DB Migration**: Create a `release/db-migration-{name}` branch from canary, write a dedicated migration changelog
|
- **DB Migration**: Create a `release/db-migration-{name}` branch from main, cherry-pick migration commits, write a dedicated migration changelog
|
||||||
|
|
||||||
### Important Notes
|
### Important Notes
|
||||||
|
|
||||||
|
|||||||
@@ -15,4 +15,4 @@ This release includes a **database schema migration** involving **5 new tables**
|
|||||||
- The migration runs automatically on application startup
|
- The migration runs automatically on application startup
|
||||||
- No manual intervention required
|
- No manual intervention required
|
||||||
|
|
||||||
The migration owner: @arvinxx — responsible for this database schema change, reach out for any migration-related issues.
|
The migration owner: @\[pr-author] — responsible for this database schema change, reach out for any migration-related issues.
|
||||||
|
|||||||
@@ -91,12 +91,13 @@ Database schema changes that need to be released independently. These require a
|
|||||||
|
|
||||||
### Steps
|
### Steps
|
||||||
|
|
||||||
1. **Create release branch from canary**
|
1. **Create release branch from main and cherry-pick migration commits**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git checkout canary
|
git checkout main
|
||||||
git pull origin canary
|
git pull --rebase origin main
|
||||||
git checkout -b release/db-migration-{name}
|
git checkout -b release/db-migration-{name}
|
||||||
|
git cherry-pick <migration-commit-hash>
|
||||||
git push -u origin release/db-migration-{name}
|
git push -u origin release/db-migration-{name}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
3
packages/database/migrations/0089_add_api_key_hash.sql
Normal file
3
packages/database/migrations/0089_add_api_key_hash.sql
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
ALTER TABLE "api_keys" ADD COLUMN IF NOT EXISTS "key_hash" varchar(128);--> statement-breakpoint
|
||||||
|
ALTER TABLE "api_keys" DROP CONSTRAINT IF EXISTS "api_keys_key_hash_unique";--> statement-breakpoint
|
||||||
|
ALTER TABLE "api_keys" ADD CONSTRAINT "api_keys_key_hash_unique" UNIQUE("key_hash");
|
||||||
12426
packages/database/migrations/meta/0089_snapshot.json
Normal file
12426
packages/database/migrations/meta/0089_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -623,6 +623,13 @@
|
|||||||
"when": 1772277762014,
|
"when": 1772277762014,
|
||||||
"tag": "0088_fix_benchmark_add_bot_provider",
|
"tag": "0088_fix_benchmark_add_bot_provider",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 89,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1772723999146,
|
||||||
|
"tag": "0089_add_api_key_hash",
|
||||||
|
"breakpoints": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"version": "6"
|
"version": "6"
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ export const apiKeys = pgTable(
|
|||||||
.notNull()
|
.notNull()
|
||||||
.primaryKey(),
|
.primaryKey(),
|
||||||
name: varchar('name', { length: 256 }).notNull(), // name of the API key
|
name: varchar('name', { length: 256 }).notNull(), // name of the API key
|
||||||
key: varchar('key', { length: 256 }).notNull().unique(), // API key
|
key: varchar('key', { length: 256 }).notNull().unique(), // encrypted API key
|
||||||
|
keyHash: varchar('key_hash', { length: 128 }).unique(), // hash of api key for authentication lookup
|
||||||
enabled: boolean('enabled').default(true), // whether the API key is enabled
|
enabled: boolean('enabled').default(true), // whether the API key is enabled
|
||||||
expiresAt: timestamptz('expires_at'), // expires time
|
expiresAt: timestamptz('expires_at'), // expires time
|
||||||
lastUsedAt: timestamptz('last_used_at'), // last used time
|
lastUsedAt: timestamptz('last_used_at'), // last used time
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import { asyncTasks } from './asyncTask';
|
|||||||
import { chatGroups, chatGroupsAgents } from './chatGroup';
|
import { chatGroups, chatGroupsAgents } from './chatGroup';
|
||||||
import { documents, files, knowledgeBases } from './file';
|
import { documents, files, knowledgeBases } from './file';
|
||||||
import { generationBatches, generations, generationTopics } from './generation';
|
import { generationBatches, generations, generationTopics } from './generation';
|
||||||
import { messageGroups, messages, messagesFiles } from './message';
|
import { messageGroups, messages, messagesFiles, messageTranslates } from './message';
|
||||||
import { chunks, documentChunks, unstructuredChunks } from './rag';
|
import { chunks, documentChunks, unstructuredChunks } from './rag';
|
||||||
import { sessionGroups, sessions } from './session';
|
import { sessionGroups, sessions } from './session';
|
||||||
import { threads, topicDocuments, topics } from './topic';
|
import { threads, topicDocuments, topics } from './topic';
|
||||||
@@ -98,6 +98,10 @@ export const threadsRelations = relations(threads, ({ one }) => ({
|
|||||||
|
|
||||||
export const messagesRelations = relations(messages, ({ many, one }) => ({
|
export const messagesRelations = relations(messages, ({ many, one }) => ({
|
||||||
filesToMessages: many(messagesFiles),
|
filesToMessages: many(messagesFiles),
|
||||||
|
translation: one(messageTranslates, {
|
||||||
|
fields: [messages.id],
|
||||||
|
references: [messageTranslates.id],
|
||||||
|
}),
|
||||||
|
|
||||||
session: one(sessions, {
|
session: one(sessions, {
|
||||||
fields: [messages.sessionId],
|
fields: [messages.sessionId],
|
||||||
|
|||||||
Reference in New Issue
Block a user