Merge branch 'master' into chore/label-dashboard-queries

This commit is contained in:
Monica Khoury authored and GitHub committed 2026-04-08 18:07:34 +03:00
commit b20ffb99b6
4 files changed
+39 -9

No files matched your search

@@ -27,7 +27,7 @@ import { InlineLink } from '@/components/ui/InlineLink'
import { DatabaseMigration, useMigrationsQuery } from '@/data/database/migrations-query'
import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
import { DOCS_URL } from '@/lib/constants'
import { parseMigrationVersion } from '@/lib/migration-utils'
import { formatMigrationVersionLabel, parseMigrationVersion } from '@/lib/migration-utils'
const Migrations = () => {
const [search, setSearch] = useState('')
@@ -119,9 +119,7 @@ const Migrations = () => {
{migrations.length > 0 ? (
migrations.map((migration) => {
const versionDayjs = parseMigrationVersion(migration.version)
const label = versionDayjs
? versionDayjs.format('DD MMM YYYY, HH:mm:ss')
: 'Unknown'
const label = formatMigrationVersionLabel(migration.version)
const insertedAt = versionDayjs ? versionDayjs.toISOString() : undefined
return (
+24 -1
View File
@@ -1,7 +1,10 @@
import dayjs from 'dayjs'
import utc from 'dayjs/plugin/utc'
import { describe, expect, it } from 'vitest'
import { parseMigrationVersion } from './migration-utils'
import { formatMigrationVersionLabel, parseMigrationVersion } from './migration-utils'
dayjs.extend(utc)
describe('parseMigrationVersion', () => {
it('should parse valid migration version in YYYYMMDDHHmmss format', () => {
@@ -70,4 +73,24 @@ describe('parseMigrationVersion', () => {
expect(result?.toISOString()).toBeDefined()
expect(result?.format('DD MMM YYYY')).toBe('28 Nov 2023')
})
it('should parse version digits as UTC so the UTC time is preserved exactly', () => {
// Migration versions are stored as UTC in the DB. Parsing without UTC mode
// would shift the time by the viewer's local offset, showing wrong UTC values.
const result = parseMigrationVersion('20231128095400')
expect(result?.toISOString()).toBe('2023-11-28T09:54:00.000Z')
})
})
describe('formatMigrationVersionLabel', () => {
it('should format a valid version as a UTC date string', () => {
expect(formatMigrationVersionLabel('20231128095400')).toBe('28 Nov 2023, 09:54:00')
})
it('should return Unknown for an invalid version', () => {
expect(formatMigrationVersionLabel('001')).toBe('Unknown')
expect(formatMigrationVersionLabel(null)).toBe('Unknown')
expect(formatMigrationVersionLabel(undefined)).toBe('Unknown')
})
})
+12 -3
View File
@@ -6,7 +6,7 @@ import dayjs, { Dayjs } from 'dayjs'
* However, some projects may have custom version formats (e.g., "001", "002") that cannot be parsed as dates.
*
* @param version - Migration version string
* @returns Dayjs object if the version is a valid datetime, null otherwise
* @returns Dayjs object (UTC mode) if the version is a valid datetime, undefined otherwise
*
* @example
* const parsed = parseMigrationVersion('20231128095400')
@@ -16,7 +16,7 @@ import dayjs, { Dayjs } from 'dayjs'
* }
*
* @example
* const invalid = parseMigrationVersion('001') // returns null
* const invalid = parseMigrationVersion('001') // returns undefined
*/
export function parseMigrationVersion(version: string | null | undefined): Dayjs | undefined {
if (!version) return undefined
@@ -24,6 +24,15 @@ export function parseMigrationVersion(version: string | null | undefined): Dayjs
// Must contain only digits
if (!/^\d{14}$/.test(version)) return undefined
const parsed = dayjs(version, 'YYYYMMDDHHmmss', true)
const parsed = dayjs.utc(version, 'YYYYMMDDHHmmss', true)
return parsed.isValid() ? parsed : undefined
}
/**
* Formats a migration version string as a human-readable UTC date label.
* Returns 'Unknown' if the version cannot be parsed.
*/
export function formatMigrationVersionLabel(version: string | null | undefined): string {
const parsed = parseMigrationVersion(version)
return parsed ? parsed.format('DD MMM YYYY, HH:mm:ss') : 'Unknown'
}
@@ -21,7 +21,7 @@ export const LogPage: NextPageWithLayout = () => {
condensedLayout
projectRef={ref as string}
queryType="fn_edge"
filterOverride={{ function_id: selectedFunction.id }}
filterOverride={{ 'request.pathname': `/functions/v1/${selectedFunction.slug}` }}
/>
</div>
)