edited ci file

This commit is contained in:
2026-05-13 00:55:28 +02:00
parent f99f0e0fc5
commit 77268e2302
17 changed files with 684 additions and 29 deletions
+7 -2
View File
@@ -110,7 +110,7 @@ func (h *SBOMHandler) GetLatestDocument(w http.ResponseWriter, r *http.Request)
}
// Generate triggers on-demand SBOM generation for a repo at a given ref/SHA.
// POST /api/v1/repos/{owner}/{repo}/sbom/generate?ref=<sha-or-branch>
// POST /api/v1/repos/{owner}/{repo}/sbom/generate?ref=<sha-or-branch>[&runID=<id>]
func (h *SBOMHandler) Generate(w http.ResponseWriter, r *http.Request) {
repoID, ok := resolveRepoID(h.db, w, r)
if !ok {
@@ -126,7 +126,12 @@ func (h *SBOMHandler) Generate(w http.ResponseWriter, r *http.Request) {
return
}
report, err := h.generator.GenerateOnDemand(repoID, sha)
var runID int64
if rid := r.URL.Query().Get("runID"); rid != "" {
runID, _ = strconv.ParseInt(rid, 10, 64)
}
report, err := h.generator.GenerateOnDemand(repoID, runID, sha)
if err != nil {
jsonError(w, "generation failed: "+err.Error(), http.StatusInternalServerError)
return
+2 -1
View File
@@ -7,6 +7,7 @@ import (
"github.com/go-chi/chi/v5"
"xorm.io/xorm"
"github.com/forgeo/forgebucket/internal/api/middleware"
"github.com/forgeo/forgebucket/internal/domain/scanning"
"github.com/forgeo/forgebucket/internal/models"
)
@@ -52,7 +53,7 @@ func (h *ScanningHandler) DismissSecrets(w http.ResponseWriter, r *http.Request)
}
// Get current user from session for audit trail.
username := r.Context().Value("user").(string)
username, _ := r.Context().Value(middleware.ContextKeyUsername).(string)
if err := h.scanner.DismissFindings(leakID, username); err != nil {
jsonError(w, err.Error(), http.StatusNotFound)
+5 -1
View File
@@ -7,6 +7,7 @@ import (
"github.com/go-chi/chi/v5"
"xorm.io/xorm"
"github.com/forgeo/forgebucket/internal/api/middleware"
"github.com/forgeo/forgebucket/internal/domain/vulnscan"
"github.com/forgeo/forgebucket/internal/models"
)
@@ -49,6 +50,9 @@ func (h *VulnScanHandler) Scan(w http.ResponseWriter, r *http.Request) {
jsonError(w, "scan failed: "+err.Error(), http.StatusInternalServerError)
return
}
if findings == nil {
findings = []models.VulnerabilityFinding{}
}
w.WriteHeader(http.StatusCreated)
jsonOK(w, findings)
}
@@ -68,7 +72,7 @@ func (h *VulnScanHandler) Dismiss(w http.ResponseWriter, r *http.Request) {
return
}
username := r.Context().Value("user").(string)
username, _ := r.Context().Value(middleware.ContextKeyUsername).(string)
if err := h.scanner.DismissFindings(findingID, username); err != nil {
jsonError(w, err.Error(), http.StatusNotFound)
+2 -2
View File
@@ -206,13 +206,13 @@ func New(cfg *config.Config, engine *xorm.Engine, store sessions.Store, bus even
})
r.Get("/artifacts", artifactH.List)
r.With(csrf).Post("/artifacts", artifactH.Upload)
r.Get("/sbom", sbomH.GetForRun)
r.Get("/sbom/document", sbomH.GetDocumentForRun)
})
})
r.Get("/artifacts/{artifactID}/download", artifactH.Download)
r.Get("/artifacts/{artifactID}/signature", artifactH.GetSignature)
r.Get("/artifacts/{artifactID}/verify", artifactH.VerifySignature)
r.Get("/sbom", sbomH.GetForRun)
r.Get("/sbom/document", sbomH.GetDocumentForRun)
r.Route("/members", func(r chi.Router) {
r.Get("/", memberH.List)
r.With(csrf).Post("/", memberH.Add)
+14 -5
View File
@@ -9,6 +9,7 @@ import (
"xorm.io/xorm"
"github.com/forgeo/forgebucket/internal/domain/sbom"
"github.com/forgeo/forgebucket/internal/events"
"github.com/forgeo/forgebucket/internal/models"
)
@@ -17,12 +18,13 @@ import (
// advances the DAG as jobs complete. It does NOT execute jobs directly —
// that is the RunnerManager's responsibility.
type Orchestrator struct {
db *xorm.Engine
bus events.EventBus
db *xorm.Engine
bus events.EventBus
sbomGen *sbom.Generator
}
func NewOrchestrator(db *xorm.Engine, bus events.EventBus) *Orchestrator {
return &Orchestrator{db: db, bus: bus}
func NewOrchestrator(db *xorm.Engine, bus events.EventBus, sbomGen *sbom.Generator) *Orchestrator {
return &Orchestrator{db: db, bus: bus, sbomGen: sbomGen}
}
// Start subscribes to relevant NATS subjects and blocks until ctx is cancelled.
@@ -142,7 +144,11 @@ func (o *Orchestrator) createRun(repo models.Repository, evt events.PushEvent, w
// Create job + step records for every job in the workflow.
for jobName, wfJob := range wf.Jobs {
needsJSON, _ := json.Marshal([]string(wfJob.Needs))
needs := []string(wfJob.Needs)
if needs == nil {
needs = []string{}
}
needsJSON, _ := json.Marshal(needs)
job := &models.PipelineJob{
RunID: run.ID,
Name: jobName,
@@ -231,6 +237,9 @@ func (o *Orchestrator) advanceDAG(runID, jobID int64, result string) {
run.FinishedAt = &now
o.db.ID(run.ID).Cols("status", "finished_at").Update(&run) //nolint:errcheck
o.bus.Publish(events.SubjectPipelineCompleted, events.PipelineEvent{RunID: run.ID, RepoID: run.RepoID, Status: "succeeded", At: now}) //nolint:errcheck
if o.sbomGen != nil {
go o.sbomGen.GenerateOnDemand(run.RepoID, run.ID, run.TriggerSHA)
}
return
}
+16 -8
View File
@@ -86,24 +86,32 @@ func (g *Generator) generateForRun(runID, repoID int64) {
// GenerateOnDemand generates an SBOM for a specific repo + SHA and stores it
// (or returns the cached one if the SHA was already processed).
func (g *Generator) GenerateOnDemand(repoID int64, sha string) (*models.SBOMReport, error) {
// Return cached report for this exact SHA if one already exists.
var existing models.SBOMReport
if found, _ := g.db.Where("repo_id = ? AND sha = ?", repoID, sha).Get(&existing); found {
return &existing, nil
}
func (g *Generator) GenerateOnDemand(repoID, runID int64, ref string) (*models.SBOMReport, error) {
var repo models.Repository
if found, _ := g.db.ID(repoID).Get(&repo); !found {
return nil, fmt.Errorf("repo %d not found", repoID)
}
// Resolve the ref to a full commit SHA — ref can be a branch name, tag, etc.
sha, err := gitdomain.RevParse(repo.DiskPath, ref)
if err != nil {
return nil, fmt.Errorf("rev-parse %s: %w", ref, err)
}
// Return cached report for this exact SHA + runID if one already exists.
// Without runID in the cache key, a prior on-demand generation (runID=0)
// would shadow subsequent per-run generation requests.
var existing models.SBOMReport
if found, _ := g.db.Where("repo_id = ? AND sha = ? AND run_id = ?", repoID, sha, runID).Get(&existing); found {
return &existing, nil
}
doc, err := Generate(repo.DiskPath, repo.Name, sha)
if err != nil {
return nil, err
}
report, err := g.persistAndReturn(repoID, 0, sha, doc)
report, err := g.persistAndReturn(repoID, runID, sha, doc)
if err != nil {
return nil, err
}