chore(schema): migrate to GORM V2 with multi-database support

- [x] Implement GORM V2 metadata store with SQLite, PostgreSQL, and MySQL support
- [x] Add database migration system using gormigrate for schema versioning
- [x] Create migration CLI tool with support for migrate, rollback, and status commands
- [x] Add Docker support for migration container (Dockerfile.migrate)
- [x] Implement automatic partition management for PostgreSQL time-series tables
- [x] Add background aggregation worker for download statistics
- [x] Support connection pooling configuration (max_open_conns, max_idle_conns, conn_max_lifetime)
- [x] Add blocking mechanism based on vulnerability thresholds in stats and handlers
- [x] Update Helm charts with migration init containers and multi-database configuration
- [x] Replace deprecated SQLite store with optimized GORM implementation
- [x] Add comprehensive integration tests for MySQL and PostgreSQL
- [x] Update frontend to display blocked packages and storage utilization
- [x] Add goreleaser configuration for migrate binary and container image
- [x] Update configuration examples with database backend options and recommendations
This commit is contained in:
2026-01-03 20:44:23 +00:00
parent b129279fb8
commit c0061b99e3
37 changed files with 5711 additions and 1222 deletions
+20 -6
View File
@@ -7,11 +7,16 @@
Back to Stats
</Button>
<div class="flex items-center gap-3">
<i class="fas fa-exclamation-triangle text-3xl text-red-600"></i>
<i :class="showOnlyBlocked ? 'fas fa-hand' : 'fas fa-exclamation-triangle'" class="text-3xl text-red-600"></i>
<div>
<h1 class="text-3xl font-bold text-gray-900">Vulnerable Packages</h1>
<h1 class="text-3xl font-bold text-gray-900">
{{ showOnlyBlocked ? 'Blocked Packages' : 'Vulnerable Packages' }}
</h1>
<p class="text-gray-600 mt-1">
Packages with known security vulnerabilities, sorted by risk
{{ showOnlyBlocked
? 'Packages blocked from download due to exceeding vulnerability thresholds'
: 'Packages with known security vulnerabilities, sorted by risk'
}}
</p>
</div>
</div>
@@ -132,6 +137,7 @@
:counts="version.vulnerabilities.counts"
:total="version.vulnerabilities.total"
:scannedAt="version.vulnerabilities.scannedAt"
:isBlocked="version.vulnerabilities.isBlocked"
@click.stop="navigateToPackage(version)"
/>
</div>
@@ -170,11 +176,15 @@ import { getRegistryBadgeClass } from '@/composables/useBadgeStyles'
const store = usePackageStore()
const router = useRouter()
const route = useRoute()
const loading = ref(false)
const error = ref<string | null>(null)
const vulnerablePackages = ref<Package[]>([])
// Check if we should filter to show only blocked packages
const showOnlyBlocked = computed(() => route.path === '/blocked-packages')
onMounted(async () => {
await fetchVulnerablePackages()
})
@@ -185,9 +195,13 @@ async function fetchVulnerablePackages() {
try {
await store.fetchPackages()
vulnerablePackages.value = store.packages.filter(
pkg => pkg.vulnerabilities?.status === 'vulnerable'
)
vulnerablePackages.value = store.packages.filter(pkg => {
const isVulnerable = pkg.vulnerabilities?.status === 'vulnerable'
if (showOnlyBlocked.value) {
return isVulnerable && pkg.vulnerabilities?.isBlocked === true
}
return isVulnerable
})
} catch (err: any) {
console.error('Failed to load vulnerable packages:', err)
error.value = err.message || 'Failed to load vulnerable packages'