freeleaps-ops/apps/gitea-webhook-ambassador/internal/database/repository.go
zhenyus db590f3f27 refactor: update gitea-webhook-ambassador Dockerfile and configuration
- Changed the build process to include a web UI build stage using Node.js.
- Updated Go build stage to copy web UI files to the correct location.
- Removed the main.go file as it is no longer needed.
- Added SQLite database configuration to example config.
- Updated dependencies in go.mod and go.sum, including new packages for JWT and SQLite.
- Modified .gitignore to include new database and configuration files.

Signed-off-by: zhenyus <zhenyus@mathmast.com>
2025-06-10 16:00:52 +08:00

359 lines
6.9 KiB
Go

package database
import (
"database/sql"
"time"
)
// APIKey represents an API key record
type APIKey struct {
ID int64
Key string
Description string
CreatedAt time.Time
UpdatedAt time.Time
}
// ProjectMapping represents a project to Jenkins job mapping
type ProjectMapping struct {
ID int64
RepositoryName string
DefaultJob string
BranchJobs []BranchJob
BranchPatterns []BranchPattern
CreatedAt time.Time
UpdatedAt time.Time
}
// BranchJob represents a branch to job mapping
type BranchJob struct {
ID int64
ProjectID int64
BranchName string
JobName string
CreatedAt time.Time
UpdatedAt time.Time
}
// BranchPattern represents a branch pattern to job mapping
type BranchPattern struct {
ID int64
ProjectID int64
Pattern string
JobName string
CreatedAt time.Time
UpdatedAt time.Time
}
// TriggerLog represents a job trigger log entry
type TriggerLog struct {
ID int64
RepositoryName string
BranchName string
CommitSHA string
JobName string
Status string
ErrorMessage string
CreatedAt time.Time
}
// CreateAPIKey creates a new API key
func (db *DB) CreateAPIKey(key *APIKey) error {
query := `
INSERT INTO api_keys (key, description)
VALUES (?, ?)`
result, err := db.Exec(query, key.Key, key.Description)
if err != nil {
return err
}
key.ID, _ = result.LastInsertId()
return nil
}
// GetAPIKey retrieves an API key by its value
func (db *DB) GetAPIKey(key string) (*APIKey, error) {
var apiKey APIKey
query := `
SELECT id, key, description, created_at, updated_at
FROM api_keys
WHERE key = ?`
err := db.QueryRow(query, key).Scan(
&apiKey.ID,
&apiKey.Key,
&apiKey.Description,
&apiKey.CreatedAt,
&apiKey.UpdatedAt,
)
if err == sql.ErrNoRows {
return nil, nil
}
if err != nil {
return nil, err
}
return &apiKey, nil
}
// DeleteAPIKey deletes an API key by its value
func (db *DB) DeleteAPIKey(key string) error {
query := `DELETE FROM api_keys WHERE key = ?`
result, err := db.Exec(query, key)
if err != nil {
return err
}
affected, err := result.RowsAffected()
if err != nil {
return err
}
if affected == 0 {
return sql.ErrNoRows
}
return nil
}
// GetAPIKeys retrieves all API keys
func (db *DB) GetAPIKeys() ([]APIKey, error) {
query := `
SELECT id, key, description, created_at, updated_at
FROM api_keys
ORDER BY created_at DESC`
rows, err := db.Query(query)
if err != nil {
return nil, err
}
defer rows.Close()
var keys []APIKey
for rows.Next() {
var key APIKey
err := rows.Scan(
&key.ID,
&key.Key,
&key.Description,
&key.CreatedAt,
&key.UpdatedAt,
)
if err != nil {
return nil, err
}
keys = append(keys, key)
}
return keys, nil
}
// CreateProjectMapping creates a new project mapping
func (db *DB) CreateProjectMapping(project *ProjectMapping) error {
tx, err := db.Begin()
if err != nil {
return err
}
defer tx.Rollback()
// Insert project mapping
query := `
INSERT INTO project_mappings (repository_name, default_job)
VALUES (?, ?)`
result, err := tx.Exec(query, project.RepositoryName, project.DefaultJob)
if err != nil {
return err
}
projectID, _ := result.LastInsertId()
project.ID = projectID
// Insert branch jobs
for _, job := range project.BranchJobs {
query = `
INSERT INTO branch_jobs (project_id, branch_name, job_name)
VALUES (?, ?, ?)`
_, err = tx.Exec(query, projectID, job.BranchName, job.JobName)
if err != nil {
return err
}
}
// Insert branch patterns
for _, pattern := range project.BranchPatterns {
query = `
INSERT INTO branch_patterns (project_id, pattern, job_name)
VALUES (?, ?, ?)`
_, err = tx.Exec(query, projectID, pattern.Pattern, pattern.JobName)
if err != nil {
return err
}
}
return tx.Commit()
}
// GetProjectMapping retrieves a project mapping by repository name
func (db *DB) GetProjectMapping(repoName string) (*ProjectMapping, error) {
var project ProjectMapping
// Get project mapping
query := `
SELECT id, repository_name, default_job, created_at, updated_at
FROM project_mappings
WHERE repository_name = ?`
err := db.QueryRow(query, repoName).Scan(
&project.ID,
&project.RepositoryName,
&project.DefaultJob,
&project.CreatedAt,
&project.UpdatedAt,
)
if err == sql.ErrNoRows {
return nil, nil
}
if err != nil {
return nil, err
}
// Get branch jobs
query = `
SELECT id, branch_name, job_name, created_at, updated_at
FROM branch_jobs
WHERE project_id = ?`
rows, err := db.Query(query, project.ID)
if err != nil {
return nil, err
}
defer rows.Close()
for rows.Next() {
var job BranchJob
err := rows.Scan(
&job.ID,
&job.BranchName,
&job.JobName,
&job.CreatedAt,
&job.UpdatedAt,
)
if err != nil {
return nil, err
}
project.BranchJobs = append(project.BranchJobs, job)
}
// Get branch patterns
query = `
SELECT id, pattern, job_name, created_at, updated_at
FROM branch_patterns
WHERE project_id = ?`
rows, err = db.Query(query, project.ID)
if err != nil {
return nil, err
}
defer rows.Close()
for rows.Next() {
var pattern BranchPattern
err := rows.Scan(
&pattern.ID,
&pattern.Pattern,
&pattern.JobName,
&pattern.CreatedAt,
&pattern.UpdatedAt,
)
if err != nil {
return nil, err
}
project.BranchPatterns = append(project.BranchPatterns, pattern)
}
return &project, nil
}
// LogTrigger logs a job trigger event
func (db *DB) LogTrigger(log *TriggerLog) error {
query := `
INSERT INTO trigger_logs (repository_name, branch_name, commit_sha, job_name, status, error_message)
VALUES (?, ?, ?, ?, ?, ?)`
result, err := db.Exec(query,
log.RepositoryName,
log.BranchName,
log.CommitSHA,
log.JobName,
log.Status,
log.ErrorMessage,
)
if err != nil {
return err
}
log.ID, _ = result.LastInsertId()
return nil
}
// GetTriggerLogs retrieves trigger logs with optional filters
func (db *DB) GetTriggerLogs(repoName, branchName string, since time.Time, limit int) ([]TriggerLog, error) {
query := `
SELECT id, repository_name, branch_name, commit_sha, job_name, status, error_message, created_at
FROM trigger_logs
WHERE 1=1`
args := []interface{}{}
if repoName != "" {
query += " AND repository_name = ?"
args = append(args, repoName)
}
if branchName != "" {
query += " AND branch_name = ?"
args = append(args, branchName)
}
if !since.IsZero() {
query += " AND created_at >= ?"
args = append(args, since)
}
query += " ORDER BY created_at DESC"
if limit > 0 {
query += " LIMIT ?"
args = append(args, limit)
}
rows, err := db.Query(query, args...)
if err != nil {
return nil, err
}
defer rows.Close()
var logs []TriggerLog
for rows.Next() {
var log TriggerLog
err := rows.Scan(
&log.ID,
&log.RepositoryName,
&log.BranchName,
&log.CommitSHA,
&log.JobName,
&log.Status,
&log.ErrorMessage,
&log.CreatedAt,
)
if err != nil {
return nil, err
}
logs = append(logs, log)
}
return logs, nil
}